summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorYves-Alexis Perez <corsac@debian.org>2013-01-02 14:18:20 +0100
committerYves-Alexis Perez <corsac@debian.org>2013-01-02 14:18:20 +0100
commitc1343b3278cdf99533b7902744d15969f9d6fdc1 (patch)
treed5ed3dc5677a59260ec41cd39bb284d3e94c91b3 /src
parentb34738ed08c2227300d554b139e2495ca5da97d6 (diff)
downloadvyos-strongswan-c1343b3278cdf99533b7902744d15969f9d6fdc1.tar.gz
vyos-strongswan-c1343b3278cdf99533b7902744d15969f9d6fdc1.zip
Imported Upstream version 5.0.1
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am16
-rw-r--r--src/Makefile.in65
-rw-r--r--src/_copyright/Makefile.am3
-rw-r--r--src/_copyright/Makefile.in18
-rw-r--r--src/_copyright/_copyright.c36
-rw-r--r--src/_updown/Makefile.in12
-rw-r--r--src/_updown/_updown.in14
-rw-r--r--src/_updown_espmark/Makefile.in12
-rw-r--r--src/charon-nm/Makefile.am26
-rw-r--r--src/charon-nm/Makefile.in676
-rw-r--r--src/charon-nm/charon-nm.c269
-rw-r--r--src/charon-nm/nm/nm_backend.c (renamed from src/libcharon/plugins/nm/nm_plugin.c)104
-rw-r--r--src/charon-nm/nm/nm_backend.h (renamed from src/libcharon/plugins/nm/nm_plugin.h)30
-rw-r--r--src/charon-nm/nm/nm_creds.c (renamed from src/libcharon/plugins/nm/nm_creds.c)0
-rw-r--r--src/charon-nm/nm/nm_creds.h (renamed from src/libcharon/plugins/nm/nm_creds.h)0
-rw-r--r--src/charon-nm/nm/nm_handler.c (renamed from src/libcharon/plugins/nm/nm_handler.c)16
-rw-r--r--src/charon-nm/nm/nm_handler.h (renamed from src/libcharon/plugins/nm/nm_handler.h)0
-rw-r--r--src/charon-nm/nm/nm_service.c (renamed from src/libcharon/plugins/nm/nm_service.c)40
-rw-r--r--src/charon-nm/nm/nm_service.h (renamed from src/libcharon/plugins/nm/nm_service.h)0
-rw-r--r--src/charon/Android.mk3
-rw-r--r--src/charon/Makefile.am5
-rw-r--r--src/charon/Makefile.in19
-rw-r--r--src/charon/charon.c103
-rw-r--r--src/checksum/Makefile.am10
-rw-r--r--src/checksum/Makefile.in60
-rw-r--r--src/checksum/checksum_builder.c6
-rw-r--r--src/conftest/Makefile.am3
-rw-r--r--src/conftest/Makefile.in18
-rw-r--r--src/conftest/config.c10
-rw-r--r--src/conftest/conftest.c11
-rw-r--r--src/conftest/hooks/add_notify.c8
-rw-r--r--src/conftest/hooks/add_payload.c6
-rw-r--r--src/conftest/hooks/custom_proposal.c9
-rw-r--r--src/conftest/hooks/force_cookie.c6
-rw-r--r--src/conftest/hooks/ignore_message.c4
-rw-r--r--src/conftest/hooks/ike_auth_fill.c11
-rw-r--r--src/conftest/hooks/log_id.c4
-rw-r--r--src/conftest/hooks/log_ke.c4
-rw-r--r--src/conftest/hooks/log_proposals.c4
-rw-r--r--src/conftest/hooks/log_ts.c4
-rw-r--r--src/conftest/hooks/pretend_auth.c66
-rw-r--r--src/conftest/hooks/rebuild_auth.c66
-rw-r--r--src/conftest/hooks/reset_seq.c3
-rw-r--r--src/conftest/hooks/set_critical.c4
-rw-r--r--src/conftest/hooks/set_ike_initiator.c4
-rw-r--r--src/conftest/hooks/set_ike_request.c4
-rw-r--r--src/conftest/hooks/set_ike_spi.c4
-rw-r--r--src/conftest/hooks/set_ike_version.c4
-rw-r--r--src/conftest/hooks/set_length.c9
-rw-r--r--src/conftest/hooks/set_proposal_number.c6
-rw-r--r--src/conftest/hooks/set_reserved.c4
-rw-r--r--src/conftest/hooks/unencrypted_notify.c6
-rw-r--r--src/conftest/hooks/unsort_message.c4
-rw-r--r--src/dumm/Makefile.in14
-rw-r--r--src/dumm/ext/extconf.rb.in2
-rw-r--r--src/dumm/mconsole.c2
-rw-r--r--src/include/Makefile.in12
-rw-r--r--src/ipsec/Makefile.am25
-rw-r--r--src/ipsec/Makefile.in66
-rw-r--r--src/ipsec/_ipsec.8 (renamed from src/ipsec/ipsec.8)177
-rw-r--r--src/ipsec/_ipsec.8.in (renamed from src/ipsec/ipsec.8.in)187
-rw-r--r--[-rwxr-xr-x]src/ipsec/_ipsec.in (renamed from src/ipsec/ipsec.in)103
-rw-r--r--src/libcharon/Android.mk114
-rw-r--r--src/libcharon/Makefile.am159
-rw-r--r--src/libcharon/Makefile.in1213
-rw-r--r--src/libcharon/bus/bus.c380
-rw-r--r--src/libcharon/bus/bus.h75
-rw-r--r--src/libcharon/bus/listeners/file_logger.c116
-rw-r--r--src/libcharon/bus/listeners/file_logger.h6
-rw-r--r--src/libcharon/bus/listeners/listener.h44
-rw-r--r--src/libcharon/bus/listeners/logger.h63
-rw-r--r--src/libcharon/bus/listeners/sys_logger.c85
-rw-r--r--src/libcharon/bus/listeners/sys_logger.h6
-rw-r--r--src/libcharon/config/backend_manager.c109
-rw-r--r--src/libcharon/config/backend_manager.h4
-rw-r--r--src/libcharon/config/child_cfg.c79
-rw-r--r--src/libcharon/config/child_cfg.h4
-rw-r--r--src/libcharon/config/ike_cfg.c29
-rw-r--r--src/libcharon/config/ike_cfg.h57
-rw-r--r--src/libcharon/config/peer_cfg.c155
-rw-r--r--src/libcharon/config/peer_cfg.h112
-rw-r--r--src/libcharon/config/proposal.c81
-rw-r--r--src/libcharon/config/proposal.h3
-rw-r--r--src/libcharon/control/controller.c437
-rw-r--r--src/libcharon/control/controller.h37
-rw-r--r--src/libcharon/daemon.c172
-rw-r--r--src/libcharon/daemon.h91
-rw-r--r--src/libcharon/encoding/generator.c154
-rw-r--r--src/libcharon/encoding/generator.h8
-rw-r--r--src/libcharon/encoding/message.c770
-rw-r--r--src/libcharon/encoding/message.h65
-rw-r--r--src/libcharon/encoding/parser.c232
-rw-r--r--src/libcharon/encoding/payloads/auth_payload.c23
-rw-r--r--src/libcharon/encoding/payloads/auth_payload.h7
-rw-r--r--src/libcharon/encoding/payloads/cert_payload.c58
-rw-r--r--src/libcharon/encoding/payloads/cert_payload.h27
-rw-r--r--src/libcharon/encoding/payloads/certreq_payload.c74
-rw-r--r--src/libcharon/encoding/payloads/certreq_payload.h34
-rw-r--r--src/libcharon/encoding/payloads/configuration_attribute.c211
-rw-r--r--src/libcharon/encoding/payloads/configuration_attribute.h44
-rw-r--r--src/libcharon/encoding/payloads/cp_payload.c144
-rw-r--r--src/libcharon/encoding/payloads/cp_payload.h35
-rw-r--r--src/libcharon/encoding/payloads/delete_payload.c143
-rw-r--r--src/libcharon/encoding/payloads/delete_payload.h21
-rw-r--r--src/libcharon/encoding/payloads/eap_payload.c189
-rw-r--r--src/libcharon/encoding/payloads/eap_payload.h29
-rw-r--r--src/libcharon/encoding/payloads/encodings.c20
-rw-r--r--src/libcharon/encoding/payloads/encodings.h199
-rw-r--r--src/libcharon/encoding/payloads/encryption_payload.c177
-rw-r--r--src/libcharon/encoding/payloads/encryption_payload.h16
-rw-r--r--src/libcharon/encoding/payloads/endpoint_notify.c2
-rw-r--r--src/libcharon/encoding/payloads/hash_payload.c177
-rw-r--r--src/libcharon/encoding/payloads/hash_payload.h67
-rw-r--r--src/libcharon/encoding/payloads/id_payload.c304
-rw-r--r--src/libcharon/encoding/payloads/id_payload.h48
-rw-r--r--src/libcharon/encoding/payloads/ike_header.c195
-rw-r--r--src/libcharon/encoding/payloads/ike_header.h139
-rw-r--r--src/libcharon/encoding/payloads/ke_payload.c76
-rw-r--r--src/libcharon/encoding/payloads/ke_payload.h32
-rw-r--r--src/libcharon/encoding/payloads/nonce_payload.c54
-rw-r--r--src/libcharon/encoding/payloads/nonce_payload.h14
-rw-r--r--src/libcharon/encoding/payloads/notify_payload.c284
-rw-r--r--src/libcharon/encoding/payloads/notify_payload.h62
-rw-r--r--src/libcharon/encoding/payloads/payload.c159
-rw-r--r--src/libcharon/encoding/payloads/payload.h175
-rw-r--r--src/libcharon/encoding/payloads/proposal_substructure.c1218
-rw-r--r--src/libcharon/encoding/payloads/proposal_substructure.h120
-rw-r--r--src/libcharon/encoding/payloads/sa_payload.c366
-rw-r--r--src/libcharon/encoding/payloads/sa_payload.h94
-rw-r--r--src/libcharon/encoding/payloads/traffic_selector_substructure.c22
-rw-r--r--src/libcharon/encoding/payloads/traffic_selector_substructure.h5
-rw-r--r--src/libcharon/encoding/payloads/transform_attribute.c185
-rw-r--r--src/libcharon/encoding/payloads/transform_attribute.h104
-rw-r--r--src/libcharon/encoding/payloads/transform_substructure.c188
-rw-r--r--src/libcharon/encoding/payloads/transform_substructure.h39
-rw-r--r--src/libcharon/encoding/payloads/ts_payload.c26
-rw-r--r--src/libcharon/encoding/payloads/ts_payload.h5
-rw-r--r--src/libcharon/encoding/payloads/unknown_payload.c27
-rw-r--r--src/libcharon/encoding/payloads/unknown_payload.h5
-rw-r--r--src/libcharon/encoding/payloads/vendor_id_payload.c37
-rw-r--r--src/libcharon/encoding/payloads/vendor_id_payload.h16
-rw-r--r--src/libcharon/kernel/kernel_handler.c2
-rw-r--r--src/libcharon/network/packet.h115
-rw-r--r--src/libcharon/network/receiver.c297
-rw-r--r--src/libcharon/network/receiver.h42
-rw-r--r--src/libcharon/network/sender.c60
-rw-r--r--src/libcharon/network/sender.h19
-rw-r--r--src/libcharon/network/socket.h12
-rw-r--r--src/libcharon/network/socket_manager.c16
-rw-r--r--src/libcharon/network/socket_manager.h10
-rw-r--r--src/libcharon/plugins/addrblock/Makefile.in14
-rw-r--r--src/libcharon/plugins/android/Makefile.am1
-rw-r--r--src/libcharon/plugins/android/Makefile.in19
-rw-r--r--src/libcharon/plugins/android/android_handler.c2
-rw-r--r--src/libcharon/plugins/android/android_logger.c97
-rw-r--r--src/libcharon/plugins/android/android_plugin.c10
-rw-r--r--src/libcharon/plugins/android/android_service.c36
-rw-r--r--src/libcharon/plugins/android_log/Makefile.am17
-rw-r--r--src/libcharon/plugins/android_log/Makefile.in622
-rw-r--r--src/libcharon/plugins/android_log/android_log_logger.c108
-rw-r--r--src/libcharon/plugins/android_log/android_log_logger.h (renamed from src/libcharon/plugins/android/android_logger.h)22
-rw-r--r--src/libcharon/plugins/android_log/android_log_plugin.c76
-rw-r--r--src/libcharon/plugins/android_log/android_log_plugin.h42
-rw-r--r--src/libcharon/plugins/certexpire/Makefile.in14
-rw-r--r--src/libcharon/plugins/certexpire/certexpire_export.c22
-rw-r--r--src/libcharon/plugins/coupling/Makefile.in14
-rw-r--r--src/libcharon/plugins/coupling/coupling_validator.c37
-rw-r--r--src/libcharon/plugins/dhcp/Makefile.in14
-rw-r--r--src/libcharon/plugins/dhcp/dhcp_provider.c77
-rw-r--r--src/libcharon/plugins/dhcp/dhcp_socket.c43
-rw-r--r--src/libcharon/plugins/duplicheck/Makefile.in14
-rw-r--r--src/libcharon/plugins/duplicheck/duplicheck_listener.c4
-rw-r--r--src/libcharon/plugins/duplicheck/duplicheck_notify.c18
-rw-r--r--src/libcharon/plugins/duplicheck/duplicheck_plugin.c2
-rw-r--r--src/libcharon/plugins/eap_aka/Makefile.in14
-rw-r--r--src/libcharon/plugins/eap_aka/eap_aka_peer.c160
-rw-r--r--src/libcharon/plugins/eap_aka/eap_aka_peer.h2
-rw-r--r--src/libcharon/plugins/eap_aka/eap_aka_server.c64
-rw-r--r--src/libcharon/plugins/eap_aka/eap_aka_server.h2
-rw-r--r--src/libcharon/plugins/eap_aka_3gpp2/Makefile.in14
-rw-r--r--src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.c36
-rw-r--r--src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_functions.c100
-rw-r--r--src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_functions.h21
-rw-r--r--src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c35
-rw-r--r--src/libcharon/plugins/eap_dynamic/Makefile.am16
-rw-r--r--src/libcharon/plugins/eap_dynamic/Makefile.in (renamed from src/whack/Makefile.in)212
-rw-r--r--src/libcharon/plugins/eap_dynamic/eap_dynamic.c393
-rw-r--r--src/libcharon/plugins/eap_dynamic/eap_dynamic.h52
-rw-r--r--src/libcharon/plugins/eap_dynamic/eap_dynamic_plugin.c (renamed from src/pluto/plugins/xauth/xauth_plugin.c)36
-rw-r--r--src/libcharon/plugins/eap_dynamic/eap_dynamic_plugin.h43
-rw-r--r--src/libcharon/plugins/eap_gtc/Makefile.am2
-rw-r--r--src/libcharon/plugins/eap_gtc/Makefile.in16
-rw-r--r--src/libcharon/plugins/eap_gtc/eap_gtc.c130
-rw-r--r--src/libcharon/plugins/eap_gtc/eap_gtc.h2
-rw-r--r--src/libcharon/plugins/eap_gtc/eap_gtc_plugin.c11
-rw-r--r--src/libcharon/plugins/eap_identity/Makefile.in14
-rw-r--r--src/libcharon/plugins/eap_identity/eap_identity.h2
-rw-r--r--src/libcharon/plugins/eap_md5/Makefile.in14
-rw-r--r--src/libcharon/plugins/eap_md5/eap_md5.c10
-rw-r--r--src/libcharon/plugins/eap_md5/eap_md5.h2
-rw-r--r--src/libcharon/plugins/eap_mschapv2/Makefile.in14
-rw-r--r--src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c116
-rw-r--r--src/libcharon/plugins/eap_mschapv2/eap_mschapv2.h2
-rw-r--r--src/libcharon/plugins/eap_peap/Makefile.in14
-rw-r--r--src/libcharon/plugins/eap_peap/eap_peap.c13
-rw-r--r--src/libcharon/plugins/eap_peap/eap_peap.h2
-rw-r--r--src/libcharon/plugins/eap_peap/eap_peap_peer.c5
-rw-r--r--src/libcharon/plugins/eap_peap/eap_peap_peer.h2
-rw-r--r--src/libcharon/plugins/eap_peap/eap_peap_server.c26
-rw-r--r--src/libcharon/plugins/eap_peap/eap_peap_server.h2
-rw-r--r--src/libcharon/plugins/eap_radius/Makefile.in14
-rw-r--r--src/libcharon/plugins/eap_radius/eap_radius.c15
-rw-r--r--src/libcharon/plugins/eap_radius/eap_radius.h2
-rw-r--r--src/libcharon/plugins/eap_radius/eap_radius_accounting.c48
-rw-r--r--src/libcharon/plugins/eap_radius/eap_radius_dae.c44
-rw-r--r--src/libcharon/plugins/eap_radius/eap_radius_forward.c10
-rw-r--r--src/libcharon/plugins/eap_radius/eap_radius_plugin.c44
-rw-r--r--src/libcharon/plugins/eap_sim/Makefile.in14
-rw-r--r--src/libcharon/plugins/eap_sim/eap_sim_peer.c161
-rw-r--r--src/libcharon/plugins/eap_sim/eap_sim_peer.h2
-rw-r--r--src/libcharon/plugins/eap_sim/eap_sim_server.c63
-rw-r--r--src/libcharon/plugins/eap_sim/eap_sim_server.h2
-rw-r--r--src/libcharon/plugins/eap_sim_file/Makefile.in14
-rw-r--r--src/libcharon/plugins/eap_sim_pcsc/Makefile.in14
-rw-r--r--src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in14
-rw-r--r--src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_provider.c11
-rw-r--r--src/libcharon/plugins/eap_simaka_reauth/Makefile.in14
-rw-r--r--src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_provider.c22
-rw-r--r--src/libcharon/plugins/eap_simaka_sql/Makefile.in14
-rw-r--r--src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_plugin.c6
-rw-r--r--src/libcharon/plugins/eap_tls/Makefile.in14
-rw-r--r--src/libcharon/plugins/eap_tls/eap_tls.c8
-rw-r--r--src/libcharon/plugins/eap_tls/eap_tls.h2
-rw-r--r--src/libcharon/plugins/eap_tnc/Makefile.in14
-rw-r--r--src/libcharon/plugins/eap_tnc/eap_tnc.c37
-rw-r--r--src/libcharon/plugins/eap_tnc/eap_tnc.h4
-rw-r--r--src/libcharon/plugins/eap_ttls/Makefile.in14
-rw-r--r--src/libcharon/plugins/eap_ttls/eap_ttls.c13
-rw-r--r--src/libcharon/plugins/eap_ttls/eap_ttls.h2
-rw-r--r--src/libcharon/plugins/eap_ttls/eap_ttls_peer.c7
-rw-r--r--src/libcharon/plugins/eap_ttls/eap_ttls_server.c15
-rw-r--r--src/libcharon/plugins/farp/Makefile.in14
-rw-r--r--src/libcharon/plugins/farp/farp_spoofer.c12
-rw-r--r--src/libcharon/plugins/ha/Makefile.in14
-rw-r--r--src/libcharon/plugins/ha/ha_attribute.c42
-rw-r--r--src/libcharon/plugins/ha/ha_cache.c20
-rw-r--r--src/libcharon/plugins/ha/ha_ctl.c15
-rw-r--r--src/libcharon/plugins/ha/ha_dispatcher.c254
-rw-r--r--src/libcharon/plugins/ha/ha_ike.c160
-rw-r--r--src/libcharon/plugins/ha/ha_kernel.c3
-rw-r--r--src/libcharon/plugins/ha/ha_message.c20
-rw-r--r--src/libcharon/plugins/ha/ha_message.h16
-rw-r--r--src/libcharon/plugins/ha/ha_plugin.c14
-rw-r--r--src/libcharon/plugins/ha/ha_segments.c42
-rw-r--r--src/libcharon/plugins/ha/ha_socket.c1
-rw-r--r--src/libcharon/plugins/ha/ha_tunnel.c11
-rw-r--r--src/libcharon/plugins/led/Makefile.in14
-rw-r--r--src/libcharon/plugins/led/led_listener.c9
-rw-r--r--src/libcharon/plugins/load_tester/Makefile.in14
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_config.c64
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_creds.c4
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_ipsec.c9
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_listener.c3
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_plugin.c119
-rw-r--r--src/libcharon/plugins/maemo/Makefile.in14
-rw-r--r--src/libcharon/plugins/maemo/maemo_service.c41
-rw-r--r--src/libcharon/plugins/medcli/Makefile.in14
-rw-r--r--src/libcharon/plugins/medcli/medcli_config.c26
-rw-r--r--src/libcharon/plugins/medsrv/Makefile.in14
-rw-r--r--src/libcharon/plugins/medsrv/medsrv_config.c9
-rw-r--r--src/libcharon/plugins/nm/Makefile.am21
-rw-r--r--src/libcharon/plugins/radattr/Makefile.in14
-rw-r--r--src/libcharon/plugins/radattr/radattr_listener.c8
-rw-r--r--src/libcharon/plugins/smp/Makefile.in14
-rw-r--r--src/libcharon/plugins/smp/smp.c37
-rw-r--r--src/libcharon/plugins/socket_default/Makefile.in14
-rw-r--r--src/libcharon/plugins/socket_default/socket_default_socket.c198
-rw-r--r--src/libcharon/plugins/socket_dynamic/Makefile.in14
-rw-r--r--src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c65
-rw-r--r--src/libcharon/plugins/socket_raw/Makefile.am17
-rw-r--r--src/libcharon/plugins/socket_raw/socket_raw_socket.c717
-rw-r--r--src/libcharon/plugins/socket_raw/socket_raw_socket.h51
-rw-r--r--src/libcharon/plugins/sql/Makefile.in14
-rw-r--r--src/libcharon/plugins/sql/sql_config.c23
-rw-r--r--src/libcharon/plugins/sql/sql_logger.c39
-rw-r--r--src/libcharon/plugins/sql/sql_logger.h4
-rw-r--r--src/libcharon/plugins/sql/sql_plugin.c7
-rw-r--r--src/libcharon/plugins/stroke/Makefile.am1
-rw-r--r--src/libcharon/plugins/stroke/Makefile.in18
-rw-r--r--src/libcharon/plugins/stroke/stroke_attribute.c280
-rw-r--r--src/libcharon/plugins/stroke/stroke_attribute.h23
-rw-r--r--src/libcharon/plugins/stroke/stroke_ca.c10
-rw-r--r--src/libcharon/plugins/stroke/stroke_config.c473
-rw-r--r--src/libcharon/plugins/stroke/stroke_config.h4
-rw-r--r--src/libcharon/plugins/stroke/stroke_control.c85
-rw-r--r--src/libcharon/plugins/stroke/stroke_cred.c13
-rw-r--r--src/libcharon/plugins/stroke/stroke_handler.c231
-rw-r--r--src/libcharon/plugins/stroke/stroke_handler.h64
-rw-r--r--src/libcharon/plugins/stroke/stroke_list.c133
-rw-r--r--src/libcharon/plugins/stroke/stroke_plugin.c44
-rw-r--r--src/libcharon/plugins/stroke/stroke_socket.c60
-rw-r--r--src/libcharon/plugins/tnc_ifmap/Makefile.in14
-rw-r--r--src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.c6
-rw-r--r--src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c77
-rw-r--r--src/libcharon/plugins/tnc_imc/Makefile.am2
-rw-r--r--src/libcharon/plugins/tnc_imc/Makefile.in16
-rw-r--r--src/libcharon/plugins/tnc_imc/tnc_imc_manager.c3
-rw-r--r--src/libcharon/plugins/tnc_imc/tnc_imc_plugin.c2
-rw-r--r--src/libcharon/plugins/tnc_imv/Makefile.in14
-rw-r--r--src/libcharon/plugins/tnc_imv/tnc_imv_manager.c5
-rw-r--r--src/libcharon/plugins/tnc_imv/tnc_imv_plugin.c2
-rw-r--r--src/libcharon/plugins/tnc_imv/tnc_imv_recommendations.c58
-rw-r--r--src/libcharon/plugins/tnc_pdp/Makefile.in14
-rw-r--r--src/libcharon/plugins/tnc_pdp/tnc_pdp.c99
-rw-r--r--src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.c17
-rw-r--r--src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.h2
-rw-r--r--src/libcharon/plugins/tnc_pdp/tnc_pdp_plugin.c4
-rw-r--r--src/libcharon/plugins/tnc_tnccs/Makefile.in14
-rw-r--r--src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.c20
-rw-r--r--src/libcharon/plugins/tnccs_11/Makefile.am2
-rw-r--r--src/libcharon/plugins/tnccs_11/Makefile.in16
-rw-r--r--src/libcharon/plugins/tnccs_11/tnccs_11.c36
-rw-r--r--src/libcharon/plugins/tnccs_20/Makefile.am2
-rw-r--r--src/libcharon/plugins/tnccs_20/Makefile.in16
-rw-r--r--src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c65
-rw-r--r--src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.h10
-rw-r--r--src/libcharon/plugins/tnccs_20/messages/pb_access_recommendation_msg.c7
-rw-r--r--src/libcharon/plugins/tnccs_20/messages/pb_assessment_result_msg.c7
-rw-r--r--src/libcharon/plugins/tnccs_20/messages/pb_error_msg.c7
-rw-r--r--src/libcharon/plugins/tnccs_20/messages/pb_language_preference_msg.c4
-rw-r--r--src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.c41
-rw-r--r--src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.h7
-rw-r--r--src/libcharon/plugins/tnccs_20/messages/pb_reason_string_msg.c7
-rw-r--r--src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.c6
-rw-r--r--src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.c23
-rw-r--r--src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.h14
-rw-r--r--src/libcharon/plugins/tnccs_20/tnccs_20.c226
-rw-r--r--src/libcharon/plugins/tnccs_dynamic/Makefile.in14
-rw-r--r--src/libcharon/plugins/uci/Makefile.in14
-rw-r--r--src/libcharon/plugins/uci/uci_config.c14
-rw-r--r--src/libcharon/plugins/uci/uci_control.c15
-rw-r--r--src/libcharon/plugins/unit_tester/Makefile.in14
-rw-r--r--src/libcharon/plugins/unit_tester/tests/test_cert.c4
-rw-r--r--src/libcharon/plugins/unit_tester/tests/test_pool.c11
-rw-r--r--src/libcharon/plugins/unity/Makefile.am19
-rw-r--r--src/libcharon/plugins/unity/Makefile.in624
-rw-r--r--src/libcharon/plugins/unity/unity_handler.c433
-rw-r--r--src/libcharon/plugins/unity/unity_handler.h58
-rw-r--r--src/libcharon/plugins/unity/unity_narrow.c171
-rw-r--r--src/libcharon/plugins/unity/unity_narrow.h51
-rw-r--r--src/libcharon/plugins/unity/unity_plugin.c96
-rw-r--r--src/libcharon/plugins/unity/unity_plugin.h42
-rw-r--r--src/libcharon/plugins/unity/unity_provider.c175
-rw-r--r--src/libcharon/plugins/unity/unity_provider.h49
-rw-r--r--src/libcharon/plugins/updown/Makefile.am1
-rw-r--r--src/libcharon/plugins/updown/Makefile.in18
-rw-r--r--src/libcharon/plugins/updown/updown_handler.c243
-rw-r--r--src/libcharon/plugins/updown/updown_handler.h57
-rw-r--r--src/libcharon/plugins/updown/updown_listener.c117
-rw-r--r--src/libcharon/plugins/updown/updown_listener.h4
-rw-r--r--src/libcharon/plugins/updown/updown_plugin.c22
-rw-r--r--src/libcharon/plugins/whitelist/Makefile.in14
-rw-r--r--src/libcharon/plugins/whitelist/whitelist.c1
-rw-r--r--src/libcharon/plugins/whitelist/whitelist_control.c15
-rw-r--r--src/libcharon/plugins/whitelist/whitelist_listener.c2
-rw-r--r--src/libcharon/plugins/xauth_eap/Makefile.am17
-rw-r--r--src/libcharon/plugins/xauth_eap/Makefile.in (renamed from src/libcharon/plugins/socket_raw/Makefile.in)66
-rw-r--r--src/libcharon/plugins/xauth_eap/xauth_eap.c289
-rw-r--r--src/libcharon/plugins/xauth_eap/xauth_eap.h55
-rw-r--r--src/libcharon/plugins/xauth_eap/xauth_eap_plugin.c60
-rw-r--r--src/libcharon/plugins/xauth_eap/xauth_eap_plugin.h (renamed from src/libcharon/plugins/socket_raw/socket_raw_plugin.h)22
-rw-r--r--src/libcharon/plugins/xauth_generic/Makefile.am17
-rw-r--r--src/libcharon/plugins/xauth_generic/Makefile.in622
-rw-r--r--src/libcharon/plugins/xauth_generic/xauth_generic.c232
-rw-r--r--src/libcharon/plugins/xauth_generic/xauth_generic.h60
-rw-r--r--src/libcharon/plugins/xauth_generic/xauth_generic_plugin.c62
-rw-r--r--src/libcharon/plugins/xauth_generic/xauth_generic_plugin.h42
-rw-r--r--src/libcharon/plugins/xauth_pam/Makefile.am17
-rw-r--r--src/libcharon/plugins/xauth_pam/Makefile.in (renamed from src/libcharon/plugins/nm/Makefile.in)77
-rw-r--r--src/libcharon/plugins/xauth_pam/xauth_pam.c215
-rw-r--r--src/libcharon/plugins/xauth_pam/xauth_pam.h49
-rw-r--r--src/libcharon/plugins/xauth_pam/xauth_pam_plugin.c67
-rw-r--r--src/libcharon/plugins/xauth_pam/xauth_pam_plugin.h42
-rw-r--r--src/libcharon/processing/jobs/acquire_job.c4
-rw-r--r--src/libcharon/processing/jobs/adopt_children_job.c177
-rw-r--r--src/libcharon/processing/jobs/adopt_children_job.h49
-rw-r--r--src/libcharon/processing/jobs/delete_child_sa_job.c15
-rw-r--r--src/libcharon/processing/jobs/delete_child_sa_job.h4
-rw-r--r--src/libcharon/processing/jobs/delete_ike_sa_job.c6
-rw-r--r--src/libcharon/processing/jobs/dpd_timeout_job.c118
-rw-r--r--src/libcharon/processing/jobs/dpd_timeout_job.h52
-rw-r--r--src/libcharon/processing/jobs/inactivity_job.c15
-rw-r--r--src/libcharon/processing/jobs/initiate_mediation_job.c25
-rw-r--r--src/libcharon/processing/jobs/mediation_job.c10
-rw-r--r--src/libcharon/processing/jobs/migrate_job.c21
-rw-r--r--src/libcharon/processing/jobs/process_message_job.c7
-rw-r--r--src/libcharon/processing/jobs/rekey_child_sa_job.c4
-rw-r--r--src/libcharon/processing/jobs/rekey_ike_sa_job.c4
-rw-r--r--src/libcharon/processing/jobs/retransmit_job.c4
-rw-r--r--src/libcharon/processing/jobs/retry_initiate_job.c95
-rw-r--r--src/libcharon/processing/jobs/retry_initiate_job.h48
-rw-r--r--src/libcharon/processing/jobs/roam_job.c5
-rw-r--r--src/libcharon/processing/jobs/send_dpd_job.c4
-rw-r--r--src/libcharon/processing/jobs/send_keepalive_job.c4
-rw-r--r--src/libcharon/processing/jobs/start_action_job.c11
-rw-r--r--src/libcharon/processing/jobs/update_sa_job.c4
-rw-r--r--src/libcharon/sa/authenticator.c (renamed from src/libcharon/sa/authenticators/authenticator.c)64
-rw-r--r--src/libcharon/sa/authenticator.h (renamed from src/libcharon/sa/authenticators/authenticator.h)63
-rw-r--r--src/libcharon/sa/child_sa.c79
-rw-r--r--src/libcharon/sa/child_sa.h12
-rw-r--r--src/libcharon/sa/eap/eap_manager.c (renamed from src/libcharon/sa/authenticators/eap/eap_manager.c)41
-rw-r--r--src/libcharon/sa/eap/eap_manager.h (renamed from src/libcharon/sa/authenticators/eap/eap_manager.h)14
-rw-r--r--src/libcharon/sa/eap/eap_method.c (renamed from src/libcharon/sa/authenticators/eap/eap_method.c)0
-rw-r--r--src/libcharon/sa/eap/eap_method.h (renamed from src/libcharon/sa/authenticators/eap/eap_method.h)0
-rw-r--r--src/libcharon/sa/ike_sa.c694
-rw-r--r--src/libcharon/sa/ike_sa.h102
-rw-r--r--src/libcharon/sa/ike_sa_id.c51
-rw-r--r--src/libcharon/sa/ike_sa_id.h31
-rw-r--r--src/libcharon/sa/ike_sa_manager.c914
-rw-r--r--src/libcharon/sa/ike_sa_manager.h18
-rw-r--r--src/libcharon/sa/ikev1/authenticators/hybrid_authenticator.c114
-rw-r--r--src/libcharon/sa/ikev1/authenticators/hybrid_authenticator.h56
-rw-r--r--src/libcharon/sa/ikev1/authenticators/psk_v1_authenticator.c172
-rw-r--r--src/libcharon/sa/ikev1/authenticators/psk_v1_authenticator.h57
-rw-r--r--src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.c233
-rw-r--r--src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.h57
-rw-r--r--src/libcharon/sa/ikev1/keymat_v1.c1157
-rw-r--r--src/libcharon/sa/ikev1/keymat_v1.h166
-rw-r--r--src/libcharon/sa/ikev1/phase1.c795
-rw-r--r--src/libcharon/sa/ikev1/phase1.h166
-rw-r--r--src/libcharon/sa/ikev1/task_manager_v1.c1714
-rw-r--r--src/libcharon/sa/ikev1/task_manager_v1.h46
-rw-r--r--src/libcharon/sa/ikev1/tasks/aggressive_mode.c714
-rw-r--r--src/libcharon/sa/ikev1/tasks/aggressive_mode.h50
-rw-r--r--src/libcharon/sa/ikev1/tasks/informational.c253
-rw-r--r--src/libcharon/sa/ikev1/tasks/informational.h51
-rw-r--r--src/libcharon/sa/ikev1/tasks/isakmp_cert_post.c359
-rw-r--r--src/libcharon/sa/ikev1/tasks/isakmp_cert_post.h53
-rw-r--r--src/libcharon/sa/ikev1/tasks/isakmp_cert_pre.c578
-rw-r--r--src/libcharon/sa/ikev1/tasks/isakmp_cert_pre.h53
-rw-r--r--src/libcharon/sa/ikev1/tasks/isakmp_delete.c147
-rw-r--r--src/libcharon/sa/ikev1/tasks/isakmp_delete.h50
-rw-r--r--src/libcharon/sa/ikev1/tasks/isakmp_dpd.c123
-rw-r--r--src/libcharon/sa/ikev1/tasks/isakmp_dpd.h52
-rw-r--r--src/libcharon/sa/ikev1/tasks/isakmp_natd.c456
-rw-r--r--src/libcharon/sa/ikev1/tasks/isakmp_natd.h50
-rw-r--r--src/libcharon/sa/ikev1/tasks/isakmp_vendor.c225
-rw-r--r--src/libcharon/sa/ikev1/tasks/isakmp_vendor.h49
-rw-r--r--src/libcharon/sa/ikev1/tasks/main_mode.c735
-rw-r--r--src/libcharon/sa/ikev1/tasks/main_mode.h50
-rw-r--r--src/libcharon/sa/ikev1/tasks/mode_config.c459
-rw-r--r--src/libcharon/sa/ikev1/tasks/mode_config.h50
-rw-r--r--src/libcharon/sa/ikev1/tasks/quick_delete.c247
-rw-r--r--src/libcharon/sa/ikev1/tasks/quick_delete.h55
-rw-r--r--src/libcharon/sa/ikev1/tasks/quick_mode.c1273
-rw-r--r--src/libcharon/sa/ikev1/tasks/quick_mode.h67
-rw-r--r--src/libcharon/sa/ikev1/tasks/xauth.c551
-rw-r--r--src/libcharon/sa/ikev1/tasks/xauth.h50
-rw-r--r--src/libcharon/sa/ikev2/authenticators/eap_authenticator.c (renamed from src/libcharon/sa/authenticators/eap_authenticator.c)97
-rw-r--r--src/libcharon/sa/ikev2/authenticators/eap_authenticator.h (renamed from src/libcharon/sa/authenticators/eap_authenticator.h)4
-rw-r--r--src/libcharon/sa/ikev2/authenticators/psk_authenticator.c (renamed from src/libcharon/sa/authenticators/psk_authenticator.c)25
-rw-r--r--src/libcharon/sa/ikev2/authenticators/psk_authenticator.h (renamed from src/libcharon/sa/authenticators/psk_authenticator.h)4
-rw-r--r--src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c (renamed from src/libcharon/sa/authenticators/pubkey_authenticator.c)24
-rw-r--r--src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.h (renamed from src/libcharon/sa/authenticators/pubkey_authenticator.h)4
-rw-r--r--src/libcharon/sa/ikev2/connect_manager.c (renamed from src/libcharon/sa/connect_manager.c)37
-rw-r--r--src/libcharon/sa/ikev2/connect_manager.h (renamed from src/libcharon/sa/connect_manager.h)2
-rw-r--r--src/libcharon/sa/ikev2/keymat_v2.c687
-rw-r--r--src/libcharon/sa/ikev2/keymat_v2.h137
-rw-r--r--src/libcharon/sa/ikev2/mediation_manager.c (renamed from src/libcharon/sa/mediation_manager.c)0
-rw-r--r--src/libcharon/sa/ikev2/mediation_manager.h (renamed from src/libcharon/sa/mediation_manager.h)2
-rw-r--r--src/libcharon/sa/ikev2/task_manager_v2.c1502
-rw-r--r--src/libcharon/sa/ikev2/task_manager_v2.h46
-rw-r--r--src/libcharon/sa/ikev2/tasks/child_create.c (renamed from src/libcharon/sa/tasks/child_create.c)258
-rw-r--r--src/libcharon/sa/ikev2/tasks/child_create.h (renamed from src/libcharon/sa/tasks/child_create.h)13
-rw-r--r--src/libcharon/sa/ikev2/tasks/child_delete.c (renamed from src/libcharon/sa/tasks/child_delete.c)47
-rw-r--r--src/libcharon/sa/ikev2/tasks/child_delete.h (renamed from src/libcharon/sa/tasks/child_delete.h)7
-rw-r--r--src/libcharon/sa/ikev2/tasks/child_rekey.c (renamed from src/libcharon/sa/tasks/child_rekey.c)33
-rw-r--r--src/libcharon/sa/ikev2/tasks/child_rekey.h (renamed from src/libcharon/sa/tasks/child_rekey.h)8
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_auth.c (renamed from src/libcharon/sa/tasks/ike_auth.c)17
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_auth.h (renamed from src/libcharon/sa/tasks/ike_auth.h)6
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_auth_lifetime.c (renamed from src/libcharon/sa/tasks/ike_auth_lifetime.c)3
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_auth_lifetime.h (renamed from src/libcharon/sa/tasks/ike_auth_lifetime.h)10
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_cert_post.c (renamed from src/libcharon/sa/tasks/ike_cert_post.c)18
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_cert_post.h (renamed from src/libcharon/sa/tasks/ike_cert_post.h)4
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_cert_pre.c (renamed from src/libcharon/sa/tasks/ike_cert_pre.c)5
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_cert_pre.h (renamed from src/libcharon/sa/tasks/ike_cert_pre.h)4
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_config.c (renamed from src/libcharon/sa/tasks/ike_config.c)163
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_config.h (renamed from src/libcharon/sa/tasks/ike_config.h)6
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_delete.c (renamed from src/libcharon/sa/tasks/ike_delete.c)4
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_delete.h (renamed from src/libcharon/sa/tasks/ike_delete.h)4
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_dpd.c (renamed from src/libcharon/sa/tasks/ike_dpd.c)2
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_dpd.h (renamed from src/libcharon/sa/tasks/ike_dpd.h)4
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_init.c (renamed from src/libcharon/sa/tasks/ike_init.c)71
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_init.h (renamed from src/libcharon/sa/tasks/ike_init.h)8
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_me.c (renamed from src/libcharon/sa/tasks/ike_me.c)20
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_me.h (renamed from src/libcharon/sa/tasks/ike_me.h)6
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_mobike.c (renamed from src/libcharon/sa/tasks/ike_mobike.c)57
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_mobike.h (renamed from src/libcharon/sa/tasks/ike_mobike.h)6
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_natd.c (renamed from src/libcharon/sa/tasks/ike_natd.c)54
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_natd.h (renamed from src/libcharon/sa/tasks/ike_natd.h)6
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_reauth.c (renamed from src/libcharon/sa/tasks/ike_reauth.c)5
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_reauth.h (renamed from src/libcharon/sa/tasks/ike_reauth.h)4
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_rekey.c (renamed from src/libcharon/sa/tasks/ike_rekey.c)35
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_rekey.h (renamed from src/libcharon/sa/tasks/ike_rekey.h)10
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_vendor.c (renamed from src/libcharon/sa/tasks/ike_vendor.c)12
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_vendor.h (renamed from src/libcharon/sa/tasks/ike_vendor.h)4
-rw-r--r--src/libcharon/sa/keymat.c653
-rw-r--r--src/libcharon/sa/keymat.h141
-rw-r--r--src/libcharon/sa/shunt_manager.c1
-rw-r--r--src/libcharon/sa/task.c (renamed from src/libcharon/sa/tasks/task.c)40
-rw-r--r--src/libcharon/sa/task.h (renamed from src/libcharon/sa/tasks/task.h)66
-rw-r--r--src/libcharon/sa/task_manager.c1139
-rw-r--r--src/libcharon/sa/task_manager.h83
-rw-r--r--src/libcharon/sa/trap_manager.c60
-rw-r--r--src/libcharon/sa/xauth/xauth_manager.c157
-rw-r--r--src/libcharon/sa/xauth/xauth_manager.h79
-rw-r--r--src/libcharon/sa/xauth/xauth_method.c42
-rw-r--r--src/libcharon/sa/xauth/xauth_method.h126
-rw-r--r--src/libfast/Makefile.am11
-rw-r--r--src/libfast/Makefile.in75
-rw-r--r--src/libfast/dispatcher.c14
-rw-r--r--src/libfast/request.c60
-rw-r--r--src/libfast/request.h9
-rw-r--r--src/libfast/session.c20
-rw-r--r--src/libfast/session.h1
-rw-r--r--src/libfast/smtp.c11
-rw-r--r--src/libfreeswan/Android.mk38
-rw-r--r--src/libfreeswan/Makefile.am22
-rw-r--r--src/libfreeswan/addrtoa.c66
-rw-r--r--src/libfreeswan/addrtot.c302
-rw-r--r--src/libfreeswan/addrtypeof.c94
-rw-r--r--src/libfreeswan/anyaddr.386
-rw-r--r--src/libfreeswan/anyaddr.c147
-rw-r--r--src/libfreeswan/atoaddr.3291
-rw-r--r--src/libfreeswan/atoaddr.c261
-rw-r--r--src/libfreeswan/atoasr.3185
-rw-r--r--src/libfreeswan/atoasr.c210
-rw-r--r--src/libfreeswan/atosubnet.c214
-rw-r--r--src/libfreeswan/atoul.3160
-rw-r--r--src/libfreeswan/atoul.c88
-rw-r--r--src/libfreeswan/copyright.c57
-rw-r--r--src/libfreeswan/datatot.c230
-rw-r--r--src/libfreeswan/freeswan.h371
-rw-r--r--src/libfreeswan/goodmask.356
-rw-r--r--src/libfreeswan/goodmask.c95
-rw-r--r--src/libfreeswan/initaddr.3128
-rw-r--r--src/libfreeswan/initaddr.c51
-rw-r--r--src/libfreeswan/initsaid.c31
-rw-r--r--src/libfreeswan/initsubnet.3136
-rw-r--r--src/libfreeswan/initsubnet.c93
-rw-r--r--src/libfreeswan/internal.h46
-rw-r--r--src/libfreeswan/ipsec_param.h54
-rw-r--r--src/libfreeswan/pfkey.h205
-rw-r--r--src/libfreeswan/pfkey_v2_build.c1388
-rw-r--r--src/libfreeswan/pfkey_v2_debug.c104
-rw-r--r--src/libfreeswan/pfkey_v2_ext_bits.c692
-rw-r--r--src/libfreeswan/pfkey_v2_parse.c1539
-rw-r--r--src/libfreeswan/pfkeyv2.h368
-rw-r--r--src/libfreeswan/portof.369
-rw-r--r--src/libfreeswan/portof.c96
-rw-r--r--src/libfreeswan/rangetoa.c59
-rw-r--r--src/libfreeswan/rangetosubnet.358
-rw-r--r--src/libfreeswan/rangetosubnet.c224
-rw-r--r--src/libfreeswan/sameaddr.3164
-rw-r--r--src/libfreeswan/sameaddr.c188
-rw-r--r--src/libfreeswan/satot.c132
-rw-r--r--src/libfreeswan/subnetof.346
-rw-r--r--src/libfreeswan/subnetof.c58
-rw-r--r--src/libfreeswan/subnettoa.c60
-rw-r--r--src/libfreeswan/subnettot.c54
-rw-r--r--src/libfreeswan/subnettypeof.c107
-rw-r--r--src/libfreeswan/ttoaddr.3374
-rw-r--r--src/libfreeswan/ttoaddr.c471
-rw-r--r--src/libfreeswan/ttodata.3280
-rw-r--r--src/libfreeswan/ttodata.c720
-rw-r--r--src/libfreeswan/ttoprotoport.c101
-rw-r--r--src/libfreeswan/ttosa.3287
-rw-r--r--src/libfreeswan/ttosa.c280
-rw-r--r--src/libfreeswan/ttosubnet.c296
-rw-r--r--src/libfreeswan/ttoul.3191
-rw-r--r--src/libfreeswan/ttoul.c89
-rw-r--r--src/libfreeswan/ultoa.c65
-rw-r--r--src/libfreeswan/ultot.c81
-rw-r--r--src/libhydra/Makefile.in14
-rw-r--r--src/libhydra/attributes/attribute_handler.h6
-rw-r--r--src/libhydra/attributes/attribute_manager.c75
-rw-r--r--src/libhydra/attributes/attribute_manager.h23
-rw-r--r--src/libhydra/attributes/attribute_provider.h17
-rw-r--r--src/libhydra/attributes/mem_pool.c208
-rw-r--r--src/libhydra/attributes/mem_pool.h28
-rw-r--r--src/libhydra/hydra.c3
-rw-r--r--src/libhydra/kernel/kernel_interface.c223
-rw-r--r--src/libhydra/kernel/kernel_interface.h105
-rw-r--r--src/libhydra/kernel/kernel_ipsec.c22
-rw-r--r--src/libhydra/kernel/kernel_ipsec.h153
-rw-r--r--src/libhydra/kernel/kernel_net.h43
-rw-r--r--src/libhydra/plugins/attr/Makefile.in14
-rw-r--r--src/libhydra/plugins/attr/attr_provider.c74
-rw-r--r--src/libhydra/plugins/attr_sql/Makefile.in14
-rw-r--r--src/libhydra/plugins/attr_sql/pool_attributes.c6
-rw-r--r--src/libhydra/plugins/attr_sql/sql_attribute.c97
-rw-r--r--src/libhydra/plugins/kernel_klips/Makefile.in14
-rw-r--r--src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c65
-rw-r--r--src/libhydra/plugins/kernel_netlink/Makefile.in14
-rw-r--r--src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c353
-rw-r--r--src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c1712
-rw-r--r--src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.c5
-rw-r--r--src/libhydra/plugins/kernel_pfkey/Makefile.in14
-rw-r--r--src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c205
-rw-r--r--src/libhydra/plugins/kernel_pfroute/Makefile.in14
-rw-r--r--src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c325
-rw-r--r--src/libhydra/plugins/resolve/Makefile.in14
-rw-r--r--src/libhydra/plugins/resolve/resolve_handler.c83
-rw-r--r--src/libimcv/Makefile.am3
-rw-r--r--src/libimcv/Makefile.in46
-rw-r--r--src/libimcv/ietf/ietf_attr.c12
-rw-r--r--src/libimcv/ietf/ietf_attr_assess_result.c209
-rw-r--r--src/libimcv/ietf/ietf_attr_assess_result.h63
-rw-r--r--src/libimcv/ietf/ietf_attr_attr_request.c270
-rw-r--r--src/libimcv/ietf/ietf_attr_attr_request.h71
-rw-r--r--src/libimcv/ietf/ietf_attr_pa_tnc_error.c82
-rw-r--r--src/libimcv/ietf/ietf_attr_pa_tnc_error.h18
-rw-r--r--src/libimcv/ietf/ietf_attr_port_filter.c29
-rw-r--r--src/libimcv/ietf/ietf_attr_product_info.c29
-rw-r--r--src/libimcv/imc/imc_agent.c170
-rw-r--r--src/libimcv/imc/imc_agent.h8
-rw-r--r--src/libimcv/imc/imc_state.h41
-rw-r--r--src/libimcv/imcv.c2
-rw-r--r--src/libimcv/imv/imv_agent.c210
-rw-r--r--src/libimcv/imv/imv_agent.h12
-rw-r--r--src/libimcv/imv/imv_state.h17
-rw-r--r--src/libimcv/ita/ita_attr.c8
-rw-r--r--src/libimcv/ita/ita_attr.h3
-rw-r--r--src/libimcv/ita/ita_attr_command.c32
-rw-r--r--src/libimcv/ita/ita_attr_dummy.c183
-rw-r--r--src/libimcv/ita/ita_attr_dummy.h61
-rw-r--r--src/libimcv/pa_tnc/pa_tnc_attr.h15
-rw-r--r--src/libimcv/pa_tnc/pa_tnc_msg.c165
-rw-r--r--src/libimcv/pa_tnc/pa_tnc_msg.h11
-rw-r--r--src/libimcv/plugins/imc_scanner/Makefile.in14
-rw-r--r--src/libimcv/plugins/imc_scanner/imc_scanner.c67
-rw-r--r--src/libimcv/plugins/imc_scanner/imc_scanner_state.c51
-rw-r--r--src/libimcv/plugins/imc_test/Makefile.in14
-rw-r--r--src/libimcv/plugins/imc_test/imc_test.c103
-rw-r--r--src/libimcv/plugins/imc_test/imc_test_state.c117
-rw-r--r--src/libimcv/plugins/imc_test/imc_test_state.h16
-rw-r--r--src/libimcv/plugins/imv_scanner/Makefile.in14
-rw-r--r--src/libimcv/plugins/imv_scanner/imv_scanner.c17
-rw-r--r--src/libimcv/plugins/imv_scanner/imv_scanner_state.c22
-rw-r--r--src/libimcv/plugins/imv_test/Makefile.in14
-rw-r--r--src/libimcv/plugins/imv_test/imv_test.c46
-rw-r--r--src/libimcv/plugins/imv_test/imv_test_state.c22
-rw-r--r--src/libipsec/Android.mk38
-rw-r--r--src/libipsec/Makefile.am31
-rw-r--r--src/libipsec/Makefile.in (renamed from src/libfreeswan/Makefile.in)492
-rw-r--r--src/libipsec/esp_context.c301
-rw-r--r--src/libipsec/esp_context.h110
-rw-r--r--src/libipsec/esp_packet.c468
-rw-r--r--src/libipsec/esp_packet.h151
-rw-r--r--src/libipsec/ip_packet.c193
-rw-r--r--src/libipsec/ip_packet.h96
-rw-r--r--src/libipsec/ipsec.c77
-rw-r--r--src/libipsec/ipsec.h83
-rw-r--r--src/libipsec/ipsec_event_listener.h48
-rw-r--r--src/libipsec/ipsec_event_relay.c193
-rw-r--r--src/libipsec/ipsec_event_relay.h79
-rw-r--r--src/libipsec/ipsec_policy.c212
-rw-r--r--src/libipsec/ipsec_policy.h140
-rw-r--r--src/libipsec/ipsec_policy_mgr.c286
-rw-r--r--src/libipsec/ipsec_policy_mgr.h119
-rw-r--r--src/libipsec/ipsec_processor.c324
-rw-r--r--src/libipsec/ipsec_processor.h115
-rw-r--r--src/libipsec/ipsec_sa.c234
-rw-r--r--src/libipsec/ipsec_sa.h169
-rw-r--r--src/libipsec/ipsec_sa_mgr.c626
-rw-r--r--src/libipsec/ipsec_sa_mgr.h167
-rw-r--r--src/libpts/Makefile.am1
-rw-r--r--src/libpts/Makefile.in27
-rw-r--r--src/libpts/plugins/imc_attestation/Makefile.in14
-rw-r--r--src/libpts/plugins/imc_attestation/imc_attestation.c88
-rw-r--r--src/libpts/plugins/imc_attestation/imc_attestation_process.c72
-rw-r--r--src/libpts/plugins/imc_attestation/imc_attestation_state.c103
-rw-r--r--src/libpts/plugins/imc_attestation/imc_attestation_state.h19
-rw-r--r--src/libpts/plugins/imv_attestation/Makefile.am2
-rw-r--r--src/libpts/plugins/imv_attestation/Makefile.in15
-rw-r--r--src/libpts/plugins/imv_attestation/attest.c18
-rw-r--r--src/libpts/plugins/imv_attestation/attest_db.c382
-rw-r--r--src/libpts/plugins/imv_attestation/attest_db.h15
-rw-r--r--src/libpts/plugins/imv_attestation/attest_usage.c23
-rwxr-xr-xsrc/libpts/plugins/imv_attestation/build-database.sh221
-rw-r--r--src/libpts/plugins/imv_attestation/data.sql371
-rw-r--r--src/libpts/plugins/imv_attestation/imv_attestation.c74
-rw-r--r--src/libpts/plugins/imv_attestation/imv_attestation_build.c24
-rw-r--r--src/libpts/plugins/imv_attestation/imv_attestation_process.c72
-rw-r--r--src/libpts/plugins/imv_attestation/imv_attestation_state.c162
-rw-r--r--src/libpts/plugins/imv_attestation/imv_attestation_state.h36
-rw-r--r--src/libpts/plugins/imv_attestation/tables.sql5
-rw-r--r--src/libpts/pts/components/ita/ita_comp_ima.c807
-rw-r--r--src/libpts/pts/components/ita/ita_comp_ima.h5
-rw-r--r--src/libpts/pts/components/ita/ita_comp_tboot.c149
-rw-r--r--src/libpts/pts/components/ita/ita_comp_tboot.h5
-rw-r--r--src/libpts/pts/components/ita/ita_comp_tgrub.c65
-rw-r--r--src/libpts/pts/components/ita/ita_comp_tgrub.h5
-rw-r--r--src/libpts/pts/components/pts_comp_evidence.c22
-rw-r--r--src/libpts/pts/components/pts_comp_evidence.h4
-rw-r--r--src/libpts/pts/components/pts_comp_func_name.c9
-rw-r--r--src/libpts/pts/components/pts_comp_func_name.h9
-rw-r--r--src/libpts/pts/components/pts_component.h24
-rw-r--r--src/libpts/pts/components/pts_component_manager.c6
-rw-r--r--src/libpts/pts/components/pts_component_manager.h3
-rw-r--r--src/libpts/pts/pts.c420
-rw-r--r--src/libpts/pts/pts.h53
-rw-r--r--src/libpts/pts/pts_database.c41
-rw-r--r--src/libpts/pts/pts_database.h13
-rw-r--r--src/libpts/pts/pts_error.c12
-rw-r--r--src/libpts/pts/pts_file_meas.c188
-rw-r--r--src/libpts/pts/pts_file_meas.h26
-rw-r--r--src/libpts/pts/pts_meas_algo.c21
-rw-r--r--src/libpts/pts/pts_meas_algo.h9
-rw-r--r--src/libpts/pts/pts_pcr.c289
-rw-r--r--src/libpts/pts/pts_pcr.h118
-rw-r--r--src/libpts/tcg/tcg_pts_attr_aik.c31
-rw-r--r--src/libpts/tcg/tcg_pts_attr_dh_nonce_finish.c31
-rw-r--r--src/libpts/tcg/tcg_pts_attr_dh_nonce_params_req.c31
-rw-r--r--src/libpts/tcg/tcg_pts_attr_dh_nonce_params_resp.c31
-rw-r--r--src/libpts/tcg/tcg_pts_attr_file_meas.c31
-rw-r--r--src/libpts/tcg/tcg_pts_attr_gen_attest_evid.c31
-rw-r--r--src/libpts/tcg/tcg_pts_attr_get_aik.c31
-rw-r--r--src/libpts/tcg/tcg_pts_attr_get_tpm_version_info.c31
-rw-r--r--src/libpts/tcg/tcg_pts_attr_meas_algo.c33
-rw-r--r--src/libpts/tcg/tcg_pts_attr_proto_caps.c33
-rw-r--r--src/libpts/tcg/tcg_pts_attr_req_file_meas.c31
-rw-r--r--src/libpts/tcg/tcg_pts_attr_req_file_meta.c31
-rw-r--r--src/libpts/tcg/tcg_pts_attr_req_func_comp_evid.c31
-rw-r--r--src/libpts/tcg/tcg_pts_attr_simple_comp_evid.c51
-rw-r--r--src/libpts/tcg/tcg_pts_attr_simple_evid_final.c31
-rw-r--r--src/libpts/tcg/tcg_pts_attr_tpm_version_info.c31
-rw-r--r--src/libpts/tcg/tcg_pts_attr_unix_file_meta.c31
-rw-r--r--src/libradius/Makefile.in14
-rw-r--r--src/libradius/radius_message.c28
-rw-r--r--src/libradius/radius_message.h3
-rw-r--r--src/libradius/radius_socket.c18
-rw-r--r--src/libsimaka/Makefile.in14
-rw-r--r--src/libsimaka/simaka_crypto.c94
-rw-r--r--src/libsimaka/simaka_crypto.h18
-rw-r--r--src/libsimaka/simaka_message.c28
-rw-r--r--src/libsimaka/simaka_message.h5
-rw-r--r--src/libstrongswan/Android.mk108
-rw-r--r--src/libstrongswan/AndroidConfigLocal.h15
-rw-r--r--src/libstrongswan/Makefile.am167
-rw-r--r--src/libstrongswan/Makefile.in759
-rw-r--r--src/libstrongswan/asn1/asn1.c20
-rw-r--r--src/libstrongswan/asn1/oid.c289
-rw-r--r--src/libstrongswan/asn1/oid.h141
-rw-r--r--src/libstrongswan/asn1/oid.txt3
-rw-r--r--src/libstrongswan/bio/bio_reader.c174
-rw-r--r--src/libstrongswan/bio/bio_reader.h54
-rw-r--r--src/libstrongswan/bio/bio_writer.c28
-rw-r--r--src/libstrongswan/bio/bio_writer.h25
-rw-r--r--src/libstrongswan/chunk.c8
-rw-r--r--src/libstrongswan/chunk.h11
-rw-r--r--src/libstrongswan/credentials/auth_cfg.c210
-rw-r--r--src/libstrongswan/credentials/auth_cfg.h13
-rw-r--r--src/libstrongswan/credentials/certificates/certificate.h4
-rw-r--r--src/libstrongswan/credentials/certificates/x509.h2
-rw-r--r--src/libstrongswan/credentials/credential_manager.c200
-rw-r--r--src/libstrongswan/credentials/credential_manager.h12
-rw-r--r--src/libstrongswan/credentials/sets/cert_cache.c28
-rw-r--r--src/libstrongswan/credentials/sets/cert_cache.h4
-rw-r--r--src/libstrongswan/crypto/aead.c45
-rw-r--r--src/libstrongswan/crypto/aead.h9
-rw-r--r--src/libstrongswan/crypto/crypters/crypter.h20
-rw-r--r--src/libstrongswan/crypto/crypto_factory.c104
-rw-r--r--src/libstrongswan/crypto/crypto_factory.h51
-rw-r--r--src/libstrongswan/crypto/crypto_tester.c371
-rw-r--r--src/libstrongswan/crypto/hashers/hasher.c116
-rw-r--r--src/libstrongswan/crypto/hashers/hasher.h53
-rw-r--r--src/libstrongswan/crypto/mac.h76
-rw-r--r--src/libstrongswan/crypto/nonce_gen.h59
-rw-r--r--src/libstrongswan/crypto/pkcs7.c1061
-rw-r--r--src/libstrongswan/crypto/pkcs7.h178
-rw-r--r--src/libstrongswan/crypto/pkcs9.c101
-rw-r--r--src/libstrongswan/crypto/pkcs9.h19
-rw-r--r--src/libstrongswan/crypto/prf_plus.c126
-rw-r--r--src/libstrongswan/crypto/prf_plus.h34
-rw-r--r--src/libstrongswan/crypto/prfs/mac_prf.c101
-rw-r--r--src/libstrongswan/crypto/prfs/mac_prf.h (renamed from src/pluto/plugins/xauth/xauth_default_verifier.h)25
-rw-r--r--src/libstrongswan/crypto/prfs/prf.h19
-rw-r--r--src/libstrongswan/crypto/proposal/proposal_keywords.c416
-rw-r--r--src/libstrongswan/crypto/proposal/proposal_keywords.h109
-rw-r--r--src/libstrongswan/crypto/proposal/proposal_keywords_static.c324
-rw-r--r--src/libstrongswan/crypto/proposal/proposal_keywords_static.h (renamed from src/pluto/cookie.h)17
-rw-r--r--src/libstrongswan/crypto/proposal/proposal_keywords_static.txt (renamed from src/libstrongswan/crypto/proposal/proposal_keywords.txt)8
-rw-r--r--src/libstrongswan/crypto/rngs/rng.c41
-rw-r--r--src/libstrongswan/crypto/rngs/rng.h39
-rw-r--r--src/libstrongswan/crypto/signers/mac_signer.c139
-rw-r--r--src/libstrongswan/crypto/signers/mac_signer.h (renamed from src/libstrongswan/plugins/cmac/cmac_signer.h)36
-rw-r--r--src/libstrongswan/crypto/signers/signer.h20
-rw-r--r--src/libstrongswan/crypto/transform.c7
-rw-r--r--src/libstrongswan/crypto/transform.h3
-rw-r--r--src/libstrongswan/debug.c4
-rw-r--r--src/libstrongswan/debug.h4
-rw-r--r--src/libstrongswan/eap/eap.c80
-rw-r--r--src/libstrongswan/eap/eap.h39
-rw-r--r--src/libstrongswan/enum.c6
-rw-r--r--src/libstrongswan/enum.h2
-rw-r--r--src/libstrongswan/ipsec/ipsec_types.c (renamed from src/pluto/plugins/xauth/xauth_default_provider.h)37
-rw-r--r--src/libstrongswan/ipsec/ipsec_types.h172
-rw-r--r--src/libstrongswan/library.c6
-rw-r--r--src/libstrongswan/library.h13
-rw-r--r--src/libstrongswan/pen/pen.c8
-rw-r--r--src/libstrongswan/pen/pen.h22
-rw-r--r--src/libstrongswan/plugins/aes/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/aes/aes_crypter.c9
-rw-r--r--src/libstrongswan/plugins/af_alg/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/af_alg/af_alg_crypter.c22
-rw-r--r--src/libstrongswan/plugins/af_alg/af_alg_hasher.c16
-rw-r--r--src/libstrongswan/plugins/af_alg/af_alg_ops.c73
-rw-r--r--src/libstrongswan/plugins/af_alg/af_alg_ops.h9
-rw-r--r--src/libstrongswan/plugins/af_alg/af_alg_prf.c24
-rw-r--r--src/libstrongswan/plugins/af_alg/af_alg_signer.c22
-rw-r--r--src/libstrongswan/plugins/agent/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/blowfish/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/blowfish/blowfish_crypter.c11
-rw-r--r--src/libstrongswan/plugins/ccm/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/ccm/ccm_aead.c70
-rw-r--r--src/libstrongswan/plugins/cmac/Makefile.am3
-rw-r--r--src/libstrongswan/plugins/cmac/Makefile.in22
-rw-r--r--src/libstrongswan/plugins/cmac/cmac.c127
-rw-r--r--src/libstrongswan/plugins/cmac/cmac.h60
-rw-r--r--src/libstrongswan/plugins/cmac/cmac_plugin.c3
-rw-r--r--src/libstrongswan/plugins/cmac/cmac_prf.c121
-rw-r--r--src/libstrongswan/plugins/cmac/cmac_signer.c159
-rw-r--r--src/libstrongswan/plugins/constraints/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/ctr/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/ctr/ctr_ipsec_crypter.c23
-rw-r--r--src/libstrongswan/plugins/curl/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/des/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/des/des_crypter.c24
-rw-r--r--src/libstrongswan/plugins/dnskey/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/fips_prf/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/fips_prf/fips_prf.c23
-rw-r--r--src/libstrongswan/plugins/gcm/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/gcm/gcm_aead.c65
-rw-r--r--src/libstrongswan/plugins/gcrypt/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/gcrypt/gcrypt_crypter.c45
-rw-r--r--src/libstrongswan/plugins/gcrypt/gcrypt_dh.c4
-rw-r--r--src/libstrongswan/plugins/gcrypt/gcrypt_hasher.c15
-rw-r--r--src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c2
-rw-r--r--src/libstrongswan/plugins/gcrypt/gcrypt_rng.c6
-rw-r--r--src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c4
-rw-r--r--src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c4
-rw-r--r--src/libstrongswan/plugins/gmp/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c9
-rw-r--r--src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c11
-rw-r--r--src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c22
-rw-r--r--src/libstrongswan/plugins/hmac/Makefile.am3
-rw-r--r--src/libstrongswan/plugins/hmac/Makefile.in22
-rw-r--r--src/libstrongswan/plugins/hmac/hmac.c123
-rw-r--r--src/libstrongswan/plugins/hmac/hmac.h78
-rw-r--r--src/libstrongswan/plugins/hmac/hmac_plugin.c3
-rw-r--r--src/libstrongswan/plugins/hmac/hmac_prf.c126
-rw-r--r--src/libstrongswan/plugins/hmac/hmac_prf.h51
-rw-r--r--src/libstrongswan/plugins/hmac/hmac_signer.c197
-rw-r--r--src/libstrongswan/plugins/hmac/hmac_signer.h54
-rw-r--r--src/libstrongswan/plugins/ldap/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/ldap/ldap_fetcher.c7
-rw-r--r--src/libstrongswan/plugins/md4/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/md4/md4_hasher.c32
-rw-r--r--src/libstrongswan/plugins/md5/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/md5/md5_hasher.c44
-rw-r--r--src/libstrongswan/plugins/md5/md5_plugin.c2
-rw-r--r--src/libstrongswan/plugins/mysql/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/mysql/mysql_database.c1
-rw-r--r--src/libstrongswan/plugins/nonce/Makefile.am16
-rw-r--r--src/libstrongswan/plugins/nonce/Makefile.in (renamed from src/pluto/plugins/xauth/Makefile.in)104
-rw-r--r--src/libstrongswan/plugins/nonce/nonce_nonceg.c84
-rw-r--r--src/libstrongswan/plugins/nonce/nonce_nonceg.h46
-rw-r--r--src/libstrongswan/plugins/nonce/nonce_plugin.c (renamed from src/libcharon/plugins/socket_raw/socket_raw_plugin.c)39
-rw-r--r--src/libstrongswan/plugins/nonce/nonce_plugin.h (renamed from src/pluto/plugins/xauth/xauth_plugin.h)24
-rw-r--r--src/libstrongswan/plugins/openssl/Makefile.am4
-rw-r--r--src/libstrongswan/plugins/openssl/Makefile.in23
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_crl.c7
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_crypter.c28
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_ec_public_key.c4
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_hasher.c88
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_hmac.c191
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_hmac.h (renamed from src/libstrongswan/plugins/cmac/cmac_prf.h)35
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_plugin.c55
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_rng.c100
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_rng.h54
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c3
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c4
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_sha1_prf.c20
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_x509.c13
-rw-r--r--src/libstrongswan/plugins/padlock/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/padlock/padlock_aes_crypter.c9
-rw-r--r--src/libstrongswan/plugins/padlock/padlock_rng.c6
-rw-r--r--src/libstrongswan/plugins/padlock/padlock_sha1_hasher.c15
-rw-r--r--src/libstrongswan/plugins/pem/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/pem/pem_builder.c26
-rw-r--r--src/libstrongswan/plugins/pem/pem_plugin.c26
-rw-r--r--src/libstrongswan/plugins/pgp/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/pgp/pgp_cert.c10
-rw-r--r--src/libstrongswan/plugins/pgp/pgp_encoder.c8
-rw-r--r--src/libstrongswan/plugins/pkcs1/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/pkcs1/pkcs1_encoder.c4
-rw-r--r--src/libstrongswan/plugins/pkcs11/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/pkcs11/pkcs11_creds.c5
-rw-r--r--src/libstrongswan/plugins/pkcs11/pkcs11_hasher.c47
-rw-r--r--src/libstrongswan/plugins/pkcs11/pkcs11_manager.c20
-rw-r--r--src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c8
-rw-r--r--src/libstrongswan/plugins/pkcs11/pkcs11_public_key.c12
-rw-r--r--src/libstrongswan/plugins/pkcs11/pkcs11_rng.c14
-rw-r--r--src/libstrongswan/plugins/pkcs8/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/pkcs8/pkcs8_builder.c60
-rw-r--r--src/libstrongswan/plugins/plugin_feature.c88
-rw-r--r--src/libstrongswan/plugins/plugin_feature.h49
-rw-r--r--src/libstrongswan/plugins/plugin_loader.c233
-rw-r--r--src/libstrongswan/plugins/plugin_loader.h24
-rw-r--r--src/libstrongswan/plugins/pubkey/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/pubkey/pubkey_cert.c7
-rw-r--r--src/libstrongswan/plugins/pubkey/pubkey_plugin.c5
-rw-r--r--src/libstrongswan/plugins/random/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/random/random_plugin.c70
-rw-r--r--src/libstrongswan/plugins/random/random_plugin.h10
-rw-r--r--src/libstrongswan/plugins/random/random_rng.c56
-rw-r--r--src/libstrongswan/plugins/revocation/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/revocation/revocation_validator.c6
-rw-r--r--src/libstrongswan/plugins/sha1/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/sha1/sha1_hasher.c10
-rw-r--r--src/libstrongswan/plugins/sha1/sha1_prf.c17
-rw-r--r--src/libstrongswan/plugins/sha2/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/sha2/sha2_hasher.c40
-rw-r--r--src/libstrongswan/plugins/soup/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/sqlite/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/sqlite/sqlite_database.c1
-rw-r--r--src/libstrongswan/plugins/test_vectors/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/test_vectors/test_vectors.h1
-rw-r--r--src/libstrongswan/plugins/test_vectors/test_vectors/sha1.c6
-rw-r--r--src/libstrongswan/plugins/x509/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/x509/x509_ac.c6
-rw-r--r--src/libstrongswan/plugins/x509/x509_cert.c64
-rw-r--r--src/libstrongswan/plugins/x509/x509_crl.c8
-rw-r--r--src/libstrongswan/plugins/x509/x509_ocsp_request.c47
-rw-r--r--src/libstrongswan/plugins/x509/x509_ocsp_response.c16
-rw-r--r--src/libstrongswan/plugins/x509/x509_pkcs10.c17
-rw-r--r--src/libstrongswan/plugins/x509/x509_plugin.c3
-rw-r--r--src/libstrongswan/plugins/xcbc/Makefile.am3
-rw-r--r--src/libstrongswan/plugins/xcbc/Makefile.in22
-rw-r--r--src/libstrongswan/plugins/xcbc/xcbc.c148
-rw-r--r--src/libstrongswan/plugins/xcbc/xcbc.h60
-rw-r--r--src/libstrongswan/plugins/xcbc/xcbc_plugin.c3
-rw-r--r--src/libstrongswan/plugins/xcbc/xcbc_prf.c124
-rw-r--r--src/libstrongswan/plugins/xcbc/xcbc_prf.h50
-rw-r--r--src/libstrongswan/plugins/xcbc/xcbc_signer.c164
-rw-r--r--src/libstrongswan/plugins/xcbc/xcbc_signer.h47
-rw-r--r--src/libstrongswan/printf_hook.c42
-rw-r--r--src/libstrongswan/printf_hook.h126
-rw-r--r--src/libstrongswan/processing/jobs/callback_job.c186
-rw-r--r--src/libstrongswan/processing/jobs/callback_job.h66
-rw-r--r--src/libstrongswan/processing/jobs/job.h107
-rw-r--r--src/libstrongswan/processing/processor.c219
-rw-r--r--src/libstrongswan/processing/processor.h14
-rw-r--r--src/libstrongswan/processing/scheduler.c14
-rw-r--r--src/libstrongswan/selectors/traffic_selector.c94
-rw-r--r--src/libstrongswan/selectors/traffic_selector.h7
-rw-r--r--src/libstrongswan/settings.c11
-rw-r--r--src/libstrongswan/settings.h2
-rw-r--r--src/libstrongswan/threading/mutex.c40
-rw-r--r--src/libstrongswan/threading/rwlock.c233
-rw-r--r--src/libstrongswan/threading/rwlock_condvar.h90
-rw-r--r--src/libstrongswan/threading/semaphore.c179
-rw-r--r--src/libstrongswan/threading/semaphore.h85
-rw-r--r--src/libstrongswan/threading/spinlock.c136
-rw-r--r--src/libstrongswan/threading/spinlock.h58
-rw-r--r--src/libstrongswan/threading/thread.c4
-rw-r--r--src/libstrongswan/threading/thread_value.c21
-rw-r--r--src/libstrongswan/utils.c99
-rw-r--r--src/libstrongswan/utils.h110
-rw-r--r--src/libstrongswan/utils/backtrace.c325
-rw-r--r--src/libstrongswan/utils/backtrace.h19
-rw-r--r--src/libstrongswan/utils/blocking_queue.c129
-rw-r--r--src/libstrongswan/utils/blocking_queue.h97
-rw-r--r--src/libstrongswan/utils/capabilities.c291
-rw-r--r--src/libstrongswan/utils/capabilities.h107
-rw-r--r--src/libstrongswan/utils/enumerator.c12
-rw-r--r--src/libstrongswan/utils/enumerator.h5
-rw-r--r--src/libstrongswan/utils/hashtable.c26
-rw-r--r--src/libstrongswan/utils/hashtable.h18
-rw-r--r--src/libstrongswan/utils/host.c22
-rw-r--r--src/libstrongswan/utils/host.h15
-rw-r--r--src/libstrongswan/utils/identification.c34
-rw-r--r--src/libstrongswan/utils/identification.h4
-rw-r--r--src/libstrongswan/utils/leak_detective.c52
-rw-r--r--src/libstrongswan/utils/leak_detective.h8
-rw-r--r--src/libstrongswan/utils/linked_list.c41
-rw-r--r--src/libstrongswan/utils/linked_list.h17
-rw-r--r--src/libstrongswan/utils/packet.c (renamed from src/libcharon/network/packet.c)45
-rw-r--r--src/libstrongswan/utils/packet.h121
-rw-r--r--src/libstrongswan/utils/tun_device.c461
-rw-r--r--src/libstrongswan/utils/tun_device.h112
-rw-r--r--src/libtls/Makefile.am23
-rw-r--r--src/libtls/Makefile.in90
-rw-r--r--src/libtls/tls.h6
-rw-r--r--src/libtls/tls_crypto.c96
-rw-r--r--src/libtls/tls_crypto.h3
-rw-r--r--src/libtls/tls_eap.c59
-rw-r--r--src/libtls/tls_fragmentation.c33
-rw-r--r--src/libtls/tls_peer.c39
-rw-r--r--src/libtls/tls_prf.c46
-rw-r--r--src/libtls/tls_prf.h6
-rw-r--r--src/libtls/tls_protection.c45
-rw-r--r--src/libtls/tls_server.c45
-rw-r--r--src/libtnccs/Makefile.in14
-rw-r--r--src/libtnccs/tnc/imv/imv_recommendations.h10
-rw-r--r--src/libtnccs/tnc/tnc.c14
-rw-r--r--src/libtnccs/tnc/tnccs/tnccs_manager.h2
-rw-r--r--src/libtncif/Makefile.in14
-rw-r--r--src/manager/Makefile.in14
-rw-r--r--src/manager/storage.c6
-rw-r--r--src/medsrv/Makefile.in14
-rw-r--r--[-rwxr-xr-x]src/medsrv/controller/peer_controller.c0
-rw-r--r--[-rwxr-xr-x]src/medsrv/controller/peer_controller.h0
-rw-r--r--[-rwxr-xr-x]src/medsrv/controller/user_controller.c6
-rw-r--r--[-rwxr-xr-x]src/medsrv/controller/user_controller.h0
-rw-r--r--[-rwxr-xr-x]src/medsrv/filter/auth_filter.c0
-rw-r--r--[-rwxr-xr-x]src/medsrv/filter/auth_filter.h0
-rw-r--r--[-rwxr-xr-x]src/medsrv/templates/footer.cs0
-rw-r--r--[-rwxr-xr-x]src/medsrv/templates/header.cs0
-rw-r--r--[-rwxr-xr-x]src/medsrv/templates/peer/add.cs0
-rw-r--r--[-rwxr-xr-x]src/medsrv/templates/peer/edit.cs0
-rw-r--r--[-rwxr-xr-x]src/medsrv/templates/peer/list.cs0
-rw-r--r--[-rwxr-xr-x]src/medsrv/templates/static/favicon.icobin894 -> 894 bytes
-rw-r--r--[-rwxr-xr-x]src/medsrv/templates/static/strongswan.pngbin19837 -> 19837 bytes
-rw-r--r--[-rwxr-xr-x]src/medsrv/templates/static/style.css0
-rw-r--r--[-rwxr-xr-x]src/medsrv/templates/user/add.cs0
-rw-r--r--[-rwxr-xr-x]src/medsrv/templates/user/edit.cs0
-rw-r--r--[-rwxr-xr-x]src/medsrv/templates/user/login.cs0
-rw-r--r--src/openac/Makefile.in14
-rw-r--r--[-rwxr-xr-x]src/openac/openac.c0
-rw-r--r--src/pki/Makefile.in14
-rw-r--r--src/pki/command.c2
-rw-r--r--src/pki/commands/issue.c16
-rw-r--r--src/pki/commands/print.c4
-rw-r--r--src/pki/commands/req.c4
-rw-r--r--src/pki/commands/self.c16
-rw-r--r--src/pki/commands/signcrl.c4
-rw-r--r--src/pki/commands/verify.c2
-rw-r--r--src/pki/pki.c32
-rw-r--r--src/pki/pki.h5
-rw-r--r--src/pluto/Android.mk80
-rw-r--r--src/pluto/Makefile.am155
-rw-r--r--src/pluto/Makefile.in1001
-rw-r--r--src/pluto/ac.c298
-rw-r--r--src/pluto/ac.h39
-rw-r--r--src/pluto/adns.c610
-rw-r--r--src/pluto/adns.h78
-rw-r--r--src/pluto/alg_info.c683
-rw-r--r--src/pluto/alg_info.h80
-rw-r--r--src/pluto/builder.c150
-rw-r--r--src/pluto/builder.h24
-rw-r--r--src/pluto/ca.c712
-rw-r--r--src/pluto/ca.h58
-rw-r--r--src/pluto/certs.c268
-rw-r--r--src/pluto/certs.h80
-rw-r--r--src/pluto/connections.c4507
-rw-r--r--src/pluto/connections.h366
-rw-r--r--src/pluto/constants.c1401
-rw-r--r--src/pluto/constants.h1099
-rw-r--r--src/pluto/cookie.c73
-rw-r--r--src/pluto/crl.c541
-rw-r--r--src/pluto/crl.h53
-rw-r--r--src/pluto/crypto.c698
-rw-r--r--src/pluto/crypto.h64
-rw-r--r--src/pluto/db_ops.c412
-rw-r--r--src/pluto/db_ops.h54
-rw-r--r--src/pluto/defs.c145
-rw-r--r--src/pluto/defs.h79
-rw-r--r--src/pluto/demux.c2527
-rw-r--r--src/pluto/demux.h97
-rw-r--r--src/pluto/dnskey.c1590
-rw-r--r--src/pluto/dnskey.h75
-rw-r--r--src/pluto/event_queue.c195
-rw-r--r--src/pluto/event_queue.h69
-rw-r--r--src/pluto/fetch.c766
-rw-r--r--src/pluto/fetch.h82
-rw-r--r--src/pluto/foodgroups.c450
-rw-r--r--src/pluto/foodgroups.h22
-rw-r--r--src/pluto/ike_alg.c452
-rw-r--r--src/pluto/ike_alg.h76
-rw-r--r--src/pluto/ipsec_doi.c5921
-rw-r--r--src/pluto/ipsec_doi.h108
-rw-r--r--src/pluto/kameipsec.h47
-rw-r--r--src/pluto/kernel.c2114
-rw-r--r--src/pluto/kernel.h118
-rw-r--r--src/pluto/kernel_alg.c663
-rw-r--r--src/pluto/kernel_alg.h43
-rw-r--r--src/pluto/kernel_pfkey.c380
-rw-r--r--src/pluto/kernel_pfkey.h20
-rw-r--r--src/pluto/keys.c1474
-rw-r--r--src/pluto/keys.h93
-rw-r--r--src/pluto/lex.c211
-rw-r--r--src/pluto/lex.h50
-rw-r--r--src/pluto/log.c946
-rw-r--r--src/pluto/log.h234
-rw-r--r--src/pluto/modecfg.c1263
-rw-r--r--src/pluto/modecfg.h78
-rw-r--r--src/pluto/myid.c121
-rw-r--r--src/pluto/myid.h38
-rw-r--r--src/pluto/nat_traversal.c845
-rw-r--r--src/pluto/nat_traversal.h152
-rw-r--r--src/pluto/ocsp.c1558
-rw-r--r--src/pluto/ocsp.h85
-rw-r--r--src/pluto/packet.c1242
-rw-r--r--src/pluto/packet.h653
-rw-r--r--src/pluto/pkcs7.c755
-rw-r--r--src/pluto/pkcs7.h53
-rw-r--r--src/pluto/plugin_list.c72
-rw-r--r--src/pluto/plugin_list.h21
-rw-r--r--src/pluto/plugins/xauth/Makefile.am15
-rw-r--r--src/pluto/plugins/xauth/xauth_default_provider.c66
-rw-r--r--src/pluto/plugins/xauth/xauth_default_verifier.c81
-rw-r--r--src/pluto/pluto.81594
-rw-r--r--src/pluto/pluto.c73
-rw-r--r--src/pluto/pluto.h76
-rw-r--r--src/pluto/plutomain.c852
-rw-r--r--src/pluto/rcv_whack.c728
-rw-r--r--src/pluto/rcv_whack.h15
-rw-r--r--src/pluto/rsaref/pkcs11.h299
-rw-r--r--src/pluto/rsaref/pkcs11f.h912
-rw-r--r--src/pluto/rsaref/pkcs11t.h1685
-rw-r--r--src/pluto/rsaref/unix.h24
-rw-r--r--src/pluto/server.c910
-rw-r--r--src/pluto/server.h56
-rw-r--r--src/pluto/smartcard.c1940
-rw-r--r--src/pluto/smartcard.h100
-rw-r--r--src/pluto/spdb.c2315
-rw-r--r--src/pluto/spdb.h110
-rw-r--r--src/pluto/state.c952
-rw-r--r--src/pluto/state.h274
-rw-r--r--src/pluto/timer.c551
-rw-r--r--src/pluto/timer.h34
-rw-r--r--src/pluto/vendor.c511
-rw-r--r--src/pluto/vendor.h137
-rw-r--r--src/pluto/virtual.c325
-rw-r--r--src/pluto/virtual.h29
-rw-r--r--src/pluto/whack_attribute.c365
-rw-r--r--src/pluto/whack_attribute.h111
-rw-r--r--src/pluto/x509.c463
-rw-r--r--src/pluto/x509.h42
-rw-r--r--src/pluto/xauth/xauth_manager.c127
-rw-r--r--src/pluto/xauth/xauth_manager.h80
-rw-r--r--src/pluto/xauth/xauth_provider.h56
-rw-r--r--src/pluto/xauth/xauth_verifier.h56
-rw-r--r--src/scepclient/Makefile.am47
-rw-r--r--src/scepclient/Makefile.in77
-rw-r--r--src/scepclient/loglite.c350
-rw-r--r--src/scepclient/scep.c360
-rw-r--r--src/scepclient/scep.h46
-rw-r--r--src/scepclient/scepclient.8172
-rw-r--r--src/scepclient/scepclient.c865
-rw-r--r--src/starter/Android.mk21
-rw-r--r--src/starter/Makefile.am25
-rw-r--r--src/starter/Makefile.in62
-rw-r--r--src/starter/args.c171
-rw-r--r--src/starter/cmp.c67
-rw-r--r--src/starter/cmp.h9
-rw-r--r--src/starter/confread.c684
-rw-r--r--src/starter/confread.h121
-rw-r--r--src/starter/exec.c52
-rw-r--r--src/starter/exec.h21
-rw-r--r--src/starter/files.h4
-rw-r--r--src/starter/interfaces.c213
-rw-r--r--src/starter/interfaces.h36
-rw-r--r--src/starter/invokecharon.c43
-rw-r--r--src/starter/invokepluto.c327
-rw-r--r--src/starter/invokepluto.h26
-rw-r--r--src/starter/ipsec.conf10
-rw-r--r--src/starter/keywords.c283
-rw-r--r--src/starter/keywords.h91
-rw-r--r--src/starter/keywords.txt97
-rw-r--r--src/starter/klips.c26
-rw-r--r--src/starter/loglite.c297
-rw-r--r--src/starter/netkey.c28
-rw-r--r--src/starter/parser.c46
-rw-r--r--src/starter/parser.h2
-rw-r--r--src/starter/parser.y18
-rw-r--r--src/starter/starter.c488
-rw-r--r--src/starter/starterstroke.c173
-rw-r--r--src/starter/starterstroke.h19
-rw-r--r--src/starter/starterwhack.c420
-rw-r--r--src/starter/starterwhack.h30
-rw-r--r--src/stroke/Makefile.in14
-rw-r--r--src/stroke/stroke.c5
-rw-r--r--src/stroke/stroke_msg.h13
-rw-r--r--src/whack/Android.mk30
-rw-r--r--src/whack/Makefile.am18
-rw-r--r--src/whack/whack.c1959
-rw-r--r--src/whack/whack.h352
1200 files changed, 61902 insertions, 92399 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 1440de20f..e4c0374a2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -8,6 +8,10 @@ if USE_LIBHYDRA
SUBDIRS += libhydra
endif
+if USE_LIBIPSEC
+ SUBDIRS += libipsec
+endif
+
if USE_SIMAKA
SUBDIRS += libsimaka
endif
@@ -41,21 +45,21 @@ if USE_LIBCHARON
endif
if USE_FILE_CONFIG
- SUBDIRS += libfreeswan starter
+ SUBDIRS += starter
endif
if USE_IPSEC_SCRIPT
SUBDIRS += ipsec _copyright
endif
-if USE_PLUTO
- SUBDIRS += pluto whack
-endif
-
if USE_CHARON
SUBDIRS += charon
endif
+if USE_NM
+ SUBDIRS += charon-nm
+endif
+
if USE_STROKE
SUBDIRS += stroke
endif
@@ -65,7 +69,7 @@ if USE_UPDOWN
endif
if USE_TOOLS
- SUBDIRS += libfreeswan openac scepclient pki
+ SUBDIRS += openac scepclient pki
endif
if USE_CONFTEST
diff --git a/src/Makefile.in b/src/Makefile.in
index caa0c5bb9..939473424 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -35,27 +35,28 @@ build_triplet = @build@
host_triplet = @host@
@USE_LIBSTRONGSWAN_TRUE@am__append_1 = libstrongswan
@USE_LIBHYDRA_TRUE@am__append_2 = libhydra
-@USE_SIMAKA_TRUE@am__append_3 = libsimaka
-@USE_TLS_TRUE@am__append_4 = libtls
-@USE_RADIUS_TRUE@am__append_5 = libradius
-@USE_LIBTNCIF_TRUE@am__append_6 = libtncif
-@USE_LIBTNCCS_TRUE@am__append_7 = libtnccs
-@USE_IMCV_TRUE@am__append_8 = libimcv
-@USE_PTS_TRUE@am__append_9 = libpts
-@USE_LIBCHARON_TRUE@am__append_10 = libcharon
-@USE_FILE_CONFIG_TRUE@am__append_11 = libfreeswan starter
-@USE_IPSEC_SCRIPT_TRUE@am__append_12 = ipsec _copyright
-@USE_PLUTO_TRUE@am__append_13 = pluto whack
+@USE_LIBIPSEC_TRUE@am__append_3 = libipsec
+@USE_SIMAKA_TRUE@am__append_4 = libsimaka
+@USE_TLS_TRUE@am__append_5 = libtls
+@USE_RADIUS_TRUE@am__append_6 = libradius
+@USE_LIBTNCIF_TRUE@am__append_7 = libtncif
+@USE_LIBTNCCS_TRUE@am__append_8 = libtnccs
+@USE_IMCV_TRUE@am__append_9 = libimcv
+@USE_PTS_TRUE@am__append_10 = libpts
+@USE_LIBCHARON_TRUE@am__append_11 = libcharon
+@USE_FILE_CONFIG_TRUE@am__append_12 = starter
+@USE_IPSEC_SCRIPT_TRUE@am__append_13 = ipsec _copyright
@USE_CHARON_TRUE@am__append_14 = charon
-@USE_STROKE_TRUE@am__append_15 = stroke
-@USE_UPDOWN_TRUE@am__append_16 = _updown _updown_espmark
-@USE_TOOLS_TRUE@am__append_17 = libfreeswan openac scepclient pki
-@USE_CONFTEST_TRUE@am__append_18 = conftest
-@USE_DUMM_TRUE@am__append_19 = dumm
-@USE_FAST_TRUE@am__append_20 = libfast
-@USE_MANAGER_TRUE@am__append_21 = manager
-@USE_MEDSRV_TRUE@am__append_22 = medsrv
-@USE_INTEGRITY_TEST_TRUE@am__append_23 = checksum
+@USE_NM_TRUE@am__append_15 = charon-nm
+@USE_STROKE_TRUE@am__append_16 = stroke
+@USE_UPDOWN_TRUE@am__append_17 = _updown _updown_espmark
+@USE_TOOLS_TRUE@am__append_18 = openac scepclient pki
+@USE_CONFTEST_TRUE@am__append_19 = conftest
+@USE_DUMM_TRUE@am__append_20 = dumm
+@USE_FAST_TRUE@am__append_21 = libfast
+@USE_MANAGER_TRUE@am__append_22 = manager
+@USE_MEDSRV_TRUE@am__append_23 = medsrv
+@USE_INTEGRITY_TEST_TRUE@am__append_24 = checksum
subdir = src
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -71,6 +72,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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 =
SOURCES =
@@ -89,11 +91,11 @@ AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
distdir
ETAGS = etags
CTAGS = ctags
-DIST_SUBDIRS = . include libstrongswan libhydra libsimaka libtls \
- libradius libtncif libtnccs libimcv libpts libcharon \
- libfreeswan starter ipsec _copyright pluto whack charon stroke \
- _updown _updown_espmark openac scepclient pki conftest dumm \
- libfast manager medsrv checksum
+DIST_SUBDIRS = . include libstrongswan libhydra libipsec libsimaka \
+ libtls libradius libtncif libtnccs libimcv libpts libcharon \
+ starter ipsec _copyright charon charon-nm stroke _updown \
+ _updown_espmark openac scepclient pki conftest dumm libfast \
+ manager medsrv checksum
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
am__relativize = \
dir0=`pwd`; \
@@ -128,6 +130,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -222,11 +225,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -243,11 +249,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -263,6 +270,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -272,7 +280,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -307,7 +314,7 @@ SUBDIRS = . include $(am__append_1) $(am__append_2) $(am__append_3) \
$(am__append_13) $(am__append_14) $(am__append_15) \
$(am__append_16) $(am__append_17) $(am__append_18) \
$(am__append_19) $(am__append_20) $(am__append_21) \
- $(am__append_22) $(am__append_23)
+ $(am__append_22) $(am__append_23) $(am__append_24)
EXTRA_DIST = strongswan.conf
all: all-recursive
diff --git a/src/_copyright/Makefile.am b/src/_copyright/Makefile.am
index 405e08b3d..915b57421 100644
--- a/src/_copyright/Makefile.am
+++ b/src/_copyright/Makefile.am
@@ -2,7 +2,6 @@ ipsec_PROGRAMS = _copyright
_copyright_SOURCES = _copyright.c
INCLUDES = \
--I$(top_srcdir)/src/libfreeswan \
-I$(top_srcdir)/src/libstrongswan
-_copyright_LDADD = $(top_builddir)/src/libfreeswan/libfreeswan.a $(top_builddir)/src/libstrongswan/libstrongswan.la
+_copyright_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
diff --git a/src/_copyright/Makefile.in b/src/_copyright/Makefile.in
index ae15d3cde..c4477f303 100644
--- a/src/_copyright/Makefile.in
+++ b/src/_copyright/Makefile.in
@@ -50,6 +50,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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__installdirs = "$(DESTDIR)$(ipsecdir)"
@@ -57,9 +58,8 @@ PROGRAMS = $(ipsec_PROGRAMS)
am__copyright_OBJECTS = _copyright.$(OBJEXT)
_copyright_OBJECTS = $(am__copyright_OBJECTS)
_copyright_DEPENDENCIES = \
- $(top_builddir)/src/libfreeswan/libfreeswan.a \
$(top_builddir)/src/libstrongswan/libstrongswan.la
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -85,6 +85,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -179,11 +180,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -200,11 +204,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -220,6 +225,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -229,7 +235,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -259,10 +264,9 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
_copyright_SOURCES = _copyright.c
INCLUDES = \
--I$(top_srcdir)/src/libfreeswan \
-I$(top_srcdir)/src/libstrongswan
-_copyright_LDADD = $(top_builddir)/src/libfreeswan/libfreeswan.a $(top_builddir)/src/libstrongswan/libstrongswan.la
+_copyright_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
all: all-am
.SUFFIXES:
diff --git a/src/_copyright/_copyright.c b/src/_copyright/_copyright.c
index 072998345..b20b17256 100644
--- a/src/_copyright/_copyright.c
+++ b/src/_copyright/_copyright.c
@@ -21,9 +21,41 @@
#include <unistd.h>
#include <getopt.h>
-#include <freeswan.h>
#include <library.h>
+static const char *copyright[] = {
+ "Copyright (C) 1999-2012",
+ " Henry Spencer, D. Hugh Redelmeier, Michael Richardson, Ken Bantoft,",
+ " Stephen J. Bevan, JuanJo Ciarlante, Thomas Egerer, Heiko Hund,",
+ " Mathieu Lafon, Stephane Laroche, Kai Martius, Stephan Scholz,",
+ " Tuomo Soini, Herbert Xu.",
+ "",
+ " Martin Berner, Marco Bertossa, David Buechi, Ueli Galizzi,",
+ " Christoph Gysin, Andreas Hess, Patric Lichtsteiner, Michael Meier,",
+ " Andreas Schleiss, Ariane Seiler, Mario Strasser, Lukas Suter,",
+ " Roger Wegmann, Simon Zwahlen,",
+ " ZHW Zuercher Hochschule Winterthur (Switzerland).",
+ "",
+ " Philip Boetschi, Tobias Brunner, Sansar Choinyambuu, Adrian Doerig,",
+ " Andreas Eigenmann, Giuliano Grassi, Reto Guadagnini, Fabian Hartmann,",
+ " Noah Heusser, Jan Hutter, Thomas Kallenberg, Daniel Roethlisberger,",
+ " Ralf Sager, Joel Stillhart, Daniel Wydler, Andreas Steffen,",
+ " HSR Hochschule fuer Technik Rapperswil (Switzerland).",
+ "",
+ " Martin Willi (revosec AG), Clavister (Sweden).",
+ "",
+ "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 (file COPYING in the distribution) for more details.",
+ NULL,
+};
+
char usage[] = "Usage: ipsec _copyright";
struct option opts[] = {
{"help", 0, NULL, 'h',},
@@ -39,7 +71,7 @@ main(int argc, char *argv[])
int opt;
extern int optind;
int errflg = 0;
- const char **notice = ipsec_copyright_notice();
+ const char **notice = copyright;
const char **co;
library_init(NULL);
diff --git a/src/_updown/Makefile.in b/src/_updown/Makefile.in
index a406d79ac..672285ad0 100644
--- a/src/_updown/Makefile.in
+++ b/src/_updown/Makefile.in
@@ -50,6 +50,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -89,6 +90,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -183,11 +185,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -204,11 +209,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -224,6 +230,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -233,7 +240,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/_updown/_updown.in b/src/_updown/_updown.in
index 2c742c010..3a40e2110 100644
--- a/src/_updown/_updown.in
+++ b/src/_updown/_updown.in
@@ -73,8 +73,12 @@
# just the host, this will be 255.255.255.255.
#
# PLUTO_MY_SOURCEIP
-# if non-empty, then the source address for the route will be
-# set to this IP address.
+# PLUTO_MY_SOURCEIP4_$i
+# 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
+# virtual IP, IPv4 or IPv6.
#
# PLUTO_MY_PROTOCOL
# is the IP protocol that will be transported.
@@ -128,6 +132,12 @@
# contains the remote UDP port in the case of ESP_IN_UDP
# encapsulation
#
+# PLUTO_DNS4_$i
+# PLUTO_DNS6_$i
+# contains IPv4/IPv6 DNS server attribute received from a
+# responder, $i enumerates from 1 to the number of servers per
+# address family.
+#
# define a minimum PATH environment in case it is not set
PATH="/sbin:/bin:/usr/sbin:/usr/bin:@sbindir@"
diff --git a/src/_updown_espmark/Makefile.in b/src/_updown_espmark/Makefile.in
index 3ae236a90..b62ceba2b 100644
--- a/src/_updown_espmark/Makefile.in
+++ b/src/_updown_espmark/Makefile.in
@@ -50,6 +50,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -89,6 +90,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -183,11 +185,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -204,11 +209,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -224,6 +230,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -233,7 +240,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/charon-nm/Makefile.am b/src/charon-nm/Makefile.am
new file mode 100644
index 000000000..80fc13ba1
--- /dev/null
+++ b/src/charon-nm/Makefile.am
@@ -0,0 +1,26 @@
+ipsec_PROGRAMS = charon-nm
+
+charon_nm_SOURCES = \
+charon-nm.c \
+nm/nm_backend.c nm/nm_backend.h \
+nm/nm_creds.c nm/nm_creds.h \
+nm/nm_handler.c nm/nm_handler.h \
+nm/nm_service.c nm/nm_service.h
+
+INCLUDES = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon \
+ ${nm_CFLAGS}
+
+AM_CFLAGS = \
+ -DIPSEC_DIR=\"${ipsecdir}\" \
+ -DIPSEC_PIDDIR=\"${piddir}\" \
+ -DNM_CA_DIR=\"${nm_ca_dir}\" \
+ -DPLUGINS=\""${nm_plugins}\""
+
+charon_nm_LDADD = \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la \
+ $(top_builddir)/src/libhydra/libhydra.la \
+ $(top_builddir)/src/libcharon/libcharon.la \
+ -lm $(PTHREADLIB) $(DLLIB) ${nm_LIBS}
diff --git a/src/charon-nm/Makefile.in b/src/charon-nm/Makefile.in
new file mode 100644
index 000000000..be72892e9
--- /dev/null
+++ b/src/charon-nm/Makefile.in
@@ -0,0 +1,676 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+ipsec_PROGRAMS = charon-nm$(EXEEXT)
+subdir = src/charon-nm
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
+ $(top_srcdir)/m4/config/ltoptions.m4 \
+ $(top_srcdir)/m4/config/ltsugar.m4 \
+ $(top_srcdir)/m4/config/ltversion.m4 \
+ $(top_srcdir)/m4/config/lt~obsolete.m4 \
+ $(top_srcdir)/m4/macros/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/m4/macros/add-plugin.m4 \
+ $(top_srcdir)/configure.in
+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__installdirs = "$(DESTDIR)$(ipsecdir)"
+PROGRAMS = $(ipsec_PROGRAMS)
+am_charon_nm_OBJECTS = charon-nm.$(OBJEXT) nm_backend.$(OBJEXT) \
+ nm_creds.$(OBJEXT) nm_handler.$(OBJEXT) nm_service.$(OBJEXT)
+charon_nm_OBJECTS = $(am_charon_nm_OBJECTS)
+am__DEPENDENCIES_1 =
+charon_nm_DEPENDENCIES = \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la \
+ $(top_builddir)/src/libhydra/libhydra.la \
+ $(top_builddir)/src/libcharon/libcharon.la \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(charon_nm_SOURCES)
+DIST_SOURCES = $(charon_nm_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BFDLIB = @BFDLIB@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+attest_plugins = @attest_plugins@
+axis2c_CFLAGS = @axis2c_CFLAGS@
+axis2c_LIBS = @axis2c_LIBS@
+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@
+datadir = @datadir@
+datarootdir = @datarootdir@
+dbusservicedir = @dbusservicedir@
+dev_headers = @dev_headers@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+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@
+libdir = @libdir@
+libexecdir = @libexecdir@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+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@
+openac_plugins = @openac_plugins@
+p_plugins = @p_plugins@
+pcsclite_CFLAGS = @pcsclite_CFLAGS@
+pcsclite_LIBS = @pcsclite_LIBS@
+pdfdir = @pdfdir@
+piddir = @piddir@
+pki_plugins = @pki_plugins@
+plugindir = @plugindir@
+pool_plugins = @pool_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+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@
+sysconfdir = @sysconfdir@
+systemdsystemunitdir = @systemdsystemunitdir@
+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@
+charon_nm_SOURCES = \
+charon-nm.c \
+nm/nm_backend.c nm/nm_backend.h \
+nm/nm_creds.c nm/nm_creds.h \
+nm/nm_handler.c nm/nm_handler.h \
+nm/nm_service.c nm/nm_service.h
+
+INCLUDES = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon \
+ ${nm_CFLAGS}
+
+AM_CFLAGS = \
+ -DIPSEC_DIR=\"${ipsecdir}\" \
+ -DIPSEC_PIDDIR=\"${piddir}\" \
+ -DNM_CA_DIR=\"${nm_ca_dir}\" \
+ -DPLUGINS=\""${nm_plugins}\""
+
+charon_nm_LDADD = \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la \
+ $(top_builddir)/src/libhydra/libhydra.la \
+ $(top_builddir)/src/libcharon/libcharon.la \
+ -lm $(PTHREADLIB) $(DLLIB) ${nm_LIBS}
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/charon-nm/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/charon-nm/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-ipsecPROGRAMS: $(ipsec_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(ipsecdir)" || $(MKDIR_P) "$(DESTDIR)$(ipsecdir)"
+ @list='$(ipsec_PROGRAMS)'; test -n "$(ipsecdir)" || list=; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p || test -f $$p1; \
+ then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(ipsecdir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(ipsecdir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-ipsecPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(ipsec_PROGRAMS)'; test -n "$(ipsecdir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(ipsecdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(ipsecdir)" && rm -f $$files
+
+clean-ipsecPROGRAMS:
+ @list='$(ipsec_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
+charon-nm$(EXEEXT): $(charon_nm_OBJECTS) $(charon_nm_DEPENDENCIES)
+ @rm -f charon-nm$(EXEEXT)
+ $(LINK) $(charon_nm_OBJECTS) $(charon_nm_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/charon-nm.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm_backend.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm_creds.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm_handler.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm_service.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+nm_backend.o: nm/nm_backend.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm_backend.o -MD -MP -MF $(DEPDIR)/nm_backend.Tpo -c -o nm_backend.o `test -f 'nm/nm_backend.c' || echo '$(srcdir)/'`nm/nm_backend.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/nm_backend.Tpo $(DEPDIR)/nm_backend.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm/nm_backend.c' object='nm_backend.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm_backend.o `test -f 'nm/nm_backend.c' || echo '$(srcdir)/'`nm/nm_backend.c
+
+nm_backend.obj: nm/nm_backend.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm_backend.obj -MD -MP -MF $(DEPDIR)/nm_backend.Tpo -c -o nm_backend.obj `if test -f 'nm/nm_backend.c'; then $(CYGPATH_W) 'nm/nm_backend.c'; else $(CYGPATH_W) '$(srcdir)/nm/nm_backend.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/nm_backend.Tpo $(DEPDIR)/nm_backend.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm/nm_backend.c' object='nm_backend.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm_backend.obj `if test -f 'nm/nm_backend.c'; then $(CYGPATH_W) 'nm/nm_backend.c'; else $(CYGPATH_W) '$(srcdir)/nm/nm_backend.c'; fi`
+
+nm_creds.o: nm/nm_creds.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm_creds.o -MD -MP -MF $(DEPDIR)/nm_creds.Tpo -c -o nm_creds.o `test -f 'nm/nm_creds.c' || echo '$(srcdir)/'`nm/nm_creds.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/nm_creds.Tpo $(DEPDIR)/nm_creds.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm/nm_creds.c' object='nm_creds.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm_creds.o `test -f 'nm/nm_creds.c' || echo '$(srcdir)/'`nm/nm_creds.c
+
+nm_creds.obj: nm/nm_creds.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm_creds.obj -MD -MP -MF $(DEPDIR)/nm_creds.Tpo -c -o nm_creds.obj `if test -f 'nm/nm_creds.c'; then $(CYGPATH_W) 'nm/nm_creds.c'; else $(CYGPATH_W) '$(srcdir)/nm/nm_creds.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/nm_creds.Tpo $(DEPDIR)/nm_creds.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm/nm_creds.c' object='nm_creds.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm_creds.obj `if test -f 'nm/nm_creds.c'; then $(CYGPATH_W) 'nm/nm_creds.c'; else $(CYGPATH_W) '$(srcdir)/nm/nm_creds.c'; fi`
+
+nm_handler.o: nm/nm_handler.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm_handler.o -MD -MP -MF $(DEPDIR)/nm_handler.Tpo -c -o nm_handler.o `test -f 'nm/nm_handler.c' || echo '$(srcdir)/'`nm/nm_handler.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/nm_handler.Tpo $(DEPDIR)/nm_handler.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm/nm_handler.c' object='nm_handler.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm_handler.o `test -f 'nm/nm_handler.c' || echo '$(srcdir)/'`nm/nm_handler.c
+
+nm_handler.obj: nm/nm_handler.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm_handler.obj -MD -MP -MF $(DEPDIR)/nm_handler.Tpo -c -o nm_handler.obj `if test -f 'nm/nm_handler.c'; then $(CYGPATH_W) 'nm/nm_handler.c'; else $(CYGPATH_W) '$(srcdir)/nm/nm_handler.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/nm_handler.Tpo $(DEPDIR)/nm_handler.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm/nm_handler.c' object='nm_handler.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm_handler.obj `if test -f 'nm/nm_handler.c'; then $(CYGPATH_W) 'nm/nm_handler.c'; else $(CYGPATH_W) '$(srcdir)/nm/nm_handler.c'; fi`
+
+nm_service.o: nm/nm_service.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm_service.o -MD -MP -MF $(DEPDIR)/nm_service.Tpo -c -o nm_service.o `test -f 'nm/nm_service.c' || echo '$(srcdir)/'`nm/nm_service.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/nm_service.Tpo $(DEPDIR)/nm_service.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm/nm_service.c' object='nm_service.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm_service.o `test -f 'nm/nm_service.c' || echo '$(srcdir)/'`nm/nm_service.c
+
+nm_service.obj: nm/nm_service.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm_service.obj -MD -MP -MF $(DEPDIR)/nm_service.Tpo -c -o nm_service.obj `if test -f 'nm/nm_service.c'; then $(CYGPATH_W) 'nm/nm_service.c'; else $(CYGPATH_W) '$(srcdir)/nm/nm_service.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/nm_service.Tpo $(DEPDIR)/nm_service.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm/nm_service.c' object='nm_service.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm_service.obj `if test -f 'nm/nm_service.c'; then $(CYGPATH_W) 'nm/nm_service.c'; else $(CYGPATH_W) '$(srcdir)/nm/nm_service.c'; fi`
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+ for dir in "$(DESTDIR)$(ipsecdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-ipsecPROGRAMS 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-ipsecPROGRAMS
+
+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-ipsecPROGRAMS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-ipsecPROGRAMS clean-libtool ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am \
+ install-ipsecPROGRAMS 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 uninstall uninstall-am uninstall-ipsecPROGRAMS
+
+
+# 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/charon-nm/charon-nm.c b/src/charon-nm/charon-nm.c
new file mode 100644
index 000000000..35e906778
--- /dev/null
+++ b/src/charon-nm/charon-nm.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2012 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 <stdio.h>
+#include <syslog.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <hydra.h>
+#include <daemon.h>
+
+#include <library.h>
+#include <utils/backtrace.h>
+#include <threading/thread.h>
+
+#include <nm/nm_backend.h>
+
+/**
+ * Hook in library for debugging messages
+ */
+extern void (*dbg) (debug_t group, level_t level, char *fmt, ...);
+
+/**
+ * Simple logging hook for library logs, using syslog output
+ */
+static void dbg_syslog(debug_t group, level_t level, char *fmt, ...)
+{
+ if (level <= 1)
+ {
+ char buffer[8192], groupstr[4];
+ va_list args;
+
+ va_start(args, fmt);
+ /* write in memory buffer first */
+ vsnprintf(buffer, sizeof(buffer), fmt, args);
+ /* cache group name */
+ snprintf(groupstr, sizeof(groupstr), "%N", debug_names, group);
+ syslog(LOG_DAEMON|LOG_INFO, "00[%s] %s", groupstr, buffer);
+ va_end(args);
+ }
+}
+
+/**
+ * Run the daemon and handle unix signals
+ */
+static void run()
+{
+ sigset_t set;
+
+ /* handle SIGINT and SIGTERM in this handler */
+ sigemptyset(&set);
+ sigaddset(&set, SIGINT);
+ sigaddset(&set, SIGTERM);
+ sigprocmask(SIG_BLOCK, &set, NULL);
+
+ while (TRUE)
+ {
+ int sig;
+ int error;
+
+ error = sigwait(&set, &sig);
+ if (error)
+ {
+ DBG1(DBG_DMN, "error %d while waiting for a signal", error);
+ return;
+ }
+ switch (sig)
+ {
+ case SIGINT:
+ {
+ DBG1(DBG_DMN, "signal of type SIGINT received. Shutting down");
+ charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig);
+ return;
+ }
+ case SIGTERM:
+ {
+ DBG1(DBG_DMN, "signal of type SIGTERM received. Shutting down");
+ charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig);
+ return;
+ }
+ default:
+ {
+ DBG1(DBG_DMN, "unknown signal %d received. Ignored", sig);
+ break;
+ }
+ }
+ }
+}
+
+/**
+ * Handle SIGSEGV/SIGILL signals raised by threads
+ */
+static void segv_handler(int signal)
+{
+ backtrace_t *backtrace;
+
+ DBG1(DBG_DMN, "thread %u received %d", thread_current_id(), signal);
+ backtrace = backtrace_create(2);
+ backtrace->log(backtrace, stderr, TRUE);
+ backtrace->destroy(backtrace);
+
+ DBG1(DBG_DMN, "killing ourself, received critical signal");
+ abort();
+}
+
+/**
+ * Initialize logging to syslog
+ */
+static void initialize_logger()
+{
+ sys_logger_t *sys_logger;
+ debug_t group;
+ level_t def;
+
+ sys_logger = sys_logger_create(LOG_DAEMON, FALSE);
+ def = lib->settings->get_int(lib->settings,
+ "charon-nm.syslog.default", 1);
+ for (group = 0; group < DBG_MAX; group++)
+ {
+ sys_logger->set_level(sys_logger, group,
+ lib->settings->get_int(lib->settings, "charon-nm.syslog.%N", def,
+ debug_lower_names, group));
+ }
+ charon->sys_loggers->insert_last(charon->sys_loggers, sys_logger);
+ charon->bus->add_logger(charon->bus, &sys_logger->logger);
+}
+
+/**
+ * Lookup UID and GID
+ */
+static bool lookup_uid_gid()
+{
+#ifdef IPSEC_USER
+ if (!charon->caps->resolve_uid(charon->caps, IPSEC_USER))
+ {
+ return FALSE;
+ }
+#endif
+#ifdef IPSEC_GROUP
+ if (!charon->caps->resolve_gid(charon->caps, IPSEC_GROUP))
+ {
+ return FALSE;
+ }
+#endif
+ return TRUE;
+}
+
+/**
+ * Main function, starts NetworkManager backend.
+ */
+int main(int argc, char *argv[])
+{
+ struct sigaction action;
+ int status = SS_RC_INITIALIZATION_FAILED;
+
+ /* logging for library during initialization, as we have no bus yet */
+ dbg = dbg_syslog;
+
+ /* initialize library */
+ if (!library_init(NULL))
+ {
+ library_deinit();
+ exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
+ }
+
+ if (lib->integrity &&
+ !lib->integrity->check_file(lib->integrity, "charon-nm", argv[0]))
+ {
+ dbg_syslog(DBG_DMN, 1, "integrity check of charon-nm failed");
+ library_deinit();
+ exit(SS_RC_DAEMON_INTEGRITY);
+ }
+
+ if (!libhydra_init("charon-nm"))
+ {
+ dbg_syslog(DBG_DMN, 1, "initialization failed - aborting charon-nm");
+ libhydra_deinit();
+ library_deinit();
+ exit(SS_RC_INITIALIZATION_FAILED);
+ }
+
+ if (!libcharon_init("charon-nm"))
+ {
+ dbg_syslog(DBG_DMN, 1, "initialization failed - aborting charon-nm");
+ goto deinit;
+ }
+
+ if (!lookup_uid_gid())
+ {
+ dbg_syslog(DBG_DMN, 1, "invalid uid/gid - aborting charon-nm");
+ goto deinit;
+ }
+
+ initialize_logger();
+
+ /* use random ports to avoid conflicts with regular charon */
+ lib->settings->set_int(lib->settings, "charon-nm.port", 0);
+ lib->settings->set_int(lib->settings, "charon-nm.port_natt_t", 0);
+
+ DBG1(DBG_DMN, "Starting charon NetworkManager backend (strongSwan "VERSION")");
+ if (lib->integrity)
+ {
+ DBG1(DBG_DMN, "integrity tests enabled:");
+ DBG1(DBG_DMN, "lib 'libstrongswan': passed file and segment integrity tests");
+ DBG1(DBG_DMN, "lib 'libhydra': passed file and segment integrity tests");
+ DBG1(DBG_DMN, "lib 'libcharon': passed file and segment integrity tests");
+ DBG1(DBG_DMN, "daemon 'charon-nm': passed file integrity test");
+ }
+
+ /* register NM backend to be loaded with plugins */
+ nm_backend_register();
+
+ /* initialize daemon */
+ if (!charon->initialize(charon,
+ lib->settings->get_str(lib->settings, "charon-nm.load", PLUGINS)))
+ {
+ DBG1(DBG_DMN, "initialization failed - aborting charon-nm");
+ goto deinit;
+ }
+
+ if (!charon->caps->drop(charon->caps))
+ {
+ DBG1(DBG_DMN, "capability dropping failed - aborting charon-nm");
+ goto deinit;
+ }
+
+ /* add handler for SEGV and ILL,
+ * INT and TERM are handled by sigwait() in run() */
+ action.sa_handler = segv_handler;
+ action.sa_flags = 0;
+ sigemptyset(&action.sa_mask);
+ sigaddset(&action.sa_mask, SIGINT);
+ sigaddset(&action.sa_mask, SIGTERM);
+ sigaction(SIGSEGV, &action, NULL);
+ sigaction(SIGILL, &action, NULL);
+ sigaction(SIGBUS, &action, NULL);
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &action, NULL);
+
+ pthread_sigmask(SIG_SETMASK, &action.sa_mask, NULL);
+
+ /* start daemon (i.e. the threads in the thread-pool) */
+ charon->start(charon);
+
+ /* main thread goes to run loop */
+ run();
+
+ status = 0;
+
+deinit:
+ libcharon_deinit();
+ libhydra_deinit();
+ library_deinit();
+ return status;
+}
+
diff --git a/src/libcharon/plugins/nm/nm_plugin.c b/src/charon-nm/nm/nm_backend.c
index 84b7c810a..f36cf1f68 100644
--- a/src/libcharon/plugins/nm/nm_plugin.c
+++ b/src/charon-nm/nm/nm_backend.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2008-2009 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -13,7 +14,6 @@
* for more details.
*/
-#include "nm_plugin.h"
#include "nm_service.h"
#include "nm_creds.h"
#include "nm_handler.h"
@@ -22,19 +22,16 @@
#include <daemon.h>
#include <processing/jobs/callback_job.h>
+#ifndef CAP_DAC_OVERRIDE
#define CAP_DAC_OVERRIDE 1
+#endif
-typedef struct private_nm_plugin_t private_nm_plugin_t;
+typedef struct nm_backend_t nm_backend_t;
/**
- * private data of nm plugin
+ * Data for the NetworkManager backend.
*/
-struct private_nm_plugin_t {
-
- /**
- * implements plugin interface
- */
- nm_plugin_t public;
+struct nm_backend_t {
/**
* NetworkManager service (VPNPlugin)
@@ -58,23 +55,24 @@ struct private_nm_plugin_t {
};
/**
+ * Global (but private) instance of the NM backend.
+ */
+static nm_backend_t *nm_backend = NULL;
+
+/**
* NM plugin processing routine, creates and handles NMVPNPlugin
*/
-static job_requeue_t run(private_nm_plugin_t *this)
+static job_requeue_t run(nm_backend_t *this)
{
this->loop = g_main_loop_new(NULL, FALSE);
g_main_loop_run(this->loop);
return JOB_REQUEUE_NONE;
}
-METHOD(plugin_t, get_name, char*,
- private_nm_plugin_t *this)
-{
- return "nm";
-}
-
-METHOD(plugin_t, destroy, void,
- private_nm_plugin_t *this)
+/**
+ * Cancel the GLib Main Event Loop
+ */
+static bool cancel(nm_backend_t *this)
{
if (this->loop)
{
@@ -84,6 +82,20 @@ METHOD(plugin_t, destroy, void,
}
g_main_loop_unref(this->loop);
}
+ return TRUE;
+}
+
+/**
+ * Deinitialize NetworkManager backend
+ */
+static void nm_backend_deinit()
+{
+ nm_backend_t *this = nm_backend;
+
+ if (!this)
+ {
+ return;
+ }
if (this->plugin)
{
g_object_unref(this->plugin);
@@ -93,14 +105,16 @@ METHOD(plugin_t, destroy, void,
this->creds->destroy(this->creds);
this->handler->destroy(this->handler);
free(this);
+
+ nm_backend = NULL;
}
-/*
- * see header file
+/**
+ * Initialize NetworkManager backend
*/
-plugin_t *nm_plugin_create()
+static bool nm_backend_init()
{
- private_nm_plugin_t *this;
+ nm_backend_t *this;
g_type_init ();
if (!g_thread_supported())
@@ -109,34 +123,54 @@ plugin_t *nm_plugin_create()
}
INIT(this,
- .public = {
- .plugin = {
- .get_name = _get_name,
- .reload = (void*)return_false,
- .destroy = _destroy,
- },
- },
.creds = nm_creds_create(),
.handler = nm_handler_create(),
);
this->plugin = nm_strongswan_plugin_new(this->creds, this->handler);
+ nm_backend = this;
hydra->attributes->add_handler(hydra->attributes, &this->handler->handler);
lib->credmgr->add_set(lib->credmgr, &this->creds->set);
if (!this->plugin)
{
DBG1(DBG_CFG, "DBUS binding failed");
- destroy(this);
- return NULL;
+ nm_backend_deinit();
+ return FALSE;
}
/* bypass file permissions to read from users ssh-agent */
- charon->keep_cap(charon, CAP_DAC_OVERRIDE);
+ charon->caps->keep(charon->caps, CAP_DAC_OVERRIDE);
lib->processor->queue_job(lib->processor,
- (job_t*)callback_job_create_with_prio((callback_job_cb_t)run,
- this, NULL, NULL, JOB_PRIO_CRITICAL));
+ (job_t*)callback_job_create_with_prio((callback_job_cb_t)run, this,
+ NULL, (callback_job_cancel_t)cancel, JOB_PRIO_CRITICAL));
+ return TRUE;
+}
- return &this->public.plugin;
+/**
+ * Initialize/deinitialize NetworkManager backend
+ */
+static bool nm_backend_cb(void *plugin,
+ plugin_feature_t *feature, bool reg, void *data)
+{
+ if (reg)
+ {
+ return nm_backend_init();
+ }
+ nm_backend_deinit();
+ return TRUE;
}
+/*
+ * see header file
+ */
+void nm_backend_register()
+{
+ static plugin_feature_t features[] = {
+ PLUGIN_CALLBACK((plugin_feature_callback_t)nm_backend_cb, NULL),
+ PLUGIN_PROVIDE(CUSTOM, "NetworkManager backend"),
+ PLUGIN_DEPENDS(CUSTOM, "libcharon"),
+ };
+ lib->plugins->add_static_features(lib->plugins, "nm-backend", features,
+ countof(features), TRUE);
+}
diff --git a/src/libcharon/plugins/nm/nm_plugin.h b/src/charon-nm/nm/nm_backend.h
index b64b3edf6..89dc536f6 100644
--- a/src/libcharon/plugins/nm/nm_plugin.h
+++ b/src/charon-nm/nm/nm_backend.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Martin Willi
+ * Copyright (C) 2012 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -14,29 +14,23 @@
*/
/**
+ * @defgroup charon-nm charon-nm
+ *
* @defgroup nm nm
- * @ingroup cplugins
+ * @ingroup charon-nm
*
- * @defgroup nm_plugin nm_plugin
+ * @defgroup nm_backend nm_backend
* @{ @ingroup nm
*/
-#ifndef NM_PLUGIN_H_
-#define NM_PLUGIN_H_
-
-#include <plugins/plugin.h>
-
-typedef struct nm_plugin_t nm_plugin_t;
+#ifndef NM_BACKEND_H_
+#define NM_BACKEND_H_
/**
- * NetworkManager integration plugin.
+ * Initialize the NetworkManager backend.
+ *
+ * @return TRUE, if initialization was successful
*/
-struct nm_plugin_t {
-
- /**
- * implements plugin interface
- */
- plugin_t plugin;
-};
+void nm_backend_register();
-#endif /** NM_PLUGIN_H_ @}*/
+#endif /** NM_BACKEND_H_ @}*/
diff --git a/src/libcharon/plugins/nm/nm_creds.c b/src/charon-nm/nm/nm_creds.c
index f8fae9504..f8fae9504 100644
--- a/src/libcharon/plugins/nm/nm_creds.c
+++ b/src/charon-nm/nm/nm_creds.c
diff --git a/src/libcharon/plugins/nm/nm_creds.h b/src/charon-nm/nm/nm_creds.h
index 91f645c7e..91f645c7e 100644
--- a/src/libcharon/plugins/nm/nm_creds.h
+++ b/src/charon-nm/nm/nm_creds.h
diff --git a/src/libcharon/plugins/nm/nm_handler.c b/src/charon-nm/nm/nm_handler.c
index 408129ebe..28aa04b31 100644
--- a/src/libcharon/plugins/nm/nm_handler.c
+++ b/src/charon-nm/nm/nm_handler.c
@@ -92,15 +92,17 @@ static bool enumerate_dns(enumerator_t *this,
}
METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*,
- private_nm_handler_t *this, identification_t *server, host_t *vip)
+ private_nm_handler_t *this, identification_t *server, linked_list_t *vips)
{
- if (vip && vip->get_family(vip) == AF_INET)
- { /* no IPv6 attributes yet */
- enumerator_t *enumerator = malloc_thing(enumerator_t);
- /* enumerate DNS attribute first ... */
- enumerator->enumerate = (void*)enumerate_dns;
- enumerator->destroy = (void*)free;
+ if (vips->get_count(vips))
+ {
+ enumerator_t *enumerator;
+ INIT(enumerator,
+ /* enumerate DNS attribute first ... */
+ .enumerate = (void*)enumerate_dns,
+ .destroy = (void*)free,
+ );
return enumerator;
}
return enumerator_create_empty();
diff --git a/src/libcharon/plugins/nm/nm_handler.h b/src/charon-nm/nm/nm_handler.h
index bb35ce767..bb35ce767 100644
--- a/src/libcharon/plugins/nm/nm_handler.h
+++ b/src/charon-nm/nm/nm_handler.h
diff --git a/src/libcharon/plugins/nm/nm_service.c b/src/charon-nm/nm/nm_service.c
index a6783fcc3..b7155b44b 100644
--- a/src/libcharon/plugins/nm/nm_service.c
+++ b/src/charon-nm/nm/nm_service.c
@@ -89,11 +89,12 @@ static void signal_ipv4_config(NMVPNPlugin *plugin,
me = ike_sa->get_my_host(ike_sa);
handler = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin)->handler;
- /* NM requires a tundev, but netkey does not use one. Passing an invalid
- * iface makes NM complain, but it accepts it without fiddling on eth0. */
+ /* NM requires a tundev, but netkey does not use one. Passing the physical
+ * interface does not work, as NM fiddles around with it. Passing the
+ * loopback seems to work, though... */
val = g_slice_new0 (GValue);
g_value_init (val, G_TYPE_STRING);
- g_value_set_string (val, "none");
+ g_value_set_string (val, "lo");
g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_TUNDEV, val);
val = g_slice_new0(GValue);
@@ -276,7 +277,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
auth_class_t auth_class = AUTH_CLASS_EAP;
certificate_t *cert = NULL;
x509_t *x509;
- bool agent = FALSE, smartcard = FALSE;
+ bool agent = FALSE, smartcard = FALSE, loose_gateway_id = FALSE;
lifetime_cfg_t lifetime = {
.time = {
.life = 10800 /* 3h */,
@@ -379,6 +380,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
* included in the gateway certificate. */
gateway = identification_create_from_string((char*)address);
DBG1(DBG_CFG, "using CA certificate, gateway identity '%Y'", gateway);
+ loose_gateway_id = TRUE;
}
if (auth_class == AUTH_CLASS_EAP)
@@ -496,16 +498,21 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
/**
* Set up configurations
*/
- ike_cfg = ike_cfg_create(TRUE, encap,
- "0.0.0.0", IKEV2_UDP_PORT, (char*)address, IKEV2_UDP_PORT);
+ ike_cfg = ike_cfg_create(TRUE, encap, "0.0.0.0", FALSE,
+ charon->socket->get_port(charon->socket, FALSE),
+ (char*)address, FALSE, IKEV2_UDP_PORT);
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
- peer_cfg = peer_cfg_create(priv->name, 2, ike_cfg,
+ peer_cfg = peer_cfg_create(priv->name, IKEV2, ike_cfg,
CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */
36000, 0, /* rekey 10h, reauth none */
600, 600, /* jitter, over 10min */
- TRUE, 0, /* mobike, DPD */
- virtual ? host_create_from_string("0.0.0.0", 0) : NULL,
- NULL, FALSE, NULL, NULL); /* pool, mediation */
+ TRUE, FALSE, /* mobike, aggressive */
+ 0, 0, /* DPD delay, timeout */
+ FALSE, NULL, NULL); /* mediation */
+ if (virtual)
+ {
+ peer_cfg->add_virtual_ip(peer_cfg, host_create_from_string("0.0.0.0", 0));
+ }
auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, auth_class);
auth->add(auth, AUTH_RULE_IDENTITY, user);
@@ -513,6 +520,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
auth->add(auth, AUTH_RULE_IDENTITY, gateway);
+ auth->add(auth, AUTH_RULE_IDENTITY_LOOSE, loose_gateway_id);
peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
child_cfg = child_cfg_create(priv->name, &lifetime,
@@ -533,6 +541,13 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
*/
ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
peer_cfg);
+ if (!ike_sa)
+ {
+ peer_cfg->destroy(peer_cfg);
+ g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
+ "IKE version not supported.");
+ return FALSE;
+ }
if (!ike_sa->get_peer_cfg(ike_sa))
{
ike_sa->set_peer_cfg(ike_sa, peer_cfg);
@@ -550,6 +565,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
/**
* Initiate
*/
+ child_cfg->get_ref(child_cfg);
if (ike_sa->initiate(ike_sa, child_cfg, 0, NULL, NULL) != SUCCESS)
{
charon->bus->remove_listener(charon->bus, &priv->listener);
@@ -608,7 +624,7 @@ static gboolean need_secrets(NMVPNPlugin *plugin, NMConnection *connection,
}
}
}
- else if streq(method, "smartcard")
+ else if (streq(method, "smartcard"))
{
if (nm_setting_vpn_get_secret(settings, "password"))
{
@@ -660,7 +676,7 @@ static void nm_strongswan_plugin_init(NMStrongswanPlugin *plugin)
priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
priv->plugin = NM_VPN_PLUGIN(plugin);
- memset(&priv->listener.log, 0, sizeof(listener_t));
+ memset(&priv->listener, 0, sizeof(listener_t));
priv->listener.child_updown = child_updown;
priv->listener.ike_rekey = ike_rekey;
}
diff --git a/src/libcharon/plugins/nm/nm_service.h b/src/charon-nm/nm/nm_service.h
index 828d1a452..828d1a452 100644
--- a/src/libcharon/plugins/nm/nm_service.h
+++ b/src/charon-nm/nm/nm_service.h
diff --git a/src/charon/Android.mk b/src/charon/Android.mk
index eb7eca9dd..1dd27d534 100644
--- a/src/charon/Android.mk
+++ b/src/charon/Android.mk
@@ -13,7 +13,8 @@ LOCAL_C_INCLUDES += \
$(strongswan_PATH)/src/libcharon \
$(strongswan_PATH)/src/libstrongswan
-LOCAL_CFLAGS := $(strongswan_CFLAGS)
+LOCAL_CFLAGS := $(strongswan_CFLAGS) \
+ -DPLUGINS='"$(strongswan_CHARON_PLUGINS)"'
LOCAL_MODULE := charon
diff --git a/src/charon/Makefile.am b/src/charon/Makefile.am
index 6481947f1..0ca15cb10 100644
--- a/src/charon/Makefile.am
+++ b/src/charon/Makefile.am
@@ -3,6 +3,8 @@ ipsec_PROGRAMS = charon
charon_SOURCES = \
charon.c
+charon.o : $(top_builddir)/config.status
+
INCLUDES = \
-I$(top_srcdir)/src/libstrongswan \
-I$(top_srcdir)/src/libhydra \
@@ -10,7 +12,8 @@ INCLUDES = \
AM_CFLAGS = \
-DIPSEC_DIR=\"${ipsecdir}\" \
- -DIPSEC_PIDDIR=\"${piddir}\"
+ -DIPSEC_PIDDIR=\"${piddir}\" \
+ -DPLUGINS=\""${charon_plugins}\""
charon_LDADD = \
$(top_builddir)/src/libstrongswan/libstrongswan.la \
diff --git a/src/charon/Makefile.in b/src/charon/Makefile.in
index 5da167dfd..d8109bb7f 100644
--- a/src/charon/Makefile.in
+++ b/src/charon/Makefile.in
@@ -50,6 +50,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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__installdirs = "$(DESTDIR)$(ipsecdir)"
@@ -62,7 +63,7 @@ charon_DEPENDENCIES = \
$(top_builddir)/src/libhydra/libhydra.la \
$(top_builddir)/src/libcharon/libcharon.la \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -88,6 +89,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -182,11 +184,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -203,11 +208,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -223,6 +229,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -232,7 +239,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -270,7 +276,8 @@ INCLUDES = \
AM_CFLAGS = \
-DIPSEC_DIR=\"${ipsecdir}\" \
- -DIPSEC_PIDDIR=\"${piddir}\"
+ -DIPSEC_PIDDIR=\"${piddir}\" \
+ -DPLUGINS=\""${charon_plugins}\""
charon_LDADD = \
$(top_builddir)/src/libstrongswan/libstrongswan.la \
@@ -597,6 +604,8 @@ uninstall-am: uninstall-ipsecPROGRAMS
tags uninstall uninstall-am uninstall-ipsecPROGRAMS
+charon.o : $(top_builddir)/config.status
+
# 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/charon/charon.c b/src/charon/charon.c
index 6dbb0b592..bd36c72f4 100644
--- a/src/charon/charon.c
+++ b/src/charon/charon.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2010 Tobias Brunner
+ * Copyright (C) 2006-2012 Tobias Brunner
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005 Jan Hutter
@@ -17,21 +17,17 @@
*/
#include <stdio.h>
-#ifdef HAVE_PRCTL
-#include <sys/prctl.h>
-#endif
#define _POSIX_PTHREAD_SEMANTICS /* for two param sigwait on OpenSolaris */
#include <signal.h>
#undef _POSIX_PTHREAD_SEMANTICS
#include <pthread.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <sys/utsname.h>
#include <syslog.h>
#include <errno.h>
#include <unistd.h>
#include <getopt.h>
-#include <pwd.h>
-#include <grp.h>
#include <hydra.h>
#include <daemon.h>
@@ -143,67 +139,24 @@ static void run()
}
/**
- * drop daemon capabilities
- */
-static bool drop_capabilities()
-{
-#ifdef HAVE_PRCTL
- prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
-#endif
-
- if (setgid(charon->gid) != 0)
- {
- DBG1(DBG_DMN, "change to unprivileged group failed");
- return FALSE;
- }
- if (setuid(charon->uid) != 0)
- {
- DBG1(DBG_DMN, "change to unprivileged user failed");
- return FALSE;
- }
- if (!charon->drop_capabilities(charon))
- {
- DBG1(DBG_DMN, "unable to drop daemon capabilities");
- return FALSE;
- }
- return TRUE;
-}
-
-/**
* lookup UID and GID
*/
static bool lookup_uid_gid()
{
#ifdef IPSEC_USER
+ if (!charon->caps->resolve_uid(charon->caps, IPSEC_USER))
{
- char buf[1024];
- struct passwd passwd, *pwp;
-
- if (getpwnam_r(IPSEC_USER, &passwd, buf, sizeof(buf), &pwp) != 0 ||
- pwp == NULL)
- {
- DBG1(DBG_DMN, "resolving user '"IPSEC_USER"' failed");
- return FALSE;
- }
- charon->uid = pwp->pw_uid;
+ return FALSE;
}
#endif
#ifdef IPSEC_GROUP
+ if (!charon->caps->resolve_gid(charon->caps, IPSEC_GROUP))
{
- char buf[1024];
- struct group group, *grp;
-
- if (getgrnam_r(IPSEC_GROUP, &group, buf, sizeof(buf), &grp) != 0 ||
- grp == NULL)
- {
- DBG1(DBG_DMN, "resolving group '"IPSEC_GROUP"' failed");
- return FALSE;
- }
- charon->gid = grp->gr_gid;
+ return FALSE;
}
#endif
#ifdef ANDROID
- charon->uid = AID_VPN;
+ charon->caps->set_uid(charon->caps, AID_VPN);
#endif
return TRUE;
}
@@ -259,7 +212,9 @@ static bool check_pidfile()
pidfile = fopen(PID_FILE, "w");
if (pidfile)
{
- ignore_result(fchown(fileno(pidfile), charon->uid, charon->gid));
+ ignore_result(fchown(fileno(pidfile),
+ charon->caps->get_uid(charon->caps),
+ charon->caps->get_gid(charon->caps)));
fprintf(pidfile, "%d\n", getpid());
fflush(pidfile);
}
@@ -335,7 +290,7 @@ static void initialize_loggers(bool use_stderr, level_t levels[])
facility, debug_lower_names, group));
}
charon->sys_loggers->insert_last(charon->sys_loggers, sys_logger);
- charon->bus->add_listener(charon->bus, &sys_logger->listener);
+ charon->bus->add_logger(charon->bus, &sys_logger->logger);
}
enumerator->destroy(enumerator);
@@ -385,7 +340,7 @@ static void initialize_loggers(bool use_stderr, level_t levels[])
filename, debug_lower_names, group));
}
charon->file_loggers->insert_last(charon->file_loggers, file_logger);
- charon->bus->add_listener(charon->bus, &file_logger->listener);
+ charon->bus->add_logger(charon->bus, &file_logger->logger);
}
enumerator->destroy(enumerator);
@@ -395,11 +350,9 @@ static void initialize_loggers(bool use_stderr, level_t levels[])
{
/* set up default stdout file_logger */
file_logger = file_logger_create(stdout, NULL, FALSE);
- charon->bus->add_listener(charon->bus, &file_logger->listener);
charon->file_loggers->insert_last(charon->file_loggers, file_logger);
/* set up default daemon sys_logger */
sys_logger = sys_logger_create(LOG_DAEMON, FALSE);
- charon->bus->add_listener(charon->bus, &sys_logger->listener);
charon->sys_loggers->insert_last(charon->sys_loggers, sys_logger);
for (group = 0; group < DBG_MAX; group++)
{
@@ -409,12 +362,14 @@ static void initialize_loggers(bool use_stderr, level_t levels[])
file_logger->set_level(file_logger, group, levels[group]);
}
}
+ charon->bus->add_logger(charon->bus, &file_logger->logger);
+ charon->bus->add_logger(charon->bus, &sys_logger->logger);
/* set up default auth sys_logger */
sys_logger = sys_logger_create(LOG_AUTHPRIV, FALSE);
- charon->bus->add_listener(charon->bus, &sys_logger->listener);
- charon->sys_loggers->insert_last(charon->sys_loggers, sys_logger);
sys_logger->set_level(sys_logger, DBG_ANY, LEVEL_AUDIT);
+ charon->sys_loggers->insert_last(charon->sys_loggers, sys_logger);
+ charon->bus->add_logger(charon->bus, &sys_logger->logger);
}
}
@@ -432,7 +387,7 @@ static void usage(const char *msg)
" [--version]\n"
" [--use-syslog]\n"
" [--debug-<type> <level>]\n"
- " <type>: log context type (dmn|mgr|ike|chd|job|cfg|knl|net|asn|enc|tnc|imc|imv|pts|tls|lib)\n"
+ " <type>: log context type (dmn|mgr|ike|chd|job|cfg|knl|net|asn|enc|tnc|imc|imv|pts|tls|esp|lib)\n"
" <level>: log verbosity (-1 = silent, 0 = audit, 1 = control,\n"
" 2 = controlmore, 3 = raw, 4 = private)\n"
"\n"
@@ -448,6 +403,7 @@ int main(int argc, char *argv[])
bool use_syslog = FALSE;
level_t levels[DBG_MAX];
int group, status = SS_RC_INITIALIZATION_FAILED;
+ struct utsname utsname;
/* logging for library during initialization, as we have no bus yet */
dbg = dbg_stderr;
@@ -475,7 +431,7 @@ int main(int argc, char *argv[])
exit(SS_RC_INITIALIZATION_FAILED);
}
- if (!libcharon_init())
+ if (!libcharon_init("charon"))
{
dbg_stderr(DBG_DMN, 1, "initialization failed - aborting charon");
goto deinit;
@@ -510,6 +466,7 @@ int main(int argc, char *argv[])
{ "debug-imv", required_argument, &group, DBG_IMV },
{ "debug-pts", required_argument, &group, DBG_PTS },
{ "debug-tls", required_argument, &group, DBG_TLS },
+ { "debug-esp", required_argument, &group, DBG_ESP },
{ "debug-lib", required_argument, &group, DBG_LIB },
{ 0,0,0,0 }
};
@@ -550,8 +507,24 @@ int main(int argc, char *argv[])
initialize_loggers(!use_syslog, levels);
+ if (uname(&utsname) != 0)
+ {
+ memset(&utsname, 0, sizeof(utsname));
+ }
+ DBG1(DBG_DMN, "Starting IKE charon daemon (strongSwan "VERSION", %s %s, %s)",
+ utsname.sysname, utsname.release, utsname.machine);
+ if (lib->integrity)
+ {
+ DBG1(DBG_DMN, "integrity tests enabled:");
+ DBG1(DBG_DMN, "lib 'libstrongswan': passed file and segment integrity tests");
+ DBG1(DBG_DMN, "lib 'libhydra': passed file and segment integrity tests");
+ DBG1(DBG_DMN, "lib 'libcharon': passed file and segment integrity tests");
+ DBG1(DBG_DMN, "daemon 'charon': passed file integrity test");
+ }
+
/* initialize daemon */
- if (!charon->initialize(charon))
+ if (!charon->initialize(charon,
+ lib->settings->get_str(lib->settings, "charon.load", PLUGINS)))
{
DBG1(DBG_DMN, "initialization failed - aborting charon");
goto deinit;
@@ -564,7 +537,7 @@ int main(int argc, char *argv[])
goto deinit;
}
- if (!drop_capabilities())
+ if (!charon->caps->drop(charon->caps))
{
DBG1(DBG_DMN, "capability dropping failed - aborting charon");
goto deinit;
diff --git a/src/checksum/Makefile.am b/src/checksum/Makefile.am
index 58292a45a..1405fcd05 100644
--- a/src/checksum/Makefile.am
+++ b/src/checksum/Makefile.am
@@ -40,6 +40,11 @@ if !MONOLITHIC
endif
endif
+if USE_LIBIPSEC
+ deps += $(top_builddir)/src/libipsec/libipsec.la
+ libs += $(DESTDIR)$(ipseclibdir)/libipsec.so
+endif
+
if USE_TLS
deps += $(top_builddir)/src/libtls/libtls.la
libs += $(DESTDIR)$(ipseclibdir)/libtls.so
@@ -79,11 +84,6 @@ if !MONOLITHIC
endif
endif
-if USE_PLUTO
- exes += $(top_builddir)/src/pluto/.libs/pluto
- AM_CFLAGS += -DP_PLUGINS=\""${p_plugins}\""
-endif
-
if USE_TOOLS
exes += $(top_builddir)/src/openac/.libs/openac
exes += $(top_builddir)/src/pki/.libs/pki
diff --git a/src/checksum/Makefile.in b/src/checksum/Makefile.in
index 8c89fc615..ecbc3ae39 100644
--- a/src/checksum/Makefile.in
+++ b/src/checksum/Makefile.in
@@ -40,24 +40,24 @@ noinst_PROGRAMS = checksum_builder$(EXEEXT)
@USE_LIBHYDRA_TRUE@am__append_2 = $(top_builddir)/src/libhydra/libhydra.la
@USE_LIBHYDRA_TRUE@am__append_3 = $(DESTDIR)$(ipseclibdir)/libhydra.so
@MONOLITHIC_FALSE@@USE_LIBHYDRA_TRUE@am__append_4 = -DH_PLUGINS=\""${h_plugins}\""
-@USE_TLS_TRUE@am__append_5 = $(top_builddir)/src/libtls/libtls.la
-@USE_TLS_TRUE@am__append_6 = $(DESTDIR)$(ipseclibdir)/libtls.so
-@USE_RADIUS_TRUE@am__append_7 = $(top_builddir)/src/libradius/libradius.la
-@USE_RADIUS_TRUE@am__append_8 = $(DESTDIR)$(ipseclibdir)/libradius.so
-@USE_LIBTNCCS_TRUE@am__append_9 = $(top_builddir)/src/libtnccs/libtnccs.la
-@USE_LIBTNCCS_TRUE@am__append_10 = $(DESTDIR)$(ipseclibdir)/libtnccs.so
-@USE_SIMAKA_TRUE@am__append_11 = $(top_builddir)/src/libsimaka/libsimaka.la
-@USE_SIMAKA_TRUE@am__append_12 = $(DESTDIR)$(ipseclibdir)/libsimaka.so
-@USE_IMCV_TRUE@am__append_13 = $(top_builddir)/src/libimcv/libimcv.la
-@USE_IMCV_TRUE@am__append_14 = $(DESTDIR)$(ipseclibdir)/libimcv.so
-@USE_PTS_TRUE@am__append_15 = $(top_builddir)/src/libpts/libpts.la
-@USE_PTS_TRUE@am__append_16 = $(DESTDIR)$(ipseclibdir)/libpts.so
-@USE_CHARON_TRUE@am__append_17 = $(top_builddir)/src/libcharon/libcharon.la
-@USE_CHARON_TRUE@am__append_18 = $(DESTDIR)$(ipseclibdir)/libcharon.so
-@USE_CHARON_TRUE@am__append_19 = $(top_builddir)/src/charon/.libs/charon
-@MONOLITHIC_FALSE@@USE_CHARON_TRUE@am__append_20 = -DC_PLUGINS=\""${c_plugins}\""
-@USE_PLUTO_TRUE@am__append_21 = $(top_builddir)/src/pluto/.libs/pluto
-@USE_PLUTO_TRUE@am__append_22 = -DP_PLUGINS=\""${p_plugins}\""
+@USE_LIBIPSEC_TRUE@am__append_5 = $(top_builddir)/src/libipsec/libipsec.la
+@USE_LIBIPSEC_TRUE@am__append_6 = $(DESTDIR)$(ipseclibdir)/libipsec.so
+@USE_TLS_TRUE@am__append_7 = $(top_builddir)/src/libtls/libtls.la
+@USE_TLS_TRUE@am__append_8 = $(DESTDIR)$(ipseclibdir)/libtls.so
+@USE_RADIUS_TRUE@am__append_9 = $(top_builddir)/src/libradius/libradius.la
+@USE_RADIUS_TRUE@am__append_10 = $(DESTDIR)$(ipseclibdir)/libradius.so
+@USE_LIBTNCCS_TRUE@am__append_11 = $(top_builddir)/src/libtnccs/libtnccs.la
+@USE_LIBTNCCS_TRUE@am__append_12 = $(DESTDIR)$(ipseclibdir)/libtnccs.so
+@USE_SIMAKA_TRUE@am__append_13 = $(top_builddir)/src/libsimaka/libsimaka.la
+@USE_SIMAKA_TRUE@am__append_14 = $(DESTDIR)$(ipseclibdir)/libsimaka.so
+@USE_IMCV_TRUE@am__append_15 = $(top_builddir)/src/libimcv/libimcv.la
+@USE_IMCV_TRUE@am__append_16 = $(DESTDIR)$(ipseclibdir)/libimcv.so
+@USE_PTS_TRUE@am__append_17 = $(top_builddir)/src/libpts/libpts.la
+@USE_PTS_TRUE@am__append_18 = $(DESTDIR)$(ipseclibdir)/libpts.so
+@USE_CHARON_TRUE@am__append_19 = $(top_builddir)/src/libcharon/libcharon.la
+@USE_CHARON_TRUE@am__append_20 = $(DESTDIR)$(ipseclibdir)/libcharon.so
+@USE_CHARON_TRUE@am__append_21 = $(top_builddir)/src/charon/.libs/charon
+@MONOLITHIC_FALSE@@USE_CHARON_TRUE@am__append_22 = -DC_PLUGINS=\""${c_plugins}\""
@USE_TOOLS_TRUE@am__append_23 = \
@USE_TOOLS_TRUE@ $(top_builddir)/src/openac/.libs/openac \
@USE_TOOLS_TRUE@ $(top_builddir)/src/pki/.libs/pki \
@@ -79,6 +79,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -119,7 +120,7 @@ checksum_builder_DEPENDENCIES = \
$(top_builddir)/src/libhydra/libhydra.la \
$(top_builddir)/src/libcharon/libcharon.la \
$(am__DEPENDENCIES_1)
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -145,6 +146,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -239,11 +241,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -260,11 +265,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -280,6 +286,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -289,7 +296,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -337,7 +343,7 @@ INCLUDES = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = -DPLUGINDIR=\"${plugindir}\" -rdynamic $(am__append_1) \
- $(am__append_4) $(am__append_20) $(am__append_22)
+ $(am__append_4) $(am__append_22)
# we keep track of build dependencies in deps and use libs to store the paths
# to the installed libraries. for executables we use the built files directly
@@ -345,13 +351,13 @@ AM_CFLAGS = -DPLUGINDIR=\"${plugindir}\" -rdynamic $(am__append_1) \
deps = $(top_builddir)/src/libstrongswan/libstrongswan.la \
$(am__append_2) $(am__append_5) $(am__append_7) \
$(am__append_9) $(am__append_11) $(am__append_13) \
- $(am__append_15) $(am__append_17)
+ $(am__append_15) $(am__append_17) $(am__append_19)
libs = $(DESTDIR)$(ipseclibdir)/libstrongswan.so $(am__append_3) \
$(am__append_6) $(am__append_8) $(am__append_10) \
$(am__append_12) $(am__append_14) $(am__append_16) \
- $(am__append_18)
-exes = $(am__append_19) $(am__append_21) $(am__append_23) \
- $(am__append_24) $(am__append_25)
+ $(am__append_18) $(am__append_20)
+exes = $(am__append_21) $(am__append_23) $(am__append_24) \
+ $(am__append_25)
all: all-am
.SUFFIXES:
diff --git a/src/checksum/checksum_builder.c b/src/checksum/checksum_builder.c
index 670ec76bd..b083d54db 100644
--- a/src/checksum/checksum_builder.c
+++ b/src/checksum/checksum_builder.c
@@ -106,14 +106,16 @@ static void build_binary_checksum(char *path)
pos = strrchr(binary, '.');
if (pos && streq(pos, ".so"))
{
- snprintf(name, sizeof(name), "%.*s\",", pos - binary, binary);
+ snprintf(name, sizeof(name), "%.*s\",", (int)(pos - binary),
+ binary);
if (streq(name, "libstrongswan\","))
{
snprintf(sname, sizeof(sname), "%s", "library_init");
}
else
{
- snprintf(sname, sizeof(sname), "%.*s_init", pos - binary, binary);
+ snprintf(sname, sizeof(sname), "%.*s_init", (int)(pos - binary),
+ binary);
}
build_checksum(path, name, sname);
}
diff --git a/src/conftest/Makefile.am b/src/conftest/Makefile.am
index 7eab0df27..64a2cc6d3 100644
--- a/src/conftest/Makefile.am
+++ b/src/conftest/Makefile.am
@@ -1,6 +1,7 @@
ipsec_PROGRAMS = conftest
-AM_CFLAGS = -rdynamic
+AM_CFLAGS = -rdynamic \
+ -DPLUGINS=\""${charon_plugins}\""
conftest_SOURCES = conftest.c conftest.h config.c config.h actions.c actions.h \
hooks/hook.h hooks/ike_auth_fill.c hooks/unsort_message.c \
diff --git a/src/conftest/Makefile.in b/src/conftest/Makefile.in
index 4efdeaad5..ea26b70e7 100644
--- a/src/conftest/Makefile.in
+++ b/src/conftest/Makefile.in
@@ -50,6 +50,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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__installdirs = "$(DESTDIR)$(ipsecdir)"
@@ -73,7 +74,7 @@ conftest_DEPENDENCIES = \
$(top_builddir)/src/libhydra/libhydra.la \
$(top_builddir)/src/libcharon/libcharon.la \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -99,6 +100,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -193,11 +195,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -214,11 +219,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -234,6 +240,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -243,7 +250,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -271,7 +277,9 @@ top_srcdir = @top_srcdir@
urandom_device = @urandom_device@
xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
-AM_CFLAGS = -rdynamic
+AM_CFLAGS = -rdynamic \
+ -DPLUGINS=\""${charon_plugins}\""
+
conftest_SOURCES = conftest.c conftest.h config.c config.h actions.c actions.h \
hooks/hook.h hooks/ike_auth_fill.c hooks/unsort_message.c \
hooks/add_notify.c hooks/unencrypted_notify.c hooks/ignore_message.c \
diff --git a/src/conftest/config.c b/src/conftest/config.c
index 952141211..cbc6ac05f 100644
--- a/src/conftest/config.c
+++ b/src/conftest/config.c
@@ -103,9 +103,9 @@ static ike_cfg_t *load_ike_config(private_config_t *this,
ike_cfg = ike_cfg_create(TRUE,
settings->get_bool(settings, "configs.%s.fake_nat", FALSE, config),
- settings->get_str(settings, "configs.%s.lhost", "%any", config),
+ settings->get_str(settings, "configs.%s.lhost", "%any", config), FALSE,
settings->get_int(settings, "configs.%s.lport", 500, config),
- settings->get_str(settings, "configs.%s.rhost", "%any", config),
+ settings->get_str(settings, "configs.%s.rhost", "%any", config), FALSE,
settings->get_int(settings, "configs.%s.rport", 500, config));
token = settings->get_str(settings, "configs.%s.proposal", NULL, config);
if (token)
@@ -251,9 +251,9 @@ static peer_cfg_t *load_peer_config(private_config_t *this,
uintptr_t strength;
ike_cfg = load_ike_config(this, settings, config);
- peer_cfg = peer_cfg_create(config, 2, ike_cfg, CERT_ALWAYS_SEND,
- UNIQUE_NO, 1, 0, 0, 0, 0, FALSE, 0,
- NULL, NULL, FALSE, NULL, NULL);
+ peer_cfg = peer_cfg_create(config, IKEV2, ike_cfg, CERT_ALWAYS_SEND,
+ UNIQUE_NO, 1, 0, 0, 0, 0, FALSE, FALSE, 0, 0,
+ FALSE, NULL, NULL);
auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
diff --git a/src/conftest/conftest.c b/src/conftest/conftest.c
index 48bf9681f..6491fd294 100644
--- a/src/conftest/conftest.c
+++ b/src/conftest/conftest.c
@@ -289,7 +289,8 @@ static bool load_hooks()
pos = strchr(name, '-');
if (pos)
{
- snprintf(buf, sizeof(buf), "%.*s_hook_create", pos - name, name);
+ snprintf(buf, sizeof(buf), "%.*s_hook_create", (int)(pos - name),
+ name);
}
else
{
@@ -392,7 +393,7 @@ static void load_loggers(file_logger_t *logger)
}
logger = file_logger_create(file, NULL, FALSE);
load_log_levels(logger, section);
- charon->bus->add_listener(charon->bus, &logger->listener);
+ charon->bus->add_logger(charon->bus, &logger->logger);
charon->file_loggers->insert_last(charon->file_loggers, logger);
}
}
@@ -422,7 +423,7 @@ int main(int argc, char *argv[])
library_deinit();
return SS_RC_INITIALIZATION_FAILED;
}
- if (!libcharon_init())
+ if (!libcharon_init("conftest"))
{
libcharon_deinit();
libhydra_deinit();
@@ -436,7 +437,7 @@ int main(int argc, char *argv[])
logger = file_logger_create(stdout, NULL, FALSE);
logger->set_level(logger, DBG_ANY, LEVEL_CTRL);
- charon->bus->add_listener(charon->bus, &logger->listener);
+ charon->bus->add_logger(charon->bus, &logger->logger);
charon->file_loggers->insert_last(charon->file_loggers, logger);
lib->credmgr->add_set(lib->credmgr, &conftest->creds->set);
@@ -488,7 +489,7 @@ int main(int argc, char *argv[])
{
return 1;
}
- if (!charon->initialize(charon))
+ if (!charon->initialize(charon, PLUGINS))
{
return 1;
}
diff --git a/src/conftest/hooks/add_notify.c b/src/conftest/hooks/add_notify.c
index de46ca81f..9611cad6c 100644
--- a/src/conftest/hooks/add_notify.c
+++ b/src/conftest/hooks/add_notify.c
@@ -60,9 +60,9 @@ struct private_add_notify_t {
METHOD(listener_t, message, bool,
private_add_notify_t *this, ike_sa_t *ike_sa, message_t *message,
- bool incoming)
+ bool incoming, bool plain)
{
- if (!incoming &&
+ if (!incoming && plain &&
message->get_request(message) == this->req &&
message->get_message_id(message) == this->id)
{
@@ -85,11 +85,11 @@ METHOD(listener_t, message, bool,
data = chunk_skip(chunk_create(this->data, strlen(this->data)), 2);
data = chunk_from_hex(data, NULL);
}
- else if (this->data && strlen(this->data))
+ else if (strlen(this->data))
{
data = chunk_clone(chunk_create(this->data, strlen(this->data)));
}
- notify = notify_payload_create_from_protocol_and_type(
+ notify = notify_payload_create_from_protocol_and_type(NOTIFY,
this->esp ? PROTO_ESP : PROTO_IKE, type);
notify->set_spi(notify, this->spi);
if (data.len)
diff --git a/src/conftest/hooks/add_payload.c b/src/conftest/hooks/add_payload.c
index 03a47cc23..2903bb20f 100644
--- a/src/conftest/hooks/add_payload.c
+++ b/src/conftest/hooks/add_payload.c
@@ -62,9 +62,9 @@ struct private_add_payload_t {
METHOD(listener_t, message, bool,
private_add_payload_t *this, ike_sa_t *ike_sa, message_t *message,
- bool incoming)
+ bool incoming, bool plain)
{
- if (!incoming &&
+ if (!incoming && plain &&
message->get_request(message) == this->req &&
message->get_message_id(message) == this->id)
{
@@ -103,7 +103,7 @@ METHOD(listener_t, message, bool,
data = chunk_skip(chunk_create(this->data, strlen(this->data)), 2);
data = chunk_from_hex(data, NULL);
}
- else if (this->data && strlen(this->data))
+ else if (strlen(this->data))
{
data = chunk_clone(chunk_create(this->data, strlen(this->data)));
}
diff --git a/src/conftest/hooks/custom_proposal.c b/src/conftest/hooks/custom_proposal.c
index e4acd841f..38d4286c4 100644
--- a/src/conftest/hooks/custom_proposal.c
+++ b/src/conftest/hooks/custom_proposal.c
@@ -19,7 +19,6 @@
#include <encoding/payloads/sa_payload.h>
#include <config/proposal.h>
-#include <crypto/proposal/proposal_keywords.h>
typedef struct private_custom_proposal_t private_custom_proposal_t;
@@ -91,7 +90,7 @@ static linked_list_t* load_proposals(private_custom_proposal_t *this,
alg = strtoul(value, &end, 10);
if (end == value || errno)
{
- token = proposal_get_token(value, strlen(value));
+ token = lib->proposal->get_token(lib->proposal, value);
if (!token)
{
DBG1(DBG_CFG, "unknown algorithm: '%s', skipped", value);
@@ -111,9 +110,9 @@ static linked_list_t* load_proposals(private_custom_proposal_t *this,
METHOD(listener_t, message, bool,
private_custom_proposal_t *this, ike_sa_t *ike_sa, message_t *message,
- bool incoming)
+ bool incoming, bool plain)
{
- if (!incoming &&
+ if (!incoming && plain &&
message->get_request(message) == this->req &&
message->get_message_id(message) == this->id)
{
@@ -145,7 +144,7 @@ METHOD(listener_t, message, bool,
proposal->get_protocol(proposal),
proposal->get_spi(proposal));
DBG1(DBG_CFG, "injecting custom proposal: %#P", new_props);
- new = sa_payload_create_from_proposal_list(new_props);
+ new = sa_payload_create_from_proposals_v2(new_props);
message->add_payload(message, (payload_t*)new);
new_props->destroy_offset(new_props, offsetof(proposal_t, destroy));
}
diff --git a/src/conftest/hooks/force_cookie.c b/src/conftest/hooks/force_cookie.c
index e34f82851..1b044db14 100644
--- a/src/conftest/hooks/force_cookie.c
+++ b/src/conftest/hooks/force_cookie.c
@@ -32,9 +32,9 @@ struct private_force_cookie_t {
METHOD(listener_t, message, bool,
private_force_cookie_t *this, ike_sa_t *ike_sa, message_t *message,
- bool incoming)
+ bool incoming, bool plain)
{
- if (incoming && message->get_request(message) &&
+ if (incoming && plain && message->get_request(message) &&
message->get_exchange_type(message) == IKE_SA_INIT)
{
enumerator_t *enumerator;
@@ -68,7 +68,7 @@ METHOD(listener_t, message, bool,
chunk_t data = chunk_from_thing("COOKIE test data");
DBG1(DBG_CFG, "sending COOKIE: %#B", &data);
- response = message_create();
+ response = message_create(IKEV2_MAJOR_VERSION, IKEV2_MINOR_VERSION);
dst = message->get_source(message);
src = message->get_destination(message);
response->set_source(response, src->clone(src));
diff --git a/src/conftest/hooks/ignore_message.c b/src/conftest/hooks/ignore_message.c
index 210f3ac50..3cb5f2059 100644
--- a/src/conftest/hooks/ignore_message.c
+++ b/src/conftest/hooks/ignore_message.c
@@ -45,9 +45,9 @@ struct private_ignore_message_t {
METHOD(listener_t, message, bool,
private_ignore_message_t *this, ike_sa_t *ike_sa, message_t *message,
- bool incoming)
+ bool incoming, bool plain)
{
- if (incoming == this->in &&
+ if (incoming == this->in && plain &&
message->get_request(message) == this->req &&
message->get_message_id(message) == this->id)
{
diff --git a/src/conftest/hooks/ike_auth_fill.c b/src/conftest/hooks/ike_auth_fill.c
index 2843d60c1..09590d4f3 100644
--- a/src/conftest/hooks/ike_auth_fill.c
+++ b/src/conftest/hooks/ike_auth_fill.c
@@ -51,7 +51,10 @@ struct private_ike_auth_fill_t {
/** size of non ESP-Marker */
#define NON_ESP_MARKER_LEN 4
-
+/** length of fixed encryption payload header */
+#define ENCRYPTION_PAYLOAD_HEADER_LENGTH 4
+/** length of fixed cert payload header */
+#define CERT_PAYLOAD_HEADER_LENGTH 5
/**
* Calculate packet size on wire (without ethernet/IP header)
*/
@@ -89,9 +92,9 @@ static size_t calculate_wire_size(message_t *message, ike_sa_t *ike_sa)
METHOD(listener_t, message, bool,
private_ike_auth_fill_t *this, ike_sa_t *ike_sa, message_t *message,
- bool incoming)
+ bool incoming, bool plain)
{
- if (!incoming &&
+ if (!incoming && plain &&
message->get_request(message) == this->req &&
message->get_message_id(message) == this->id)
{
@@ -105,7 +108,7 @@ METHOD(listener_t, message, bool,
diff = this->bytes - size - CERT_PAYLOAD_HEADER_LENGTH;
data = chunk_alloc(diff);
memset(data.ptr, 0x12, data.len);
- pld = cert_payload_create_custom(201, data);
+ pld = cert_payload_create_custom(CERTIFICATE, 201, data);
message->add_payload(message, &pld->payload_interface);
DBG1(DBG_CFG, "inserting %d dummy bytes certificate payload", diff);
}
diff --git a/src/conftest/hooks/log_id.c b/src/conftest/hooks/log_id.c
index ad14cea10..07dd6a44e 100644
--- a/src/conftest/hooks/log_id.c
+++ b/src/conftest/hooks/log_id.c
@@ -32,9 +32,9 @@ struct private_log_id_t {
METHOD(listener_t, message, bool,
private_log_id_t *this, ike_sa_t *ike_sa, message_t *message,
- bool incoming)
+ bool incoming, bool plain)
{
- if (incoming)
+ if (incoming && plain)
{
enumerator_t *enumerator;
payload_t *payload;
diff --git a/src/conftest/hooks/log_ke.c b/src/conftest/hooks/log_ke.c
index 231c0a8d8..710482326 100644
--- a/src/conftest/hooks/log_ke.c
+++ b/src/conftest/hooks/log_ke.c
@@ -32,9 +32,9 @@ struct private_log_ke_t {
METHOD(listener_t, message, bool,
private_log_ke_t *this, ike_sa_t *ike_sa, message_t *message,
- bool incoming)
+ bool incoming, bool plain)
{
- if (incoming)
+ if (incoming && plain)
{
enumerator_t *enumerator;
payload_t *payload;
diff --git a/src/conftest/hooks/log_proposals.c b/src/conftest/hooks/log_proposals.c
index 8c330ab3d..347b83209 100644
--- a/src/conftest/hooks/log_proposals.c
+++ b/src/conftest/hooks/log_proposals.c
@@ -32,9 +32,9 @@ struct private_log_proposals_t {
METHOD(listener_t, message, bool,
private_log_proposals_t *this, ike_sa_t *ike_sa, message_t *message,
- bool incoming)
+ bool incoming, bool plain)
{
- if (incoming)
+ if (incoming && plain)
{
enumerator_t *enumerator, *proposals;
payload_t *payload;
diff --git a/src/conftest/hooks/log_ts.c b/src/conftest/hooks/log_ts.c
index fb7c89a0a..f212efa12 100644
--- a/src/conftest/hooks/log_ts.c
+++ b/src/conftest/hooks/log_ts.c
@@ -32,9 +32,9 @@ struct private_log_ts_t {
METHOD(listener_t, message, bool,
private_log_ts_t *this, ike_sa_t *ike_sa, message_t *message,
- bool incoming)
+ bool incoming, bool plain)
{
- if (incoming)
+ if (incoming && plain)
{
enumerator_t *enumerator;
payload_t *payload;
diff --git a/src/conftest/hooks/pretend_auth.c b/src/conftest/hooks/pretend_auth.c
index 4b7168cac..4166afc79 100644
--- a/src/conftest/hooks/pretend_auth.c
+++ b/src/conftest/hooks/pretend_auth.c
@@ -15,6 +15,7 @@
#include "hook.h"
+#include <sa/ikev2/keymat_v2.h>
#include <encoding/payloads/nonce_payload.h>
#include <encoding/payloads/cert_payload.h>
#include <encoding/payloads/auth_payload.h>
@@ -135,7 +136,7 @@ static void process_auth_request(private_pretend_auth_t *this,
static void process_init_response(private_pretend_auth_t *this,
ike_sa_t *ike_sa, message_t *message)
{
- this->ike_init = message->get_packet_data(message);
+ this->ike_init = chunk_clone(message->get_packet_data(message));
}
/**
@@ -153,7 +154,7 @@ static void build_certs(private_pretend_auth_t *this,
cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
if (cert)
{
- payload = cert_payload_create_from_cert(cert);
+ payload = cert_payload_create_from_cert(CERTIFICATE, cert);
if (payload)
{
DBG1(DBG_IKE, "pretending end entity cert \"%Y\"",
@@ -166,7 +167,7 @@ static void build_certs(private_pretend_auth_t *this,
{
if (type == AUTH_RULE_IM_CERT)
{
- payload = cert_payload_create_from_cert(cert);
+ payload = cert_payload_create_from_cert(CERTIFICATE, cert);
if (payload)
{
DBG1(DBG_IKE, "pretending issuer cert \"%Y\"",
@@ -190,7 +191,7 @@ static bool build_auth(private_pretend_auth_t *this,
auth_payload_t *auth_payload;
auth_method_t auth_method;
signature_scheme_t scheme;
- keymat_t *keymat;
+ keymat_v2_t *keymat;
auth = auth_cfg_create();
private = lib->credmgr->get_private(lib->credmgr, KEY_ANY, this->id, auth);
@@ -235,9 +236,13 @@ static bool build_auth(private_pretend_auth_t *this,
key_type_names, private->get_type(private));
return FALSE;
}
- keymat = ike_sa->get_keymat(ike_sa);
- octets = keymat->get_auth_octets(keymat, TRUE, this->ike_init,
- this->nonce, this->id, this->reserved);
+ keymat = (keymat_v2_t*)ike_sa->get_keymat(ike_sa);
+ if (!keymat->get_auth_octets(keymat, TRUE, this->ike_init,
+ this->nonce, this->id, this->reserved, &octets))
+ {
+ private->destroy(private);
+ return FALSE;
+ }
if (!private->sign(private, scheme, octets, &auth_data))
{
chunk_free(&octets);
@@ -294,7 +299,7 @@ static void process_auth_response(private_pretend_auth_t *this,
if (this->proposal)
{
message->add_payload(message, (payload_t*)
- sa_payload_create_from_proposal(this->proposal));
+ sa_payload_create_from_proposal_v2(this->proposal));
}
if (this->tsi)
{
@@ -310,35 +315,38 @@ static void process_auth_response(private_pretend_auth_t *this,
METHOD(listener_t, message, bool,
private_pretend_auth_t *this, ike_sa_t *ike_sa, message_t *message,
- bool incoming)
+ bool incoming, bool plain)
{
- if (incoming)
+ if (plain)
{
- if (!message->get_request(message))
+ if (incoming)
{
- if (message->get_exchange_type(message) == IKE_SA_INIT)
- {
- process_init_response(this, ike_sa, message);
- }
- if (message->get_exchange_type(message) == IKE_AUTH &&
- message->get_message_id(message) == 1)
+ if (!message->get_request(message))
{
- process_auth_response(this, ike_sa, message);
+ if (message->get_exchange_type(message) == IKE_SA_INIT)
+ {
+ process_init_response(this, ike_sa, message);
+ }
+ if (message->get_exchange_type(message) == IKE_AUTH &&
+ message->get_message_id(message) == 1)
+ {
+ process_auth_response(this, ike_sa, message);
+ }
}
}
- }
- else
- {
- if (message->get_request(message))
+ else
{
- if (message->get_exchange_type(message) == IKE_SA_INIT)
- {
- process_init_request(this, ike_sa, message);
- }
- if (message->get_exchange_type(message) == IKE_AUTH &&
- message->get_message_id(message) == 1)
+ if (message->get_request(message))
{
- process_auth_request(this, ike_sa, message);
+ if (message->get_exchange_type(message) == IKE_SA_INIT)
+ {
+ process_init_request(this, ike_sa, message);
+ }
+ if (message->get_exchange_type(message) == IKE_AUTH &&
+ message->get_message_id(message) == 1)
+ {
+ process_auth_request(this, ike_sa, message);
+ }
}
}
}
diff --git a/src/conftest/hooks/rebuild_auth.c b/src/conftest/hooks/rebuild_auth.c
index 993c952e0..b7e6f22e7 100644
--- a/src/conftest/hooks/rebuild_auth.c
+++ b/src/conftest/hooks/rebuild_auth.c
@@ -15,6 +15,7 @@
#include "hook.h"
+#include <sa/ikev2/keymat_v2.h>
#include <encoding/generator.h>
#include <encoding/payloads/nonce_payload.h>
#include <encoding/payloads/auth_payload.h>
@@ -57,12 +58,11 @@ static bool rebuild_auth(private_rebuild_auth_t *this, ike_sa_t *ike_sa,
enumerator_t *enumerator;
chunk_t octets, auth_data;
private_key_t *private;
- auth_cfg_t *auth;
payload_t *payload;
auth_payload_t *auth_payload;
auth_method_t auth_method;
signature_scheme_t scheme;
- keymat_t *keymat;
+ keymat_v2_t *keymat;
identification_t *id;
char reserved[3];
generator_t *generator;
@@ -90,10 +90,8 @@ static bool rebuild_auth(private_rebuild_auth_t *this, ike_sa_t *ike_sa,
id = identification_create_from_encoding(data.ptr[4], chunk_skip(data, 8));
generator->destroy(generator);
- auth = auth_cfg_create();
private = lib->credmgr->get_private(lib->credmgr, KEY_ANY,
- this->id ?: id, auth);
- auth->destroy(auth);
+ this->id ?: id, NULL);
if (private == NULL)
{
DBG1(DBG_CFG, "no private key found for '%Y' to rebuild AUTH",
@@ -137,9 +135,14 @@ static bool rebuild_auth(private_rebuild_auth_t *this, ike_sa_t *ike_sa,
id->destroy(id);
return FALSE;
}
- keymat = ike_sa->get_keymat(ike_sa);
- octets = keymat->get_auth_octets(keymat, FALSE, this->ike_init,
- this->nonce, id, reserved);
+ keymat = (keymat_v2_t*)ike_sa->get_keymat(ike_sa);
+ if (!keymat->get_auth_octets(keymat, FALSE, this->ike_init,
+ this->nonce, id, reserved, &octets))
+ {
+ private->destroy(private);
+ id->destroy(id);
+ return FALSE;
+ }
if (!private->sign(private, scheme, octets, &auth_data))
{
chunk_free(&octets);
@@ -174,34 +177,37 @@ static bool rebuild_auth(private_rebuild_auth_t *this, ike_sa_t *ike_sa,
METHOD(listener_t, message, bool,
private_rebuild_auth_t *this, ike_sa_t *ike_sa, message_t *message,
- bool incoming)
+ bool incoming, bool plain)
{
- if (!incoming && message->get_message_id(message) == 1)
- {
- rebuild_auth(this, ike_sa, message);
- }
- if (message->get_exchange_type(message) == IKE_SA_INIT)
+ if (plain)
{
- if (incoming)
+ if (!incoming && message->get_message_id(message) == 1)
{
- nonce_payload_t *nonce;
-
- nonce = (nonce_payload_t*)message->get_payload(message, NONCE);
- if (nonce)
- {
- free(this->nonce.ptr);
- this->nonce = nonce->get_nonce(nonce);
- }
+ rebuild_auth(this, ike_sa, message);
}
- else
+ if (message->get_exchange_type(message) == IKE_SA_INIT)
{
- packet_t *packet;
-
- if (message->generate(message, NULL, &packet) == SUCCESS)
+ if (incoming)
+ {
+ nonce_payload_t *nonce;
+
+ nonce = (nonce_payload_t*)message->get_payload(message, NONCE);
+ if (nonce)
+ {
+ free(this->nonce.ptr);
+ this->nonce = nonce->get_nonce(nonce);
+ }
+ }
+ else
{
- free(this->ike_init.ptr);
- this->ike_init = chunk_clone(packet->get_data(packet));
- packet->destroy(packet);
+ packet_t *packet;
+
+ if (message->generate(message, NULL, &packet) == SUCCESS)
+ {
+ free(this->ike_init.ptr);
+ this->ike_init = chunk_clone(packet->get_data(packet));
+ packet->destroy(packet);
+ }
}
}
}
diff --git a/src/conftest/hooks/reset_seq.c b/src/conftest/hooks/reset_seq.c
index ccf8e997d..6fb7a2e4b 100644
--- a/src/conftest/hooks/reset_seq.c
+++ b/src/conftest/hooks/reset_seq.c
@@ -51,7 +51,6 @@ static job_requeue_t reset_cb(struct xfrm_usersa_id *data)
struct nlmsghdr *hdr;
struct xfrm_aevent_id *id;
struct rtattr *rthdr;
- struct xfrm_replay_state *replay;
struct sockaddr_nl addr;
int s, len;
@@ -74,8 +73,6 @@ static job_requeue_t reset_cb(struct xfrm_usersa_id *data)
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_replay_state));
hdr->nlmsg_len += rthdr->rta_len;
- replay = (struct xfrm_replay_state*)RTA_DATA(rthdr);
-
s = socket(AF_NETLINK, SOCK_RAW, NETLINK_XFRM);
if (s == -1)
{
diff --git a/src/conftest/hooks/set_critical.c b/src/conftest/hooks/set_critical.c
index caf2215c3..8ec84e13d 100644
--- a/src/conftest/hooks/set_critical.c
+++ b/src/conftest/hooks/set_critical.c
@@ -47,9 +47,9 @@ struct private_set_critical_t {
METHOD(listener_t, message, bool,
private_set_critical_t *this, ike_sa_t *ike_sa, message_t *message,
- bool incoming)
+ bool incoming, bool plain)
{
- if (!incoming &&
+ if (!incoming && plain &&
message->get_request(message) == this->req &&
message->get_message_id(message) == this->id)
{
diff --git a/src/conftest/hooks/set_ike_initiator.c b/src/conftest/hooks/set_ike_initiator.c
index 6ba43eaca..1674f0a2d 100644
--- a/src/conftest/hooks/set_ike_initiator.c
+++ b/src/conftest/hooks/set_ike_initiator.c
@@ -42,9 +42,9 @@ struct private_set_ike_initiator_t {
METHOD(listener_t, message, bool,
private_set_ike_initiator_t *this, ike_sa_t *ike_sa, message_t *message,
- bool incoming)
+ bool incoming, bool plain)
{
- if (!incoming &&
+ if (!incoming && plain &&
message->get_request(message) == this->req &&
message->get_message_id(message) == this->id)
{
diff --git a/src/conftest/hooks/set_ike_request.c b/src/conftest/hooks/set_ike_request.c
index baabea66a..fd5b6de61 100644
--- a/src/conftest/hooks/set_ike_request.c
+++ b/src/conftest/hooks/set_ike_request.c
@@ -42,9 +42,9 @@ struct private_set_ike_request_t {
METHOD(listener_t, message, bool,
private_set_ike_request_t *this, ike_sa_t *ike_sa, message_t *message,
- bool incoming)
+ bool incoming, bool plain)
{
- if (!incoming &&
+ if (!incoming && plain &&
message->get_request(message) == this->req &&
message->get_message_id(message) == this->id)
{
diff --git a/src/conftest/hooks/set_ike_spi.c b/src/conftest/hooks/set_ike_spi.c
index 14a0da9cd..bda02580d 100644
--- a/src/conftest/hooks/set_ike_spi.c
+++ b/src/conftest/hooks/set_ike_spi.c
@@ -52,9 +52,9 @@ struct private_set_ike_spi_t {
METHOD(listener_t, message, bool,
private_set_ike_spi_t *this, ike_sa_t *ike_sa, message_t *message,
- bool incoming)
+ bool incoming, bool plain)
{
- if (!incoming &&
+ if (!incoming && plain &&
message->get_request(message) == this->req &&
message->get_message_id(message) == this->id)
{
diff --git a/src/conftest/hooks/set_ike_version.c b/src/conftest/hooks/set_ike_version.c
index d2de9dc81..ca52879d1 100644
--- a/src/conftest/hooks/set_ike_version.c
+++ b/src/conftest/hooks/set_ike_version.c
@@ -57,9 +57,9 @@ struct private_set_ike_version_t {
METHOD(listener_t, message, bool,
private_set_ike_version_t *this, ike_sa_t *ike_sa, message_t *message,
- bool incoming)
+ bool incoming, bool plain)
{
- if (!incoming &&
+ if (!incoming && plain &&
message->get_request(message) == this->req &&
message->get_message_id(message) == this->id)
{
diff --git a/src/conftest/hooks/set_length.c b/src/conftest/hooks/set_length.c
index 0379dcb7c..c1a867a99 100644
--- a/src/conftest/hooks/set_length.c
+++ b/src/conftest/hooks/set_length.c
@@ -50,9 +50,9 @@ struct private_set_length_t {
METHOD(listener_t, message, bool,
private_set_length_t *this, ike_sa_t *ike_sa, message_t *message,
- bool incoming)
+ bool incoming, bool plain)
{
- if (!incoming &&
+ if (!incoming && plain &&
message->get_request(message) == this->req &&
message->get_message_id(message) == this->id)
{
@@ -76,11 +76,10 @@ METHOD(listener_t, message, bool,
if (type == payload->get_type(payload))
{
encoding_rule_t *rules;
- size_t count;
u_int16_t *len;
- int i;
+ int i, count;
- payload->get_encoding_rules(payload, &rules, &count);
+ count = payload->get_encoding_rules(payload, &rules);
for (i = 0; i < count; i++)
{
if (rules[i].type == PAYLOAD_LENGTH)
diff --git a/src/conftest/hooks/set_proposal_number.c b/src/conftest/hooks/set_proposal_number.c
index a59d96b6d..0cc3cfc63 100644
--- a/src/conftest/hooks/set_proposal_number.c
+++ b/src/conftest/hooks/set_proposal_number.c
@@ -69,9 +69,9 @@ static void copy_proposal_algs(proposal_t *from, proposal_t *to,
METHOD(listener_t, message, bool,
private_set_proposal_number_t *this, ike_sa_t *ike_sa, message_t *message,
- bool incoming)
+ bool incoming, bool plain)
{
- if (!incoming &&
+ if (!incoming && plain &&
message->get_request(message) == this->req &&
message->get_message_id(message) == this->id)
{
@@ -121,7 +121,7 @@ METHOD(listener_t, message, bool,
}
enumerator->destroy(enumerator);
}
- sa = sa_payload_create_from_proposal_list(updated);
+ sa = sa_payload_create_from_proposals_v2(updated);
list->destroy_offset(list, offsetof(proposal_t, destroy));
updated->destroy_offset(updated, offsetof(proposal_t, destroy));
message->add_payload(message, (payload_t*)sa);
diff --git a/src/conftest/hooks/set_reserved.c b/src/conftest/hooks/set_reserved.c
index 77a605d2a..d1a4a977b 100644
--- a/src/conftest/hooks/set_reserved.c
+++ b/src/conftest/hooks/set_reserved.c
@@ -163,9 +163,9 @@ static void set_byte(private_set_reserved_t *this, message_t *message,
METHOD(listener_t, message, bool,
private_set_reserved_t *this, ike_sa_t *ike_sa, message_t *message,
- bool incoming)
+ bool incoming, bool plain)
{
- if (!incoming &&
+ if (!incoming && plain &&
message->get_request(message) == this->req &&
message->get_message_id(message) == this->id)
{
diff --git a/src/conftest/hooks/unencrypted_notify.c b/src/conftest/hooks/unencrypted_notify.c
index 80bdc64b7..f4c35725c 100644
--- a/src/conftest/hooks/unencrypted_notify.c
+++ b/src/conftest/hooks/unencrypted_notify.c
@@ -80,11 +80,11 @@ METHOD(listener_t, ike_updown, bool,
data = chunk_skip(chunk_create(this->data, strlen(this->data)), 2);
data = chunk_from_hex(data, NULL);
}
- else if (this->data && strlen(this->data))
+ else if (strlen(this->data))
{
data = chunk_clone(chunk_create(this->data, strlen(this->data)));
}
- notify = notify_payload_create_from_protocol_and_type(
+ notify = notify_payload_create_from_protocol_and_type(NOTIFY,
this->esp ? PROTO_ESP : PROTO_IKE, type);
notify->set_spi(notify, this->spi);
if (data.len)
@@ -95,7 +95,7 @@ METHOD(listener_t, ike_updown, bool,
DBG1(DBG_CFG, "injecting unencrypted INFORMATIONAL message");
- message = message_create();
+ message = message_create(IKEV2_MAJOR_VERSION, IKEV2_MINOR_VERSION);
message->set_message_id(message, this->id);
message->set_ike_sa_id(message, ike_sa->get_id(ike_sa));
message->set_exchange_type(message, INFORMATIONAL);
diff --git a/src/conftest/hooks/unsort_message.c b/src/conftest/hooks/unsort_message.c
index b37b261a4..1b2b302af 100644
--- a/src/conftest/hooks/unsort_message.c
+++ b/src/conftest/hooks/unsort_message.c
@@ -45,9 +45,9 @@ struct private_unsort_message_t {
METHOD(listener_t, message, bool,
private_unsort_message_t *this, ike_sa_t *ike_sa, message_t *message,
- bool incoming)
+ bool incoming, bool plain)
{
- if (!incoming &&
+ if (!incoming && plain &&
message->get_request(message) == this->req &&
message->get_message_id(message) == this->id)
{
diff --git a/src/dumm/Makefile.in b/src/dumm/Makefile.in
index bd172b701..ad24ca998 100644
--- a/src/dumm/Makefile.in
+++ b/src/dumm/Makefile.in
@@ -51,6 +51,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -91,7 +92,7 @@ am_irdumm_OBJECTS = irdumm.$(OBJEXT)
irdumm_OBJECTS = $(am_irdumm_OBJECTS)
irdumm_DEPENDENCIES = libdumm.la \
$(top_builddir)/src/libstrongswan/libstrongswan.la
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -117,6 +118,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -211,11 +213,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -232,11 +237,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -252,6 +258,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -261,7 +268,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/dumm/ext/extconf.rb.in b/src/dumm/ext/extconf.rb.in
index 36536ec52..29df65ca7 100644
--- a/src/dumm/ext/extconf.rb.in
+++ b/src/dumm/ext/extconf.rb.in
@@ -5,7 +5,7 @@
require 'mkmf'
$defs << " @DEFS@"
-$CFLAGS << " -Wno-format"
+$CFLAGS << " -Wno-format -include \"@top_builddir@/config.h\""
dir_config('dumm', '@top_srcdir@/src/dumm', '../.libs')
dir_config('strongswan', '@top_srcdir@/src/libstrongswan', '../../libstrongswan/.libs')
diff --git a/src/dumm/mconsole.c b/src/dumm/mconsole.c
index de70b7e69..40045cc3a 100644
--- a/src/dumm/mconsole.c
+++ b/src/dumm/mconsole.c
@@ -150,7 +150,7 @@ static int request(private_mconsole_t *this, void(*cb)(void*,char*,size_t),
if (reply.len && *reply.data)
{
DBG1(DBG_LIB, "received mconsole error %d: %.*s",
- reply.err, reply.len, reply.data);
+ reply.err, (int)reply.len, reply.data);
}
break;
}
diff --git a/src/include/Makefile.in b/src/include/Makefile.in
index 8bc6befc7..bdf80a49c 100644
--- a/src/include/Makefile.in
+++ b/src/include/Makefile.in
@@ -48,6 +48,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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 =
SOURCES =
@@ -61,6 +62,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -155,11 +157,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -176,11 +181,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -196,6 +202,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -205,7 +212,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/ipsec/Makefile.am b/src/ipsec/Makefile.am
index bbf009721..8be28eff8 100644
--- a/src/ipsec/Makefile.am
+++ b/src/ipsec/Makefile.am
@@ -1,22 +1,35 @@
-sbin_SCRIPTS = ipsec
-CLEANFILES = ipsec ipsec.8
-dist_man8_MANS = ipsec.8
-EXTRA_DIST = ipsec.in ipsec.8.in Android.mk
+sbin_SCRIPTS = _ipsec
+CLEANFILES = _ipsec _ipsec.8
+dist_man8_MANS = _ipsec.8
+EXTRA_DIST = _ipsec.in _ipsec.8.in Android.mk
-ipsec.8 : ipsec.8.in
+_ipsec.8 : _ipsec.8.in
sed \
-e "s:@IPSEC_VERSION@:$(PACKAGE_VERSION):" \
+ -e "s:@IPSEC_SCRIPT@:$(ipsec_script):g" \
+ -e "s:@IPSEC_SCRIPT_UPPER@:$(ipsec_script_upper):g" \
$(srcdir)/$@.in > $@
-ipsec : ipsec.in
+_ipsec : _ipsec.in
sed \
-e "s:@IPSEC_SHELL@:/bin/sh:" \
-e "s:@IPSEC_VERSION@:$(PACKAGE_VERSION):" \
-e "s:@IPSEC_NAME@:$(PACKAGE_NAME):" \
-e "s:@IPSEC_DISTRO@::" \
-e "s:@IPSEC_DIR@:$(ipsecdir):" \
+ -e "s:@IPSEC_SCRIPT@:$(ipsec_script):" \
-e "s:@IPSEC_SBINDIR@:$(sbindir):" \
-e "s:@IPSEC_CONFDIR@:$(sysconfdir):" \
-e "s:@IPSEC_PIDDIR@:$(piddir):" \
$(srcdir)/$@.in > $@
chmod +x $@
+
+install-exec-hook:
+ mv $(DESTDIR)$(sbindir)/_ipsec $(DESTDIR)$(sbindir)/$(ipsec_script)
+
+install-data-hook:
+ mv $(DESTDIR)$(man8dir)/_ipsec.8 $(DESTDIR)$(man8dir)/$(ipsec_script).8
+
+uninstall-hook:
+ rm -f $(DESTDIR)$(sbindir)/$(ipsec_script)
+ rm -f $(DESTDIR)$(man8dir)/$(ipsec_script).8
diff --git a/src/ipsec/Makefile.in b/src/ipsec/Makefile.in
index b0474159d..dbb163f42 100644
--- a/src/ipsec/Makefile.in
+++ b/src/ipsec/Makefile.in
@@ -50,6 +50,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -89,6 +90,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -183,11 +185,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -204,11 +209,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -224,6 +230,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -233,7 +240,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -261,10 +267,10 @@ top_srcdir = @top_srcdir@
urandom_device = @urandom_device@
xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
-sbin_SCRIPTS = ipsec
-CLEANFILES = ipsec ipsec.8
-dist_man8_MANS = ipsec.8
-EXTRA_DIST = ipsec.in ipsec.8.in Android.mk
+sbin_SCRIPTS = _ipsec
+CLEANFILES = _ipsec _ipsec.8
+dist_man8_MANS = _ipsec.8
+EXTRA_DIST = _ipsec.in _ipsec.8.in Android.mk
all: all-am
.SUFFIXES:
@@ -476,13 +482,15 @@ info: info-am
info-am:
install-data-am: install-man
-
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) install-data-hook
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am: install-sbinSCRIPTS
-
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) install-exec-hook
install-html: install-html-am
install-html-am:
@@ -520,43 +528,59 @@ ps: ps-am
ps-am:
uninstall-am: uninstall-man uninstall-sbinSCRIPTS
-
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) uninstall-hook
uninstall-man: uninstall-man8
-.MAKE: install-am install-strip
+.MAKE: install-am install-data-am install-exec-am install-strip \
+ uninstall-am
.PHONY: all all-am check check-am clean clean-generic clean-libtool \
distclean distclean-generic distclean-libtool distdir dvi \
dvi-am html html-am info info-am install install-am \
- install-data install-data-am install-dvi install-dvi-am \
- install-exec install-exec-am install-html install-html-am \
- install-info install-info-am install-man install-man8 \
- install-pdf install-pdf-am install-ps install-ps-am \
- install-sbinSCRIPTS install-strip installcheck installcheck-am \
- installdirs maintainer-clean maintainer-clean-generic \
- mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
- ps ps-am uninstall uninstall-am uninstall-man uninstall-man8 \
+ install-data install-data-am install-data-hook install-dvi \
+ install-dvi-am install-exec install-exec-am install-exec-hook \
+ install-html install-html-am install-info install-info-am \
+ install-man install-man8 install-pdf install-pdf-am install-ps \
+ install-ps-am install-sbinSCRIPTS install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am \
+ uninstall-hook uninstall-man uninstall-man8 \
uninstall-sbinSCRIPTS
-ipsec.8 : ipsec.8.in
+_ipsec.8 : _ipsec.8.in
sed \
-e "s:@IPSEC_VERSION@:$(PACKAGE_VERSION):" \
+ -e "s:@IPSEC_SCRIPT@:$(ipsec_script):g" \
+ -e "s:@IPSEC_SCRIPT_UPPER@:$(ipsec_script_upper):g" \
$(srcdir)/$@.in > $@
-ipsec : ipsec.in
+_ipsec : _ipsec.in
sed \
-e "s:@IPSEC_SHELL@:/bin/sh:" \
-e "s:@IPSEC_VERSION@:$(PACKAGE_VERSION):" \
-e "s:@IPSEC_NAME@:$(PACKAGE_NAME):" \
-e "s:@IPSEC_DISTRO@::" \
-e "s:@IPSEC_DIR@:$(ipsecdir):" \
+ -e "s:@IPSEC_SCRIPT@:$(ipsec_script):" \
-e "s:@IPSEC_SBINDIR@:$(sbindir):" \
-e "s:@IPSEC_CONFDIR@:$(sysconfdir):" \
-e "s:@IPSEC_PIDDIR@:$(piddir):" \
$(srcdir)/$@.in > $@
chmod +x $@
+install-exec-hook:
+ mv $(DESTDIR)$(sbindir)/_ipsec $(DESTDIR)$(sbindir)/$(ipsec_script)
+
+install-data-hook:
+ mv $(DESTDIR)$(man8dir)/_ipsec.8 $(DESTDIR)$(man8dir)/$(ipsec_script).8
+
+uninstall-hook:
+ rm -f $(DESTDIR)$(sbindir)/$(ipsec_script)
+ rm -f $(DESTDIR)$(man8dir)/$(ipsec_script).8
+
# 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/ipsec/ipsec.8 b/src/ipsec/_ipsec.8
index 66e43b481..7802fc48f 100644
--- a/src/ipsec/ipsec.8
+++ b/src/ipsec/_ipsec.8
@@ -1,4 +1,4 @@
-.TH IPSEC 8 "2010-05-30" "4.5.3dr3" "strongSwan"
+.TH IPSEC 8 "2012-06-19" "5.0.1dr3" "strongSwan"
.SH NAME
ipsec \- invoke IPsec utilities
.SH SYNOPSIS
@@ -31,240 +31,229 @@ and the IPsec version number.
.PP
.SS CONTROL COMMANDS
.TP
-.B "ipsec start [ starter options ]"
+.B "start [ starter options ]"
calls
-.BR "ipsec starter"
-which in turn parses \fIipsec.conf\fR and starts the IKEv1 \fIpluto\fR and
-IKEv2 \fIcharon\fR daemons.
+.BR "starter"
+which in turn parses \fIipsec.conf\fR and starts the IKEv1/IKEv2 daemon
+\fIcharon\fR.
.PP
.TP
-.B "ipsec update"
+.B "update"
sends a \fIHUP\fR signal to
-.BR "ipsec starter"
+.BR "starter"
which in turn determines any changes in \fIipsec.conf\fR
-and updates the configuration on the running IKEv1 \fIpluto\fR and IKEv2
-\fIcharon\fR daemons, correspondingly.
+and updates the configuration on the running IKE daemon \fIcharon\fR.
.PP
.TP
-.B "ipsec reload"
+.B "reload"
sends a \fIUSR1\fR signal to
-.BR "ipsec starter"
-which in turn reloads the whole configuration on the running IKEv1 \fIpluto\fR
-and IKEv2 \fIcharon\fR daemons based on the actual \fIipsec.conf\fR.
+.BR "starter"
+which in turn reloads the whole configuration on the running IKE daemon
+\fIcharon\fR based on the actual \fIipsec.conf\fR.
.PP
.TP
-.B "ipsec restart"
+.B "restart"
is equivalent to
-.B "ipsec stop"
+.B "stop"
followed by
-.B "ipsec start"
+.B "start"
after a guard of 2 seconds.
.PP
.TP
-.B "ipsec stop"
-terminates all IPsec connections and stops the IKEv1 \fIpluto\fR and IKEv2
-\fIcharon\fR daemons by sending a \fITERM\fR signal to
-.BR "ipsec starter".
+.B "stop"
+terminates all IPsec connections and stops the IKE daemon \fIcharon\fR
+by sending a \fITERM\fR signal to
+.BR "starter".
.PP
.TP
-.B "ipsec up \fIname\fP"
-tells the responsible IKE daemon to start up connection \fIname\fP.
+.B "up \fIname\fP"
+tells the IKE daemon to start up connection \fIname\fP.
.PP
.TP
-.B "ipsec down \fIname\fP"
-tells the responsible IKE daemon to terminate connection \fIname\fP.
+.B "down \fIname\fP"
+tells the IKE daemon to terminate connection \fIname\fP.
.PP
.TP
-.B "ipsec down \fIname{n}\fP"
-terminates IKEv2 CHILD SA instance \fIn\fP of connection \fIname\fP.
+.B "down \fIname{n}\fP"
+terminates IKEv1 Quick Mode and IKEv2 CHILD SA instance \fIn\fP of
+connection \fIname\fP.
.PP
.TP
-.B "ipsec down \fIname{*}\fP"
-terminates all IKEv2 CHILD SA instances of connection \fIname\fP.
+.B "down \fIname{*}\fP"
+terminates all IKEv1 Quick Mode and IKEv2 CHILD SA instances of connection
+\fIname\fP.
.PP
.TP
-.B "ipsec down \fIname[n]\fP"
-terminates all IKEv2 IKE SA instance \fIn\fP of connection \fIname\fP.
+.B "down \fIname[n]\fP"
+terminates IKE SA instance \fIn\fP of connection \fIname\fP.
.PP
.TP
-.B "ipsec down \fIname[*]\fP"
-terminates all IKEv2 IKE SA instances of connection \fIname\fP.
+.B "down \fIname[*]\fP"
+terminates all IKE SA instances of connection \fIname\fP.
.PP
.TP
-.B "ipsec route \fIname\fP"
-tells the responsible IKE daemon to insert an IPsec policy in the kernel
+.B "route \fIname\fP"
+tells the IKE daemon to insert an IPsec policy in the kernel
for connection \fIname\fP. The first payload packet matching the IPsec policy
will automatically trigger an IKE connection setup.
.PP
.TP
-.B "ipsec unroute \fIname\fP"
+.B "unroute \fIname\fP"
remove the IPsec policy in the kernel for connection \fIname\fP.
.PP
.TP
-.B "ipsec status [ \fIname\fP ]"
+.B "status [ \fIname\fP ]"
returns concise status information either on connection
\fIname\fP or if the argument is lacking, on all connections.
.PP
.TP
-.B "ipsec statusall [ \fIname\fP ]"
+.B "statusall [ \fIname\fP ]"
returns detailed status information either on connection
\fIname\fP or if the argument is lacking, on all connections.
.PP
.SS LIST COMMANDS
.TP
-.B "ipsec listalgs"
-returns a list all supported IKE encryption and hash algorithms, the available
-Diffie-Hellman groups, as well as all supported ESP encryption and
-authentication algorithms registered via the Linux kernel's Crypto API.
-.br
-Supported by the IKEv1 \fIpluto\fP daemon only.
+.B "listalgs"
+returns a list supported cryptographic algorithms usable for IKE, and their
+corresponding plugin.
.PP
.TP
-.B "ipsec listpubkeys [ --utc ]"
+.B "listpubkeys [ --utc ]"
returns a list of RSA public keys that were either loaded in raw key format
or extracted from X.509 and|or OpenPGP certificates.
-.br
-Supported by the IKEv1 \fIpluto\fP daemon only.
.PP
.TP
-.B "ipsec listcerts [ --utc ]"
+.B "listcerts [ --utc ]"
returns a list of X.509 and|or OpenPGP certificates that were either loaded
-locally by the IKE daemon or received via the IKEv2 protocol.
+locally by the IKE daemon or received via the IKE protocol.
.PP
.TP
-.B "ipsec listcacerts [ --utc ]"
+.B "listcacerts [ --utc ]"
returns a list of X.509 Certification Authority (CA) certificates that were
loaded locally by the IKE daemon from the \fI/etc/ipsec.d/cacerts/\fP
-directory or received in PKCS#7-wrapped certificate payloads via the IKE
-protocol.
+directory or received via the IKE protocol.
.PP
.TP
-.B "ipsec listaacerts [ --utc ]"
+.B "listaacerts [ --utc ]"
returns a list of X.509 Authorization Authority (AA) certificates that were
loaded locally by the IKE daemon from the \fI/etc/ipsec.d/aacerts/\fP
directory.
.PP
.TP
-.B "ipsec listocspcerts [ --utc ]"
+.B "listocspcerts [ --utc ]"
returns a list of X.509 OCSP Signer certificates that were either loaded
locally by the IKE daemon from the \fI/etc/ipsec.d/ocspcerts/\fP
directory or were sent by an OCSP server.
.PP
.TP
-.B "ipsec listacerts [ --utc ]"
+.B "listacerts [ --utc ]"
returns a list of X.509 Attribute certificates that were loaded locally by
the IKE daemon from the \fI/etc/ipsec.d/acerts/\fP directory.
.PP
.TP
-.B "ipsec listgroups [ --utc ]"
+.B "listgroups [ --utc ]"
returns a list of groups that are used to define user authorization profiles.
-.br
-Supported by the IKEv1 \fIpluto\fP daemon only.
.PP
.TP
-.B "ipsec listcainfos [ --utc ]"
+.B "listcainfos [ --utc ]"
returns certification authority information (CRL distribution points, OCSP URIs,
LDAP servers) that were defined by
.BR ca
sections in \fIipsec.conf\fP.
.PP
.TP
-.B "ipsec listcrls [ --utc ]"
+.B "listcrls [ --utc ]"
returns a list of Certificate Revocation Lists (CRLs) that were either loaded
by the IKE daemon from the \fI/etc/ipsec.d/crls\fP directory or fetched from
an HTTP- or LDAP-based CRL distribution point.
.PP
.TP
-.B "ipsec listocsp [ --utc ]"
+.B "listocsp [ --utc ]"
returns revocation information fetched from OCSP servers.
.PP
.TP
-.B "ipsec listcards [ --utc ]"
-list all certificates found on attached smart cards.
-.br
-Supported by the IKEv1 \fIpluto\fP daemon only.
-.PP
-.TP
-.B "ipsec listall [ --utc ]"
-returns all information generated by the list commands above. Each list command
+.B "listall [ --utc ]"
+returns all information generated by the list commands above. Each list command
can be called with the
\fB\-\-utc\fP
option which displays all dates in UTC instead of local time.
.PP
.SS REREAD COMMANDS
.TP
-.B "ipsec rereadsecrets"
+.B "rereadsecrets"
flushes and rereads all secrets defined in \fIipsec.secrets\fP.
.PP
.TP
-.B "ipsec rereadcacerts"
+.B "rereadcacerts"
reads all certificate files contained in the \fI/etc/ipsec.d/cacerts\fP
directory and adds them to the list of Certification Authority (CA)
certificates.
.PP
.TP
-.B "ipsec rereadaacerts"
+.B "rereadaacerts"
reads all certificate files contained in the \fI/etc/ipsec.d/aacerts\fP
directory and adds them to the list of Authorization Authority (AA)
certificates.
.PP
.TP
-.B "ipsec rereadocspcerts"
+.B "rereadocspcerts"
reads all certificate files contained in the \fI/etc/ipsec.d/ocspcerts/\fP
directory and adds them to the list of OCSP signer certificates.
.PP
.TP
-.B "ipsec rereadacerts"
+.B "rereadacerts"
reads all certificate files contained in the \fI/etc/ipsec.d/acerts/\fP
directory and adds them to the list of attribute certificates.
.PP
.TP
-.B "ipsec rereadcrls"
+.B "rereadcrls"
reads all Certificate Revocation Lists (CRLs) contained in the
\fI/etc/ipsec.d/crls/\fP directory and adds them to the list of CRLs.
.PP
.TP
-.B "ipsec rereadall"
+.B "rereadall"
executes all reread commands listed above.
.PP
.SS PURGE COMMANDS
.TP
-.B "ipsec purgeike"
-purges IKEv2 SAs that don't have a CHILD SA.
+.B "purgeike"
+purges IKE SAs that don't have a Quick Mode or CHILD SA.
.PP
.TP
-.B "ipsec purgeocsp"
+.B "purgeocsp"
purges all cached OCSP information records.
.PP
.SS INFO COMMANDS
.TP
-.B "ipsec \-\-help"
-returns the usage information for the ipsec command.
+.B "\-\-help"
+returns the usage information for the
+.B ipsec
+command.
.PP
.TP
-.B "ipsec \-\-version"
+.B "\-\-version"
returns the version in the form of
.B Linux strongSwan U<strongSwan userland version>/K<Linux kernel version>
if strongSwan uses the native NETKEY IPsec stack of the Linux kernel it is
running on.
.PP
.TP
-.B "ipsec \-\-versioncode"
+.B "\-\-versioncode"
returns the version number in the form of
.B U<strongSwan userland version>/K<Linux kernel version>
if strongSwan uses the native NETKEY IPsec stack of the Linux kernel it is
running on.
.PP
.TP
-.B "ipsec \-\-copyright"
+.B "\-\-copyright"
returns the copyright information.
.PP
.TP
-.B "ipsec \-\-directory"
+.B "\-\-directory"
returns the \fILIBEXECDIR\fP directory as defined by the configure options.
.PP
.TP
-.B "ipsec \-\-confdir"
+.B "\-\-confdir"
returns the \fISYSCONFDIR\fP directory as defined by the configure options.
.SH FILES
/usr/local/lib/ipsec usual utilities directory
@@ -278,15 +267,15 @@ command sets them if they are not already set.
.nf
.na
-IPSEC_DIR directory containing ipsec programs and utilities
-IPSEC_SBINDIR directory containing \fBipsec\fP command
-IPSEC_CONFDIR directory containing configuration files
-IPSEC_PIDDIR directory containing PID files
-IPSEC_NAME name of ipsec distribution
-IPSEC_VERSION version numer of ipsec userland and kernel
-IPSEC_STARTER_PID PID file for ipsec starter
-IPSEC_PLUTO_PID PID file for IKEv1 keying daemon
-IPSEC_CHARON_PID PID file for IKEv2 keying daemon
+IPSEC_DIR directory containing ipsec programs and utilities
+IPSEC_SBINDIR directory containing \fBipsec\fP command
+IPSEC_CONFDIR directory containing configuration files
+IPSEC_PIDDIR directory containing PID files
+IPSEC_SCRIPT name of the ipsec script
+IPSEC_NAME name of ipsec distribution
+IPSEC_VERSION version numer of ipsec userland and kernel
+IPSEC_STARTER_PID PID file for ipsec starter
+IPSEC_CHARON_PID PID file for IKE keying daemon
.ad
.fi
.SH SEE ALSO
diff --git a/src/ipsec/ipsec.8.in b/src/ipsec/_ipsec.8.in
index 24a796392..41c6ff8d2 100644
--- a/src/ipsec/ipsec.8.in
+++ b/src/ipsec/_ipsec.8.in
@@ -1,13 +1,13 @@
-.TH IPSEC 8 "2010-05-30" "@IPSEC_VERSION@" "strongSwan"
+.TH @IPSEC_SCRIPT_UPPER@ 8 "2012-06-19" "@IPSEC_VERSION@" "strongSwan"
.SH NAME
-ipsec \- invoke IPsec utilities
+@IPSEC_SCRIPT@ \- invoke IPsec utilities
.SH SYNOPSIS
-.B ipsec
+.B @IPSEC_SCRIPT@
\fIcommand\fP [ \fIarguments\fP ] [ \fIoptions\fP ]
.PP
.SH DESCRIPTION
The
-.B ipsec
+.B @IPSEC_SCRIPT@
utility invokes any of several utilities involved in controlling and monitoring
the IPsec encryption/authentication system, running the specified \fIcommand\fP
with the specified \fIarguments\fP and \fIoptions\fP as if it had been invoked
@@ -18,7 +18,7 @@ All the commands described in this manual page are built-in and are used to
control and monitor IPsec connections as well as the IKE daemons.
.PP
For other commands
-.I ipsec
+.I @IPSEC_SCRIPT@
supplies the invoked
.I command
with a suitable PATH environment variable,
@@ -31,240 +31,229 @@ and the IPsec version number.
.PP
.SS CONTROL COMMANDS
.TP
-.B "ipsec start [ starter options ]"
+.B "start [ starter options ]"
calls
-.BR "ipsec starter"
-which in turn parses \fIipsec.conf\fR and starts the IKEv1 \fIpluto\fR and
-IKEv2 \fIcharon\fR daemons.
+.BR "starter"
+which in turn parses \fIipsec.conf\fR and starts the IKEv1/IKEv2 daemon
+\fIcharon\fR.
.PP
.TP
-.B "ipsec update"
+.B "update"
sends a \fIHUP\fR signal to
-.BR "ipsec starter"
+.BR "starter"
which in turn determines any changes in \fIipsec.conf\fR
-and updates the configuration on the running IKEv1 \fIpluto\fR and IKEv2
-\fIcharon\fR daemons, correspondingly.
+and updates the configuration on the running IKE daemon \fIcharon\fR.
.PP
.TP
-.B "ipsec reload"
+.B "reload"
sends a \fIUSR1\fR signal to
-.BR "ipsec starter"
-which in turn reloads the whole configuration on the running IKEv1 \fIpluto\fR
-and IKEv2 \fIcharon\fR daemons based on the actual \fIipsec.conf\fR.
+.BR "starter"
+which in turn reloads the whole configuration on the running IKE daemon
+\fIcharon\fR based on the actual \fIipsec.conf\fR.
.PP
.TP
-.B "ipsec restart"
+.B "restart"
is equivalent to
-.B "ipsec stop"
+.B "stop"
followed by
-.B "ipsec start"
+.B "start"
after a guard of 2 seconds.
.PP
.TP
-.B "ipsec stop"
-terminates all IPsec connections and stops the IKEv1 \fIpluto\fR and IKEv2
-\fIcharon\fR daemons by sending a \fITERM\fR signal to
-.BR "ipsec starter".
+.B "stop"
+terminates all IPsec connections and stops the IKE daemon \fIcharon\fR
+by sending a \fITERM\fR signal to
+.BR "starter".
.PP
.TP
-.B "ipsec up \fIname\fP"
-tells the responsible IKE daemon to start up connection \fIname\fP.
+.B "up \fIname\fP"
+tells the IKE daemon to start up connection \fIname\fP.
.PP
.TP
-.B "ipsec down \fIname\fP"
-tells the responsible IKE daemon to terminate connection \fIname\fP.
+.B "down \fIname\fP"
+tells the IKE daemon to terminate connection \fIname\fP.
.PP
.TP
-.B "ipsec down \fIname{n}\fP"
-terminates IKEv2 CHILD SA instance \fIn\fP of connection \fIname\fP.
+.B "down \fIname{n}\fP"
+terminates IKEv1 Quick Mode and IKEv2 CHILD SA instance \fIn\fP of
+connection \fIname\fP.
.PP
.TP
-.B "ipsec down \fIname{*}\fP"
-terminates all IKEv2 CHILD SA instances of connection \fIname\fP.
+.B "down \fIname{*}\fP"
+terminates all IKEv1 Quick Mode and IKEv2 CHILD SA instances of connection
+\fIname\fP.
.PP
.TP
-.B "ipsec down \fIname[n]\fP"
-terminates all IKEv2 IKE SA instance \fIn\fP of connection \fIname\fP.
+.B "down \fIname[n]\fP"
+terminates IKE SA instance \fIn\fP of connection \fIname\fP.
.PP
.TP
-.B "ipsec down \fIname[*]\fP"
-terminates all IKEv2 IKE SA instances of connection \fIname\fP.
+.B "down \fIname[*]\fP"
+terminates all IKE SA instances of connection \fIname\fP.
.PP
.TP
-.B "ipsec route \fIname\fP"
-tells the responsible IKE daemon to insert an IPsec policy in the kernel
+.B "route \fIname\fP"
+tells the IKE daemon to insert an IPsec policy in the kernel
for connection \fIname\fP. The first payload packet matching the IPsec policy
will automatically trigger an IKE connection setup.
.PP
.TP
-.B "ipsec unroute \fIname\fP"
+.B "unroute \fIname\fP"
remove the IPsec policy in the kernel for connection \fIname\fP.
.PP
.TP
-.B "ipsec status [ \fIname\fP ]"
+.B "status [ \fIname\fP ]"
returns concise status information either on connection
\fIname\fP or if the argument is lacking, on all connections.
.PP
.TP
-.B "ipsec statusall [ \fIname\fP ]"
+.B "statusall [ \fIname\fP ]"
returns detailed status information either on connection
\fIname\fP or if the argument is lacking, on all connections.
.PP
.SS LIST COMMANDS
.TP
-.B "ipsec listalgs"
-returns a list all supported IKE encryption and hash algorithms, the available
-Diffie-Hellman groups, as well as all supported ESP encryption and
-authentication algorithms registered via the Linux kernel's Crypto API.
-.br
-Supported by the IKEv1 \fIpluto\fP daemon only.
+.B "listalgs"
+returns a list supported cryptographic algorithms usable for IKE, and their
+corresponding plugin.
.PP
.TP
-.B "ipsec listpubkeys [ --utc ]"
+.B "listpubkeys [ --utc ]"
returns a list of RSA public keys that were either loaded in raw key format
or extracted from X.509 and|or OpenPGP certificates.
-.br
-Supported by the IKEv1 \fIpluto\fP daemon only.
.PP
.TP
-.B "ipsec listcerts [ --utc ]"
+.B "listcerts [ --utc ]"
returns a list of X.509 and|or OpenPGP certificates that were either loaded
-locally by the IKE daemon or received via the IKEv2 protocol.
+locally by the IKE daemon or received via the IKE protocol.
.PP
.TP
-.B "ipsec listcacerts [ --utc ]"
+.B "listcacerts [ --utc ]"
returns a list of X.509 Certification Authority (CA) certificates that were
loaded locally by the IKE daemon from the \fI/etc/ipsec.d/cacerts/\fP
-directory or received in PKCS#7-wrapped certificate payloads via the IKE
-protocol.
+directory or received via the IKE protocol.
.PP
.TP
-.B "ipsec listaacerts [ --utc ]"
+.B "listaacerts [ --utc ]"
returns a list of X.509 Authorization Authority (AA) certificates that were
loaded locally by the IKE daemon from the \fI/etc/ipsec.d/aacerts/\fP
directory.
.PP
.TP
-.B "ipsec listocspcerts [ --utc ]"
+.B "listocspcerts [ --utc ]"
returns a list of X.509 OCSP Signer certificates that were either loaded
locally by the IKE daemon from the \fI/etc/ipsec.d/ocspcerts/\fP
directory or were sent by an OCSP server.
.PP
.TP
-.B "ipsec listacerts [ --utc ]"
+.B "listacerts [ --utc ]"
returns a list of X.509 Attribute certificates that were loaded locally by
the IKE daemon from the \fI/etc/ipsec.d/acerts/\fP directory.
.PP
.TP
-.B "ipsec listgroups [ --utc ]"
+.B "listgroups [ --utc ]"
returns a list of groups that are used to define user authorization profiles.
-.br
-Supported by the IKEv1 \fIpluto\fP daemon only.
.PP
.TP
-.B "ipsec listcainfos [ --utc ]"
+.B "listcainfos [ --utc ]"
returns certification authority information (CRL distribution points, OCSP URIs,
LDAP servers) that were defined by
.BR ca
sections in \fIipsec.conf\fP.
.PP
.TP
-.B "ipsec listcrls [ --utc ]"
+.B "listcrls [ --utc ]"
returns a list of Certificate Revocation Lists (CRLs) that were either loaded
by the IKE daemon from the \fI/etc/ipsec.d/crls\fP directory or fetched from
an HTTP- or LDAP-based CRL distribution point.
.PP
.TP
-.B "ipsec listocsp [ --utc ]"
+.B "listocsp [ --utc ]"
returns revocation information fetched from OCSP servers.
.PP
.TP
-.B "ipsec listcards [ --utc ]"
-list all certificates found on attached smart cards.
-.br
-Supported by the IKEv1 \fIpluto\fP daemon only.
-.PP
-.TP
-.B "ipsec listall [ --utc ]"
-returns all information generated by the list commands above. Each list command
+.B "listall [ --utc ]"
+returns all information generated by the list commands above. Each list command
can be called with the
\fB\-\-utc\fP
option which displays all dates in UTC instead of local time.
.PP
.SS REREAD COMMANDS
.TP
-.B "ipsec rereadsecrets"
+.B "rereadsecrets"
flushes and rereads all secrets defined in \fIipsec.secrets\fP.
.PP
.TP
-.B "ipsec rereadcacerts"
+.B "rereadcacerts"
reads all certificate files contained in the \fI/etc/ipsec.d/cacerts\fP
directory and adds them to the list of Certification Authority (CA)
certificates.
.PP
.TP
-.B "ipsec rereadaacerts"
+.B "rereadaacerts"
reads all certificate files contained in the \fI/etc/ipsec.d/aacerts\fP
directory and adds them to the list of Authorization Authority (AA)
certificates.
.PP
.TP
-.B "ipsec rereadocspcerts"
+.B "rereadocspcerts"
reads all certificate files contained in the \fI/etc/ipsec.d/ocspcerts/\fP
directory and adds them to the list of OCSP signer certificates.
.PP
.TP
-.B "ipsec rereadacerts"
+.B "rereadacerts"
reads all certificate files contained in the \fI/etc/ipsec.d/acerts/\fP
directory and adds them to the list of attribute certificates.
.PP
.TP
-.B "ipsec rereadcrls"
+.B "rereadcrls"
reads all Certificate Revocation Lists (CRLs) contained in the
\fI/etc/ipsec.d/crls/\fP directory and adds them to the list of CRLs.
.PP
.TP
-.B "ipsec rereadall"
+.B "rereadall"
executes all reread commands listed above.
.PP
.SS PURGE COMMANDS
.TP
-.B "ipsec purgeike"
-purges IKEv2 SAs that don't have a CHILD SA.
+.B "purgeike"
+purges IKE SAs that don't have a Quick Mode or CHILD SA.
.PP
.TP
-.B "ipsec purgeocsp"
+.B "purgeocsp"
purges all cached OCSP information records.
.PP
.SS INFO COMMANDS
.TP
-.B "ipsec \-\-help"
-returns the usage information for the ipsec command.
+.B "\-\-help"
+returns the usage information for the
+.B @IPSEC_SCRIPT@
+command.
.PP
.TP
-.B "ipsec \-\-version"
+.B "\-\-version"
returns the version in the form of
.B Linux strongSwan U<strongSwan userland version>/K<Linux kernel version>
if strongSwan uses the native NETKEY IPsec stack of the Linux kernel it is
running on.
.PP
.TP
-.B "ipsec \-\-versioncode"
+.B "\-\-versioncode"
returns the version number in the form of
.B U<strongSwan userland version>/K<Linux kernel version>
if strongSwan uses the native NETKEY IPsec stack of the Linux kernel it is
running on.
.PP
.TP
-.B "ipsec \-\-copyright"
+.B "\-\-copyright"
returns the copyright information.
.PP
.TP
-.B "ipsec \-\-directory"
+.B "\-\-directory"
returns the \fILIBEXECDIR\fP directory as defined by the configure options.
.PP
.TP
-.B "ipsec \-\-confdir"
+.B "\-\-confdir"
returns the \fISYSCONFDIR\fP directory as defined by the configure options.
.SH FILES
/usr/local/lib/ipsec usual utilities directory
@@ -273,20 +262,20 @@ returns the \fISYSCONFDIR\fP directory as defined by the configure options.
The following environment variables control where strongSwan finds its
components.
The
-.B ipsec
+.B @IPSEC_SCRIPT@
command sets them if they are not already set.
.nf
.na
-IPSEC_DIR directory containing ipsec programs and utilities
-IPSEC_SBINDIR directory containing \fBipsec\fP command
-IPSEC_CONFDIR directory containing configuration files
-IPSEC_PIDDIR directory containing PID files
-IPSEC_NAME name of ipsec distribution
-IPSEC_VERSION version numer of ipsec userland and kernel
-IPSEC_STARTER_PID PID file for ipsec starter
-IPSEC_PLUTO_PID PID file for IKEv1 keying daemon
-IPSEC_CHARON_PID PID file for IKEv2 keying daemon
+IPSEC_DIR directory containing ipsec programs and utilities
+IPSEC_SBINDIR directory containing \fBipsec\fP command
+IPSEC_CONFDIR directory containing configuration files
+IPSEC_PIDDIR directory containing PID files
+IPSEC_SCRIPT name of the ipsec script
+IPSEC_NAME name of ipsec distribution
+IPSEC_VERSION version numer of ipsec userland and kernel
+IPSEC_STARTER_PID PID file for ipsec starter
+IPSEC_CHARON_PID PID file for IKE keying daemon
.ad
.fi
.SH SEE ALSO
diff --git a/src/ipsec/ipsec.in b/src/ipsec/_ipsec.in
index 479974a0e..2acf5a3f6 100755..100644
--- a/src/ipsec/ipsec.in
+++ b/src/ipsec/_ipsec.in
@@ -28,36 +28,34 @@ IPSEC_DIR="@IPSEC_DIR@"
IPSEC_SBINDIR="@IPSEC_SBINDIR@"
IPSEC_CONFDIR="@IPSEC_CONFDIR@"
IPSEC_PIDDIR="@IPSEC_PIDDIR@"
+IPSEC_SCRIPT="@IPSEC_SCRIPT@"
IPSEC_STARTER_PID="${IPSEC_PIDDIR}/starter.pid"
-IPSEC_PLUTO_PID="${IPSEC_PIDDIR}/pluto.pid"
IPSEC_CHARON_PID="${IPSEC_PIDDIR}/charon.pid"
-IPSEC_WHACK="${IPSEC_DIR}/whack"
IPSEC_STROKE="${IPSEC_DIR}/stroke"
IPSEC_STARTER="${IPSEC_DIR}/starter"
-export IPSEC_DIR IPSEC_SBINDIR IPSEC_CONFDIR IPSEC_PIDDIR IPSEC_VERSION IPSEC_NAME IPSEC_STARTER_PID IPSEC_PLUTO_PID IPSEC_CHARON_PID
+export IPSEC_DIR IPSEC_SBINDIR IPSEC_CONFDIR IPSEC_PIDDIR IPSEC_SCRIPT IPSEC_VERSION IPSEC_NAME IPSEC_STARTER_PID IPSEC_CHARON_PID
IPSEC_DISTRO="Institute for Internet Technologies and Applications\nUniversity of Applied Sciences Rapperswil, Switzerland"
case "$1" in
'')
- echo "Usage: ipsec command argument ..."
- echo "Use --help for list of commands, or see ipsec(8) manual page"
- echo "or the $IPSEC_NAME documentation for names of the common ones."
- echo "Most have their own manual pages, e.g. ipsec_auto(8)."
+ echo "Usage: $IPSEC_SCRIPT command argument ..."
+ echo "Use --help for list of commands, or see $IPSEC_SCRIPT(8) manual "
+ echo "page or the $IPSEC_NAME documentation for names of the common "
+ echo "ones."
echo "See <http://www.strongswan.org> for more general info."
exit 0
;;
--help)
- echo "Usage: ipsec command argument ..."
+ echo "Usage: $IPSEC_SCRIPT command argument ..."
echo "where command is one of:"
echo " start|restart arguments..."
echo " update|reload|stop"
echo " up|down|route|unroute <connectionname>"
echo " status|statusall [<connectionname>]"
- echo " ready"
echo " listalgs|listpubkeys|listcerts [--utc]"
echo " listcacerts|listaacerts|listocspcerts [--utc]"
echo " listacerts|listgroups|listcainfos [--utc]"
@@ -67,14 +65,11 @@ case "$1" in
echo " rereadcacerts|rereadaacerts|rereadocspcerts"
echo " rereadacerts|rereadcrls|rereadall"
echo " purgeocsp|purgecrls|purgecerts|purgeike"
- echo " scencrypt|scdecrypt <value> [--inbase <base>] [--outbase <base>] [--keyid <id>]"
echo " openac"
- echo " pluto"
echo " scepclient"
echo " secrets"
echo " starter"
echo " version"
- echo " whack"
echo " stroke"
echo
echo "Some of these functions have their own manual pages, e.g. ipsec_scepclient(8)."
@@ -100,15 +95,10 @@ down)
shift
if [ "$#" -ne 1 ]
then
- echo "Usage: ipsec down <connection name>"
+ echo "Usage: $IPSEC_SCRIPT down <connection name>"
exit 2
fi
rc=7
- if [ -e $IPSEC_PLUTO_PID ]
- then
- $IPSEC_WHACK --name "$1" --terminate
- rc="$?"
- fi
if [ -e $IPSEC_CHARON_PID ]
then
$IPSEC_STROKE down "$1"
@@ -120,7 +110,7 @@ down-srcip)
shift
if [ "$#" -lt 1 ]
then
- echo "Usage: ipsec down-srcip <start> [<end>]"
+ echo "Usage: $IPSEC_SCRIPT down-srcip <start> [<end>]"
exit 2
fi
rc=7
@@ -134,11 +124,6 @@ down-srcip)
listcards|rereadgroups)
op="$1"
shift
- if [ -e $IPSEC_PLUTO_PID ]
- then
- $IPSEC_WHACK "$@" "--$op"
- rc="$?"
- fi
if [ -e $IPSEC_CHARON_PID ]
then
exit 3
@@ -150,15 +135,6 @@ leases)
op="$1"
rc=7
shift
- if [ -e $IPSEC_PLUTO_PID ]
- then
- case "$#" in
- 0) $IPSEC_WHACK "--$op" ;;
- 1) $IPSEC_WHACK "--$op" --name "$1" ;;
- *) $IPSEC_WHACK "--$op" --name "$1" --lease-addr "$2" ;;
- esac
- rc="$?"
- fi
if [ -e $IPSEC_CHARON_PID ]
then
case "$#" in
@@ -180,11 +156,6 @@ rereadall|purgeocsp)
op="$1"
rc=7
shift
- if [ -e $IPSEC_PLUTO_PID ]
- then
- $IPSEC_WHACK "$@" "--$op"
- rc="$?"
- fi
if [ -e $IPSEC_CHARON_PID ]
then
$IPSEC_STROKE "$op" "$@"
@@ -201,16 +172,6 @@ purgeike|purgecrls|purgecerts)
fi
exit "$rc"
;;
-ready)
- shift
- if [ -e $IPSEC_PLUTO_PID ]
- then
- $IPSEC_WHACK --listen
- exit 0
- else
- exit 7
- fi
- ;;
reload)
rc=7
if [ -e $IPSEC_STARTER_PID ]
@@ -223,10 +184,10 @@ reload)
exit "$rc"
;;
restart)
- $IPSEC_SBINDIR/ipsec stop
+ $IPSEC_SBINDIR/$IPSEC_SCRIPT stop
sleep 2
shift
- exec $IPSEC_SBINDIR/ipsec start "$@"
+ exec $IPSEC_SBINDIR/$IPSEC_SCRIPT start "$@"
;;
route|unroute)
op="$1"
@@ -234,14 +195,9 @@ route|unroute)
shift
if [ "$#" -ne 1 ]
then
- echo "Usage: ipsec $op <connection name>"
+ echo "Usage: $IPSEC_SCRIPT $op <connection name>"
exit 2
fi
- if [ -e $IPSEC_PLUTO_PID ]
- then
- $IPSEC_WHACK --name "$1" "--$op"
- rc="$?"
- fi
if [ -e $IPSEC_CHARON_PID ]
then
$IPSEC_STROKE "$op" "$1"
@@ -249,24 +205,8 @@ route|unroute)
fi
exit "$rc"
;;
-scencrypt|scdecrypt)
- op="$1"
- shift
- if [ -e $IPSEC_PLUTO_PID ]
- then
- $IPSEC_WHACK "--$op" "$@"
- exit "$?"
- else
- exit 7
- fi
- ;;
secrets)
rc=7
- if [ -e $IPSEC_PLUTO_PID ]
- then
- $IPSEC_WHACK --rereadsecrets
- rc="$?"
- fi
if [ -e $IPSEC_CHARON_PID ]
then
$IPSEC_STROKE rereadsecrets
@@ -293,19 +233,11 @@ status|statusall)
shift
if [ $# -eq 0 ]
then
- if [ -e $IPSEC_PLUTO_PID ]
- then
- $IPSEC_WHACK "--$op"
- fi
if [ -e $IPSEC_CHARON_PID ]
then
$IPSEC_STROKE "$op"
fi
else
- if [ -e $IPSEC_PLUTO_PID ]
- then
- $IPSEC_WHACK --name "$1" "--$op"
- fi
if [ -e $IPSEC_CHARON_PID ]
then
$IPSEC_STROKE "$op" "$1"
@@ -351,15 +283,10 @@ up)
shift
if [ "$#" -ne 1 ]
then
- echo "Usage: ipsec up <connection name>"
+ echo "Usage: $IPSEC_SCRIPT up <connection name>"
exit 2
fi
rc=7
- if [ -e $IPSEC_PLUTO_PID ]
- then
- $IPSEC_WHACK --name "$1" --initiate
- rc="$?"
- fi
if [ -e $IPSEC_CHARON_PID ]
then
$IPSEC_STROKE up "$1"
@@ -381,7 +308,7 @@ update)
version|--version)
printf "$OS_NAME $IPSEC_NAME $IPSEC_VERSION\n"
printf "$IPSEC_DISTRO\n"
- printf "See 'ipsec --copyright' for copyright information.\n"
+ printf "See '$IPSEC_SCRIPT --copyright' for copyright information.\n"
exit 0
;;
--*)
@@ -400,7 +327,7 @@ then
path="$IPSEC_DIR/$cmd"
if [ ! -x "$path" ]
then
- echo "$0: unknown IPsec command \`$cmd' (\`ipsec --help' for list)" >&2
+ echo "$0: unknown IPsec command \`$cmd' (\`$IPSEC_SCRIPT --help' for list)" >&2
exit 2
fi
fi
diff --git a/src/libcharon/Android.mk b/src/libcharon/Android.mk
index f98d36a61..9eb864f50 100644
--- a/src/libcharon/Android.mk
+++ b/src/libcharon/Android.mk
@@ -5,6 +5,7 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
bus/bus.c bus/bus.h \
bus/listeners/listener.h \
+bus/listeners/logger.h \
bus/listeners/file_logger.c bus/listeners/file_logger.h \
bus/listeners/sys_logger.c bus/listeners/sys_logger.h \
config/backend_manager.c config/backend_manager.h config/backend.h \
@@ -40,9 +41,10 @@ encoding/payloads/transform_substructure.c encoding/payloads/transform_substruct
encoding/payloads/ts_payload.c encoding/payloads/ts_payload.h \
encoding/payloads/unknown_payload.c encoding/payloads/unknown_payload.h \
encoding/payloads/vendor_id_payload.c encoding/payloads/vendor_id_payload.h \
+encoding/payloads/hash_payload.c encoding/payloads/hash_payload.h \
kernel/kernel_handler.c kernel/kernel_handler.h \
network/receiver.c network/receiver.h network/sender.c network/sender.h \
-network/packet.c network/packet.h network/socket.c network/socket.h \
+network/socket.c network/socket.h \
network/socket_manager.c network/socket_manager.h \
processing/jobs/acquire_job.c processing/jobs/acquire_job.h \
processing/jobs/delete_child_sa_job.c processing/jobs/delete_child_sa_job.h \
@@ -52,43 +54,73 @@ processing/jobs/process_message_job.c processing/jobs/process_message_job.h \
processing/jobs/rekey_child_sa_job.c processing/jobs/rekey_child_sa_job.h \
processing/jobs/rekey_ike_sa_job.c processing/jobs/rekey_ike_sa_job.h \
processing/jobs/retransmit_job.c processing/jobs/retransmit_job.h \
+processing/jobs/retry_initiate_job.c processing/jobs/retry_initiate_job.h \
processing/jobs/send_dpd_job.c processing/jobs/send_dpd_job.h \
processing/jobs/send_keepalive_job.c processing/jobs/send_keepalive_job.h \
processing/jobs/start_action_job.c processing/jobs/start_action_job.h \
processing/jobs/roam_job.c processing/jobs/roam_job.h \
processing/jobs/update_sa_job.c processing/jobs/update_sa_job.h \
processing/jobs/inactivity_job.c processing/jobs/inactivity_job.h \
-sa/authenticators/authenticator.c sa/authenticators/authenticator.h \
-sa/authenticators/eap_authenticator.c sa/authenticators/eap_authenticator.h \
-sa/authenticators/eap/eap_method.c sa/authenticators/eap/eap_method.h \
-sa/authenticators/eap/eap_manager.c sa/authenticators/eap/eap_manager.h \
-sa/authenticators/psk_authenticator.c sa/authenticators/psk_authenticator.h \
-sa/authenticators/pubkey_authenticator.c sa/authenticators/pubkey_authenticator.h \
+sa/eap/eap_method.c sa/eap/eap_method.h \
+sa/eap/eap_manager.c sa/eap/eap_manager.h \
+sa/xauth/xauth_method.c sa/xauth/xauth_method.h \
+sa/xauth/xauth_manager.c sa/xauth/xauth_manager.h \
+sa/authenticator.c sa/authenticator.h \
sa/child_sa.c sa/child_sa.h \
sa/ike_sa.c sa/ike_sa.h \
sa/ike_sa_id.c sa/ike_sa_id.h \
+sa/keymat.h sa/keymat.c \
sa/ike_sa_manager.c sa/ike_sa_manager.h \
-sa/task_manager.c sa/task_manager.h \
-sa/keymat.c sa/keymat.h \
+sa/task_manager.h sa/task_manager.c \
sa/shunt_manager.c sa/shunt_manager.h \
sa/trap_manager.c sa/trap_manager.h \
-sa/tasks/child_create.c sa/tasks/child_create.h \
-sa/tasks/child_delete.c sa/tasks/child_delete.h \
-sa/tasks/child_rekey.c sa/tasks/child_rekey.h \
-sa/tasks/ike_auth.c sa/tasks/ike_auth.h \
-sa/tasks/ike_cert_pre.c sa/tasks/ike_cert_pre.h \
-sa/tasks/ike_cert_post.c sa/tasks/ike_cert_post.h \
-sa/tasks/ike_config.c sa/tasks/ike_config.h \
-sa/tasks/ike_delete.c sa/tasks/ike_delete.h \
-sa/tasks/ike_dpd.c sa/tasks/ike_dpd.h \
-sa/tasks/ike_init.c sa/tasks/ike_init.h \
-sa/tasks/ike_natd.c sa/tasks/ike_natd.h \
-sa/tasks/ike_mobike.c sa/tasks/ike_mobike.h \
-sa/tasks/ike_rekey.c sa/tasks/ike_rekey.h \
-sa/tasks/ike_reauth.c sa/tasks/ike_reauth.h \
-sa/tasks/ike_auth_lifetime.c sa/tasks/ike_auth_lifetime.h \
-sa/tasks/ike_vendor.c sa/tasks/ike_vendor.h \
-sa/tasks/task.c sa/tasks/task.h
+sa/task.c sa/task.h
+
+LOCAL_SRC_FILES += \
+sa/ikev2/keymat_v2.c sa/ikev2/keymat_v2.h \
+sa/ikev2/task_manager_v2.c sa/ikev2/task_manager_v2.h \
+sa/ikev2/authenticators/eap_authenticator.c sa/ikev2/authenticators/eap_authenticator.h \
+sa/ikev2/authenticators/psk_authenticator.c sa/ikev2/authenticators/psk_authenticator.h \
+sa/ikev2/authenticators/pubkey_authenticator.c sa/ikev2/authenticators/pubkey_authenticator.h \
+sa/ikev2/tasks/child_create.c sa/ikev2/tasks/child_create.h \
+sa/ikev2/tasks/child_delete.c sa/ikev2/tasks/child_delete.h \
+sa/ikev2/tasks/child_rekey.c sa/ikev2/tasks/child_rekey.h \
+sa/ikev2/tasks/ike_auth.c sa/ikev2/tasks/ike_auth.h \
+sa/ikev2/tasks/ike_cert_pre.c sa/ikev2/tasks/ike_cert_pre.h \
+sa/ikev2/tasks/ike_cert_post.c sa/ikev2/tasks/ike_cert_post.h \
+sa/ikev2/tasks/ike_config.c sa/ikev2/tasks/ike_config.h \
+sa/ikev2/tasks/ike_delete.c sa/ikev2/tasks/ike_delete.h \
+sa/ikev2/tasks/ike_dpd.c sa/ikev2/tasks/ike_dpd.h \
+sa/ikev2/tasks/ike_init.c sa/ikev2/tasks/ike_init.h \
+sa/ikev2/tasks/ike_natd.c sa/ikev2/tasks/ike_natd.h \
+sa/ikev2/tasks/ike_mobike.c sa/ikev2/tasks/ike_mobike.h \
+sa/ikev2/tasks/ike_rekey.c sa/ikev2/tasks/ike_rekey.h \
+sa/ikev2/tasks/ike_reauth.c sa/ikev2/tasks/ike_reauth.h \
+sa/ikev2/tasks/ike_auth_lifetime.c sa/ikev2/tasks/ike_auth_lifetime.h \
+sa/ikev2/tasks/ike_vendor.c sa/ikev2/tasks/ike_vendor.h
+
+LOCAL_SRC_FILES += \
+sa/ikev1/keymat_v1.c sa/ikev1/keymat_v1.h \
+sa/ikev1/task_manager_v1.c sa/ikev1/task_manager_v1.h \
+sa/ikev1/authenticators/psk_v1_authenticator.c sa/ikev1/authenticators/psk_v1_authenticator.h \
+sa/ikev1/authenticators/pubkey_v1_authenticator.c sa/ikev1/authenticators/pubkey_v1_authenticator.h \
+sa/ikev1/authenticators/hybrid_authenticator.c sa/ikev1/authenticators/hybrid_authenticator.h \
+sa/ikev1/phase1.c sa/ikev1/phase1.h \
+sa/ikev1/tasks/main_mode.c sa/ikev1/tasks/main_mode.h \
+sa/ikev1/tasks/aggressive_mode.c sa/ikev1/tasks/aggressive_mode.h \
+sa/ikev1/tasks/informational.c sa/ikev1/tasks/informational.h \
+sa/ikev1/tasks/isakmp_cert_pre.c sa/ikev1/tasks/isakmp_cert_pre.h \
+sa/ikev1/tasks/isakmp_cert_post.c sa/ikev1/tasks/isakmp_cert_post.h \
+sa/ikev1/tasks/isakmp_natd.c sa/ikev1/tasks/isakmp_natd.h \
+sa/ikev1/tasks/isakmp_vendor.c sa/ikev1/tasks/isakmp_vendor.h \
+sa/ikev1/tasks/isakmp_delete.c sa/ikev1/tasks/isakmp_delete.h \
+sa/ikev1/tasks/isakmp_dpd.c sa/ikev1/tasks/isakmp_dpd.h \
+sa/ikev1/tasks/xauth.c sa/ikev1/tasks/xauth.h \
+sa/ikev1/tasks/quick_mode.c sa/ikev1/tasks/quick_mode.h \
+sa/ikev1/tasks/quick_delete.c sa/ikev1/tasks/quick_delete.h \
+sa/ikev1/tasks/mode_config.c sa/ikev1/tasks/mode_config.h \
+processing/jobs/dpd_timeout_job.c processing/jobs/dpd_timeout_job.h \
+processing/jobs/adopt_children_job.c processing/jobs/adopt_children_job.h
# adding the plugin source files
@@ -98,6 +130,11 @@ LOCAL_C_INCLUDES += frameworks/base/cmds/keystore
LOCAL_SHARED_LIBRARIES += libcutils
endif
+LOCAL_SRC_FILES += $(call add_plugin, android-log)
+ifneq ($(call plugin_enabled, android-log),)
+LOCAL_LDLIBS += -llog
+endif
+
LOCAL_SRC_FILES += $(call add_plugin, attr)
LOCAL_SRC_FILES += $(call add_plugin, eap-aka)
@@ -137,14 +174,32 @@ LOCAL_SRC_FILES += $(addprefix ../libsimaka/, \
)
endif
+LOCAL_SRC_FILES += $(call add_plugin, eap-tls)
+
+LOCAL_SRC_FILES += $(call add_plugin, eap-ttls)
+ifneq ($(call plugin_enabled, eap-ttls),)
+# for radius_message.h
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../libradius/
+endif
+
+LOCAL_SRC_FILES += $(call add_plugin, eap-peap)
+
+# adding libtls if any of the three plugins above is enabled
+ifneq ($(or $(call plugin_enabled, eap-tls), $(call plugin_enabled, eap-ttls), $(call plugin_enabled, eap-peap)),)
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../libtls/
+LOCAL_SRC_FILES += $(addprefix ../libtls/, \
+ tls_protection.c tls_compression.c tls_fragmentation.c tls_alert.c \
+ tls_crypto.c tls_prf.c tls_socket.c tls_eap.c tls_cache.c tls_peer.c \
+ tls_server.c tls.c \
+ )
+endif
+
LOCAL_SRC_FILES += $(call add_plugin, load-tester)
LOCAL_SRC_FILES += $(call add_plugin, socket-default)
LOCAL_SRC_FILES += $(call add_plugin, socket-dynamic)
-LOCAL_SRC_FILES += $(call add_plugin, socket-raw)
-
LOCAL_SRC_FILES += $(call add_plugin, stroke)
ifneq ($(call plugin_enabled, stroke),)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../stroke/
@@ -160,8 +215,7 @@ LOCAL_C_INCLUDES += \
$(strongswan_PATH)/src/libstrongswan \
$(strongswan_PATH)/src/libtncif
-LOCAL_CFLAGS := $(strongswan_CFLAGS) \
- -DPLUGINS='"$(strongswan_CHARON_PLUGINS)"'
+LOCAL_CFLAGS := $(strongswan_CFLAGS)
LOCAL_MODULE := libcharon
diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am
index b86bd428c..56192bf0e 100644
--- a/src/libcharon/Makefile.am
+++ b/src/libcharon/Makefile.am
@@ -3,6 +3,7 @@ ipseclib_LTLIBRARIES = libcharon.la
libcharon_la_SOURCES = \
bus/bus.c bus/bus.h \
bus/listeners/listener.h \
+bus/listeners/logger.h \
bus/listeners/file_logger.c bus/listeners/file_logger.h \
bus/listeners/sys_logger.c bus/listeners/sys_logger.h \
config/backend_manager.c config/backend_manager.h config/backend.h \
@@ -38,9 +39,10 @@ encoding/payloads/transform_substructure.c encoding/payloads/transform_substruct
encoding/payloads/ts_payload.c encoding/payloads/ts_payload.h \
encoding/payloads/unknown_payload.c encoding/payloads/unknown_payload.h \
encoding/payloads/vendor_id_payload.c encoding/payloads/vendor_id_payload.h \
+encoding/payloads/hash_payload.c encoding/payloads/hash_payload.h \
kernel/kernel_handler.c kernel/kernel_handler.h \
network/receiver.c network/receiver.h network/sender.c network/sender.h \
-network/packet.c network/packet.h network/socket.c network/socket.h \
+network/socket.c network/socket.h \
network/socket_manager.c network/socket_manager.h \
processing/jobs/acquire_job.c processing/jobs/acquire_job.h \
processing/jobs/delete_child_sa_job.c processing/jobs/delete_child_sa_job.h \
@@ -50,43 +52,78 @@ processing/jobs/process_message_job.c processing/jobs/process_message_job.h \
processing/jobs/rekey_child_sa_job.c processing/jobs/rekey_child_sa_job.h \
processing/jobs/rekey_ike_sa_job.c processing/jobs/rekey_ike_sa_job.h \
processing/jobs/retransmit_job.c processing/jobs/retransmit_job.h \
+processing/jobs/retry_initiate_job.c processing/jobs/retry_initiate_job.h \
processing/jobs/send_dpd_job.c processing/jobs/send_dpd_job.h \
processing/jobs/send_keepalive_job.c processing/jobs/send_keepalive_job.h \
processing/jobs/start_action_job.c processing/jobs/start_action_job.h \
processing/jobs/roam_job.c processing/jobs/roam_job.h \
processing/jobs/update_sa_job.c processing/jobs/update_sa_job.h \
processing/jobs/inactivity_job.c processing/jobs/inactivity_job.h \
-sa/authenticators/authenticator.c sa/authenticators/authenticator.h \
-sa/authenticators/eap_authenticator.c sa/authenticators/eap_authenticator.h \
-sa/authenticators/eap/eap_method.c sa/authenticators/eap/eap_method.h \
-sa/authenticators/eap/eap_manager.c sa/authenticators/eap/eap_manager.h \
-sa/authenticators/psk_authenticator.c sa/authenticators/psk_authenticator.h \
-sa/authenticators/pubkey_authenticator.c sa/authenticators/pubkey_authenticator.h \
+sa/eap/eap_method.c sa/eap/eap_method.h \
+sa/eap/eap_manager.c sa/eap/eap_manager.h \
+sa/xauth/xauth_method.c sa/xauth/xauth_method.h \
+sa/xauth/xauth_manager.c sa/xauth/xauth_manager.h \
+sa/authenticator.c sa/authenticator.h \
sa/child_sa.c sa/child_sa.h \
sa/ike_sa.c sa/ike_sa.h \
sa/ike_sa_id.c sa/ike_sa_id.h \
+sa/keymat.h sa/keymat.c \
sa/ike_sa_manager.c sa/ike_sa_manager.h \
-sa/task_manager.c sa/task_manager.h \
-sa/keymat.c sa/keymat.h \
+sa/task_manager.h sa/task_manager.c \
sa/shunt_manager.c sa/shunt_manager.h \
sa/trap_manager.c sa/trap_manager.h \
-sa/tasks/child_create.c sa/tasks/child_create.h \
-sa/tasks/child_delete.c sa/tasks/child_delete.h \
-sa/tasks/child_rekey.c sa/tasks/child_rekey.h \
-sa/tasks/ike_auth.c sa/tasks/ike_auth.h \
-sa/tasks/ike_cert_pre.c sa/tasks/ike_cert_pre.h \
-sa/tasks/ike_cert_post.c sa/tasks/ike_cert_post.h \
-sa/tasks/ike_config.c sa/tasks/ike_config.h \
-sa/tasks/ike_delete.c sa/tasks/ike_delete.h \
-sa/tasks/ike_dpd.c sa/tasks/ike_dpd.h \
-sa/tasks/ike_init.c sa/tasks/ike_init.h \
-sa/tasks/ike_natd.c sa/tasks/ike_natd.h \
-sa/tasks/ike_mobike.c sa/tasks/ike_mobike.h \
-sa/tasks/ike_rekey.c sa/tasks/ike_rekey.h \
-sa/tasks/ike_reauth.c sa/tasks/ike_reauth.h \
-sa/tasks/ike_auth_lifetime.c sa/tasks/ike_auth_lifetime.h \
-sa/tasks/ike_vendor.c sa/tasks/ike_vendor.h \
-sa/tasks/task.c sa/tasks/task.h
+sa/task.c sa/task.h
+
+if USE_IKEV2
+libcharon_la_SOURCES += \
+sa/ikev2/keymat_v2.c sa/ikev2/keymat_v2.h \
+sa/ikev2/task_manager_v2.c sa/ikev2/task_manager_v2.h \
+sa/ikev2/authenticators/eap_authenticator.c sa/ikev2/authenticators/eap_authenticator.h \
+sa/ikev2/authenticators/psk_authenticator.c sa/ikev2/authenticators/psk_authenticator.h \
+sa/ikev2/authenticators/pubkey_authenticator.c sa/ikev2/authenticators/pubkey_authenticator.h \
+sa/ikev2/tasks/child_create.c sa/ikev2/tasks/child_create.h \
+sa/ikev2/tasks/child_delete.c sa/ikev2/tasks/child_delete.h \
+sa/ikev2/tasks/child_rekey.c sa/ikev2/tasks/child_rekey.h \
+sa/ikev2/tasks/ike_auth.c sa/ikev2/tasks/ike_auth.h \
+sa/ikev2/tasks/ike_cert_pre.c sa/ikev2/tasks/ike_cert_pre.h \
+sa/ikev2/tasks/ike_cert_post.c sa/ikev2/tasks/ike_cert_post.h \
+sa/ikev2/tasks/ike_config.c sa/ikev2/tasks/ike_config.h \
+sa/ikev2/tasks/ike_delete.c sa/ikev2/tasks/ike_delete.h \
+sa/ikev2/tasks/ike_dpd.c sa/ikev2/tasks/ike_dpd.h \
+sa/ikev2/tasks/ike_init.c sa/ikev2/tasks/ike_init.h \
+sa/ikev2/tasks/ike_natd.c sa/ikev2/tasks/ike_natd.h \
+sa/ikev2/tasks/ike_mobike.c sa/ikev2/tasks/ike_mobike.h \
+sa/ikev2/tasks/ike_rekey.c sa/ikev2/tasks/ike_rekey.h \
+sa/ikev2/tasks/ike_reauth.c sa/ikev2/tasks/ike_reauth.h \
+sa/ikev2/tasks/ike_auth_lifetime.c sa/ikev2/tasks/ike_auth_lifetime.h \
+sa/ikev2/tasks/ike_vendor.c sa/ikev2/tasks/ike_vendor.h
+endif
+
+if USE_IKEV1
+libcharon_la_SOURCES += \
+sa/ikev1/keymat_v1.c sa/ikev1/keymat_v1.h \
+sa/ikev1/task_manager_v1.c sa/ikev1/task_manager_v1.h \
+sa/ikev1/authenticators/psk_v1_authenticator.c sa/ikev1/authenticators/psk_v1_authenticator.h \
+sa/ikev1/authenticators/pubkey_v1_authenticator.c sa/ikev1/authenticators/pubkey_v1_authenticator.h \
+sa/ikev1/authenticators/hybrid_authenticator.c sa/ikev1/authenticators/hybrid_authenticator.h \
+sa/ikev1/phase1.c sa/ikev1/phase1.h \
+sa/ikev1/tasks/main_mode.c sa/ikev1/tasks/main_mode.h \
+sa/ikev1/tasks/aggressive_mode.c sa/ikev1/tasks/aggressive_mode.h \
+sa/ikev1/tasks/informational.c sa/ikev1/tasks/informational.h \
+sa/ikev1/tasks/isakmp_cert_pre.c sa/ikev1/tasks/isakmp_cert_pre.h \
+sa/ikev1/tasks/isakmp_cert_post.c sa/ikev1/tasks/isakmp_cert_post.h \
+sa/ikev1/tasks/isakmp_natd.c sa/ikev1/tasks/isakmp_natd.h \
+sa/ikev1/tasks/isakmp_vendor.c sa/ikev1/tasks/isakmp_vendor.h \
+sa/ikev1/tasks/isakmp_delete.c sa/ikev1/tasks/isakmp_delete.h \
+sa/ikev1/tasks/isakmp_dpd.c sa/ikev1/tasks/isakmp_dpd.h \
+sa/ikev1/tasks/xauth.c sa/ikev1/tasks/xauth.h \
+sa/ikev1/tasks/quick_mode.c sa/ikev1/tasks/quick_mode.h \
+sa/ikev1/tasks/quick_delete.c sa/ikev1/tasks/quick_delete.h \
+sa/ikev1/tasks/mode_config.c sa/ikev1/tasks/mode_config.h \
+processing/jobs/dpd_timeout_job.c processing/jobs/dpd_timeout_job.h \
+processing/jobs/adopt_children_job.c processing/jobs/adopt_children_job.h
+endif
+
daemon.lo : $(top_builddir)/config.status
@@ -98,8 +135,7 @@ INCLUDES = \
AM_CFLAGS = \
-DIPSEC_DIR=\"${ipsecdir}\" \
- -DIPSEC_PIDDIR=\"${piddir}\" \
- -DPLUGINS=\""${libcharon_plugins}\""
+ -DIPSEC_PIDDIR=\"${piddir}\"
libcharon_la_LIBADD = -lm $(PTHREADLIB) $(DLLIB) $(SOCKLIB)
@@ -112,13 +148,9 @@ if USE_ME
libcharon_la_SOURCES += encoding/payloads/endpoint_notify.c encoding/payloads/endpoint_notify.h \
processing/jobs/initiate_mediation_job.c processing/jobs/initiate_mediation_job.h \
processing/jobs/mediation_job.c processing/jobs/mediation_job.h \
- sa/connect_manager.c sa/connect_manager.h \
- sa/mediation_manager.c sa/mediation_manager.h \
- sa/tasks/ike_me.c sa/tasks/ike_me.h
-endif
-
-if USE_LIBCAP
- libcharon_la_LIBADD += -lcap
+ sa/ikev2/connect_manager.c sa/ikev2/connect_manager.h \
+ sa/ikev2/mediation_manager.c sa/ikev2/mediation_manager.h \
+ sa/ikev2/tasks/ike_me.c sa/ikev2/tasks/ike_me.h
endif
# build optional plugins
@@ -144,13 +176,6 @@ if MONOLITHIC
endif
endif
-if USE_SOCKET_RAW
- SUBDIRS += plugins/socket_raw
-if MONOLITHIC
- libcharon_la_LIBADD += plugins/socket_raw/libstrongswan-socket-raw.la
-endif
-endif
-
if USE_SOCKET_DYNAMIC
SUBDIRS += plugins/socket_dynamic
if MONOLITHIC
@@ -284,6 +309,13 @@ if MONOLITHIC
endif
endif
+if USE_EAP_DYNAMIC
+ SUBDIRS += plugins/eap_dynamic
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/eap_dynamic/libstrongswan-eap-dynamic.la
+endif
+endif
+
if USE_EAP_RADIUS
SUBDIRS += plugins/eap_radius
if MONOLITHIC
@@ -410,13 +442,6 @@ if MONOLITHIC
endif
endif
-if USE_NM
- SUBDIRS += plugins/nm
-if MONOLITHIC
- libcharon_la_LIBADD += plugins/nm/libstrongswan-nm.la
-endif
-endif
-
if USE_DHCP
SUBDIRS += plugins/dhcp
if MONOLITHIC
@@ -431,6 +456,13 @@ if MONOLITHIC
endif
endif
+if USE_ANDROID_LOG
+ SUBDIRS += plugins/android_log
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/android_log/libstrongswan-android-log.la
+endif
+endif
+
if USE_MAEMO
SUBDIRS += plugins/maemo
if MONOLITHIC
@@ -497,7 +529,14 @@ endif
if USE_ADDRBLOCK
SUBDIRS += plugins/addrblock
if MONOLITHIC
- libcharon_la_LIBADD += plugins/uci/libstrongswan-addrblock.la
+ libcharon_la_LIBADD += plugins/addrblock/libstrongswan-addrblock.la
+endif
+endif
+
+if USE_UNITY
+ SUBDIRS += plugins/unity
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/unity/libstrongswan-unity.la
endif
endif
@@ -508,3 +547,23 @@ if MONOLITHIC
endif
endif
+if USE_XAUTH_GENERIC
+ SUBDIRS += plugins/xauth_generic
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/xauth_generic/libstrongswan-xauth-generic.la
+endif
+endif
+
+if USE_XAUTH_EAP
+ SUBDIRS += plugins/xauth_eap
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/xauth_eap/libstrongswan-xauth-eap.la
+endif
+endif
+
+if USE_XAUTH_PAM
+ SUBDIRS += plugins/xauth_pam
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/xauth_pam/libstrongswan-xauth-pam.la
+endif
+endif
diff --git a/src/libcharon/Makefile.in b/src/libcharon/Makefile.in
index ccbd4add2..3a9239af3 100644
--- a/src/libcharon/Makefile.in
+++ b/src/libcharon/Makefile.in
@@ -34,121 +34,174 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
+@USE_IKEV2_TRUE@am__append_1 = \
+@USE_IKEV2_TRUE@sa/ikev2/keymat_v2.c sa/ikev2/keymat_v2.h \
+@USE_IKEV2_TRUE@sa/ikev2/task_manager_v2.c sa/ikev2/task_manager_v2.h \
+@USE_IKEV2_TRUE@sa/ikev2/authenticators/eap_authenticator.c sa/ikev2/authenticators/eap_authenticator.h \
+@USE_IKEV2_TRUE@sa/ikev2/authenticators/psk_authenticator.c sa/ikev2/authenticators/psk_authenticator.h \
+@USE_IKEV2_TRUE@sa/ikev2/authenticators/pubkey_authenticator.c sa/ikev2/authenticators/pubkey_authenticator.h \
+@USE_IKEV2_TRUE@sa/ikev2/tasks/child_create.c sa/ikev2/tasks/child_create.h \
+@USE_IKEV2_TRUE@sa/ikev2/tasks/child_delete.c sa/ikev2/tasks/child_delete.h \
+@USE_IKEV2_TRUE@sa/ikev2/tasks/child_rekey.c sa/ikev2/tasks/child_rekey.h \
+@USE_IKEV2_TRUE@sa/ikev2/tasks/ike_auth.c sa/ikev2/tasks/ike_auth.h \
+@USE_IKEV2_TRUE@sa/ikev2/tasks/ike_cert_pre.c sa/ikev2/tasks/ike_cert_pre.h \
+@USE_IKEV2_TRUE@sa/ikev2/tasks/ike_cert_post.c sa/ikev2/tasks/ike_cert_post.h \
+@USE_IKEV2_TRUE@sa/ikev2/tasks/ike_config.c sa/ikev2/tasks/ike_config.h \
+@USE_IKEV2_TRUE@sa/ikev2/tasks/ike_delete.c sa/ikev2/tasks/ike_delete.h \
+@USE_IKEV2_TRUE@sa/ikev2/tasks/ike_dpd.c sa/ikev2/tasks/ike_dpd.h \
+@USE_IKEV2_TRUE@sa/ikev2/tasks/ike_init.c sa/ikev2/tasks/ike_init.h \
+@USE_IKEV2_TRUE@sa/ikev2/tasks/ike_natd.c sa/ikev2/tasks/ike_natd.h \
+@USE_IKEV2_TRUE@sa/ikev2/tasks/ike_mobike.c sa/ikev2/tasks/ike_mobike.h \
+@USE_IKEV2_TRUE@sa/ikev2/tasks/ike_rekey.c sa/ikev2/tasks/ike_rekey.h \
+@USE_IKEV2_TRUE@sa/ikev2/tasks/ike_reauth.c sa/ikev2/tasks/ike_reauth.h \
+@USE_IKEV2_TRUE@sa/ikev2/tasks/ike_auth_lifetime.c sa/ikev2/tasks/ike_auth_lifetime.h \
+@USE_IKEV2_TRUE@sa/ikev2/tasks/ike_vendor.c sa/ikev2/tasks/ike_vendor.h
+
+@USE_IKEV1_TRUE@am__append_2 = \
+@USE_IKEV1_TRUE@sa/ikev1/keymat_v1.c sa/ikev1/keymat_v1.h \
+@USE_IKEV1_TRUE@sa/ikev1/task_manager_v1.c sa/ikev1/task_manager_v1.h \
+@USE_IKEV1_TRUE@sa/ikev1/authenticators/psk_v1_authenticator.c sa/ikev1/authenticators/psk_v1_authenticator.h \
+@USE_IKEV1_TRUE@sa/ikev1/authenticators/pubkey_v1_authenticator.c sa/ikev1/authenticators/pubkey_v1_authenticator.h \
+@USE_IKEV1_TRUE@sa/ikev1/authenticators/hybrid_authenticator.c sa/ikev1/authenticators/hybrid_authenticator.h \
+@USE_IKEV1_TRUE@sa/ikev1/phase1.c sa/ikev1/phase1.h \
+@USE_IKEV1_TRUE@sa/ikev1/tasks/main_mode.c sa/ikev1/tasks/main_mode.h \
+@USE_IKEV1_TRUE@sa/ikev1/tasks/aggressive_mode.c sa/ikev1/tasks/aggressive_mode.h \
+@USE_IKEV1_TRUE@sa/ikev1/tasks/informational.c sa/ikev1/tasks/informational.h \
+@USE_IKEV1_TRUE@sa/ikev1/tasks/isakmp_cert_pre.c sa/ikev1/tasks/isakmp_cert_pre.h \
+@USE_IKEV1_TRUE@sa/ikev1/tasks/isakmp_cert_post.c sa/ikev1/tasks/isakmp_cert_post.h \
+@USE_IKEV1_TRUE@sa/ikev1/tasks/isakmp_natd.c sa/ikev1/tasks/isakmp_natd.h \
+@USE_IKEV1_TRUE@sa/ikev1/tasks/isakmp_vendor.c sa/ikev1/tasks/isakmp_vendor.h \
+@USE_IKEV1_TRUE@sa/ikev1/tasks/isakmp_delete.c sa/ikev1/tasks/isakmp_delete.h \
+@USE_IKEV1_TRUE@sa/ikev1/tasks/isakmp_dpd.c sa/ikev1/tasks/isakmp_dpd.h \
+@USE_IKEV1_TRUE@sa/ikev1/tasks/xauth.c sa/ikev1/tasks/xauth.h \
+@USE_IKEV1_TRUE@sa/ikev1/tasks/quick_mode.c sa/ikev1/tasks/quick_mode.h \
+@USE_IKEV1_TRUE@sa/ikev1/tasks/quick_delete.c sa/ikev1/tasks/quick_delete.h \
+@USE_IKEV1_TRUE@sa/ikev1/tasks/mode_config.c sa/ikev1/tasks/mode_config.h \
+@USE_IKEV1_TRUE@processing/jobs/dpd_timeout_job.c processing/jobs/dpd_timeout_job.h \
+@USE_IKEV1_TRUE@processing/jobs/adopt_children_job.c processing/jobs/adopt_children_job.h
+
# compile options
#################
-@USE_ME_TRUE@am__append_1 = encoding/payloads/endpoint_notify.c encoding/payloads/endpoint_notify.h \
+@USE_ME_TRUE@am__append_3 = encoding/payloads/endpoint_notify.c encoding/payloads/endpoint_notify.h \
@USE_ME_TRUE@ processing/jobs/initiate_mediation_job.c processing/jobs/initiate_mediation_job.h \
@USE_ME_TRUE@ processing/jobs/mediation_job.c processing/jobs/mediation_job.h \
-@USE_ME_TRUE@ sa/connect_manager.c sa/connect_manager.h \
-@USE_ME_TRUE@ sa/mediation_manager.c sa/mediation_manager.h \
-@USE_ME_TRUE@ sa/tasks/ike_me.c sa/tasks/ike_me.h
-
-@USE_LIBCAP_TRUE@am__append_2 = -lcap
-@USE_LOAD_TESTER_TRUE@am__append_3 = plugins/load_tester
-@MONOLITHIC_TRUE@@USE_LOAD_TESTER_TRUE@am__append_4 = plugins/load_tester/libstrongswan-load-tester.la
-@USE_SOCKET_DEFAULT_TRUE@am__append_5 = plugins/socket_default
-@MONOLITHIC_TRUE@@USE_SOCKET_DEFAULT_TRUE@am__append_6 = plugins/socket_default/libstrongswan-socket-default.la
-@USE_SOCKET_RAW_TRUE@am__append_7 = plugins/socket_raw
-@MONOLITHIC_TRUE@@USE_SOCKET_RAW_TRUE@am__append_8 = plugins/socket_raw/libstrongswan-socket-raw.la
-@USE_SOCKET_DYNAMIC_TRUE@am__append_9 = plugins/socket_dynamic
-@MONOLITHIC_TRUE@@USE_SOCKET_DYNAMIC_TRUE@am__append_10 = plugins/socket_dynamic/libstrongswan-socket-dynamic.la
-@USE_FARP_TRUE@am__append_11 = plugins/farp
-@MONOLITHIC_TRUE@@USE_FARP_TRUE@am__append_12 = plugins/farp/libstrongswan-farp.la
-@USE_STROKE_TRUE@am__append_13 = plugins/stroke
-@MONOLITHIC_TRUE@@USE_STROKE_TRUE@am__append_14 = plugins/stroke/libstrongswan-stroke.la
-@USE_SMP_TRUE@am__append_15 = plugins/smp
-@MONOLITHIC_TRUE@@USE_SMP_TRUE@am__append_16 = plugins/smp/libstrongswan-smp.la
-@USE_SQL_TRUE@am__append_17 = plugins/sql
-@MONOLITHIC_TRUE@@USE_SQL_TRUE@am__append_18 = plugins/sql/libstrongswan-sql.la
-@USE_UPDOWN_TRUE@am__append_19 = plugins/updown
-@MONOLITHIC_TRUE@@USE_UPDOWN_TRUE@am__append_20 = plugins/updown/libstrongswan-updown.la
-@USE_EAP_IDENTITY_TRUE@am__append_21 = plugins/eap_identity
-@MONOLITHIC_TRUE@@USE_EAP_IDENTITY_TRUE@am__append_22 = plugins/eap_identity/libstrongswan-eap-identity.la
-@USE_EAP_SIM_TRUE@am__append_23 = plugins/eap_sim
-@MONOLITHIC_TRUE@@USE_EAP_SIM_TRUE@am__append_24 = plugins/eap_sim/libstrongswan-eap-sim.la
-@USE_EAP_SIM_FILE_TRUE@am__append_25 = plugins/eap_sim_file
-@MONOLITHIC_TRUE@@USE_EAP_SIM_FILE_TRUE@am__append_26 = plugins/eap_sim_file/libstrongswan-eap-sim-file.la
-@USE_EAP_SIM_PCSC_TRUE@am__append_27 = plugins/eap_sim_pcsc
-@MONOLITHIC_TRUE@@USE_EAP_SIM_PCSC_TRUE@am__append_28 = plugins/eap_sim_pcsc/libstrongswan-eap-sim-pcsc.la
-@USE_EAP_SIMAKA_SQL_TRUE@am__append_29 = plugins/eap_simaka_sql
-@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_SQL_TRUE@am__append_30 = plugins/eap_simaka_sql/libstrongswan-eap-simaka-sql.la
-@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_31 = plugins/eap_simaka_pseudonym
-@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_32 = plugins/eap_simaka_pseudonym/libstrongswan-eap-simaka-pseudonym.la
-@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_33 = plugins/eap_simaka_reauth
-@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_34 = plugins/eap_simaka_reauth/libstrongswan-eap-simaka-reauth.la
-@USE_EAP_AKA_TRUE@am__append_35 = plugins/eap_aka
-@MONOLITHIC_TRUE@@USE_EAP_AKA_TRUE@am__append_36 = plugins/eap_aka/libstrongswan-eap-aka.la
-@USE_EAP_AKA_3GPP2_TRUE@am__append_37 = plugins/eap_aka_3gpp2
-@MONOLITHIC_TRUE@@USE_EAP_AKA_3GPP2_TRUE@am__append_38 = plugins/eap_aka_3gpp2/libstrongswan-eap-aka-3gpp2.la
-@MONOLITHIC_TRUE@@USE_SIMAKA_TRUE@am__append_39 = $(top_builddir)/src/libsimaka/libsimaka.la
-@USE_EAP_MD5_TRUE@am__append_40 = plugins/eap_md5
-@MONOLITHIC_TRUE@@USE_EAP_MD5_TRUE@am__append_41 = plugins/eap_md5/libstrongswan-eap-md5.la
-@USE_EAP_GTC_TRUE@am__append_42 = plugins/eap_gtc
-@MONOLITHIC_TRUE@@USE_EAP_GTC_TRUE@am__append_43 = plugins/eap_gtc/libstrongswan-eap-gtc.la
-@USE_EAP_MSCHAPV2_TRUE@am__append_44 = plugins/eap_mschapv2
-@MONOLITHIC_TRUE@@USE_EAP_MSCHAPV2_TRUE@am__append_45 = plugins/eap_mschapv2/libstrongswan-eap-mschapv2.la
-@USE_EAP_RADIUS_TRUE@am__append_46 = plugins/eap_radius
-@MONOLITHIC_TRUE@@USE_EAP_RADIUS_TRUE@am__append_47 = plugins/eap_radius/libstrongswan-eap-radius.la
-@USE_EAP_TLS_TRUE@am__append_48 = plugins/eap_tls
-@MONOLITHIC_TRUE@@USE_EAP_TLS_TRUE@am__append_49 = plugins/eap_tls/libstrongswan-eap-tls.la
-@USE_EAP_TTLS_TRUE@am__append_50 = plugins/eap_ttls
-@MONOLITHIC_TRUE@@USE_EAP_TTLS_TRUE@am__append_51 = plugins/eap_ttls/libstrongswan-eap-ttls.la
-@USE_EAP_PEAP_TRUE@am__append_52 = plugins/eap_peap
-@MONOLITHIC_TRUE@@USE_EAP_PEAP_TRUE@am__append_53 = plugins/eap_peap/libstrongswan-eap-peap.la
-@USE_EAP_TNC_TRUE@am__append_54 = plugins/eap_tnc
-@MONOLITHIC_TRUE@@USE_EAP_TNC_TRUE@am__append_55 = plugins/eap_tnc/libstrongswan-eap-tnc.la
-@MONOLITHIC_TRUE@@USE_TLS_TRUE@am__append_56 = $(top_builddir)/src/libtls/libtls.la
-@MONOLITHIC_TRUE@@USE_RADIUS_TRUE@am__append_57 = $(top_builddir)/src/libradius/libradius.la
-@USE_TNC_IFMAP_TRUE@am__append_58 = plugins/tnc_ifmap
-@MONOLITHIC_TRUE@@USE_TNC_IFMAP_TRUE@am__append_59 = plugins/tnc_ifmap/libstrongswan-tnc-ifmap.la
-@USE_TNC_PDP_TRUE@am__append_60 = plugins/tnc_pdp
-@MONOLITHIC_TRUE@@USE_TNC_PDP_TRUE@am__append_61 = plugins/tnc_pdp/libstrongswan-tnc-pdp.la
-@USE_TNC_IMC_TRUE@am__append_62 = plugins/tnc_imc
-@MONOLITHIC_TRUE@@USE_TNC_IMC_TRUE@am__append_63 = plugins/tnc_imc/libstrongswan-tnc-imc.la
-@USE_TNC_IMV_TRUE@am__append_64 = plugins/tnc_imv
-@MONOLITHIC_TRUE@@USE_TNC_IMV_TRUE@am__append_65 = plugins/tnc_imv/libstrongswan-tnc-imv.la
-@USE_TNC_TNCCS_TRUE@am__append_66 = plugins/tnc_tnccs
-@MONOLITHIC_TRUE@@USE_TNC_TNCCS_TRUE@am__append_67 = plugins/tnc_tnccs/libstrongswan-tnc-tnccs.la
-@USE_TNCCS_11_TRUE@am__append_68 = plugins/tnccs_11
-@MONOLITHIC_TRUE@@USE_TNCCS_11_TRUE@am__append_69 = plugins/tnccs_11/libstrongswan-tnccs-11.la
-@USE_TNCCS_20_TRUE@am__append_70 = plugins/tnccs_20
-@MONOLITHIC_TRUE@@USE_TNCCS_20_TRUE@am__append_71 = plugins/tnccs_20/libstrongswan-tnccs-20.la
-@USE_TNCCS_DYNAMIC_TRUE@am__append_72 = plugins/tnccs_dynamic
-@MONOLITHIC_TRUE@@USE_TNCCS_DYNAMIC_TRUE@am__append_73 = plugins/tnccs_dynamic/libstrongswan-tnccs-dynamic.la
-@MONOLITHIC_TRUE@@USE_LIBTNCCS_TRUE@am__append_74 = $(top_builddir)/src/libtnccs/libtnccs.la
-@USE_MEDSRV_TRUE@am__append_75 = plugins/medsrv
-@MONOLITHIC_TRUE@@USE_MEDSRV_TRUE@am__append_76 = plugins/medsrv/libstrongswan-medsrv.la
-@USE_MEDCLI_TRUE@am__append_77 = plugins/medcli
-@MONOLITHIC_TRUE@@USE_MEDCLI_TRUE@am__append_78 = plugins/medcli/libstrongswan-medcli.la
-@USE_NM_TRUE@am__append_79 = plugins/nm
-@MONOLITHIC_TRUE@@USE_NM_TRUE@am__append_80 = plugins/nm/libstrongswan-nm.la
-@USE_DHCP_TRUE@am__append_81 = plugins/dhcp
-@MONOLITHIC_TRUE@@USE_DHCP_TRUE@am__append_82 = plugins/dhcp/libstrongswan-dhcp.la
-@USE_ANDROID_TRUE@am__append_83 = plugins/android
-@MONOLITHIC_TRUE@@USE_ANDROID_TRUE@am__append_84 = plugins/android/libstrongswan-android.la
-@USE_MAEMO_TRUE@am__append_85 = plugins/maemo
-@MONOLITHIC_TRUE@@USE_MAEMO_TRUE@am__append_86 = plugins/maemo/libstrongswan-maemo.la
-@USE_HA_TRUE@am__append_87 = plugins/ha
-@MONOLITHIC_TRUE@@USE_HA_TRUE@am__append_88 = plugins/ha/libstrongswan-ha.la
-@USE_WHITELIST_TRUE@am__append_89 = plugins/whitelist
-@MONOLITHIC_TRUE@@USE_WHITELIST_TRUE@am__append_90 = plugins/whitelist/libstrongswan-whitelist.la
-@USE_CERTEXPIRE_TRUE@am__append_91 = plugins/certexpire
-@MONOLITHIC_TRUE@@USE_CERTEXPIRE_TRUE@am__append_92 = plugins/certexpire/libstrongswan-certexpire.la
-@USE_LED_TRUE@am__append_93 = plugins/led
-@MONOLITHIC_TRUE@@USE_LED_TRUE@am__append_94 = plugins/led/libstrongswan-led.la
-@USE_DUPLICHECK_TRUE@am__append_95 = plugins/duplicheck
-@MONOLITHIC_TRUE@@USE_DUPLICHECK_TRUE@am__append_96 = plugins/duplicheck/libstrongswan-duplicheck.la
-@USE_COUPLING_TRUE@am__append_97 = plugins/coupling
-@MONOLITHIC_TRUE@@USE_COUPLING_TRUE@am__append_98 = plugins/coupling/libstrongswan-coupling.la
-@USE_RADATTR_TRUE@am__append_99 = plugins/radattr
-@MONOLITHIC_TRUE@@USE_RADATTR_TRUE@am__append_100 = plugins/radattr/libstrongswan-radattr.la
-@USE_UCI_TRUE@am__append_101 = plugins/uci
-@MONOLITHIC_TRUE@@USE_UCI_TRUE@am__append_102 = plugins/uci/libstrongswan-uci.la
-@USE_ADDRBLOCK_TRUE@am__append_103 = plugins/addrblock
-@MONOLITHIC_TRUE@@USE_ADDRBLOCK_TRUE@am__append_104 = plugins/uci/libstrongswan-addrblock.la
-@USE_UNIT_TESTS_TRUE@am__append_105 = plugins/unit_tester
-@MONOLITHIC_TRUE@@USE_UNIT_TESTS_TRUE@am__append_106 = plugins/unit_tester/libstrongswan-unit-tester.la
+@USE_ME_TRUE@ sa/ikev2/connect_manager.c sa/ikev2/connect_manager.h \
+@USE_ME_TRUE@ sa/ikev2/mediation_manager.c sa/ikev2/mediation_manager.h \
+@USE_ME_TRUE@ sa/ikev2/tasks/ike_me.c sa/ikev2/tasks/ike_me.h
+
+@USE_LOAD_TESTER_TRUE@am__append_4 = plugins/load_tester
+@MONOLITHIC_TRUE@@USE_LOAD_TESTER_TRUE@am__append_5 = plugins/load_tester/libstrongswan-load-tester.la
+@USE_SOCKET_DEFAULT_TRUE@am__append_6 = plugins/socket_default
+@MONOLITHIC_TRUE@@USE_SOCKET_DEFAULT_TRUE@am__append_7 = plugins/socket_default/libstrongswan-socket-default.la
+@USE_SOCKET_DYNAMIC_TRUE@am__append_8 = plugins/socket_dynamic
+@MONOLITHIC_TRUE@@USE_SOCKET_DYNAMIC_TRUE@am__append_9 = plugins/socket_dynamic/libstrongswan-socket-dynamic.la
+@USE_FARP_TRUE@am__append_10 = plugins/farp
+@MONOLITHIC_TRUE@@USE_FARP_TRUE@am__append_11 = plugins/farp/libstrongswan-farp.la
+@USE_STROKE_TRUE@am__append_12 = plugins/stroke
+@MONOLITHIC_TRUE@@USE_STROKE_TRUE@am__append_13 = plugins/stroke/libstrongswan-stroke.la
+@USE_SMP_TRUE@am__append_14 = plugins/smp
+@MONOLITHIC_TRUE@@USE_SMP_TRUE@am__append_15 = plugins/smp/libstrongswan-smp.la
+@USE_SQL_TRUE@am__append_16 = plugins/sql
+@MONOLITHIC_TRUE@@USE_SQL_TRUE@am__append_17 = plugins/sql/libstrongswan-sql.la
+@USE_UPDOWN_TRUE@am__append_18 = plugins/updown
+@MONOLITHIC_TRUE@@USE_UPDOWN_TRUE@am__append_19 = plugins/updown/libstrongswan-updown.la
+@USE_EAP_IDENTITY_TRUE@am__append_20 = plugins/eap_identity
+@MONOLITHIC_TRUE@@USE_EAP_IDENTITY_TRUE@am__append_21 = plugins/eap_identity/libstrongswan-eap-identity.la
+@USE_EAP_SIM_TRUE@am__append_22 = plugins/eap_sim
+@MONOLITHIC_TRUE@@USE_EAP_SIM_TRUE@am__append_23 = plugins/eap_sim/libstrongswan-eap-sim.la
+@USE_EAP_SIM_FILE_TRUE@am__append_24 = plugins/eap_sim_file
+@MONOLITHIC_TRUE@@USE_EAP_SIM_FILE_TRUE@am__append_25 = plugins/eap_sim_file/libstrongswan-eap-sim-file.la
+@USE_EAP_SIM_PCSC_TRUE@am__append_26 = plugins/eap_sim_pcsc
+@MONOLITHIC_TRUE@@USE_EAP_SIM_PCSC_TRUE@am__append_27 = plugins/eap_sim_pcsc/libstrongswan-eap-sim-pcsc.la
+@USE_EAP_SIMAKA_SQL_TRUE@am__append_28 = plugins/eap_simaka_sql
+@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_SQL_TRUE@am__append_29 = plugins/eap_simaka_sql/libstrongswan-eap-simaka-sql.la
+@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_30 = plugins/eap_simaka_pseudonym
+@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_31 = plugins/eap_simaka_pseudonym/libstrongswan-eap-simaka-pseudonym.la
+@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_32 = plugins/eap_simaka_reauth
+@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_33 = plugins/eap_simaka_reauth/libstrongswan-eap-simaka-reauth.la
+@USE_EAP_AKA_TRUE@am__append_34 = plugins/eap_aka
+@MONOLITHIC_TRUE@@USE_EAP_AKA_TRUE@am__append_35 = plugins/eap_aka/libstrongswan-eap-aka.la
+@USE_EAP_AKA_3GPP2_TRUE@am__append_36 = plugins/eap_aka_3gpp2
+@MONOLITHIC_TRUE@@USE_EAP_AKA_3GPP2_TRUE@am__append_37 = plugins/eap_aka_3gpp2/libstrongswan-eap-aka-3gpp2.la
+@MONOLITHIC_TRUE@@USE_SIMAKA_TRUE@am__append_38 = $(top_builddir)/src/libsimaka/libsimaka.la
+@USE_EAP_MD5_TRUE@am__append_39 = plugins/eap_md5
+@MONOLITHIC_TRUE@@USE_EAP_MD5_TRUE@am__append_40 = plugins/eap_md5/libstrongswan-eap-md5.la
+@USE_EAP_GTC_TRUE@am__append_41 = plugins/eap_gtc
+@MONOLITHIC_TRUE@@USE_EAP_GTC_TRUE@am__append_42 = plugins/eap_gtc/libstrongswan-eap-gtc.la
+@USE_EAP_MSCHAPV2_TRUE@am__append_43 = plugins/eap_mschapv2
+@MONOLITHIC_TRUE@@USE_EAP_MSCHAPV2_TRUE@am__append_44 = plugins/eap_mschapv2/libstrongswan-eap-mschapv2.la
+@USE_EAP_DYNAMIC_TRUE@am__append_45 = plugins/eap_dynamic
+@MONOLITHIC_TRUE@@USE_EAP_DYNAMIC_TRUE@am__append_46 = plugins/eap_dynamic/libstrongswan-eap-dynamic.la
+@USE_EAP_RADIUS_TRUE@am__append_47 = plugins/eap_radius
+@MONOLITHIC_TRUE@@USE_EAP_RADIUS_TRUE@am__append_48 = plugins/eap_radius/libstrongswan-eap-radius.la
+@USE_EAP_TLS_TRUE@am__append_49 = plugins/eap_tls
+@MONOLITHIC_TRUE@@USE_EAP_TLS_TRUE@am__append_50 = plugins/eap_tls/libstrongswan-eap-tls.la
+@USE_EAP_TTLS_TRUE@am__append_51 = plugins/eap_ttls
+@MONOLITHIC_TRUE@@USE_EAP_TTLS_TRUE@am__append_52 = plugins/eap_ttls/libstrongswan-eap-ttls.la
+@USE_EAP_PEAP_TRUE@am__append_53 = plugins/eap_peap
+@MONOLITHIC_TRUE@@USE_EAP_PEAP_TRUE@am__append_54 = plugins/eap_peap/libstrongswan-eap-peap.la
+@USE_EAP_TNC_TRUE@am__append_55 = plugins/eap_tnc
+@MONOLITHIC_TRUE@@USE_EAP_TNC_TRUE@am__append_56 = plugins/eap_tnc/libstrongswan-eap-tnc.la
+@MONOLITHIC_TRUE@@USE_TLS_TRUE@am__append_57 = $(top_builddir)/src/libtls/libtls.la
+@MONOLITHIC_TRUE@@USE_RADIUS_TRUE@am__append_58 = $(top_builddir)/src/libradius/libradius.la
+@USE_TNC_IFMAP_TRUE@am__append_59 = plugins/tnc_ifmap
+@MONOLITHIC_TRUE@@USE_TNC_IFMAP_TRUE@am__append_60 = plugins/tnc_ifmap/libstrongswan-tnc-ifmap.la
+@USE_TNC_PDP_TRUE@am__append_61 = plugins/tnc_pdp
+@MONOLITHIC_TRUE@@USE_TNC_PDP_TRUE@am__append_62 = plugins/tnc_pdp/libstrongswan-tnc-pdp.la
+@USE_TNC_IMC_TRUE@am__append_63 = plugins/tnc_imc
+@MONOLITHIC_TRUE@@USE_TNC_IMC_TRUE@am__append_64 = plugins/tnc_imc/libstrongswan-tnc-imc.la
+@USE_TNC_IMV_TRUE@am__append_65 = plugins/tnc_imv
+@MONOLITHIC_TRUE@@USE_TNC_IMV_TRUE@am__append_66 = plugins/tnc_imv/libstrongswan-tnc-imv.la
+@USE_TNC_TNCCS_TRUE@am__append_67 = plugins/tnc_tnccs
+@MONOLITHIC_TRUE@@USE_TNC_TNCCS_TRUE@am__append_68 = plugins/tnc_tnccs/libstrongswan-tnc-tnccs.la
+@USE_TNCCS_11_TRUE@am__append_69 = plugins/tnccs_11
+@MONOLITHIC_TRUE@@USE_TNCCS_11_TRUE@am__append_70 = plugins/tnccs_11/libstrongswan-tnccs-11.la
+@USE_TNCCS_20_TRUE@am__append_71 = plugins/tnccs_20
+@MONOLITHIC_TRUE@@USE_TNCCS_20_TRUE@am__append_72 = plugins/tnccs_20/libstrongswan-tnccs-20.la
+@USE_TNCCS_DYNAMIC_TRUE@am__append_73 = plugins/tnccs_dynamic
+@MONOLITHIC_TRUE@@USE_TNCCS_DYNAMIC_TRUE@am__append_74 = plugins/tnccs_dynamic/libstrongswan-tnccs-dynamic.la
+@MONOLITHIC_TRUE@@USE_LIBTNCCS_TRUE@am__append_75 = $(top_builddir)/src/libtnccs/libtnccs.la
+@USE_MEDSRV_TRUE@am__append_76 = plugins/medsrv
+@MONOLITHIC_TRUE@@USE_MEDSRV_TRUE@am__append_77 = plugins/medsrv/libstrongswan-medsrv.la
+@USE_MEDCLI_TRUE@am__append_78 = plugins/medcli
+@MONOLITHIC_TRUE@@USE_MEDCLI_TRUE@am__append_79 = plugins/medcli/libstrongswan-medcli.la
+@USE_DHCP_TRUE@am__append_80 = plugins/dhcp
+@MONOLITHIC_TRUE@@USE_DHCP_TRUE@am__append_81 = plugins/dhcp/libstrongswan-dhcp.la
+@USE_ANDROID_TRUE@am__append_82 = plugins/android
+@MONOLITHIC_TRUE@@USE_ANDROID_TRUE@am__append_83 = plugins/android/libstrongswan-android.la
+@USE_ANDROID_LOG_TRUE@am__append_84 = plugins/android_log
+@MONOLITHIC_TRUE@@USE_ANDROID_LOG_TRUE@am__append_85 = plugins/android_log/libstrongswan-android-log.la
+@USE_MAEMO_TRUE@am__append_86 = plugins/maemo
+@MONOLITHIC_TRUE@@USE_MAEMO_TRUE@am__append_87 = plugins/maemo/libstrongswan-maemo.la
+@USE_HA_TRUE@am__append_88 = plugins/ha
+@MONOLITHIC_TRUE@@USE_HA_TRUE@am__append_89 = plugins/ha/libstrongswan-ha.la
+@USE_WHITELIST_TRUE@am__append_90 = plugins/whitelist
+@MONOLITHIC_TRUE@@USE_WHITELIST_TRUE@am__append_91 = plugins/whitelist/libstrongswan-whitelist.la
+@USE_CERTEXPIRE_TRUE@am__append_92 = plugins/certexpire
+@MONOLITHIC_TRUE@@USE_CERTEXPIRE_TRUE@am__append_93 = plugins/certexpire/libstrongswan-certexpire.la
+@USE_LED_TRUE@am__append_94 = plugins/led
+@MONOLITHIC_TRUE@@USE_LED_TRUE@am__append_95 = plugins/led/libstrongswan-led.la
+@USE_DUPLICHECK_TRUE@am__append_96 = plugins/duplicheck
+@MONOLITHIC_TRUE@@USE_DUPLICHECK_TRUE@am__append_97 = plugins/duplicheck/libstrongswan-duplicheck.la
+@USE_COUPLING_TRUE@am__append_98 = plugins/coupling
+@MONOLITHIC_TRUE@@USE_COUPLING_TRUE@am__append_99 = plugins/coupling/libstrongswan-coupling.la
+@USE_RADATTR_TRUE@am__append_100 = plugins/radattr
+@MONOLITHIC_TRUE@@USE_RADATTR_TRUE@am__append_101 = plugins/radattr/libstrongswan-radattr.la
+@USE_UCI_TRUE@am__append_102 = plugins/uci
+@MONOLITHIC_TRUE@@USE_UCI_TRUE@am__append_103 = plugins/uci/libstrongswan-uci.la
+@USE_ADDRBLOCK_TRUE@am__append_104 = plugins/addrblock
+@MONOLITHIC_TRUE@@USE_ADDRBLOCK_TRUE@am__append_105 = plugins/addrblock/libstrongswan-addrblock.la
+@USE_UNITY_TRUE@am__append_106 = plugins/unity
+@MONOLITHIC_TRUE@@USE_UNITY_TRUE@am__append_107 = plugins/unity/libstrongswan-unity.la
+@USE_UNIT_TESTS_TRUE@am__append_108 = plugins/unit_tester
+@MONOLITHIC_TRUE@@USE_UNIT_TESTS_TRUE@am__append_109 = plugins/unit_tester/libstrongswan-unit-tester.la
+@USE_XAUTH_GENERIC_TRUE@am__append_110 = plugins/xauth_generic
+@MONOLITHIC_TRUE@@USE_XAUTH_GENERIC_TRUE@am__append_111 = plugins/xauth_generic/libstrongswan-xauth-generic.la
+@USE_XAUTH_EAP_TRUE@am__append_112 = plugins/xauth_eap
+@MONOLITHIC_TRUE@@USE_XAUTH_EAP_TRUE@am__append_113 = plugins/xauth_eap/libstrongswan-xauth-eap.la
+@USE_XAUTH_PAM_TRUE@am__append_114 = plugins/xauth_pam
+@MONOLITHIC_TRUE@@USE_XAUTH_PAM_TRUE@am__append_115 = plugins/xauth_pam/libstrongswan-xauth-pam.la
subdir = src/libcharon
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -164,6 +217,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -191,37 +245,38 @@ am__installdirs = "$(DESTDIR)$(ipseclibdir)"
LTLIBRARIES = $(ipseclib_LTLIBRARIES)
am__DEPENDENCIES_1 =
libcharon_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1) $(am__append_4) $(am__append_6) \
- $(am__append_8) $(am__append_10) $(am__append_12) \
- $(am__append_14) $(am__append_16) $(am__append_18) \
- $(am__append_20) $(am__append_22) $(am__append_24) \
- $(am__append_26) $(am__append_28) $(am__append_30) \
- $(am__append_32) $(am__append_34) $(am__append_36) \
- $(am__append_38) $(am__append_39) $(am__append_41) \
- $(am__append_43) $(am__append_45) $(am__append_47) \
- $(am__append_49) $(am__append_51) $(am__append_53) \
- $(am__append_55) $(am__append_56) $(am__append_57) \
- $(am__append_59) $(am__append_61) $(am__append_63) \
- $(am__append_65) $(am__append_67) $(am__append_69) \
- $(am__append_71) $(am__append_73) $(am__append_74) \
- $(am__append_76) $(am__append_78) $(am__append_80) \
- $(am__append_82) $(am__append_84) $(am__append_86) \
- $(am__append_88) $(am__append_90) $(am__append_92) \
- $(am__append_94) $(am__append_96) $(am__append_98) \
- $(am__append_100) $(am__append_102) $(am__append_104) \
- $(am__append_106)
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) $(am__append_5) \
+ $(am__append_7) $(am__append_9) $(am__append_11) \
+ $(am__append_13) $(am__append_15) $(am__append_17) \
+ $(am__append_19) $(am__append_21) $(am__append_23) \
+ $(am__append_25) $(am__append_27) $(am__append_29) \
+ $(am__append_31) $(am__append_33) $(am__append_35) \
+ $(am__append_37) $(am__append_38) $(am__append_40) \
+ $(am__append_42) $(am__append_44) $(am__append_46) \
+ $(am__append_48) $(am__append_50) $(am__append_52) \
+ $(am__append_54) $(am__append_56) $(am__append_57) \
+ $(am__append_58) $(am__append_60) $(am__append_62) \
+ $(am__append_64) $(am__append_66) $(am__append_68) \
+ $(am__append_70) $(am__append_72) $(am__append_74) \
+ $(am__append_75) $(am__append_77) $(am__append_79) \
+ $(am__append_81) $(am__append_83) $(am__append_85) \
+ $(am__append_87) $(am__append_89) $(am__append_91) \
+ $(am__append_93) $(am__append_95) $(am__append_97) \
+ $(am__append_99) $(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__libcharon_la_SOURCES_DIST = bus/bus.c bus/bus.h \
- bus/listeners/listener.h bus/listeners/file_logger.c \
- bus/listeners/file_logger.h bus/listeners/sys_logger.c \
- bus/listeners/sys_logger.h config/backend_manager.c \
- config/backend_manager.h config/backend.h config/child_cfg.c \
- config/child_cfg.h config/ike_cfg.c config/ike_cfg.h \
- config/peer_cfg.c config/peer_cfg.h config/proposal.c \
- config/proposal.h control/controller.c control/controller.h \
- daemon.c daemon.h encoding/generator.c encoding/generator.h \
- encoding/message.c encoding/message.h encoding/parser.c \
- encoding/parser.h encoding/payloads/auth_payload.c \
+ bus/listeners/listener.h bus/listeners/logger.h \
+ bus/listeners/file_logger.c bus/listeners/file_logger.h \
+ bus/listeners/sys_logger.c bus/listeners/sys_logger.h \
+ config/backend_manager.c config/backend_manager.h \
+ config/backend.h config/child_cfg.c config/child_cfg.h \
+ config/ike_cfg.c config/ike_cfg.h config/peer_cfg.c \
+ config/peer_cfg.h config/proposal.c config/proposal.h \
+ control/controller.c control/controller.h daemon.c daemon.h \
+ encoding/generator.c encoding/generator.h encoding/message.c \
+ encoding/message.h encoding/parser.c encoding/parser.h \
+ encoding/payloads/auth_payload.c \
encoding/payloads/auth_payload.h \
encoding/payloads/cert_payload.c \
encoding/payloads/cert_payload.h \
@@ -258,12 +313,14 @@ am__libcharon_la_SOURCES_DIST = bus/bus.c bus/bus.h \
encoding/payloads/unknown_payload.c \
encoding/payloads/unknown_payload.h \
encoding/payloads/vendor_id_payload.c \
- encoding/payloads/vendor_id_payload.h kernel/kernel_handler.c \
+ encoding/payloads/vendor_id_payload.h \
+ encoding/payloads/hash_payload.c \
+ encoding/payloads/hash_payload.h kernel/kernel_handler.c \
kernel/kernel_handler.h network/receiver.c network/receiver.h \
- network/sender.c network/sender.h network/packet.c \
- network/packet.h network/socket.c network/socket.h \
- network/socket_manager.c network/socket_manager.h \
- processing/jobs/acquire_job.c processing/jobs/acquire_job.h \
+ network/sender.c network/sender.h network/socket.c \
+ network/socket.h network/socket_manager.c \
+ network/socket_manager.h processing/jobs/acquire_job.c \
+ processing/jobs/acquire_job.h \
processing/jobs/delete_child_sa_job.c \
processing/jobs/delete_child_sa_job.h \
processing/jobs/delete_ike_sa_job.c \
@@ -277,6 +334,8 @@ am__libcharon_la_SOURCES_DIST = bus/bus.c bus/bus.h \
processing/jobs/rekey_ike_sa_job.h \
processing/jobs/retransmit_job.c \
processing/jobs/retransmit_job.h \
+ processing/jobs/retry_initiate_job.c \
+ processing/jobs/retry_initiate_job.h \
processing/jobs/send_dpd_job.c processing/jobs/send_dpd_job.h \
processing/jobs/send_keepalive_job.c \
processing/jobs/send_keepalive_job.h \
@@ -285,47 +344,97 @@ am__libcharon_la_SOURCES_DIST = bus/bus.c bus/bus.h \
processing/jobs/roam_job.h processing/jobs/update_sa_job.c \
processing/jobs/update_sa_job.h \
processing/jobs/inactivity_job.c \
- processing/jobs/inactivity_job.h \
- sa/authenticators/authenticator.c \
- sa/authenticators/authenticator.h \
- sa/authenticators/eap_authenticator.c \
- sa/authenticators/eap_authenticator.h \
- sa/authenticators/eap/eap_method.c \
- sa/authenticators/eap/eap_method.h \
- sa/authenticators/eap/eap_manager.c \
- sa/authenticators/eap/eap_manager.h \
- sa/authenticators/psk_authenticator.c \
- sa/authenticators/psk_authenticator.h \
- sa/authenticators/pubkey_authenticator.c \
- sa/authenticators/pubkey_authenticator.h sa/child_sa.c \
+ processing/jobs/inactivity_job.h sa/eap/eap_method.c \
+ sa/eap/eap_method.h sa/eap/eap_manager.c sa/eap/eap_manager.h \
+ sa/xauth/xauth_method.c sa/xauth/xauth_method.h \
+ sa/xauth/xauth_manager.c sa/xauth/xauth_manager.h \
+ sa/authenticator.c sa/authenticator.h sa/child_sa.c \
sa/child_sa.h sa/ike_sa.c sa/ike_sa.h sa/ike_sa_id.c \
- sa/ike_sa_id.h sa/ike_sa_manager.c sa/ike_sa_manager.h \
- sa/task_manager.c sa/task_manager.h sa/keymat.c sa/keymat.h \
+ sa/ike_sa_id.h sa/keymat.h sa/keymat.c sa/ike_sa_manager.c \
+ sa/ike_sa_manager.h sa/task_manager.h sa/task_manager.c \
sa/shunt_manager.c sa/shunt_manager.h sa/trap_manager.c \
- sa/trap_manager.h sa/tasks/child_create.c \
- sa/tasks/child_create.h sa/tasks/child_delete.c \
- sa/tasks/child_delete.h sa/tasks/child_rekey.c \
- sa/tasks/child_rekey.h sa/tasks/ike_auth.c sa/tasks/ike_auth.h \
- sa/tasks/ike_cert_pre.c sa/tasks/ike_cert_pre.h \
- sa/tasks/ike_cert_post.c sa/tasks/ike_cert_post.h \
- sa/tasks/ike_config.c sa/tasks/ike_config.h \
- sa/tasks/ike_delete.c sa/tasks/ike_delete.h sa/tasks/ike_dpd.c \
- sa/tasks/ike_dpd.h sa/tasks/ike_init.c sa/tasks/ike_init.h \
- sa/tasks/ike_natd.c sa/tasks/ike_natd.h sa/tasks/ike_mobike.c \
- sa/tasks/ike_mobike.h sa/tasks/ike_rekey.c \
- sa/tasks/ike_rekey.h sa/tasks/ike_reauth.c \
- sa/tasks/ike_reauth.h sa/tasks/ike_auth_lifetime.c \
- sa/tasks/ike_auth_lifetime.h sa/tasks/ike_vendor.c \
- sa/tasks/ike_vendor.h sa/tasks/task.c sa/tasks/task.h \
+ sa/trap_manager.h sa/task.c sa/task.h sa/ikev2/keymat_v2.c \
+ sa/ikev2/keymat_v2.h sa/ikev2/task_manager_v2.c \
+ sa/ikev2/task_manager_v2.h \
+ sa/ikev2/authenticators/eap_authenticator.c \
+ sa/ikev2/authenticators/eap_authenticator.h \
+ sa/ikev2/authenticators/psk_authenticator.c \
+ sa/ikev2/authenticators/psk_authenticator.h \
+ sa/ikev2/authenticators/pubkey_authenticator.c \
+ sa/ikev2/authenticators/pubkey_authenticator.h \
+ sa/ikev2/tasks/child_create.c sa/ikev2/tasks/child_create.h \
+ sa/ikev2/tasks/child_delete.c sa/ikev2/tasks/child_delete.h \
+ sa/ikev2/tasks/child_rekey.c sa/ikev2/tasks/child_rekey.h \
+ sa/ikev2/tasks/ike_auth.c sa/ikev2/tasks/ike_auth.h \
+ sa/ikev2/tasks/ike_cert_pre.c sa/ikev2/tasks/ike_cert_pre.h \
+ sa/ikev2/tasks/ike_cert_post.c sa/ikev2/tasks/ike_cert_post.h \
+ sa/ikev2/tasks/ike_config.c sa/ikev2/tasks/ike_config.h \
+ sa/ikev2/tasks/ike_delete.c sa/ikev2/tasks/ike_delete.h \
+ sa/ikev2/tasks/ike_dpd.c sa/ikev2/tasks/ike_dpd.h \
+ sa/ikev2/tasks/ike_init.c sa/ikev2/tasks/ike_init.h \
+ sa/ikev2/tasks/ike_natd.c sa/ikev2/tasks/ike_natd.h \
+ sa/ikev2/tasks/ike_mobike.c sa/ikev2/tasks/ike_mobike.h \
+ sa/ikev2/tasks/ike_rekey.c sa/ikev2/tasks/ike_rekey.h \
+ sa/ikev2/tasks/ike_reauth.c sa/ikev2/tasks/ike_reauth.h \
+ sa/ikev2/tasks/ike_auth_lifetime.c \
+ sa/ikev2/tasks/ike_auth_lifetime.h sa/ikev2/tasks/ike_vendor.c \
+ sa/ikev2/tasks/ike_vendor.h sa/ikev1/keymat_v1.c \
+ sa/ikev1/keymat_v1.h sa/ikev1/task_manager_v1.c \
+ sa/ikev1/task_manager_v1.h \
+ sa/ikev1/authenticators/psk_v1_authenticator.c \
+ sa/ikev1/authenticators/psk_v1_authenticator.h \
+ sa/ikev1/authenticators/pubkey_v1_authenticator.c \
+ sa/ikev1/authenticators/pubkey_v1_authenticator.h \
+ sa/ikev1/authenticators/hybrid_authenticator.c \
+ sa/ikev1/authenticators/hybrid_authenticator.h \
+ sa/ikev1/phase1.c sa/ikev1/phase1.h sa/ikev1/tasks/main_mode.c \
+ sa/ikev1/tasks/main_mode.h sa/ikev1/tasks/aggressive_mode.c \
+ sa/ikev1/tasks/aggressive_mode.h \
+ sa/ikev1/tasks/informational.c sa/ikev1/tasks/informational.h \
+ sa/ikev1/tasks/isakmp_cert_pre.c \
+ sa/ikev1/tasks/isakmp_cert_pre.h \
+ sa/ikev1/tasks/isakmp_cert_post.c \
+ sa/ikev1/tasks/isakmp_cert_post.h sa/ikev1/tasks/isakmp_natd.c \
+ sa/ikev1/tasks/isakmp_natd.h sa/ikev1/tasks/isakmp_vendor.c \
+ sa/ikev1/tasks/isakmp_vendor.h sa/ikev1/tasks/isakmp_delete.c \
+ sa/ikev1/tasks/isakmp_delete.h sa/ikev1/tasks/isakmp_dpd.c \
+ sa/ikev1/tasks/isakmp_dpd.h sa/ikev1/tasks/xauth.c \
+ sa/ikev1/tasks/xauth.h sa/ikev1/tasks/quick_mode.c \
+ sa/ikev1/tasks/quick_mode.h sa/ikev1/tasks/quick_delete.c \
+ sa/ikev1/tasks/quick_delete.h sa/ikev1/tasks/mode_config.c \
+ sa/ikev1/tasks/mode_config.h processing/jobs/dpd_timeout_job.c \
+ processing/jobs/dpd_timeout_job.h \
+ processing/jobs/adopt_children_job.c \
+ processing/jobs/adopt_children_job.h \
encoding/payloads/endpoint_notify.c \
encoding/payloads/endpoint_notify.h \
processing/jobs/initiate_mediation_job.c \
processing/jobs/initiate_mediation_job.h \
processing/jobs/mediation_job.c \
- processing/jobs/mediation_job.h sa/connect_manager.c \
- sa/connect_manager.h sa/mediation_manager.c \
- sa/mediation_manager.h sa/tasks/ike_me.c sa/tasks/ike_me.h
-@USE_ME_TRUE@am__objects_1 = endpoint_notify.lo \
+ processing/jobs/mediation_job.h sa/ikev2/connect_manager.c \
+ sa/ikev2/connect_manager.h sa/ikev2/mediation_manager.c \
+ sa/ikev2/mediation_manager.h sa/ikev2/tasks/ike_me.c \
+ sa/ikev2/tasks/ike_me.h
+@USE_IKEV2_TRUE@am__objects_1 = keymat_v2.lo task_manager_v2.lo \
+@USE_IKEV2_TRUE@ eap_authenticator.lo psk_authenticator.lo \
+@USE_IKEV2_TRUE@ pubkey_authenticator.lo child_create.lo \
+@USE_IKEV2_TRUE@ child_delete.lo child_rekey.lo ike_auth.lo \
+@USE_IKEV2_TRUE@ ike_cert_pre.lo ike_cert_post.lo ike_config.lo \
+@USE_IKEV2_TRUE@ ike_delete.lo ike_dpd.lo ike_init.lo \
+@USE_IKEV2_TRUE@ ike_natd.lo ike_mobike.lo ike_rekey.lo \
+@USE_IKEV2_TRUE@ ike_reauth.lo ike_auth_lifetime.lo \
+@USE_IKEV2_TRUE@ ike_vendor.lo
+@USE_IKEV1_TRUE@am__objects_2 = keymat_v1.lo task_manager_v1.lo \
+@USE_IKEV1_TRUE@ psk_v1_authenticator.lo \
+@USE_IKEV1_TRUE@ pubkey_v1_authenticator.lo \
+@USE_IKEV1_TRUE@ hybrid_authenticator.lo phase1.lo main_mode.lo \
+@USE_IKEV1_TRUE@ aggressive_mode.lo informational.lo \
+@USE_IKEV1_TRUE@ isakmp_cert_pre.lo isakmp_cert_post.lo \
+@USE_IKEV1_TRUE@ isakmp_natd.lo isakmp_vendor.lo \
+@USE_IKEV1_TRUE@ isakmp_delete.lo isakmp_dpd.lo xauth.lo \
+@USE_IKEV1_TRUE@ quick_mode.lo quick_delete.lo mode_config.lo \
+@USE_IKEV1_TRUE@ dpd_timeout_job.lo adopt_children_job.lo
+@USE_ME_TRUE@am__objects_3 = endpoint_notify.lo \
@USE_ME_TRUE@ initiate_mediation_job.lo mediation_job.lo \
@USE_ME_TRUE@ connect_manager.lo mediation_manager.lo ike_me.lo
am_libcharon_la_OBJECTS = bus.lo file_logger.lo sys_logger.lo \
@@ -338,24 +447,20 @@ am_libcharon_la_OBJECTS = bus.lo file_logger.lo sys_logger.lo \
notify_payload.lo payload.lo proposal_substructure.lo \
sa_payload.lo traffic_selector_substructure.lo \
transform_attribute.lo transform_substructure.lo ts_payload.lo \
- unknown_payload.lo vendor_id_payload.lo kernel_handler.lo \
- receiver.lo sender.lo packet.lo socket.lo socket_manager.lo \
- acquire_job.lo delete_child_sa_job.lo delete_ike_sa_job.lo \
- migrate_job.lo process_message_job.lo rekey_child_sa_job.lo \
- rekey_ike_sa_job.lo retransmit_job.lo send_dpd_job.lo \
- send_keepalive_job.lo start_action_job.lo roam_job.lo \
- update_sa_job.lo inactivity_job.lo authenticator.lo \
- eap_authenticator.lo eap_method.lo eap_manager.lo \
- psk_authenticator.lo pubkey_authenticator.lo child_sa.lo \
- ike_sa.lo ike_sa_id.lo ike_sa_manager.lo task_manager.lo \
- keymat.lo shunt_manager.lo trap_manager.lo child_create.lo \
- child_delete.lo child_rekey.lo ike_auth.lo ike_cert_pre.lo \
- ike_cert_post.lo ike_config.lo ike_delete.lo ike_dpd.lo \
- ike_init.lo ike_natd.lo ike_mobike.lo ike_rekey.lo \
- ike_reauth.lo ike_auth_lifetime.lo ike_vendor.lo task.lo \
- $(am__objects_1)
+ unknown_payload.lo vendor_id_payload.lo hash_payload.lo \
+ kernel_handler.lo receiver.lo sender.lo socket.lo \
+ socket_manager.lo acquire_job.lo delete_child_sa_job.lo \
+ delete_ike_sa_job.lo migrate_job.lo process_message_job.lo \
+ rekey_child_sa_job.lo rekey_ike_sa_job.lo retransmit_job.lo \
+ retry_initiate_job.lo send_dpd_job.lo send_keepalive_job.lo \
+ start_action_job.lo roam_job.lo update_sa_job.lo \
+ inactivity_job.lo eap_method.lo eap_manager.lo xauth_method.lo \
+ xauth_manager.lo authenticator.lo child_sa.lo ike_sa.lo \
+ ike_sa_id.lo keymat.lo ike_sa_manager.lo task_manager.lo \
+ shunt_manager.lo trap_manager.lo task.lo $(am__objects_1) \
+ $(am__objects_2) $(am__objects_3)
libcharon_la_OBJECTS = $(am_libcharon_la_OBJECTS)
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -385,22 +490,23 @@ AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
ETAGS = etags
CTAGS = ctags
DIST_SUBDIRS = . plugins/load_tester plugins/socket_default \
- plugins/socket_raw plugins/socket_dynamic plugins/farp \
- plugins/stroke plugins/smp plugins/sql plugins/updown \
- plugins/eap_identity plugins/eap_sim plugins/eap_sim_file \
- plugins/eap_sim_pcsc plugins/eap_simaka_sql \
- plugins/eap_simaka_pseudonym plugins/eap_simaka_reauth \
- plugins/eap_aka plugins/eap_aka_3gpp2 plugins/eap_md5 \
- plugins/eap_gtc plugins/eap_mschapv2 plugins/eap_radius \
+ plugins/socket_dynamic plugins/farp plugins/stroke plugins/smp \
+ plugins/sql plugins/updown plugins/eap_identity \
+ plugins/eap_sim plugins/eap_sim_file plugins/eap_sim_pcsc \
+ plugins/eap_simaka_sql plugins/eap_simaka_pseudonym \
+ plugins/eap_simaka_reauth plugins/eap_aka \
+ plugins/eap_aka_3gpp2 plugins/eap_md5 plugins/eap_gtc \
+ plugins/eap_mschapv2 plugins/eap_dynamic plugins/eap_radius \
plugins/eap_tls plugins/eap_ttls plugins/eap_peap \
plugins/eap_tnc plugins/tnc_ifmap plugins/tnc_pdp \
plugins/tnc_imc plugins/tnc_imv plugins/tnc_tnccs \
plugins/tnccs_11 plugins/tnccs_20 plugins/tnccs_dynamic \
- plugins/medsrv plugins/medcli plugins/nm plugins/dhcp \
- plugins/android plugins/maemo plugins/ha plugins/whitelist \
+ plugins/medsrv plugins/medcli plugins/dhcp plugins/android \
+ plugins/android_log plugins/maemo plugins/ha plugins/whitelist \
plugins/certexpire plugins/led plugins/duplicheck \
plugins/coupling plugins/radattr plugins/uci plugins/addrblock \
- plugins/unit_tester
+ plugins/unity plugins/unit_tester plugins/xauth_generic \
+ plugins/xauth_eap plugins/xauth_pam
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
am__relativize = \
dir0=`pwd`; \
@@ -435,6 +541,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -529,11 +636,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -550,11 +660,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -570,6 +681,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -579,7 +691,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -609,16 +720,16 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
ipseclib_LTLIBRARIES = libcharon.la
libcharon_la_SOURCES = bus/bus.c bus/bus.h bus/listeners/listener.h \
- bus/listeners/file_logger.c bus/listeners/file_logger.h \
- bus/listeners/sys_logger.c bus/listeners/sys_logger.h \
- config/backend_manager.c config/backend_manager.h \
- config/backend.h config/child_cfg.c config/child_cfg.h \
- config/ike_cfg.c config/ike_cfg.h config/peer_cfg.c \
- config/peer_cfg.h config/proposal.c config/proposal.h \
- control/controller.c control/controller.h daemon.c daemon.h \
- encoding/generator.c encoding/generator.h encoding/message.c \
- encoding/message.h encoding/parser.c encoding/parser.h \
- encoding/payloads/auth_payload.c \
+ bus/listeners/logger.h bus/listeners/file_logger.c \
+ bus/listeners/file_logger.h bus/listeners/sys_logger.c \
+ bus/listeners/sys_logger.h config/backend_manager.c \
+ config/backend_manager.h config/backend.h config/child_cfg.c \
+ config/child_cfg.h config/ike_cfg.c config/ike_cfg.h \
+ config/peer_cfg.c config/peer_cfg.h config/proposal.c \
+ config/proposal.h control/controller.c control/controller.h \
+ daemon.c daemon.h encoding/generator.c encoding/generator.h \
+ encoding/message.c encoding/message.h encoding/parser.c \
+ encoding/parser.h encoding/payloads/auth_payload.c \
encoding/payloads/auth_payload.h \
encoding/payloads/cert_payload.c \
encoding/payloads/cert_payload.h \
@@ -655,12 +766,14 @@ libcharon_la_SOURCES = bus/bus.c bus/bus.h bus/listeners/listener.h \
encoding/payloads/unknown_payload.c \
encoding/payloads/unknown_payload.h \
encoding/payloads/vendor_id_payload.c \
- encoding/payloads/vendor_id_payload.h kernel/kernel_handler.c \
+ encoding/payloads/vendor_id_payload.h \
+ encoding/payloads/hash_payload.c \
+ encoding/payloads/hash_payload.h kernel/kernel_handler.c \
kernel/kernel_handler.h network/receiver.c network/receiver.h \
- network/sender.c network/sender.h network/packet.c \
- network/packet.h network/socket.c network/socket.h \
- network/socket_manager.c network/socket_manager.h \
- processing/jobs/acquire_job.c processing/jobs/acquire_job.h \
+ network/sender.c network/sender.h network/socket.c \
+ network/socket.h network/socket_manager.c \
+ network/socket_manager.h processing/jobs/acquire_job.c \
+ processing/jobs/acquire_job.h \
processing/jobs/delete_child_sa_job.c \
processing/jobs/delete_child_sa_job.h \
processing/jobs/delete_ike_sa_job.c \
@@ -674,6 +787,8 @@ libcharon_la_SOURCES = bus/bus.c bus/bus.h bus/listeners/listener.h \
processing/jobs/rekey_ike_sa_job.h \
processing/jobs/retransmit_job.c \
processing/jobs/retransmit_job.h \
+ processing/jobs/retry_initiate_job.c \
+ processing/jobs/retry_initiate_job.h \
processing/jobs/send_dpd_job.c processing/jobs/send_dpd_job.h \
processing/jobs/send_keepalive_job.c \
processing/jobs/send_keepalive_job.h \
@@ -682,39 +797,17 @@ libcharon_la_SOURCES = bus/bus.c bus/bus.h bus/listeners/listener.h \
processing/jobs/roam_job.h processing/jobs/update_sa_job.c \
processing/jobs/update_sa_job.h \
processing/jobs/inactivity_job.c \
- processing/jobs/inactivity_job.h \
- sa/authenticators/authenticator.c \
- sa/authenticators/authenticator.h \
- sa/authenticators/eap_authenticator.c \
- sa/authenticators/eap_authenticator.h \
- sa/authenticators/eap/eap_method.c \
- sa/authenticators/eap/eap_method.h \
- sa/authenticators/eap/eap_manager.c \
- sa/authenticators/eap/eap_manager.h \
- sa/authenticators/psk_authenticator.c \
- sa/authenticators/psk_authenticator.h \
- sa/authenticators/pubkey_authenticator.c \
- sa/authenticators/pubkey_authenticator.h sa/child_sa.c \
+ processing/jobs/inactivity_job.h sa/eap/eap_method.c \
+ sa/eap/eap_method.h sa/eap/eap_manager.c sa/eap/eap_manager.h \
+ sa/xauth/xauth_method.c sa/xauth/xauth_method.h \
+ sa/xauth/xauth_manager.c sa/xauth/xauth_manager.h \
+ sa/authenticator.c sa/authenticator.h sa/child_sa.c \
sa/child_sa.h sa/ike_sa.c sa/ike_sa.h sa/ike_sa_id.c \
- sa/ike_sa_id.h sa/ike_sa_manager.c sa/ike_sa_manager.h \
- sa/task_manager.c sa/task_manager.h sa/keymat.c sa/keymat.h \
+ sa/ike_sa_id.h sa/keymat.h sa/keymat.c sa/ike_sa_manager.c \
+ sa/ike_sa_manager.h sa/task_manager.h sa/task_manager.c \
sa/shunt_manager.c sa/shunt_manager.h sa/trap_manager.c \
- sa/trap_manager.h sa/tasks/child_create.c \
- sa/tasks/child_create.h sa/tasks/child_delete.c \
- sa/tasks/child_delete.h sa/tasks/child_rekey.c \
- sa/tasks/child_rekey.h sa/tasks/ike_auth.c sa/tasks/ike_auth.h \
- sa/tasks/ike_cert_pre.c sa/tasks/ike_cert_pre.h \
- sa/tasks/ike_cert_post.c sa/tasks/ike_cert_post.h \
- sa/tasks/ike_config.c sa/tasks/ike_config.h \
- sa/tasks/ike_delete.c sa/tasks/ike_delete.h sa/tasks/ike_dpd.c \
- sa/tasks/ike_dpd.h sa/tasks/ike_init.c sa/tasks/ike_init.h \
- sa/tasks/ike_natd.c sa/tasks/ike_natd.h sa/tasks/ike_mobike.c \
- sa/tasks/ike_mobike.h sa/tasks/ike_rekey.c \
- sa/tasks/ike_rekey.h sa/tasks/ike_reauth.c \
- sa/tasks/ike_reauth.h sa/tasks/ike_auth_lifetime.c \
- sa/tasks/ike_auth_lifetime.h sa/tasks/ike_vendor.c \
- sa/tasks/ike_vendor.h sa/tasks/task.c sa/tasks/task.h \
- $(am__append_1)
+ sa/trap_manager.h sa/task.c sa/task.h $(am__append_1) \
+ $(am__append_2) $(am__append_3)
INCLUDES = \
-I${linux_headers} \
-I$(top_srcdir)/src/libstrongswan \
@@ -723,83 +816,87 @@ INCLUDES = \
AM_CFLAGS = \
-DIPSEC_DIR=\"${ipsecdir}\" \
- -DIPSEC_PIDDIR=\"${piddir}\" \
- -DPLUGINS=\""${libcharon_plugins}\""
+ -DIPSEC_PIDDIR=\"${piddir}\"
libcharon_la_LIBADD = -lm $(PTHREADLIB) $(DLLIB) $(SOCKLIB) \
- $(am__append_2) $(am__append_4) $(am__append_6) \
- $(am__append_8) $(am__append_10) $(am__append_12) \
- $(am__append_14) $(am__append_16) $(am__append_18) \
- $(am__append_20) $(am__append_22) $(am__append_24) \
- $(am__append_26) $(am__append_28) $(am__append_30) \
- $(am__append_32) $(am__append_34) $(am__append_36) \
- $(am__append_38) $(am__append_39) $(am__append_41) \
- $(am__append_43) $(am__append_45) $(am__append_47) \
- $(am__append_49) $(am__append_51) $(am__append_53) \
- $(am__append_55) $(am__append_56) $(am__append_57) \
- $(am__append_59) $(am__append_61) $(am__append_63) \
- $(am__append_65) $(am__append_67) $(am__append_69) \
- $(am__append_71) $(am__append_73) $(am__append_74) \
- $(am__append_76) $(am__append_78) $(am__append_80) \
- $(am__append_82) $(am__append_84) $(am__append_86) \
- $(am__append_88) $(am__append_90) $(am__append_92) \
- $(am__append_94) $(am__append_96) $(am__append_98) \
- $(am__append_100) $(am__append_102) $(am__append_104) \
- $(am__append_106)
+ $(am__append_5) $(am__append_7) $(am__append_9) \
+ $(am__append_11) $(am__append_13) $(am__append_15) \
+ $(am__append_17) $(am__append_19) $(am__append_21) \
+ $(am__append_23) $(am__append_25) $(am__append_27) \
+ $(am__append_29) $(am__append_31) $(am__append_33) \
+ $(am__append_35) $(am__append_37) $(am__append_38) \
+ $(am__append_40) $(am__append_42) $(am__append_44) \
+ $(am__append_46) $(am__append_48) $(am__append_50) \
+ $(am__append_52) $(am__append_54) $(am__append_56) \
+ $(am__append_57) $(am__append_58) $(am__append_60) \
+ $(am__append_62) $(am__append_64) $(am__append_66) \
+ $(am__append_68) $(am__append_70) $(am__append_72) \
+ $(am__append_74) $(am__append_75) $(am__append_77) \
+ $(am__append_79) $(am__append_81) $(am__append_83) \
+ $(am__append_85) $(am__append_87) $(am__append_89) \
+ $(am__append_91) $(am__append_93) $(am__append_95) \
+ $(am__append_97) $(am__append_99) $(am__append_101) \
+ $(am__append_103) $(am__append_105) $(am__append_107) \
+ $(am__append_109) $(am__append_111) $(am__append_113) \
+ $(am__append_115)
EXTRA_DIST = Android.mk
-@MONOLITHIC_FALSE@SUBDIRS = . $(am__append_3) $(am__append_5) \
-@MONOLITHIC_FALSE@ $(am__append_7) $(am__append_9) \
-@MONOLITHIC_FALSE@ $(am__append_11) $(am__append_13) \
-@MONOLITHIC_FALSE@ $(am__append_15) $(am__append_17) \
-@MONOLITHIC_FALSE@ $(am__append_19) $(am__append_21) \
-@MONOLITHIC_FALSE@ $(am__append_23) $(am__append_25) \
-@MONOLITHIC_FALSE@ $(am__append_27) $(am__append_29) \
-@MONOLITHIC_FALSE@ $(am__append_31) $(am__append_33) \
-@MONOLITHIC_FALSE@ $(am__append_35) $(am__append_37) \
-@MONOLITHIC_FALSE@ $(am__append_40) $(am__append_42) \
-@MONOLITHIC_FALSE@ $(am__append_44) $(am__append_46) \
-@MONOLITHIC_FALSE@ $(am__append_48) $(am__append_50) \
-@MONOLITHIC_FALSE@ $(am__append_52) $(am__append_54) \
-@MONOLITHIC_FALSE@ $(am__append_58) $(am__append_60) \
-@MONOLITHIC_FALSE@ $(am__append_62) $(am__append_64) \
-@MONOLITHIC_FALSE@ $(am__append_66) $(am__append_68) \
-@MONOLITHIC_FALSE@ $(am__append_70) $(am__append_72) \
-@MONOLITHIC_FALSE@ $(am__append_75) $(am__append_77) \
-@MONOLITHIC_FALSE@ $(am__append_79) $(am__append_81) \
-@MONOLITHIC_FALSE@ $(am__append_83) $(am__append_85) \
-@MONOLITHIC_FALSE@ $(am__append_87) $(am__append_89) \
-@MONOLITHIC_FALSE@ $(am__append_91) $(am__append_93) \
-@MONOLITHIC_FALSE@ $(am__append_95) $(am__append_97) \
-@MONOLITHIC_FALSE@ $(am__append_99) $(am__append_101) \
-@MONOLITHIC_FALSE@ $(am__append_103) $(am__append_105)
+@MONOLITHIC_FALSE@SUBDIRS = . $(am__append_4) $(am__append_6) \
+@MONOLITHIC_FALSE@ $(am__append_8) $(am__append_10) \
+@MONOLITHIC_FALSE@ $(am__append_12) $(am__append_14) \
+@MONOLITHIC_FALSE@ $(am__append_16) $(am__append_18) \
+@MONOLITHIC_FALSE@ $(am__append_20) $(am__append_22) \
+@MONOLITHIC_FALSE@ $(am__append_24) $(am__append_26) \
+@MONOLITHIC_FALSE@ $(am__append_28) $(am__append_30) \
+@MONOLITHIC_FALSE@ $(am__append_32) $(am__append_34) \
+@MONOLITHIC_FALSE@ $(am__append_36) $(am__append_39) \
+@MONOLITHIC_FALSE@ $(am__append_41) $(am__append_43) \
+@MONOLITHIC_FALSE@ $(am__append_45) $(am__append_47) \
+@MONOLITHIC_FALSE@ $(am__append_49) $(am__append_51) \
+@MONOLITHIC_FALSE@ $(am__append_53) $(am__append_55) \
+@MONOLITHIC_FALSE@ $(am__append_59) $(am__append_61) \
+@MONOLITHIC_FALSE@ $(am__append_63) $(am__append_65) \
+@MONOLITHIC_FALSE@ $(am__append_67) $(am__append_69) \
+@MONOLITHIC_FALSE@ $(am__append_71) $(am__append_73) \
+@MONOLITHIC_FALSE@ $(am__append_76) $(am__append_78) \
+@MONOLITHIC_FALSE@ $(am__append_80) $(am__append_82) \
+@MONOLITHIC_FALSE@ $(am__append_84) $(am__append_86) \
+@MONOLITHIC_FALSE@ $(am__append_88) $(am__append_90) \
+@MONOLITHIC_FALSE@ $(am__append_92) $(am__append_94) \
+@MONOLITHIC_FALSE@ $(am__append_96) $(am__append_98) \
+@MONOLITHIC_FALSE@ $(am__append_100) $(am__append_102) \
+@MONOLITHIC_FALSE@ $(am__append_104) $(am__append_106) \
+@MONOLITHIC_FALSE@ $(am__append_108) $(am__append_110) \
+@MONOLITHIC_FALSE@ $(am__append_112) $(am__append_114)
# build optional plugins
########################
-@MONOLITHIC_TRUE@SUBDIRS = $(am__append_3) $(am__append_5) \
-@MONOLITHIC_TRUE@ $(am__append_7) $(am__append_9) \
-@MONOLITHIC_TRUE@ $(am__append_11) $(am__append_13) \
-@MONOLITHIC_TRUE@ $(am__append_15) $(am__append_17) \
-@MONOLITHIC_TRUE@ $(am__append_19) $(am__append_21) \
-@MONOLITHIC_TRUE@ $(am__append_23) $(am__append_25) \
-@MONOLITHIC_TRUE@ $(am__append_27) $(am__append_29) \
-@MONOLITHIC_TRUE@ $(am__append_31) $(am__append_33) \
-@MONOLITHIC_TRUE@ $(am__append_35) $(am__append_37) \
-@MONOLITHIC_TRUE@ $(am__append_40) $(am__append_42) \
-@MONOLITHIC_TRUE@ $(am__append_44) $(am__append_46) \
-@MONOLITHIC_TRUE@ $(am__append_48) $(am__append_50) \
-@MONOLITHIC_TRUE@ $(am__append_52) $(am__append_54) \
-@MONOLITHIC_TRUE@ $(am__append_58) $(am__append_60) \
-@MONOLITHIC_TRUE@ $(am__append_62) $(am__append_64) \
-@MONOLITHIC_TRUE@ $(am__append_66) $(am__append_68) \
-@MONOLITHIC_TRUE@ $(am__append_70) $(am__append_72) \
-@MONOLITHIC_TRUE@ $(am__append_75) $(am__append_77) \
-@MONOLITHIC_TRUE@ $(am__append_79) $(am__append_81) \
-@MONOLITHIC_TRUE@ $(am__append_83) $(am__append_85) \
-@MONOLITHIC_TRUE@ $(am__append_87) $(am__append_89) \
-@MONOLITHIC_TRUE@ $(am__append_91) $(am__append_93) \
-@MONOLITHIC_TRUE@ $(am__append_95) $(am__append_97) \
-@MONOLITHIC_TRUE@ $(am__append_99) $(am__append_101) \
-@MONOLITHIC_TRUE@ $(am__append_103) $(am__append_105)
+@MONOLITHIC_TRUE@SUBDIRS = $(am__append_4) $(am__append_6) \
+@MONOLITHIC_TRUE@ $(am__append_8) $(am__append_10) \
+@MONOLITHIC_TRUE@ $(am__append_12) $(am__append_14) \
+@MONOLITHIC_TRUE@ $(am__append_16) $(am__append_18) \
+@MONOLITHIC_TRUE@ $(am__append_20) $(am__append_22) \
+@MONOLITHIC_TRUE@ $(am__append_24) $(am__append_26) \
+@MONOLITHIC_TRUE@ $(am__append_28) $(am__append_30) \
+@MONOLITHIC_TRUE@ $(am__append_32) $(am__append_34) \
+@MONOLITHIC_TRUE@ $(am__append_36) $(am__append_39) \
+@MONOLITHIC_TRUE@ $(am__append_41) $(am__append_43) \
+@MONOLITHIC_TRUE@ $(am__append_45) $(am__append_47) \
+@MONOLITHIC_TRUE@ $(am__append_49) $(am__append_51) \
+@MONOLITHIC_TRUE@ $(am__append_53) $(am__append_55) \
+@MONOLITHIC_TRUE@ $(am__append_59) $(am__append_61) \
+@MONOLITHIC_TRUE@ $(am__append_63) $(am__append_65) \
+@MONOLITHIC_TRUE@ $(am__append_67) $(am__append_69) \
+@MONOLITHIC_TRUE@ $(am__append_71) $(am__append_73) \
+@MONOLITHIC_TRUE@ $(am__append_76) $(am__append_78) \
+@MONOLITHIC_TRUE@ $(am__append_80) $(am__append_82) \
+@MONOLITHIC_TRUE@ $(am__append_84) $(am__append_86) \
+@MONOLITHIC_TRUE@ $(am__append_88) $(am__append_90) \
+@MONOLITHIC_TRUE@ $(am__append_92) $(am__append_94) \
+@MONOLITHIC_TRUE@ $(am__append_96) $(am__append_98) \
+@MONOLITHIC_TRUE@ $(am__append_100) $(am__append_102) \
+@MONOLITHIC_TRUE@ $(am__append_104) $(am__append_106) \
+@MONOLITHIC_TRUE@ $(am__append_108) $(am__append_110) \
+@MONOLITHIC_TRUE@ $(am__append_112) $(am__append_114)
all: all-recursive
.SUFFIXES:
@@ -875,6 +972,8 @@ distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/acquire_job.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/adopt_children_job.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aggressive_mode.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_payload.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/authenticator.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backend_manager.Plo@am__quote@
@@ -894,6 +993,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/delete_child_sa_job.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/delete_ike_sa_job.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/delete_payload.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dpd_timeout_job.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_authenticator.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_manager.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_method.Plo@am__quote@
@@ -903,6 +1003,8 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/endpoint_notify.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file_logger.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generator.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash_payload.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hybrid_authenticator.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/id_payload.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_auth.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_auth_lifetime.Plo@am__quote@
@@ -924,29 +1026,45 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_sa_manager.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_vendor.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inactivity_job.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/informational.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/initiate_mediation_job.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isakmp_cert_post.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isakmp_cert_pre.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isakmp_delete.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isakmp_dpd.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isakmp_natd.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isakmp_vendor.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ke_payload.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel_handler.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keymat.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keymat_v1.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keymat_v2.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main_mode.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mediation_job.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mediation_manager.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/message.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/migrate_job.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mode_config.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nonce_payload.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/notify_payload.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/packet.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/payload.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/peer_cfg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/phase1.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/process_message_job.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proposal.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proposal_substructure.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/psk_authenticator.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/psk_v1_authenticator.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pubkey_authenticator.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pubkey_v1_authenticator.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quick_delete.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quick_mode.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/receiver.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rekey_child_sa_job.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rekey_ike_sa_job.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/retransmit_job.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/retry_initiate_job.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/roam_job.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sa_payload.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/send_dpd_job.Plo@am__quote@
@@ -959,6 +1077,8 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sys_logger.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task_manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task_manager_v1.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task_manager_v2.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/traffic_selector_substructure.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transform_attribute.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transform_substructure.Plo@am__quote@
@@ -967,6 +1087,9 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unknown_payload.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/update_sa_job.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vendor_id_payload.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xauth.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xauth_manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xauth_method.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@@ -1234,6 +1357,13 @@ vendor_id_payload.lo: encoding/payloads/vendor_id_payload.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vendor_id_payload.lo `test -f 'encoding/payloads/vendor_id_payload.c' || echo '$(srcdir)/'`encoding/payloads/vendor_id_payload.c
+hash_payload.lo: encoding/payloads/hash_payload.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT hash_payload.lo -MD -MP -MF $(DEPDIR)/hash_payload.Tpo -c -o hash_payload.lo `test -f 'encoding/payloads/hash_payload.c' || echo '$(srcdir)/'`encoding/payloads/hash_payload.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/hash_payload.Tpo $(DEPDIR)/hash_payload.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encoding/payloads/hash_payload.c' object='hash_payload.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o hash_payload.lo `test -f 'encoding/payloads/hash_payload.c' || echo '$(srcdir)/'`encoding/payloads/hash_payload.c
+
kernel_handler.lo: kernel/kernel_handler.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT kernel_handler.lo -MD -MP -MF $(DEPDIR)/kernel_handler.Tpo -c -o kernel_handler.lo `test -f 'kernel/kernel_handler.c' || echo '$(srcdir)/'`kernel/kernel_handler.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/kernel_handler.Tpo $(DEPDIR)/kernel_handler.Plo
@@ -1255,13 +1385,6 @@ sender.lo: network/sender.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sender.lo `test -f 'network/sender.c' || echo '$(srcdir)/'`network/sender.c
-packet.lo: network/packet.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT packet.lo -MD -MP -MF $(DEPDIR)/packet.Tpo -c -o packet.lo `test -f 'network/packet.c' || echo '$(srcdir)/'`network/packet.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/packet.Tpo $(DEPDIR)/packet.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='network/packet.c' object='packet.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o packet.lo `test -f 'network/packet.c' || echo '$(srcdir)/'`network/packet.c
-
socket.lo: network/socket.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT socket.lo -MD -MP -MF $(DEPDIR)/socket.Tpo -c -o socket.lo `test -f 'network/socket.c' || echo '$(srcdir)/'`network/socket.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/socket.Tpo $(DEPDIR)/socket.Plo
@@ -1332,6 +1455,13 @@ retransmit_job.lo: processing/jobs/retransmit_job.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o retransmit_job.lo `test -f 'processing/jobs/retransmit_job.c' || echo '$(srcdir)/'`processing/jobs/retransmit_job.c
+retry_initiate_job.lo: processing/jobs/retry_initiate_job.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT retry_initiate_job.lo -MD -MP -MF $(DEPDIR)/retry_initiate_job.Tpo -c -o retry_initiate_job.lo `test -f 'processing/jobs/retry_initiate_job.c' || echo '$(srcdir)/'`processing/jobs/retry_initiate_job.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/retry_initiate_job.Tpo $(DEPDIR)/retry_initiate_job.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/retry_initiate_job.c' object='retry_initiate_job.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o retry_initiate_job.lo `test -f 'processing/jobs/retry_initiate_job.c' || echo '$(srcdir)/'`processing/jobs/retry_initiate_job.c
+
send_dpd_job.lo: processing/jobs/send_dpd_job.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT send_dpd_job.lo -MD -MP -MF $(DEPDIR)/send_dpd_job.Tpo -c -o send_dpd_job.lo `test -f 'processing/jobs/send_dpd_job.c' || echo '$(srcdir)/'`processing/jobs/send_dpd_job.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/send_dpd_job.Tpo $(DEPDIR)/send_dpd_job.Plo
@@ -1374,47 +1504,40 @@ inactivity_job.lo: processing/jobs/inactivity_job.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o inactivity_job.lo `test -f 'processing/jobs/inactivity_job.c' || echo '$(srcdir)/'`processing/jobs/inactivity_job.c
-authenticator.lo: sa/authenticators/authenticator.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT authenticator.lo -MD -MP -MF $(DEPDIR)/authenticator.Tpo -c -o authenticator.lo `test -f 'sa/authenticators/authenticator.c' || echo '$(srcdir)/'`sa/authenticators/authenticator.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/authenticator.Tpo $(DEPDIR)/authenticator.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/authenticator.c' object='authenticator.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o authenticator.lo `test -f 'sa/authenticators/authenticator.c' || echo '$(srcdir)/'`sa/authenticators/authenticator.c
-
-eap_authenticator.lo: sa/authenticators/eap_authenticator.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT eap_authenticator.lo -MD -MP -MF $(DEPDIR)/eap_authenticator.Tpo -c -o eap_authenticator.lo `test -f 'sa/authenticators/eap_authenticator.c' || echo '$(srcdir)/'`sa/authenticators/eap_authenticator.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/eap_authenticator.Tpo $(DEPDIR)/eap_authenticator.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/eap_authenticator.c' object='eap_authenticator.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o eap_authenticator.lo `test -f 'sa/authenticators/eap_authenticator.c' || echo '$(srcdir)/'`sa/authenticators/eap_authenticator.c
-
-eap_method.lo: sa/authenticators/eap/eap_method.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT eap_method.lo -MD -MP -MF $(DEPDIR)/eap_method.Tpo -c -o eap_method.lo `test -f 'sa/authenticators/eap/eap_method.c' || echo '$(srcdir)/'`sa/authenticators/eap/eap_method.c
+eap_method.lo: sa/eap/eap_method.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT eap_method.lo -MD -MP -MF $(DEPDIR)/eap_method.Tpo -c -o eap_method.lo `test -f 'sa/eap/eap_method.c' || echo '$(srcdir)/'`sa/eap/eap_method.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/eap_method.Tpo $(DEPDIR)/eap_method.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/eap/eap_method.c' object='eap_method.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/eap/eap_method.c' object='eap_method.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o eap_method.lo `test -f 'sa/authenticators/eap/eap_method.c' || echo '$(srcdir)/'`sa/authenticators/eap/eap_method.c
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o eap_method.lo `test -f 'sa/eap/eap_method.c' || echo '$(srcdir)/'`sa/eap/eap_method.c
-eap_manager.lo: sa/authenticators/eap/eap_manager.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT eap_manager.lo -MD -MP -MF $(DEPDIR)/eap_manager.Tpo -c -o eap_manager.lo `test -f 'sa/authenticators/eap/eap_manager.c' || echo '$(srcdir)/'`sa/authenticators/eap/eap_manager.c
+eap_manager.lo: sa/eap/eap_manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT eap_manager.lo -MD -MP -MF $(DEPDIR)/eap_manager.Tpo -c -o eap_manager.lo `test -f 'sa/eap/eap_manager.c' || echo '$(srcdir)/'`sa/eap/eap_manager.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/eap_manager.Tpo $(DEPDIR)/eap_manager.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/eap/eap_manager.c' object='eap_manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/eap/eap_manager.c' object='eap_manager.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o eap_manager.lo `test -f 'sa/authenticators/eap/eap_manager.c' || echo '$(srcdir)/'`sa/authenticators/eap/eap_manager.c
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o eap_manager.lo `test -f 'sa/eap/eap_manager.c' || echo '$(srcdir)/'`sa/eap/eap_manager.c
-psk_authenticator.lo: sa/authenticators/psk_authenticator.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT psk_authenticator.lo -MD -MP -MF $(DEPDIR)/psk_authenticator.Tpo -c -o psk_authenticator.lo `test -f 'sa/authenticators/psk_authenticator.c' || echo '$(srcdir)/'`sa/authenticators/psk_authenticator.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/psk_authenticator.Tpo $(DEPDIR)/psk_authenticator.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/psk_authenticator.c' object='psk_authenticator.lo' libtool=yes @AMDEPBACKSLASH@
+xauth_method.lo: sa/xauth/xauth_method.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xauth_method.lo -MD -MP -MF $(DEPDIR)/xauth_method.Tpo -c -o xauth_method.lo `test -f 'sa/xauth/xauth_method.c' || echo '$(srcdir)/'`sa/xauth/xauth_method.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/xauth_method.Tpo $(DEPDIR)/xauth_method.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/xauth/xauth_method.c' object='xauth_method.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o psk_authenticator.lo `test -f 'sa/authenticators/psk_authenticator.c' || echo '$(srcdir)/'`sa/authenticators/psk_authenticator.c
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xauth_method.lo `test -f 'sa/xauth/xauth_method.c' || echo '$(srcdir)/'`sa/xauth/xauth_method.c
-pubkey_authenticator.lo: sa/authenticators/pubkey_authenticator.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pubkey_authenticator.lo -MD -MP -MF $(DEPDIR)/pubkey_authenticator.Tpo -c -o pubkey_authenticator.lo `test -f 'sa/authenticators/pubkey_authenticator.c' || echo '$(srcdir)/'`sa/authenticators/pubkey_authenticator.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pubkey_authenticator.Tpo $(DEPDIR)/pubkey_authenticator.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/pubkey_authenticator.c' object='pubkey_authenticator.lo' libtool=yes @AMDEPBACKSLASH@
+xauth_manager.lo: sa/xauth/xauth_manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xauth_manager.lo -MD -MP -MF $(DEPDIR)/xauth_manager.Tpo -c -o xauth_manager.lo `test -f 'sa/xauth/xauth_manager.c' || echo '$(srcdir)/'`sa/xauth/xauth_manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/xauth_manager.Tpo $(DEPDIR)/xauth_manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/xauth/xauth_manager.c' object='xauth_manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xauth_manager.lo `test -f 'sa/xauth/xauth_manager.c' || echo '$(srcdir)/'`sa/xauth/xauth_manager.c
+
+authenticator.lo: sa/authenticator.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT authenticator.lo -MD -MP -MF $(DEPDIR)/authenticator.Tpo -c -o authenticator.lo `test -f 'sa/authenticator.c' || echo '$(srcdir)/'`sa/authenticator.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/authenticator.Tpo $(DEPDIR)/authenticator.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticator.c' object='authenticator.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pubkey_authenticator.lo `test -f 'sa/authenticators/pubkey_authenticator.c' || echo '$(srcdir)/'`sa/authenticators/pubkey_authenticator.c
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o authenticator.lo `test -f 'sa/authenticator.c' || echo '$(srcdir)/'`sa/authenticator.c
child_sa.lo: sa/child_sa.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT child_sa.lo -MD -MP -MF $(DEPDIR)/child_sa.Tpo -c -o child_sa.lo `test -f 'sa/child_sa.c' || echo '$(srcdir)/'`sa/child_sa.c
@@ -1437,6 +1560,13 @@ ike_sa_id.lo: sa/ike_sa_id.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_sa_id.lo `test -f 'sa/ike_sa_id.c' || echo '$(srcdir)/'`sa/ike_sa_id.c
+keymat.lo: sa/keymat.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT keymat.lo -MD -MP -MF $(DEPDIR)/keymat.Tpo -c -o keymat.lo `test -f 'sa/keymat.c' || echo '$(srcdir)/'`sa/keymat.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/keymat.Tpo $(DEPDIR)/keymat.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/keymat.c' object='keymat.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o keymat.lo `test -f 'sa/keymat.c' || echo '$(srcdir)/'`sa/keymat.c
+
ike_sa_manager.lo: sa/ike_sa_manager.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_sa_manager.lo -MD -MP -MF $(DEPDIR)/ike_sa_manager.Tpo -c -o ike_sa_manager.lo `test -f 'sa/ike_sa_manager.c' || echo '$(srcdir)/'`sa/ike_sa_manager.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_sa_manager.Tpo $(DEPDIR)/ike_sa_manager.Plo
@@ -1451,13 +1581,6 @@ task_manager.lo: sa/task_manager.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o task_manager.lo `test -f 'sa/task_manager.c' || echo '$(srcdir)/'`sa/task_manager.c
-keymat.lo: sa/keymat.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT keymat.lo -MD -MP -MF $(DEPDIR)/keymat.Tpo -c -o keymat.lo `test -f 'sa/keymat.c' || echo '$(srcdir)/'`sa/keymat.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/keymat.Tpo $(DEPDIR)/keymat.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/keymat.c' object='keymat.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o keymat.lo `test -f 'sa/keymat.c' || echo '$(srcdir)/'`sa/keymat.c
-
shunt_manager.lo: sa/shunt_manager.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT shunt_manager.lo -MD -MP -MF $(DEPDIR)/shunt_manager.Tpo -c -o shunt_manager.lo `test -f 'sa/shunt_manager.c' || echo '$(srcdir)/'`sa/shunt_manager.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/shunt_manager.Tpo $(DEPDIR)/shunt_manager.Plo
@@ -1472,124 +1595,306 @@ trap_manager.lo: sa/trap_manager.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o trap_manager.lo `test -f 'sa/trap_manager.c' || echo '$(srcdir)/'`sa/trap_manager.c
-child_create.lo: sa/tasks/child_create.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT child_create.lo -MD -MP -MF $(DEPDIR)/child_create.Tpo -c -o child_create.lo `test -f 'sa/tasks/child_create.c' || echo '$(srcdir)/'`sa/tasks/child_create.c
+task.lo: sa/task.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT task.lo -MD -MP -MF $(DEPDIR)/task.Tpo -c -o task.lo `test -f 'sa/task.c' || echo '$(srcdir)/'`sa/task.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/task.Tpo $(DEPDIR)/task.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/task.c' object='task.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o task.lo `test -f 'sa/task.c' || echo '$(srcdir)/'`sa/task.c
+
+keymat_v2.lo: sa/ikev2/keymat_v2.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT keymat_v2.lo -MD -MP -MF $(DEPDIR)/keymat_v2.Tpo -c -o keymat_v2.lo `test -f 'sa/ikev2/keymat_v2.c' || echo '$(srcdir)/'`sa/ikev2/keymat_v2.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/keymat_v2.Tpo $(DEPDIR)/keymat_v2.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev2/keymat_v2.c' object='keymat_v2.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o keymat_v2.lo `test -f 'sa/ikev2/keymat_v2.c' || echo '$(srcdir)/'`sa/ikev2/keymat_v2.c
+
+task_manager_v2.lo: sa/ikev2/task_manager_v2.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT task_manager_v2.lo -MD -MP -MF $(DEPDIR)/task_manager_v2.Tpo -c -o task_manager_v2.lo `test -f 'sa/ikev2/task_manager_v2.c' || echo '$(srcdir)/'`sa/ikev2/task_manager_v2.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/task_manager_v2.Tpo $(DEPDIR)/task_manager_v2.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev2/task_manager_v2.c' object='task_manager_v2.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o task_manager_v2.lo `test -f 'sa/ikev2/task_manager_v2.c' || echo '$(srcdir)/'`sa/ikev2/task_manager_v2.c
+
+eap_authenticator.lo: sa/ikev2/authenticators/eap_authenticator.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT eap_authenticator.lo -MD -MP -MF $(DEPDIR)/eap_authenticator.Tpo -c -o eap_authenticator.lo `test -f 'sa/ikev2/authenticators/eap_authenticator.c' || echo '$(srcdir)/'`sa/ikev2/authenticators/eap_authenticator.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/eap_authenticator.Tpo $(DEPDIR)/eap_authenticator.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev2/authenticators/eap_authenticator.c' object='eap_authenticator.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o eap_authenticator.lo `test -f 'sa/ikev2/authenticators/eap_authenticator.c' || echo '$(srcdir)/'`sa/ikev2/authenticators/eap_authenticator.c
+
+psk_authenticator.lo: sa/ikev2/authenticators/psk_authenticator.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT psk_authenticator.lo -MD -MP -MF $(DEPDIR)/psk_authenticator.Tpo -c -o psk_authenticator.lo `test -f 'sa/ikev2/authenticators/psk_authenticator.c' || echo '$(srcdir)/'`sa/ikev2/authenticators/psk_authenticator.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/psk_authenticator.Tpo $(DEPDIR)/psk_authenticator.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev2/authenticators/psk_authenticator.c' object='psk_authenticator.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o psk_authenticator.lo `test -f 'sa/ikev2/authenticators/psk_authenticator.c' || echo '$(srcdir)/'`sa/ikev2/authenticators/psk_authenticator.c
+
+pubkey_authenticator.lo: sa/ikev2/authenticators/pubkey_authenticator.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pubkey_authenticator.lo -MD -MP -MF $(DEPDIR)/pubkey_authenticator.Tpo -c -o pubkey_authenticator.lo `test -f 'sa/ikev2/authenticators/pubkey_authenticator.c' || echo '$(srcdir)/'`sa/ikev2/authenticators/pubkey_authenticator.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pubkey_authenticator.Tpo $(DEPDIR)/pubkey_authenticator.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev2/authenticators/pubkey_authenticator.c' object='pubkey_authenticator.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pubkey_authenticator.lo `test -f 'sa/ikev2/authenticators/pubkey_authenticator.c' || echo '$(srcdir)/'`sa/ikev2/authenticators/pubkey_authenticator.c
+
+child_create.lo: sa/ikev2/tasks/child_create.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT child_create.lo -MD -MP -MF $(DEPDIR)/child_create.Tpo -c -o child_create.lo `test -f 'sa/ikev2/tasks/child_create.c' || echo '$(srcdir)/'`sa/ikev2/tasks/child_create.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/child_create.Tpo $(DEPDIR)/child_create.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/child_create.c' object='child_create.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev2/tasks/child_create.c' object='child_create.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o child_create.lo `test -f 'sa/tasks/child_create.c' || echo '$(srcdir)/'`sa/tasks/child_create.c
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o child_create.lo `test -f 'sa/ikev2/tasks/child_create.c' || echo '$(srcdir)/'`sa/ikev2/tasks/child_create.c
-child_delete.lo: sa/tasks/child_delete.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT child_delete.lo -MD -MP -MF $(DEPDIR)/child_delete.Tpo -c -o child_delete.lo `test -f 'sa/tasks/child_delete.c' || echo '$(srcdir)/'`sa/tasks/child_delete.c
+child_delete.lo: sa/ikev2/tasks/child_delete.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT child_delete.lo -MD -MP -MF $(DEPDIR)/child_delete.Tpo -c -o child_delete.lo `test -f 'sa/ikev2/tasks/child_delete.c' || echo '$(srcdir)/'`sa/ikev2/tasks/child_delete.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/child_delete.Tpo $(DEPDIR)/child_delete.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/child_delete.c' object='child_delete.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev2/tasks/child_delete.c' object='child_delete.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o child_delete.lo `test -f 'sa/tasks/child_delete.c' || echo '$(srcdir)/'`sa/tasks/child_delete.c
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o child_delete.lo `test -f 'sa/ikev2/tasks/child_delete.c' || echo '$(srcdir)/'`sa/ikev2/tasks/child_delete.c
-child_rekey.lo: sa/tasks/child_rekey.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT child_rekey.lo -MD -MP -MF $(DEPDIR)/child_rekey.Tpo -c -o child_rekey.lo `test -f 'sa/tasks/child_rekey.c' || echo '$(srcdir)/'`sa/tasks/child_rekey.c
+child_rekey.lo: sa/ikev2/tasks/child_rekey.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT child_rekey.lo -MD -MP -MF $(DEPDIR)/child_rekey.Tpo -c -o child_rekey.lo `test -f 'sa/ikev2/tasks/child_rekey.c' || echo '$(srcdir)/'`sa/ikev2/tasks/child_rekey.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/child_rekey.Tpo $(DEPDIR)/child_rekey.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/child_rekey.c' object='child_rekey.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev2/tasks/child_rekey.c' object='child_rekey.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o child_rekey.lo `test -f 'sa/tasks/child_rekey.c' || echo '$(srcdir)/'`sa/tasks/child_rekey.c
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o child_rekey.lo `test -f 'sa/ikev2/tasks/child_rekey.c' || echo '$(srcdir)/'`sa/ikev2/tasks/child_rekey.c
-ike_auth.lo: sa/tasks/ike_auth.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_auth.lo -MD -MP -MF $(DEPDIR)/ike_auth.Tpo -c -o ike_auth.lo `test -f 'sa/tasks/ike_auth.c' || echo '$(srcdir)/'`sa/tasks/ike_auth.c
+ike_auth.lo: sa/ikev2/tasks/ike_auth.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_auth.lo -MD -MP -MF $(DEPDIR)/ike_auth.Tpo -c -o ike_auth.lo `test -f 'sa/ikev2/tasks/ike_auth.c' || echo '$(srcdir)/'`sa/ikev2/tasks/ike_auth.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_auth.Tpo $(DEPDIR)/ike_auth.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_auth.c' object='ike_auth.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev2/tasks/ike_auth.c' object='ike_auth.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_auth.lo `test -f 'sa/tasks/ike_auth.c' || echo '$(srcdir)/'`sa/tasks/ike_auth.c
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_auth.lo `test -f 'sa/ikev2/tasks/ike_auth.c' || echo '$(srcdir)/'`sa/ikev2/tasks/ike_auth.c
-ike_cert_pre.lo: sa/tasks/ike_cert_pre.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_cert_pre.lo -MD -MP -MF $(DEPDIR)/ike_cert_pre.Tpo -c -o ike_cert_pre.lo `test -f 'sa/tasks/ike_cert_pre.c' || echo '$(srcdir)/'`sa/tasks/ike_cert_pre.c
+ike_cert_pre.lo: sa/ikev2/tasks/ike_cert_pre.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_cert_pre.lo -MD -MP -MF $(DEPDIR)/ike_cert_pre.Tpo -c -o ike_cert_pre.lo `test -f 'sa/ikev2/tasks/ike_cert_pre.c' || echo '$(srcdir)/'`sa/ikev2/tasks/ike_cert_pre.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_cert_pre.Tpo $(DEPDIR)/ike_cert_pre.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_cert_pre.c' object='ike_cert_pre.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev2/tasks/ike_cert_pre.c' object='ike_cert_pre.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_cert_pre.lo `test -f 'sa/tasks/ike_cert_pre.c' || echo '$(srcdir)/'`sa/tasks/ike_cert_pre.c
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_cert_pre.lo `test -f 'sa/ikev2/tasks/ike_cert_pre.c' || echo '$(srcdir)/'`sa/ikev2/tasks/ike_cert_pre.c
-ike_cert_post.lo: sa/tasks/ike_cert_post.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_cert_post.lo -MD -MP -MF $(DEPDIR)/ike_cert_post.Tpo -c -o ike_cert_post.lo `test -f 'sa/tasks/ike_cert_post.c' || echo '$(srcdir)/'`sa/tasks/ike_cert_post.c
+ike_cert_post.lo: sa/ikev2/tasks/ike_cert_post.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_cert_post.lo -MD -MP -MF $(DEPDIR)/ike_cert_post.Tpo -c -o ike_cert_post.lo `test -f 'sa/ikev2/tasks/ike_cert_post.c' || echo '$(srcdir)/'`sa/ikev2/tasks/ike_cert_post.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_cert_post.Tpo $(DEPDIR)/ike_cert_post.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_cert_post.c' object='ike_cert_post.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev2/tasks/ike_cert_post.c' object='ike_cert_post.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_cert_post.lo `test -f 'sa/tasks/ike_cert_post.c' || echo '$(srcdir)/'`sa/tasks/ike_cert_post.c
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_cert_post.lo `test -f 'sa/ikev2/tasks/ike_cert_post.c' || echo '$(srcdir)/'`sa/ikev2/tasks/ike_cert_post.c
-ike_config.lo: sa/tasks/ike_config.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_config.lo -MD -MP -MF $(DEPDIR)/ike_config.Tpo -c -o ike_config.lo `test -f 'sa/tasks/ike_config.c' || echo '$(srcdir)/'`sa/tasks/ike_config.c
+ike_config.lo: sa/ikev2/tasks/ike_config.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_config.lo -MD -MP -MF $(DEPDIR)/ike_config.Tpo -c -o ike_config.lo `test -f 'sa/ikev2/tasks/ike_config.c' || echo '$(srcdir)/'`sa/ikev2/tasks/ike_config.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_config.Tpo $(DEPDIR)/ike_config.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_config.c' object='ike_config.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev2/tasks/ike_config.c' object='ike_config.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_config.lo `test -f 'sa/tasks/ike_config.c' || echo '$(srcdir)/'`sa/tasks/ike_config.c
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_config.lo `test -f 'sa/ikev2/tasks/ike_config.c' || echo '$(srcdir)/'`sa/ikev2/tasks/ike_config.c
-ike_delete.lo: sa/tasks/ike_delete.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_delete.lo -MD -MP -MF $(DEPDIR)/ike_delete.Tpo -c -o ike_delete.lo `test -f 'sa/tasks/ike_delete.c' || echo '$(srcdir)/'`sa/tasks/ike_delete.c
+ike_delete.lo: sa/ikev2/tasks/ike_delete.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_delete.lo -MD -MP -MF $(DEPDIR)/ike_delete.Tpo -c -o ike_delete.lo `test -f 'sa/ikev2/tasks/ike_delete.c' || echo '$(srcdir)/'`sa/ikev2/tasks/ike_delete.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_delete.Tpo $(DEPDIR)/ike_delete.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_delete.c' object='ike_delete.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev2/tasks/ike_delete.c' object='ike_delete.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_delete.lo `test -f 'sa/tasks/ike_delete.c' || echo '$(srcdir)/'`sa/tasks/ike_delete.c
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_delete.lo `test -f 'sa/ikev2/tasks/ike_delete.c' || echo '$(srcdir)/'`sa/ikev2/tasks/ike_delete.c
-ike_dpd.lo: sa/tasks/ike_dpd.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_dpd.lo -MD -MP -MF $(DEPDIR)/ike_dpd.Tpo -c -o ike_dpd.lo `test -f 'sa/tasks/ike_dpd.c' || echo '$(srcdir)/'`sa/tasks/ike_dpd.c
+ike_dpd.lo: sa/ikev2/tasks/ike_dpd.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_dpd.lo -MD -MP -MF $(DEPDIR)/ike_dpd.Tpo -c -o ike_dpd.lo `test -f 'sa/ikev2/tasks/ike_dpd.c' || echo '$(srcdir)/'`sa/ikev2/tasks/ike_dpd.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_dpd.Tpo $(DEPDIR)/ike_dpd.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_dpd.c' object='ike_dpd.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev2/tasks/ike_dpd.c' object='ike_dpd.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_dpd.lo `test -f 'sa/tasks/ike_dpd.c' || echo '$(srcdir)/'`sa/tasks/ike_dpd.c
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_dpd.lo `test -f 'sa/ikev2/tasks/ike_dpd.c' || echo '$(srcdir)/'`sa/ikev2/tasks/ike_dpd.c
-ike_init.lo: sa/tasks/ike_init.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_init.lo -MD -MP -MF $(DEPDIR)/ike_init.Tpo -c -o ike_init.lo `test -f 'sa/tasks/ike_init.c' || echo '$(srcdir)/'`sa/tasks/ike_init.c
+ike_init.lo: sa/ikev2/tasks/ike_init.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_init.lo -MD -MP -MF $(DEPDIR)/ike_init.Tpo -c -o ike_init.lo `test -f 'sa/ikev2/tasks/ike_init.c' || echo '$(srcdir)/'`sa/ikev2/tasks/ike_init.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_init.Tpo $(DEPDIR)/ike_init.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_init.c' object='ike_init.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev2/tasks/ike_init.c' object='ike_init.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_init.lo `test -f 'sa/tasks/ike_init.c' || echo '$(srcdir)/'`sa/tasks/ike_init.c
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_init.lo `test -f 'sa/ikev2/tasks/ike_init.c' || echo '$(srcdir)/'`sa/ikev2/tasks/ike_init.c
-ike_natd.lo: sa/tasks/ike_natd.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_natd.lo -MD -MP -MF $(DEPDIR)/ike_natd.Tpo -c -o ike_natd.lo `test -f 'sa/tasks/ike_natd.c' || echo '$(srcdir)/'`sa/tasks/ike_natd.c
+ike_natd.lo: sa/ikev2/tasks/ike_natd.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_natd.lo -MD -MP -MF $(DEPDIR)/ike_natd.Tpo -c -o ike_natd.lo `test -f 'sa/ikev2/tasks/ike_natd.c' || echo '$(srcdir)/'`sa/ikev2/tasks/ike_natd.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_natd.Tpo $(DEPDIR)/ike_natd.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_natd.c' object='ike_natd.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev2/tasks/ike_natd.c' object='ike_natd.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_natd.lo `test -f 'sa/tasks/ike_natd.c' || echo '$(srcdir)/'`sa/tasks/ike_natd.c
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_natd.lo `test -f 'sa/ikev2/tasks/ike_natd.c' || echo '$(srcdir)/'`sa/ikev2/tasks/ike_natd.c
-ike_mobike.lo: sa/tasks/ike_mobike.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_mobike.lo -MD -MP -MF $(DEPDIR)/ike_mobike.Tpo -c -o ike_mobike.lo `test -f 'sa/tasks/ike_mobike.c' || echo '$(srcdir)/'`sa/tasks/ike_mobike.c
+ike_mobike.lo: sa/ikev2/tasks/ike_mobike.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_mobike.lo -MD -MP -MF $(DEPDIR)/ike_mobike.Tpo -c -o ike_mobike.lo `test -f 'sa/ikev2/tasks/ike_mobike.c' || echo '$(srcdir)/'`sa/ikev2/tasks/ike_mobike.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_mobike.Tpo $(DEPDIR)/ike_mobike.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_mobike.c' object='ike_mobike.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev2/tasks/ike_mobike.c' object='ike_mobike.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_mobike.lo `test -f 'sa/tasks/ike_mobike.c' || echo '$(srcdir)/'`sa/tasks/ike_mobike.c
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_mobike.lo `test -f 'sa/ikev2/tasks/ike_mobike.c' || echo '$(srcdir)/'`sa/ikev2/tasks/ike_mobike.c
-ike_rekey.lo: sa/tasks/ike_rekey.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_rekey.lo -MD -MP -MF $(DEPDIR)/ike_rekey.Tpo -c -o ike_rekey.lo `test -f 'sa/tasks/ike_rekey.c' || echo '$(srcdir)/'`sa/tasks/ike_rekey.c
+ike_rekey.lo: sa/ikev2/tasks/ike_rekey.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_rekey.lo -MD -MP -MF $(DEPDIR)/ike_rekey.Tpo -c -o ike_rekey.lo `test -f 'sa/ikev2/tasks/ike_rekey.c' || echo '$(srcdir)/'`sa/ikev2/tasks/ike_rekey.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_rekey.Tpo $(DEPDIR)/ike_rekey.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_rekey.c' object='ike_rekey.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev2/tasks/ike_rekey.c' object='ike_rekey.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_rekey.lo `test -f 'sa/tasks/ike_rekey.c' || echo '$(srcdir)/'`sa/tasks/ike_rekey.c
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_rekey.lo `test -f 'sa/ikev2/tasks/ike_rekey.c' || echo '$(srcdir)/'`sa/ikev2/tasks/ike_rekey.c
-ike_reauth.lo: sa/tasks/ike_reauth.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_reauth.lo -MD -MP -MF $(DEPDIR)/ike_reauth.Tpo -c -o ike_reauth.lo `test -f 'sa/tasks/ike_reauth.c' || echo '$(srcdir)/'`sa/tasks/ike_reauth.c
+ike_reauth.lo: sa/ikev2/tasks/ike_reauth.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_reauth.lo -MD -MP -MF $(DEPDIR)/ike_reauth.Tpo -c -o ike_reauth.lo `test -f 'sa/ikev2/tasks/ike_reauth.c' || echo '$(srcdir)/'`sa/ikev2/tasks/ike_reauth.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_reauth.Tpo $(DEPDIR)/ike_reauth.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_reauth.c' object='ike_reauth.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev2/tasks/ike_reauth.c' object='ike_reauth.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_reauth.lo `test -f 'sa/tasks/ike_reauth.c' || echo '$(srcdir)/'`sa/tasks/ike_reauth.c
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_reauth.lo `test -f 'sa/ikev2/tasks/ike_reauth.c' || echo '$(srcdir)/'`sa/ikev2/tasks/ike_reauth.c
-ike_auth_lifetime.lo: sa/tasks/ike_auth_lifetime.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_auth_lifetime.lo -MD -MP -MF $(DEPDIR)/ike_auth_lifetime.Tpo -c -o ike_auth_lifetime.lo `test -f 'sa/tasks/ike_auth_lifetime.c' || echo '$(srcdir)/'`sa/tasks/ike_auth_lifetime.c
+ike_auth_lifetime.lo: sa/ikev2/tasks/ike_auth_lifetime.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_auth_lifetime.lo -MD -MP -MF $(DEPDIR)/ike_auth_lifetime.Tpo -c -o ike_auth_lifetime.lo `test -f 'sa/ikev2/tasks/ike_auth_lifetime.c' || echo '$(srcdir)/'`sa/ikev2/tasks/ike_auth_lifetime.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_auth_lifetime.Tpo $(DEPDIR)/ike_auth_lifetime.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_auth_lifetime.c' object='ike_auth_lifetime.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev2/tasks/ike_auth_lifetime.c' object='ike_auth_lifetime.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_auth_lifetime.lo `test -f 'sa/tasks/ike_auth_lifetime.c' || echo '$(srcdir)/'`sa/tasks/ike_auth_lifetime.c
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_auth_lifetime.lo `test -f 'sa/ikev2/tasks/ike_auth_lifetime.c' || echo '$(srcdir)/'`sa/ikev2/tasks/ike_auth_lifetime.c
-ike_vendor.lo: sa/tasks/ike_vendor.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_vendor.lo -MD -MP -MF $(DEPDIR)/ike_vendor.Tpo -c -o ike_vendor.lo `test -f 'sa/tasks/ike_vendor.c' || echo '$(srcdir)/'`sa/tasks/ike_vendor.c
+ike_vendor.lo: sa/ikev2/tasks/ike_vendor.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_vendor.lo -MD -MP -MF $(DEPDIR)/ike_vendor.Tpo -c -o ike_vendor.lo `test -f 'sa/ikev2/tasks/ike_vendor.c' || echo '$(srcdir)/'`sa/ikev2/tasks/ike_vendor.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_vendor.Tpo $(DEPDIR)/ike_vendor.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_vendor.c' object='ike_vendor.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev2/tasks/ike_vendor.c' object='ike_vendor.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_vendor.lo `test -f 'sa/tasks/ike_vendor.c' || echo '$(srcdir)/'`sa/tasks/ike_vendor.c
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_vendor.lo `test -f 'sa/ikev2/tasks/ike_vendor.c' || echo '$(srcdir)/'`sa/ikev2/tasks/ike_vendor.c
-task.lo: sa/tasks/task.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT task.lo -MD -MP -MF $(DEPDIR)/task.Tpo -c -o task.lo `test -f 'sa/tasks/task.c' || echo '$(srcdir)/'`sa/tasks/task.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/task.Tpo $(DEPDIR)/task.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/task.c' object='task.lo' libtool=yes @AMDEPBACKSLASH@
+keymat_v1.lo: sa/ikev1/keymat_v1.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT keymat_v1.lo -MD -MP -MF $(DEPDIR)/keymat_v1.Tpo -c -o keymat_v1.lo `test -f 'sa/ikev1/keymat_v1.c' || echo '$(srcdir)/'`sa/ikev1/keymat_v1.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/keymat_v1.Tpo $(DEPDIR)/keymat_v1.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev1/keymat_v1.c' object='keymat_v1.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o keymat_v1.lo `test -f 'sa/ikev1/keymat_v1.c' || echo '$(srcdir)/'`sa/ikev1/keymat_v1.c
+
+task_manager_v1.lo: sa/ikev1/task_manager_v1.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT task_manager_v1.lo -MD -MP -MF $(DEPDIR)/task_manager_v1.Tpo -c -o task_manager_v1.lo `test -f 'sa/ikev1/task_manager_v1.c' || echo '$(srcdir)/'`sa/ikev1/task_manager_v1.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/task_manager_v1.Tpo $(DEPDIR)/task_manager_v1.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev1/task_manager_v1.c' object='task_manager_v1.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o task_manager_v1.lo `test -f 'sa/ikev1/task_manager_v1.c' || echo '$(srcdir)/'`sa/ikev1/task_manager_v1.c
+
+psk_v1_authenticator.lo: sa/ikev1/authenticators/psk_v1_authenticator.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT psk_v1_authenticator.lo -MD -MP -MF $(DEPDIR)/psk_v1_authenticator.Tpo -c -o psk_v1_authenticator.lo `test -f 'sa/ikev1/authenticators/psk_v1_authenticator.c' || echo '$(srcdir)/'`sa/ikev1/authenticators/psk_v1_authenticator.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/psk_v1_authenticator.Tpo $(DEPDIR)/psk_v1_authenticator.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev1/authenticators/psk_v1_authenticator.c' object='psk_v1_authenticator.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o psk_v1_authenticator.lo `test -f 'sa/ikev1/authenticators/psk_v1_authenticator.c' || echo '$(srcdir)/'`sa/ikev1/authenticators/psk_v1_authenticator.c
+
+pubkey_v1_authenticator.lo: sa/ikev1/authenticators/pubkey_v1_authenticator.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pubkey_v1_authenticator.lo -MD -MP -MF $(DEPDIR)/pubkey_v1_authenticator.Tpo -c -o pubkey_v1_authenticator.lo `test -f 'sa/ikev1/authenticators/pubkey_v1_authenticator.c' || echo '$(srcdir)/'`sa/ikev1/authenticators/pubkey_v1_authenticator.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pubkey_v1_authenticator.Tpo $(DEPDIR)/pubkey_v1_authenticator.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev1/authenticators/pubkey_v1_authenticator.c' object='pubkey_v1_authenticator.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pubkey_v1_authenticator.lo `test -f 'sa/ikev1/authenticators/pubkey_v1_authenticator.c' || echo '$(srcdir)/'`sa/ikev1/authenticators/pubkey_v1_authenticator.c
+
+hybrid_authenticator.lo: sa/ikev1/authenticators/hybrid_authenticator.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT hybrid_authenticator.lo -MD -MP -MF $(DEPDIR)/hybrid_authenticator.Tpo -c -o hybrid_authenticator.lo `test -f 'sa/ikev1/authenticators/hybrid_authenticator.c' || echo '$(srcdir)/'`sa/ikev1/authenticators/hybrid_authenticator.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/hybrid_authenticator.Tpo $(DEPDIR)/hybrid_authenticator.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev1/authenticators/hybrid_authenticator.c' object='hybrid_authenticator.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o hybrid_authenticator.lo `test -f 'sa/ikev1/authenticators/hybrid_authenticator.c' || echo '$(srcdir)/'`sa/ikev1/authenticators/hybrid_authenticator.c
+
+phase1.lo: sa/ikev1/phase1.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT phase1.lo -MD -MP -MF $(DEPDIR)/phase1.Tpo -c -o phase1.lo `test -f 'sa/ikev1/phase1.c' || echo '$(srcdir)/'`sa/ikev1/phase1.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/phase1.Tpo $(DEPDIR)/phase1.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev1/phase1.c' object='phase1.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o phase1.lo `test -f 'sa/ikev1/phase1.c' || echo '$(srcdir)/'`sa/ikev1/phase1.c
+
+main_mode.lo: sa/ikev1/tasks/main_mode.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT main_mode.lo -MD -MP -MF $(DEPDIR)/main_mode.Tpo -c -o main_mode.lo `test -f 'sa/ikev1/tasks/main_mode.c' || echo '$(srcdir)/'`sa/ikev1/tasks/main_mode.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/main_mode.Tpo $(DEPDIR)/main_mode.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev1/tasks/main_mode.c' object='main_mode.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o main_mode.lo `test -f 'sa/ikev1/tasks/main_mode.c' || echo '$(srcdir)/'`sa/ikev1/tasks/main_mode.c
+
+aggressive_mode.lo: sa/ikev1/tasks/aggressive_mode.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT aggressive_mode.lo -MD -MP -MF $(DEPDIR)/aggressive_mode.Tpo -c -o aggressive_mode.lo `test -f 'sa/ikev1/tasks/aggressive_mode.c' || echo '$(srcdir)/'`sa/ikev1/tasks/aggressive_mode.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/aggressive_mode.Tpo $(DEPDIR)/aggressive_mode.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev1/tasks/aggressive_mode.c' object='aggressive_mode.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o aggressive_mode.lo `test -f 'sa/ikev1/tasks/aggressive_mode.c' || echo '$(srcdir)/'`sa/ikev1/tasks/aggressive_mode.c
+
+informational.lo: sa/ikev1/tasks/informational.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT informational.lo -MD -MP -MF $(DEPDIR)/informational.Tpo -c -o informational.lo `test -f 'sa/ikev1/tasks/informational.c' || echo '$(srcdir)/'`sa/ikev1/tasks/informational.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/informational.Tpo $(DEPDIR)/informational.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev1/tasks/informational.c' object='informational.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o informational.lo `test -f 'sa/ikev1/tasks/informational.c' || echo '$(srcdir)/'`sa/ikev1/tasks/informational.c
+
+isakmp_cert_pre.lo: sa/ikev1/tasks/isakmp_cert_pre.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT isakmp_cert_pre.lo -MD -MP -MF $(DEPDIR)/isakmp_cert_pre.Tpo -c -o isakmp_cert_pre.lo `test -f 'sa/ikev1/tasks/isakmp_cert_pre.c' || echo '$(srcdir)/'`sa/ikev1/tasks/isakmp_cert_pre.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/isakmp_cert_pre.Tpo $(DEPDIR)/isakmp_cert_pre.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev1/tasks/isakmp_cert_pre.c' object='isakmp_cert_pre.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o isakmp_cert_pre.lo `test -f 'sa/ikev1/tasks/isakmp_cert_pre.c' || echo '$(srcdir)/'`sa/ikev1/tasks/isakmp_cert_pre.c
+
+isakmp_cert_post.lo: sa/ikev1/tasks/isakmp_cert_post.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT isakmp_cert_post.lo -MD -MP -MF $(DEPDIR)/isakmp_cert_post.Tpo -c -o isakmp_cert_post.lo `test -f 'sa/ikev1/tasks/isakmp_cert_post.c' || echo '$(srcdir)/'`sa/ikev1/tasks/isakmp_cert_post.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/isakmp_cert_post.Tpo $(DEPDIR)/isakmp_cert_post.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev1/tasks/isakmp_cert_post.c' object='isakmp_cert_post.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o isakmp_cert_post.lo `test -f 'sa/ikev1/tasks/isakmp_cert_post.c' || echo '$(srcdir)/'`sa/ikev1/tasks/isakmp_cert_post.c
+
+isakmp_natd.lo: sa/ikev1/tasks/isakmp_natd.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT isakmp_natd.lo -MD -MP -MF $(DEPDIR)/isakmp_natd.Tpo -c -o isakmp_natd.lo `test -f 'sa/ikev1/tasks/isakmp_natd.c' || echo '$(srcdir)/'`sa/ikev1/tasks/isakmp_natd.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/isakmp_natd.Tpo $(DEPDIR)/isakmp_natd.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev1/tasks/isakmp_natd.c' object='isakmp_natd.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o isakmp_natd.lo `test -f 'sa/ikev1/tasks/isakmp_natd.c' || echo '$(srcdir)/'`sa/ikev1/tasks/isakmp_natd.c
+
+isakmp_vendor.lo: sa/ikev1/tasks/isakmp_vendor.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT isakmp_vendor.lo -MD -MP -MF $(DEPDIR)/isakmp_vendor.Tpo -c -o isakmp_vendor.lo `test -f 'sa/ikev1/tasks/isakmp_vendor.c' || echo '$(srcdir)/'`sa/ikev1/tasks/isakmp_vendor.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/isakmp_vendor.Tpo $(DEPDIR)/isakmp_vendor.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev1/tasks/isakmp_vendor.c' object='isakmp_vendor.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o isakmp_vendor.lo `test -f 'sa/ikev1/tasks/isakmp_vendor.c' || echo '$(srcdir)/'`sa/ikev1/tasks/isakmp_vendor.c
+
+isakmp_delete.lo: sa/ikev1/tasks/isakmp_delete.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT isakmp_delete.lo -MD -MP -MF $(DEPDIR)/isakmp_delete.Tpo -c -o isakmp_delete.lo `test -f 'sa/ikev1/tasks/isakmp_delete.c' || echo '$(srcdir)/'`sa/ikev1/tasks/isakmp_delete.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/isakmp_delete.Tpo $(DEPDIR)/isakmp_delete.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev1/tasks/isakmp_delete.c' object='isakmp_delete.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o isakmp_delete.lo `test -f 'sa/ikev1/tasks/isakmp_delete.c' || echo '$(srcdir)/'`sa/ikev1/tasks/isakmp_delete.c
+
+isakmp_dpd.lo: sa/ikev1/tasks/isakmp_dpd.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT isakmp_dpd.lo -MD -MP -MF $(DEPDIR)/isakmp_dpd.Tpo -c -o isakmp_dpd.lo `test -f 'sa/ikev1/tasks/isakmp_dpd.c' || echo '$(srcdir)/'`sa/ikev1/tasks/isakmp_dpd.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/isakmp_dpd.Tpo $(DEPDIR)/isakmp_dpd.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev1/tasks/isakmp_dpd.c' object='isakmp_dpd.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o isakmp_dpd.lo `test -f 'sa/ikev1/tasks/isakmp_dpd.c' || echo '$(srcdir)/'`sa/ikev1/tasks/isakmp_dpd.c
+
+xauth.lo: sa/ikev1/tasks/xauth.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xauth.lo -MD -MP -MF $(DEPDIR)/xauth.Tpo -c -o xauth.lo `test -f 'sa/ikev1/tasks/xauth.c' || echo '$(srcdir)/'`sa/ikev1/tasks/xauth.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/xauth.Tpo $(DEPDIR)/xauth.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev1/tasks/xauth.c' object='xauth.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xauth.lo `test -f 'sa/ikev1/tasks/xauth.c' || echo '$(srcdir)/'`sa/ikev1/tasks/xauth.c
+
+quick_mode.lo: sa/ikev1/tasks/quick_mode.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT quick_mode.lo -MD -MP -MF $(DEPDIR)/quick_mode.Tpo -c -o quick_mode.lo `test -f 'sa/ikev1/tasks/quick_mode.c' || echo '$(srcdir)/'`sa/ikev1/tasks/quick_mode.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/quick_mode.Tpo $(DEPDIR)/quick_mode.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev1/tasks/quick_mode.c' object='quick_mode.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o quick_mode.lo `test -f 'sa/ikev1/tasks/quick_mode.c' || echo '$(srcdir)/'`sa/ikev1/tasks/quick_mode.c
+
+quick_delete.lo: sa/ikev1/tasks/quick_delete.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT quick_delete.lo -MD -MP -MF $(DEPDIR)/quick_delete.Tpo -c -o quick_delete.lo `test -f 'sa/ikev1/tasks/quick_delete.c' || echo '$(srcdir)/'`sa/ikev1/tasks/quick_delete.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/quick_delete.Tpo $(DEPDIR)/quick_delete.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev1/tasks/quick_delete.c' object='quick_delete.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o quick_delete.lo `test -f 'sa/ikev1/tasks/quick_delete.c' || echo '$(srcdir)/'`sa/ikev1/tasks/quick_delete.c
+
+mode_config.lo: sa/ikev1/tasks/mode_config.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mode_config.lo -MD -MP -MF $(DEPDIR)/mode_config.Tpo -c -o mode_config.lo `test -f 'sa/ikev1/tasks/mode_config.c' || echo '$(srcdir)/'`sa/ikev1/tasks/mode_config.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/mode_config.Tpo $(DEPDIR)/mode_config.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev1/tasks/mode_config.c' object='mode_config.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mode_config.lo `test -f 'sa/ikev1/tasks/mode_config.c' || echo '$(srcdir)/'`sa/ikev1/tasks/mode_config.c
+
+dpd_timeout_job.lo: processing/jobs/dpd_timeout_job.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dpd_timeout_job.lo -MD -MP -MF $(DEPDIR)/dpd_timeout_job.Tpo -c -o dpd_timeout_job.lo `test -f 'processing/jobs/dpd_timeout_job.c' || echo '$(srcdir)/'`processing/jobs/dpd_timeout_job.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/dpd_timeout_job.Tpo $(DEPDIR)/dpd_timeout_job.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/dpd_timeout_job.c' object='dpd_timeout_job.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dpd_timeout_job.lo `test -f 'processing/jobs/dpd_timeout_job.c' || echo '$(srcdir)/'`processing/jobs/dpd_timeout_job.c
+
+adopt_children_job.lo: processing/jobs/adopt_children_job.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT adopt_children_job.lo -MD -MP -MF $(DEPDIR)/adopt_children_job.Tpo -c -o adopt_children_job.lo `test -f 'processing/jobs/adopt_children_job.c' || echo '$(srcdir)/'`processing/jobs/adopt_children_job.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/adopt_children_job.Tpo $(DEPDIR)/adopt_children_job.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/adopt_children_job.c' object='adopt_children_job.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o task.lo `test -f 'sa/tasks/task.c' || echo '$(srcdir)/'`sa/tasks/task.c
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o adopt_children_job.lo `test -f 'processing/jobs/adopt_children_job.c' || echo '$(srcdir)/'`processing/jobs/adopt_children_job.c
endpoint_notify.lo: encoding/payloads/endpoint_notify.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT endpoint_notify.lo -MD -MP -MF $(DEPDIR)/endpoint_notify.Tpo -c -o endpoint_notify.lo `test -f 'encoding/payloads/endpoint_notify.c' || echo '$(srcdir)/'`encoding/payloads/endpoint_notify.c
@@ -1612,26 +1917,26 @@ mediation_job.lo: processing/jobs/mediation_job.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mediation_job.lo `test -f 'processing/jobs/mediation_job.c' || echo '$(srcdir)/'`processing/jobs/mediation_job.c
-connect_manager.lo: sa/connect_manager.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT connect_manager.lo -MD -MP -MF $(DEPDIR)/connect_manager.Tpo -c -o connect_manager.lo `test -f 'sa/connect_manager.c' || echo '$(srcdir)/'`sa/connect_manager.c
+connect_manager.lo: sa/ikev2/connect_manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT connect_manager.lo -MD -MP -MF $(DEPDIR)/connect_manager.Tpo -c -o connect_manager.lo `test -f 'sa/ikev2/connect_manager.c' || echo '$(srcdir)/'`sa/ikev2/connect_manager.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/connect_manager.Tpo $(DEPDIR)/connect_manager.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/connect_manager.c' object='connect_manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev2/connect_manager.c' object='connect_manager.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o connect_manager.lo `test -f 'sa/connect_manager.c' || echo '$(srcdir)/'`sa/connect_manager.c
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o connect_manager.lo `test -f 'sa/ikev2/connect_manager.c' || echo '$(srcdir)/'`sa/ikev2/connect_manager.c
-mediation_manager.lo: sa/mediation_manager.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mediation_manager.lo -MD -MP -MF $(DEPDIR)/mediation_manager.Tpo -c -o mediation_manager.lo `test -f 'sa/mediation_manager.c' || echo '$(srcdir)/'`sa/mediation_manager.c
+mediation_manager.lo: sa/ikev2/mediation_manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mediation_manager.lo -MD -MP -MF $(DEPDIR)/mediation_manager.Tpo -c -o mediation_manager.lo `test -f 'sa/ikev2/mediation_manager.c' || echo '$(srcdir)/'`sa/ikev2/mediation_manager.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/mediation_manager.Tpo $(DEPDIR)/mediation_manager.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/mediation_manager.c' object='mediation_manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev2/mediation_manager.c' object='mediation_manager.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mediation_manager.lo `test -f 'sa/mediation_manager.c' || echo '$(srcdir)/'`sa/mediation_manager.c
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mediation_manager.lo `test -f 'sa/ikev2/mediation_manager.c' || echo '$(srcdir)/'`sa/ikev2/mediation_manager.c
-ike_me.lo: sa/tasks/ike_me.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_me.lo -MD -MP -MF $(DEPDIR)/ike_me.Tpo -c -o ike_me.lo `test -f 'sa/tasks/ike_me.c' || echo '$(srcdir)/'`sa/tasks/ike_me.c
+ike_me.lo: sa/ikev2/tasks/ike_me.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_me.lo -MD -MP -MF $(DEPDIR)/ike_me.Tpo -c -o ike_me.lo `test -f 'sa/ikev2/tasks/ike_me.c' || echo '$(srcdir)/'`sa/ikev2/tasks/ike_me.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_me.Tpo $(DEPDIR)/ike_me.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_me.c' object='ike_me.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/ikev2/tasks/ike_me.c' object='ike_me.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_me.lo `test -f 'sa/tasks/ike_me.c' || echo '$(srcdir)/'`sa/tasks/ike_me.c
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_me.lo `test -f 'sa/ikev2/tasks/ike_me.c' || echo '$(srcdir)/'`sa/ikev2/tasks/ike_me.c
mostlyclean-libtool:
-rm -f *.lo
diff --git a/src/libcharon/bus/bus.c b/src/libcharon/bus/bus.c
index bf0ab2286..1f9592e6e 100644
--- a/src/libcharon/bus/bus.c
+++ b/src/libcharon/bus/bus.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2011-2012 Tobias Brunner
* Copyright (C) 2006 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -19,8 +20,8 @@
#include <threading/thread.h>
#include <threading/thread_value.h>
-#include <threading/condvar.h>
#include <threading/mutex.h>
+#include <threading/rwlock.h>
typedef struct private_bus_t private_bus_t;
@@ -34,16 +35,34 @@ struct private_bus_t {
bus_t public;
/**
- * List of registered listeners as entry_t's
+ * List of registered listeners as entry_t.
*/
linked_list_t *listeners;
/**
- * mutex to synchronize active listeners, recursively
+ * List of registered loggers for each log group as log_entry_t.
+ * Loggers are ordered by descending log level.
+ * The extra list stores all loggers so we can properly unregister them.
+ */
+ linked_list_t *loggers[DBG_MAX + 1];
+
+ /**
+ * Maximum log level of any registered logger for each log group.
+ * This allows to check quickly if a log message has to be logged at all.
+ */
+ level_t max_level[DBG_MAX + 1];
+
+ /**
+ * Mutex for the list of listeners, recursively.
*/
mutex_t *mutex;
/**
+ * Read-write lock for the list of loggers.
+ */
+ rwlock_t *log_lock;
+
+ /**
* Thread local storage the threads IKE_SA
*/
thread_value_t *thread_sa;
@@ -52,7 +71,7 @@ struct private_bus_t {
typedef struct entry_t entry_t;
/**
- * a listener entry, either active or passive
+ * a listener entry
*/
struct entry_t {
@@ -62,50 +81,42 @@ struct entry_t {
listener_t *listener;
/**
- * is this a active listen() call with a blocking thread
- */
- bool blocker;
-
- /**
* are we currently calling this listener
*/
int calling;
- /**
- * condvar where active listeners wait
- */
- condvar_t *condvar;
};
+typedef struct log_entry_t log_entry_t;
+
/**
- * create a listener entry
+ * a logger entry
*/
-static entry_t *entry_create(listener_t *listener, bool blocker)
-{
- entry_t *this = malloc_thing(entry_t);
+struct log_entry_t {
- this->listener = listener;
- this->blocker = blocker;
- this->calling = 0;
- this->condvar = condvar_create(CONDVAR_TYPE_DEFAULT);
+ /**
+ * registered logger interface
+ */
+ logger_t *logger;
- return this;
-}
+ /**
+ * registered log levels per group
+ */
+ level_t levels[DBG_MAX];
-/**
- * destroy an entry_t
- */
-static void entry_destroy(entry_t *entry)
-{
- entry->condvar->destroy(entry->condvar);
- free(entry);
-}
+};
METHOD(bus_t, add_listener, void,
private_bus_t *this, listener_t *listener)
{
+ entry_t *entry;
+
+ INIT(entry,
+ .listener = listener,
+ );
+
this->mutex->lock(this->mutex);
- this->listeners->insert_last(this->listeners, entry_create(listener, FALSE));
+ this->listeners->insert_last(this->listeners, entry);
this->mutex->unlock(this->mutex);
}
@@ -122,7 +133,7 @@ METHOD(bus_t, remove_listener, void,
if (entry->listener == listener)
{
this->listeners->remove_at(this->listeners, enumerator);
- entry_destroy(entry);
+ free(entry);
break;
}
}
@@ -130,74 +141,107 @@ METHOD(bus_t, remove_listener, void,
this->mutex->unlock(this->mutex);
}
-typedef struct cleanup_data_t cleanup_data_t;
-
/**
- * data to remove a listener using thread_cleanup_t handler
+ * Register a logger on the given log group according to the requested level
*/
-struct cleanup_data_t {
- /** bus instance */
- private_bus_t *this;
- /** listener entry */
- entry_t *entry;
-};
-
-/**
- * thread_cleanup_t handler to remove a listener
- */
-static void listener_cleanup(cleanup_data_t *data)
+static inline void register_logger(private_bus_t *this, debug_t group,
+ log_entry_t *entry)
{
- data->this->listeners->remove(data->this->listeners, data->entry, NULL);
- entry_destroy(data->entry);
+ enumerator_t *enumerator;
+ linked_list_t *loggers;
+ log_entry_t *current;
+ level_t level;
+
+ loggers = this->loggers[group];
+ level = entry->levels[group];
+
+ enumerator = loggers->create_enumerator(loggers);
+ while (enumerator->enumerate(enumerator, (void**)&current))
+ {
+ if (current->levels[group] <= level)
+ {
+ break;
+ }
+ }
+ loggers->insert_before(loggers, enumerator, entry);
+ enumerator->destroy(enumerator);
+
+ this->max_level[group] = max(this->max_level[group], level);
}
-METHOD(bus_t, listen_, bool,
- private_bus_t *this, listener_t *listener, job_t *job, u_int timeout)
+/**
+ * Unregister a logger from all log groups (destroys the log_entry_t)
+ */
+static inline void unregister_logger(private_bus_t *this, logger_t *logger)
{
- bool old, timed_out = FALSE;
- cleanup_data_t data;
- timeval_t tv, add;
+ enumerator_t *enumerator;
+ linked_list_t *loggers;
+ log_entry_t *entry, *found = NULL;
- if (timeout)
+ loggers = this->loggers[DBG_MAX];
+ enumerator = loggers->create_enumerator(loggers);
+ while (enumerator->enumerate(enumerator, &entry))
{
- add.tv_sec = timeout / 1000;
- add.tv_usec = (timeout - (add.tv_sec * 1000)) * 1000;
- time_monotonic(&tv);
- timeradd(&tv, &add, &tv);
+ if (entry->logger == logger)
+ {
+ loggers->remove_at(loggers, enumerator);
+ found = entry;
+ break;
+ }
}
+ enumerator->destroy(enumerator);
- data.this = this;
- data.entry = entry_create(listener, TRUE);
-
- this->mutex->lock(this->mutex);
- this->listeners->insert_last(this->listeners, data.entry);
- lib->processor->queue_job(lib->processor, job);
- thread_cleanup_push((thread_cleanup_t)this->mutex->unlock, this->mutex);
- thread_cleanup_push((thread_cleanup_t)listener_cleanup, &data);
- old = thread_cancelability(TRUE);
- while (data.entry->blocker)
+ if (found)
{
- if (timeout)
+ debug_t group;
+ for (group = 0; group < DBG_MAX; group++)
{
- if (data.entry->condvar->timed_wait_abs(data.entry->condvar,
- this->mutex, tv))
+ if (found->levels[group] > LEVEL_SILENT)
{
- this->listeners->remove(this->listeners, data.entry, NULL);
- timed_out = TRUE;
- break;
+ loggers = this->loggers[group];
+ loggers->remove(loggers, found, NULL);
+
+ this->max_level[group] = LEVEL_SILENT;
+ if (loggers->get_first(loggers, (void**)&entry) == SUCCESS)
+ {
+ this->max_level[group] = entry->levels[group];
+ }
}
}
- else
+ free(found);
+ }
+}
+
+METHOD(bus_t, add_logger, void,
+ private_bus_t *this, logger_t *logger)
+{
+ log_entry_t *entry;
+ debug_t group;
+
+ INIT(entry,
+ .logger = logger,
+ );
+
+ this->log_lock->write_lock(this->log_lock);
+ unregister_logger(this, logger);
+ for (group = 0; group < DBG_MAX; group++)
+ {
+ entry->levels[group] = logger->get_level(logger, group);
+ if (entry->levels[group] > LEVEL_SILENT)
{
- data.entry->condvar->wait(data.entry->condvar, this->mutex);
+ register_logger(this, group, entry);
}
}
- thread_cancelability(old);
- thread_cleanup_pop(FALSE);
- /* unlock mutex */
- thread_cleanup_pop(TRUE);
- entry_destroy(data.entry);
- return timed_out;
+ this->loggers[DBG_MAX]->insert_last(this->loggers[DBG_MAX], entry);
+ this->log_lock->unlock(this->log_lock);
+}
+
+METHOD(bus_t, remove_logger, void,
+ private_bus_t *this, logger_t *logger)
+{
+ this->log_lock->write_lock(this->log_lock);
+ unregister_logger(this, logger);
+ this->log_lock->unlock(this->log_lock);
}
METHOD(bus_t, set_sa, void,
@@ -224,66 +268,61 @@ typedef struct {
debug_t group;
/** debug level */
level_t level;
- /** format string */
- char *format;
- /** argument list */
- va_list args;
+ /** message */
+ char *message;
} log_data_t;
/**
- * listener->log() invocation as a list remove callback
+ * logger->log() invocation as a invoke_function callback
*/
-static bool log_cb(entry_t *entry, log_data_t *data)
+static void log_cb(log_entry_t *entry, log_data_t *data)
{
- va_list args;
-
- if (entry->calling || !entry->listener->log)
- { /* avoid recursive calls */
- return FALSE;
- }
- entry->calling++;
- va_copy(args, data->args);
- if (!entry->listener->log(entry->listener, data->group, data->level,
- data->thread, data->ike_sa, data->format, args))
+ if (entry->levels[data->group] < data->level)
{
- if (entry->blocker)
- {
- entry->blocker = FALSE;
- entry->condvar->signal(entry->condvar);
- entry->calling--;
- }
- else
- {
- entry_destroy(entry);
- }
- va_end(args);
- return TRUE;
+ return;
}
- va_end(args);
- entry->calling--;
- return FALSE;
+ entry->logger->log(entry->logger, data->group, data->level,
+ data->thread, data->ike_sa, data->message);
}
METHOD(bus_t, vlog, void,
private_bus_t *this, debug_t group, level_t level,
char* format, va_list args)
{
- log_data_t data;
-
- data.ike_sa = this->thread_sa->get(this->thread_sa);
- data.thread = thread_current_id();
- data.group = group;
- data.level = level;
- data.format = format;
- va_copy(data.args, args);
-
- this->mutex->lock(this->mutex);
- /* We use the remove() method to invoke all listeners. This is cheap and
- * does not require an allocation for this performance critical function. */
- this->listeners->remove(this->listeners, &data, (void*)log_cb);
- this->mutex->unlock(this->mutex);
-
- va_end(data.args);
+ this->log_lock->read_lock(this->log_lock);
+ if (this->max_level[group] >= level)
+ {
+ linked_list_t *loggers = this->loggers[group];
+ log_data_t data;
+ va_list copy;
+ char buf[1024];
+ ssize_t len;
+
+ data.ike_sa = this->thread_sa->get(this->thread_sa);
+ data.thread = thread_current_id();
+ data.group = group;
+ data.level = level;
+ data.message = buf;
+
+ va_copy(copy, args);
+ len = vsnprintf(data.message, sizeof(buf), format, copy);
+ va_end(copy);
+ if (len >= sizeof(buf))
+ {
+ data.message = malloc(len);
+ len = vsnprintf(data.message, len, format, args);
+ }
+ if (len > 0)
+ {
+ loggers->invoke_function(loggers, (linked_list_invoke_t)log_cb,
+ &data);
+ }
+ if (data.message != buf)
+ {
+ free(data.message);
+ }
+ }
+ this->log_lock->unlock(this->log_lock);
}
METHOD(bus_t, log_, void,
@@ -299,19 +338,11 @@ METHOD(bus_t, log_, void,
/**
* unregister a listener
*/
-static void unregister_listener(private_bus_t *this, entry_t *entry,
- enumerator_t *enumerator)
+static inline void unregister_listener(private_bus_t *this, entry_t *entry,
+ enumerator_t *enumerator)
{
- if (entry->blocker)
- {
- entry->blocker = FALSE;
- entry->condvar->signal(entry->condvar);
- }
- else
- {
- entry_destroy(entry);
- }
this->listeners->remove_at(this->listeners, enumerator);
+ free(entry);
}
METHOD(bus_t, alert, void,
@@ -406,7 +437,7 @@ METHOD(bus_t, child_state_change, void,
}
METHOD(bus_t, message, void,
- private_bus_t *this, message_t *message, bool incoming)
+ private_bus_t *this, message_t *message, bool incoming, bool plain)
{
enumerator_t *enumerator;
ike_sa_t *ike_sa;
@@ -425,7 +456,7 @@ METHOD(bus_t, message, void,
}
entry->calling++;
keep = entry->listener->message(entry->listener, ike_sa,
- message, incoming);
+ message, incoming, plain);
entry->calling--;
if (!keep)
{
@@ -438,7 +469,8 @@ METHOD(bus_t, message, void,
METHOD(bus_t, ike_keys, void,
private_bus_t *this, ike_sa_t *ike_sa, diffie_hellman_t *dh,
- chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey)
+ chunk_t dh_other, chunk_t nonce_i, chunk_t nonce_r,
+ ike_sa_t *rekey, shared_key_t *shared)
{
enumerator_t *enumerator;
entry_t *entry;
@@ -453,8 +485,8 @@ METHOD(bus_t, ike_keys, void,
continue;
}
entry->calling++;
- keep = entry->listener->ike_keys(entry->listener, ike_sa, dh,
- nonce_i, nonce_r, rekey);
+ keep = entry->listener->ike_keys(entry->listener, ike_sa, dh, dh_other,
+ nonce_i, nonce_r, rekey, shared);
entry->calling--;
if (!keep)
{
@@ -485,8 +517,8 @@ METHOD(bus_t, child_keys, void,
continue;
}
entry->calling++;
- keep = entry->listener->child_keys(entry->listener, ike_sa, child_sa,
- initiator, dh, nonce_i, nonce_r);
+ keep = entry->listener->child_keys(entry->listener, ike_sa,
+ child_sa, initiator, dh, nonce_i, nonce_r);
entry->calling--;
if (!keep)
{
@@ -547,7 +579,8 @@ METHOD(bus_t, child_rekey, void,
continue;
}
entry->calling++;
- keep = entry->listener->child_rekey(entry->listener, ike_sa, old, new);
+ keep = entry->listener->child_rekey(entry->listener, ike_sa,
+ old, new);
entry->calling--;
if (!keep)
{
@@ -626,6 +659,33 @@ METHOD(bus_t, ike_rekey, void,
this->mutex->unlock(this->mutex);
}
+METHOD(bus_t, ike_reestablish, void,
+ private_bus_t *this, ike_sa_t *old, ike_sa_t *new)
+{
+ enumerator_t *enumerator;
+ entry_t *entry;
+ bool keep;
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->listeners->create_enumerator(this->listeners);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->calling || !entry->listener->ike_reestablish)
+ {
+ continue;
+ }
+ entry->calling++;
+ keep = entry->listener->ike_reestablish(entry->listener, old, new);
+ entry->calling--;
+ if (!keep)
+ {
+ unregister_listener(this, entry, enumerator);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+}
+
METHOD(bus_t, authorize, bool,
private_bus_t *this, bool final)
{
@@ -697,9 +757,17 @@ METHOD(bus_t, narrow, void,
METHOD(bus_t, destroy, void,
private_bus_t *this)
{
+ debug_t group;
+ for (group = 0; group < DBG_MAX; group++)
+ {
+ this->loggers[group]->destroy(this->loggers[group]);
+ }
+ this->loggers[DBG_MAX]->destroy_function(this->loggers[DBG_MAX],
+ (void*)free);
+ this->listeners->destroy_function(this->listeners, (void*)free);
this->thread_sa->destroy(this->thread_sa);
+ this->log_lock->destroy(this->log_lock);
this->mutex->destroy(this->mutex);
- this->listeners->destroy_function(this->listeners, (void*)entry_destroy);
free(this);
}
@@ -709,12 +777,14 @@ METHOD(bus_t, destroy, void,
bus_t *bus_create()
{
private_bus_t *this;
+ debug_t group;
INIT(this,
.public = {
.add_listener = _add_listener,
.remove_listener = _remove_listener,
- .listen = _listen_,
+ .add_logger = _add_logger,
+ .remove_logger = _remove_logger,
.set_sa = _set_sa,
.get_sa = _get_sa,
.log = _log_,
@@ -727,6 +797,7 @@ bus_t *bus_create()
.child_keys = _child_keys,
.ike_updown = _ike_updown,
.ike_rekey = _ike_rekey,
+ .ike_reestablish = _ike_reestablish,
.child_updown = _child_updown,
.child_rekey = _child_rekey,
.authorize = _authorize,
@@ -735,9 +806,16 @@ bus_t *bus_create()
},
.listeners = linked_list_create(),
.mutex = mutex_create(MUTEX_TYPE_RECURSIVE),
+ .log_lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
.thread_sa = thread_value_create(NULL),
);
+ for (group = 0; group <= DBG_MAX; group++)
+ {
+ this->loggers[group] = linked_list_create();
+ this->max_level[group] = LEVEL_SILENT;
+ }
+
return &this->public;
}
diff --git a/src/libcharon/bus/bus.h b/src/libcharon/bus/bus.h
index 69060d383..aba8acdbd 100644
--- a/src/libcharon/bus/bus.h
+++ b/src/libcharon/bus/bus.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2006-2009 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -31,6 +32,7 @@ typedef struct bus_t bus_t;
#include <sa/ike_sa.h>
#include <sa/child_sa.h>
#include <processing/jobs/job.h>
+#include <bus/listeners/logger.h>
#include <bus/listeners/listener.h>
/* undefine the definitions from libstrongswan */
@@ -109,6 +111,8 @@ enum narrow_hook_t {
NARROW_INITIATOR_PRE_AUTH,
/** invoked as responder during exchange, peer is authenticated */
NARROW_RESPONDER,
+ /** invoked as responder after exchange, peer is authenticated */
+ NARROW_RESPONDER_POST,
/** invoked as initiator after exchange, follows a INITIATOR_PRE_NOAUTH */
NARROW_INITIATOR_POST_NOAUTH,
/** invoked as initiator after exchange, follows a INITIATOR_PRE_AUTH */
@@ -118,8 +122,7 @@ enum narrow_hook_t {
/**
* The bus receives events and sends them to all registered listeners.
*
- * Any events sent to are delivered to all registered listeners. Threads
- * may wait actively to events using the blocking listen() call.
+ * Loggers are handled separately.
*/
struct bus_t {
@@ -142,26 +145,37 @@ struct bus_t {
void (*remove_listener) (bus_t *this, listener_t *listener);
/**
- * Register a listener and block the calling thread.
+ * Register a logger with the bus.
*
- * This call registers a listener and blocks the calling thread until
- * its listeners function returns FALSE. This allows to wait for certain
- * events. The associated job is executed after the listener has been
- * registered: This allows to listen on events we initiate with the job,
- * without missing any events to job may fire.
+ * The logger is passive; the thread which emitted the event
+ * processes the logger routine. This routine may be called concurrently
+ * by multiple threads. Recursive calls are not prevented, so logger that
+ * may cause recursive calls are responsible to avoid infinite loops.
*
- * @param listener listener to register
- * @param job job to execute asynchronously when registered, or NULL
- * @param timeout max timeout in ms to listen for events, 0 to disable
- * @return TRUE if timed out
+ * During registration get_level() is called for all log groups and the
+ * logger is registered to receive log messages for groups for which
+ * the requested log level is > LEVEL_SILENT and whose level is lower
+ * or equal than the requested level.
+ *
+ * To update the registered log levels call add_logger again with the
+ * same logger and return the new levels from get_level().
+ *
+ * @param logger logger to register.
*/
- bool (*listen)(bus_t *this, listener_t *listener, job_t *job, u_int timeout);
+ void (*add_logger) (bus_t *this, logger_t *logger);
+
+ /**
+ * Unregister a logger from the bus.
+ *
+ * @param logger logger to unregister.
+ */
+ void (*remove_logger) (bus_t *this, logger_t *logger);
/**
* Set the IKE_SA the calling thread is using.
*
- * To associate an received log message to an IKE_SA without passing it as
- * parameter each time, the thread registers the currenlty used IKE_SA
+ * To associate a received log message with an IKE_SA without passing it as
+ * parameter each time, the thread registers the currently used IKE_SA
* during check-out. Before check-in, the thread unregisters the IKE_SA.
* This IKE_SA is stored per-thread, so each thread has its own IKE_SA
* registered.
@@ -183,9 +197,8 @@ struct bus_t {
/**
* Send a log message to the bus.
*
- * The signal specifies the type of the event occurred. The format string
- * specifies an additional informational or error message with a
- * printf() like variable argument list.
+ * The format string specifies an additional informational or error
+ * message with a printf() like variable argument list.
* Use the DBG() macros.
*
* @param group debugging group
@@ -198,7 +211,7 @@ struct bus_t {
/**
* Send a log message to the bus using va_list arguments.
*
- * Same as bus_t.signal(), but uses va_list argument list.
+ * Same as bus_t.log(), but uses va_list argument list.
*
* @param group kind of the signal (up, down, rekeyed, ...)
* @param level verbosity level of the signal
@@ -212,7 +225,7 @@ struct bus_t {
* Raise an alert over the bus.
*
* @param alert kind of alert
- * @param ... alert specific attributes
+ * @param ... alert specific arguments
*/
void (*alert)(bus_t *this, alert_t alert, ...);
@@ -235,10 +248,14 @@ struct bus_t {
/**
* Message send/receive hook.
*
+ * The hook is invoked twice for each message: Once with plain, parsed data
+ * and once encoded and encrypted.
+ *
* @param message message to send/receive
* @param incoming TRUE for incoming messages, FALSE for outgoing
+ * @param plain TRUE if message is parsed and decrypted, FALSE it not
*/
- void (*message)(bus_t *this, message_t *message, bool incoming);
+ void (*message)(bus_t *this, message_t *message, bool incoming, bool plain);
/**
* IKE_SA authorization hook.
@@ -264,12 +281,16 @@ struct bus_t {
*
* @param ike_sa IKE_SA this keymat belongs to
* @param dh diffie hellman shared secret
+ * @param dh_other others DH public value (IKEv1 only)
* @param nonce_i initiators nonce
* @param nonce_r responders nonce
- * @param rekey IKE_SA we are rekeying, if any
+ * @param rekey IKE_SA we are rekeying, if any (IKEv2 only)
+ * @param shared shared key used for key derivation (IKEv1-PSK only)
*/
void (*ike_keys)(bus_t *this, ike_sa_t *ike_sa, diffie_hellman_t *dh,
- chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey);
+ chunk_t dh_other, chunk_t nonce_i, chunk_t nonce_r,
+ ike_sa_t *rekey, shared_key_t *shared);
+
/**
* CHILD_SA keymat hook.
*
@@ -299,6 +320,14 @@ struct bus_t {
void (*ike_rekey)(bus_t *this, ike_sa_t *old, ike_sa_t *new);
/**
+ * IKE_SA reestablishing hook.
+ *
+ * @param old reestablished and obsolete IKE_SA
+ * @param new new IKE_SA replacing old
+ */
+ void (*ike_reestablish)(bus_t *this, ike_sa_t *old, ike_sa_t *new);
+
+ /**
* CHILD_SA up/down hook.
*
* @param child_sa CHILD_SA coming up/going down
diff --git a/src/libcharon/bus/listeners/file_logger.c b/src/libcharon/bus/listeners/file_logger.c
index 36d18619a..9c8458eb5 100644
--- a/src/libcharon/bus/listeners/file_logger.c
+++ b/src/libcharon/bus/listeners/file_logger.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2006 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -19,6 +20,7 @@
#include "file_logger.h"
+#include <threading/mutex.h>
typedef struct private_file_logger_t private_file_logger_t;
@@ -51,73 +53,80 @@ struct private_file_logger_t {
* Print the name/# of the IKE_SA?
*/
bool ike_name;
+
+ /**
+ * Mutex to ensure multi-line log messages are not torn apart
+ */
+ mutex_t *mutex;
};
-METHOD(listener_t, log_, bool,
- private_file_logger_t *this, debug_t group, level_t level, int thread,
- ike_sa_t* ike_sa, char *format, va_list args)
+METHOD(logger_t, log_, void,
+ private_file_logger_t *this, debug_t group, level_t level, int thread,
+ ike_sa_t* ike_sa, const char *message)
{
- if (level <= this->levels[group])
- {
- char buffer[8192], timestr[128], namestr[128] = "";
- char *current = buffer, *next;
- struct tm tm;
- time_t t;
+ char timestr[128], namestr[128] = "";
+ const char *current = message, *next;
+ struct tm tm;
+ time_t t;
- if (this->time_format)
+ if (this->time_format)
+ {
+ t = time(NULL);
+ localtime_r(&t, &tm);
+ strftime(timestr, sizeof(timestr), this->time_format, &tm);
+ }
+ if (this->ike_name && ike_sa)
+ {
+ if (ike_sa->get_peer_cfg(ike_sa))
{
- t = time(NULL);
- localtime_r(&t, &tm);
- strftime(timestr, sizeof(timestr), this->time_format, &tm);
+ snprintf(namestr, sizeof(namestr), " <%s|%d>",
+ ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa));
}
- if (this->ike_name && ike_sa)
+ else
{
- if (ike_sa->get_peer_cfg(ike_sa))
- {
- snprintf(namestr, sizeof(namestr), " <%s|%d>",
- ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa));
- }
- else
- {
- snprintf(namestr, sizeof(namestr), " <%d>",
- ike_sa->get_unique_id(ike_sa));
- }
+ snprintf(namestr, sizeof(namestr), " <%d>",
+ ike_sa->get_unique_id(ike_sa));
+ }
+ }
+ else
+ {
+ namestr[0] = '\0';
+ }
+
+ /* prepend a prefix in front of every line */
+ this->mutex->lock(this->mutex);
+ while (TRUE)
+ {
+ next = strchr(current, '\n');
+ if (this->time_format)
+ {
+ fprintf(this->out, "%s %.2d[%N]%s ",
+ timestr, thread, debug_names, group, namestr);
}
else
{
- namestr[0] = '\0';
+ fprintf(this->out, "%.2d[%N]%s ",
+ thread, debug_names, group, namestr);
}
-
- /* write in memory buffer first */
- vsnprintf(buffer, sizeof(buffer), format, args);
-
- /* prepend a prefix in front of every line */
- while (current)
+ if (next == NULL)
{
- next = strchr(current, '\n');
- if (next)
- {
- *(next++) = '\0';
- }
- if (this->time_format)
- {
- fprintf(this->out, "%s %.2d[%N]%s %s\n",
- timestr, thread, debug_names, group, namestr, current);
- }
- else
- {
- fprintf(this->out, "%.2d[%N]%s %s\n",
- thread, debug_names, group, namestr, current);
- }
- current = next;
+ fprintf(this->out, "%s\n", current);
+ break;
}
+ fprintf(this->out, "%.*s\n", (int)(next - current), current);
+ current = next + 1;
}
- /* always stay registered */
- return TRUE;
+ this->mutex->unlock(this->mutex);
+}
+
+METHOD(logger_t, get_level, level_t,
+ private_file_logger_t *this, debug_t group)
+{
+ return this->levels[group];
}
METHOD(file_logger_t, set_level, void,
- private_file_logger_t *this, debug_t group, level_t level)
+ private_file_logger_t *this, debug_t group, level_t level)
{
if (group < DBG_ANY)
{
@@ -133,12 +142,13 @@ METHOD(file_logger_t, set_level, void,
}
METHOD(file_logger_t, destroy, void,
- private_file_logger_t *this)
+ private_file_logger_t *this)
{
if (this->out != stdout && this->out != stderr)
{
fclose(this->out);
}
+ this->mutex->destroy(this->mutex);
free(this);
}
@@ -151,8 +161,9 @@ file_logger_t *file_logger_create(FILE *out, char *time_format, bool ike_name)
INIT(this,
.public = {
- .listener = {
+ .logger = {
.log = _log_,
+ .get_level = _get_level,
},
.set_level = _set_level,
.destroy = _destroy,
@@ -160,6 +171,7 @@ file_logger_t *file_logger_create(FILE *out, char *time_format, bool ike_name)
.out = out,
.time_format = time_format,
.ike_name = ike_name,
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
);
set_level(this, DBG_ANY, LEVEL_SILENT);
diff --git a/src/libcharon/bus/listeners/file_logger.h b/src/libcharon/bus/listeners/file_logger.h
index d02f1701d..85a2690a2 100644
--- a/src/libcharon/bus/listeners/file_logger.h
+++ b/src/libcharon/bus/listeners/file_logger.h
@@ -21,7 +21,7 @@
#ifndef FILE_LOGGER_H_
#define FILE_LOGGER_H_
-#include <bus/listeners/listener.h>
+#include <bus/listeners/logger.h>
typedef struct file_logger_t file_logger_t;
@@ -31,9 +31,9 @@ typedef struct file_logger_t file_logger_t;
struct file_logger_t {
/**
- * Implements the listener_t interface.
+ * Implements the logger_t interface.
*/
- listener_t listener;
+ logger_t logger;
/**
* Set the loglevel for a debug group.
diff --git a/src/libcharon/bus/listeners/listener.h b/src/libcharon/bus/listeners/listener.h
index 21caed064..782289302 100644
--- a/src/libcharon/bus/listeners/listener.h
+++ b/src/libcharon/bus/listeners/listener.h
@@ -31,25 +31,6 @@ typedef struct listener_t listener_t;
struct listener_t {
/**
- * Log a debugging message.
- *
- * The implementing signal function returns TRUE to stay registered
- * to the bus, or FALSE to unregister itself.
- * Calling bus_t.log() inside of a registered listener is possible,
- * but the bus does not invoke listeners recursively.
- *
- * @param group kind of the signal (up, down, rekeyed, ...)
- * @param level verbosity level of the signal
- * @param thread ID of the thread raised this signal
- * @param ike_sa IKE_SA associated to the event
- * @param format printf() style format string
- * @param args vprintf() style va_list argument list
- * @return TRUE to stay registered, FALSE to unregister
- */
- bool (*log)(listener_t *this, debug_t group, level_t level, int thread,
- ike_sa_t *ike_sa, char* format, va_list args);
-
- /**
* Hook called if a critical alert is risen.
*
* @param ike_sa IKE_SA associated to the alert, if any
@@ -84,26 +65,33 @@ struct listener_t {
/**
* Hook called for received/sent messages of an IKE_SA.
*
+ * The hook is invoked twice for each message: Once with plain, parsed data
+ * and once encoded and encrypted.
+ *
* @param ike_sa IKE_SA sending/receiving a message
* @param message message object
* @param incoming TRUE for incoming messages, FALSE for outgoing
+ * @param plain TRUE if message is parsed and decrypted, FALSE it not
* @return TRUE to stay registered, FALSE to unregister
*/
bool (*message)(listener_t *this, ike_sa_t *ike_sa, message_t *message,
- bool incoming);
+ bool incoming, bool plain);
/**
* Hook called with IKE_SA key material.
*
* @param ike_sa IKE_SA this keymat belongs to
* @param dh diffie hellman shared secret
+ * @param dh_other others DH public value (IKEv1 only)
* @param nonce_i initiators nonce
* @param nonce_r responders nonce
- * @param rekey IKE_SA we are rekeying, if any
+ * @param rekey IKE_SA we are rekeying, if any (IKEv2 only)
+ * @param shared shared key used for key derivation (IKEv1-PSK only)
* @return TRUE to stay registered, FALSE to unregister
*/
bool (*ike_keys)(listener_t *this, ike_sa_t *ike_sa, diffie_hellman_t *dh,
- chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey);
+ chunk_t dh_other, chunk_t nonce_i, chunk_t nonce_r,
+ ike_sa_t *rekey, shared_key_t *shared);
/**
* Hook called with CHILD_SA key material.
@@ -139,6 +127,18 @@ struct listener_t {
bool (*ike_rekey)(listener_t *this, ike_sa_t *old, ike_sa_t *new);
/**
+ * Hook called when an initiator reestablishes an IKE_SA.
+ *
+ * This is invoked right before the new IKE_SA is checked in after
+ * initiating it. It is not invoked on the responder.
+ *
+ * @param old IKE_SA getting reestablished (is destroyed)
+ * @param new new IKE_SA replacing old (gets established)
+ * @return TRUE to stay registered, FALSE to unregister
+ */
+ bool (*ike_reestablish)(listener_t *this, ike_sa_t *old, ike_sa_t *new);
+
+ /**
* Hook called when a CHILD_SA gets up or down.
*
* @param ike_sa IKE_SA containing the handled CHILD_SA
diff --git a/src/libcharon/bus/listeners/logger.h b/src/libcharon/bus/listeners/logger.h
new file mode 100644
index 000000000..3b99e7dc1
--- /dev/null
+++ b/src/libcharon/bus/listeners/logger.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup logger logger
+ * @{ @ingroup listeners
+ */
+
+#ifndef LOGGER_H_
+#define LOGGER_H_
+
+typedef struct logger_t logger_t;
+
+#include <bus/bus.h>
+
+/**
+ * Logger interface, listens for log events on the bus.
+ */
+struct logger_t {
+
+ /**
+ * Log a debugging message.
+ *
+ * @note Calls to bus_t.log() are handled separately from calls to
+ * other functions. This callback may be called concurrently by
+ * multiple threads. Also recursive calls are not prevented, loggers that
+ * may cause recursive log messages are responsible to avoid infinite loops.
+ *
+ * @param group kind of the signal (up, down, rekeyed, ...)
+ * @param level verbosity level of the signal
+ * @param thread ID of the thread raised this signal
+ * @param ike_sa IKE_SA associated to the event
+ * @param message log message
+ */
+ void (*log)(logger_t *this, debug_t group, level_t level, int thread,
+ ike_sa_t *ike_sa, const char *message);
+
+ /**
+ * Get the desired log level for a debug group. This is called during
+ * registration.
+ *
+ * If the desired log levels have changed, re-register the logger with
+ * the bus.
+ *
+ * @param group debug group
+ * @return max level to log (0..4) or -1 for none (see debug.h)
+ */
+ level_t (*get_level)(logger_t *this, debug_t group);
+};
+
+#endif /** LOGGER_H_ @}*/
diff --git a/src/libcharon/bus/listeners/sys_logger.c b/src/libcharon/bus/listeners/sys_logger.c
index c29c9f2e4..53fdefe89 100644
--- a/src/libcharon/bus/listeners/sys_logger.c
+++ b/src/libcharon/bus/listeners/sys_logger.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2006 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -19,6 +20,7 @@
#include "sys_logger.h"
+#include <threading/mutex.h>
typedef struct private_sys_logger_t private_sys_logger_t;
@@ -46,55 +48,63 @@ struct private_sys_logger_t {
* Print the name/# of the IKE_SA?
*/
bool ike_name;
+
+ /**
+ * Mutex to ensure multi-line log messages are not torn apart
+ */
+ mutex_t *mutex;
};
-METHOD(listener_t, log_, bool,
- private_sys_logger_t *this, debug_t group, level_t level, int thread,
- ike_sa_t* ike_sa, char *format, va_list args)
+METHOD(logger_t, log_, void,
+ private_sys_logger_t *this, debug_t group, level_t level, int thread,
+ ike_sa_t* ike_sa, const char *message)
{
- if (level <= this->levels[group])
- {
- char buffer[8192], groupstr[4], namestr[128] = "";
- char *current = buffer, *next;
+ char groupstr[4], namestr[128] = "";
+ const char *current = message, *next;
- /* write in memory buffer first */
- vsnprintf(buffer, sizeof(buffer), format, args);
- /* cache group name */
- snprintf(groupstr, sizeof(groupstr), "%N", debug_names, group);
+ /* cache group name and optional name string */
+ snprintf(groupstr, sizeof(groupstr), "%N", debug_names, group);
- if (this->ike_name && ike_sa)
+ if (this->ike_name && ike_sa)
+ {
+ if (ike_sa->get_peer_cfg(ike_sa))
+ {
+ snprintf(namestr, sizeof(namestr), " <%s|%d>",
+ ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa));
+ }
+ else
{
- if (ike_sa->get_peer_cfg(ike_sa))
- {
- snprintf(namestr, sizeof(namestr), " <%s|%d>",
- ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa));
- }
- else
- {
- snprintf(namestr, sizeof(namestr), " <%d>",
- ike_sa->get_unique_id(ike_sa));
- }
+ snprintf(namestr, sizeof(namestr), " <%d>",
+ ike_sa->get_unique_id(ike_sa));
}
+ }
- /* do a syslog with every line */
- while (current)
+ /* do a syslog for every line */
+ this->mutex->lock(this->mutex);
+ while (TRUE)
+ {
+ next = strchr(current, '\n');
+ if (next == NULL)
{
- next = strchr(current, '\n');
- if (next)
- {
- *(next++) = '\0';
- }
- syslog(this->facility|LOG_INFO, "%.2d[%s]%s %s\n",
+ syslog(this->facility | LOG_INFO, "%.2d[%s]%s %s\n",
thread, groupstr, namestr, current);
- current = next;
+ break;
}
+ syslog(this->facility | LOG_INFO, "%.2d[%s]%s %.*s\n",
+ thread, groupstr, namestr, (int)(next - current), current);
+ current = next + 1;
}
- /* always stay registered */
- return TRUE;
+ this->mutex->unlock(this->mutex);
+}
+
+METHOD(logger_t, get_level, level_t,
+ private_sys_logger_t *this, debug_t group)
+{
+ return this->levels[group];
}
METHOD(sys_logger_t, set_level, void,
- private_sys_logger_t *this, debug_t group, level_t level)
+ private_sys_logger_t *this, debug_t group, level_t level)
{
if (group < DBG_ANY)
{
@@ -110,9 +120,10 @@ METHOD(sys_logger_t, set_level, void,
}
METHOD(sys_logger_t, destroy, void,
- private_sys_logger_t *this)
+ private_sys_logger_t *this)
{
closelog();
+ this->mutex->destroy(this->mutex);
free(this);
}
@@ -125,14 +136,16 @@ sys_logger_t *sys_logger_create(int facility, bool ike_name)
INIT(this,
.public = {
- .listener = {
+ .logger = {
.log = _log_,
+ .get_level = _get_level,
},
.set_level = _set_level,
.destroy = _destroy,
},
.facility = facility,
.ike_name = ike_name,
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
);
set_level(this, DBG_ANY, LEVEL_SILENT);
diff --git a/src/libcharon/bus/listeners/sys_logger.h b/src/libcharon/bus/listeners/sys_logger.h
index d83715a6a..fcb6655ca 100644
--- a/src/libcharon/bus/listeners/sys_logger.h
+++ b/src/libcharon/bus/listeners/sys_logger.h
@@ -21,7 +21,7 @@
#ifndef SYS_LOGGER_H_
#define SYS_LOGGER_H_
-#include <bus/listeners/listener.h>
+#include <bus/listeners/logger.h>
typedef struct sys_logger_t sys_logger_t;
@@ -31,9 +31,9 @@ typedef struct sys_logger_t sys_logger_t;
struct sys_logger_t {
/**
- * Implements the listener_t interface.
+ * Implements the logger_t interface.
*/
- listener_t listener;
+ logger_t logger;
/**
* Set the loglevel for a debug group.
diff --git a/src/libcharon/config/backend_manager.c b/src/libcharon/config/backend_manager.c
index a93457ea4..09e123e67 100644
--- a/src/libcharon/config/backend_manager.c
+++ b/src/libcharon/config/backend_manager.c
@@ -78,12 +78,14 @@ static enumerator_t *ike_enum_create(backend_t *backend, ike_data_t *data)
static ike_cfg_match_t get_ike_match(ike_cfg_t *cand, host_t *me, host_t *other)
{
host_t *me_cand, *other_cand;
+ char *my_addr, *other_addr;
+ bool my_allow_any, other_allow_any;
ike_cfg_match_t match = MATCH_NONE;
if (me)
{
- me_cand = host_create_from_dns(cand->get_my_addr(cand),
- me->get_family(me), 0);
+ my_addr = cand->get_my_addr(cand, &my_allow_any);
+ me_cand = host_create_from_dns(my_addr, me->get_family(me), 0);
if (!me_cand)
{
return MATCH_NONE;
@@ -92,7 +94,7 @@ static ike_cfg_match_t get_ike_match(ike_cfg_t *cand, host_t *me, host_t *other)
{
match += MATCH_ME;
}
- else if (me_cand->is_anyaddr(me_cand))
+ else if (my_allow_any || me_cand->is_anyaddr(me_cand))
{
match += MATCH_ANY;
}
@@ -110,8 +112,8 @@ static ike_cfg_match_t get_ike_match(ike_cfg_t *cand, host_t *me, host_t *other)
if (other)
{
- other_cand = host_create_from_dns(cand->get_other_addr(cand),
- other->get_family(other), 0);
+ other_addr = cand->get_other_addr(cand, &other_allow_any);
+ other_cand = host_create_from_dns(other_addr, other->get_family(other), 0);
if (!other_cand)
{
return MATCH_NONE;
@@ -120,7 +122,7 @@ static ike_cfg_match_t get_ike_match(ike_cfg_t *cand, host_t *me, host_t *other)
{
match += MATCH_OTHER;
}
- else if (other_cand->is_anyaddr(other_cand))
+ else if (other_allow_any || other_cand->is_anyaddr(other_cand))
{
match += MATCH_ANY;
}
@@ -142,14 +144,17 @@ METHOD(backend_manager_t, get_ike_cfg, ike_cfg_t*,
private_backend_manager_t *this, host_t *me, host_t *other)
{
ike_cfg_t *current, *found = NULL;
+ char *my_addr, *other_addr;
+ bool my_allow_any, other_allow_any;
enumerator_t *enumerator;
ike_cfg_match_t match, best = MATCH_ANY;
ike_data_t *data;
- data = malloc_thing(ike_data_t);
- data->this = this;
- data->me = me;
- data->other = other;
+ INIT(data,
+ .this = this,
+ .me = me,
+ .other = other,
+ );
DBG2(DBG_CFG, "looking for an ike config for %H...%H", me, other);
@@ -160,12 +165,14 @@ METHOD(backend_manager_t, get_ike_cfg, ike_cfg_t*,
while (enumerator->enumerate(enumerator, (void**)&current))
{
match = get_ike_match(current, me, other);
-
+ DBG3(DBG_CFG, "ike config match: %d (%H %H)", match, me, other);
if (match)
{
- DBG2(DBG_CFG, " candidate: %s...%s, prio %d",
- current->get_my_addr(current),
- current->get_other_addr(current), match);
+ my_addr = current->get_my_addr(current, &my_allow_any);
+ other_addr = current->get_other_addr(current, &other_allow_any);
+ DBG2(DBG_CFG, " candidate: %s%s...%s%s, prio %d",
+ my_allow_any ? "%":"", my_addr,
+ other_allow_any ? "%":"", other_addr, match);
if (match > best)
{
DESTROY_IF(found);
@@ -179,8 +186,11 @@ METHOD(backend_manager_t, get_ike_cfg, ike_cfg_t*,
this->lock->unlock(this->lock);
if (found)
{
- DBG2(DBG_CFG, "found matching ike config: %s...%s with prio %d",
- found->get_my_addr(found), found->get_other_addr(found), best);
+ my_addr = found->get_my_addr(found, &my_allow_any);
+ other_addr = found->get_other_addr(found, &other_allow_any);
+ DBG2(DBG_CFG, "found matching ike config: %s%s...%s%s with prio %d",
+ my_allow_any ? "%":"", my_addr,
+ other_allow_any ? "%":"", other_addr, best);
}
return found;
}
@@ -195,9 +205,13 @@ static id_match_t get_peer_match(identification_t *id,
auth_cfg_t *auth;
identification_t *candidate;
id_match_t match = ID_MATCH_NONE;
+ char *where = local ? "local" : "remote";
+ chunk_t data;
if (!id)
{
+ DBG3(DBG_CFG, "peer config match %s: %d (%N)",
+ where, ID_MATCH_ANY, id_type_names, ID_ANY);
return ID_MATCH_ANY;
}
@@ -221,10 +235,30 @@ static id_match_t get_peer_match(identification_t *id,
}
}
enumerator->destroy(enumerator);
+
+ data = id->get_encoding(id);
+ DBG3(DBG_CFG, "peer config match %s: %d (%N -> %#B)",
+ where, match, id_type_names, id->get_type(id), &data);
return match;
}
/**
+ * Get match quality of IKE version
+ */
+static int get_version_match(ike_version_t cfg, ike_version_t req)
+{
+ if (req == IKE_ANY || cfg == IKE_ANY)
+ {
+ return 1;
+ }
+ if (req == cfg)
+ {
+ return 2;
+ }
+ return 0;
+}
+
+/**
* data to pass nested peer enumerator
*/
typedef struct {
@@ -317,17 +351,18 @@ static void insert_sorted(match_entry_t *entry, linked_list_t *list,
METHOD(backend_manager_t, create_peer_cfg_enumerator, enumerator_t*,
private_backend_manager_t *this, host_t *me, host_t *other,
- identification_t *my_id, identification_t *other_id)
+ identification_t *my_id, identification_t *other_id, ike_version_t version)
{
enumerator_t *enumerator;
peer_data_t *data;
peer_cfg_t *cfg;
linked_list_t *configs, *helper;
- data = malloc_thing(peer_data_t);
- data->lock = this->lock;
- data->me = my_id;
- data->other = other_id;
+ INIT(data,
+ .lock = this->lock,
+ .me = my_id,
+ .other = other_id,
+ );
/* create a sorted list with all matches */
this->lock->read_lock(this->lock);
@@ -340,9 +375,6 @@ METHOD(backend_manager_t, create_peer_cfg_enumerator, enumerator_t*,
return enumerator;
}
- DBG1(DBG_CFG, "looking for peer configs matching %H[%Y]...%H[%Y]",
- me, my_id, other, other_id);
-
configs = linked_list_create();
/* only once allocated helper list for sorting */
helper = linked_list_create();
@@ -350,29 +382,26 @@ METHOD(backend_manager_t, create_peer_cfg_enumerator, enumerator_t*,
{
id_match_t match_peer_me, match_peer_other;
ike_cfg_match_t match_ike;
+ int match_version;
match_entry_t *entry;
- chunk_t data;
match_peer_me = get_peer_match(my_id, cfg, TRUE);
- data = my_id->get_encoding(my_id);
- DBG3(DBG_CFG, "match_peer_me: %d (%N -> %#B)", match_peer_me,
- id_type_names, my_id->get_type(my_id), &data);
match_peer_other = get_peer_match(other_id, cfg, FALSE);
- data = other_id->get_encoding(other_id);
- DBG3(DBG_CFG, "match_peer_other: %d (%N -> %#B)", match_peer_other,
- id_type_names, other_id->get_type(other_id), &data);
match_ike = get_ike_match(cfg->get_ike_cfg(cfg), me, other);
- DBG3(DBG_CFG, "match_ike: %d (%H %H)", match_ike, me, other);
+ match_version = get_version_match(cfg->get_ike_version(cfg), version);
+ DBG3(DBG_CFG, "ike config match: %d (%H %H)", match_ike, me, other);
- if (match_peer_me && match_peer_other && match_ike)
+ if (match_peer_me && match_peer_other && match_ike && match_version)
{
- DBG2(DBG_CFG, " candidate \"%s\", match: %d/%d/%d (me/other/ike)",
- cfg->get_name(cfg), match_peer_me, match_peer_other, match_ike);
-
- entry = malloc_thing(match_entry_t);
- entry->match_peer = match_peer_me + match_peer_other;
- entry->match_ike = match_ike;
- entry->cfg = cfg->get_ref(cfg);
+ DBG2(DBG_CFG, " candidate \"%s\", match: %d/%d/%d/%d "
+ "(me/other/ike/version)", cfg->get_name(cfg),
+ match_peer_me, match_peer_other, match_ike, match_version);
+
+ INIT(entry,
+ .match_peer = match_peer_me + match_peer_other,
+ .match_ike = match_ike,
+ .cfg = cfg->get_ref(cfg),
+ );
insert_sorted(entry, configs, helper);
}
}
diff --git a/src/libcharon/config/backend_manager.h b/src/libcharon/config/backend_manager.h
index 5b394f791..de263365b 100644
--- a/src/libcharon/config/backend_manager.h
+++ b/src/libcharon/config/backend_manager.h
@@ -56,6 +56,7 @@ struct backend_manager_t {
*
* @param my_host address of own host
* @param other_host address of remote host
+ * @param version IKE version to get a config for
* @return matching ike_config, or NULL if none found
*/
ike_cfg_t* (*get_ike_cfg)(backend_manager_t *this,
@@ -79,11 +80,12 @@ struct backend_manager_t {
* @param other remote address
* @param my_id IDr in first authentication round
* @param other_id IDi in first authentication round
+ * @param version IKE version to get a config for
* @return enumerator over peer_cfg_t
*/
enumerator_t* (*create_peer_cfg_enumerator)(backend_manager_t *this,
host_t *me, host_t *other, identification_t *my_id,
- identification_t *other_id);
+ identification_t *other_id, ike_version_t version);
/**
* Register a backend on the manager.
*
diff --git a/src/libcharon/config/child_cfg.c b/src/libcharon/config/child_cfg.c
index 74949be3c..b675c908f 100644
--- a/src/libcharon/config/child_cfg.c
+++ b/src/libcharon/config/child_cfg.c
@@ -171,6 +171,8 @@ METHOD(child_cfg_t, get_proposals, linked_list_t*,
}
enumerator->destroy(enumerator);
+ DBG2(DBG_CFG, "configured proposals: %#P", proposals);
+
return proposals;
}
@@ -235,12 +237,16 @@ METHOD(child_cfg_t, add_traffic_selector, void,
}
METHOD(child_cfg_t, get_traffic_selectors, linked_list_t*,
- private_child_cfg_t *this, bool local, linked_list_t *supplied, host_t *host)
+ private_child_cfg_t *this, bool local, linked_list_t *supplied,
+ linked_list_t *hosts)
{
enumerator_t *e1, *e2;
traffic_selector_t *ts1, *ts2, *selected;
- linked_list_t *result = linked_list_create();
+ linked_list_t *result, *derived;
+ host_t *host;
+ result = linked_list_create();
+ derived = linked_list_create();
if (local)
{
e1 = this->my_ts->create_enumerator(this->my_ts);
@@ -249,42 +255,46 @@ METHOD(child_cfg_t, get_traffic_selectors, linked_list_t*,
{
e1 = this->other_ts->create_enumerator(this->other_ts);
}
-
- /* no list supplied, just fetch the stored traffic selectors */
- if (supplied == NULL)
+ /* In a first step, replace "dynamic" TS with the host list */
+ while (e1->enumerate(e1, &ts1))
{
- DBG2(DBG_CFG, "proposing traffic selectors for %s:",
- local ? "us" : "other");
- while (e1->enumerate(e1, &ts1))
+ if (hosts && hosts->get_count(hosts) &&
+ ts1->is_dynamic(ts1))
{
- /* we make a copy of the TS, this allows us to update dynamic TS' */
- selected = ts1->clone(ts1);
- if (host)
+ e2 = hosts->create_enumerator(hosts);
+ while (e2->enumerate(e2, &host))
{
- selected->set_address(selected, host);
+ ts2 = ts1->clone(ts1);
+ ts2->set_address(ts2, host);
+ derived->insert_last(derived, ts2);
}
- DBG2(DBG_CFG, " %R (derived from %R)", selected, ts1);
- result->insert_last(result, selected);
+ e2->destroy(e2);
+ }
+ else
+ {
+ derived->insert_last(derived, ts1->clone(ts1));
+ }
+ }
+ e1->destroy(e1);
+
+ DBG2(DBG_CFG, "%s traffic selectors for %s:",
+ supplied ? "selecting" : "proposing", local ? "us" : "other");
+ if (supplied == NULL)
+ {
+ while (derived->remove_first(derived, (void**)&ts1) == SUCCESS)
+ {
+ DBG2(DBG_CFG, " %R", ts1);
+ result->insert_last(result, ts1);
}
- e1->destroy(e1);
}
else
{
- DBG2(DBG_CFG, "selecting traffic selectors for %s:",
- local ? "us" : "other");
- e2 = supplied->create_enumerator(supplied);
- /* iterate over all stored selectors */
- while (e1->enumerate(e1, &ts1))
+ e1 = supplied->create_enumerator(supplied);
+ /* enumerate all configured/derived selectors */
+ while (derived->remove_first(derived, (void**)&ts1) == SUCCESS)
{
- /* we make a copy of the TS, as we have to update dynamic TS' */
- ts1 = ts1->clone(ts1);
- if (host)
- {
- ts1->set_address(ts1, host);
- }
-
- /* iterate over all supplied traffic selectors */
- while (e2->enumerate(e2, &ts2))
+ /* enumerate all supplied traffic selectors */
+ while (e1->enumerate(e1, &ts2))
{
selected = ts1->get_subset(ts1, ts2);
if (selected)
@@ -299,13 +309,12 @@ METHOD(child_cfg_t, get_traffic_selectors, linked_list_t*,
ts1, ts2);
}
}
- e2->destroy(e2);
- e2 = supplied->create_enumerator(supplied);
+ supplied->reset_enumerator(supplied, e1);
ts1->destroy(ts1);
}
e1->destroy(e1);
- e2->destroy(e2);
}
+ derived->destroy(derived);
/* remove any redundant traffic selectors in the list */
e1 = result->create_enumerator(result);
@@ -320,16 +329,14 @@ METHOD(child_cfg_t, get_traffic_selectors, linked_list_t*,
{
result->remove_at(result, e2);
ts2->destroy(ts2);
- e1->destroy(e1);
- e1 = result->create_enumerator(result);
+ result->reset_enumerator(result, e1);
break;
}
if (ts1->is_contained_in(ts1, ts2))
{
result->remove_at(result, e1);
ts1->destroy(ts1);
- e2->destroy(e2);
- e2 = result->create_enumerator(result);
+ result->reset_enumerator(result, e2);
break;
}
}
diff --git a/src/libcharon/config/child_cfg.h b/src/libcharon/config/child_cfg.h
index 370ff9d58..6e8829a47 100644
--- a/src/libcharon/config/child_cfg.h
+++ b/src/libcharon/config/child_cfg.h
@@ -129,12 +129,12 @@ struct child_cfg_t {
*
* @param local TRUE for TS on local side, FALSE for remote
* @param supplied list with TS to select from, or NULL
- * @param host address to use for narrowing "dynamic" TS', or NULL
+ * @param hosts addresses to use for narrowing "dynamic" TS', host_t
* @return list containing the traffic selectors
*/
linked_list_t *(*get_traffic_selectors)(child_cfg_t *this, bool local,
linked_list_t *supplied,
- host_t *host);
+ linked_list_t *hosts);
/**
* Get the updown script to run for the CHILD_SA.
*
diff --git a/src/libcharon/config/ike_cfg.c b/src/libcharon/config/ike_cfg.c
index 342b9ddbe..acf4b6141 100644
--- a/src/libcharon/config/ike_cfg.c
+++ b/src/libcharon/config/ike_cfg.c
@@ -49,6 +49,16 @@ struct private_ike_cfg_t {
char *other;
/**
+ * Allow override of local address
+ */
+ bool my_allow_any;
+
+ /**
+ * Allow override of remote address
+ */
+ bool other_allow_any;
+
+ /**
* our source port
*/
u_int16_t my_port;
@@ -87,14 +97,22 @@ METHOD(ike_cfg_t, force_encap_, bool,
}
METHOD(ike_cfg_t, get_my_addr, char*,
- private_ike_cfg_t *this)
+ private_ike_cfg_t *this, bool *allow_any)
{
+ if (allow_any)
+ {
+ *allow_any = this->my_allow_any;
+ }
return this->me;
}
METHOD(ike_cfg_t, get_other_addr, char*,
- private_ike_cfg_t *this)
+ private_ike_cfg_t *this, bool *allow_any)
{
+ if (allow_any)
+ {
+ *allow_any = this->other_allow_any;
+ }
return this->other;
}
@@ -132,6 +150,8 @@ METHOD(ike_cfg_t, get_proposals, linked_list_t*,
}
enumerator->destroy(enumerator);
+ DBG2(DBG_CFG, "configured proposals: %#P", proposals);
+
return proposals;
}
@@ -260,7 +280,8 @@ METHOD(ike_cfg_t, destroy, void,
* Described in header.
*/
ike_cfg_t *ike_cfg_create(bool certreq, bool force_encap,
- char *me, u_int16_t my_port, char *other, u_int16_t other_port)
+ char *me, bool my_allow_any, u_int16_t my_port,
+ char *other, bool other_allow_any, u_int16_t other_port)
{
private_ike_cfg_t *this;
@@ -285,6 +306,8 @@ ike_cfg_t *ike_cfg_create(bool certreq, bool force_encap,
.force_encap = force_encap,
.me = strdup(me),
.other = strdup(other),
+ .my_allow_any = my_allow_any,
+ .other_allow_any = other_allow_any,
.my_port = my_port,
.other_port = other_port,
.proposals = linked_list_create(),
diff --git a/src/libcharon/config/ike_cfg.h b/src/libcharon/config/ike_cfg.h
index f1edde255..691d223a3 100644
--- a/src/libcharon/config/ike_cfg.h
+++ b/src/libcharon/config/ike_cfg.h
@@ -41,28 +41,30 @@ struct ike_cfg_t {
/**
* Get own address.
*
- * @return string of address/DNS name
+ * @param allow_any allow any address to match
+ * @return string of address/DNS name
*/
- char* (*get_my_addr) (ike_cfg_t *this);
+ char* (*get_my_addr) (ike_cfg_t *this, bool *allow_any);
/**
- * Get peers address.
+ * Get peer's address.
*
- * @return string of address/DNS name
+ * @param allow_any allow any address to match
+ * @return string of address/DNS name
*/
- char* (*get_other_addr) (ike_cfg_t *this);
+ char* (*get_other_addr) (ike_cfg_t *this, bool *allow_any);
/**
* Get the port to use as our source port.
*
- * @return source address port, host order
+ * @return source address port, host order
*/
u_int16_t (*get_my_port)(ike_cfg_t *this);
/**
* Get the port to use as destination port.
*
- * @return destination address, host order
+ * @return destination address, host order
*/
u_int16_t (*get_other_port)(ike_cfg_t *this);
@@ -72,7 +74,7 @@ struct ike_cfg_t {
* The first added proposal has the highest priority, the last
* added the lowest.
*
- * @param proposal proposal to add
+ * @param proposal proposal to add
*/
void (*add_proposal) (ike_cfg_t *this, proposal_t *proposal);
@@ -81,7 +83,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);
@@ -90,9 +92,9 @@ struct ike_cfg_t {
*
* Returned proposal must be destroyed after use.
*
- * @param proposals list of proposals to select from
- * @param private accept algorithms from a private range
- * @return selected proposal, or NULL if none matches.
+ * @param proposals list of proposals to select from
+ * @param private accept algorithms from a private range
+ * @return selected proposal, or NULL if none matches.
*/
proposal_t *(*select_proposal) (ike_cfg_t *this, linked_list_t *proposals,
bool private);
@@ -100,36 +102,36 @@ struct ike_cfg_t {
/**
* Should we send a certificate request in IKE_SA_INIT?
*
- * @return certificate request sending policy
+ * @return certificate request sending policy
*/
bool (*send_certreq) (ike_cfg_t *this);
/**
* Enforce UDP encapsulation by faking NATD notifies?
*
- * @return TRUE to enfoce UDP encapsulation
+ * @return TRUE to enfoce UDP encapsulation
*/
bool (*force_encap) (ike_cfg_t *this);
/**
* Get the DH group to use for IKE_SA setup.
*
- * @return dh group to use for initialization
+ * @return dh group to use for initialization
*/
diffie_hellman_group_t (*get_dh_group)(ike_cfg_t *this);
/**
* Check if two IKE configs are equal.
*
- * @param other other to check for equality
- * @return TRUE if other equal to this
+ * @param other other to check for equality
+ * @return TRUE if other equal to this
*/
bool (*equals)(ike_cfg_t *this, ike_cfg_t *other);
/**
* Increase reference count.
*
- * @return reference to this
+ * @return reference to this
*/
ike_cfg_t* (*get_ref) (ike_cfg_t *this);
@@ -147,15 +149,18 @@ struct ike_cfg_t {
*
* Supplied hosts become owned by ike_cfg, the name gets cloned.
*
- * @param certreq TRUE to send a certificate request
- * @param force_encap enforce UDP encapsulation by faking NATD notify
- * @param me address/DNS name of local peer
- * @param my_port IKE port to use as source, 500 uses IKEv2 port floating
- * @param other address/DNS name of remote peer
- * @param other_port IKE port to use as dest, 500 uses IKEv2 port floating
- * @return ike_cfg_t object.
+ * @param certreq TRUE to send a certificate request
+ * @param force_encap enforce UDP encapsulation by faking NATD notify
+ * @param me address/DNS name of local peer
+ * @param my_allow_any allow override of local address by any address
+ * @param my_port IKE port to use as source, 500 uses IKEv2 port floating
+ * @param other address/DNS name of remote peer
+ * @param other_allow_any allow override of remote address by any address
+ * @param other_port IKE port to use as dest, 500 uses IKEv2 port floating
+ * @return ike_cfg_t object.
*/
ike_cfg_t *ike_cfg_create(bool certreq, bool force_encap,
- char *me, u_int16_t my_port, char *other, u_int16_t other_port);
+ char *me, bool my_allow_any, u_int16_t my_port,
+ char *other, bool other_allow_any, u_int16_t other_port);
#endif /** IKE_CFG_H_ @}*/
diff --git a/src/libcharon/config/peer_cfg.c b/src/libcharon/config/peer_cfg.c
index c623cbc9b..01ca026e1 100644
--- a/src/libcharon/config/peer_cfg.c
+++ b/src/libcharon/config/peer_cfg.c
@@ -25,6 +25,12 @@
#include <utils/linked_list.h>
#include <utils/identification.h>
+ENUM(ike_version_names, IKE_ANY, IKEV2,
+ "IKEv1/2",
+ "IKEv1",
+ "IKEv2",
+);
+
ENUM(cert_policy_names, CERT_ALWAYS_SEND, CERT_NEVER_SEND,
"CERT_ALWAYS_SEND",
"CERT_SEND_IF_ASKED",
@@ -62,7 +68,7 @@ struct private_peer_cfg_t {
/**
* IKE version to use for initiation
*/
- u_int ike_version;
+ ike_version_t ike_version;
/**
* IKE config associated to this peer config
@@ -100,6 +106,11 @@ struct private_peer_cfg_t {
bool use_mobike;
/**
+ * Use aggressive mode?
+ */
+ bool aggressive;
+
+ /**
* Time before starting rekeying
*/
u_int32_t rekey_time;
@@ -125,14 +136,19 @@ struct private_peer_cfg_t {
u_int32_t dpd;
/**
- * virtual IP to use locally
+ * DPD timeout intervall (used for IKEv1 only)
+ */
+ u_int32_t dpd_timeout;
+
+ /**
+ * List of virtual IPs (host_t*) to request
*/
- host_t *virtual_ip;
+ linked_list_t *vips;
/**
- * pool to acquire configuration attributes from
+ * List of pool names to use for virtual IP lookup
*/
- char *pool;
+ linked_list_t *pools;
/**
* local authentication configs (rulesets)
@@ -169,7 +185,7 @@ METHOD(peer_cfg_t, get_name, char*,
return this->name;
}
-METHOD(peer_cfg_t, get_ike_version, u_int,
+METHOD(peer_cfg_t, get_ike_version, ike_version_t,
private_peer_cfg_t *this)
{
return this->ike_version;
@@ -240,7 +256,7 @@ METHOD(peer_cfg_t, create_child_cfg_enumerator, enumerator_t*,
* Check how good a list of TS matches a given child config
*/
static int get_ts_match(child_cfg_t *cfg, bool local,
- linked_list_t *sup_list, host_t *host)
+ linked_list_t *sup_list, linked_list_t *hosts)
{
linked_list_t *cfg_list;
enumerator_t *sup_enum, *cfg_enum;
@@ -248,7 +264,7 @@ static int get_ts_match(child_cfg_t *cfg, bool local,
int match = 0, round;
/* fetch configured TS list, narrowing dynamic TS */
- cfg_list = cfg->get_traffic_selectors(cfg, local, NULL, host);
+ cfg_list = cfg->get_traffic_selectors(cfg, local, NULL, hosts);
/* use a round counter to rate leading TS with higher priority */
round = sup_list->get_count(sup_list);
@@ -281,7 +297,7 @@ static int get_ts_match(child_cfg_t *cfg, bool local,
METHOD(peer_cfg_t, select_child_cfg, child_cfg_t*,
private_peer_cfg_t *this, linked_list_t *my_ts, linked_list_t *other_ts,
- host_t *my_host, host_t *other_host)
+ linked_list_t *my_hosts, linked_list_t *other_hosts)
{
child_cfg_t *current, *found = NULL;
enumerator_t *enumerator;
@@ -293,8 +309,8 @@ METHOD(peer_cfg_t, select_child_cfg, child_cfg_t*,
{
int my_prio, other_prio;
- my_prio = get_ts_match(current, TRUE, my_ts, my_host);
- other_prio = get_ts_match(current, FALSE, other_ts, other_host);
+ my_prio = get_ts_match(current, TRUE, my_ts, my_hosts);
+ other_prio = get_ts_match(current, FALSE, other_ts, other_hosts);
if (my_prio && other_prio)
{
@@ -336,13 +352,13 @@ METHOD(peer_cfg_t, get_keyingtries, u_int32_t,
}
METHOD(peer_cfg_t, get_rekey_time, u_int32_t,
- private_peer_cfg_t *this)
+ private_peer_cfg_t *this, bool jitter)
{
if (this->rekey_time == 0)
{
return 0;
}
- if (this->jitter_time == 0)
+ if (this->jitter_time == 0 || !jitter)
{
return this->rekey_time;
}
@@ -350,13 +366,13 @@ METHOD(peer_cfg_t, get_rekey_time, u_int32_t,
}
METHOD(peer_cfg_t, get_reauth_time, u_int32_t,
- private_peer_cfg_t *this)
+ private_peer_cfg_t *this, bool jitter)
{
if (this->reauth_time == 0)
{
return 0;
}
- if (this->jitter_time == 0)
+ if (this->jitter_time == 0 || !jitter)
{
return this->reauth_time;
}
@@ -375,22 +391,46 @@ METHOD(peer_cfg_t, use_mobike, bool,
return this->use_mobike;
}
+METHOD(peer_cfg_t, use_aggressive, bool,
+ private_peer_cfg_t *this)
+{
+ return this->aggressive;
+}
+
METHOD(peer_cfg_t, get_dpd, u_int32_t,
private_peer_cfg_t *this)
{
return this->dpd;
}
-METHOD(peer_cfg_t, get_virtual_ip, host_t*,
+METHOD(peer_cfg_t, get_dpd_timeout, u_int32_t,
private_peer_cfg_t *this)
{
- return this->virtual_ip;
+ return this->dpd_timeout;
+}
+
+METHOD(peer_cfg_t, add_virtual_ip, void,
+ private_peer_cfg_t *this, host_t *vip)
+{
+ this->vips->insert_last(this->vips, vip);
+}
+
+METHOD(peer_cfg_t, create_virtual_ip_enumerator, enumerator_t*,
+ private_peer_cfg_t *this)
+{
+ return this->vips->create_enumerator(this->vips);
+}
+
+METHOD(peer_cfg_t, add_pool, void,
+ private_peer_cfg_t *this, char *name)
+{
+ this->pools->insert_last(this->pools, strdup(name));
}
-METHOD(peer_cfg_t, get_pool, char*,
+METHOD(peer_cfg_t, create_pool_enumerator, enumerator_t*,
private_peer_cfg_t *this)
{
- return this->pool;
+ return this->pools->create_enumerator(this->pools);
}
METHOD(peer_cfg_t, add_auth_cfg, void,
@@ -493,6 +533,10 @@ static bool auth_cfg_equal(private_peer_cfg_t *this, private_peer_cfg_t *other)
METHOD(peer_cfg_t, equals, bool,
private_peer_cfg_t *this, private_peer_cfg_t *other)
{
+ enumerator_t *e1, *e2;
+ host_t *vip1, *vip2;
+ char *pool1, *pool2;
+
if (this == other)
{
return TRUE;
@@ -502,6 +546,43 @@ METHOD(peer_cfg_t, equals, bool,
return FALSE;
}
+ if (this->vips->get_count(this->vips) != other->vips->get_count(other->vips))
+ {
+ return FALSE;
+ }
+ e1 = create_virtual_ip_enumerator(this);
+ e2 = create_virtual_ip_enumerator(other);
+ if (e1->enumerate(e1, &vip1) && e2->enumerate(e2, &vip2))
+ {
+ if (!vip1->ip_equals(vip1, vip2))
+ {
+ e1->destroy(e1);
+ e2->destroy(e2);
+ return FALSE;
+ }
+ }
+ e1->destroy(e1);
+ e2->destroy(e2);
+
+ if (this->pools->get_count(this->pools) !=
+ other->pools->get_count(other->pools))
+ {
+ return FALSE;
+ }
+ e1 = create_pool_enumerator(this);
+ e2 = create_pool_enumerator(other);
+ if (e1->enumerate(e1, &pool1) && e2->enumerate(e2, &pool2))
+ {
+ if (!streq(pool1, pool2))
+ {
+ e1->destroy(e1);
+ e2->destroy(e2);
+ return FALSE;
+ }
+ }
+ e1->destroy(e1);
+ e2->destroy(e2);
+
return (
this->ike_version == other->ike_version &&
this->cert_policy == other->cert_policy &&
@@ -513,11 +594,6 @@ METHOD(peer_cfg_t, equals, bool,
this->jitter_time == other->jitter_time &&
this->over_time == other->over_time &&
this->dpd == other->dpd &&
- (this->virtual_ip == other->virtual_ip ||
- (this->virtual_ip && other->virtual_ip &&
- this->virtual_ip->equals(this->virtual_ip, other->virtual_ip))) &&
- (this->pool == other->pool ||
- (this->pool && other->pool && streq(this->pool, other->pool))) &&
auth_cfg_equal(this, other)
#ifdef ME
&& this->mediation == other->mediation &&
@@ -544,18 +620,18 @@ METHOD(peer_cfg_t, destroy, void,
this->ike_cfg->destroy(this->ike_cfg);
this->child_cfgs->destroy_offset(this->child_cfgs,
offsetof(child_cfg_t, destroy));
- DESTROY_IF(this->virtual_ip);
this->local_auth->destroy_offset(this->local_auth,
offsetof(auth_cfg_t, destroy));
this->remote_auth->destroy_offset(this->remote_auth,
offsetof(auth_cfg_t, destroy));
+ this->vips->destroy_offset(this->vips, offsetof(host_t, destroy));
+ this->pools->destroy_function(this->pools, free);
#ifdef ME
DESTROY_IF(this->mediated_by);
DESTROY_IF(this->peer_id);
#endif /* ME */
this->mutex->destroy(this->mutex);
free(this->name);
- free(this->pool);
free(this);
}
}
@@ -563,12 +639,13 @@ METHOD(peer_cfg_t, destroy, void,
/*
* Described in header-file
*/
-peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
- cert_policy_t cert_policy, unique_policy_t unique,
- u_int32_t keyingtries, u_int32_t rekey_time,
- u_int32_t reauth_time, u_int32_t jitter_time,
- u_int32_t over_time, bool mobike, u_int32_t dpd,
- host_t *virtual_ip, char *pool,
+peer_cfg_t *peer_cfg_create(char *name, ike_version_t ike_version,
+ ike_cfg_t *ike_cfg, cert_policy_t cert_policy,
+ unique_policy_t unique, u_int32_t keyingtries,
+ u_int32_t rekey_time, u_int32_t reauth_time,
+ u_int32_t jitter_time, u_int32_t over_time,
+ bool mobike, bool aggressive, u_int32_t dpd,
+ u_int32_t dpd_timeout,
bool mediation, peer_cfg_t *mediated_by,
identification_t *peer_id)
{
@@ -599,9 +676,13 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
.get_reauth_time = _get_reauth_time,
.get_over_time = _get_over_time,
.use_mobike = _use_mobike,
+ .use_aggressive = _use_aggressive,
.get_dpd = _get_dpd,
- .get_virtual_ip = _get_virtual_ip,
- .get_pool = _get_pool,
+ .get_dpd_timeout = _get_dpd_timeout,
+ .add_virtual_ip = _add_virtual_ip,
+ .create_virtual_ip_enumerator = _create_virtual_ip_enumerator,
+ .add_pool = _add_pool,
+ .create_pool_enumerator = _create_pool_enumerator,
.add_auth_cfg = _add_auth_cfg,
.create_auth_cfg_enumerator = _create_auth_cfg_enumerator,
.equals = (void*)_equals,
@@ -626,9 +707,11 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
.jitter_time = jitter_time,
.over_time = over_time,
.use_mobike = mobike,
+ .aggressive = aggressive,
.dpd = dpd,
- .virtual_ip = virtual_ip,
- .pool = strdupnull(pool),
+ .dpd_timeout = dpd_timeout,
+ .vips = linked_list_create(),
+ .pools = linked_list_create(),
.local_auth = linked_list_create(),
.remote_auth = linked_list_create(),
.refcount = 1,
diff --git a/src/libcharon/config/peer_cfg.h b/src/libcharon/config/peer_cfg.h
index f644fb547..97089e1b0 100644
--- a/src/libcharon/config/peer_cfg.h
+++ b/src/libcharon/config/peer_cfg.h
@@ -23,6 +23,7 @@
#ifndef PEER_CFG_H_
#define PEER_CFG_H_
+typedef enum ike_version_t ike_version_t;
typedef enum cert_policy_t cert_policy_t;
typedef enum unique_policy_t unique_policy_t;
typedef struct peer_cfg_t peer_cfg_t;
@@ -34,11 +35,26 @@ typedef struct peer_cfg_t peer_cfg_t;
#include <config/proposal.h>
#include <config/ike_cfg.h>
#include <config/child_cfg.h>
-#include <sa/authenticators/authenticator.h>
-#include <sa/authenticators/eap/eap_method.h>
#include <credentials/auth_cfg.h>
/**
+ * IKE version.
+ */
+enum ike_version_t {
+ /** any version */
+ IKE_ANY = 0,
+ /** IKE version 1 */
+ IKEV1 = 1,
+ /** IKE version 2 */
+ IKEV2 = 2,
+};
+
+/**
+ * enum strings fro ike_version_t
+ */
+extern enum_name_t *ike_version_names;
+
+/**
* Certificate sending policy. This is also used for certificate
* requests when using this definition for the other peer. If
* it is CERT_NEVER_SEND, a certreq is omitted, otherwise its
@@ -65,11 +81,13 @@ extern enum_name_t *cert_policy_names;
* Uniqueness of an IKE_SA, used to drop multiple connections with one peer.
*/
enum unique_policy_t {
- /** do not check for client uniqueness */
+ /** never check for client uniqueness */
+ UNIQUE_NEVER,
+ /** only check for client uniqueness when receiving an INITIAL_CONTACT */
UNIQUE_NO,
- /** replace unique IKE_SAs if new ones get established */
+ /** replace existing IKE_SAs when new ones get established by a client */
UNIQUE_REPLACE,
- /** keep existing IKE_SAs, close the new ones on connection attept */
+ /** keep existing IKE_SAs, close the new ones on connection attempt */
UNIQUE_KEEP,
};
@@ -130,7 +148,7 @@ struct peer_cfg_t {
*
* @return IKE major version
*/
- u_int (*get_ike_version)(peer_cfg_t *this);
+ ike_version_t (*get_ike_version)(peer_cfg_t *this);
/**
* Get the IKE config to use for initiaton.
@@ -165,13 +183,13 @@ struct peer_cfg_t {
*
* @param my_ts TS for local side
* @param other_ts TS for remote side
- * @param my_host host to narrow down dynamic TS for local side
- * @param other_host host to narrow down dynamic TS for remote side
+ * @param my_hosts hosts to narrow down dynamic TS for local side
+ * @param other_hosts hosts to narrow down dynamic TS for remote side
* @return selected CHILD config, or NULL if no match found
*/
- child_cfg_t* (*select_child_cfg) (peer_cfg_t *this, linked_list_t *my_ts,
- linked_list_t *other_ts, host_t *my_host,
- host_t *other_host);
+ child_cfg_t* (*select_child_cfg) (peer_cfg_t *this,
+ linked_list_t *my_ts, linked_list_t *other_ts,
+ linked_list_t *my_hosts, linked_list_t *other_hosts);
/**
* Add an authentication config to the peer configuration.
@@ -211,18 +229,20 @@ struct peer_cfg_t {
u_int32_t (*get_keyingtries) (peer_cfg_t *this);
/**
- * Get a time to start rekeying (is randomized with jitter).
+ * Get a time to start rekeying.
*
+ * @param jitter remove a jitter value to randomize time
* @return time in s when to start rekeying, 0 disables rekeying
*/
- u_int32_t (*get_rekey_time)(peer_cfg_t *this);
+ u_int32_t (*get_rekey_time)(peer_cfg_t *this, bool jitter);
/**
- * Get a time to start reauthentication (is randomized with jitter).
+ * Get a time to start reauthentication.
*
+ * @param jitter remove a jitter value to randomize time
* @return time in s when to start reauthentication, 0 disables it
*/
- u_int32_t (*get_reauth_time)(peer_cfg_t *this);
+ u_int32_t (*get_reauth_time)(peer_cfg_t *this, bool jitter);
/**
* Get the timeout of a rekeying/reauthenticating SA.
@@ -239,6 +259,13 @@ struct peer_cfg_t {
bool (*use_mobike) (peer_cfg_t *this);
/**
+ * Use/Accept aggressive mode with IKEv1?.
+ *
+ * @return TRUE to use aggressive mode
+ */
+ bool (*use_aggressive)(peer_cfg_t *this);
+
+ /**
* Get the DPD check interval.
*
* @return dpd_delay in seconds
@@ -246,23 +273,41 @@ struct peer_cfg_t {
u_int32_t (*get_dpd) (peer_cfg_t *this);
/**
- * Get a virtual IP for the local peer.
+ * Get the DPD timeout interval (IKEv1 only)
*
- * If no virtual IP should be used, NULL is returned. %any means to request
- * a virtual IP using configuration payloads. A specific address is also
- * used for a request and may be changed by the server.
+ * @return dpd_timeout in seconds
+ */
+ u_int32_t (*get_dpd_timeout) (peer_cfg_t *this);
+
+ /**
+ * Add a virtual IP to request as initiator.
+ *
+ * @param vip virtual IP to request, may be %any or %any6
+ */
+ void (*add_virtual_ip)(peer_cfg_t *this, host_t *vip);
+
+ /**
+ * Create an enumerator over virtual IPs to request.
+ *
+ * The returned enumerator enumerates over IPs added with add_virtual_ip().
+ *
+ * @return enumerator over host_t*
+ */
+ enumerator_t* (*create_virtual_ip_enumerator)(peer_cfg_t *this);
+
+ /**
+ * Add a pool name this configuration uses to select virtual IPs.
*
- * @param suggestion NULL, %any or specific
- * @return virtual IP, %any or NULL
+ * @param name pool name to use for virtual IP lookup
*/
- host_t* (*get_virtual_ip) (peer_cfg_t *this);
+ void (*add_pool)(peer_cfg_t *this, char *name);
/**
- * Get the name of the pool to acquire configuration attributes from.
+ * Create an enumerator over pool names of this config.
*
- * @return pool name, NULL if none defined
+ * @return enumerator over char*
*/
- char* (*get_pool)(peer_cfg_t *this);
+ enumerator_t* (*create_pool_enumerator)(peer_cfg_t *this);
#ifdef ME
/**
@@ -339,20 +384,21 @@ struct peer_cfg_t {
* @param jitter_time timerange to randomly subtract from rekey/reauth time
* @param over_time maximum overtime before closing a rekeying/reauth SA
* @param mobike use MOBIKE (RFC4555) if peer supports it
+ * @param aggressive use/accept aggressive mode with IKEv1
* @param dpd DPD check interval, 0 to disable
- * @param virtual_ip virtual IP for local host, or NULL
- * @param pool pool name to get configuration attributes from, or NULL
+ * @param dpd_timeout DPD timeout interval (IKEv1 only), if 0 default applies
* @param mediation TRUE if this is a mediation connection
* @param mediated_by peer_cfg_t of the mediation connection to mediate through
* @param peer_id ID that identifies our peer at the mediation server
* @return peer_cfg_t object
*/
-peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
- cert_policy_t cert_policy, unique_policy_t unique,
- u_int32_t keyingtries, u_int32_t rekey_time,
- u_int32_t reauth_time, u_int32_t jitter_time,
- u_int32_t over_time, bool mobike, u_int32_t dpd,
- host_t *virtual_ip, char *pool,
+peer_cfg_t *peer_cfg_create(char *name, ike_version_t ike_version,
+ ike_cfg_t *ike_cfg, cert_policy_t cert_policy,
+ unique_policy_t unique, u_int32_t keyingtries,
+ u_int32_t rekey_time, u_int32_t reauth_time,
+ u_int32_t jitter_time, u_int32_t over_time,
+ bool mobike, bool aggressive, u_int32_t dpd,
+ u_int32_t dpd_timeout,
bool mediation, peer_cfg_t *mediated_by,
identification_t *peer_id);
diff --git a/src/libcharon/config/proposal.c b/src/libcharon/config/proposal.c
index d3c60a469..43b467f46 100644
--- a/src/libcharon/config/proposal.c
+++ b/src/libcharon/config/proposal.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2009 Tobias Brunner
+ * Copyright (C) 2008-2012 Tobias Brunner
* Copyright (C) 2006-2010 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -21,18 +21,18 @@
#include <daemon.h>
#include <utils/linked_list.h>
#include <utils/identification.h>
-#include <utils/lexparser.h>
+
#include <crypto/transform.h>
#include <crypto/prfs/prf.h>
#include <crypto/crypters/crypter.h>
#include <crypto/signers/signer.h>
-#include <crypto/proposal/proposal_keywords.h>
-ENUM(protocol_id_names, PROTO_NONE, PROTO_ESP,
+ENUM(protocol_id_names, PROTO_NONE, PROTO_IPCOMP,
"PROTO_NONE",
"IKE",
"AH",
"ESP",
+ "IPCOMP",
);
typedef struct private_proposal_t private_proposal_t;
@@ -559,14 +559,15 @@ static void check_proposal(private_proposal_t *this)
/**
* add a algorithm identified by a string to the proposal.
*/
-static status_t add_string_algo(private_proposal_t *this, chunk_t alg)
+static bool add_string_algo(private_proposal_t *this, const char *alg)
{
- const proposal_token_t *token = proposal_get_token(alg.ptr, alg.len);
+ const proposal_token_t *token;
+ token = lib->proposal->get_token(lib->proposal, alg);
if (token == NULL)
{
- DBG1(DBG_CFG, "algorithm '%.*s' not recognized", alg.len, alg.ptr);
- return FAILED;
+ DBG1(DBG_CFG, "algorithm '%s' not recognized", alg);
+ return FALSE;
}
add_algorithm(this, token->type, token->algorithm, token->keysize);
@@ -609,13 +610,13 @@ static status_t add_string_algo(private_proposal_t *this, chunk_t alg)
add_algorithm(this, PSEUDO_RANDOM_FUNCTION, prf, 0);
}
}
- return SUCCESS;
+ return TRUE;
}
/**
* print all algorithms of a kind to buffer
*/
-static int print_alg(private_proposal_t *this, char **dst, size_t *len,
+static int print_alg(private_proposal_t *this, printf_hook_data_t *data,
u_int kind, void *names, bool *first)
{
enumerator_t *enumerator;
@@ -627,16 +628,16 @@ static int print_alg(private_proposal_t *this, char **dst, size_t *len,
{
if (*first)
{
- written += print_in_hook(*dst, *len, "%N", names, alg);
+ written += print_in_hook(data, "%N", names, alg);
*first = FALSE;
}
else
{
- written += print_in_hook(*dst, *len, "/%N", names, alg);
+ written += print_in_hook(data, "/%N", names, alg);
}
if (size)
{
- written += print_in_hook(*dst, *len, "_%u", size);
+ written += print_in_hook(data, "_%u", size);
}
}
enumerator->destroy(enumerator);
@@ -646,7 +647,7 @@ static int print_alg(private_proposal_t *this, char **dst, size_t *len,
/**
* Described in header.
*/
-int proposal_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
+int proposal_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
const void *const *args)
{
private_proposal_t *this = *((private_proposal_t**)(args[0]));
@@ -657,7 +658,7 @@ int proposal_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
if (this == NULL)
{
- return print_in_hook(dst, len, "(null)");
+ return print_in_hook(data, "(null)");
}
if (spec->hash)
@@ -667,28 +668,28 @@ int proposal_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
{ /* call recursivly */
if (first)
{
- written += print_in_hook(dst, len, "%P", this);
+ written += print_in_hook(data, "%P", this);
first = FALSE;
}
else
{
- written += print_in_hook(dst, len, ", %P", this);
+ written += print_in_hook(data, ", %P", this);
}
}
enumerator->destroy(enumerator);
return written;
}
- written = print_in_hook(dst, len, "%N:", protocol_id_names, this->protocol);
- written += print_alg(this, &dst, &len, ENCRYPTION_ALGORITHM,
+ written = print_in_hook(data, "%N:", protocol_id_names, this->protocol);
+ written += print_alg(this, data, ENCRYPTION_ALGORITHM,
encryption_algorithm_names, &first);
- written += print_alg(this, &dst, &len, INTEGRITY_ALGORITHM,
+ written += print_alg(this, data, INTEGRITY_ALGORITHM,
integrity_algorithm_names, &first);
- written += print_alg(this, &dst, &len, PSEUDO_RANDOM_FUNCTION,
+ written += print_alg(this, data, PSEUDO_RANDOM_FUNCTION,
pseudo_random_function_names, &first);
- written += print_alg(this, &dst, &len, DIFFIE_HELLMAN_GROUP,
+ written += print_alg(this, data, DIFFIE_HELLMAN_GROUP,
diffie_hellman_group_names, &first);
- written += print_alg(this, &dst, &len, EXTENDED_SEQUENCE_NUMBERS,
+ written += print_alg(this, data, EXTENDED_SEQUENCE_NUMBERS,
extended_sequence_numbers_names, &first);
return written;
}
@@ -840,6 +841,7 @@ static void proposal_add_supported_ike(private_proposal_t *this)
case MODP_1024_BIT:
case MODP_1536_BIT:
case MODP_2048_BIT:
+ case MODP_3072_BIT:
case MODP_4096_BIT:
case MODP_8192_BIT:
case ECP_256_BIT:
@@ -899,28 +901,27 @@ proposal_t *proposal_create_default(protocol_id_t protocol)
*/
proposal_t *proposal_create_from_string(protocol_id_t protocol, const char *algs)
{
- private_proposal_t *this = (private_proposal_t*)proposal_create(protocol, 0);
- chunk_t string = {(void*)algs, strlen(algs)};
- chunk_t alg;
- status_t status = SUCCESS;
+ private_proposal_t *this;
+ enumerator_t *enumerator;
+ bool failed = TRUE;
+ char *alg;
- eat_whitespace(&string);
- if (string.len < 1)
- {
- destroy(this);
- return NULL;
- }
+ this = (private_proposal_t*)proposal_create(protocol, 0);
/* get all tokens, separated by '-' */
- while (extract_token(&alg, '-', &string))
- {
- status |= add_string_algo(this, alg);
- }
- if (string.len)
+ enumerator = enumerator_create_token(algs, "-", " ");
+ while (enumerator->enumerate(enumerator, &alg))
{
- status |= add_string_algo(this, string);
+ if (!add_string_algo(this, alg))
+ {
+ failed = TRUE;
+ break;
+ }
+ failed = FALSE;
}
- if (status != SUCCESS)
+ enumerator->destroy(enumerator);
+
+ if (failed)
{
destroy(this);
return NULL;
diff --git a/src/libcharon/config/proposal.h b/src/libcharon/config/proposal.h
index 8f54d7e6e..33abf006c 100644
--- a/src/libcharon/config/proposal.h
+++ b/src/libcharon/config/proposal.h
@@ -43,6 +43,7 @@ enum protocol_id_t {
PROTO_IKE = 1,
PROTO_AH = 2,
PROTO_ESP = 3,
+ PROTO_IPCOMP = 4, /* IKEv1 only */
};
/**
@@ -215,7 +216,7 @@ proposal_t *proposal_create_from_string(protocol_id_t protocol, const char *algs
* With the #-specifier, arguments are:
* linked_list_t *list containing proposal_t*
*/
-int proposal_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
+int proposal_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
const void *const *args);
#endif /** PROPOSAL_H_ @}*/
diff --git a/src/libcharon/control/controller.c b/src/libcharon/control/controller.c
index 0f247962b..77d73dba9 100644
--- a/src/libcharon/control/controller.c
+++ b/src/libcharon/control/controller.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2011-2012 Tobias Brunner
* Copyright (C) 2007-2011 Martin Willi
* Copyright (C) 2011 revosec AG
* Hochschule fuer Technik Rapperswil
@@ -23,10 +24,13 @@
#include <daemon.h>
#include <library.h>
-
+#include <threading/thread.h>
+#include <threading/spinlock.h>
+#include <threading/semaphore.h>
typedef struct private_controller_t private_controller_t;
typedef struct interface_listener_t interface_listener_t;
+typedef struct interface_logger_t interface_logger_t;
/**
* Private data of an stroke_t object.
@@ -40,19 +44,18 @@ struct private_controller_t {
};
/**
- * helper struct to map listener callbacks to interface callbacks
+ * helper struct for the logger interface
*/
-struct interface_listener_t {
-
+struct interface_logger_t {
/**
- * public bus listener interface
+ * public logger interface
*/
- listener_t public;
+ logger_t public;
/**
- * status of the operation, return to method callers
+ * reference to the listener
*/
- status_t status;
+ interface_listener_t *listener;
/**
* interface callback (listener gets redirected to here)
@@ -63,6 +66,27 @@ struct interface_listener_t {
* user parameter to pass to callback
*/
void *param;
+};
+
+/**
+ * helper struct to map listener callbacks to interface callbacks
+ */
+struct interface_listener_t {
+
+ /**
+ * public bus listener interface
+ */
+ listener_t public;
+
+ /**
+ * logger interface
+ */
+ interface_logger_t logger;
+
+ /**
+ * status of the operation, return to method callers
+ */
+ status_t status;
/**
* child configuration, used for initiate
@@ -80,14 +104,19 @@ struct interface_listener_t {
ike_sa_t *ike_sa;
/**
- * CHILD_SA to handle
+ * unique ID, used for various methods
*/
- child_sa_t *child_sa;
+ u_int32_t id;
/**
- * unique ID, used for various methods
+ * semaphore to implement wait_for_listener()
*/
- u_int32_t id;
+ semaphore_t *done;
+
+ /**
+ * spinlock to update the IKE_SA handle properly
+ */
+ spinlock_t *lock;
};
@@ -107,20 +136,103 @@ struct interface_job_t {
* associated listener
*/
interface_listener_t listener;
+
+ /**
+ * the job is reference counted as the thread executing a job as well as
+ * the thread waiting in wait_for_listener() require it but either of them
+ * could be done first
+ */
+ refcount_t refcount;
};
-METHOD(listener_t, listener_log, bool,
- interface_listener_t *this, debug_t group, level_t level, int thread,
- ike_sa_t *ike_sa, char* format, va_list args)
+/**
+ * This function wakes a thread that is waiting in wait_for_listener(),
+ * either from a listener or from a job.
+ */
+static inline bool listener_done(interface_listener_t *listener)
{
- if (this->ike_sa == ike_sa)
+ if (listener->done)
{
- if (!this->callback(this->param, group, level, ike_sa, format, args))
+ listener->done->post(listener->done);
+ }
+ return FALSE;
+}
+
+/**
+ * thread_cleanup_t handler to unregister a listener.
+ */
+static void listener_unregister(interface_listener_t *listener)
+{
+ charon->bus->remove_listener(charon->bus, &listener->public);
+ charon->bus->remove_logger(charon->bus, &listener->logger.public);
+}
+
+/**
+ * Registers the listener, executes the job and then waits synchronously until
+ * the listener is done or the timeout occurred.
+ *
+ * @note Use 'return listener_done(listener)' to properly unregister a listener
+ *
+ * @param listener listener to register
+ * @param job job to execute asynchronously when registered, or NULL
+ * @param timeout max timeout in ms to listen for events, 0 to disable
+ * @return TRUE if timed out
+ */
+static bool wait_for_listener(interface_job_t *job, u_int timeout)
+{
+ interface_listener_t *listener = &job->listener;
+ bool old, timed_out = FALSE;
+
+ /* avoid that the job is destroyed too early */
+ ref_get(&job->refcount);
+
+ listener->done = semaphore_create(0);
+
+ charon->bus->add_logger(charon->bus, &listener->logger.public);
+ charon->bus->add_listener(charon->bus, &listener->public);
+ lib->processor->queue_job(lib->processor, &job->public);
+
+ thread_cleanup_push((thread_cleanup_t)listener_unregister, listener);
+ old = thread_cancelability(TRUE);
+ if (timeout)
+ {
+ timed_out = listener->done->timed_wait(listener->done, timeout);
+ }
+ else
+ {
+ listener->done->wait(listener->done);
+ }
+ thread_cancelability(old);
+ thread_cleanup_pop(TRUE);
+ return timed_out;
+}
+
+METHOD(logger_t, listener_log, void,
+ interface_logger_t *this, debug_t group, level_t level, int thread,
+ ike_sa_t *ike_sa, const char *message)
+{
+ ike_sa_t *target;
+
+ this->listener->lock->lock(this->listener->lock);
+ target = this->listener->ike_sa;
+ this->listener->lock->unlock(this->listener->lock);
+
+ if (target == ike_sa)
+ {
+ if (!this->callback(this->param, group, level, ike_sa, message))
{
- return FALSE;
+ this->listener->status = NEED_MORE;
+ listener_done(this->listener);
}
}
- return TRUE;
+}
+
+METHOD(logger_t, listener_get_level, level_t,
+ interface_logger_t *this, debug_t group)
+{
+ /* in order to allow callback listeners to decide what they want to log
+ * we request any log message, but only if we actually want logging */
+ return this->callback == controller_cb_empty ? LEVEL_SILENT : LEVEL_PRIVATE;
}
METHOD(job_t, get_priority_medium, job_priority_t,
@@ -132,7 +244,13 @@ METHOD(job_t, get_priority_medium, job_priority_t,
METHOD(listener_t, ike_state_change, bool,
interface_listener_t *this, ike_sa_t *ike_sa, ike_sa_state_t state)
{
- if (this->ike_sa == ike_sa)
+ ike_sa_t *target;
+
+ this->lock->lock(this->lock);
+ target = this->ike_sa;
+ this->lock->unlock(this->lock);
+
+ if (target == ike_sa)
{
switch (state)
{
@@ -144,7 +262,7 @@ METHOD(listener_t, ike_state_change, bool,
if (peer_cfg->is_mediation(peer_cfg))
{
this->status = SUCCESS;
- return FALSE;
+ return listener_done(this);
}
break;
}
@@ -154,7 +272,7 @@ METHOD(listener_t, ike_state_change, bool,
{ /* proper termination */
this->status = SUCCESS;
}
- return FALSE;
+ return listener_done(this);
default:
break;
}
@@ -166,13 +284,19 @@ METHOD(listener_t, child_state_change, bool,
interface_listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
child_sa_state_t state)
{
- if (this->ike_sa == ike_sa)
+ ike_sa_t *target;
+
+ this->lock->lock(this->lock);
+ target = this->ike_sa;
+ this->lock->unlock(this->lock);
+
+ if (target == ike_sa)
{
switch (state)
{
case CHILD_INSTALLED:
this->status = SUCCESS;
- return FALSE;
+ return listener_done(this);
case CHILD_DESTROYING:
switch (child_sa->get_state(child_sa))
{
@@ -183,7 +307,7 @@ METHOD(listener_t, child_state_change, bool,
default:
break;
}
- return FALSE;
+ return listener_done(this);
default:
break;
}
@@ -191,13 +315,14 @@ METHOD(listener_t, child_state_change, bool,
return TRUE;
}
-METHOD(job_t, recheckin, void,
- interface_job_t *job)
+METHOD(job_t, destroy_job, void,
+ interface_job_t *this)
{
- if (job->listener.ike_sa)
+ if (ref_put(&this->refcount))
{
- charon->ike_sa_manager->checkin(charon->ike_sa_manager,
- job->listener.ike_sa);
+ this->listener.lock->destroy(this->listener.lock);
+ DESTROY_IF(this->listener.done);
+ free(this);
}
}
@@ -208,7 +333,7 @@ METHOD(controller_t, create_ike_sa_enumerator, enumerator_t*,
wait);
}
-METHOD(job_t, initiate_execute, void,
+METHOD(job_t, initiate_execute, job_requeue_t,
interface_job_t *job)
{
ike_sa_t *ike_sa;
@@ -217,7 +342,18 @@ METHOD(job_t, initiate_execute, void,
ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
peer_cfg);
+ if (!ike_sa)
+ {
+ listener->child_cfg->destroy(listener->child_cfg);
+ peer_cfg->destroy(peer_cfg);
+ listener->status = FAILED;
+ /* release listener */
+ listener_done(listener);
+ return JOB_REQUEUE_NONE;
+ }
+ listener->lock->lock(listener->lock);
listener->ike_sa = ike_sa;
+ listener->lock->unlock(listener->lock);
if (ike_sa->get_peer_cfg(ike_sa) == NULL)
{
@@ -227,228 +363,271 @@ METHOD(job_t, initiate_execute, void,
if (ike_sa->initiate(ike_sa, listener->child_cfg, 0, NULL, NULL) == SUCCESS)
{
- charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
listener->status = SUCCESS;
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
}
else
{
+ listener->status = FAILED;
charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
ike_sa);
- listener->status = FAILED;
}
+ return JOB_REQUEUE_NONE;
}
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)
{
- interface_job_t job = {
+ interface_job_t *job;
+ status_t status;
+
+ INIT(job,
.listener = {
.public = {
- .log = _listener_log,
.ike_state_change = _ike_state_change,
.child_state_change = _child_state_change,
},
- .callback = callback,
- .param = param,
+ .logger = {
+ .public = {
+ .log = _listener_log,
+ .get_level = _listener_get_level,
+ },
+ .callback = callback,
+ .param = param,
+ },
.status = FAILED,
.child_cfg = child_cfg,
.peer_cfg = peer_cfg,
+ .lock = spinlock_create(),
},
.public = {
.execute = _initiate_execute,
.get_priority = _get_priority_medium,
- .destroy = _recheckin,
+ .destroy = _destroy_job,
},
- };
+ .refcount = 1,
+ );
+ job->listener.logger.listener = &job->listener;
+
if (callback == NULL)
{
- initiate_execute(&job);
+ initiate_execute(job);
}
else
{
- if (charon->bus->listen(charon->bus, &job.listener.public, &job.public,
- timeout))
+ if (wait_for_listener(job, timeout))
{
- job.listener.status = OUT_OF_RES;
+ job->listener.status = OUT_OF_RES;
}
}
- return job.listener.status;
+ status = job->listener.status;
+ destroy_job(job);
+ return status;
}
-METHOD(job_t, terminate_ike_execute, void,
+METHOD(job_t, terminate_ike_execute, job_requeue_t,
interface_job_t *job)
{
interface_listener_t *listener = &job->listener;
- ike_sa_t *ike_sa = listener->ike_sa;
+ u_int32_t unique_id = listener->id;
+ ike_sa_t *ike_sa;
- charon->bus->set_sa(charon->bus, ike_sa);
+ ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
+ unique_id, FALSE);
+ if (!ike_sa)
+ {
+ DBG1(DBG_IKE, "unable to terminate IKE_SA: ID %d not found", unique_id);
+ listener->status = NOT_FOUND;
+ /* release listener */
+ listener_done(listener);
+ return JOB_REQUEUE_NONE;
+ }
+ listener->lock->lock(listener->lock);
+ listener->ike_sa = ike_sa;
+ listener->lock->unlock(listener->lock);
if (ike_sa->delete(ike_sa) != DESTROY_ME)
- {
- charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
- /* delete failed */
+ { /* delete failed */
listener->status = FAILED;
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
}
else
{
+ listener->status = SUCCESS;
charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
ike_sa);
- listener->status = SUCCESS;
}
+ return JOB_REQUEUE_NONE;
}
METHOD(controller_t, terminate_ike, status_t,
controller_t *this, u_int32_t unique_id,
controller_cb_t callback, void *param, u_int timeout)
{
- ike_sa_t *ike_sa;
- interface_job_t job = {
+ interface_job_t *job;
+ status_t status;
+
+ INIT(job,
.listener = {
.public = {
- .log = _listener_log,
.ike_state_change = _ike_state_change,
.child_state_change = _child_state_change,
},
- .callback = callback,
- .param = param,
+ .logger = {
+ .public = {
+ .log = _listener_log,
+ .get_level = _listener_get_level,
+ },
+ .callback = callback,
+ .param = param,
+ },
.status = FAILED,
.id = unique_id,
+ .lock = spinlock_create(),
},
.public = {
.execute = _terminate_ike_execute,
.get_priority = _get_priority_medium,
- .destroy = _recheckin,
+ .destroy = _destroy_job,
},
- };
-
- ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
- unique_id, FALSE);
- if (ike_sa == NULL)
- {
- DBG1(DBG_IKE, "unable to terminate IKE_SA: ID %d not found", unique_id);
- return NOT_FOUND;
- }
- job.listener.ike_sa = ike_sa;
+ .refcount = 1,
+ );
+ job->listener.logger.listener = &job->listener;
if (callback == NULL)
{
- terminate_ike_execute(&job);
+ terminate_ike_execute(job);
}
else
{
- if (charon->bus->listen(charon->bus, &job.listener.public, &job.public,
- timeout))
+ if (wait_for_listener(job, timeout))
{
- job.listener.status = OUT_OF_RES;
+ job->listener.status = OUT_OF_RES;
}
- /* checkin of the ike_sa happened in the thread that executed the job */
- charon->bus->set_sa(charon->bus, NULL);
}
- return job.listener.status;
+ status = job->listener.status;
+ destroy_job(job);
+ return status;
}
-METHOD(job_t, terminate_child_execute, void,
+METHOD(job_t, terminate_child_execute, job_requeue_t,
interface_job_t *job)
{
interface_listener_t *listener = &job->listener;
- ike_sa_t *ike_sa = listener->ike_sa;
- child_sa_t *child_sa = listener->child_sa;
+ u_int32_t reqid = listener->id;
+ enumerator_t *enumerator;
+ child_sa_t *child_sa;
+ ike_sa_t *ike_sa;
- charon->bus->set_sa(charon->bus, ike_sa);
- if (ike_sa->delete_child_sa(ike_sa, child_sa->get_protocol(child_sa),
- child_sa->get_spi(child_sa, TRUE)) != DESTROY_ME)
+ ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
+ reqid, TRUE);
+ if (!ike_sa)
+ {
+ DBG1(DBG_IKE, "unable to terminate, CHILD_SA with ID %d not found",
+ reqid);
+ listener->status = NOT_FOUND;
+ /* release listener */
+ listener_done(listener);
+ return JOB_REQUEUE_NONE;
+ }
+ listener->lock->lock(listener->lock);
+ listener->ike_sa = ike_sa;
+ listener->lock->unlock(listener->lock);
+
+ enumerator = ike_sa->create_child_sa_enumerator(ike_sa);
+ while (enumerator->enumerate(enumerator, (void**)&child_sa))
{
+ if (child_sa->get_state(child_sa) != CHILD_ROUTED &&
+ child_sa->get_reqid(child_sa) == reqid)
+ {
+ break;
+ }
+ child_sa = NULL;
+ }
+ enumerator->destroy(enumerator);
+
+ if (!child_sa)
+ {
+ DBG1(DBG_IKE, "unable to terminate, established "
+ "CHILD_SA with ID %d not found", reqid);
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ listener->status = NOT_FOUND;
+ /* release listener */
+ listener_done(listener);
+ return JOB_REQUEUE_NONE;
+ }
+
+ if (ike_sa->delete_child_sa(ike_sa, child_sa->get_protocol(child_sa),
+ child_sa->get_spi(child_sa, TRUE), FALSE) != DESTROY_ME)
+ {
listener->status = SUCCESS;
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
}
else
{
+ listener->status = FAILED;
charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
ike_sa);
- listener->status = FAILED;
}
+ return JOB_REQUEUE_NONE;
}
METHOD(controller_t, terminate_child, status_t,
controller_t *this, u_int32_t reqid,
controller_cb_t callback, void *param, u_int timeout)
{
- ike_sa_t *ike_sa;
- child_sa_t *child_sa;
- enumerator_t *enumerator;
- interface_job_t job = {
+ interface_job_t *job;
+ status_t status;
+
+ INIT(job,
.listener = {
.public = {
- .log = _listener_log,
.ike_state_change = _ike_state_change,
.child_state_change = _child_state_change,
},
- .callback = callback,
- .param = param,
+ .logger = {
+ .public = {
+ .log = _listener_log,
+ .get_level = _listener_get_level,
+ },
+ .callback = callback,
+ .param = param,
+ },
.status = FAILED,
.id = reqid,
+ .lock = spinlock_create(),
},
.public = {
.execute = _terminate_child_execute,
.get_priority = _get_priority_medium,
- .destroy = _recheckin,
+ .destroy = _destroy_job,
},
- };
-
- ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
- reqid, TRUE);
- if (ike_sa == NULL)
- {
- DBG1(DBG_IKE, "unable to terminate, CHILD_SA with ID %d not found",
- reqid);
- return NOT_FOUND;
- }
- job.listener.ike_sa = ike_sa;
-
- enumerator = ike_sa->create_child_sa_enumerator(ike_sa);
- while (enumerator->enumerate(enumerator, (void**)&child_sa))
- {
- if (child_sa->get_state(child_sa) != CHILD_ROUTED &&
- child_sa->get_reqid(child_sa) == reqid)
- {
- break;
- }
- child_sa = NULL;
- }
- enumerator->destroy(enumerator);
-
- if (child_sa == NULL)
- {
- DBG1(DBG_IKE, "unable to terminate, established "
- "CHILD_SA with ID %d not found", reqid);
- charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
- return NOT_FOUND;
- }
- job.listener.child_sa = child_sa;
+ .refcount = 1,
+ );
+ job->listener.logger.listener = &job->listener;
if (callback == NULL)
{
- terminate_child_execute(&job);
+ terminate_child_execute(job);
}
else
{
- if (charon->bus->listen(charon->bus, &job.listener.public, &job.public,
- timeout))
+ if (wait_for_listener(job, timeout))
{
- job.listener.status = OUT_OF_RES;
+ job->listener.status = OUT_OF_RES;
}
- /* checkin of the ike_sa happened in the thread that executed the job */
- charon->bus->set_sa(charon->bus, NULL);
}
- return job.listener.status;
+ status = job->listener.status;
+ destroy_job(job);
+ return status;
}
/**
* See header
*/
bool controller_cb_empty(void *param, debug_t group, level_t level,
- ike_sa_t *ike_sa, char *format, va_list args)
+ ike_sa_t *ike_sa, const char *message)
{
return TRUE;
}
diff --git a/src/libcharon/control/controller.h b/src/libcharon/control/controller.h
index 6adaef109..222285cde 100644
--- a/src/libcharon/control/controller.h
+++ b/src/libcharon/control/controller.h
@@ -24,27 +24,26 @@
#include <bus/bus.h>
/**
- * callback to log things triggered by controller.
+ * Callback to log things triggered by controller.
*
- * @param param echoed parameter supplied when function invoked
+ * @param param parameter supplied when controller method was called
* @param group debugging group
- * @param level verbosity level if log
+ * @param level verbosity level
* @param ike_sa associated IKE_SA, if any
- * @param format printf like format string
- * @param args list of arguments to use for format
- * @return FALSE to return from invoked function
+ * @param message log message
+ * @return FALSE to return from called controller method
*/
-typedef bool(*controller_cb_t)(void* param, debug_t group, level_t level,
- ike_sa_t* ike_sa, char* format, va_list args);
+typedef bool (*controller_cb_t)(void* param, debug_t group, level_t level,
+ ike_sa_t* ike_sa, const char *message);
/**
- * Empty callback function for controller_t functions.
+ * Empty callback function for controller_t methods.
*
* If you want to do a synchronous call, but don't need a callback, pass
- * this function to the controllers methods.
+ * this function to the controller methods.
*/
bool controller_cb_empty(void *param, debug_t group, level_t level,
- ike_sa_t *ike_sa, char *format, va_list args);
+ ike_sa_t *ike_sa, const char *message);
typedef struct controller_t controller_t;
@@ -75,9 +74,8 @@ struct controller_t {
/**
* Initiate a CHILD_SA, and if required, an IKE_SA.
*
- * The initiate() function is synchronous and thus blocks until the
- * IKE_SA is established or failed. Because of this, the initiate() function
- * contains a thread cancellation point.
+ * If a callback is provided the function is synchronous and thus blocks
+ * until the IKE_SA is established or failed.
*
* @param peer_cfg peer_cfg to use for IKE_SA setup
* @param child_cfg child_cfg to set up CHILD_SA from
@@ -97,9 +95,8 @@ struct controller_t {
/**
* Terminate an IKE_SA and all of its CHILD_SAs.
*
- * The terminate() function is synchronous and thus blocks until the
- * IKE_SA is properly deleted, or the delete timed out.
- * The terminate() function contains a thread cancellation point.
+ * If a callback is provided the function is synchronous and thus blocks
+ * until the IKE_SA is properly deleted, or the call timed out.
*
* @param unique_id unique id of the IKE_SA to terminate.
* @param cb logging callback
@@ -118,6 +115,9 @@ struct controller_t {
/**
* Terminate a CHILD_SA.
*
+ * If a callback is provided the function is synchronous and thus blocks
+ * until the CHILD_SA is properly deleted, or the call timed out.
+ *
* @param reqid reqid of the CHILD_SA to terminate
* @param cb logging callback
* @param param parameter to include in each call of cb
@@ -138,12 +138,11 @@ struct controller_t {
void (*destroy) (controller_t *this);
};
-
/**
* Creates a controller instance.
*
* @return controller_t object
*/
-controller_t *controller_create(void);
+controller_t *controller_create();
#endif /** CONTROLLER_H_ @}*/
diff --git a/src/libcharon/daemon.c b/src/libcharon/daemon.c
index 3fb49d475..6e977efc4 100644
--- a/src/libcharon/daemon.c
+++ b/src/libcharon/daemon.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2010 Tobias Brunner
+ * Copyright (C) 2006-2012 Tobias Brunner
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005 Jan Hutter
@@ -21,22 +21,18 @@
#include <unistd.h>
#include <time.h>
-#ifdef CAPABILITIES
-# ifdef HAVE_SYS_CAPABILITY_H
-# include <sys/capability.h>
-# elif defined(CAPABILITIES_NATIVE)
-# include <linux/capability.h>
-# endif /* CAPABILITIES_NATIVE */
-#endif /* CAPABILITIES */
-
#include "daemon.h"
#include <library.h>
-#include <plugins/plugin.h>
+#include <plugins/plugin_feature.h>
#include <config/proposal.h>
#include <kernel/kernel_handler.h>
#include <processing/jobs/start_action_job.h>
+#ifndef CAP_NET_ADMIN
+#define CAP_NET_ADMIN 12
+#endif
+
typedef struct private_daemon_t private_daemon_t;
/**
@@ -52,17 +48,6 @@ struct private_daemon_t {
* Handler for kernel events
*/
kernel_handler_t *kernel_handler;
-
- /**
- * capabilities to keep
- */
-#ifdef CAPABILITIES_LIBCAP
- cap_t caps;
-#endif /* CAPABILITIES_LIBCAP */
-#ifdef CAPABILITIES_NATIVE
- struct __user_cap_data_struct caps[2];
-#endif /* CAPABILITIES_NATIVE */
-
};
/**
@@ -109,27 +94,31 @@ static void destroy(private_daemon_t *this)
{
this->public.traps->flush(this->public.traps);
}
- DESTROY_IF(this->public.receiver);
- DESTROY_IF(this->public.sender);
+ if (this->public.sender)
+ {
+ this->public.sender->flush(this->public.sender);
+ }
+
+ /* cancel all threads and wait for their termination */
+ lib->processor->cancel(lib->processor);
+
#ifdef ME
DESTROY_IF(this->public.connect_manager);
DESTROY_IF(this->public.mediation_manager);
#endif /* ME */
/* make sure the cache is clear before unloading plugins */
lib->credmgr->flush_cache(lib->credmgr, CERT_ANY);
- /* unload plugins to release threads */
lib->plugins->unload(lib->plugins);
-#ifdef CAPABILITIES_LIBCAP
- cap_free(this->caps);
-#endif /* CAPABILITIES_LIBCAP */
DESTROY_IF(this->kernel_handler);
DESTROY_IF(this->public.traps);
DESTROY_IF(this->public.shunts);
DESTROY_IF(this->public.ike_sa_manager);
DESTROY_IF(this->public.controller);
DESTROY_IF(this->public.eap);
+ DESTROY_IF(this->public.xauth);
DESTROY_IF(this->public.backends);
DESTROY_IF(this->public.socket);
+ DESTROY_IF(this->public.caps);
/* rehook library logging, shutdown logging */
dbg = dbg_old;
@@ -138,86 +127,63 @@ static void destroy(private_daemon_t *this)
offsetof(file_logger_t, destroy));
this->public.sys_loggers->destroy_offset(this->public.sys_loggers,
offsetof(sys_logger_t, destroy));
+ free((void*)this->public.name);
free(this);
}
-METHOD(daemon_t, keep_cap, void,
- private_daemon_t *this, u_int cap)
+METHOD(daemon_t, start, void,
+ private_daemon_t *this)
{
-#ifdef CAPABILITIES_LIBCAP
- cap_set_flag(this->caps, CAP_EFFECTIVE, 1, &cap, CAP_SET);
- cap_set_flag(this->caps, CAP_INHERITABLE, 1, &cap, CAP_SET);
- cap_set_flag(this->caps, CAP_PERMITTED, 1, &cap, CAP_SET);
-#endif /* CAPABILITIES_LIBCAP */
-#ifdef CAPABILITIES_NATIVE
- int i = 0;
-
- if (cap >= 32)
- {
- i++;
- cap -= 32;
- }
- this->caps[i].effective |= 1 << cap;
- this->caps[i].permitted |= 1 << cap;
- this->caps[i].inheritable |= 1 << cap;
-#endif /* CAPABILITIES_NATIVE */
+ /* start the engine, go multithreaded */
+ lib->processor->set_threads(lib->processor,
+ lib->settings->get_int(lib->settings, "%s.threads",
+ DEFAULT_THREADS, charon->name));
}
-METHOD(daemon_t, drop_capabilities, bool,
- private_daemon_t *this)
+
+/**
+ * Initialize/deinitialize sender and receiver
+ */
+static bool sender_receiver_cb(void *plugin, plugin_feature_t *feature,
+ bool reg, private_daemon_t *this)
{
-#ifdef CAPABILITIES_LIBCAP
- if (cap_set_proc(this->caps) != 0)
+ if (reg)
{
- return FALSE;
+ this->public.receiver = receiver_create();
+ if (!this->public.receiver)
+ {
+ return FALSE;
+ }
+ this->public.sender = sender_create();
}
-#endif /* CAPABILITIES_LIBCAP */
-#ifdef CAPABILITIES_NATIVE
- struct __user_cap_header_struct header = {
-#if defined(_LINUX_CAPABILITY_VERSION_3)
- .version = _LINUX_CAPABILITY_VERSION_3,
-#elif defined(_LINUX_CAPABILITY_VERSION_2)
- .version = _LINUX_CAPABILITY_VERSION_2,
-#elif defined(_LINUX_CAPABILITY_VERSION_1)
- .version = _LINUX_CAPABILITY_VERSION_1,
-#else
- .version = _LINUX_CAPABILITY_VERSION,
-#endif
- };
- if (capset(&header, this->caps) != 0)
+ else
{
- return FALSE;
+ DESTROY_IF(this->public.receiver);
+ DESTROY_IF(this->public.sender);
}
-#endif /* CAPABILITIES_NATIVE */
return TRUE;
}
-METHOD(daemon_t, start, void,
- private_daemon_t *this)
-{
- /* start the engine, go multithreaded */
- lib->processor->set_threads(lib->processor,
- lib->settings->get_int(lib->settings, "charon.threads",
- DEFAULT_THREADS));
-}
-
METHOD(daemon_t, initialize, bool,
- private_daemon_t *this)
+ private_daemon_t *this, char *plugins)
{
- DBG1(DBG_DMN, "Starting IKEv2 charon daemon (strongSwan "VERSION")");
-
- if (lib->integrity)
- {
- DBG1(DBG_DMN, "integrity tests enabled:");
- DBG1(DBG_DMN, "lib 'libstrongswan': passed file and segment integrity tests");
- DBG1(DBG_DMN, "lib 'libhydra': passed file and segment integrity tests");
- DBG1(DBG_DMN, "lib 'libcharon': passed file and segment integrity tests");
- DBG1(DBG_DMN, "daemon 'charon': passed file integrity test");
- }
+ plugin_feature_t features[] = {
+ PLUGIN_PROVIDE(CUSTOM, "libcharon"),
+ PLUGIN_DEPENDS(NONCE_GEN),
+ PLUGIN_DEPENDS(CUSTOM, "libcharon-receiver"),
+ PLUGIN_DEPENDS(CUSTOM, "kernel-ipsec"),
+ PLUGIN_DEPENDS(CUSTOM, "kernel-net"),
+ PLUGIN_CALLBACK((plugin_feature_callback_t)sender_receiver_cb, this),
+ PLUGIN_PROVIDE(CUSTOM, "libcharon-receiver"),
+ PLUGIN_DEPENDS(HASHER, HASH_SHA1),
+ PLUGIN_DEPENDS(RNG, RNG_STRONG),
+ PLUGIN_DEPENDS(CUSTOM, "socket"),
+ };
+ lib->plugins->add_static_features(lib->plugins, charon->name, features,
+ countof(features), TRUE);
/* load plugins, further infrastructure may need it */
- if (!lib->plugins->load(lib->plugins, NULL,
- lib->settings->get_str(lib->settings, "charon.load", PLUGINS)))
+ if (!lib->plugins->load(lib->plugins, NULL, plugins))
{
return FALSE;
}
@@ -229,12 +195,6 @@ METHOD(daemon_t, initialize, bool,
{
return FALSE;
}
- this->public.sender = sender_create();
- this->public.receiver = receiver_create();
- if (this->public.receiver == NULL)
- {
- return FALSE;
- }
/* Queue start_action job */
lib->processor->queue_job(lib->processor, (job_t*)start_action_job_create());
@@ -254,40 +214,32 @@ METHOD(daemon_t, initialize, bool,
/**
* Create the daemon.
*/
-private_daemon_t *daemon_create()
+private_daemon_t *daemon_create(const char *name)
{
private_daemon_t *this;
INIT(this,
.public = {
- .keep_cap = _keep_cap,
- .drop_capabilities = _drop_capabilities,
.initialize = _initialize,
.start = _start,
.bus = bus_create(),
.file_loggers = linked_list_create(),
.sys_loggers = linked_list_create(),
+ .name = strdup(name ?: "libcharon"),
},
);
charon = &this->public;
+ this->public.caps = capabilities_create();
this->public.controller = controller_create();
this->public.eap = eap_manager_create();
+ this->public.xauth = xauth_manager_create();
this->public.backends = backend_manager_create();
this->public.socket = socket_manager_create();
this->public.traps = trap_manager_create();
this->public.shunts = shunt_manager_create();
this->kernel_handler = kernel_handler_create();
-#ifdef CAPABILITIES
-#ifdef CAPABILITIES_LIBCAP
- this->caps = cap_init();
-#endif /* CAPABILITIES_LIBCAP */
- keep_cap(this, CAP_NET_ADMIN);
- if (lib->leak_detective)
- {
- keep_cap(this, CAP_SYS_NICE);
- }
-#endif /* CAPABILITIES */
+ this->public.caps->keep(this->public.caps, CAP_NET_ADMIN);
return this;
}
@@ -304,9 +256,9 @@ void libcharon_deinit()
/**
* Described in header.
*/
-bool libcharon_init()
+bool libcharon_init(const char *name)
{
- daemon_create();
+ daemon_create(name);
/* for uncritical pseudo random numbers */
srandom(time(NULL) + getpid());
diff --git a/src/libcharon/daemon.h b/src/libcharon/daemon.h
index 2e01c8d9b..b67de77b8 100644
--- a/src/libcharon/daemon.h
+++ b/src/libcharon/daemon.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2010 Tobias Brunner
+ * Copyright (C) 2006-2012 Tobias Brunner
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005 Jan Hutter
@@ -55,15 +55,30 @@
* @defgroup sa sa
* @ingroup libcharon
*
- * @defgroup authenticators authenticators
+ * @defgroup ikev1 ikev1
* @ingroup sa
*
+ * @defgroup ikev2 ikev2
+ * @ingroup sa
+ *
+ * @defgroup authenticators_v1 authenticators
+ * @ingroup ikev1
+ *
+ * @defgroup authenticators_v2 authenticators
+ * @ingroup ikev2
+ *
* @defgroup eap eap
- * @ingroup authenticators
+ * @ingroup sa
*
- * @defgroup tasks tasks
+ * @defgroup xauth xauth
* @ingroup sa
*
+ * @defgroup tasks_v1 tasks
+ * @ingroup ikev1
+ *
+ * @defgroup tasks_v2 tasks
+ * @ingroup ikev2
+ *
* @addtogroup libcharon
* @{
*
@@ -148,11 +163,13 @@ typedef struct daemon_t daemon_t;
#include <sa/trap_manager.h>
#include <sa/shunt_manager.h>
#include <config/backend_manager.h>
-#include <sa/authenticators/eap/eap_manager.h>
+#include <sa/eap/eap_manager.h>
+#include <sa/xauth/xauth_manager.h>
+#include <utils/capabilities.h>
#ifdef ME
-#include <sa/connect_manager.h>
-#include <sa/mediation_manager.h>
+#include <sa/ikev2/connect_manager.h>
+#include <sa/ikev2/mediation_manager.h>
#endif /* ME */
/**
@@ -161,16 +178,31 @@ typedef struct daemon_t daemon_t;
#define DEFAULT_THREADS 16
/**
- * UDP Port on which the daemon will listen for incoming traffic.
+ * Primary UDP port used by IKE.
*/
#define IKEV2_UDP_PORT 500
/**
- * UDP Port to which the daemon will float to if NAT is detected.
+ * UDP port defined for use in case a NAT is detected.
*/
#define IKEV2_NATT_PORT 4500
/**
+ * UDP port on which the daemon will listen for incoming traffic (also used as
+ * source port for outgoing traffic).
+ */
+#ifndef CHARON_UDP_PORT
+#define CHARON_UDP_PORT IKEV2_UDP_PORT
+#endif
+
+/**
+ * UDP port used by the daemon in case a NAT is detected.
+ */
+#ifndef CHARON_NATT_PORT
+#define CHARON_NATT_PORT IKEV2_NATT_PORT
+#endif
+
+/**
* Main class of daemon, contains some globals.
*/
struct daemon_t {
@@ -235,6 +267,11 @@ struct daemon_t {
*/
eap_manager_t *eap;
+ /**
+ * XAuth manager to maintain registered XAuth methods
+ */
+ xauth_manager_t *xauth;
+
#ifdef ME
/**
* Connect manager
@@ -248,39 +285,22 @@ struct daemon_t {
#endif /* ME */
/**
- * User ID the daemon will user after initialization
+ * POSIX capability dropping
*/
- uid_t uid;
+ capabilities_t *caps;
/**
- * Group ID the daemon will use after initialization
- */
- gid_t gid;
-
- /**
- * Do not drop a given capability after initialization.
- *
- * Some plugins might need additional capabilites. They tell the daemon
- * during plugin initialization which one they need, the daemon won't
- * drop these.
+ * Name of the binary that uses the library (used for settings etc.)
*/
- void (*keep_cap)(daemon_t *this, u_int cap);
-
- /**
- * Drop all capabilities of the current process.
- *
- * Drops all capabalities, excect those exlcuded using keep_cap().
- * This should be called after the initialization of the daemon because
- * some plugins require the process to keep additional capabilities.
- *
- * @return TRUE if successful, FALSE otherwise
- */
- bool (*drop_capabilities)(daemon_t *this);
+ const char *name;
/**
* Initialize the daemon.
+ *
+ * @param plugins list of plugins to load
+ * @return TRUE, if successful
*/
- bool (*initialize)(daemon_t *this);
+ bool (*initialize)(daemon_t *this, char *plugins);
/**
* Starts the daemon, i.e. spawns the threads of the thread pool.
@@ -302,9 +322,10 @@ extern daemon_t *charon;
* This function initializes the bus, listeners can be registered before
* calling initialize().
*
+ * @param name name of the binary that uses the library
* @return FALSE if integrity check failed
*/
-bool libcharon_init();
+bool libcharon_init(const char *name);
/**
* Deinitialize libcharon and destroy the "charon" instance of daemon_t.
diff --git a/src/libcharon/encoding/generator.c b/src/libcharon/encoding/generator.c
index 60fa7e0c4..2dfaf43df 100644
--- a/src/libcharon/encoding/generator.c
+++ b/src/libcharon/encoding/generator.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2011 Tobias Brunner
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -108,6 +109,11 @@ struct private_generator_t {
* to hold the length of the transform attribute in bytes.
*/
u_int16_t attribute_length;
+
+ /**
+ * TRUE, if debug messages should be logged during generation.
+ */
+ bool debug;
};
/**
@@ -155,8 +161,11 @@ static void make_space_available(private_generator_t *this, int bits)
new_buffer_size = old_buffer_size + GENERATOR_DATA_BUFFER_INCREASE_VALUE;
out_position_offset = this->out_position - this->buffer;
- DBG2(DBG_ENC, "increasing gen buffer from %d to %d byte",
- old_buffer_size, new_buffer_size);
+ if (this->debug)
+ {
+ DBG2(DBG_ENC, "increasing gen buffer from %d to %d byte",
+ old_buffer_size, new_buffer_size);
+ }
this->buffer = realloc(this->buffer,new_buffer_size);
this->out_position = (this->buffer + out_position_offset);
@@ -205,7 +214,7 @@ static void generate_u_int_type(private_generator_t *this,
break;
case U_INT_16:
case PAYLOAD_LENGTH:
- case CONFIGURATION_ATTRIBUTE_LENGTH:
+ case ATTRIBUTE_LENGTH:
number_of_bits = 16;
break;
case U_INT_32:
@@ -244,7 +253,10 @@ static void generate_u_int_type(private_generator_t *this,
low = *(this->out_position) & 0x0F;
/* high is set, low_val is not changed */
*(this->out_position) = high | low;
- DBG3(DBG_ENC, " => %d", *(this->out_position));
+ if (this->debug)
+ {
+ DBG3(DBG_ENC, " => %d", *(this->out_position));
+ }
/* write position is not changed, just bit position is moved */
this->current_bit = 4;
}
@@ -255,7 +267,10 @@ static void generate_u_int_type(private_generator_t *this,
/* low of current byte in buffer has to be set to the new value*/
low = *((u_int8_t *)(this->data_struct + offset)) & 0x0F;
*(this->out_position) = high | low;
- DBG3(DBG_ENC, " => %d", *(this->out_position));
+ if (this->debug)
+ {
+ DBG3(DBG_ENC, " => %d", *(this->out_position));
+ }
this->out_position++;
this->current_bit = 0;
}
@@ -274,7 +289,10 @@ static void generate_u_int_type(private_generator_t *this,
{
/* 8 bit values are written as they are */
*this->out_position = *((u_int8_t *)(this->data_struct + offset));
- DBG3(DBG_ENC, " => %d", *(this->out_position));
+ if (this->debug)
+ {
+ DBG3(DBG_ENC, " => %d", *(this->out_position));
+ }
this->out_position++;
break;
}
@@ -299,7 +317,10 @@ static void generate_u_int_type(private_generator_t *this,
val |= 0x8000;
}
val = htons(val);
- DBG3(DBG_ENC, " => %d", val);
+ if (this->debug)
+ {
+ DBG3(DBG_ENC, " => %d", val);
+ }
/* write bytes to buffer (set bit is overwritten) */
write_bytes_to_buffer(this, &val, sizeof(u_int16_t));
this->current_bit = 0;
@@ -308,17 +329,23 @@ static void generate_u_int_type(private_generator_t *this,
}
case U_INT_16:
case PAYLOAD_LENGTH:
- case CONFIGURATION_ATTRIBUTE_LENGTH:
+ case ATTRIBUTE_LENGTH:
{
u_int16_t val = htons(*((u_int16_t*)(this->data_struct + offset)));
- DBG3(DBG_ENC, " => %b", &val, sizeof(u_int16_t));
+ if (this->debug)
+ {
+ DBG3(DBG_ENC, " %b", &val, sizeof(u_int16_t));
+ }
write_bytes_to_buffer(this, &val, sizeof(u_int16_t));
break;
}
case U_INT_32:
{
u_int32_t val = htonl(*((u_int32_t*)(this->data_struct + offset)));
- DBG3(DBG_ENC, " => %b", &val, sizeof(u_int32_t));
+ if (this->debug)
+ {
+ DBG3(DBG_ENC, " %b", &val, sizeof(u_int32_t));
+ }
write_bytes_to_buffer(this, &val, sizeof(u_int32_t));
break;
}
@@ -327,8 +354,11 @@ static void generate_u_int_type(private_generator_t *this,
/* 64 bit are written as-is, no host order conversion */
write_bytes_to_buffer(this, this->data_struct + offset,
sizeof(u_int64_t));
- DBG3(DBG_ENC, " => %b", this->data_struct + offset,
- sizeof(u_int64_t));
+ if (this->debug)
+ {
+ DBG3(DBG_ENC, " %b", this->data_struct + offset,
+ sizeof(u_int64_t));
+ }
break;
}
default:
@@ -361,7 +391,10 @@ static void generate_flag(private_generator_t *this, u_int32_t offset)
}
*(this->out_position) = *(this->out_position) | flag;
- DBG3(DBG_ENC, " => %d", *this->out_position);
+ if (this->debug)
+ {
+ DBG3(DBG_ENC, " => %d", *this->out_position);
+ }
this->current_bit++;
if (this->current_bit >= 8)
@@ -380,12 +413,16 @@ static void generate_from_chunk(private_generator_t *this, u_int32_t offset)
if (this->current_bit != 0)
{
- DBG1(DBG_ENC, "can not generate a chunk at Bitpos %d", this->current_bit);
+ DBG1(DBG_ENC, "can not generate a chunk at bitpos %d",
+ this->current_bit);
return ;
}
value = (chunk_t *)(this->data_struct + offset);
- DBG3(DBG_ENC, " => %B", value);
+ if (this->debug)
+ {
+ DBG3(DBG_ENC, " %B", value);
+ }
write_bytes_to_buffer(this, value->ptr, value->len);
}
@@ -397,15 +434,17 @@ METHOD(generator_t, get_chunk, chunk_t,
*lenpos = (u_int32_t*)(this->buffer + this->header_length_offset);
data = chunk_create(this->buffer, get_length(this));
- DBG3(DBG_ENC, "generated data of this generator %B", &data);
+ if (this->debug)
+ {
+ DBG3(DBG_ENC, "generated data of this generator %B", &data);
+ }
return data;
}
METHOD(generator_t, generate_payload, void,
- private_generator_t *this,payload_t *payload)
+ private_generator_t *this, payload_t *payload)
{
- int i, offset_start;
- size_t rule_count;
+ int i, offset_start, rule_count;
encoding_rule_t *rules;
payload_type_t payload_type;
@@ -414,17 +453,23 @@ METHOD(generator_t, generate_payload, void,
offset_start = this->out_position - this->buffer;
- DBG2(DBG_ENC, "generating payload of type %N",
- payload_type_names, payload_type);
+ if (this->debug)
+ {
+ DBG2(DBG_ENC, "generating payload of type %N",
+ payload_type_names, payload_type);
+ }
/* each payload has its own encoding rules */
- payload->get_encoding_rules(payload, &rules, &rule_count);
+ rule_count = payload->get_encoding_rules(payload, &rules);
for (i = 0; i < rule_count;i++)
{
- DBG2(DBG_ENC, " generating rule %d %N",
- i, encoding_type_names, rules[i].type);
- switch (rules[i].type)
+ if (this->debug)
+ {
+ DBG2(DBG_ENC, " generating rule %d %N",
+ i, encoding_type_names, rules[i].type);
+ }
+ switch ((int)rules[i].type)
{
case U_INT_4:
case U_INT_8:
@@ -436,7 +481,7 @@ METHOD(generator_t, generate_payload, void,
case SPI_SIZE:
case TS_TYPE:
case ATTRIBUTE_TYPE:
- case CONFIGURATION_ATTRIBUTE_LENGTH:
+ case ATTRIBUTE_LENGTH:
generate_u_int_type(this, rules[i].type, rules[i].offset);
break;
case RESERVED_BIT:
@@ -449,26 +494,19 @@ METHOD(generator_t, generate_payload, void,
break;
case ADDRESS:
case SPI:
- case KEY_EXCHANGE_DATA:
- case NOTIFICATION_DATA:
- case NONCE_DATA:
- case ID_DATA:
- case AUTH_DATA:
- case CERT_DATA:
- case CERTREQ_DATA:
- case SPIS:
- case CONFIGURATION_ATTRIBUTE_VALUE:
- case VID_DATA:
- case EAP_DATA:
+ case CHUNK_DATA:
case ENCRYPTED_DATA:
- case UNKNOWN_DATA:
generate_from_chunk(this, rules[i].offset);
break;
- case PROPOSALS:
- case TRANSFORMS:
- case TRANSFORM_ATTRIBUTES:
- case CONFIGURATION_ATTRIBUTES:
- case TRAFFIC_SELECTORS:
+ case PAYLOAD_LIST + PROPOSAL_SUBSTRUCTURE:
+ case PAYLOAD_LIST + PROPOSAL_SUBSTRUCTURE_V1:
+ case PAYLOAD_LIST + TRANSFORM_SUBSTRUCTURE:
+ case PAYLOAD_LIST + TRANSFORM_SUBSTRUCTURE_V1:
+ case PAYLOAD_LIST + TRANSFORM_ATTRIBUTE:
+ case PAYLOAD_LIST + TRANSFORM_ATTRIBUTE_V1:
+ case PAYLOAD_LIST + CONFIGURATION_ATTRIBUTE:
+ case PAYLOAD_LIST + CONFIGURATION_ATTRIBUTE_V1:
+ case PAYLOAD_LIST + TRAFFIC_SELECTOR_SUBSTRUCTURE:
{
linked_list_t *proposals;
enumerator_t *enumerator;
@@ -507,7 +545,10 @@ METHOD(generator_t, generate_payload, void,
{
if (!this->attribute_format)
{
- DBG2(DBG_ENC, "attribute value has not fixed size");
+ if (this->debug)
+ {
+ DBG2(DBG_ENC, "attribute value has not fixed size");
+ }
/* the attribute value is generated */
generate_from_chunk(this, rules[i].offset);
}
@@ -519,11 +560,14 @@ METHOD(generator_t, generate_payload, void,
return;
}
}
- DBG2(DBG_ENC, "generating %N payload finished",
- payload_type_names, payload_type);
- DBG3(DBG_ENC, "generated data for this payload %b",
- this->buffer + offset_start,
- (u_int)(this->out_position - this->buffer - offset_start));
+ if (this->debug)
+ {
+ DBG2(DBG_ENC, "generating %N payload finished",
+ payload_type_names, payload_type);
+ DBG3(DBG_ENC, "generated data for this payload %b",
+ this->buffer + offset_start,
+ (u_int)(this->out_position - this->buffer - offset_start));
+ }
}
METHOD(generator_t, destroy, void,
@@ -547,6 +591,7 @@ generator_t *generator_create()
.destroy = _destroy,
},
.buffer = malloc(GENERATOR_DATA_BUFFER_SIZE),
+ .debug = TRUE,
);
this->out_position = this->buffer;
@@ -555,3 +600,14 @@ generator_t *generator_create()
return &this->public;
}
+/*
+ * Described in header
+ */
+generator_t *generator_create_no_dbg()
+{
+ private_generator_t *this = (private_generator_t*)generator_create();
+
+ this->debug = FALSE;
+
+ return &this->public;
+}
diff --git a/src/libcharon/encoding/generator.h b/src/libcharon/encoding/generator.h
index fe561fdfd..c2c0aad2a 100644
--- a/src/libcharon/encoding/generator.h
+++ b/src/libcharon/encoding/generator.h
@@ -72,4 +72,12 @@ struct generator_t {
*/
generator_t *generator_create(void);
+/**
+ * Constructor to create a generator that does not log any debug messages > 1.
+ *
+ * @return generator_t object.
+ */
+generator_t *generator_create_no_dbg(void);
+
+
#endif /** GENERATOR_H_ @}*/
diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c
index 2b5399294..d3b72ea95 100644
--- a/src/libcharon/encoding/message.c
+++ b/src/libcharon/encoding/message.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2007 Tobias Brunner
+ * Copyright (C) 2006-2011 Tobias Brunner
* Copyright (C) 2005-2010 Martin Willi
* Copyright (C) 2010 revosec AG
* Copyright (C) 2006 Daniel Roethlisberger
@@ -24,37 +24,47 @@
#include <library.h>
#include <daemon.h>
-#include <sa/ike_sa_id.h>
+#include <sa/ikev1/keymat_v1.h>
#include <encoding/generator.h>
#include <encoding/parser.h>
-#include <utils/linked_list.h>
#include <encoding/payloads/encodings.h>
#include <encoding/payloads/payload.h>
+#include <encoding/payloads/hash_payload.h>
#include <encoding/payloads/encryption_payload.h>
#include <encoding/payloads/unknown_payload.h>
#include <encoding/payloads/cp_payload.h>
/**
- * Max number of notify payloads per IKEv2 Message
+ * Max number of notify payloads per IKEv2 message
*/
#define MAX_NOTIFY_PAYLOADS 20
/**
- * Max number of delete payloads per IKEv2 Message
+ * Max number of delete payloads per IKEv2 message
*/
#define MAX_DELETE_PAYLOADS 20
/**
- * Max number of certificate payloads per IKEv2 Message
+ * Max number of certificate payloads per IKEv2 message
*/
#define MAX_CERT_PAYLOADS 8
/**
- * Max number of Vendor ID payloads per IKEv2 Message
+ * Max number of vendor ID payloads per IKEv2 message
*/
#define MAX_VID_PAYLOADS 20
/**
+ * Max number of certificate request payloads per IKEv1 message
+ */
+#define MAX_CERTREQ_PAYLOADS 5
+
+/**
+ * Max number of NAT-D payloads per IKEv1 message
+ */
+#define MAX_NAT_D_PAYLOADS 5
+
+/**
* A payload rule defines the rules for a payload
* in a specific message rule. It defines if and how
* many times a payload must/can occur in a message
@@ -414,6 +424,273 @@ static payload_order_t me_connect_r_order[] = {
};
#endif /* ME */
+#ifdef USE_IKEV1
+/**
+ * Message rule for ID_PROT from initiator.
+ */
+static payload_rule_t id_prot_i_rules[] = {
+/* payload type min max encr suff */
+ {NOTIFY_V1, 0, MAX_NOTIFY_PAYLOADS, FALSE, FALSE},
+ {SECURITY_ASSOCIATION_V1, 0, 1, FALSE, FALSE},
+ {KEY_EXCHANGE_V1, 0, 1, FALSE, FALSE},
+ {NONCE_V1, 0, 1, FALSE, FALSE},
+ {VENDOR_ID_V1, 0, MAX_VID_PAYLOADS, FALSE, FALSE},
+ {CERTIFICATE_REQUEST_V1, 0, MAX_CERTREQ_PAYLOADS, FALSE, FALSE},
+ {NAT_D_V1, 0, MAX_NAT_D_PAYLOADS, FALSE, FALSE},
+ {ID_V1, 0, 1, TRUE, FALSE},
+ {CERTIFICATE_V1, 0, 2, TRUE, FALSE},
+ {SIGNATURE_V1, 0, 1, TRUE, FALSE},
+ {HASH_V1, 0, 1, TRUE, FALSE},
+};
+
+/**
+ * payload order for ID_PROT from initiator.
+ */
+static payload_order_t id_prot_i_order[] = {
+/* payload type notify type */
+ {SECURITY_ASSOCIATION_V1, 0},
+ {KEY_EXCHANGE_V1, 0},
+ {NONCE_V1, 0},
+ {ID_V1, 0},
+ {CERTIFICATE_V1, 0},
+ {SIGNATURE_V1, 0},
+ {HASH_V1, 0},
+ {CERTIFICATE_REQUEST_V1, 0},
+ {NOTIFY_V1, 0},
+ {VENDOR_ID_V1, 0},
+ {NAT_D_V1, 0},
+};
+
+/**
+ * Message rule for ID_PROT from responder.
+ */
+static payload_rule_t id_prot_r_rules[] = {
+/* payload type min max encr suff */
+ {NOTIFY_V1, 0, MAX_NOTIFY_PAYLOADS, FALSE, FALSE},
+ {SECURITY_ASSOCIATION_V1, 0, 1, FALSE, FALSE},
+ {KEY_EXCHANGE_V1, 0, 1, FALSE, FALSE},
+ {NONCE_V1, 0, 1, FALSE, FALSE},
+ {VENDOR_ID_V1, 0, MAX_VID_PAYLOADS, FALSE, FALSE},
+ {CERTIFICATE_REQUEST_V1, 0, MAX_CERTREQ_PAYLOADS, FALSE, FALSE},
+ {NAT_D_V1, 0, MAX_NAT_D_PAYLOADS, FALSE, FALSE},
+ {ID_V1, 0, 1, TRUE, FALSE},
+ {CERTIFICATE_V1, 0, 2, TRUE, FALSE},
+ {SIGNATURE_V1, 0, 1, TRUE, FALSE},
+ {HASH_V1, 0, 1, TRUE, FALSE},
+};
+
+/**
+ * payload order for ID_PROT from responder.
+ */
+static payload_order_t id_prot_r_order[] = {
+/* payload type notify type */
+ {SECURITY_ASSOCIATION_V1, 0},
+ {KEY_EXCHANGE_V1, 0},
+ {NONCE_V1, 0},
+ {ID_V1, 0},
+ {CERTIFICATE_V1, 0},
+ {SIGNATURE_V1, 0},
+ {HASH_V1, 0},
+ {CERTIFICATE_REQUEST_V1, 0},
+ {NOTIFY_V1, 0},
+ {VENDOR_ID_V1, 0},
+ {NAT_D_V1, 0},
+};
+
+/**
+ * Message rule for AGGRESSIVE from initiator.
+ */
+static payload_rule_t aggressive_i_rules[] = {
+/* payload type min max encr suff */
+ {NOTIFY_V1, 0, MAX_NOTIFY_PAYLOADS, FALSE, FALSE},
+ {SECURITY_ASSOCIATION_V1, 0, 1, FALSE, FALSE},
+ {KEY_EXCHANGE_V1, 0, 1, FALSE, FALSE},
+ {NONCE_V1, 0, 1, FALSE, FALSE},
+ {VENDOR_ID_V1, 0, MAX_VID_PAYLOADS, FALSE, FALSE},
+ {CERTIFICATE_REQUEST_V1, 0, MAX_CERTREQ_PAYLOADS, FALSE, FALSE},
+ {NAT_D_V1, 0, MAX_NAT_D_PAYLOADS, FALSE, FALSE},
+ {ID_V1, 0, 1, FALSE, FALSE},
+ {CERTIFICATE_V1, 0, 1, TRUE, FALSE},
+ {SIGNATURE_V1, 0, 1, TRUE, FALSE},
+ {HASH_V1, 0, 1, TRUE, FALSE},
+};
+
+/**
+ * payload order for AGGRESSIVE from initiator.
+ */
+static payload_order_t aggressive_i_order[] = {
+/* payload type notify type */
+ {SECURITY_ASSOCIATION_V1, 0},
+ {KEY_EXCHANGE_V1, 0},
+ {NONCE_V1, 0},
+ {ID_V1, 0},
+ {CERTIFICATE_V1, 0},
+ {NAT_D_V1, 0},
+ {SIGNATURE_V1, 0},
+ {HASH_V1, 0},
+ {CERTIFICATE_REQUEST_V1, 0},
+ {NOTIFY_V1, 0},
+ {VENDOR_ID_V1, 0},
+};
+
+/**
+ * Message rule for AGGRESSIVE from responder.
+ */
+static payload_rule_t aggressive_r_rules[] = {
+/* payload type min max encr suff */
+ {NOTIFY_V1, 0, MAX_NOTIFY_PAYLOADS, FALSE, FALSE},
+ {SECURITY_ASSOCIATION_V1, 0, 1, FALSE, FALSE},
+ {KEY_EXCHANGE_V1, 0, 1, FALSE, FALSE},
+ {NONCE_V1, 0, 1, FALSE, FALSE},
+ {VENDOR_ID_V1, 0, MAX_VID_PAYLOADS, FALSE, FALSE},
+ {CERTIFICATE_REQUEST_V1, 0, MAX_CERTREQ_PAYLOADS, FALSE, FALSE},
+ {NAT_D_V1, 0, MAX_NAT_D_PAYLOADS, FALSE, FALSE},
+ {ID_V1, 0, 1, FALSE, FALSE},
+ {CERTIFICATE_V1, 0, 1, FALSE, FALSE},
+ {SIGNATURE_V1, 0, 1, FALSE, FALSE},
+ {HASH_V1, 0, 1, FALSE, FALSE},
+};
+
+/**
+ * payload order for AGGRESSIVE from responder.
+ */
+static payload_order_t aggressive_r_order[] = {
+/* payload type notify type */
+ {SECURITY_ASSOCIATION_V1, 0},
+ {KEY_EXCHANGE_V1, 0},
+ {NONCE_V1, 0},
+ {ID_V1, 0},
+ {CERTIFICATE_V1, 0},
+ {NAT_D_V1, 0},
+ {SIGNATURE_V1, 0},
+ {HASH_V1, 0},
+ {CERTIFICATE_REQUEST_V1, 0},
+ {NOTIFY_V1, 0},
+ {VENDOR_ID_V1, 0},
+};
+
+/**
+ * Message rule for INFORMATIONAL_V1 from initiator.
+ */
+static payload_rule_t informational_i_rules_v1[] = {
+/* payload type min max encr suff */
+ {NOTIFY_V1, 0, MAX_NOTIFY_PAYLOADS, FALSE, FALSE},
+ {NOTIFY_V1, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE},
+ {DELETE_V1, 0, MAX_DELETE_PAYLOADS, TRUE, FALSE},
+ {VENDOR_ID_V1, 0, MAX_VID_PAYLOADS, TRUE, FALSE},
+};
+
+/**
+ * payload order for INFORMATIONAL_V1 from initiator.
+ */
+static payload_order_t informational_i_order_v1[] = {
+/* payload type notify type */
+ {NOTIFY_V1, 0},
+ {DELETE_V1, 0},
+ {VENDOR_ID_V1, 0},
+};
+
+/**
+ * Message rule for INFORMATIONAL_V1 from responder.
+ */
+static payload_rule_t informational_r_rules_v1[] = {
+/* payload type min max encr suff */
+ {NOTIFY_V1, 0, MAX_NOTIFY_PAYLOADS, FALSE, FALSE},
+ {NOTIFY_V1, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE},
+ {DELETE_V1, 0, MAX_DELETE_PAYLOADS, TRUE, FALSE},
+ {VENDOR_ID_V1, 0, MAX_VID_PAYLOADS, TRUE, FALSE},
+};
+
+/**
+ * payload order for INFORMATIONAL_V1 from responder.
+ */
+static payload_order_t informational_r_order_v1[] = {
+/* payload type notify type */
+ {NOTIFY_V1, 0},
+ {DELETE_V1, 0},
+ {VENDOR_ID_V1, 0},
+};
+
+/**
+ * Message rule for QUICK_MODE from initiator.
+ */
+static payload_rule_t quick_mode_i_rules[] = {
+/* payload type min max encr suff */
+ {NOTIFY_V1, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE},
+ {VENDOR_ID_V1, 0, MAX_VID_PAYLOADS, TRUE, FALSE},
+ {HASH_V1, 0, 1, TRUE, FALSE},
+ {SECURITY_ASSOCIATION_V1, 0, 2, TRUE, FALSE},
+ {NONCE_V1, 0, 1, TRUE, FALSE},
+ {KEY_EXCHANGE_V1, 0, 1, TRUE, FALSE},
+ {ID_V1, 0, 2, TRUE, FALSE},
+ {NAT_OA_V1, 0, 2, TRUE, FALSE},
+};
+
+/**
+ * payload order for QUICK_MODE from initiator.
+ */
+static payload_order_t quick_mode_i_order[] = {
+/* payload type notify type */
+ {NOTIFY_V1, 0},
+ {VENDOR_ID_V1, 0},
+ {HASH_V1, 0},
+ {SECURITY_ASSOCIATION_V1, 0},
+ {NONCE_V1, 0},
+ {KEY_EXCHANGE_V1, 0},
+ {ID_V1, 0},
+ {NAT_OA_V1, 0},
+};
+
+/**
+ * Message rule for QUICK_MODE from responder.
+ */
+static payload_rule_t quick_mode_r_rules[] = {
+/* payload type min max encr suff */
+ {NOTIFY_V1, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE},
+ {VENDOR_ID_V1, 0, MAX_VID_PAYLOADS, TRUE, FALSE},
+ {HASH_V1, 0, 1, TRUE, FALSE},
+ {SECURITY_ASSOCIATION_V1, 0, 2, TRUE, FALSE},
+ {NONCE_V1, 0, 1, TRUE, FALSE},
+ {KEY_EXCHANGE_V1, 0, 1, TRUE, FALSE},
+ {ID_V1, 0, 2, TRUE, FALSE},
+ {NAT_OA_V1, 0, 2, TRUE, FALSE},
+};
+
+/**
+ * payload order for QUICK_MODE from responder.
+ */
+static payload_order_t quick_mode_r_order[] = {
+/* payload type notify type */
+ {NOTIFY_V1, 0},
+ {VENDOR_ID_V1, 0},
+ {HASH_V1, 0},
+ {SECURITY_ASSOCIATION_V1, 0},
+ {NONCE_V1, 0},
+ {KEY_EXCHANGE_V1, 0},
+ {ID_V1, 0},
+ {NAT_OA_V1, 0},
+};
+
+/**
+ * Message rule for TRANSACTION.
+ */
+static payload_rule_t transaction_payload_rules_v1[] = {
+/* payload type min max encr suff */
+ {HASH_V1, 0, 1, TRUE, FALSE},
+ {CONFIGURATION_V1, 1, 1, FALSE, FALSE},
+};
+
+/**
+ * Payload order for TRANSACTION.
+ */
+static payload_order_t transaction_payload_order_v1[] = {
+/* payload type notify type */
+ {HASH_V1, 0},
+ {CONFIGURATION_V1, 0},
+};
+
+#endif /* USE_IKEV1 */
+
/**
* Message rules, defines allowed payloads.
*/
@@ -460,6 +737,49 @@ static message_rule_t message_rules[] = {
countof(me_connect_r_order), me_connect_r_order,
},
#endif /* ME */
+#ifdef USE_IKEV1
+ {ID_PROT, TRUE, FALSE,
+ countof(id_prot_i_rules), id_prot_i_rules,
+ countof(id_prot_i_order), id_prot_i_order,
+ },
+ {ID_PROT, FALSE, FALSE,
+ countof(id_prot_r_rules), id_prot_r_rules,
+ countof(id_prot_r_order), id_prot_r_order,
+ },
+ {AGGRESSIVE, TRUE, FALSE,
+ countof(aggressive_i_rules), aggressive_i_rules,
+ countof(aggressive_i_order), aggressive_i_order,
+ },
+ {AGGRESSIVE, FALSE, FALSE,
+ countof(aggressive_r_rules), aggressive_r_rules,
+ countof(aggressive_r_order), aggressive_r_order,
+ },
+ {INFORMATIONAL_V1, TRUE, TRUE,
+ countof(informational_i_rules_v1), informational_i_rules_v1,
+ countof(informational_i_order_v1), informational_i_order_v1,
+ },
+ {INFORMATIONAL_V1, FALSE, TRUE,
+ countof(informational_r_rules_v1), informational_r_rules_v1,
+ countof(informational_r_order_v1), informational_r_order_v1,
+ },
+ {QUICK_MODE, TRUE, TRUE,
+ countof(quick_mode_i_rules), quick_mode_i_rules,
+ countof(quick_mode_i_order), quick_mode_i_order,
+ },
+ {QUICK_MODE, FALSE, TRUE,
+ countof(quick_mode_r_rules), quick_mode_r_rules,
+ countof(quick_mode_r_order), quick_mode_r_order,
+ },
+ {TRANSACTION, TRUE, TRUE,
+ countof(transaction_payload_rules_v1), transaction_payload_rules_v1,
+ countof(transaction_payload_order_v1), transaction_payload_order_v1,
+ },
+ {TRANSACTION, FALSE, TRUE,
+ countof(transaction_payload_rules_v1), transaction_payload_rules_v1,
+ countof(transaction_payload_order_v1), transaction_payload_order_v1,
+ },
+ /* TODO-IKEv1: define rules for other exchanges */
+#endif /* USE_IKEV1 */
};
@@ -501,6 +821,11 @@ struct private_message_t {
bool is_request;
/**
+ * The message is encrypted (IKEv1)
+ */
+ bool is_encrypted;
+
+ /**
* Higher version supported?
*/
bool version_flag;
@@ -508,7 +833,7 @@ struct private_message_t {
/**
* Reserved bits in IKE header
*/
- bool reserved[5];
+ bool reserved[2];
/**
* Sorting of message disabled?
@@ -739,7 +1064,14 @@ METHOD(message_t, add_notify, void,
payload->destroy(payload);
}
}
- notify = notify_payload_create();
+ if (this->major_version == IKEV2_MAJOR_VERSION)
+ {
+ notify = notify_payload_create(NOTIFY);
+ }
+ else
+ {
+ notify = notify_payload_create(NOTIFY_V1);
+ }
notify->set_notify_type(notify, type);
notify->set_notification_data(notify, data);
add_payload(this, (payload_t*)notify);
@@ -810,7 +1142,8 @@ METHOD(message_t, get_notify, notify_payload_t*,
enumerator = create_payload_enumerator(this);
while (enumerator->enumerate(enumerator, &payload))
{
- if (payload->get_type(payload) == NOTIFY)
+ if (payload->get_type(payload) == NOTIFY ||
+ payload->get_type(payload) == NOTIFY_V1)
{
notify = (notify_payload_t*)payload;
if (notify->get_notify_type(notify) == type)
@@ -837,7 +1170,7 @@ static char* get_string(private_message_t *this, char *buf, int len)
memset(buf, 0, len);
len--;
- written = snprintf(pos, len, "%N %s %d [",
+ written = snprintf(pos, len, "%N %s %u [",
exchange_type_names, this->exchange_type,
this->is_request ? "request" : "response",
this->message_id);
@@ -859,7 +1192,8 @@ static char* get_string(private_message_t *this, char *buf, int len)
}
pos += written;
len -= written;
- if (payload->get_type(payload) == NOTIFY)
+ if (payload->get_type(payload) == NOTIFY ||
+ payload->get_type(payload) == NOTIFY_V1)
{
notify_payload_t *notify;
notify_type_t type;
@@ -1017,7 +1351,7 @@ static void order_payloads(private_message_t *this)
}
/**
- * Wrap payloads in a encryption payload
+ * Wrap payloads in an encryption payload
*/
static encryption_payload_t* wrap_payloads(private_message_t *this)
{
@@ -1033,7 +1367,14 @@ static encryption_payload_t* wrap_payloads(private_message_t *this)
payloads->insert_last(payloads, current);
}
- encryption = encryption_payload_create();
+ if (this->is_encrypted)
+ {
+ encryption = encryption_payload_create(ENCRYPTED_V1);
+ }
+ else
+ {
+ encryption = encryption_payload_create(ENCRYPTED);
+ }
while (payloads->remove_first(payloads, (void**)&current) == SUCCESS)
{
payload_rule_t *rule;
@@ -1046,8 +1387,8 @@ static encryption_payload_t* wrap_payloads(private_message_t *this)
{
encrypt = rule->encrypted;
}
- if (encrypt)
- {
+ if (encrypt || this->is_encrypted)
+ { /* encryption is forced for IKEv1 */
DBG2(DBG_ENC, "insert payload %N to encryption payload",
payload_type_names, type);
encryption->add_payload(encryption, current);
@@ -1071,17 +1412,20 @@ METHOD(message_t, disable_sort, void,
}
METHOD(message_t, generate, status_t,
- private_message_t *this, aead_t *aead, packet_t **packet)
+ private_message_t *this, keymat_t *keymat, packet_t **packet)
{
+ keymat_v1_t *keymat_v1 = (keymat_v1_t*)keymat;
generator_t *generator;
ike_header_t *ike_header;
payload_t *payload, *next;
encryption_payload_t *encryption = NULL;
+ payload_type_t next_type;
enumerator_t *enumerator;
- chunk_t chunk;
+ aead_t *aead = NULL;
+ chunk_t chunk, hash = chunk_empty;
char str[BUF_LEN];
u_int32_t *lenpos;
- bool *reserved;
+ bool encrypted = FALSE, *reserved;
int i;
if (this->exchange_type == EXCHANGE_TYPE_UNDEFINED)
@@ -1108,27 +1452,77 @@ METHOD(message_t, generate, status_t,
{
order_payloads(this);
}
+ if (keymat && keymat->get_version(keymat) == IKEV1)
+ {
+ /* get a hash for this message, if any is required */
+ if (keymat_v1->get_hash_phase2(keymat_v1, &this->public, &hash))
+ { /* insert a HASH payload as first payload */
+ hash_payload_t *hash_payload;
+
+ hash_payload = hash_payload_create(HASH_V1);
+ hash_payload->set_hash(hash_payload, hash);
+ this->payloads->insert_first(this->payloads, hash_payload);
+ if (this->exchange_type == INFORMATIONAL_V1)
+ {
+ this->is_encrypted = encrypted = TRUE;
+ }
+ chunk_free(&hash);
+ }
+ }
+ if (this->major_version == IKEV2_MAJOR_VERSION)
+ {
+ encrypted = this->rule->encrypted;
+ }
+ else if (!encrypted)
+ {
+ /* If at least one payload requires encryption, encrypt the message.
+ * If no key material is available, the flag will be reset below. */
+ enumerator = this->payloads->create_enumerator(this->payloads);
+ while (enumerator->enumerate(enumerator, (void**)&payload))
+ {
+ payload_rule_t *rule;
+
+ rule = get_payload_rule(this, payload->get_type(payload));
+ if (rule && rule->encrypted)
+ {
+ this->is_encrypted = encrypted = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
DBG1(DBG_ENC, "generating %s", get_string(this, str, sizeof(str)));
- if (aead && this->rule->encrypted)
+ if (keymat)
+ {
+ aead = keymat->get_aead(keymat, FALSE);
+ }
+ if (aead && encrypted)
{
encryption = wrap_payloads(this);
}
else
{
DBG2(DBG_ENC, "not encrypting payloads");
+ this->is_encrypted = FALSE;
}
- ike_header = ike_header_create();
- ike_header->set_maj_version(ike_header, this->major_version);
- ike_header->set_min_version(ike_header, this->minor_version);
+ ike_header = ike_header_create_version(this->major_version,
+ this->minor_version);
ike_header->set_exchange_type(ike_header, this->exchange_type);
ike_header->set_message_id(ike_header, this->message_id);
- ike_header->set_response_flag(ike_header, !this->is_request);
- ike_header->set_version_flag(ike_header, this->version_flag);
- ike_header->set_initiator_flag(ike_header,
+ if (this->major_version == IKEV2_MAJOR_VERSION)
+ {
+ ike_header->set_response_flag(ike_header, !this->is_request);
+ ike_header->set_version_flag(ike_header, this->version_flag);
+ ike_header->set_initiator_flag(ike_header,
this->ike_sa_id->is_initiator(this->ike_sa_id));
+ }
+ else
+ {
+ ike_header->set_encryption_flag(ike_header, this->is_encrypted);
+ }
ike_header->set_initiator_spi(ike_header,
this->ike_sa_id->get_initiator_spi(this->ike_sa_id));
ike_header->set_responder_spi(ike_header,
@@ -1156,22 +1550,38 @@ METHOD(message_t, generate, status_t,
payload = next;
}
enumerator->destroy(enumerator);
- payload->set_next_type(payload, encryption ? ENCRYPTED : NO_PAYLOAD);
+ if (this->is_encrypted)
+ { /* for encrypted IKEv1 messages */
+ next_type = encryption->payload_interface.get_next_type(
+ (payload_t*)encryption);
+ }
+ else
+ {
+ next_type = encryption ? ENCRYPTED : NO_PAYLOAD;
+ }
+ payload->set_next_type(payload, next_type);
generator->generate_payload(generator, payload);
ike_header->destroy(ike_header);
if (encryption)
- {
- u_int32_t *lenpos;
-
- /* build associated data (without header of encryption payload) */
- chunk = generator->get_chunk(generator, &lenpos);
+ { /* set_transform() has to be called before get_length() */
encryption->set_transform(encryption, aead);
- /* fill in length, including encryption payload */
- htoun32(lenpos, chunk.len + encryption->get_length(encryption));
-
+ if (this->is_encrypted)
+ { /* for IKEv1 instead of associated data we provide the IV */
+ if (!keymat_v1->get_iv(keymat_v1, this->message_id, &chunk))
+ {
+ generator->destroy(generator);
+ return FAILED;
+ }
+ }
+ else
+ { /* build associated data (without header of encryption payload) */
+ chunk = generator->get_chunk(generator, &lenpos);
+ /* fill in length, including encryption payload */
+ htoun32(lenpos, chunk.len + encryption->get_length(encryption));
+ }
this->payloads->insert_last(this->payloads, encryption);
- if (!encryption->encrypt(encryption, chunk))
+ if (encryption->encrypt(encryption, chunk) != SUCCESS)
{
generator->destroy(generator);
return INVALID_STATE;
@@ -1181,8 +1591,22 @@ METHOD(message_t, generate, status_t,
chunk = generator->get_chunk(generator, &lenpos);
htoun32(lenpos, chunk.len);
this->packet->set_data(this->packet, chunk_clone(chunk));
+ if (this->is_encrypted)
+ {
+ /* update the IV for the next IKEv1 message */
+ chunk_t last_block;
+ size_t bs;
+
+ bs = aead->get_block_size(aead);
+ last_block = chunk_create(chunk.ptr + chunk.len - bs, bs);
+ if (!keymat_v1->update_iv(keymat_v1, this->message_id, last_block) ||
+ !keymat_v1->confirm_iv(keymat_v1, this->message_id))
+ {
+ generator->destroy(generator);
+ return FAILED;
+ }
+ }
generator->destroy(generator);
-
*packet = this->packet->clone(this->packet);
return SUCCESS;
}
@@ -1204,7 +1628,7 @@ METHOD(message_t, get_packet_data, chunk_t,
{
return chunk_empty;
}
- return chunk_clone(this->packet->get_data(this->packet));
+ return this->packet->get_data(this->packet);
}
METHOD(message_t, parse_header, status_t,
@@ -1237,15 +1661,24 @@ METHOD(message_t, parse_header, status_t,
}
DESTROY_IF(this->ike_sa_id);
- this->ike_sa_id = ike_sa_id_create(ike_header->get_initiator_spi(ike_header),
+ this->ike_sa_id = ike_sa_id_create(
+ ike_header->get_maj_version(ike_header),
+ ike_header->get_initiator_spi(ike_header),
ike_header->get_responder_spi(ike_header),
ike_header->get_initiator_flag(ike_header));
this->exchange_type = ike_header->get_exchange_type(ike_header);
this->message_id = ike_header->get_message_id(ike_header);
- this->is_request = !ike_header->get_response_flag(ike_header);
this->major_version = ike_header->get_maj_version(ike_header);
this->minor_version = ike_header->get_min_version(ike_header);
+ if (this->major_version == IKEV2_MAJOR_VERSION)
+ {
+ this->is_request = !ike_header->get_response_flag(ike_header);
+ }
+ else
+ {
+ this->is_encrypted = ike_header->get_encryption_flag(ike_header);
+ }
this->first_payload = ike_header->payload_interface.get_next_type(
&ike_header->payload_interface);
for (i = 0; i < countof(this->reserved); i++)
@@ -1257,19 +1690,12 @@ METHOD(message_t, parse_header, status_t,
this->reserved[i] = *reserved;
}
}
- DBG2(DBG_ENC, "parsed a %N %s", exchange_type_names, this->exchange_type,
- this->is_request ? "request" : "response");
-
ike_header->destroy(ike_header);
- this->rule = get_message_rule(this);
- if (!this->rule)
- {
- DBG1(DBG_ENC, "no message rules specified for a %N %s",
- exchange_type_names, this->exchange_type,
- this->is_request ? "request" : "response");
- }
- return status;
+ DBG2(DBG_ENC, "parsed a %N %s header", exchange_type_names,
+ this->exchange_type, this->major_version == IKEV1_MAJOR_VERSION ?
+ "message" : (this->is_request ? "request" : "response"));
+ return SUCCESS;
}
/**
@@ -1298,15 +1724,83 @@ static bool is_connectivity_check(private_message_t *this, payload_t *payload)
}
/**
+ * Parses and verifies the unencrypted payloads contained in the message
+ */
+static status_t parse_payloads(private_message_t *this)
+{
+ payload_type_t type = this->first_payload;
+ payload_t *payload;
+ status_t status;
+
+ if (this->is_encrypted)
+ { /* wrap the whole encrypted IKEv1 message in a special encryption
+ * payload which is then handled just like a regular payload */
+ encryption_payload_t *encryption;
+
+ status = this->parser->parse_payload(this->parser, ENCRYPTED_V1,
+ (payload_t**)&encryption);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_ENC, "failed to wrap encrypted IKEv1 message");
+ return PARSE_ERROR;
+ }
+ encryption->payload_interface.set_next_type((payload_t*)encryption,
+ this->first_payload);
+ this->payloads->insert_last(this->payloads, encryption);
+ return SUCCESS;
+ }
+
+ while (type != NO_PAYLOAD)
+ {
+ DBG2(DBG_ENC, "starting parsing a %N payload",
+ payload_type_names, type);
+
+ status = this->parser->parse_payload(this->parser, type, &payload);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_ENC, "payload type %N could not be parsed",
+ payload_type_names, type);
+ return PARSE_ERROR;
+ }
+
+ DBG2(DBG_ENC, "verifying payload of type %N", payload_type_names, type);
+ status = payload->verify(payload);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_ENC, "%N payload verification failed",
+ payload_type_names, type);
+ payload->destroy(payload);
+ return VERIFY_ERROR;
+ }
+
+ DBG2(DBG_ENC, "%N payload verified. Adding to payload list",
+ payload_type_names, type);
+ this->payloads->insert_last(this->payloads, payload);
+
+ /* an encryption payload is the last one, so STOP here. decryption is
+ * done later */
+ if (type == ENCRYPTED)
+ {
+ DBG2(DBG_ENC, "%N payload found. Stop parsing",
+ payload_type_names, type);
+ break;
+ }
+ type = payload->get_next_type(payload);
+ }
+ return SUCCESS;
+}
+
+/**
* Decrypt payload from the encryption payload
*/
-static status_t decrypt_payloads(private_message_t *this, aead_t *aead)
+static status_t decrypt_payloads(private_message_t *this, keymat_t *keymat)
{
bool was_encrypted = FALSE;
payload_t *payload, *previous = NULL;
enumerator_t *enumerator;
payload_rule_t *rule;
payload_type_t type;
+ aead_t *aead;
status_t status = SUCCESS;
enumerator = this->payloads->create_enumerator(this->payloads);
@@ -1316,11 +1810,12 @@ static status_t decrypt_payloads(private_message_t *this, aead_t *aead)
DBG2(DBG_ENC, "process payload of type %N", payload_type_names, type);
- if (type == ENCRYPTED)
+ if (type == ENCRYPTED || type == ENCRYPTED_V1)
{
encryption_payload_t *encryption;
payload_t *encrypted;
chunk_t chunk;
+ size_t bs;
encryption = (encryption_payload_t*)payload;
@@ -1332,16 +1827,57 @@ static status_t decrypt_payloads(private_message_t *this, aead_t *aead)
status = VERIFY_ERROR;
break;
}
+ if (!keymat)
+ {
+ DBG1(DBG_ENC, "found encryption payload, but no keymat");
+ status = INVALID_ARG;
+ break;
+ }
+ aead = keymat->get_aead(keymat, TRUE);
+ if (!aead)
+ {
+ DBG1(DBG_ENC, "found encryption payload, but no transform set");
+ status = INVALID_ARG;
+ break;
+ }
+ bs = aead->get_block_size(aead);
encryption->set_transform(encryption, aead);
chunk = this->packet->get_data(this->packet);
- if (chunk.len < encryption->get_length(encryption))
+ if (chunk.len < encryption->get_length(encryption) ||
+ chunk.len < bs)
{
DBG1(DBG_ENC, "invalid payload length");
status = VERIFY_ERROR;
break;
}
- chunk.len -= encryption->get_length(encryption);
- status = encryption->decrypt(encryption, chunk);
+ if (keymat->get_version(keymat) == IKEV1)
+ { /* instead of associated data we provide the IV, we also update
+ * the IV with the last encrypted block */
+ keymat_v1_t *keymat_v1 = (keymat_v1_t*)keymat;
+ chunk_t iv;
+
+ if (keymat_v1->get_iv(keymat_v1, this->message_id, &iv))
+ {
+ status = encryption->decrypt(encryption, iv);
+ if (status == SUCCESS)
+ {
+ if (!keymat_v1->update_iv(keymat_v1, this->message_id,
+ chunk_create(chunk.ptr + chunk.len - bs, bs)))
+ {
+ status = FAILED;
+ }
+ }
+ }
+ else
+ {
+ status = FAILED;
+ }
+ }
+ else
+ {
+ chunk.len -= encryption->get_length(encryption);
+ status = encryption->decrypt(encryption, chunk);
+ }
if (status != SUCCESS)
{
break;
@@ -1369,7 +1905,8 @@ static status_t decrypt_payloads(private_message_t *this, aead_t *aead)
encryption->destroy(encryption);
}
if (payload_is_known(type) && !was_encrypted &&
- !is_connectivity_check(this, payload))
+ !is_connectivity_check(this, payload) &&
+ this->exchange_type != AGGRESSIVE)
{
rule = get_payload_rule(this, type);
if (!rule || rule->encrypted)
@@ -1396,7 +1933,7 @@ static status_t verify(private_message_t *this)
DBG2(DBG_ENC, "verifying message structure");
- /* check for payloads with wrong count*/
+ /* check for payloads with wrong count */
for (i = 0; i < this->rule->rule_count; i++)
{
enumerator_t *enumerator;
@@ -1443,57 +1980,30 @@ static status_t verify(private_message_t *this)
}
METHOD(message_t, parse_body, status_t,
- private_message_t *this, aead_t *aead)
+ private_message_t *this, keymat_t *keymat)
{
status_t status = SUCCESS;
- payload_t *payload;
- payload_type_t type;
char str[BUF_LEN];
- type = this->first_payload;
-
DBG2(DBG_ENC, "parsing body of message, first payload is %N",
- payload_type_names, type);
+ payload_type_names, this->first_payload);
- while (type != NO_PAYLOAD)
+ this->rule = get_message_rule(this);
+ if (!this->rule)
{
- DBG2(DBG_ENC, "starting parsing a %N payload",
- payload_type_names, type);
-
- status = this->parser->parse_payload(this->parser, type, &payload);
- if (status != SUCCESS)
- {
- DBG1(DBG_ENC, "payload type %N could not be parsed",
- payload_type_names, type);
- return this->exchange_type == IKE_SA_INIT ? PARSE_ERROR : FAILED;
- }
-
- DBG2(DBG_ENC, "verifying payload of type %N", payload_type_names, type);
- status = payload->verify(payload);
- if (status != SUCCESS)
- {
- DBG1(DBG_ENC, "%N payload verification failed",
- payload_type_names, type);
- payload->destroy(payload);
- return this->exchange_type == IKE_SA_INIT ? VERIFY_ERROR : FAILED;
- }
-
- DBG2(DBG_ENC, "%N payload verified. Adding to payload list",
- payload_type_names, type);
- this->payloads->insert_last(this->payloads, payload);
+ DBG1(DBG_ENC, "no message rules specified for a %N %s",
+ exchange_type_names, this->exchange_type,
+ this->is_request ? "request" : "response");
+ return NOT_SUPPORTED;
+ }
- /* an encryption payload is the last one, so STOP here. decryption is
- * done later */
- if (type == ENCRYPTED)
- {
- DBG2(DBG_ENC, "%N payload found. Stop parsing",
- payload_type_names, type);
- break;
- }
- type = payload->get_next_type(payload);
+ status = parse_payloads(this);
+ if (status != SUCCESS)
+ { /* error is already logged */
+ return status;
}
- status = decrypt_payloads(this, aead);
+ status = decrypt_payloads(this, keymat);
if (status != SUCCESS)
{
DBG1(DBG_ENC, "could not decrypt payloads");
@@ -1508,6 +2018,50 @@ METHOD(message_t, parse_body, status_t,
DBG1(DBG_ENC, "parsed %s", get_string(this, str, sizeof(str)));
+ if (keymat && keymat->get_version(keymat) == IKEV1)
+ {
+ keymat_v1_t *keymat_v1 = (keymat_v1_t*)keymat;
+ chunk_t hash;
+
+ if (keymat_v1->get_hash_phase2(keymat_v1, &this->public, &hash))
+ {
+ hash_payload_t *hash_payload;
+ chunk_t other_hash;
+
+ if (this->first_payload != HASH_V1)
+ {
+ if (this->exchange_type == INFORMATIONAL_V1)
+ {
+ DBG1(DBG_ENC, "ignoring unprotected INFORMATIONAL from %H",
+ this->packet->get_source(this->packet));
+ }
+ else
+ {
+ DBG1(DBG_ENC, "expected HASH payload as first payload");
+ }
+ chunk_free(&hash);
+ return VERIFY_ERROR;
+ }
+ hash_payload = (hash_payload_t*)get_payload(this, HASH_V1);
+ other_hash = hash_payload->get_hash(hash_payload);
+ DBG3(DBG_ENC, "HASH received %B\nHASH expected %B",
+ &other_hash, &hash);
+ if (!chunk_equals(hash, other_hash))
+ {
+ DBG1(DBG_ENC, "received HASH payload does not match");
+ chunk_free(&hash);
+ return FAILED;
+ }
+ chunk_free(&hash);
+ }
+ if (this->is_encrypted)
+ { /* message verified, confirm IV */
+ if (!keymat_v1->confirm_iv(keymat_v1, this->message_id))
+ {
+ return FAILED;
+ }
+ }
+ }
return SUCCESS;
}
@@ -1522,7 +2076,7 @@ METHOD(message_t, destroy, void,
}
/*
- * Described in Header-File
+ * Described in header.
*/
message_t *message_create_from_packet(packet_t *packet)
{
@@ -1567,8 +2121,6 @@ message_t *message_create_from_packet(packet_t *packet)
.get_packet_data = _get_packet_data,
.destroy = _destroy,
},
- .major_version = IKE_MAJOR_VERSION,
- .minor_version = IKE_MINOR_VERSION,
.exchange_type = EXCHANGE_TYPE_UNDEFINED,
.is_request = TRUE,
.first_payload = NO_PAYLOAD,
@@ -1577,14 +2129,18 @@ message_t *message_create_from_packet(packet_t *packet)
.parser = parser_create(packet->get_data(packet)),
);
- return (&this->public);
+ return &this->public;
}
/*
- * Described in Header.
+ * Described in header.
*/
-message_t *message_create()
+message_t *message_create(int major, int minor)
{
- return message_create_from_packet(packet_create());
-}
+ message_t *this = message_create_from_packet(packet_create());
+ this->set_major_version(this, major);
+ this->set_minor_version(this, minor);
+
+ return this;
+}
diff --git a/src/libcharon/encoding/message.h b/src/libcharon/encoding/message.h
index 0e78ea436..6d558daf6 100644
--- a/src/libcharon/encoding/message.h
+++ b/src/libcharon/encoding/message.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2007 Tobias Brunner
+ * Copyright (C) 2006-2011 Tobias Brunner
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005 Jan Hutter
@@ -27,15 +27,15 @@
typedef struct message_t message_t;
#include <library.h>
-#include <sa/ike_sa_id.h>
-#include <network/packet.h>
#include <encoding/payloads/ike_header.h>
#include <encoding/payloads/notify_payload.h>
+#include <sa/keymat.h>
+#include <sa/ike_sa_id.h>
+#include <utils/packet.h>
#include <utils/linked_list.h>
-#include <crypto/aead.h>
/**
- * This class is used to represent an IKEv2-Message.
+ * This class is used to represent an IKE-Message.
*
* The message handles parsing and generation of payloads
* via parser_t/generator_t. Encryption is done transparently
@@ -182,7 +182,7 @@ struct message_t {
* all payloads to encrypt are added to the encryption payload, which is
* always the last one.
*
- * @param payload payload to append
+ * @param payload payload to append
*/
void (*add_payload) (message_t *this, payload_t *payload);
@@ -208,14 +208,14 @@ struct message_t {
/**
* Parses header of message.
*
- * Begins parisng of a message created via message_create_from_packet().
+ * Begins parsing of a message created via message_create_from_packet().
* The parsing context is stored, so a subsequent call to parse_body()
* will continue the parsing process.
*
* @return
- * - SUCCESS if header could be parsed
+ * - SUCCESS if header could be parsed
* - PARSE_ERROR if corrupted/invalid data found
- * - FAILED if consistence check of header failed
+ * - FAILED if consistency check of header failed
*/
status_t (*parse_header) (message_t *this);
@@ -228,15 +228,15 @@ struct message_t {
* If there are encrypted payloads, they get decrypted and verified using
* the given aead transform (if given).
*
- * @param aead aead transform to verify/decrypt message
+ * @param keymat keymat to verify/decrypt message
* @return
- * - SUCCESS if parsing successful
+ * - SUCCESS if parsing successful
* - PARSE_ERROR if message parsing failed
- * - VERIFY_ERROR if message verification failed (bad syntax)
- * - FAILED if integrity check failed
- * - INVALID_STATE if aead not supplied, but needed
+ * - VERIFY_ERROR if message verification failed (bad syntax)
+ * - FAILED if integrity check failed
+ * - INVALID_STATE if aead not supplied, but needed
*/
- status_t (*parse_body) (message_t *this, aead_t *aead);
+ status_t (*parse_body) (message_t *this, keymat_t *keymat);
/**
* Generates the UDP packet of specific message.
@@ -247,15 +247,15 @@ struct message_t {
* Generation is only done once, multiple calls will just return a copy
* of the packet.
*
- * @param aead aead transform to encrypt/sign message
+ * @param keymat keymat to encrypt/sign message
* @param packet copy of generated packet
* @return
- * - SUCCESS if packet could be generated
- * - INVALID_STATE if exchange type is currently not set
- * - NOT_FOUND if no rules found for message generation
- * - INVALID_STATE if aead not supplied but needed.
+ * - SUCCESS if packet could be generated
+ * - INVALID_STATE if exchange type is currently not set
+ * - NOT_FOUND if no rules found for message generation
+ * - INVALID_STATE if aead not supplied but needed.
*/
- status_t (*generate) (message_t *this, aead_t *aead, packet_t **packet);
+ status_t (*generate) (message_t *this, keymat_t *keymat, packet_t **packet);
/**
* Check if the message has already been encoded using generate().
@@ -278,7 +278,7 @@ struct message_t {
* Sets the source host informations.
*
* @warning host_t object is not getting cloned and gets destroyed by
- * message_t.destroy or next call of message_t.set_source.
+ * message_t.destroy or next call of message_t.set_source.
*
* @param host host_t object representing source host
*/
@@ -298,7 +298,7 @@ struct message_t {
* Sets the destination host informations.
*
* @warning host_t object is not getting cloned and gets destroyed by
- * message_t.destroy or next call of message_t.set_destination.
+ * message_t.destroy or next call of message_t.set_destination.
*
* @param host host_t object representing destination host
*/
@@ -344,9 +344,9 @@ struct message_t {
packet_t * (*get_packet) (message_t *this);
/**
- * Returns a clone of the internal stored packet_t data.
+ * Returns a chunk pointing to internal packet_t data.
*
- * @return clone of the internal stored packet_t data.
+ * @return packet data.
*/
chunk_t (*get_packet_data) (message_t *this);
@@ -357,26 +357,27 @@ struct message_t {
};
/**
- * Creates an message_t object from a incoming UDP Packet.
+ * Creates a message_t object from an incoming UDP packet.
*
* The given packet gets owned by the message. The message is uninitialized,
* call parse_header() to populate header fields.
*
* @param packet packet_t object which is assigned to message
- * @return message_t object
+ * @return message_t object
*/
-message_t * message_create_from_packet(packet_t *packet);
-
+message_t *message_create_from_packet(packet_t *packet);
/**
- * Creates an empty message_t object.
+ * Creates an empty message_t object for a specific major/minor version.
*
* - exchange_type is set to NOT_SET
* - original_initiator is set to TRUE
* - is_request is set to TRUE
*
- * @return message_t object
+ * @param major major IKE version of this message
+ * @param minor minor IKE version of this message
+ * @return message_t object
*/
-message_t * message_create(void);
+message_t *message_create(int major, int minor);
#endif /** MESSAGE_H_ @}*/
diff --git a/src/libcharon/encoding/parser.c b/src/libcharon/encoding/parser.c
index e49210309..e4b140c3e 100644
--- a/src/libcharon/encoding/parser.c
+++ b/src/libcharon/encoding/parser.c
@@ -137,7 +137,7 @@ static bool parse_uint4(private_parser_t *this, int rule_number,
}
if (output_pos)
{
- DBG3(DBG_ENC, " => %d", *output_pos);
+ DBG3(DBG_ENC, " => %hhu", *output_pos);
}
return TRUE;
}
@@ -159,7 +159,7 @@ static bool parse_uint8(private_parser_t *this, int rule_number,
if (output_pos)
{
*output_pos = *(this->byte_pos);
- DBG3(DBG_ENC, " => %d", *output_pos);
+ DBG3(DBG_ENC, " => %hhu", *output_pos);
}
this->byte_pos++;
return TRUE;
@@ -183,7 +183,7 @@ static bool parse_uint15(private_parser_t *this, int rule_number,
{
memcpy(output_pos, this->byte_pos, sizeof(u_int16_t));
*output_pos = ntohs(*output_pos) & ~0x8000;
- DBG3(DBG_ENC, " => %d", *output_pos);
+ DBG3(DBG_ENC, " => %hu", *output_pos);
}
this->byte_pos += sizeof(u_int16_t);
this->bit_pos = 0;
@@ -208,7 +208,7 @@ static bool parse_uint16(private_parser_t *this, int rule_number,
{
memcpy(output_pos, this->byte_pos, sizeof(u_int16_t));
*output_pos = ntohs(*output_pos);
- DBG3(DBG_ENC, " => %d", *output_pos);
+ DBG3(DBG_ENC, " => %hu", *output_pos);
}
this->byte_pos += sizeof(u_int16_t);
return TRUE;
@@ -231,7 +231,7 @@ static bool parse_uint32(private_parser_t *this, int rule_number,
{
memcpy(output_pos, this->byte_pos, sizeof(u_int32_t));
*output_pos = ntohl(*output_pos);
- DBG3(DBG_ENC, " => %d", *output_pos);
+ DBG3(DBG_ENC, " => %u", *output_pos);
}
this->byte_pos += sizeof(u_int32_t);
return TRUE;
@@ -254,7 +254,7 @@ static bool parse_bytes(private_parser_t *this, int rule_number,
if (output_pos)
{
memcpy(output_pos, this->byte_pos, bytes);
- DBG3(DBG_ENC, " => %b", output_pos, bytes);
+ DBG3(DBG_ENC, " %b", output_pos, bytes);
}
this->byte_pos += bytes;
return TRUE;
@@ -352,7 +352,7 @@ static bool parse_chunk(private_parser_t *this, int rule_number,
{
*output_pos = chunk_alloc(length);
memcpy(output_pos->ptr, this->byte_pos, length);
- DBG3(DBG_ENC, " => %b", output_pos->ptr, length);
+ DBG3(DBG_ENC, " %b", output_pos->ptr, length);
}
this->byte_pos += length;
return TRUE;
@@ -363,11 +363,10 @@ METHOD(parser_t, parse_payload, status_t,
{
payload_t *pld;
void *output;
- size_t rule_count;
- int payload_length = 0, spi_size = 0, attribute_length = 0;
+ int payload_length = 0, spi_size = 0, attribute_length = 0, header_length;
u_int16_t ts_type = 0;
bool attribute_format = FALSE;
- int rule_number;
+ int rule_number, rule_count;
encoding_rule_t *rule;
/* create instance of the payload to parse */
@@ -381,15 +380,17 @@ METHOD(parser_t, parse_payload, status_t,
/* base pointer for output, avoids casting in every rule */
output = pld;
-
/* parse the payload with its own rulse */
- pld->get_encoding_rules(pld, &this->rules, &rule_count);
+ rule_count = pld->get_encoding_rules(pld, &this->rules);
for (rule_number = 0; rule_number < rule_count; rule_number++)
{
+ /* update header length for each rule, as it is dynamic (SPIs) */
+ header_length = pld->get_header_length(pld);
+
rule = &(this->rules[rule_number]);
DBG2(DBG_ENC, " parsing rule %d %N",
rule_number, encoding_type_names, rule->type);
- switch (rule->type)
+ switch ((int)rule->type)
{
case U_INT_4:
{
@@ -457,7 +458,8 @@ METHOD(parser_t, parse_payload, status_t,
}
/* parsed u_int16 should be aligned */
payload_length = *(u_int16_t*)(output + rule->offset);
- if (payload_length < UNKNOWN_PAYLOAD_HEADER_LENGTH)
+ /* all payloads must have at least 4 bytes header */
+ if (payload_length < 4)
{
pld->destroy(pld);
return PARSE_ERROR;
@@ -484,49 +486,41 @@ METHOD(parser_t, parse_payload, status_t,
}
break;
}
- case PROPOSALS:
+ case PAYLOAD_LIST + PROPOSAL_SUBSTRUCTURE:
+ case PAYLOAD_LIST + PROPOSAL_SUBSTRUCTURE_V1:
+ case PAYLOAD_LIST + TRANSFORM_SUBSTRUCTURE:
+ case PAYLOAD_LIST + TRANSFORM_SUBSTRUCTURE_V1:
+ case PAYLOAD_LIST + TRANSFORM_ATTRIBUTE:
+ case PAYLOAD_LIST + TRANSFORM_ATTRIBUTE_V1:
+ case PAYLOAD_LIST + CONFIGURATION_ATTRIBUTE:
+ case PAYLOAD_LIST + CONFIGURATION_ATTRIBUTE_V1:
+ case PAYLOAD_LIST + TRAFFIC_SELECTOR_SUBSTRUCTURE:
{
- if (payload_length < SA_PAYLOAD_HEADER_LENGTH ||
+ if (payload_length < header_length ||
!parse_list(this, rule_number, output + rule->offset,
- PROPOSAL_SUBSTRUCTURE,
- payload_length - SA_PAYLOAD_HEADER_LENGTH))
+ rule->type - PAYLOAD_LIST,
+ payload_length - header_length))
{
pld->destroy(pld);
return PARSE_ERROR;
}
break;
}
- case TRANSFORMS:
+ case CHUNK_DATA:
{
- if (payload_length <
- spi_size + PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH ||
- !parse_list(this, rule_number, output + rule->offset,
- TRANSFORM_SUBSTRUCTURE, payload_length - spi_size -
- PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH))
- {
- pld->destroy(pld);
- return PARSE_ERROR;
- }
- break;
- }
- case TRANSFORM_ATTRIBUTES:
- {
- if (payload_length < TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH ||
- !parse_list(this, rule_number, output + rule->offset,
- TRANSFORM_ATTRIBUTE,
- payload_length - TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH))
+ if (payload_length < header_length ||
+ !parse_chunk(this, rule_number, output + rule->offset,
+ payload_length - header_length))
{
pld->destroy(pld);
return PARSE_ERROR;
}
break;
}
- case CONFIGURATION_ATTRIBUTES:
+ case ENCRYPTED_DATA:
{
- if (payload_length < CP_PAYLOAD_HEADER_LENGTH ||
- !parse_list(this, rule_number, output + rule->offset,
- CONFIGURATION_ATTRIBUTE,
- payload_length - CP_PAYLOAD_HEADER_LENGTH))
+ if (!parse_chunk(this, rule_number, output + rule->offset,
+ this->input_roof - this->byte_pos))
{
pld->destroy(pld);
return PARSE_ERROR;
@@ -552,7 +546,7 @@ METHOD(parser_t, parse_payload, status_t,
}
break;
}
- case CONFIGURATION_ATTRIBUTE_LENGTH:
+ case ATTRIBUTE_LENGTH:
{
if (!parse_uint16(this, rule_number, output + rule->offset))
{
@@ -583,137 +577,6 @@ METHOD(parser_t, parse_payload, status_t,
}
break;
}
- case NONCE_DATA:
- {
- if (payload_length < NONCE_PAYLOAD_HEADER_LENGTH ||
- !parse_chunk(this, rule_number, output + rule->offset,
- payload_length - NONCE_PAYLOAD_HEADER_LENGTH))
- {
- pld->destroy(pld);
- return PARSE_ERROR;
- }
- break;
- }
- case ID_DATA:
- {
- if (payload_length < ID_PAYLOAD_HEADER_LENGTH ||
- !parse_chunk(this, rule_number, output + rule->offset,
- payload_length - ID_PAYLOAD_HEADER_LENGTH))
- {
- pld->destroy(pld);
- return PARSE_ERROR;
- }
- break;
- }
- case AUTH_DATA:
- {
- if (payload_length < AUTH_PAYLOAD_HEADER_LENGTH ||
- !parse_chunk(this, rule_number, output + rule->offset,
- payload_length - AUTH_PAYLOAD_HEADER_LENGTH))
- {
- pld->destroy(pld);
- return PARSE_ERROR;
- }
- break;
- }
- case CERT_DATA:
- {
- if (payload_length < CERT_PAYLOAD_HEADER_LENGTH ||
- !parse_chunk(this, rule_number, output + rule->offset,
- payload_length - CERT_PAYLOAD_HEADER_LENGTH))
- {
- pld->destroy(pld);
- return PARSE_ERROR;
- }
- break;
- }
- case CERTREQ_DATA:
- {
- if (payload_length < CERTREQ_PAYLOAD_HEADER_LENGTH ||
- !parse_chunk(this, rule_number, output + rule->offset,
- payload_length - CERTREQ_PAYLOAD_HEADER_LENGTH))
- {
- pld->destroy(pld);
- return PARSE_ERROR;
- }
- break;
- }
- case EAP_DATA:
- {
- if (payload_length < EAP_PAYLOAD_HEADER_LENGTH ||
- !parse_chunk(this, rule_number, output + rule->offset,
- payload_length - EAP_PAYLOAD_HEADER_LENGTH))
- {
- pld->destroy(pld);
- return PARSE_ERROR;
- }
- break;
- }
- case SPIS:
- {
- if (payload_length < DELETE_PAYLOAD_HEADER_LENGTH ||
- !parse_chunk(this, rule_number, output + rule->offset,
- payload_length - DELETE_PAYLOAD_HEADER_LENGTH))
- {
- pld->destroy(pld);
- return PARSE_ERROR;
- }
- break;
- }
- case VID_DATA:
- {
- if (payload_length < VENDOR_ID_PAYLOAD_HEADER_LENGTH ||
- !parse_chunk(this, rule_number, output + rule->offset,
- payload_length - VENDOR_ID_PAYLOAD_HEADER_LENGTH))
- {
- pld->destroy(pld);
- return PARSE_ERROR;
- }
- break;
- }
- case CONFIGURATION_ATTRIBUTE_VALUE:
- {
- if (!parse_chunk(this, rule_number, output + rule->offset,
- attribute_length))
- {
- pld->destroy(pld);
- return PARSE_ERROR;
- }
- break;
- }
- case KEY_EXCHANGE_DATA:
- {
- if (payload_length < KE_PAYLOAD_HEADER_LENGTH ||
- !parse_chunk(this, rule_number, output + rule->offset,
- payload_length - KE_PAYLOAD_HEADER_LENGTH))
- {
- pld->destroy(pld);
- return PARSE_ERROR;
- }
- break;
- }
- case NOTIFICATION_DATA:
- {
- if (payload_length < NOTIFY_PAYLOAD_HEADER_LENGTH + spi_size ||
- !parse_chunk(this, rule_number, output + rule->offset,
- payload_length - NOTIFY_PAYLOAD_HEADER_LENGTH - spi_size))
- {
- pld->destroy(pld);
- return PARSE_ERROR;
- }
- break;
- }
- case ENCRYPTED_DATA:
- {
- if (payload_length < ENCRYPTION_PAYLOAD_HEADER_LENGTH ||
- !parse_chunk(this, rule_number, output + rule->offset,
- payload_length - ENCRYPTION_PAYLOAD_HEADER_LENGTH))
- {
- pld->destroy(pld);
- return PARSE_ERROR;
- }
- break;
- }
case TS_TYPE:
{
if (!parse_uint8(this, rule_number, output + rule->offset))
@@ -736,29 +599,6 @@ METHOD(parser_t, parse_payload, status_t,
}
break;
}
- case TRAFFIC_SELECTORS:
- {
- if (payload_length < TS_PAYLOAD_HEADER_LENGTH ||
- !parse_list(this, rule_number, output + rule->offset,
- TRAFFIC_SELECTOR_SUBSTRUCTURE,
- payload_length - TS_PAYLOAD_HEADER_LENGTH))
- {
- pld->destroy(pld);
- return PARSE_ERROR;
- }
- break;
- }
- case UNKNOWN_DATA:
- {
- if (payload_length < UNKNOWN_PAYLOAD_HEADER_LENGTH ||
- !parse_chunk(this, rule_number, output + rule->offset,
- payload_length - UNKNOWN_PAYLOAD_HEADER_LENGTH))
- {
- pld->destroy(pld);
- return PARSE_ERROR;
- }
- break;
- }
default:
{
DBG1(DBG_ENC, " no rule to parse rule %d %N",
diff --git a/src/libcharon/encoding/payloads/auth_payload.c b/src/libcharon/encoding/payloads/auth_payload.c
index cb44a997c..2410a1aaa 100644
--- a/src/libcharon/encoding/payloads/auth_payload.c
+++ b/src/libcharon/encoding/payloads/auth_payload.c
@@ -74,7 +74,7 @@ struct private_auth_payload_t {
* The defined offsets are the positions in a object of type
* private_auth_payload_t.
*/
-encoding_rule_t auth_payload_encodings[] = {
+static encoding_rule_t encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_auth_payload_t, next_payload) },
/* the critical bit */
@@ -96,7 +96,7 @@ encoding_rule_t auth_payload_encodings[] = {
{ RESERVED_BYTE, offsetof(private_auth_payload_t, reserved_byte[1]) },
{ RESERVED_BYTE, offsetof(private_auth_payload_t, reserved_byte[2]) },
/* some auth data bytes, length is defined in PAYLOAD_LENGTH */
- { AUTH_DATA, offsetof(private_auth_payload_t, auth_data) }
+ { CHUNK_DATA, offsetof(private_auth_payload_t, auth_data) }
};
/*
@@ -119,11 +119,17 @@ METHOD(payload_t, verify, status_t,
return SUCCESS;
}
-METHOD(payload_t, get_encoding_rules, void,
- private_auth_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, int,
+ private_auth_payload_t *this, encoding_rule_t **rules)
{
- *rules = auth_payload_encodings;
- *rule_count = countof(auth_payload_encodings);
+ *rules = encodings;
+ return countof(encodings);
+}
+
+METHOD(payload_t, get_header_length, int,
+ private_auth_payload_t *this)
+{
+ return 8;
}
METHOD(payload_t, get_type, payload_type_t,
@@ -167,7 +173,7 @@ METHOD(auth_payload_t, set_data, void,
{
free(this->auth_data.ptr);
this->auth_data = chunk_clone(data);
- this->payload_length = AUTH_PAYLOAD_HEADER_LENGTH + this->auth_data.len;
+ this->payload_length = get_header_length(this) + this->auth_data.len;
}
METHOD(auth_payload_t, get_data, chunk_t,
@@ -195,6 +201,7 @@ auth_payload_t *auth_payload_create()
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
+ .get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@@ -208,7 +215,7 @@ auth_payload_t *auth_payload_create()
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
- .payload_length = AUTH_PAYLOAD_HEADER_LENGTH,
+ .payload_length = get_header_length(this),
);
return &this->public;
}
diff --git a/src/libcharon/encoding/payloads/auth_payload.h b/src/libcharon/encoding/payloads/auth_payload.h
index e4c4e6ae3..b922d12c8 100644
--- a/src/libcharon/encoding/payloads/auth_payload.h
+++ b/src/libcharon/encoding/payloads/auth_payload.h
@@ -26,12 +26,7 @@ typedef struct auth_payload_t auth_payload_t;
#include <library.h>
#include <encoding/payloads/payload.h>
-#include <sa/authenticators/authenticator.h>
-
-/**
- * Length of a auth payload without the auth data in bytes.
- */
-#define AUTH_PAYLOAD_HEADER_LENGTH 8
+#include <sa/authenticator.h>
/**
* Class representing an IKEv2 AUTH payload.
diff --git a/src/libcharon/encoding/payloads/cert_payload.c b/src/libcharon/encoding/payloads/cert_payload.c
index c42cec680..3a230b91e 100644
--- a/src/libcharon/encoding/payloads/cert_payload.c
+++ b/src/libcharon/encoding/payloads/cert_payload.c
@@ -86,6 +86,11 @@ struct private_cert_payload_t {
* TRUE if the "Hash and URL" data is invalid
*/
bool invalid_hash_and_url;
+
+ /**
+ * The payload type.
+ */
+ payload_type_t type;
};
/**
@@ -95,7 +100,7 @@ struct private_cert_payload_t {
* private_cert_payload_t.
*
*/
-encoding_rule_t cert_payload_encodings[] = {
+static encoding_rule_t encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_cert_payload_t, next_payload) },
/* the critical bit */
@@ -113,7 +118,7 @@ encoding_rule_t cert_payload_encodings[] = {
/* 1 Byte CERT type*/
{ U_INT_8, offsetof(private_cert_payload_t, encoding) },
/* some cert data bytes, length is defined in PAYLOAD_LENGTH */
- { CERT_DATA, offsetof(private_cert_payload_t, data) }
+ { CHUNK_DATA, offsetof(private_cert_payload_t, data) }
};
/*
@@ -166,17 +171,23 @@ METHOD(payload_t, verify, status_t,
return SUCCESS;
}
-METHOD(payload_t, get_encoding_rules, void,
- private_cert_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, int,
+ private_cert_payload_t *this, encoding_rule_t **rules)
+{
+ *rules = encodings;
+ return countof(encodings);
+}
+
+METHOD(payload_t, get_header_length, int,
+ private_cert_payload_t *this)
{
- *rules = cert_payload_encodings;
- *rule_count = countof(cert_payload_encodings);
+ return 5;
}
METHOD(payload_t, get_type, payload_type_t,
private_cert_payload_t *this)
{
- return CERTIFICATE;
+ return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
@@ -261,7 +272,7 @@ METHOD2(payload_t, cert_payload_t, destroy, void,
/*
* Described in header
*/
-cert_payload_t *cert_payload_create()
+cert_payload_t *cert_payload_create(payload_type_t type)
{
private_cert_payload_t *this;
@@ -270,6 +281,7 @@ cert_payload_t *cert_payload_create()
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
+ .get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@@ -283,7 +295,8 @@ cert_payload_t *cert_payload_create()
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
- .payload_length = CERT_PAYLOAD_HEADER_LENGTH,
+ .payload_length = get_header_length(this),
+ .type = type,
);
return &this->public;
}
@@ -291,10 +304,12 @@ cert_payload_t *cert_payload_create()
/*
* Described in header
*/
-cert_payload_t *cert_payload_create_from_cert(certificate_t *cert)
+cert_payload_t *cert_payload_create_from_cert(payload_type_t type,
+ certificate_t *cert)
{
- private_cert_payload_t *this = (private_cert_payload_t*)cert_payload_create();
+ private_cert_payload_t *this;
+ this = (private_cert_payload_t*)cert_payload_create(type);
switch (cert->get_type(cert))
{
case CERT_X509:
@@ -312,7 +327,8 @@ cert_payload_t *cert_payload_create_from_cert(certificate_t *cert)
free(this);
return NULL;
}
- this->payload_length = CERT_PAYLOAD_HEADER_LENGTH + this->data.len;
+ this->payload_length = get_header_length(this) + this->data.len;
+
return &this->public;
}
@@ -321,23 +337,29 @@ cert_payload_t *cert_payload_create_from_cert(certificate_t *cert)
*/
cert_payload_t *cert_payload_create_from_hash_and_url(chunk_t hash, char *url)
{
- private_cert_payload_t *this = (private_cert_payload_t*)cert_payload_create();
+ private_cert_payload_t *this;
+ this = (private_cert_payload_t*)cert_payload_create(CERTIFICATE);
this->encoding = ENC_X509_HASH_AND_URL;
this->data = chunk_cat("cc", hash, chunk_create(url, strlen(url)));
- this->payload_length = CERT_PAYLOAD_HEADER_LENGTH + this->data.len;
+ this->payload_length = get_header_length(this) + this->data.len;
+
return &this->public;
}
/*
* Described in header
*/
-cert_payload_t *cert_payload_create_custom(cert_encoding_t type, chunk_t data)
+cert_payload_t *cert_payload_create_custom(payload_type_t type,
+ cert_encoding_t encoding, chunk_t data)
{
- private_cert_payload_t *this = (private_cert_payload_t*)cert_payload_create();
+ private_cert_payload_t *this;
- this->encoding = type;
+ this = (private_cert_payload_t*)cert_payload_create(type);
+ this->encoding = encoding;
this->data = data;
- this->payload_length = CERT_PAYLOAD_HEADER_LENGTH + this->data.len;
+ this->payload_length = get_header_length(this) + this->data.len;
+
return &this->public;
}
+
diff --git a/src/libcharon/encoding/payloads/cert_payload.h b/src/libcharon/encoding/payloads/cert_payload.h
index 21b503a40..19ed2ccd2 100644
--- a/src/libcharon/encoding/payloads/cert_payload.h
+++ b/src/libcharon/encoding/payloads/cert_payload.h
@@ -31,11 +31,6 @@ typedef enum cert_encoding_t cert_encoding_t;
#include <encoding/payloads/payload.h>
/**
- * Length of a cert payload without the cert data in bytes.
- */
-#define CERT_PAYLOAD_HEADER_LENGTH 5
-
-/**
* Certifcate encodings, as in RFC4306
*/
enum cert_encoding_t {
@@ -60,9 +55,7 @@ enum cert_encoding_t {
extern enum_name_t *cert_encoding_names;
/**
- * Class representing an IKEv2 CERT payload.
- *
- * The CERT payload format is described in RFC section 3.6.
+ * Class representing an IKEv1/IKEv2 CERT payload.
*/
struct cert_payload_t {
@@ -103,7 +96,6 @@ struct cert_payload_t {
*/
char *(*get_url)(cert_payload_t *this);
-
/**
* Destroys the cert_payload object.
*/
@@ -113,23 +105,26 @@ struct cert_payload_t {
/**
* Creates an empty certificate payload.
*
+ * @param type payload type (for IKEv1 or IKEv2)
* @return cert_payload_t object
*/
-cert_payload_t *cert_payload_create(void);
+cert_payload_t *cert_payload_create(payload_type_t type);
/**
* Creates a certificate payload with an embedded certificate.
*
+ * @param type payload type (for IKEv1 or IKEv2)
* @param cert certificate to embed
* @return cert_payload_t object
*/
-cert_payload_t *cert_payload_create_from_cert(certificate_t *cert);
+cert_payload_t *cert_payload_create_from_cert(payload_type_t type,
+ certificate_t *cert);
/**
- * Creates a certificate payload with hash and URL encoding of a certificate.
+ * Creates an IKEv2 certificate payload with hash and URL encoding.
*
* @param hash hash of the DER encoded certificate (get's cloned)
- * @param url the URL to locate the certificate (get's cloned)
+ * @param url URL to the certificate
* @return cert_payload_t object
*/
cert_payload_t *cert_payload_create_from_hash_and_url(chunk_t hash, char *url);
@@ -137,10 +132,12 @@ cert_payload_t *cert_payload_create_from_hash_and_url(chunk_t hash, char *url);
/**
* Creates a custom certificate payload using type and associated data.
*
- * @param type encoding type of certificate
+ * @param type payload type (for IKEv1 or IKEv2)
+ * @param encoding encoding type of certificate
* @param data associated data (gets owned)
* @return cert_payload_t object
*/
-cert_payload_t *cert_payload_create_custom(cert_encoding_t type, chunk_t data);
+cert_payload_t *cert_payload_create_custom(payload_type_t type,
+ cert_encoding_t encoding, chunk_t data);
#endif /** CERT_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/certreq_payload.c b/src/libcharon/encoding/payloads/certreq_payload.c
index 02015f273..df5e73b5b 100644
--- a/src/libcharon/encoding/payloads/certreq_payload.c
+++ b/src/libcharon/encoding/payloads/certreq_payload.c
@@ -64,15 +64,17 @@ struct private_certreq_payload_t {
* The contained certreq data value.
*/
chunk_t data;
+
+ /**
+ * Payload type CERTIFICATE_REQUEST or CERTIFICATE_REQUEST_V1
+ */
+ payload_type_t type;
};
/**
- * Encoding rules to parse or generate a CERTREQ payload
- *
- * The defined offsets are the positions in a object of type
- * private_certreq_payload_t.
+ * Encoding rules for CERTREQ payload.
*/
-encoding_rule_t certreq_payload_encodings[] = {
+static encoding_rule_t encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_certreq_payload_t, next_payload) },
/* the critical bit */
@@ -90,7 +92,7 @@ encoding_rule_t certreq_payload_encodings[] = {
/* 1 Byte CERTREQ type*/
{ U_INT_8, offsetof(private_certreq_payload_t, encoding) },
/* some certreq data bytes, length is defined in PAYLOAD_LENGTH */
- { CERTREQ_DATA, offsetof(private_certreq_payload_t, data) }
+ { CHUNK_DATA, offsetof(private_certreq_payload_t, data) }
};
/*
@@ -109,7 +111,8 @@ encoding_rule_t certreq_payload_encodings[] = {
METHOD(payload_t, verify, status_t,
private_certreq_payload_t *this)
{
- if (this->encoding == ENC_X509_SIGNATURE)
+ if (this->type == CERTIFICATE_REQUEST &&
+ this->encoding == ENC_X509_SIGNATURE)
{
if (this->data.len % HASH_SIZE_SHA1)
{
@@ -121,17 +124,23 @@ METHOD(payload_t, verify, status_t,
return SUCCESS;
}
-METHOD(payload_t, get_encoding_rules, void,
- private_certreq_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, int,
+ private_certreq_payload_t *this, encoding_rule_t **rules)
+{
+ *rules = encodings;
+ return countof(encodings);
+}
+
+METHOD(payload_t, get_header_length, int,
+ private_certreq_payload_t *this)
{
- *rules = certreq_payload_encodings;
- *rule_count = countof(certreq_payload_encodings);
+ return 5;
}
METHOD(payload_t, get_type, payload_type_t,
private_certreq_payload_t *this)
{
- return CERTIFICATE_REQUEST;
+ return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
@@ -152,6 +161,16 @@ METHOD(payload_t, get_length, size_t,
return this->payload_length;
}
+METHOD(certreq_payload_t, get_dn, identification_t*,
+ private_certreq_payload_t *this)
+{
+ if (this->data.len)
+ {
+ return identification_create_from_encoding(ID_DER_ASN1_DN, this->data);
+ }
+ return NULL;
+}
+
METHOD(certreq_payload_t, add_keyid, void,
private_certreq_payload_t *this, chunk_t keyid)
{
@@ -199,6 +218,10 @@ METHOD(certreq_payload_t, create_keyid_enumerator, enumerator_t*,
{
keyid_enumerator_t *enumerator;
+ if (this->type == CERTIFICATE_REQUEST_V1)
+ {
+ return enumerator_create_empty();
+ }
INIT(enumerator,
.public = {
.enumerate = (void*)_keyid_enumerate,
@@ -231,7 +254,7 @@ METHOD2(payload_t, certreq_payload_t, destroy, void,
/*
* Described in header
*/
-certreq_payload_t *certreq_payload_create()
+certreq_payload_t *certreq_payload_create(payload_type_t type)
{
private_certreq_payload_t *this;
@@ -240,6 +263,7 @@ certreq_payload_t *certreq_payload_create()
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
+ .get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@@ -250,9 +274,11 @@ certreq_payload_t *certreq_payload_create()
.get_cert_type = _get_cert_type,
.add_keyid = _add_keyid,
.destroy = _destroy,
+ .get_dn = _get_dn,
},
.next_payload = NO_PAYLOAD,
- .payload_length = CERTREQ_PAYLOAD_HEADER_LENGTH,
+ .payload_length = get_header_length(this),
+ .type = type,
);
return &this->public;
}
@@ -262,8 +288,10 @@ certreq_payload_t *certreq_payload_create()
*/
certreq_payload_t *certreq_payload_create_type(certificate_type_t type)
{
- private_certreq_payload_t *this = (private_certreq_payload_t*)certreq_payload_create();
+ private_certreq_payload_t *this;
+ this = (private_certreq_payload_t*)
+ certreq_payload_create(CERTIFICATE_REQUEST);
switch (type)
{
case CERT_X509:
@@ -278,3 +306,19 @@ certreq_payload_t *certreq_payload_create_type(certificate_type_t type)
return &this->public;
}
+/*
+ * Described in header
+ */
+certreq_payload_t *certreq_payload_create_dn(identification_t *id)
+{
+ private_certreq_payload_t *this;
+
+ this = (private_certreq_payload_t*)
+ certreq_payload_create(CERTIFICATE_REQUEST_V1);
+
+ this->encoding = ENC_X509_SIGNATURE;
+ this->data = chunk_clone(id->get_encoding(id));
+ this->payload_length = get_header_length(this) + this->data.len;
+
+ return &this->public;
+}
diff --git a/src/libcharon/encoding/payloads/certreq_payload.h b/src/libcharon/encoding/payloads/certreq_payload.h
index 914063628..cce71c0ad 100644
--- a/src/libcharon/encoding/payloads/certreq_payload.h
+++ b/src/libcharon/encoding/payloads/certreq_payload.h
@@ -27,25 +27,20 @@ typedef struct certreq_payload_t certreq_payload_t;
#include <library.h>
#include <encoding/payloads/payload.h>
#include <encoding/payloads/cert_payload.h>
+#include <utils/identification.h>
/**
- * Length of a CERTREQ payload without the CERTREQ data in bytes.
- */
-#define CERTREQ_PAYLOAD_HEADER_LENGTH 5
-
-/**
- * Class representing an IKEv2 CERTREQ payload.
- *
- * The CERTREQ payload format is described in RFC section 3.7.
+ * Class representing an IKEv1/IKEv2 CERTREQ payload.
*/
struct certreq_payload_t {
+
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
- * Create an enumerator over contained keyids.
+ * Create an enumerator over contained keyids (IKEv2 only).
*
* @return enumerator over chunk_t's.
*/
@@ -59,7 +54,7 @@ struct certreq_payload_t {
certificate_type_t (*get_cert_type)(certreq_payload_t *this);
/**
- * Add a certificates keyid to the payload.
+ * Add a certificates keyid to the payload (IKEv2 only).
*
* @param keyid keyid of the trusted certifcate
* @return
@@ -67,6 +62,13 @@ struct certreq_payload_t {
void (*add_keyid)(certreq_payload_t *this, chunk_t keyid);
/**
+ * Get the distinguished name of the payload (IKEv1 only).
+ *
+ * @return DN as identity, must be destroyed
+ */
+ identification_t* (*get_dn)(certreq_payload_t *this);
+
+ /**
* Destroys an certreq_payload_t object.
*/
void (*destroy) (certreq_payload_t *this);
@@ -77,14 +79,22 @@ struct certreq_payload_t {
*
* @return certreq payload
*/
-certreq_payload_t *certreq_payload_create(void);
+certreq_payload_t *certreq_payload_create(payload_type_t payload_type);
/**
- * Creates an empty certreq_payload_t for a kind of certificates.
+ * Creates an empty IKEv2 certreq_payload_t for a kind of certificates.
*
* @param type type of the added keyids
* @return certreq payload
*/
certreq_payload_t *certreq_payload_create_type(certificate_type_t type);
+/**
+ * Creates a IKEv1 certreq_payload_t for a given distinguished name.
+ *
+ * @param id distinguished name, does not get owned
+ * @return certreq payload
+ */
+certreq_payload_t *certreq_payload_create_dn(identification_t *id);
+
#endif /** CERTREQ_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/configuration_attribute.c b/src/libcharon/encoding/payloads/configuration_attribute.c
index e608497bd..482eca882 100644
--- a/src/libcharon/encoding/payloads/configuration_attribute.c
+++ b/src/libcharon/encoding/payloads/configuration_attribute.c
@@ -36,41 +36,48 @@ struct private_configuration_attribute_t {
configuration_attribute_t public;
/**
- * Reserved bit
+ * Value encoded in length field?
+ */
+ bool af_flag;
+
+ /**
+ * Reserved bit (af_flag in IKEv2)
*/
bool reserved;
/**
* Type of the attribute.
*/
- u_int16_t type;
+ u_int16_t attr_type;
/**
- * Length of the attribute.
+ * Length of the attribute, value if af_flag set.
*/
- u_int16_t length;
+ u_int16_t length_or_value;
/**
* Attribute value as chunk.
*/
chunk_t value;
+
+ /**
+ * Payload type, CONFIGURATION_ATTRIBUTE or DATA_ATTRIBUTE_V1
+ */
+ payload_type_t type;
};
/**
- * Encoding rules to parse or generate a configuration attribute.
- *
- * The defined offsets are the positions in a object of type
- * private_configuration_attribute_t.
+ * Encoding rules for a IKEv2 configuration attribute / IKEv1 data attribute
*/
-encoding_rule_t configuration_attribute_encodings[] = {
+static encoding_rule_t encodings_v2[] = {
/* 1 reserved bit */
- { RESERVED_BIT, offsetof(private_configuration_attribute_t, reserved)},
+ { RESERVED_BIT, offsetof(private_configuration_attribute_t, reserved) },
/* type of the attribute as 15 bit unsigned integer */
- { ATTRIBUTE_TYPE, offsetof(private_configuration_attribute_t, type) },
+ { ATTRIBUTE_TYPE, offsetof(private_configuration_attribute_t, attr_type) },
/* Length of attribute value */
- { CONFIGURATION_ATTRIBUTE_LENGTH, offsetof(private_configuration_attribute_t, length) },
+ { ATTRIBUTE_LENGTH, offsetof(private_configuration_attribute_t, length_or_value)},
/* Value of attribute if attribute format flag is zero */
- { CONFIGURATION_ATTRIBUTE_VALUE, offsetof(private_configuration_attribute_t, value) }
+ { ATTRIBUTE_VALUE, offsetof(private_configuration_attribute_t, value) },
};
/*
@@ -85,87 +92,142 @@ encoding_rule_t configuration_attribute_encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
+/**
+ * Encoding rules for a IKEv1 data attribute
+ */
+static encoding_rule_t encodings_v1[] = {
+ /* AF Flag */
+ { ATTRIBUTE_FORMAT, offsetof(private_configuration_attribute_t, af_flag) },
+ /* type of the attribute as 15 bit unsigned integer */
+ { ATTRIBUTE_TYPE, offsetof(private_configuration_attribute_t, attr_type) },
+ /* Length of attribute value */
+ { ATTRIBUTE_LENGTH_OR_VALUE, offsetof(private_configuration_attribute_t, length_or_value)},
+ /* Value of attribute if attribute format flag is zero */
+ { ATTRIBUTE_VALUE, offsetof(private_configuration_attribute_t, value) },
+};
+
+/*
+ 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
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ !F| Attribute Type ! Length |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ ~ Value ~
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+
METHOD(payload_t, verify, status_t,
private_configuration_attribute_t *this)
{
bool failed = FALSE;
- if (this->length != this->value.len)
- {
- DBG1(DBG_ENC, "invalid attribute length");
- return FAILED;
- }
-
- switch (this->type)
+ switch (this->attr_type)
{
- case INTERNAL_IP4_ADDRESS:
- case INTERNAL_IP4_NETMASK:
- case INTERNAL_IP4_DNS:
- case INTERNAL_IP4_NBNS:
- case INTERNAL_ADDRESS_EXPIRY:
- case INTERNAL_IP4_DHCP:
- if (this->length != 0 && this->length != 4)
+ case INTERNAL_IP4_ADDRESS:
+ case INTERNAL_IP4_NETMASK:
+ case INTERNAL_IP4_DNS:
+ case INTERNAL_IP4_NBNS:
+ case INTERNAL_ADDRESS_EXPIRY:
+ case INTERNAL_IP4_DHCP:
+ if (this->length_or_value != 0 && this->length_or_value != 4)
{
failed = TRUE;
}
break;
- case INTERNAL_IP4_SUBNET:
- if (this->length != 0 && this->length != 8)
+ case INTERNAL_IP4_SUBNET:
+ if (this->length_or_value != 0 && this->length_or_value != 8)
{
failed = TRUE;
}
break;
- case INTERNAL_IP6_ADDRESS:
- case INTERNAL_IP6_SUBNET:
- if (this->length != 0 && this->length != 17)
+ case INTERNAL_IP6_ADDRESS:
+ case INTERNAL_IP6_SUBNET:
+ if (this->length_or_value != 0 && this->length_or_value != 17)
{
failed = TRUE;
}
break;
- case INTERNAL_IP6_DNS:
- case INTERNAL_IP6_NBNS:
- case INTERNAL_IP6_DHCP:
- if (this->length != 0 && this->length != 16)
+ case INTERNAL_IP6_DNS:
+ case INTERNAL_IP6_NBNS:
+ case INTERNAL_IP6_DHCP:
+ if (this->length_or_value != 0 && this->length_or_value != 16)
{
failed = TRUE;
}
break;
- case SUPPORTED_ATTRIBUTES:
- if (this->length % 2)
+ case SUPPORTED_ATTRIBUTES:
+ if (this->length_or_value % 2)
{
failed = TRUE;
}
break;
- case APPLICATION_VERSION:
+ case APPLICATION_VERSION:
+ case INTERNAL_IP4_SERVER:
+ case INTERNAL_IP6_SERVER:
+ case XAUTH_TYPE:
+ case XAUTH_USER_NAME:
+ case XAUTH_USER_PASSWORD:
+ case XAUTH_PASSCODE:
+ case XAUTH_MESSAGE:
+ case XAUTH_CHALLENGE:
+ case XAUTH_DOMAIN:
+ case XAUTH_STATUS:
+ case XAUTH_NEXT_PIN:
+ case XAUTH_ANSWER:
+ case UNITY_BANNER:
+ case UNITY_SAVE_PASSWD:
+ case UNITY_DEF_DOMAIN:
+ case UNITY_SPLITDNS_NAME:
+ case UNITY_SPLIT_INCLUDE:
+ case UNITY_NATT_PORT:
+ case UNITY_LOCAL_LAN:
+ case UNITY_PFS:
+ case UNITY_FW_TYPE:
+ case UNITY_BACKUP_SERVERS:
+ case UNITY_DDNS_HOSTNAME:
/* any length acceptable */
break;
- default:
+ default:
DBG1(DBG_ENC, "unknown attribute type %N",
- configuration_attribute_type_names, this->type);
+ configuration_attribute_type_names, this->attr_type);
break;
}
if (failed)
{
DBG1(DBG_ENC, "invalid attribute length %d for %N",
- this->length, configuration_attribute_type_names, this->type);
+ this->length_or_value, configuration_attribute_type_names,
+ this->attr_type);
return FAILED;
}
return SUCCESS;
}
-METHOD(payload_t, get_encoding_rules, void,
- private_configuration_attribute_t *this, encoding_rule_t **rules,
- size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, int,
+ private_configuration_attribute_t *this, encoding_rule_t **rules)
+{
+ if (this->type == CONFIGURATION_ATTRIBUTE)
+ {
+ *rules = encodings_v2;
+ return countof(encodings_v2);
+ }
+ *rules = encodings_v1;
+ return countof(encodings_v1);
+}
+
+METHOD(payload_t, get_header_length, int,
+ private_configuration_attribute_t *this)
{
- *rules = configuration_attribute_encodings;
- *rule_count = countof(configuration_attribute_encodings);
+ return 4;
}
METHOD(payload_t, get_type, payload_type_t,
private_configuration_attribute_t *this)
{
- return CONFIGURATION_ATTRIBUTE;
+ return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
@@ -182,21 +244,35 @@ METHOD(payload_t, set_next_type, void,
METHOD(payload_t, get_length, size_t,
private_configuration_attribute_t *this)
{
- return this->value.len + CONFIGURATION_ATTRIBUTE_HEADER_LENGTH;
+ return get_header_length(this) + this->value.len;
}
METHOD(configuration_attribute_t, get_cattr_type, configuration_attribute_type_t,
private_configuration_attribute_t *this)
{
- return this->type;
+ return this->attr_type;
}
-METHOD(configuration_attribute_t, get_value, chunk_t,
+METHOD(configuration_attribute_t, get_chunk, chunk_t,
private_configuration_attribute_t *this)
{
+ if (this->af_flag)
+ {
+ return chunk_from_thing(this->length_or_value);
+ }
return this->value;
}
+METHOD(configuration_attribute_t, get_value, u_int16_t,
+ private_configuration_attribute_t *this)
+{
+ if (this->af_flag)
+ {
+ return this->length_or_value;
+ }
+ return 0;
+}
+
METHOD2(payload_t, configuration_attribute_t, destroy, void,
private_configuration_attribute_t *this)
{
@@ -207,7 +283,7 @@ METHOD2(payload_t, configuration_attribute_t, destroy, void,
/*
* Described in header.
*/
-configuration_attribute_t *configuration_attribute_create()
+configuration_attribute_t *configuration_attribute_create(payload_type_t type)
{
private_configuration_attribute_t *this;
@@ -216,16 +292,19 @@ configuration_attribute_t *configuration_attribute_create()
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
+ .get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
.get_type = _get_type,
.destroy = _destroy,
},
+ .get_chunk = _get_chunk,
.get_value = _get_value,
.get_type = _get_cattr_type,
.destroy = _destroy,
},
+ .type = type
);
return &this->public;
}
@@ -233,15 +312,33 @@ configuration_attribute_t *configuration_attribute_create()
/*
* Described in header.
*/
+configuration_attribute_t *configuration_attribute_create_chunk(
+ payload_type_t type, configuration_attribute_type_t attr_type, chunk_t chunk)
+{
+ private_configuration_attribute_t *this;
+
+ this = (private_configuration_attribute_t*)
+ configuration_attribute_create(type);
+ this->attr_type = ((u_int16_t)attr_type) & 0x7FFF;
+ this->value = chunk_clone(chunk);
+ this->length_or_value = chunk.len;
+
+ return &this->public;
+}
+
+/*
+ * Described in header.
+ */
configuration_attribute_t *configuration_attribute_create_value(
- configuration_attribute_type_t type, chunk_t value)
+ configuration_attribute_type_t attr_type, u_int16_t value)
{
private_configuration_attribute_t *this;
- this = (private_configuration_attribute_t*)configuration_attribute_create();
- this->type = ((u_int16_t)type) & 0x7FFF;
- this->value = chunk_clone(value);
- this->length = value.len;
+ this = (private_configuration_attribute_t*)
+ configuration_attribute_create(CONFIGURATION_ATTRIBUTE_V1);
+ this->attr_type = ((u_int16_t)attr_type) & 0x7FFF;
+ this->length_or_value = value;
+ this->af_flag = TRUE;
return &this->public;
}
diff --git a/src/libcharon/encoding/payloads/configuration_attribute.h b/src/libcharon/encoding/payloads/configuration_attribute.h
index 6e4b018bb..ecc0f9c07 100644
--- a/src/libcharon/encoding/payloads/configuration_attribute.h
+++ b/src/libcharon/encoding/payloads/configuration_attribute.h
@@ -29,14 +29,7 @@ typedef struct configuration_attribute_t configuration_attribute_t;
#include <encoding/payloads/payload.h>
/**
- * Configuration attribute header length in bytes.
- */
-#define CONFIGURATION_ATTRIBUTE_HEADER_LENGTH 4
-
-/**
- * Class representing an IKEv2-CONFIGURATION Attribute.
- *
- * The CONFIGURATION ATTRIBUTE format is described in RFC section 3.15.1.
+ * Class representing an IKEv2 configuration attribute / IKEv1 data attribute.
*/
struct configuration_attribute_t {
@@ -53,11 +46,18 @@ struct configuration_attribute_t {
configuration_attribute_type_t (*get_type)(configuration_attribute_t *this);
/**
- * Returns the value of the attribute.
+ * Returns the value of the attribute as chunk.
*
* @return chunk_t pointing to the internal value
*/
- chunk_t (*get_value) (configuration_attribute_t *this);
+ chunk_t (*get_chunk) (configuration_attribute_t *this);
+
+ /**
+ * Returns the 2 byte value of the attribute as u_int16.
+ *
+ * @return attribute value
+ */
+ u_int16_t (*get_value) (configuration_attribute_t *this);
/**
* Destroys an configuration_attribute_t object.
@@ -68,18 +68,30 @@ struct configuration_attribute_t {
/**
* Creates an empty configuration attribute.
*
- * @return created configuration attribute
+ * @param type CONFIGURATION_ATTRIBUTE or CONFIGURATION_ATTRIBUTE_V1
+ * @return created configuration attribute
*/
-configuration_attribute_t *configuration_attribute_create();
+configuration_attribute_t *configuration_attribute_create(payload_type_t type);
/**
* Creates a configuration attribute with type and value.
*
- * @param type type of configuration attribute
- * @param value value, gets cloned
- * @return created configuration attribute
+ * @param type CONFIGURATION_ATTRIBUTE or CONFIGURATION_ATTRIBUTE_V1
+ * @param attr_type type of configuration attribute
+ * @param chunk attribute value, gets cloned
+ * @return created configuration attribute
+ */
+configuration_attribute_t *configuration_attribute_create_chunk(
+ payload_type_t type, configuration_attribute_type_t attr_type, chunk_t chunk);
+
+/**
+ * Creates a IKEv1 configuration attribute with 2 bytes value (IKEv1 only).
+ *
+ * @param attr_type type of configuration attribute
+ * @param value attribute value, gets cloned
+ * @return created CONFIGURATION_ATTRIBUTE_V1 configuration attribute
*/
configuration_attribute_t *configuration_attribute_create_value(
- configuration_attribute_type_t type, chunk_t value);
+ configuration_attribute_type_t attr_type, u_int16_t value);
#endif /** CONFIGURATION_ATTRIBUTE_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/cp_payload.c b/src/libcharon/encoding/payloads/cp_payload.c
index 82e9e51b7..40f6ae48f 100644
--- a/src/libcharon/encoding/payloads/cp_payload.c
+++ b/src/libcharon/encoding/payloads/cp_payload.c
@@ -44,7 +44,7 @@ struct private_cp_payload_t {
/**
* Next payload type.
*/
- u_int8_t next_payload;
+ u_int8_t next_payload;
/**
* Critical flag.
@@ -67,6 +67,11 @@ struct private_cp_payload_t {
u_int16_t payload_length;
/**
+ * Identifier field, IKEv1 only
+ */
+ u_int16_t identifier;
+
+ /**
* List of attributes, as configuration_attribute_t
*/
linked_list_t *attributes;
@@ -74,38 +79,40 @@ struct private_cp_payload_t {
/**
* Config Type.
*/
- u_int8_t type;
+ u_int8_t cfg_type;
+
+ /**
+ * CONFIGURATION or CONFIGURATION_V1
+ */
+ payload_type_t type;
};
/**
- * Encoding rules to parse or generate a IKEv2-CP Payload
- *
- * The defined offsets are the positions in a object of type
- * private_cp_payload_t.
+ * Encoding rules to for an IKEv2 configuration payload
*/
-encoding_rule_t cp_payload_encodings[] = {
+static encoding_rule_t encodings_v2[] = {
/* 1 Byte next payload type, stored in the field next_payload */
- { U_INT_8, offsetof(private_cp_payload_t, next_payload) },
+ { U_INT_8, offsetof(private_cp_payload_t, next_payload) },
/* the critical bit */
- { FLAG, offsetof(private_cp_payload_t, critical) },
+ { FLAG, offsetof(private_cp_payload_t, critical) },
/* 7 Bit reserved bits */
- { RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[0]) },
- { RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[1]) },
- { RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[2]) },
- { RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[3]) },
- { RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[4]) },
- { RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[5]) },
- { RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[6]) },
+ { RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[0]) },
+ { RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[1]) },
+ { RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[2]) },
+ { RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[3]) },
+ { RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[4]) },
+ { RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[5]) },
+ { RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[6]) },
/* Length of the whole CP payload*/
- { PAYLOAD_LENGTH, offsetof(private_cp_payload_t, payload_length) },
- /* Proposals are stored in a proposal substructure,
- offset points to a linked_list_t pointer */
- { U_INT_8, offsetof(private_cp_payload_t, type) },
+ { PAYLOAD_LENGTH, offsetof(private_cp_payload_t, payload_length) },
+ { U_INT_8, offsetof(private_cp_payload_t, cfg_type) },
/* 3 reserved bytes */
- { RESERVED_BYTE, offsetof(private_cp_payload_t, reserved_byte[0])},
- { RESERVED_BYTE, offsetof(private_cp_payload_t, reserved_byte[1])},
- { RESERVED_BYTE, offsetof(private_cp_payload_t, reserved_byte[2])},
- { CONFIGURATION_ATTRIBUTES, offsetof(private_cp_payload_t, attributes) }
+ { RESERVED_BYTE, offsetof(private_cp_payload_t, reserved_byte[0])},
+ { RESERVED_BYTE, offsetof(private_cp_payload_t, reserved_byte[1])},
+ { RESERVED_BYTE, offsetof(private_cp_payload_t, reserved_byte[2])},
+ /* list of configuration attributes in a list */
+ { PAYLOAD_LIST + CONFIGURATION_ATTRIBUTE,
+ offsetof(private_cp_payload_t, attributes) },
};
/*
@@ -122,6 +129,47 @@ encoding_rule_t cp_payload_encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
+/**
+ * Encoding rules to for an IKEv1 configuration payload
+ */
+static encoding_rule_t encodings_v1[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_cp_payload_t, next_payload) },
+ /* the critical bit */
+ { FLAG, offsetof(private_cp_payload_t, critical) },
+ /* 7 Bit reserved bits */
+ { RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[0]) },
+ { RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[1]) },
+ { RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[2]) },
+ { RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[3]) },
+ { RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[4]) },
+ { RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[5]) },
+ { RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[6]) },
+ /* Length of the whole CP payload*/
+ { PAYLOAD_LENGTH, offsetof(private_cp_payload_t, payload_length) },
+ { U_INT_8, offsetof(private_cp_payload_t, cfg_type) },
+ /* 1 reserved bytes */
+ { RESERVED_BYTE, offsetof(private_cp_payload_t, reserved_byte[0])},
+ { U_INT_16, offsetof(private_cp_payload_t, identifier)},
+ /* list of configuration attributes in a list */
+ { PAYLOAD_LIST + CONFIGURATION_ATTRIBUTE_V1,
+ offsetof(private_cp_payload_t, attributes) },
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload ! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! CFG Type ! RESERVED ! Identifier !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Configuration Attributes ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
METHOD(payload_t, verify, status_t,
private_cp_payload_t *this)
{
@@ -142,17 +190,28 @@ METHOD(payload_t, verify, status_t,
return status;
}
-METHOD(payload_t, get_encoding_rules, void,
- private_cp_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, int,
+ private_cp_payload_t *this, encoding_rule_t **rules)
+{
+ if (this->type == CONFIGURATION)
+ {
+ *rules = encodings_v2;
+ return countof(encodings_v2);
+ }
+ *rules = encodings_v1;
+ return countof(encodings_v1);
+}
+
+METHOD(payload_t, get_header_length, int,
+ private_cp_payload_t *this)
{
- *rules = cp_payload_encodings;
- *rule_count = countof(cp_payload_encodings);
+ return 8;
}
METHOD(payload_t, get_type, payload_type_t,
private_cp_payload_t *this)
{
- return CONFIGURATION;
+ return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
@@ -175,7 +234,7 @@ static void compute_length(private_cp_payload_t *this)
enumerator_t *enumerator;
payload_t *attribute;
- this->payload_length = CP_PAYLOAD_HEADER_LENGTH;
+ this->payload_length = get_header_length(this);
enumerator = this->attributes->create_enumerator(this->attributes);
while (enumerator->enumerate(enumerator, &attribute))
@@ -207,7 +266,18 @@ METHOD(cp_payload_t, add_attribute, void,
METHOD(cp_payload_t, get_config_type, config_type_t,
private_cp_payload_t *this)
{
- return this->type;
+ return this->cfg_type;
+}
+
+METHOD(cp_payload_t, get_identifier, u_int16_t,
+ private_cp_payload_t *this)
+{
+ return this->identifier;
+}
+METHOD(cp_payload_t, set_identifier, void,
+ private_cp_payload_t *this, u_int16_t identifier)
+{
+ this->identifier = identifier;
}
METHOD2(payload_t, cp_payload_t, destroy, void,
@@ -221,7 +291,7 @@ METHOD2(payload_t, cp_payload_t, destroy, void,
/*
* Described in header.
*/
-cp_payload_t *cp_payload_create_type(config_type_t type)
+cp_payload_t *cp_payload_create_type(payload_type_t type, config_type_t cfg_type)
{
private_cp_payload_t *this;
@@ -230,6 +300,7 @@ cp_payload_t *cp_payload_create_type(config_type_t type)
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
+ .get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@@ -239,11 +310,14 @@ cp_payload_t *cp_payload_create_type(config_type_t type)
.create_attribute_enumerator = _create_attribute_enumerator,
.add_attribute = _add_attribute,
.get_type = _get_config_type,
+ .get_identifier = _get_identifier,
+ .set_identifier = _set_identifier,
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
- .payload_length = CP_PAYLOAD_HEADER_LENGTH,
+ .payload_length = get_header_length(this),
.attributes = linked_list_create(),
+ .cfg_type = cfg_type,
.type = type,
);
return &this->public;
@@ -252,7 +326,7 @@ cp_payload_t *cp_payload_create_type(config_type_t type)
/*
* Described in header.
*/
-cp_payload_t *cp_payload_create()
+cp_payload_t *cp_payload_create(payload_type_t type)
{
- return cp_payload_create_type(CFG_REQUEST);
+ return cp_payload_create_type(type, CFG_REQUEST);
}
diff --git a/src/libcharon/encoding/payloads/cp_payload.h b/src/libcharon/encoding/payloads/cp_payload.h
index afae6091a..5eb1e06a7 100644
--- a/src/libcharon/encoding/payloads/cp_payload.h
+++ b/src/libcharon/encoding/payloads/cp_payload.h
@@ -31,11 +31,6 @@ typedef struct cp_payload_t cp_payload_t;
#include <utils/enumerator.h>
/**
- * CP_PAYLOAD length in bytes without any proposal substructure.
- */
-#define CP_PAYLOAD_HEADER_LENGTH 8
-
-/**
* Config Type of an Configuration Payload.
*/
enum config_type_t {
@@ -51,9 +46,7 @@ enum config_type_t {
extern enum_name_t *config_type_names;
/**
- * Class representing an IKEv2-CP Payload.
- *
- * The CP Payload format is described in RFC section 3.15.
+ * Class representing an IKEv2 configuration / IKEv1 attribute payload.
*/
struct cp_payload_t {
@@ -85,6 +78,20 @@ struct cp_payload_t {
config_type_t (*get_type) (cp_payload_t *this);
/**
+ * Set the configuration payload identifier (IKEv1 only).
+ *
+ @param identifier identifier to set
+ */
+ void (*set_identifier) (cp_payload_t *this, u_int16_t identifier);
+
+ /**
+ * Get the configuration payload identifier (IKEv1 only).
+ *
+ * @return identifier
+ */
+ u_int16_t (*get_identifier) (cp_payload_t *this);
+
+ /**
* Destroys an cp_payload_t object.
*/
void (*destroy) (cp_payload_t *this);
@@ -93,16 +100,18 @@ struct cp_payload_t {
/**
* Creates an empty configuration payload
*
- * @return empty configuration payload
+ * @param type payload type, CONFIGURATION or CONFIGURATION_V1
+ * @return empty configuration payload
*/
-cp_payload_t *cp_payload_create();
+cp_payload_t *cp_payload_create(payload_type_t type);
/**
* Creates an cp_payload_t with type and value
*
- * @param config_type type of configuration payload to create
- * @return created configuration payload
+ * @param type payload type, CONFIGURATION or CONFIGURATION_V1
+ * @param cfg_type type of configuration payload to create
+ * @return created configuration payload
*/
-cp_payload_t *cp_payload_create_type(config_type_t config_type);
+cp_payload_t *cp_payload_create_type(payload_type_t type, config_type_t cfg_type);
#endif /** CP_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/delete_payload.c b/src/libcharon/encoding/payloads/delete_payload.c
index e6ee07d39..007411f37 100644
--- a/src/libcharon/encoding/payloads/delete_payload.c
+++ b/src/libcharon/encoding/payloads/delete_payload.c
@@ -24,9 +24,9 @@ typedef struct private_delete_payload_t private_delete_payload_t;
/**
* Private data of an delete_payload_t object.
- *
*/
struct private_delete_payload_t {
+
/**
* Public delete_payload_t interface.
*/
@@ -45,7 +45,7 @@ struct private_delete_payload_t {
/**
* reserved bits
*/
- bool reserved[7];
+ bool reserved[8];
/**
* Length of this payload.
@@ -53,6 +53,11 @@ struct private_delete_payload_t {
u_int16_t payload_length;
/**
+ * IKEv1 Domain of Interpretation
+ */
+ u_int32_t doi;
+
+ /**
* Protocol ID.
*/
u_int8_t protocol_id;
@@ -71,19 +76,21 @@ struct private_delete_payload_t {
* The contained SPI's.
*/
chunk_t spis;
+
+ /**
+ * Payload type, DELETE or DELETE_V1
+ */
+ payload_type_t type;
};
/**
- * Encoding rules to parse or generate a DELETE payload
- *
- * The defined offsets are the positions in a object of type
- * private_delete_payload_t.
+ * Encoding rules for an IKEv2 delete payload.
*/
-encoding_rule_t delete_payload_encodings[] = {
+static encoding_rule_t encodings_v2[] = {
/* 1 Byte next payload type, stored in the field next_payload */
- { U_INT_8, offsetof(private_delete_payload_t, next_payload) },
+ { U_INT_8, offsetof(private_delete_payload_t, next_payload) },
/* the critical bit */
- { FLAG, offsetof(private_delete_payload_t, critical) },
+ { FLAG, offsetof(private_delete_payload_t, critical) },
/* 7 Bit reserved bits */
{ RESERVED_BIT, offsetof(private_delete_payload_t, reserved[0]) },
{ RESERVED_BIT, offsetof(private_delete_payload_t, reserved[1]) },
@@ -98,7 +105,47 @@ encoding_rule_t delete_payload_encodings[] = {
{ U_INT_8, offsetof(private_delete_payload_t, spi_size) },
{ U_INT_16, offsetof(private_delete_payload_t, spi_count) },
/* some delete data bytes, length is defined in PAYLOAD_LENGTH */
- { SPIS, offsetof(private_delete_payload_t, spis) }
+ { CHUNK_DATA, offsetof(private_delete_payload_t, spis) },
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload !C! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Protocol ID ! SPI Size ! # of SPIs !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Security Parameter Index(es) (SPI) ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Encoding rules for an IKEv1 delete payload.
+ */
+static encoding_rule_t encodings_v1[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_delete_payload_t, next_payload) },
+ /* 8 Bit reserved bits */
+ { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[0]) },
+ { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[1]) },
+ { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[2]) },
+ { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[3]) },
+ { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[4]) },
+ { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[5]) },
+ { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[6]) },
+ { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[7]) },
+ /* Length of the whole payload*/
+ { PAYLOAD_LENGTH, offsetof(private_delete_payload_t, payload_length) },
+ /* Domain of interpretation */
+ { U_INT_32, offsetof(private_delete_payload_t, doi) },
+ { U_INT_8, offsetof(private_delete_payload_t, protocol_id) },
+ { U_INT_8, offsetof(private_delete_payload_t, spi_size) },
+ { U_INT_16, offsetof(private_delete_payload_t, spi_count) },
+ /* some delete data bytes, length is defined in PAYLOAD_LENGTH */
+ { CHUNK_DATA, offsetof(private_delete_payload_t, spis) },
};
/*
@@ -107,6 +154,8 @@ encoding_rule_t delete_payload_encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! DOI !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Protocol ID ! SPI Size ! # of SPIs !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
@@ -129,10 +178,19 @@ METHOD(payload_t, verify, status_t,
break;
case PROTO_IKE:
case 0:
- /* IKE deletion has no spi assigned! */
- if (this->spi_size != 0)
- {
- return FAILED;
+ if (this->type == DELETE)
+ { /* IKEv2 deletion has no spi assigned! */
+ if (this->spi_size != 0)
+ {
+ return FAILED;
+ }
+ }
+ else
+ { /* IKEv1 uses the two concatenated ISAKMP cookies as SPI */
+ if (this->spi_size != 16)
+ {
+ return FAILED;
+ }
}
break;
default:
@@ -145,17 +203,32 @@ METHOD(payload_t, verify, status_t,
return SUCCESS;
}
-METHOD(payload_t, get_encoding_rules, void,
- private_delete_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, int,
+ private_delete_payload_t *this, encoding_rule_t **rules)
{
- *rules = delete_payload_encodings;
- *rule_count = countof(delete_payload_encodings);
+ if (this->type == DELETE)
+ {
+ *rules = encodings_v2;
+ return countof(encodings_v2);
+ }
+ *rules = encodings_v1;
+ return countof(encodings_v1);
+}
+
+METHOD(payload_t, get_header_length, int,
+ private_delete_payload_t *this)
+{
+ if (this->type == DELETE)
+ {
+ return 8;
+ }
+ return 12;
}
METHOD(payload_t, get_payload_type, payload_type_t,
private_delete_payload_t *this)
{
- return DELETE;
+ return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
@@ -198,6 +271,16 @@ METHOD(delete_payload_t, add_spi, void,
}
}
+METHOD(delete_payload_t, set_ike_spi, void,
+ private_delete_payload_t *this, u_int64_t spi_i, u_int64_t spi_r)
+{
+ free(this->spis.ptr);
+ this->spis = chunk_cat("cc", chunk_from_thing(spi_i),
+ chunk_from_thing(spi_r));
+ this->spi_count = 1;
+ this->payload_length = get_header_length(this) + this->spi_size;
+}
+
/**
* SPI enumerator implementation
*/
@@ -249,7 +332,8 @@ METHOD2(payload_t, delete_payload_t, destroy, void,
/*
* Described in header
*/
-delete_payload_t *delete_payload_create(protocol_id_t protocol_id)
+delete_payload_t *delete_payload_create(payload_type_t type,
+ protocol_id_t protocol_id)
{
private_delete_payload_t *this;
@@ -258,6 +342,7 @@ delete_payload_t *delete_payload_create(protocol_id_t protocol_id)
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
+ .get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@@ -266,13 +351,27 @@ delete_payload_t *delete_payload_create(protocol_id_t protocol_id)
},
.get_protocol_id = _get_protocol_id,
.add_spi = _add_spi,
+ .set_ike_spi = _set_ike_spi,
.create_spi_enumerator = _create_spi_enumerator,
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
- .payload_length = DELETE_PAYLOAD_HEADER_LENGTH,
.protocol_id = protocol_id,
- .spi_size = protocol_id == PROTO_AH || protocol_id == PROTO_ESP ? 4 : 0,
+ .doi = IKEV1_DOI_IPSEC,
+ .type = type,
);
+ this->payload_length = get_header_length(this);
+
+ if (protocol_id == PROTO_IKE)
+ {
+ if (type == DELETE_V1)
+ {
+ this->spi_size = 16;
+ }
+ }
+ else
+ {
+ this->spi_size = 4;
+ }
return &this->public;
}
diff --git a/src/libcharon/encoding/payloads/delete_payload.h b/src/libcharon/encoding/payloads/delete_payload.h
index 026829f97..afce1ecf1 100644
--- a/src/libcharon/encoding/payloads/delete_payload.h
+++ b/src/libcharon/encoding/payloads/delete_payload.h
@@ -29,14 +29,7 @@ typedef struct delete_payload_t delete_payload_t;
#include <encoding/payloads/proposal_substructure.h>
/**
- * Length of a delete payload without the SPI in bytes.
- */
-#define DELETE_PAYLOAD_HEADER_LENGTH 8
-
-/**
- * Class representing an IKEv2 DELETE payload.
- *
- * The DELETE payload format is described in RFC section 3.11.
+ * Class representing an IKEv1 or a IKEv2 DELETE payload.
*/
struct delete_payload_t {
@@ -60,6 +53,14 @@ struct delete_payload_t {
void (*add_spi) (delete_payload_t *this, u_int32_t spi);
/**
+ * Set the IKE SPIs for an IKEv1 delete.
+ *
+ * @param spi_i initiator SPI
+ * @param spi_r responder SPI
+ */
+ void (*set_ike_spi)(delete_payload_t *this, u_int64_t spi_i, u_int64_t spi_r);
+
+ /**
* Get an enumerator over the SPIs in network order.
*
* @return enumerator over SPIs, u_int32_t
@@ -75,9 +76,11 @@ struct delete_payload_t {
/**
* Creates an empty delete_payload_t object.
*
+ * @param type DELETE or DELETE_V1
* @param protocol_id protocol, such as AH|ESP
* @return delete_payload_t object
*/
-delete_payload_t *delete_payload_create(protocol_id_t protocol_id);
+delete_payload_t *delete_payload_create(payload_type_t type,
+ protocol_id_t protocol_id);
#endif /** DELETE_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/eap_payload.c b/src/libcharon/encoding/payloads/eap_payload.c
index cacaef222..dd2e25795 100644
--- a/src/libcharon/encoding/payloads/eap_payload.c
+++ b/src/libcharon/encoding/payloads/eap_payload.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2005-2010 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -19,6 +20,8 @@
#include "eap_payload.h"
#include <daemon.h>
+#include <eap/eap.h>
+#include <bio/bio_writer.h>
typedef struct private_eap_payload_t private_eap_payload_t;
@@ -65,7 +68,7 @@ struct private_eap_payload_t {
* private_eap_payload_t.
*
*/
-static encoding_rule_t eap_payload_encodings[] = {
+static encoding_rule_t encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_eap_payload_t, next_payload) },
/* the critical bit */
@@ -81,7 +84,7 @@ static encoding_rule_t eap_payload_encodings[] = {
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_eap_payload_t, payload_length) },
/* chunt to data, starting at "code" */
- { EAP_DATA, offsetof(private_eap_payload_t, data) },
+ { CHUNK_DATA, offsetof(private_eap_payload_t, data) },
};
/*
@@ -143,11 +146,17 @@ METHOD(payload_t, verify, status_t,
return SUCCESS;
}
-METHOD(payload_t, get_encoding_rules, void,
- private_eap_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, int,
+ private_eap_payload_t *this, encoding_rule_t **rules)
{
- *rules = eap_payload_encodings;
- *rule_count = sizeof(eap_payload_encodings) / sizeof(encoding_rule_t);
+ *rules = encodings;
+ return countof(encodings);
+}
+
+METHOD(payload_t, get_header_length, int,
+ private_eap_payload_t *this)
+{
+ return 4;
}
METHOD(payload_t, get_payload_type, payload_type_t,
@@ -210,28 +219,93 @@ METHOD(eap_payload_t, get_identifier, u_int8_t,
return 0;
}
+/**
+ * Get the current type at the given offset into this->data.
+ * @return the new offset or 0 if failed
+ */
+static size_t extract_type(private_eap_payload_t *this, size_t offset,
+ eap_type_t *type, u_int32_t *vendor)
+{
+ if (this->data.len > offset)
+ {
+ *vendor = 0;
+ *type = this->data.ptr[offset];
+ if (*type != EAP_EXPANDED)
+ {
+ return offset + 1;
+ }
+ if (this->data.len >= offset + 8)
+ {
+ *vendor = untoh32(this->data.ptr + offset) & 0x00FFFFFF;
+ *type = untoh32(this->data.ptr + offset + 4);
+ return offset + 8;
+ }
+ }
+ return 0;
+}
+
METHOD(eap_payload_t, get_type, eap_type_t,
private_eap_payload_t *this, u_int32_t *vendor)
{
eap_type_t type;
*vendor = 0;
- if (this->data.len > 4)
+ if (extract_type(this, 4, &type, vendor))
{
- type = this->data.ptr[4];
- if (type != EAP_EXPANDED)
- {
- return type;
- }
- if (this->data.len >= 12)
- {
- *vendor = untoh32(this->data.ptr + 4) & 0x00FFFFFF;
- return untoh32(this->data.ptr + 8);
- }
+ return type;
}
return 0;
}
+/**
+ * Type enumerator
+ */
+typedef struct {
+ /** public interface */
+ enumerator_t public;
+ /** payload */
+ private_eap_payload_t *payload;
+ /** current offset in the data */
+ size_t offset;
+} type_enumerator_t;
+
+METHOD(enumerator_t, enumerate_types, bool,
+ type_enumerator_t *this, eap_type_t *type, u_int32_t *vendor)
+{
+ this->offset = extract_type(this->payload, this->offset, type, vendor);
+ return this->offset;
+}
+
+METHOD(eap_payload_t, get_types, enumerator_t*,
+ private_eap_payload_t *this)
+{
+ type_enumerator_t *enumerator;
+ eap_type_t type;
+ u_int32_t vendor;
+ size_t offset;
+
+ offset = extract_type(this, 4, &type, &vendor);
+ if (offset && type == EAP_NAK)
+ {
+ INIT(enumerator,
+ .public = {
+ .enumerate = (void*)_enumerate_types,
+ .destroy = (void*)free,
+ },
+ .payload = this,
+ .offset = offset,
+ );
+ return &enumerator->public;
+ }
+ return enumerator_create_empty();
+}
+
+METHOD(eap_payload_t, is_expanded, bool,
+ private_eap_payload_t *this)
+{
+ return this->data.len > 4 ? this->data.ptr[4] == EAP_EXPANDED : FALSE;
+}
+
METHOD2(payload_t, eap_payload_t, destroy, void,
private_eap_payload_t *this)
{
@@ -251,6 +325,7 @@ eap_payload_t *eap_payload_create()
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
+ .get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@@ -262,10 +337,12 @@ eap_payload_t *eap_payload_create()
.get_code = _get_code,
.get_identifier = _get_identifier,
.get_type = _get_type,
+ .get_types = _get_types,
+ .is_expanded = _is_expanded,
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
- .payload_length = EAP_PAYLOAD_HEADER_LENGTH,
+ .payload_length = get_header_length(this),
);
return &this->public;
}
@@ -305,15 +382,81 @@ eap_payload_t *eap_payload_create_code(eap_code_t code, u_int8_t identifier)
return eap_payload_create_data(data);
}
+/**
+ * Write the given type either expanded or not
+ */
+static void write_type(bio_writer_t *writer, eap_type_t type, u_int32_t vendor,
+ bool expanded)
+{
+ if (expanded)
+ {
+ writer->write_uint8(writer, EAP_EXPANDED);
+ writer->write_uint24(writer, vendor);
+ writer->write_uint32(writer, type);
+ }
+ else
+ {
+ writer->write_uint8(writer, type);
+ }
+}
+
/*
* Described in header
*/
-eap_payload_t *eap_payload_create_nak(u_int8_t identifier)
+eap_payload_t *eap_payload_create_nak(u_int8_t identifier, eap_type_t type,
+ u_int32_t vendor, bool expanded)
{
- chunk_t data;
+ enumerator_t *enumerator;
+ eap_type_t reg_type;
+ u_int32_t reg_vendor;
+ bio_writer_t *writer;
+ chunk_t length, data;
+ bool added_any = FALSE, found_vendor = FALSE;
+ eap_payload_t *payload;
+
+ writer = bio_writer_create(12);
+ writer->write_uint8(writer, EAP_RESPONSE);
+ writer->write_uint8(writer, identifier);
+ length = writer->skip(writer, 2);
+
+ write_type(writer, EAP_NAK, 0, expanded);
+
+ enumerator = charon->eap->create_enumerator(charon->eap, EAP_PEER);
+ while (enumerator->enumerate(enumerator, &reg_type, &reg_vendor))
+ {
+ if ((type && type != reg_type) ||
+ (type && vendor && vendor != reg_vendor))
+ { /* the preferred type is only sent if we actually find it */
+ continue;
+ }
+ if (!reg_vendor || expanded)
+ {
+ write_type(writer, reg_type, reg_vendor, expanded);
+ added_any = TRUE;
+ }
+ else if (reg_vendor)
+ { /* found vendor specifc method, but this is not an expanded Nak */
+ found_vendor = TRUE;
+ }
+ }
+ enumerator->destroy(enumerator);
- data = chunk_from_chars(EAP_RESPONSE, identifier, 0, 0, EAP_NAK);
- htoun16(data.ptr + 2, data.len);
- return eap_payload_create_data(data);
+ if (found_vendor)
+ { /* request an expanded authentication type */
+ write_type(writer, EAP_EXPANDED, 0, expanded);
+ added_any = TRUE;
+ }
+ if (!added_any)
+ { /* no methods added */
+ write_type(writer, 0, 0, expanded);
+ }
+
+ /* set length */
+ data = writer->get_buf(writer);
+ htoun16(length.ptr, data.len);
+
+ payload = eap_payload_create_data(data);
+ writer->destroy(writer);
+ return payload;
}
diff --git a/src/libcharon/encoding/payloads/eap_payload.h b/src/libcharon/encoding/payloads/eap_payload.h
index 60d9c99d2..e8ed1c5e7 100644
--- a/src/libcharon/encoding/payloads/eap_payload.h
+++ b/src/libcharon/encoding/payloads/eap_payload.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -25,13 +26,8 @@
typedef struct eap_payload_t eap_payload_t;
#include <library.h>
+#include <eap/eap.h>
#include <encoding/payloads/payload.h>
-#include <sa/authenticators/eap/eap_method.h>
-
-/**
- * Length of a EAP payload without the EAP Message in bytes.
- */
-#define EAP_PAYLOAD_HEADER_LENGTH 4
/**
* Class representing an IKEv2 EAP payload.
@@ -87,6 +83,21 @@ struct eap_payload_t {
eap_type_t (*get_type) (eap_payload_t *this, u_int32_t *vendor);
/**
+ * Enumerate the EAP method types contained in an EAP-Nak (i.e. get_type()
+ * returns EAP_NAK).
+ *
+ * @return enumerator over (eap_type_t type, u_int32_t vendor)
+ */
+ enumerator_t* (*get_types) (eap_payload_t *this);
+
+ /**
+ * Check if the EAP method type is encoded in the Expanded Type format.
+ *
+ * @return TRUE if in Expanded Type format
+ */
+ bool (*is_expanded) (eap_payload_t *this);
+
+ /**
* Destroys an eap_payload_t object.
*/
void (*destroy) (eap_payload_t *this);
@@ -131,8 +142,12 @@ eap_payload_t *eap_payload_create_code(eap_code_t code, u_int8_t identifier);
* Creates an eap_payload_t EAP_RESPONSE containing an EAP_NAK.
*
* @param identifier EAP identifier to use in payload
+ * @param type preferred auth type, 0 to send all supported types
+ * @param vendor vendor identifier for auth type, 0 for default
+ * @param expanded TRUE to send an expanded Nak
* @return eap_payload_t object
*/
-eap_payload_t *eap_payload_create_nak(u_int8_t identifier);
+eap_payload_t *eap_payload_create_nak(u_int8_t identifier, eap_type_t type,
+ u_int32_t vendor, bool expanded);
#endif /** EAP_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/encodings.c b/src/libcharon/encoding/payloads/encodings.c
index 85caeda82..62de81120 100644
--- a/src/libcharon/encoding/payloads/encodings.c
+++ b/src/libcharon/encoding/payloads/encodings.c
@@ -29,30 +29,14 @@ ENUM(encoding_type_names, U_INT_4, ENCRYPTED_DATA,
"HEADER_LENGTH",
"SPI_SIZE",
"SPI",
- "KEY_EXCHANGE_DATA",
- "NOTIFICATION_DATA",
- "PROPOSALS",
- "TRANSFORMS",
- "TRANSFORM_ATTRIBUTES",
- "CONFIGURATION_ATTRIBUTES",
- "CONFIGURATION_ATTRIBUTE_VALUE",
"ATTRIBUTE_FORMAT",
"ATTRIBUTE_TYPE",
"ATTRIBUTE_LENGTH_OR_VALUE",
- "CONFIGURATION_ATTRIBUTE_LENGTH",
+ "ATTRIBUTE_LENGTH",
"ATTRIBUTE_VALUE",
- "TRAFFIC_SELECTORS",
"TS_TYPE",
"ADDRESS",
- "NONCE_DATA",
- "ID_DATA",
- "AUTH_DATA",
- "CERT_DATA",
- "CERTREQ_DATA",
- "EAP_DATA",
- "SPIS",
- "VID_DATA",
- "UNKNOWN_DATA",
+ "CHUNK_DATA",
"IKE_SPI",
"ENCRYPTED_DATA",
);
diff --git a/src/libcharon/encoding/payloads/encodings.h b/src/libcharon/encoding/payloads/encodings.h
index 52af4a984..54830bc8c 100644
--- a/src/libcharon/encoding/payloads/encodings.h
+++ b/src/libcharon/encoding/payloads/encodings.h
@@ -187,87 +187,6 @@ enum encoding_type_t {
SPI,
/**
- * Representating a Key Exchange Data field.
- *
- * When generating the content of the chunkt pointing to
- * is written.
- *
- * When parsing (Payload Length - 8) bytes are read and written into the chunk pointing to.
- */
- KEY_EXCHANGE_DATA,
-
- /**
- * Representating a Notification field.
- *
- * When generating the content of the chunkt pointing to
- * is written.
- *
- * When parsing (Payload Length - spi size - 8) bytes are read and written into the chunk pointing to.
- */
- NOTIFICATION_DATA,
-
- /**
- * Representating one or more proposal substructures.
- *
- * The offset points to a linked_list_t pointer.
- *
- * When generating the proposal_substructure_t objects are stored
- * in the pointed linked_list.
- *
- * When parsing the parsed proposal_substructure_t objects have
- * to be stored in the pointed linked_list.
- */
- PROPOSALS,
-
- /**
- * Representating one or more transform substructures.
- *
- * The offset points to a linked_list_t pointer.
- *
- * When generating the transform_substructure_t objects are stored
- * in the pointed linked_list.
- *
- * When parsing the parsed transform_substructure_t objects have
- * to be stored in the pointed linked_list.
- */
- TRANSFORMS,
-
- /**
- * Representating one or more Attributes of a transform substructure.
- *
- * The offset points to a linked_list_t pointer.
- *
- * When generating the transform_attribute_t objects are stored
- * in the pointed linked_list.
- *
- * When parsing the parsed transform_attribute_t objects have
- * to be stored in the pointed linked_list.
- */
- TRANSFORM_ATTRIBUTES,
-
- /**
- * Representating one or more Attributes of a configuration payload.
- *
- * The offset points to a linked_list_t pointer.
- *
- * When generating the configuration_attribute_t objects are stored
- * in the pointed linked_list.
- *
- * When parsing the parsed configuration_attribute_t objects have
- * to be stored in the pointed linked_list.
- */
- CONFIGURATION_ATTRIBUTES,
-
- /**
- *
- * When generating the content of the chunkt pointing to
- * is written.
- *
- * When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to.
- */
- CONFIGURATION_ATTRIBUTE_VALUE,
-
- /**
* Representing a 1 Bit flag specifying the format of a transform attribute.
*
* When generation, the next bit is set to 1 if the associated value
@@ -279,6 +198,7 @@ enum encoding_type_t {
* is moved 1 bit forward afterwards.
*/
ATTRIBUTE_FORMAT,
+
/**
* Representing a 15 Bit unsigned int value used as attribute type
* in an attribute transform.
@@ -321,7 +241,7 @@ enum encoding_type_t {
* The value is written to the associated data struct.
* The current read pointer is moved 16 bit forward afterwards.
*/
- CONFIGURATION_ATTRIBUTE_LENGTH,
+ ATTRIBUTE_LENGTH,
/**
* Depending on the field of type ATTRIBUTE_FORMAT
@@ -336,19 +256,6 @@ enum encoding_type_t {
ATTRIBUTE_VALUE,
/**
- * Representating one or more Traffic selectors of a TS payload.
- *
- * The offset points to a linked_list_t pointer.
- *
- * When generating the traffic_selector_substructure_t objects are stored
- * in the pointed linked_list.
- *
- * When parsing the parsed traffic_selector_substructure_t objects have
- * to be stored in the pointed linked_list.
- */
- TRAFFIC_SELECTORS,
-
- /**
* Representating a Traffic selector type field.
*
* When generating it must be changed from host to network order.
@@ -375,94 +282,9 @@ enum encoding_type_t {
ADDRESS,
/**
- * Representating a Nonce Data field.
- *
- * When generating the content of the chunkt pointing to
- * is written.
- *
- * When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to.
+ * Representing a variable length byte field.
*/
- NONCE_DATA,
-
- /**
- * Representating a ID Data field.
- *
- * When generating the content of the chunkt pointing to
- * is written.
- *
- * When parsing (Payload Length - 8) bytes are read and written into the chunk pointing to.
- */
- ID_DATA,
-
- /**
- * Representating a AUTH Data field.
- *
- * When generating the content of the chunkt pointing to
- * is written.
- *
- * When parsing (Payload Length - 8) bytes are read and written into the chunk pointing to.
- */
- AUTH_DATA,
-
- /**
- * Representating a CERT Data field.
- *
- * When generating the content of the chunkt pointing to
- * is written.
- *
- * When parsing (Payload Length - 5) bytes are read and written into the chunk pointing to.
- */
- CERT_DATA,
-
- /**
- * Representating a CERTREQ Data field.
- *
- * When generating the content of the chunkt pointing to
- * is written.
- *
- * When parsing (Payload Length - 5) bytes are read and written into the chunk pointing to.
- */
- CERTREQ_DATA,
-
- /**
- * Representating an EAP message field.
- *
- * When generating the content of the chunkt pointing to
- * is written.
- *
- * When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to.
- */
- EAP_DATA,
-
- /**
- * Representating the SPIS field in a DELETE payload.
- *
- * When generating the content of the chunkt pointing to
- * is written.
- *
- * When parsing (Payload Length - 8) bytes are read and written into the chunk pointing to.
- */
- SPIS,
-
- /**
- * Representating the VID DATA field in a VENDOR ID payload.
- *
- * When generating the content of the chunkt pointing to
- * is written.
- *
- * When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to.
- */
- VID_DATA,
-
- /**
- * Representating the DATA of an unknown payload.
- *
- * When generating the content of the chunkt pointing to
- * is written.
- *
- * When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to.
- */
- UNKNOWN_DATA,
+ CHUNK_DATA,
/**
* Representating an IKE_SPI field in an IKEv2 Header.
@@ -475,9 +297,20 @@ enum encoding_type_t {
IKE_SPI,
/**
- * Representing the encrypted data body of a encryption payload.
+ * Representating an encrypted IKEv1 message.
*/
ENCRYPTED_DATA,
+
+ /**
+ * Reprensenting a field containing a set of wrapped payloads.
+ *
+ * This type is not used directly, but as an offset to the wrapped payloads.
+ * The type of the wrapped payload is added to this encoding type.
+ *
+ * @note As payload types are added to this encoding type, it has
+ * to be the last in encoding_type_t.
+ */
+ PAYLOAD_LIST = 1000 /* no comma, read above! */
};
/**
diff --git a/src/libcharon/encoding/payloads/encryption_payload.c b/src/libcharon/encoding/payloads/encryption_payload.c
index e7b8063b7..02e7b8bf3 100644
--- a/src/libcharon/encoding/payloads/encryption_payload.c
+++ b/src/libcharon/encoding/payloads/encryption_payload.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2005-2010 Martin Willi
* Copyright (C) 2010 revosec AG
+ * Copyright (C) 2011 Tobias Brunner
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -71,6 +72,11 @@ struct private_encryption_payload_t {
* Contained payloads
*/
linked_list_t *payloads;
+
+ /**
+ * Type of payload, ENCRYPTED or ENCRYPTED_V1
+ */
+ payload_type_t type;
};
/**
@@ -79,7 +85,7 @@ struct private_encryption_payload_t {
* The defined offsets are the positions in a object of type
* private_encryption_payload_t.
*/
-encoding_rule_t encryption_payload_encodings[] = {
+static encoding_rule_t encodings_v2[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_encryption_payload_t, next_payload) },
/* Critical and 7 reserved bits, all stored for reconstruction */
@@ -87,7 +93,7 @@ encoding_rule_t encryption_payload_encodings[] = {
/* Length of the whole encryption payload*/
{ PAYLOAD_LENGTH, offsetof(private_encryption_payload_t, payload_length) },
/* encrypted data, stored in a chunk. contains iv, data, padding */
- { ENCRYPTED_DATA, offsetof(private_encryption_payload_t, encrypted) },
+ { CHUNK_DATA, offsetof(private_encryption_payload_t, encrypted) },
};
/*
@@ -109,24 +115,59 @@ encoding_rule_t encryption_payload_encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
+/**
+ * Encoding rules to parse or generate a complete encrypted IKEv1 message.
+ *
+ * The defined offsets are the positions in a object of type
+ * private_encryption_payload_t.
+ */
+static encoding_rule_t encodings_v1[] = {
+ /* encrypted data, stored in a chunk */
+ { ENCRYPTED_DATA, offsetof(private_encryption_payload_t, encrypted) },
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Encrypted IKE Payloads !
+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! ! Padding (0-255 octets) !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
METHOD(payload_t, verify, status_t,
private_encryption_payload_t *this)
{
return SUCCESS;
}
-METHOD(payload_t, get_encoding_rules, void,
- private_encryption_payload_t *this, encoding_rule_t **rules,
- size_t *count)
+METHOD(payload_t, get_encoding_rules, int,
+ private_encryption_payload_t *this, encoding_rule_t **rules)
+{
+ if (this->type == ENCRYPTED)
+ {
+ *rules = encodings_v2;
+ return countof(encodings_v2);
+ }
+ *rules = encodings_v1;
+ return countof(encodings_v1);
+}
+
+METHOD(payload_t, get_header_length, int,
+ private_encryption_payload_t *this)
{
- *rules = encryption_payload_encodings;
- *count = countof(encryption_payload_encodings);
+ if (this->type == ENCRYPTED)
+ {
+ return 4;
+ }
+ return 0;
}
METHOD(payload_t, get_type, payload_type_t,
private_encryption_payload_t *this)
{
- return ENCRYPTED;
+ return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
@@ -138,7 +179,8 @@ METHOD(payload_t, get_next_type, payload_type_t,
METHOD(payload_t, set_next_type, void,
private_encryption_payload_t *this, payload_type_t type)
{
- /* the next payload is set during add */
+ /* the next payload is set during add, still allow this for IKEv1 */
+ this->next_payload = type;
}
/**
@@ -174,7 +216,7 @@ static void compute_length(private_encryption_payload_t *this)
length += this->aead->get_icv_size(this->aead);
}
}
- length += ENCRYPTION_PAYLOAD_HEADER_LENGTH;
+ length += get_header_length(this);
this->payload_length = length;
}
@@ -266,7 +308,7 @@ static chunk_t append_header(private_encryption_payload_t *this, chunk_t assoc)
return chunk_cat("cc", assoc, chunk_from_thing(header));
}
-METHOD(encryption_payload_t, encrypt, bool,
+METHOD(encryption_payload_t, encrypt, status_t,
private_encryption_payload_t *this, chunk_t assoc)
{
chunk_t iv, plain, padding, icv, crypt;
@@ -277,14 +319,14 @@ METHOD(encryption_payload_t, encrypt, bool,
if (this->aead == NULL)
{
DBG1(DBG_ENC, "encrypting encryption payload failed, transform missing");
- return FALSE;
+ return INVALID_STATE;
}
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
if (!rng)
{
DBG1(DBG_ENC, "encrypting encryption payload failed, no RNG found");
- return FALSE;
+ return NOT_SUPPORTED;
}
assoc = append_header(this, assoc);
@@ -314,8 +356,14 @@ METHOD(encryption_payload_t, encrypt, bool,
crypt = chunk_create(plain.ptr, plain.len + padding.len);
generator->destroy(generator);
- rng->get_bytes(rng, iv.len, iv.ptr);
- rng->get_bytes(rng, padding.len - 1, padding.ptr);
+ if (!rng->get_bytes(rng, iv.len, iv.ptr) ||
+ !rng->get_bytes(rng, padding.len - 1, padding.ptr))
+ {
+ DBG1(DBG_ENC, "encrypting encryption payload failed, no IV or padding");
+ rng->destroy(rng);
+ free(assoc.ptr);
+ return FAILED;
+ }
padding.ptr[padding.len - 1] = padding.len - 1;
rng->destroy(rng);
@@ -325,14 +373,60 @@ METHOD(encryption_payload_t, encrypt, bool,
DBG3(DBG_ENC, "padding %B", &padding);
DBG3(DBG_ENC, "assoc %B", &assoc);
- this->aead->encrypt(this->aead, crypt, assoc, iv, NULL);
+ if (!this->aead->encrypt(this->aead, crypt, assoc, iv, NULL))
+ {
+ free(assoc.ptr);
+ return FAILED;
+ }
DBG3(DBG_ENC, "encrypted %B", &crypt);
DBG3(DBG_ENC, "ICV %B", &icv);
free(assoc.ptr);
- return TRUE;
+ return SUCCESS;
+}
+
+METHOD(encryption_payload_t, encrypt_v1, status_t,
+ private_encryption_payload_t *this, chunk_t iv)
+{
+ generator_t *generator;
+ chunk_t plain, padding;
+ size_t bs;
+
+ if (this->aead == NULL)
+ {
+ DBG1(DBG_ENC, "encryption failed, transform missing");
+ return INVALID_STATE;
+ }
+
+ generator = generator_create();
+ plain = generate(this, generator);
+ bs = this->aead->get_block_size(this->aead);
+ padding.len = bs - (plain.len % bs);
+
+ /* prepare data to encrypt:
+ * | plain | padding | */
+ free(this->encrypted.ptr);
+ this->encrypted = chunk_alloc(plain.len + padding.len);
+ memcpy(this->encrypted.ptr, plain.ptr, plain.len);
+ plain.ptr = this->encrypted.ptr;
+ padding.ptr = plain.ptr + plain.len;
+ memset(padding.ptr, 0, padding.len);
+ generator->destroy(generator);
+
+ DBG3(DBG_ENC, "encrypting payloads:");
+ DBG3(DBG_ENC, "plain %B", &plain);
+ DBG3(DBG_ENC, "padding %B", &padding);
+
+ if (!this->aead->encrypt(this->aead, this->encrypted, chunk_empty, iv, NULL))
+ {
+ return FAILED;
+ }
+
+ DBG3(DBG_ENC, "encrypted %B", &this->encrypted);
+
+ return SUCCESS;
}
/**
@@ -349,6 +443,13 @@ static status_t parse(private_encryption_payload_t *this, chunk_t plain)
{
payload_t *payload;
+ if (plain.len < 4 || untoh16(plain.ptr + 2) > plain.len)
+ {
+ DBG1(DBG_ENC, "invalid %N payload length, decryption failed?",
+ payload_type_names, type);
+ parser->destroy(parser);
+ return PARSE_ERROR;
+ }
if (parser->parse_payload(parser, type, &payload) != SUCCESS)
{
parser->destroy(parser);
@@ -438,6 +539,36 @@ METHOD(encryption_payload_t, decrypt, status_t,
return parse(this, plain);
}
+METHOD(encryption_payload_t, decrypt_v1, status_t,
+ private_encryption_payload_t *this, chunk_t iv)
+{
+ if (this->aead == NULL)
+ {
+ DBG1(DBG_ENC, "decryption failed, transform missing");
+ return INVALID_STATE;
+ }
+
+ /* data must be a multiple of block size */
+ if (iv.len != this->aead->get_block_size(this->aead) ||
+ this->encrypted.len < iv.len || this->encrypted.len % iv.len)
+ {
+ DBG1(DBG_ENC, "decryption failed, invalid length");
+ return FAILED;
+ }
+
+ DBG3(DBG_ENC, "decrypting payloads:");
+ DBG3(DBG_ENC, "encrypted %B", &this->encrypted);
+
+ if (!this->aead->decrypt(this->aead, this->encrypted, chunk_empty, iv, NULL))
+ {
+ return FAILED;
+ }
+
+ DBG3(DBG_ENC, "plain %B", &this->encrypted);
+
+ return parse(this, this->encrypted);
+}
+
METHOD(encryption_payload_t, set_transform, void,
private_encryption_payload_t *this, aead_t* aead)
{
@@ -455,7 +586,7 @@ METHOD2(payload_t, encryption_payload_t, destroy, void,
/*
* Described in header
*/
-encryption_payload_t *encryption_payload_create()
+encryption_payload_t *encryption_payload_create(payload_type_t type)
{
private_encryption_payload_t *this;
@@ -464,6 +595,7 @@ encryption_payload_t *encryption_payload_create()
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
+ .get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@@ -479,9 +611,16 @@ encryption_payload_t *encryption_payload_create()
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
- .payload_length = ENCRYPTION_PAYLOAD_HEADER_LENGTH,
.payloads = linked_list_create(),
+ .type = type,
);
+ this->payload_length = get_header_length(this);
+
+ if (type == ENCRYPTED_V1)
+ {
+ this->public.encrypt = _encrypt_v1;
+ this->public.decrypt = _decrypt_v1;
+ }
return &this->public;
}
diff --git a/src/libcharon/encoding/payloads/encryption_payload.h b/src/libcharon/encoding/payloads/encryption_payload.h
index e99c42fb7..5c6069339 100644
--- a/src/libcharon/encoding/payloads/encryption_payload.h
+++ b/src/libcharon/encoding/payloads/encryption_payload.h
@@ -30,11 +30,6 @@ typedef struct encryption_payload_t encryption_payload_t;
#include <encoding/payloads/payload.h>
/**
- * Encrpytion payload length in bytes without IV and following data.
- */
-#define ENCRYPTION_PAYLOAD_HEADER_LENGTH 4
-
-/**
* The encryption payload as described in RFC section 3.14.
*/
struct encryption_payload_t {
@@ -77,14 +72,18 @@ struct encryption_payload_t {
* Generate, encrypt and sign contained payloads.
*
* @param assoc associated data
- * @return TRUE if encrypted
+ * @return
+ * - SUCCESS if encryption successful
+ * - FAILED if encryption failed
+ * - INVALID_STATE if aead not supplied, but needed
*/
- bool (*encrypt) (encryption_payload_t *this, chunk_t assoc);
+ status_t (*encrypt) (encryption_payload_t *this, chunk_t assoc);
/**
* Decrypt, verify and parse contained payloads.
*
* @param assoc associated data
+ * @return
* - SUCCESS if parsing successful
* - PARSE_ERROR if sub-payload parsing failed
* - VERIFY_ERROR if sub-payload verification failed
@@ -102,8 +101,9 @@ struct encryption_payload_t {
/**
* Creates an empty encryption_payload_t object.
*
+ * @param type ENCRYPTED or ENCRYPTED_V1
* @return encryption_payload_t object
*/
-encryption_payload_t *encryption_payload_create(void);
+encryption_payload_t *encryption_payload_create(payload_type_t type);
#endif /** ENCRYPTION_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/endpoint_notify.c b/src/libcharon/encoding/payloads/endpoint_notify.c
index 1ead0a052..25fb42acd 100644
--- a/src/libcharon/encoding/payloads/endpoint_notify.c
+++ b/src/libcharon/encoding/payloads/endpoint_notify.c
@@ -227,7 +227,7 @@ METHOD(endpoint_notify_t, build_notify, notify_payload_t*,
chunk_t data;
notify_payload_t *notify;
- notify = notify_payload_create();
+ notify = notify_payload_create(NOTIFY);
notify->set_notify_type(notify, ME_ENDPOINT);
data = build_notification_data(this);
notify->set_notification_data(notify, data);
diff --git a/src/libcharon/encoding/payloads/hash_payload.c b/src/libcharon/encoding/payloads/hash_payload.c
new file mode 100644
index 000000000..0cf63ba67
--- /dev/null
+++ b/src/libcharon/encoding/payloads/hash_payload.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 <stddef.h>
+
+#include "hash_payload.h"
+
+#include <encoding/payloads/encodings.h>
+
+typedef struct private_hash_payload_t private_hash_payload_t;
+
+/**
+ * Private data of an hash_payload_t object.
+ */
+struct private_hash_payload_t {
+
+ /**
+ * Public hash_payload_t interface.
+ */
+ hash_payload_t public;
+
+ /**
+ * Next payload type.
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Reserved byte
+ */
+ u_int8_t reserved;
+
+ /**
+ * Length of this payload.
+ */
+ u_int16_t payload_length;
+
+ /**
+ * The contained hash value.
+ */
+ chunk_t hash;
+
+ /**
+ * either HASH_V1 or NAT_D_V1
+ */
+ payload_type_t type;
+};
+
+/**
+ * Encoding rules for an IKEv1 hash payload
+ */
+static encoding_rule_t encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_hash_payload_t, next_payload) },
+ { RESERVED_BYTE, offsetof(private_hash_payload_t, reserved) },
+ /* Length of the whole payload*/
+ { PAYLOAD_LENGTH, offsetof(private_hash_payload_t, payload_length) },
+ /* Hash Data is from variable size */
+ { CHUNK_DATA, offsetof(private_hash_payload_t, hash) },
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload ! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Hash Data ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+METHOD(payload_t, verify, status_t,
+ private_hash_payload_t *this)
+{
+ return SUCCESS;
+}
+
+METHOD(payload_t, get_encoding_rules, int,
+ private_hash_payload_t *this, encoding_rule_t **rules)
+{
+ *rules = encodings;
+ return countof(encodings);
+}
+
+METHOD(payload_t, get_header_length, int,
+ private_hash_payload_t *this)
+{
+ return 4;
+}
+
+METHOD(payload_t, get_type, payload_type_t,
+ private_hash_payload_t *this)
+{
+ return this->type;
+}
+
+METHOD(payload_t, get_next_type, payload_type_t,
+ private_hash_payload_t *this)
+{
+ return this->next_payload;
+}
+
+METHOD(payload_t, set_next_type, void,
+ private_hash_payload_t *this, payload_type_t type)
+{
+ this->next_payload = type;
+}
+
+METHOD(payload_t, get_length, size_t,
+ private_hash_payload_t *this)
+{
+ return this->payload_length;
+}
+
+METHOD(hash_payload_t, set_hash, void,
+ private_hash_payload_t *this, chunk_t hash)
+{
+ free(this->hash.ptr);
+ this->hash = chunk_clone(hash);
+ this->payload_length = get_header_length(this) + hash.len;
+}
+
+METHOD(hash_payload_t, get_hash, chunk_t,
+ private_hash_payload_t *this)
+{
+ return this->hash;
+}
+
+METHOD2(payload_t, hash_payload_t, destroy, void,
+ private_hash_payload_t *this)
+{
+ free(this->hash.ptr);
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+hash_payload_t *hash_payload_create(payload_type_t type)
+{
+ private_hash_payload_t *this;
+
+ INIT(this,
+ .public = {
+ .payload_interface = {
+ .verify = _verify,
+ .get_encoding_rules = _get_encoding_rules,
+ .get_header_length = _get_header_length,
+ .get_length = _get_length,
+ .get_next_type = _get_next_type,
+ .set_next_type = _set_next_type,
+ .get_type = _get_type,
+ .destroy = _destroy,
+ },
+ .set_hash = _set_hash,
+ .get_hash = _get_hash,
+ .destroy = _destroy,
+ },
+ .next_payload = NO_PAYLOAD,
+ .payload_length = get_header_length(this),
+ .type = type,
+ );
+ return &this->public;
+}
diff --git a/src/libcharon/encoding/payloads/hash_payload.h b/src/libcharon/encoding/payloads/hash_payload.h
new file mode 100644
index 000000000..cfe28460c
--- /dev/null
+++ b/src/libcharon/encoding/payloads/hash_payload.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 hash_payload hash_payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef HASH_PAYLOAD_H_
+#define HASH_PAYLOAD_H_
+
+typedef struct hash_payload_t hash_payload_t;
+
+#include <library.h>
+#include <encoding/payloads/payload.h>
+
+/**
+ * Object representing an IKEv1 hash payload.
+ */
+struct hash_payload_t {
+
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Set the hash value.
+ *
+ * @param hash chunk containing the hash, will be cloned
+ */
+ void (*set_hash) (hash_payload_t *this, chunk_t hash);
+
+ /**
+ * Get the hash value.
+ *
+ * @return chunkt to internal hash data
+ */
+ chunk_t (*get_hash) (hash_payload_t *this);
+
+ /**
+ * Destroys an hash_payload_t object.
+ */
+ void (*destroy) (hash_payload_t *this);
+};
+
+/**
+ * Creates an empty hash_payload_t object.
+ *
+ * @param type either HASH_V1 or NAT_D_V1
+ * @return hash_payload_t object
+ */
+hash_payload_t *hash_payload_create(payload_type_t type);
+
+#endif /** HASH_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/id_payload.c b/src/libcharon/encoding/payloads/id_payload.c
index 3befadfe2..02b07d691 100644
--- a/src/libcharon/encoding/payloads/id_payload.c
+++ b/src/libcharon/encoding/payloads/id_payload.c
@@ -1,9 +1,8 @@
/*
- * Copyright (C) 2005-2010 Martin Willi
+ * Copyright (C) 2005-2011 Martin Willi
* Copyright (C) 2010 revosec AG
- * Copyright (C) 2007 Tobias Brunner
+ * Copyright (C) 2007-2011 Tobias Brunner
* Copyright (C) 2005 Jan Hutter
- *
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -28,20 +27,15 @@ typedef struct private_id_payload_t private_id_payload_t;
/**
* Private data of an id_payload_t object.
- *
*/
struct private_id_payload_t {
+
/**
* Public id_payload_t interface.
*/
id_payload_t public;
/**
- * one of ID_INITIATOR, ID_RESPONDER
- */
- payload_type_t payload_type;
-
- /**
* Next payload type.
*/
u_int8_t next_payload;
@@ -75,19 +69,31 @@ struct private_id_payload_t {
* The contained id data value.
*/
chunk_t id_data;
+
+ /**
+ * Tunneled protocol ID for IKEv1 quick modes.
+ */
+ u_int8_t protocol_id;
+
+ /**
+ * Tunneled port for IKEv1 quick modes.
+ */
+ u_int16_t port;
+
+ /**
+ * one of ID_INITIATOR, ID_RESPONDER, IDv1 and NAT_OA_V1
+ */
+ payload_type_t type;
};
/**
- * Encoding rules to parse or generate a ID payload
- *
- * The defined offsets are the positions in a object of type
- * private_id_payload_t.
+ * Encoding rules for an IKEv2 ID payload
*/
-encoding_rule_t id_payload_encodings[] = {
+static encoding_rule_t encodings_v2[] = {
/* 1 Byte next payload type, stored in the field next_payload */
- { U_INT_8, offsetof(private_id_payload_t, next_payload) },
+ { U_INT_8, offsetof(private_id_payload_t, next_payload) },
/* the critical bit */
- { FLAG, offsetof(private_id_payload_t, critical) },
+ { FLAG, offsetof(private_id_payload_t, critical) },
/* 7 Bit reserved bits */
{ RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[0]) },
{ RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[1]) },
@@ -97,7 +103,7 @@ encoding_rule_t id_payload_encodings[] = {
{ RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[5]) },
{ RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[6]) },
/* Length of the whole payload*/
- { PAYLOAD_LENGTH, offsetof(private_id_payload_t, payload_length) },
+ { PAYLOAD_LENGTH, offsetof(private_id_payload_t, payload_length) },
/* 1 Byte ID type*/
{ U_INT_8, offsetof(private_id_payload_t, id_type) },
/* 3 reserved bytes */
@@ -105,7 +111,7 @@ encoding_rule_t id_payload_encodings[] = {
{ RESERVED_BYTE, offsetof(private_id_payload_t, reserved_byte[1])},
{ RESERVED_BYTE, offsetof(private_id_payload_t, reserved_byte[2])},
/* some id data bytes, length is defined in PAYLOAD_LENGTH */
- { ID_DATA, offsetof(private_id_payload_t, id_data) }
+ { CHUNK_DATA, offsetof(private_id_payload_t, id_data) },
};
/*
@@ -122,29 +128,92 @@ encoding_rule_t id_payload_encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
+/**
+ * Encoding rules for an IKEv1 ID payload
+ */
+static encoding_rule_t encodings_v1[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_id_payload_t, next_payload) },
+ /* Reserved Byte is skipped */
+ { RESERVED_BYTE, offsetof(private_id_payload_t, reserved_byte[0])},
+ /* Length of the whole payload*/
+ { PAYLOAD_LENGTH, offsetof(private_id_payload_t, payload_length) },
+ /* 1 Byte ID type*/
+ { U_INT_8, offsetof(private_id_payload_t, id_type) },
+ { U_INT_8, offsetof(private_id_payload_t, protocol_id) },
+ { U_INT_16, offsetof(private_id_payload_t, port) },
+ /* some id data bytes, length is defined in PAYLOAD_LENGTH */
+ { CHUNK_DATA, offsetof(private_id_payload_t, id_data) },
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload ! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! ID Type ! Protocol ID ! Port |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Identification Data ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
METHOD(payload_t, verify, status_t,
private_id_payload_t *this)
{
- if (this->id_type == 0 || this->id_type == 4)
+ bool bad_length = FALSE;
+
+ if (this->type == NAT_OA_V1 &&
+ this->id_type != ID_IPV4_ADDR && this->id_type != ID_IPV6_ADDR)
+ {
+ DBG1(DBG_ENC, "invalid ID type %N for %N payload", id_type_names,
+ this->id_type, payload_type_short_names, this->type);
+ return FAILED;
+ }
+ switch (this->id_type)
+ {
+ case ID_IPV4_ADDR_RANGE:
+ case ID_IPV4_ADDR_SUBNET:
+ bad_length = this->id_data.len != 8;
+ break;
+ case ID_IPV6_ADDR_RANGE:
+ case ID_IPV6_ADDR_SUBNET:
+ bad_length = this->id_data.len != 32;
+ break;
+ }
+ if (bad_length)
{
- /* reserved IDs */
- DBG1(DBG_ENC, "received ID with reserved type %d", this->id_type);
+ DBG1(DBG_ENC, "invalid %N length (%d bytes)",
+ id_type_names, this->id_type, this->id_data.len);
return FAILED;
}
return SUCCESS;
}
-METHOD(payload_t, get_encoding_rules, void,
- private_id_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, int,
+ private_id_payload_t *this, encoding_rule_t **rules)
+{
+ if (this->type == ID_V1 || this->type == NAT_OA_V1)
+ {
+ *rules = encodings_v1;
+ return countof(encodings_v1);
+ }
+ *rules = encodings_v2;
+ return countof(encodings_v2);
+}
+
+METHOD(payload_t, get_header_length, int,
+ private_id_payload_t *this)
{
- *rules = id_payload_encodings;
- *rule_count = countof(id_payload_encodings);
+ return 8;
}
METHOD(payload_t, get_type, payload_type_t,
private_id_payload_t *this)
{
- return this->payload_type;
+ return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
@@ -171,6 +240,102 @@ METHOD(id_payload_t, get_identification, identification_t*,
return identification_create_from_encoding(this->id_type, this->id_data);
}
+/**
+ * Create a traffic selector from an range ID
+ */
+static traffic_selector_t *get_ts_from_range(private_id_payload_t *this,
+ ts_type_t type)
+{
+ return traffic_selector_create_from_bytes(this->protocol_id, type,
+ chunk_create(this->id_data.ptr, this->id_data.len / 2), this->port,
+ chunk_skip(this->id_data, this->id_data.len / 2), this->port ?: 65535);
+}
+
+/**
+ * Create a traffic selector from an subnet ID
+ */
+static traffic_selector_t *get_ts_from_subnet(private_id_payload_t *this,
+ ts_type_t type)
+{
+ chunk_t net, netmask;
+ int i;
+
+ net = chunk_create(this->id_data.ptr, this->id_data.len / 2);
+ netmask = chunk_skip(this->id_data, this->id_data.len / 2);
+ for (i = 0; i < net.len; i++)
+ {
+ netmask.ptr[i] = (netmask.ptr[i] ^ 0xFF) | net.ptr[i];
+ }
+ return traffic_selector_create_from_bytes(this->protocol_id, type,
+ net, this->port, netmask, this->port ?: 65535);
+}
+
+/**
+ * Create a traffic selector from an IP ID
+ */
+static traffic_selector_t *get_ts_from_ip(private_id_payload_t *this,
+ ts_type_t type)
+{
+ return traffic_selector_create_from_bytes(this->protocol_id, type,
+ this->id_data, this->port, this->id_data, this->port ?: 65535);
+}
+
+METHOD(id_payload_t, get_ts, traffic_selector_t*,
+ private_id_payload_t *this)
+{
+ switch (this->id_type)
+ {
+ case ID_IPV4_ADDR_SUBNET:
+ if (this->id_data.len == 8)
+ {
+ return get_ts_from_subnet(this, TS_IPV4_ADDR_RANGE);
+ }
+ break;
+ case ID_IPV6_ADDR_SUBNET:
+ if (this->id_data.len == 32)
+ {
+ return get_ts_from_subnet(this, TS_IPV6_ADDR_RANGE);
+ }
+ break;
+ case ID_IPV4_ADDR_RANGE:
+ if (this->id_data.len == 8)
+ {
+ return get_ts_from_range(this, TS_IPV4_ADDR_RANGE);
+ }
+ break;
+ case ID_IPV6_ADDR_RANGE:
+ if (this->id_data.len == 32)
+ {
+ return get_ts_from_range(this, TS_IPV6_ADDR_RANGE);
+ }
+ break;
+ case ID_IPV4_ADDR:
+ if (this->id_data.len == 4)
+ {
+ return get_ts_from_ip(this, TS_IPV4_ADDR_RANGE);
+ }
+ break;
+ case ID_IPV6_ADDR:
+ if (this->id_data.len == 16)
+ {
+ return get_ts_from_ip(this, TS_IPV6_ADDR_RANGE);
+ }
+ break;
+ default:
+ break;
+ }
+ return NULL;
+}
+
+METHOD(id_payload_t, get_encoded, chunk_t,
+ private_id_payload_t *this)
+{
+ u_int16_t port = htons(this->port);
+ return chunk_cat("cccc", chunk_from_thing(this->id_type),
+ chunk_from_thing(this->protocol_id),
+ chunk_from_thing(port), this->id_data);
+}
+
METHOD2(payload_t, id_payload_t, destroy, void,
private_id_payload_t *this)
{
@@ -181,7 +346,7 @@ METHOD2(payload_t, id_payload_t, destroy, void,
/*
* Described in header.
*/
-id_payload_t *id_payload_create(payload_type_t payload_type)
+id_payload_t *id_payload_create(payload_type_t type)
{
private_id_payload_t *this;
@@ -190,6 +355,7 @@ id_payload_t *id_payload_create(payload_type_t payload_type)
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
+ .get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@@ -197,11 +363,13 @@ id_payload_t *id_payload_create(payload_type_t payload_type)
.destroy = _destroy,
},
.get_identification = _get_identification,
+ .get_encoded = _get_encoded,
+ .get_ts = _get_ts,
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
- .payload_length = ID_PAYLOAD_HEADER_LENGTH,
- .payload_type = payload_type,
+ .payload_length = get_header_length(this),
+ .type = type,
);
return &this->public;
}
@@ -209,15 +377,89 @@ id_payload_t *id_payload_create(payload_type_t payload_type)
/*
* Described in header.
*/
-id_payload_t *id_payload_create_from_identification(payload_type_t payload_type,
+id_payload_t *id_payload_create_from_identification(payload_type_t type,
identification_t *id)
{
private_id_payload_t *this;
- this = (private_id_payload_t*)id_payload_create(payload_type);
+ this = (private_id_payload_t*)id_payload_create(type);
this->id_data = chunk_clone(id->get_encoding(id));
this->id_type = id->get_type(id);
this->payload_length += this->id_data.len;
return &this->public;
}
+
+/*
+ * Described in header.
+ */
+id_payload_t *id_payload_create_from_ts(traffic_selector_t *ts)
+{
+ private_id_payload_t *this;
+ u_int8_t mask;
+ host_t *net;
+
+ this = (private_id_payload_t*)id_payload_create(ID_V1);
+
+ if (ts->is_host(ts, NULL))
+ {
+ if (ts->get_type(ts) == TS_IPV4_ADDR_RANGE)
+ {
+ this->id_type = ID_IPV4_ADDR;
+ }
+ else
+ {
+ this->id_type = ID_IPV6_ADDR;
+ }
+ this->id_data = chunk_clone(ts->get_from_address(ts));
+ }
+ else if (ts->to_subnet(ts, &net, &mask))
+ {
+ u_int8_t netmask[16], len, byte;
+
+ if (ts->get_type(ts) == TS_IPV4_ADDR_RANGE)
+ {
+ this->id_type = ID_IPV4_ADDR_SUBNET;
+ len = 4;
+ }
+ else
+ {
+ this->id_type = ID_IPV6_ADDR_SUBNET;
+ len = 16;
+ }
+ memset(netmask, 0, sizeof(netmask));
+ for (byte = 0; byte < sizeof(netmask); byte++)
+ {
+ if (mask < 8)
+ {
+ netmask[byte] = 0xFF << (8 - mask);
+ break;
+ }
+ netmask[byte] = 0xFF;
+ mask -= 8;
+ }
+ this->id_data = chunk_cat("cc", net->get_address(net),
+ chunk_create(netmask, len));
+ net->destroy(net);
+ }
+ else
+ {
+ if (ts->get_type(ts) == TS_IPV4_ADDR_RANGE)
+ {
+ this->id_type = ID_IPV4_ADDR_RANGE;
+ }
+ else
+ {
+ this->id_type = ID_IPV6_ADDR_RANGE;
+ }
+ this->id_data = chunk_cat("cc",
+ ts->get_from_address(ts), ts->get_to_address(ts));
+ net->destroy(net);
+ }
+ this->port = ts->get_from_port(ts);
+ this->protocol_id = ts->get_protocol(ts);
+ this->payload_length += this->id_data.len;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/encoding/payloads/id_payload.h b/src/libcharon/encoding/payloads/id_payload.h
index 99831f85f..9a6249429 100644
--- a/src/libcharon/encoding/payloads/id_payload.h
+++ b/src/libcharon/encoding/payloads/id_payload.h
@@ -28,16 +28,10 @@ typedef struct id_payload_t id_payload_t;
#include <library.h>
#include <utils/identification.h>
#include <encoding/payloads/payload.h>
+#include <selectors/traffic_selector.h>
/**
- * Length of a id payload without the data in bytes.
- */
-#define ID_PAYLOAD_HEADER_LENGTH 8
-
-/**
- * Object representing an IKEv2 ID payload.
- *
- * The ID payload format is described in RFC section 3.5.
+ * Object representing an IKEv1 or an IKEv2 ID payload.
*/
struct id_payload_t {
@@ -54,6 +48,20 @@ struct id_payload_t {
identification_t *(*get_identification) (id_payload_t *this);
/**
+ * Creates a traffic selector form a ID_ADDR_SUBNET/RANGE identity.
+ *
+ * @return traffic selector, NULL on failure
+ */
+ traffic_selector_t* (*get_ts)(id_payload_t *this);
+
+ /**
+ * Get encoded payload without fixed payload header (used for IKEv1).
+ *
+ * @return encoded payload (gets allocated)
+ */
+ chunk_t (*get_encoded)(id_payload_t *this);
+
+ /**
* Destroys an id_payload_t object.
*/
void (*destroy) (id_payload_t *this);
@@ -62,19 +70,27 @@ struct id_payload_t {
/**
* Creates an empty id_payload_t object.
*
- * @param payload_type one of ID_INITIATOR, ID_RESPONDER
- * @return id_payload_t object
+ * @param type one of ID_INITIATOR, ID_RESPONDER, ID_V1 and NAT_OA_V1
+ * @return id_payload_t object
*/
-id_payload_t *id_payload_create(payload_type_t payload_type);
+id_payload_t *id_payload_create(payload_type_t type);
/**
* Creates an id_payload_t from an existing identification_t object.
*
- * @param payload_type one of ID_INITIATOR, ID_RESPONDER
- * @param identification identification_t object
- * @return id_payload_t object
+ * @param type one of ID_INITIATOR, ID_RESPONDER, ID_V1 and NAT_OA_V1
+ * @param id identification_t object
+ * @return id_payload_t object
+ */
+id_payload_t *id_payload_create_from_identification(payload_type_t type,
+ identification_t *id);
+
+/**
+ * Create an IKEv1 ID_ADDR_SUBNET/RANGE identity from a traffic selector.
+ *
+ * @param ts traffic selector
+ * @return ID_V1 id_paylad_t object.
*/
-id_payload_t *id_payload_create_from_identification(payload_type_t payload_type,
- identification_t *identification);
+id_payload_t *id_payload_create_from_ts(traffic_selector_t *ts);
#endif /** ID_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/ike_header.c b/src/libcharon/encoding/payloads/ike_header.c
index 24d22f3a1..58b624192 100644
--- a/src/libcharon/encoding/payloads/ike_header.c
+++ b/src/libcharon/encoding/payloads/ike_header.c
@@ -81,12 +81,27 @@ struct private_ike_header_t {
* TRUE, if this is a response, FALSE if its a Request.
*/
bool response;
+
+ /**
+ * TRUE, if the packet is encrypted (IKEv1).
+ */
+ bool encryption;
+
+ /**
+ * TRUE, if the commit flag is set (IKEv1).
+ */
+ bool commit;
+
+ /**
+ * TRUE, if the auth only flag is set (IKEv1).
+ */
+ bool authonly;
} flags;
/**
* Reserved bits of IKE header
*/
- bool reserved[5];
+ bool reserved[2];
/**
* Associated Message-ID.
@@ -99,9 +114,15 @@ struct private_ike_header_t {
u_int32_t length;
};
-ENUM_BEGIN(exchange_type_names, EXCHANGE_TYPE_UNDEFINED, EXCHANGE_TYPE_UNDEFINED,
- "EXCHANGE_TYPE_UNDEFINED");
-ENUM_NEXT(exchange_type_names, IKE_SA_INIT, IKE_SESSION_RESUME, EXCHANGE_TYPE_UNDEFINED,
+ENUM_BEGIN(exchange_type_names, ID_PROT, TRANSACTION,
+ "ID_PROT",
+ "AUTH_ONLY",
+ "AGGRESSIVE",
+ "INFORMATIONAL_V1",
+ "TRANSACTION");
+ENUM_NEXT(exchange_type_names, QUICK_MODE, IKE_SESSION_RESUME, TRANSACTION,
+ "QUICK_MODE",
+ "NEW_GROUP_MODE",
"IKE_SA_INIT",
"IKE_AUTH",
"CREATE_CHILD_SA",
@@ -110,18 +131,23 @@ ENUM_NEXT(exchange_type_names, IKE_SA_INIT, IKE_SESSION_RESUME, EXCHANGE_TYPE_UN
#ifdef ME
ENUM_NEXT(exchange_type_names, ME_CONNECT, ME_CONNECT, IKE_SESSION_RESUME,
"ME_CONNECT");
-ENUM_END(exchange_type_names, ME_CONNECT);
+ENUM_NEXT(exchange_type_names, EXCHANGE_TYPE_UNDEFINED,
+ EXCHANGE_TYPE_UNDEFINED, ME_CONNECT,
+ "EXCHANGE_TYPE_UNDEFINED");
#else
-ENUM_END(exchange_type_names, IKE_SESSION_RESUME);
+ENUM_NEXT(exchange_type_names, EXCHANGE_TYPE_UNDEFINED,
+ EXCHANGE_TYPE_UNDEFINED, IKE_SESSION_RESUME,
+ "EXCHANGE_TYPE_UNDEFINED");
#endif /* ME */
+ENUM_END(exchange_type_names, EXCHANGE_TYPE_UNDEFINED);
/**
- * Encoding rules to parse or generate a IKEv2-Header.
+ * Encoding rules to parse or generate a IKE-Header.
*
* The defined offsets are the positions in a object of type
* ike_header_t.
*/
-encoding_rule_t ike_header_encodings[] = {
+static encoding_rule_t encodings[] = {
/* 8 Byte SPI, stored in the field initiator_spi */
{ IKE_SPI, offsetof(private_ike_header_t, initiator_spi) },
/* 8 Byte SPI, stored in the field responder_spi */
@@ -137,22 +163,20 @@ encoding_rule_t ike_header_encodings[] = {
/* 2 Bit reserved bits */
{ RESERVED_BIT, offsetof(private_ike_header_t, reserved[0]) },
{ RESERVED_BIT, offsetof(private_ike_header_t, reserved[1]) },
- /* 3 Bit flags, stored in the fields response, version and initiator */
+ /* 6 flags */
{ FLAG, offsetof(private_ike_header_t, flags.response) },
{ FLAG, offsetof(private_ike_header_t, flags.version) },
{ FLAG, offsetof(private_ike_header_t, flags.initiator) },
- /* 3 Bit reserved bits */
- { RESERVED_BIT, offsetof(private_ike_header_t, reserved[2]) },
- { RESERVED_BIT, offsetof(private_ike_header_t, reserved[3]) },
- { RESERVED_BIT, offsetof(private_ike_header_t, reserved[4]) },
+ { FLAG, offsetof(private_ike_header_t, flags.authonly) },
+ { FLAG, offsetof(private_ike_header_t, flags.commit) },
+ { FLAG, offsetof(private_ike_header_t, flags.encryption)},
/* 4 Byte message id, stored in the field message_id */
{ U_INT_32, offsetof(private_ike_header_t, message_id) },
/* 4 Byte length fied, stored in the field length */
- { HEADER_LENGTH,offsetof(private_ike_header_t, length) },
+ { HEADER_LENGTH, offsetof(private_ike_header_t, length) }
};
-
-/* 1 2 3
+/* 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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! IKE_SA Initiator's SPI !
@@ -172,35 +196,67 @@ encoding_rule_t ike_header_encodings[] = {
METHOD(payload_t, verify, status_t,
private_ike_header_t *this)
{
- if ((this->exchange_type < IKE_SA_INIT) ||
- ((this->exchange_type > INFORMATIONAL)
+ switch (this->exchange_type)
+ {
+ case ID_PROT:
+ case AGGRESSIVE:
+ if (this->message_id != 0)
+ {
+ return FAILED;
+ }
+ /* fall */
+ case AUTH_ONLY:
+ case INFORMATIONAL_V1:
+ case TRANSACTION:
+ case QUICK_MODE:
+ case NEW_GROUP_MODE:
+ if (this->maj_version != IKEV1_MAJOR_VERSION)
+ {
+ return FAILED;
+ }
+ break;
+ case IKE_SA_INIT:
+ case IKE_AUTH:
+ case CREATE_CHILD_SA:
+ case INFORMATIONAL:
+ case IKE_SESSION_RESUME:
#ifdef ME
- && (this->exchange_type != ME_CONNECT)
+ case ME_CONNECT:
#endif /* ME */
- ))
- {
- /* unsupported exchange type */
- return FAILED;
+ if (this->maj_version != IKEV2_MAJOR_VERSION)
+ {
+ return FAILED;
+ }
+ break;
+ default:
+ /* unsupported exchange type */
+ return FAILED;
}
- if (this->initiator_spi == 0
+ if (this->initiator_spi == 0)
+ {
#ifdef ME
- /* we allow zero spi for INFORMATIONAL exchanges,
- * to allow connectivity checks */
- && this->exchange_type != INFORMATIONAL
+ if (this->exchange_type != INFORMATIONAL)
+ /* we allow zero spi for INFORMATIONAL exchanges,
+ * to allow connectivity checks */
#endif /* ME */
- )
- {
- /* initiator spi not set */
- return FAILED;
+ {
+ return FAILED;
+ }
}
return SUCCESS;
}
-METHOD(payload_t, get_encoding_rules, void,
- private_ike_header_t *this, encoding_rule_t **rules, size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, int,
+ private_ike_header_t *this, encoding_rule_t **rules)
+{
+ *rules = encodings;
+ return countof(encodings);
+}
+
+METHOD(payload_t, get_header_length, int,
+ private_ike_header_t *this)
{
- *rules = ike_header_encodings;
- *rule_count = sizeof(ike_header_encodings) / sizeof(encoding_rule_t);
+ return IKE_HEADER_LENGTH;
}
METHOD(payload_t, get_type, payload_type_t,
@@ -311,6 +367,43 @@ METHOD(ike_header_t, set_initiator_flag, void,
this->flags.initiator = initiator;
}
+METHOD(ike_header_t, get_encryption_flag, bool,
+ private_ike_header_t *this)
+{
+ return this->flags.encryption;
+}
+
+METHOD(ike_header_t, set_encryption_flag, void,
+ private_ike_header_t *this, bool encryption)
+{
+ this->flags.encryption = encryption;
+}
+
+
+METHOD(ike_header_t, get_commit_flag, bool,
+ private_ike_header_t *this)
+{
+ return this->flags.commit;
+}
+
+METHOD(ike_header_t, set_commit_flag, void,
+ private_ike_header_t *this, bool commit)
+{
+ this->flags.commit = commit;
+}
+
+METHOD(ike_header_t, get_authonly_flag, bool,
+ private_ike_header_t *this)
+{
+ return this->flags.authonly;
+}
+
+METHOD(ike_header_t, set_authonly_flag, void,
+ private_ike_header_t *this, bool authonly)
+{
+ this->flags.authonly = authonly;
+}
+
METHOD(ike_header_t, get_exchange_type, u_int8_t,
private_ike_header_t *this)
{
@@ -353,6 +446,7 @@ ike_header_t *ike_header_create()
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
+ .get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@@ -373,21 +467,38 @@ ike_header_t *ike_header_create()
.set_version_flag = _set_version_flag,
.get_initiator_flag = _get_initiator_flag,
.set_initiator_flag = _set_initiator_flag,
+ .get_encryption_flag = _get_encryption_flag,
+ .set_encryption_flag = _set_encryption_flag,
+ .get_commit_flag = _get_commit_flag,
+ .set_commit_flag = _set_commit_flag,
+ .get_authonly_flag = _get_authonly_flag,
+ .set_authonly_flag = _set_authonly_flag,
.get_exchange_type = _get_exchange_type,
.set_exchange_type = _set_exchange_type,
.get_message_id = _get_message_id,
.set_message_id = _set_message_id,
.destroy = _destroy,
},
- .maj_version = IKE_MAJOR_VERSION,
- .min_version = IKE_MINOR_VERSION,
- .exchange_type = EXCHANGE_TYPE_UNDEFINED,
- .flags = {
- .initiator = TRUE,
- .version = HIGHER_VERSION_SUPPORTED_FLAG,
- },
.length = IKE_HEADER_LENGTH,
+ .exchange_type = EXCHANGE_TYPE_UNDEFINED,
);
return &this->public;
}
+
+/*
+ * Described in header.
+ */
+ike_header_t *ike_header_create_version(int major, int minor)
+{
+ ike_header_t *this = ike_header_create();
+
+ this->set_maj_version(this, major);
+ this->set_min_version(this, minor);
+ if (major == IKEV2_MAJOR_VERSION)
+ {
+ this->set_initiator_flag(this, TRUE);
+ }
+ return this;
+}
+
diff --git a/src/libcharon/encoding/payloads/ike_header.h b/src/libcharon/encoding/payloads/ike_header.h
index 5579a4961..e6b7d0dff 100644
--- a/src/libcharon/encoding/payloads/ike_header.h
+++ b/src/libcharon/encoding/payloads/ike_header.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2007 Tobias Brunner
- * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005-2011 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -30,19 +30,24 @@ typedef struct ike_header_t ike_header_t;
#include <encoding/payloads/payload.h>
/**
- * Major Version of IKEv2.
+ * Major Version of IKEv1 we implement.
*/
-#define IKE_MAJOR_VERSION 2
+#define IKEV1_MAJOR_VERSION 1
/**
- * Minor Version of IKEv2.
+ * Minor Version of IKEv1 we implement.
*/
-#define IKE_MINOR_VERSION 0
+#define IKEV1_MINOR_VERSION 0
/**
- * Flag in IKEv2-Header. Always 0.
+ * Major Version of IKEv2 we implement.
*/
-#define HIGHER_VERSION_SUPPORTED_FLAG 0
+#define IKEV2_MAJOR_VERSION 2
+
+/**
+ * Minor Version of IKEv2 we implement.
+ */
+#define IKEV2_MINOR_VERSION 0
/**
* Length of IKE Header in Bytes.
@@ -57,9 +62,39 @@ typedef struct ike_header_t ike_header_t;
enum exchange_type_t{
/**
- * EXCHANGE_TYPE_UNDEFINED. In private space, since not a official message type.
+ * Identity Protection (Main mode).
*/
- EXCHANGE_TYPE_UNDEFINED = 255,
+ ID_PROT = 2,
+
+ /**
+ * Authentication Only.
+ */
+ AUTH_ONLY = 3,
+
+ /**
+ * Aggresive (Aggressive mode)
+ */
+ AGGRESSIVE = 4,
+
+ /**
+ * Informational in IKEv1
+ */
+ INFORMATIONAL_V1 = 5,
+
+ /**
+ * Transaction (ISAKMP Cfg Mode "draft-ietf-ipsec-isakmp-mode-cfg-05")
+ */
+ TRANSACTION = 6,
+
+ /**
+ * Quick Mode
+ */
+ QUICK_MODE = 32,
+
+ /**
+ * New Group Mode
+ */
+ NEW_GROUP_MODE = 33,
/**
* IKE_SA_INIT.
@@ -77,7 +112,7 @@ enum exchange_type_t{
CREATE_CHILD_SA = 36,
/**
- * INFORMATIONAL.
+ * INFORMATIONAL in IKEv2.
*/
INFORMATIONAL = 37,
@@ -85,12 +120,18 @@ enum exchange_type_t{
* IKE_SESSION_RESUME (RFC 5723).
*/
IKE_SESSION_RESUME = 38,
+
#ifdef ME
/**
* ME_CONNECT
*/
- ME_CONNECT = 240
+ ME_CONNECT = 240,
#endif /* ME */
+
+ /**
+ * Undefined exchange type, in private space.
+ */
+ EXCHANGE_TYPE_UNDEFINED = 255,
};
/**
@@ -99,12 +140,7 @@ enum exchange_type_t{
extern enum_name_t *exchange_type_names;
/**
- * An object of this type represents an IKEv2 header and is used to
- * generate and parse IKEv2 headers.
- *
- * The header format of an IKEv2-Message is compatible to the
- * ISAKMP-Header format to allow implementations supporting
- * both versions of the IKE-protocol.
+ * An object of this type represents an IKE header of either IKEv1 or IKEv2.
*/
struct ike_header_t {
/**
@@ -115,7 +151,7 @@ struct ike_header_t {
/**
* Get the initiator spi.
*
- * @return initiator_spi
+ * @return initiator_spi
*/
u_int64_t (*get_initiator_spi) (ike_header_t *this);
@@ -129,7 +165,7 @@ struct ike_header_t {
/**
* Get the responder spi.
*
- * @return responder_spi
+ * @return responder_spi
*/
u_int64_t (*get_responder_spi) (ike_header_t *this);
@@ -143,7 +179,7 @@ struct ike_header_t {
/**
* Get the major version.
*
- * @return major version
+ * @return major version
*/
u_int8_t (*get_maj_version) (ike_header_t *this);
@@ -157,7 +193,7 @@ struct ike_header_t {
/**
* Get the minor version.
*
- * @return minor version
+ * @return minor version
*/
u_int8_t (*get_min_version) (ike_header_t *this);
@@ -171,7 +207,7 @@ struct ike_header_t {
/**
* Get the response flag.
*
- * @return response flag
+ * @return response flag
*/
bool (*get_response_flag) (ike_header_t *this);
@@ -185,7 +221,7 @@ struct ike_header_t {
/**
* Get "higher version supported"-flag.
*
- * @return version flag
+ * @return version flag
*/
bool (*get_version_flag) (ike_header_t *this);
@@ -199,7 +235,7 @@ struct ike_header_t {
/**
* Get the initiator flag.
*
- * @return initiator flag
+ * @return initiator flag
*/
bool (*get_initiator_flag) (ike_header_t *this);
@@ -211,9 +247,51 @@ struct ike_header_t {
void (*set_initiator_flag) (ike_header_t *this, bool initiator);
/**
+ * Get the encryption flag.
+ *
+ * @return encryption flag
+ */
+ bool (*get_encryption_flag) (ike_header_t *this);
+
+ /**
+ * Set the encryption flag.
+ *
+ * @param encryption encryption flag
+ */
+ void (*set_encryption_flag) (ike_header_t *this, bool encryption);
+
+ /**
+ * Get the commit flag.
+ *
+ * @return commit flag
+ */
+ bool (*get_commit_flag) (ike_header_t *this);
+
+ /**
+ * Set the commit flag.
+ *
+ * @param commit commit flag
+ */
+ void (*set_commit_flag) (ike_header_t *this, bool commit);
+
+ /**
+ * Get the authentication only flag.
+ *
+ * @return authonly flag
+ */
+ bool (*get_authonly_flag) (ike_header_t *this);
+
+ /**
+ * Set the authentication only flag.
+ *
+ * @param authonly authonly flag
+ */
+ void (*set_authonly_flag) (ike_header_t *this, bool authonly);
+
+ /**
* Get the exchange type.
*
- * @return exchange type
+ * @return exchange type
*/
u_int8_t (*get_exchange_type) (ike_header_t *this);
@@ -227,7 +305,7 @@ struct ike_header_t {
/**
* Get the message id.
*
- * @return message id
+ * @return message id
*/
u_int32_t (*get_message_id) (ike_header_t *this);
@@ -245,10 +323,17 @@ struct ike_header_t {
};
/**
- * Create an ike_header_t object
+ * Create an empty ike_header_t object.
*
* @return ike_header_t object
*/
ike_header_t *ike_header_create(void);
+/**
+ * Create an ike_header_t object for a specific major/minor version
+ *
+ * @return ike_header_t object
+ */
+ike_header_t *ike_header_create_version(int major, int minor);
+
#endif /** IKE_HEADER_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/ke_payload.c b/src/libcharon/encoding/payloads/ke_payload.c
index 999d73192..438ea46b9 100644
--- a/src/libcharon/encoding/payloads/ke_payload.c
+++ b/src/libcharon/encoding/payloads/ke_payload.c
@@ -67,15 +67,17 @@ struct private_ke_payload_t {
* Key Exchange Data of this KE payload.
*/
chunk_t key_exchange_data;
+
+ /**
+ * Payload type, KEY_EXCHANGE or KEY_EXCHANGE_V1
+ */
+ payload_type_t type;
};
/**
- * Encoding rules to parse or generate a IKEv2-KE Payload.
- *
- * The defined offsets are the positions in a object of type
- * private_ke_payload_t.
+ * Encoding rules for IKEv2 key exchange payload.
*/
-encoding_rule_t ke_payload_encodings[] = {
+static encoding_rule_t encodings_v2[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_ke_payload_t, next_payload) },
/* the critical bit */
@@ -96,7 +98,7 @@ encoding_rule_t ke_payload_encodings[] = {
{ RESERVED_BYTE, offsetof(private_ke_payload_t, reserved_byte[0])},
{ RESERVED_BYTE, offsetof(private_ke_payload_t, reserved_byte[1])},
/* Key Exchange Data is from variable size */
- { KEY_EXCHANGE_DATA, offsetof(private_ke_payload_t, key_exchange_data)}
+ { CHUNK_DATA, offsetof(private_ke_payload_t, key_exchange_data)},
};
/*
@@ -113,23 +115,62 @@ encoding_rule_t ke_payload_encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
+static encoding_rule_t encodings_v1[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_ke_payload_t, next_payload) },
+ /* Reserved Byte */
+ { RESERVED_BYTE, offsetof(private_ke_payload_t, reserved_byte[0])},
+ /* Length of the whole payload*/
+ { PAYLOAD_LENGTH, offsetof(private_ke_payload_t, payload_length) },
+ /* Key Exchange Data is from variable size */
+ { CHUNK_DATA, offsetof(private_ke_payload_t, key_exchange_data)},
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload ! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Key Exchange Data ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+
METHOD(payload_t, verify, status_t,
private_ke_payload_t *this)
{
return SUCCESS;
}
-METHOD(payload_t, get_encoding_rules, void,
- private_ke_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, int,
+ private_ke_payload_t *this, encoding_rule_t **rules)
+{
+ if (this->type == KEY_EXCHANGE)
+ {
+ *rules = encodings_v2;
+ return countof(encodings_v2);
+ }
+ *rules = encodings_v1;
+ return countof(encodings_v1);
+}
+
+METHOD(payload_t, get_header_length, int,
+ private_ke_payload_t *this)
{
- *rules = ke_payload_encodings;
- *rule_count = countof(ke_payload_encodings);
+ if (this->type == KEY_EXCHANGE)
+ {
+ return 8;
+ }
+ return 4;
}
METHOD(payload_t, get_type, payload_type_t,
private_ke_payload_t *this)
{
- return KEY_EXCHANGE;
+ return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
@@ -172,7 +213,7 @@ METHOD2(payload_t, ke_payload_t, destroy, void,
/*
* Described in header
*/
-ke_payload_t *ke_payload_create()
+ke_payload_t *ke_payload_create(payload_type_t type)
{
private_ke_payload_t *this;
@@ -181,6 +222,7 @@ ke_payload_t *ke_payload_create()
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
+ .get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@@ -192,22 +234,24 @@ ke_payload_t *ke_payload_create()
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
- .payload_length = KE_PAYLOAD_HEADER_LENGTH,
.dh_group_number = MODP_NONE,
+ .type = type,
);
+ this->payload_length = get_header_length(this);
return &this->public;
}
/*
* Described in header
*/
-ke_payload_t *ke_payload_create_from_diffie_hellman(diffie_hellman_t *dh)
+ke_payload_t *ke_payload_create_from_diffie_hellman(payload_type_t type,
+ diffie_hellman_t *dh)
{
- private_ke_payload_t *this = (private_ke_payload_t*)ke_payload_create();
+ private_ke_payload_t *this = (private_ke_payload_t*)ke_payload_create(type);
dh->get_my_public_value(dh, &this->key_exchange_data);
this->dh_group_number = dh->get_dh_group(dh);
- this->payload_length = this->key_exchange_data.len + KE_PAYLOAD_HEADER_LENGTH;
+ this->payload_length += this->key_exchange_data.len;
return &this->public;
}
diff --git a/src/libcharon/encoding/payloads/ke_payload.h b/src/libcharon/encoding/payloads/ke_payload.h
index 65cc11883..5942954d9 100644
--- a/src/libcharon/encoding/payloads/ke_payload.h
+++ b/src/libcharon/encoding/payloads/ke_payload.h
@@ -31,16 +31,10 @@ typedef struct ke_payload_t ke_payload_t;
#include <crypto/diffie_hellman.h>
/**
- * KE payload length in bytes without any key exchange data.
- */
-#define KE_PAYLOAD_HEADER_LENGTH 8
-
-/**
- * Class representing an IKEv2-KE Payload.
- *
- * The KE Payload format is described in RFC section 3.4.
+ * Class representing an IKEv1 or IKEv2 key exchange payload.
*/
struct ke_payload_t {
+
/**
* The payload_t interface.
*/
@@ -54,32 +48,34 @@ struct ke_payload_t {
chunk_t (*get_key_exchange_data) (ke_payload_t *this);
/**
- * Gets the Diffie-Hellman Group Number of this KE payload.
+ * Gets the Diffie-Hellman Group Number of this KE payload (IKEv2 only).
*
* @return DH Group Number of this payload
*/
diffie_hellman_group_t (*get_dh_group_number) (ke_payload_t *this);
/**
- * Destroys an ke_payload_t object.
+ * Destroys a ke_payload_t object.
*/
void (*destroy) (ke_payload_t *this);
};
/**
- * Creates an empty ke_payload_t object
+ * Creates an empty ke_payload_t object.
*
- * @return ke_payload_t object
+ * @param type KEY_EXCHANGE or KEY_EXCHANGE_V1
+ * @return ke_payload_t object
*/
-ke_payload_t *ke_payload_create(void);
+ke_payload_t *ke_payload_create(payload_type_t type);
/**
- * Creates a ke_payload_t from a diffie_hellman_t
+ * Creates a ke_payload_t from a diffie_hellman_t.
*
- * @param diffie_hellman diffie hellman object containing group and key
- * @return ke_payload_t object
+ * @param type KEY_EXCHANGE or KEY_EXCHANGE_V1
+ * @param dh diffie hellman object containing group and key
+ * @return ke_payload_t object
*/
-ke_payload_t *ke_payload_create_from_diffie_hellman(
- diffie_hellman_t *diffie_hellman);
+ke_payload_t *ke_payload_create_from_diffie_hellman(payload_type_t type,
+ diffie_hellman_t *dh);
#endif /** KE_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/nonce_payload.c b/src/libcharon/encoding/payloads/nonce_payload.c
index 78000b8c6..3c5eeb535 100644
--- a/src/libcharon/encoding/payloads/nonce_payload.c
+++ b/src/libcharon/encoding/payloads/nonce_payload.c
@@ -19,6 +19,7 @@
#include "nonce_payload.h"
+#include <daemon.h>
#include <encoding/payloads/encodings.h>
typedef struct private_nonce_payload_t private_nonce_payload_t;
@@ -57,6 +58,11 @@ struct private_nonce_payload_t {
* The contained nonce value.
*/
chunk_t nonce;
+
+ /**
+ * Payload type, NONCE or NONCE_V1
+ */
+ payload_type_t type;
};
/**
@@ -65,7 +71,7 @@ struct private_nonce_payload_t {
* The defined offsets are the positions in a object of type
* private_nonce_payload_t.
*/
-encoding_rule_t nonce_payload_encodings[] = {
+static encoding_rule_t encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_nonce_payload_t, next_payload) },
/* the critical bit */
@@ -81,7 +87,7 @@ encoding_rule_t nonce_payload_encodings[] = {
/* Length of the whole nonce payload*/
{ PAYLOAD_LENGTH, offsetof(private_nonce_payload_t, payload_length) },
/* some nonce bytes, lenth is defined in PAYLOAD_LENGTH */
- { NONCE_DATA, offsetof(private_nonce_payload_t, nonce) },
+ { CHUNK_DATA, offsetof(private_nonce_payload_t, nonce) },
};
/* 1 2 3
@@ -98,24 +104,48 @@ encoding_rule_t nonce_payload_encodings[] = {
METHOD(payload_t, verify, status_t,
private_nonce_payload_t *this)
{
- if (this->nonce.len < 16 || this->nonce.len > 256)
+ bool bad_length = FALSE;
+
+ if (this->nonce.len > 256)
+ {
+ bad_length = TRUE;
+ }
+ if (this->type == NONCE &&
+ this->nonce.len < 16)
+ {
+ bad_length = TRUE;
+ }
+ if (this->type == NONCE_V1 &&
+ this->nonce.len < 8)
+ {
+ bad_length = TRUE;
+ }
+ if (bad_length)
{
+ DBG1(DBG_ENC, "%N payload has invalid length (%d bytes)",
+ payload_type_names, this->type, this->nonce.len);
return FAILED;
}
return SUCCESS;
}
-METHOD(payload_t, get_encoding_rules, void,
- private_nonce_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, int,
+ private_nonce_payload_t *this, encoding_rule_t **rules)
+{
+ *rules = encodings;
+ return countof(encodings);
+}
+
+METHOD(payload_t, get_header_length, int,
+ private_nonce_payload_t *this)
{
- *rules = nonce_payload_encodings;
- *rule_count = countof(nonce_payload_encodings);
+ return 4;
}
METHOD(payload_t, get_type, payload_type_t,
private_nonce_payload_t *this)
{
- return NONCE;
+ return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
@@ -140,7 +170,7 @@ METHOD(nonce_payload_t, set_nonce, void,
private_nonce_payload_t *this, chunk_t nonce)
{
this->nonce = chunk_clone(nonce);
- this->payload_length = NONCE_PAYLOAD_HEADER_LENGTH + nonce.len;
+ this->payload_length = get_header_length(this) + nonce.len;
}
METHOD(nonce_payload_t, get_nonce, chunk_t,
@@ -159,7 +189,7 @@ METHOD2(payload_t, nonce_payload_t, destroy, void,
/*
* Described in header
*/
-nonce_payload_t *nonce_payload_create()
+nonce_payload_t *nonce_payload_create(payload_type_t type)
{
private_nonce_payload_t *this;
@@ -168,6 +198,7 @@ nonce_payload_t *nonce_payload_create()
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
+ .get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@@ -179,7 +210,8 @@ nonce_payload_t *nonce_payload_create()
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
- .payload_length = NONCE_PAYLOAD_HEADER_LENGTH,
+ .payload_length = get_header_length(this),
+ .type = type,
);
return &this->public;
}
diff --git a/src/libcharon/encoding/payloads/nonce_payload.h b/src/libcharon/encoding/payloads/nonce_payload.h
index e9212202e..5c47f5f9f 100644
--- a/src/libcharon/encoding/payloads/nonce_payload.h
+++ b/src/libcharon/encoding/payloads/nonce_payload.h
@@ -33,14 +33,7 @@ typedef struct nonce_payload_t nonce_payload_t;
#define NONCE_SIZE 32
/**
- * Length of a nonce payload without a nonce in bytes.
- */
-#define NONCE_PAYLOAD_HEADER_LENGTH 4
-
-/**
- * Object representing an IKEv2 Nonce payload.
- *
- * The Nonce payload format is described in RFC section 3.3.
+ * Object representing an IKEv1/IKEv2 Nonce payload.
*/
struct nonce_payload_t {
/**
@@ -71,8 +64,9 @@ struct nonce_payload_t {
/**
* Creates an empty nonce_payload_t object
*
- * @return nonce_payload_t object
+ * @param type NONCE or NONCE_V1
+ * @return nonce_payload_t object
*/
-nonce_payload_t *nonce_payload_create(void);
+nonce_payload_t *nonce_payload_create(payload_type_t type);
#endif /** NONCE_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/notify_payload.c b/src/libcharon/encoding/payloads/notify_payload.c
index e03d1af67..d168e1c12 100644
--- a/src/libcharon/encoding/payloads/notify_payload.c
+++ b/src/libcharon/encoding/payloads/notify_payload.c
@@ -36,11 +36,18 @@ ENUM_NEXT(notify_type_names, INVALID_MESSAGE_ID, INVALID_MESSAGE_ID, INVALID_SYN
"INVALID_MESSAGE_ID");
ENUM_NEXT(notify_type_names, INVALID_SPI, INVALID_SPI, INVALID_MESSAGE_ID,
"INVALID_SPI");
-ENUM_NEXT(notify_type_names, NO_PROPOSAL_CHOSEN, NO_PROPOSAL_CHOSEN, INVALID_SPI,
+ENUM_NEXT(notify_type_names, ATTRIBUTES_NOT_SUPPORTED, NO_PROPOSAL_CHOSEN, INVALID_SPI,
+ "ATTRIBUTES_NOT_SUPPORTED",
"NO_PROPOSAL_CHOSEN");
-ENUM_NEXT(notify_type_names, INVALID_KE_PAYLOAD, INVALID_KE_PAYLOAD, NO_PROPOSAL_CHOSEN,
- "INVALID_KE_PAYLOAD");
-ENUM_NEXT(notify_type_names, AUTHENTICATION_FAILED, AUTHENTICATION_FAILED, INVALID_KE_PAYLOAD,
+ENUM_NEXT(notify_type_names, PAYLOAD_MALFORMED, AUTHENTICATION_FAILED, NO_PROPOSAL_CHOSEN,
+ "PAYLOAD_MALFORMED",
+ "INVALID_KE_PAYLOAD",
+ "INVALID_ID_INFORMATION",
+ "INVALID_CERT_ENCODING",
+ "INVALID_CERTIFICATE",
+ "CERT_TYPE_UNSUPPORTED",
+ "INVALID_CERT_AUTHORITY",
+ "INVALID_HASH_INFORMATION",
"AUTHENTICATION_FAILED");
ENUM_NEXT(notify_type_names, SINGLE_PAIR_REQUIRED, CHILD_SA_NOT_FOUND, AUTHENTICATION_FAILED,
"SINGLE_PAIR_REQUIRED",
@@ -102,7 +109,14 @@ ENUM_NEXT(notify_type_names, INITIAL_CONTACT, PSK_CONFIRM, MS_NOTIFY_STATUS,
"SECURE PASSWORD_METHOD",
"PSK_PERSIST",
"PSK_CONFIRM");
-ENUM_NEXT(notify_type_names, USE_BEET_MODE, USE_BEET_MODE, PSK_CONFIRM,
+ENUM_NEXT(notify_type_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, PSK_CONFIRM,
+ "INITIAL_CONTACT");
+ENUM_NEXT(notify_type_names, DPD_R_U_THERE, DPD_R_U_THERE_ACK, INITIAL_CONTACT_IKEV1,
+ "DPD_R_U_THERE",
+ "DPD_R_U_THERE_ACK");
+ENUM_NEXT(notify_type_names, UNITY_LOAD_BALANCE, UNITY_LOAD_BALANCE, DPD_R_U_THERE_ACK,
+ "UNITY_LOAD_BALANCE");
+ENUM_NEXT(notify_type_names, USE_BEET_MODE, USE_BEET_MODE, UNITY_LOAD_BALANCE,
"USE_BEET_MODE");
ENUM_NEXT(notify_type_names, ME_MEDIATION, RADIUS_ATTRIBUTE, USE_BEET_MODE,
"ME_MEDIATION",
@@ -127,11 +141,18 @@ ENUM_NEXT(notify_type_short_names, INVALID_MESSAGE_ID, INVALID_MESSAGE_ID, INVAL
"INVAL_MID");
ENUM_NEXT(notify_type_short_names, INVALID_SPI, INVALID_SPI, INVALID_MESSAGE_ID,
"INVAL_SPI");
-ENUM_NEXT(notify_type_short_names, NO_PROPOSAL_CHOSEN, NO_PROPOSAL_CHOSEN, INVALID_SPI,
+ENUM_NEXT(notify_type_short_names, ATTRIBUTES_NOT_SUPPORTED, NO_PROPOSAL_CHOSEN, INVALID_SPI,
+ "ATTR_UNSUP",
"NO_PROP");
-ENUM_NEXT(notify_type_short_names, INVALID_KE_PAYLOAD, INVALID_KE_PAYLOAD, NO_PROPOSAL_CHOSEN,
- "INVAL_KE");
-ENUM_NEXT(notify_type_short_names, AUTHENTICATION_FAILED, AUTHENTICATION_FAILED, INVALID_KE_PAYLOAD,
+ENUM_NEXT(notify_type_short_names, PAYLOAD_MALFORMED, AUTHENTICATION_FAILED, NO_PROPOSAL_CHOSEN,
+ "PLD_MAL",
+ "INVAL_KE",
+ "INVAL_ID",
+ "INVAL_CERTEN",
+ "INVAL_CERT",
+ "CERT_UNSUP",
+ "INVAL_CA",
+ "INVAL_HASH",
"AUTH_FAILED");
ENUM_NEXT(notify_type_short_names, SINGLE_PAIR_REQUIRED, CHILD_SA_NOT_FOUND, AUTHENTICATION_FAILED,
"SINGLE_PAIR",
@@ -193,7 +214,14 @@ ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, PSK_CONFIRM, MS_NOTIFY_STATU
"SEC_PASSWD",
"PSK_PST",
"PSK_CFM");
-ENUM_NEXT(notify_type_short_names, USE_BEET_MODE, USE_BEET_MODE, PSK_CONFIRM,
+ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, PSK_CONFIRM,
+ "INITIAL_CONTACT");
+ENUM_NEXT(notify_type_short_names, DPD_R_U_THERE, DPD_R_U_THERE_ACK, INITIAL_CONTACT_IKEV1,
+ "DPD",
+ "DPD_ACK");
+ENUM_NEXT(notify_type_short_names, UNITY_LOAD_BALANCE, UNITY_LOAD_BALANCE, DPD_R_U_THERE_ACK,
+ "UNITY_LB");
+ENUM_NEXT(notify_type_short_names, USE_BEET_MODE, USE_BEET_MODE, UNITY_LOAD_BALANCE,
"BEET_MODE");
ENUM_NEXT(notify_type_short_names, ME_MEDIATION, RADIUS_ATTRIBUTE, USE_BEET_MODE,
"ME_MED",
@@ -232,7 +260,7 @@ struct private_notify_payload_t {
/**
* reserved bits
*/
- bool reserved[7];
+ bool reserved[8];
/**
* Length of this payload.
@@ -240,6 +268,11 @@ struct private_notify_payload_t {
u_int16_t payload_length;
/**
+ * Domain of interpretation, IKEv1 only.
+ */
+ u_int32_t doi;
+
+ /**
* Protocol id.
*/
u_int8_t protocol_id;
@@ -262,40 +295,42 @@ struct private_notify_payload_t {
/**
* Notification data.
*/
- chunk_t notification_data;
+ chunk_t notify_data;
+
+ /**
+ * Type of payload, NOTIFY or NOTIFY_V1
+ */
+ payload_type_t type;
};
/**
- * Encoding rules to parse or generate a IKEv2-Notify Payload.
- *
- * The defined offsets are the positions in a object of type
- * private_notify_payload_t.
+ * Encoding rules for an IKEv2 notification payload
*/
-encoding_rule_t notify_payload_encodings[] = {
+static encoding_rule_t encodings_v2[] = {
/* 1 Byte next payload type, stored in the field next_payload */
- { U_INT_8, offsetof(private_notify_payload_t, next_payload) },
+ { U_INT_8, offsetof(private_notify_payload_t, next_payload) },
/* the critical bit */
- { FLAG, offsetof(private_notify_payload_t, critical) },
+ { FLAG, offsetof(private_notify_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
- { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[0]) },
- { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[1]) },
- { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[2]) },
- { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[3]) },
- { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[4]) },
- { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[5]) },
- { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[6]) },
+ { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[0]) },
+ { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[1]) },
+ { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[2]) },
+ { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[3]) },
+ { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[4]) },
+ { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[5]) },
+ { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[6]) },
/* Length of the whole payload*/
- { PAYLOAD_LENGTH, offsetof(private_notify_payload_t, payload_length) },
+ { PAYLOAD_LENGTH, offsetof(private_notify_payload_t, payload_length) },
/* Protocol ID as 8 bit field*/
- { U_INT_8, offsetof(private_notify_payload_t, protocol_id) },
+ { U_INT_8, offsetof(private_notify_payload_t, protocol_id) },
/* SPI Size as 8 bit field*/
- { SPI_SIZE, offsetof(private_notify_payload_t, spi_size) },
+ { SPI_SIZE, offsetof(private_notify_payload_t, spi_size) },
/* Notify message type as 16 bit field*/
- { U_INT_16, offsetof(private_notify_payload_t, notify_type) },
+ { U_INT_16, offsetof(private_notify_payload_t, notify_type) },
/* SPI as variable length field*/
- { SPI, offsetof(private_notify_payload_t, spi) },
+ { SPI, offsetof(private_notify_payload_t, spi) },
/* Key Exchange Data is from variable size */
- { NOTIFICATION_DATA,offsetof(private_notify_payload_t, notification_data) }
+ { CHUNK_DATA, offsetof(private_notify_payload_t, notify_data) },
};
/*
@@ -315,6 +350,57 @@ encoding_rule_t notify_payload_encodings[] = {
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
+/**
+ * Encoding rules for an IKEv1 notification payload
+ */
+static encoding_rule_t encodings_v1[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_notify_payload_t, next_payload) },
+ /* 8 reserved bits */
+ { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[0]) },
+ { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[1]) },
+ { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[2]) },
+ { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[3]) },
+ { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[4]) },
+ { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[5]) },
+ { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[6]) },
+ { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[7]) },
+ /* Length of the whole payload*/
+ { PAYLOAD_LENGTH, offsetof(private_notify_payload_t, payload_length) },
+ /* DOI as 32 bit field*/
+ { U_INT_32, offsetof(private_notify_payload_t, doi) },
+ /* Protocol ID as 8 bit field*/
+ { U_INT_8, offsetof(private_notify_payload_t, protocol_id) },
+ /* SPI Size as 8 bit field*/
+ { SPI_SIZE, offsetof(private_notify_payload_t, spi_size) },
+ /* Notify message type as 16 bit field*/
+ { U_INT_16, offsetof(private_notify_payload_t, notify_type) },
+ /* SPI as variable length field*/
+ { SPI, offsetof(private_notify_payload_t, spi) },
+ /* Key Exchange Data is from variable size */
+ { CHUNK_DATA, offsetof(private_notify_payload_t, notify_data) },
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload ! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! DOI !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Protocol ID ! SPI Size ! Notify Message Type !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Security Parameter Index (SPI) ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Notification Data ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
METHOD(payload_t, verify, status_t,
private_notify_payload_t *this)
@@ -337,7 +423,7 @@ METHOD(payload_t, verify, status_t,
{
case INVALID_KE_PAYLOAD:
{
- if (this->notification_data.len != 2)
+ if (this->type == NOTIFY && this->notify_data.len != 2)
{
bad_length = TRUE;
}
@@ -347,7 +433,7 @@ METHOD(payload_t, verify, status_t,
case NAT_DETECTION_DESTINATION_IP:
case ME_CONNECTAUTH:
{
- if (this->notification_data.len != HASH_SIZE_SHA1)
+ if (this->notify_data.len != HASH_SIZE_SHA1)
{
bad_length = TRUE;
}
@@ -357,7 +443,7 @@ METHOD(payload_t, verify, status_t,
case INVALID_MAJOR_VERSION:
case NO_PROPOSAL_CHOSEN:
{
- if (this->notification_data.len != 0)
+ if (this->type == NOTIFY && this->notify_data.len != 0)
{
bad_length = TRUE;
}
@@ -365,7 +451,7 @@ METHOD(payload_t, verify, status_t,
}
case ADDITIONAL_IP4_ADDRESS:
{
- if (this->notification_data.len != 4)
+ if (this->notify_data.len != 4)
{
bad_length = TRUE;
}
@@ -373,7 +459,7 @@ METHOD(payload_t, verify, status_t,
}
case ADDITIONAL_IP6_ADDRESS:
{
- if (this->notification_data.len != 16)
+ if (this->notify_data.len != 16)
{
bad_length = TRUE;
}
@@ -381,7 +467,7 @@ METHOD(payload_t, verify, status_t,
}
case AUTH_LIFETIME:
{
- if (this->notification_data.len != 4)
+ if (this->notify_data.len != 4)
{
bad_length = TRUE;
}
@@ -389,30 +475,37 @@ METHOD(payload_t, verify, status_t,
}
case IPCOMP_SUPPORTED:
{
- if (this->notification_data.len != 3)
+ if (this->notify_data.len != 3)
{
bad_length = TRUE;
}
break;
}
case ME_ENDPOINT:
- if (this->notification_data.len != 8 &&
- this->notification_data.len != 12 &&
- this->notification_data.len != 24)
+ if (this->notify_data.len != 8 &&
+ this->notify_data.len != 12 &&
+ this->notify_data.len != 24)
{
bad_length = TRUE;
}
break;
case ME_CONNECTID:
- if (this->notification_data.len < 4 ||
- this->notification_data.len > 16)
+ if (this->notify_data.len < 4 ||
+ this->notify_data.len > 16)
{
bad_length = TRUE;
}
break;
case ME_CONNECTKEY:
- if (this->notification_data.len < 16 ||
- this->notification_data.len > 32)
+ if (this->notify_data.len < 16 ||
+ this->notify_data.len > 32)
+ {
+ bad_length = TRUE;
+ }
+ break;
+ case DPD_R_U_THERE:
+ case DPD_R_U_THERE_ACK:
+ if (this->notify_data.len != 4)
{
bad_length = TRUE;
}
@@ -425,23 +518,38 @@ METHOD(payload_t, verify, status_t,
{
DBG1(DBG_ENC, "invalid notify data length for %N (%d)",
notify_type_names, this->notify_type,
- this->notification_data.len);
+ this->notify_data.len);
return FAILED;
}
return SUCCESS;
}
-METHOD(payload_t, get_encoding_rules, void,
- private_notify_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, int,
+ private_notify_payload_t *this, encoding_rule_t **rules)
+{
+ if (this->type == NOTIFY)
+ {
+ *rules = encodings_v2;
+ return countof(encodings_v2);
+ }
+ *rules = encodings_v1;
+ return countof(encodings_v1);
+}
+
+METHOD(payload_t, get_header_length, int,
+ private_notify_payload_t *this)
{
- *rules = notify_payload_encodings;
- *rule_count = countof(notify_payload_encodings);
+ if (this->type == NOTIFY)
+ {
+ return 8 + this->spi_size;
+ }
+ return 12 + this->spi_size;
}
METHOD(payload_t, get_type, payload_type_t,
private_notify_payload_t *this)
{
- return NOTIFY;
+ return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
@@ -459,19 +567,9 @@ METHOD(payload_t, set_next_type, void,
/**
* recompute the payloads length.
*/
-static void compute_length (private_notify_payload_t *this)
+static void compute_length(private_notify_payload_t *this)
{
- size_t length = NOTIFY_PAYLOAD_HEADER_LENGTH;
-
- if (this->notification_data.ptr != NULL)
- {
- length += this->notification_data.len;
- }
- if (this->spi.ptr != NULL)
- {
- length += this->spi.len;
- }
- this->payload_length = length;
+ this->payload_length = get_header_length(this) + this->notify_data.len;
}
METHOD(payload_t, get_length, size_t,
@@ -539,24 +637,55 @@ METHOD(notify_payload_t, set_spi, void,
compute_length(this);
}
+METHOD(notify_payload_t, get_spi_data, chunk_t,
+ private_notify_payload_t *this)
+{
+ switch (this->protocol_id)
+ {
+ case PROTO_IKE:
+ if (this->spi.len == 16)
+ {
+ return this->spi;
+ }
+ default:
+ break;
+ }
+ return chunk_empty;
+}
+
+METHOD(notify_payload_t, set_spi_data, void,
+ private_notify_payload_t *this, chunk_t spi)
+{
+ chunk_free(&this->spi);
+ switch (this->protocol_id)
+ {
+ case PROTO_IKE:
+ this->spi = chunk_clone(spi);
+ default:
+ break;
+ }
+ this->spi_size = this->spi.len;
+ compute_length(this);
+}
+
METHOD(notify_payload_t, get_notification_data, chunk_t,
private_notify_payload_t *this)
{
- return this->notification_data;
+ return this->notify_data;
}
METHOD(notify_payload_t, set_notification_data, void,
private_notify_payload_t *this, chunk_t data)
{
- free(this->notification_data.ptr);
- this->notification_data = chunk_clone(data);
+ free(this->notify_data.ptr);
+ this->notify_data = chunk_clone(data);
compute_length(this);
}
METHOD2(payload_t, notify_payload_t, destroy, void,
private_notify_payload_t *this)
{
- free(this->notification_data.ptr);
+ free(this->notify_data.ptr);
free(this->spi.ptr);
free(this);
}
@@ -564,7 +693,7 @@ METHOD2(payload_t, notify_payload_t, destroy, void,
/*
* Described in header
*/
-notify_payload_t *notify_payload_create()
+notify_payload_t *notify_payload_create(payload_type_t type)
{
private_notify_payload_t *this;
@@ -573,6 +702,7 @@ notify_payload_t *notify_payload_create()
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
+ .get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@@ -585,13 +715,17 @@ notify_payload_t *notify_payload_create()
.set_notify_type = _set_notify_type,
.get_spi = _get_spi,
.set_spi = _set_spi,
+ .get_spi_data = _get_spi_data,
+ .set_spi_data = _set_spi_data,
.get_notification_data = _get_notification_data,
.set_notification_data = _set_notification_data,
.destroy = _destroy,
},
+ .doi = IKEV1_DOI_IPSEC,
.next_payload = NO_PAYLOAD,
- .payload_length = NOTIFY_PAYLOAD_HEADER_LENGTH,
+ .type = type,
);
+ compute_length(this);
return &this->public;
}
@@ -599,12 +733,12 @@ notify_payload_t *notify_payload_create()
* Described in header.
*/
notify_payload_t *notify_payload_create_from_protocol_and_type(
- protocol_id_t protocol_id, notify_type_t notify_type)
+ payload_type_t type, protocol_id_t protocol, notify_type_t notify)
{
- notify_payload_t *notify = notify_payload_create();
+ notify_payload_t *this = notify_payload_create(type);
- notify->set_notify_type(notify, notify_type);
- notify->set_protocol_id(notify, protocol_id);
+ this->set_notify_type(this, notify);
+ this->set_protocol_id(this, protocol);
- return notify;
+ return this;
}
diff --git a/src/libcharon/encoding/payloads/notify_payload.h b/src/libcharon/encoding/payloads/notify_payload.h
index ced282700..beec1e233 100644
--- a/src/libcharon/encoding/payloads/notify_payload.h
+++ b/src/libcharon/encoding/payloads/notify_payload.h
@@ -33,25 +33,36 @@ typedef struct notify_payload_t notify_payload_t;
#include <utils/linked_list.h>
/**
- * Notify payload length in bytes without any spi and notification data.
- */
-#define NOTIFY_PAYLOAD_HEADER_LENGTH 8
-
-/**
- * Notify message types.
- *
- * See IKEv2 RFC 3.10.1.
+ * Notify message types for IKEv2, and a subset for IKEv1.
*/
enum notify_type_t {
/* notify error messages */
UNSUPPORTED_CRITICAL_PAYLOAD = 1,
+ /* IKEv1 alias */
+ INVALID_PAYLOAD_TYPE = 1,
INVALID_IKE_SPI = 4,
INVALID_MAJOR_VERSION = 5,
INVALID_SYNTAX = 7,
+ /* IKEv1 alias */
+ INVALID_EXCHANGE_TYPE = 7,
INVALID_MESSAGE_ID = 9,
INVALID_SPI = 11,
+ /* IKEv1 only */
+ ATTRIBUTES_NOT_SUPPORTED = 13,
+ /* IKEv1 alias */
NO_PROPOSAL_CHOSEN = 14,
+ /* IKEv1 only */
+ PAYLOAD_MALFORMED = 16,
INVALID_KE_PAYLOAD = 17,
+ /* IKEv1 alias */
+ INVALID_KEY_INFORMATION = 17,
+ /* IKEv1 only */
+ INVALID_ID_INFORMATION = 18,
+ INVALID_CERT_ENCODING = 19,
+ INVALID_CERTIFICATE = 20,
+ CERT_TYPE_UNSUPPORTED = 21,
+ INVALID_CERT_AUTHORITY = 22,
+ INVALID_HASH_INFORMATION = 23,
AUTHENTICATION_FAILED = 24,
SINGLE_PAIR_REQUIRED = 34,
NO_ADDITIONAL_SAS = 35,
@@ -132,6 +143,13 @@ enum notify_type_t {
/* PACE - draft-kuegler-ipsecme-pace-ikev2 */
PSK_PERSIST = 16425,
PSK_CONFIRM = 16426,
+ /* IKEv1 initial contact */
+ INITIAL_CONTACT_IKEV1 = 24578,
+ /* IKEv1 DPD */
+ DPD_R_U_THERE = 36136,
+ DPD_R_U_THERE_ACK = 36137,
+ /* IKEv1 Cisco High Availability */
+ UNITY_LOAD_BALANCE = 40501,
/* BEET mode, not even a draft yet. private use */
USE_BEET_MODE = 40961,
/* IKE-ME, private use */
@@ -214,6 +232,24 @@ struct notify_payload_t {
void (*set_spi) (notify_payload_t *this, u_int32_t spi);
/**
+ * Returns the currently set spi of this payload.
+ *
+ * This is only valid for notifys with protocol ISAKMP
+ *
+ * @return SPI value
+ */
+ chunk_t (*get_spi_data) (notify_payload_t *this);
+
+ /**
+ * Sets the spi of this payload.
+ *
+ * This is only valid for notifys with protocol ISAKMP
+ *
+ * @param spi SPI value
+ */
+ void (*set_spi_data) (notify_payload_t *this, chunk_t spi);
+
+ /**
* Returns the currently set notification data of payload.
*
* Returned data are not copied.
@@ -241,18 +277,20 @@ struct notify_payload_t {
/**
* Creates an empty notify_payload_t object
*
+ * @param type payload type, NOTIFY or NOTIFY_V1
* @return created notify_payload_t object
*/
-notify_payload_t *notify_payload_create(void);
+notify_payload_t *notify_payload_create(payload_type_t type);
/**
* Creates an notify_payload_t object of specific type for specific protocol id.
*
- * @param protocol_id protocol id (IKE, AH or ESP)
- * @param type notify type (see notify_type_t)
+ * @param type payload type, NOTIFY or NOTIFY_V1
+ * @param protocol protocol id (IKE, AH or ESP)
+ * @param notify type of notify
* @return notify_payload_t object
*/
notify_payload_t *notify_payload_create_from_protocol_and_type(
- protocol_id_t protocol_id, notify_type_t type);
+ payload_type_t type, protocol_id_t protocol, notify_type_t notify);
#endif /** NOTIFY_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/payload.c b/src/libcharon/encoding/payloads/payload.c
index a2c0a4385..dc158476b 100644
--- a/src/libcharon/encoding/payloads/payload.c
+++ b/src/libcharon/encoding/payloads/payload.c
@@ -20,6 +20,7 @@
#include <encoding/payloads/ike_header.h>
#include <encoding/payloads/sa_payload.h>
+
#include <encoding/payloads/nonce_payload.h>
#include <encoding/payloads/id_payload.h>
#include <encoding/payloads/ke_payload.h>
@@ -34,13 +35,30 @@
#include <encoding/payloads/cp_payload.h>
#include <encoding/payloads/configuration_attribute.h>
#include <encoding/payloads/eap_payload.h>
+#include <encoding/payloads/hash_payload.h>
#include <encoding/payloads/unknown_payload.h>
-
ENUM_BEGIN(payload_type_names, NO_PAYLOAD, NO_PAYLOAD,
"NO_PAYLOAD");
-ENUM_NEXT(payload_type_names, SECURITY_ASSOCIATION,
- GENERIC_SECURE_PASSWORD_METHOD, NO_PAYLOAD,
+ENUM_NEXT(payload_type_names, SECURITY_ASSOCIATION_V1, CONFIGURATION_V1, NO_PAYLOAD,
+ "SECURITY_ASSOCIATION_V1",
+ "PROPOSAL_V1",
+ "TRANSFORM_V1",
+ "KEY_EXCHANGE_V1",
+ "ID_V1",
+ "CERTIFICATE_V1",
+ "CERTIFICATE_REQUEST_V1",
+ "HASH_V1",
+ "SIGNATURE_V1",
+ "NONCE_V1",
+ "NOTIFY_V1",
+ "DELETE_V1",
+ "VENDOR_ID_V1",
+ "CONFIGURATION_V1");
+ENUM_NEXT(payload_type_names, NAT_D_V1, NAT_OA_V1, CONFIGURATION_V1,
+ "NAT_D_V1",
+ "NAT_OA_V1");
+ENUM_NEXT(payload_type_names, SECURITY_ASSOCIATION, GENERIC_SECURE_PASSWORD_METHOD, NAT_OA_V1,
"SECURITY_ASSOCIATION",
"KEY_EXCHANGE",
"ID_INITIATOR",
@@ -61,30 +79,56 @@ ENUM_NEXT(payload_type_names, SECURITY_ASSOCIATION,
#ifdef ME
ENUM_NEXT(payload_type_names, ID_PEER, ID_PEER, GENERIC_SECURE_PASSWORD_METHOD,
"ID_PEER");
-ENUM_NEXT(payload_type_names, HEADER, CONFIGURATION_ATTRIBUTE, ID_PEER,
+ENUM_NEXT(payload_type_names, HEADER, ENCRYPTED_V1, ID_PEER,
"HEADER",
"PROPOSAL_SUBSTRUCTURE",
+ "PROPOSAL_SUBSTRUCTURE_V1",
"TRANSFORM_SUBSTRUCTURE",
+ "TRANSFORM_SUBSTRUCTURE_V1",
"TRANSFORM_ATTRIBUTE",
+ "TRANSFORM_ATTRIBUTE_V1",
"TRAFFIC_SELECTOR_SUBSTRUCTURE",
- "CONFIGURATION_ATTRIBUTE");
+ "CONFIGURATION_ATTRIBUTE",
+ "CONFIGURATION_ATTRIBUTE_V1",
+ "ENCRYPTED_V1");
#else
-ENUM_NEXT(payload_type_names, HEADER, CONFIGURATION_ATTRIBUTE,
- GENERIC_SECURE_PASSWORD_METHOD,
+ENUM_NEXT(payload_type_names, HEADER, ENCRYPTED_V1, GENERIC_SECURE_PASSWORD_METHOD,
"HEADER",
"PROPOSAL_SUBSTRUCTURE",
+ "PROPOSAL_SUBSTRUCTURE_V1",
"TRANSFORM_SUBSTRUCTURE",
+ "TRANSFORM_SUBSTRUCTURE_V1",
"TRANSFORM_ATTRIBUTE",
+ "TRANSFORM_ATTRIBUTE_V1",
"TRAFFIC_SELECTOR_SUBSTRUCTURE",
- "CONFIGURATION_ATTRIBUTE");
+ "CONFIGURATION_ATTRIBUTE",
+ "CONFIGURATION_ATTRIBUTE_V1",
+ "ENCRYPTED_V1");
#endif /* ME */
-ENUM_END(payload_type_names, CONFIGURATION_ATTRIBUTE);
+ENUM_END(payload_type_names, ENCRYPTED_V1);
/* short forms of payload names */
ENUM_BEGIN(payload_type_short_names, NO_PAYLOAD, NO_PAYLOAD,
"--");
-ENUM_NEXT(payload_type_short_names, SECURITY_ASSOCIATION,
- GENERIC_SECURE_PASSWORD_METHOD, NO_PAYLOAD,
+ENUM_NEXT(payload_type_short_names, SECURITY_ASSOCIATION_V1, CONFIGURATION_V1, NO_PAYLOAD,
+ "SA",
+ "PROP",
+ "TRANS",
+ "KE",
+ "ID",
+ "CERT",
+ "CERTREQ",
+ "HASH",
+ "SIG",
+ "No",
+ "N",
+ "D",
+ "V",
+ "CP");
+ENUM_NEXT(payload_type_short_names, NAT_D_V1, NAT_OA_V1, CONFIGURATION_V1,
+ "NAT-D",
+ "NAT-OA");
+ENUM_NEXT(payload_type_short_names, SECURITY_ASSOCIATION, GENERIC_SECURE_PASSWORD_METHOD, NAT_OA_V1,
"SA",
"KE",
"IDi",
@@ -106,24 +150,33 @@ ENUM_NEXT(payload_type_short_names, SECURITY_ASSOCIATION,
ENUM_NEXT(payload_type_short_names, ID_PEER, ID_PEER,
GENERIC_SECURE_PASSWORD_METHOD,
"IDp");
-ENUM_NEXT(payload_type_short_names, HEADER, CONFIGURATION_ATTRIBUTE, ID_PEER,
+ENUM_NEXT(payload_type_short_names, HEADER, ENCRYPTED_V1, ID_PEER,
"HDR",
"PROP",
+ "PROP",
+ "TRANS",
"TRANS",
"TRANSATTR",
+ "TRANSATTR",
"TSSUB",
- "CPATTR");
+ "CATTR",
+ "CATTR",
+ "E");
#else
-ENUM_NEXT(payload_type_short_names, HEADER, CONFIGURATION_ATTRIBUTE,
- GENERIC_SECURE_PASSWORD_METHOD,
+ENUM_NEXT(payload_type_short_names, HEADER, ENCRYPTED_V1, GENERIC_SECURE_PASSWORD_METHOD,
"HDR",
"PROP",
+ "PROP",
+ "TRANS",
"TRANS",
"TRANSATTR",
+ "TRANSATTR",
"TSSUB",
- "CPATTR");
+ "CATTR",
+ "CATTR",
+ "E");
#endif /* ME */
-ENUM_END(payload_type_short_names, CONFIGURATION_ATTRIBUTE);
+ENUM_END(payload_type_short_names, ENCRYPTED_V1);
/*
* see header
@@ -135,29 +188,36 @@ payload_t *payload_create(payload_type_t type)
case HEADER:
return (payload_t*)ike_header_create();
case SECURITY_ASSOCIATION:
- return (payload_t*)sa_payload_create();
+ case SECURITY_ASSOCIATION_V1:
+ return (payload_t*)sa_payload_create(type);
case PROPOSAL_SUBSTRUCTURE:
- return (payload_t*)proposal_substructure_create();
+ case PROPOSAL_SUBSTRUCTURE_V1:
+ return (payload_t*)proposal_substructure_create(type);
case TRANSFORM_SUBSTRUCTURE:
- return (payload_t*)transform_substructure_create();
+ case TRANSFORM_SUBSTRUCTURE_V1:
+ return (payload_t*)transform_substructure_create(type);
case TRANSFORM_ATTRIBUTE:
- return (payload_t*)transform_attribute_create();
+ case TRANSFORM_ATTRIBUTE_V1:
+ return (payload_t*)transform_attribute_create(type);
case NONCE:
- return (payload_t*)nonce_payload_create();
+ case NONCE_V1:
+ return (payload_t*)nonce_payload_create(type);
case ID_INITIATOR:
- return (payload_t*)id_payload_create(ID_INITIATOR);
case ID_RESPONDER:
- return (payload_t*)id_payload_create(ID_RESPONDER);
+ case ID_V1:
+ case NAT_OA_V1:
#ifdef ME
case ID_PEER:
- return (payload_t*)id_payload_create(ID_PEER);
#endif /* ME */
+ return (payload_t*)id_payload_create(type);
case AUTHENTICATION:
return (payload_t*)auth_payload_create();
case CERTIFICATE:
- return (payload_t*)cert_payload_create();
+ case CERTIFICATE_V1:
+ return (payload_t*)cert_payload_create(type);
case CERTIFICATE_REQUEST:
- return (payload_t*)certreq_payload_create();
+ case CERTIFICATE_REQUEST_V1:
+ return (payload_t*)certreq_payload_create(type);
case TRAFFIC_SELECTOR_SUBSTRUCTURE:
return (payload_t*)traffic_selector_substructure_create();
case TRAFFIC_SELECTOR_INITIATOR:
@@ -165,21 +225,32 @@ payload_t *payload_create(payload_type_t type)
case TRAFFIC_SELECTOR_RESPONDER:
return (payload_t*)ts_payload_create(FALSE);
case KEY_EXCHANGE:
- return (payload_t*)ke_payload_create();
+ case KEY_EXCHANGE_V1:
+ return (payload_t*)ke_payload_create(type);
case NOTIFY:
- return (payload_t*)notify_payload_create();
+ case NOTIFY_V1:
+ return (payload_t*)notify_payload_create(type);
case DELETE:
- return (payload_t*)delete_payload_create(0);
+ case DELETE_V1:
+ return (payload_t*)delete_payload_create(type, 0);
case VENDOR_ID:
- return (payload_t*)vendor_id_payload_create();
+ case VENDOR_ID_V1:
+ return (payload_t*)vendor_id_payload_create(type);
+ case HASH_V1:
+ case SIGNATURE_V1:
+ case NAT_D_V1:
+ return (payload_t*)hash_payload_create(type);
case CONFIGURATION:
- return (payload_t*)cp_payload_create();
+ case CONFIGURATION_V1:
+ return (payload_t*)cp_payload_create(type);
case CONFIGURATION_ATTRIBUTE:
- return (payload_t*)configuration_attribute_create();
+ case CONFIGURATION_ATTRIBUTE_V1:
+ return (payload_t*)configuration_attribute_create(type);
case EXTENSIBLE_AUTHENTICATION:
return (payload_t*)eap_payload_create();
case ENCRYPTED:
- return (payload_t*)encryption_payload_create();
+ case ENCRYPTED_V1:
+ return (payload_t*)encryption_payload_create(type);
default:
return (payload_t*)unknown_payload_create(type);
}
@@ -190,8 +261,19 @@ payload_t *payload_create(payload_type_t type)
*/
bool payload_is_known(payload_type_t type)
{
- if (type == HEADER ||
- (type >= SECURITY_ASSOCIATION && type <= EXTENSIBLE_AUTHENTICATION))
+ if (type == HEADER)
+ {
+ return TRUE;
+ }
+ if (type >= SECURITY_ASSOCIATION && type <= EXTENSIBLE_AUTHENTICATION)
+ {
+ return TRUE;
+ }
+ if (type >= SECURITY_ASSOCIATION_V1 && type <= CONFIGURATION_V1)
+ {
+ return TRUE;
+ }
+ if (type >= NAT_D_V1 && type <= NAT_OA_V1)
{
return TRUE;
}
@@ -210,10 +292,9 @@ bool payload_is_known(payload_type_t type)
void* payload_get_field(payload_t *payload, encoding_type_t type, u_int skip)
{
encoding_rule_t *rule;
- size_t count;
- int i;
+ int i, count;
- payload->get_encoding_rules(payload, &rule, &count);
+ count = payload->get_encoding_rules(payload, &rule);
for (i = 0; i < count; i++)
{
if (rule[i].type == type && skip-- == 0)
diff --git a/src/libcharon/encoding/payloads/payload.h b/src/libcharon/encoding/payloads/payload.h
index a9af29b5b..d5e862601 100644
--- a/src/libcharon/encoding/payloads/payload.h
+++ b/src/libcharon/encoding/payloads/payload.h
@@ -29,14 +29,18 @@ typedef struct payload_t payload_t;
#include <library.h>
#include <encoding/payloads/encodings.h>
+/**
+ * Domain of interpretation used by IPsec/IKEv1
+ */
+#define IKEV1_DOI_IPSEC 1
/**
- * Payload-Types of a IKEv2-Message.
+ * Payload-Types of an IKE message.
*
* Header and substructures are also defined as
* payload types with values from PRIVATE USE space.
*/
-enum payload_type_t{
+enum payload_type_t {
/**
* End of payload list in next_payload
@@ -46,6 +50,86 @@ enum payload_type_t{
/**
* The security association (SA) payload containing proposals.
*/
+ SECURITY_ASSOCIATION_V1 = 1,
+
+ /**
+ * The proposal payload, containing transforms.
+ */
+ PROPOSAL_V1 = 2,
+
+ /**
+ * The transform payload.
+ */
+ TRANSFORM_V1 = 3,
+
+ /**
+ * The key exchange (KE) payload containing diffie-hellman values.
+ */
+ KEY_EXCHANGE_V1 = 4,
+
+ /**
+ * ID payload.
+ */
+ ID_V1 = 5,
+
+ /**
+ * Certificate payload with certificates (CERT).
+ */
+ CERTIFICATE_V1 = 6,
+
+ /**
+ * Certificate request payload.
+ */
+ CERTIFICATE_REQUEST_V1 = 7,
+
+ /**
+ * Hash payload.
+ */
+ HASH_V1 = 8,
+
+ /**
+ * Signature payload
+ */
+ SIGNATURE_V1 = 9,
+
+ /**
+ * Nonce payload.
+ */
+ NONCE_V1 = 10,
+
+ /**
+ * Notification payload.
+ */
+ NOTIFY_V1 = 11,
+
+ /**
+ * Delete payload.
+ */
+ DELETE_V1 = 12,
+
+ /**
+ * Vendor id payload.
+ */
+ VENDOR_ID_V1 = 13,
+
+ /**
+ * Attribute payload (ISAKMP Mode Config, aka configuration payload.
+ */
+ CONFIGURATION_V1 = 14,
+
+ /**
+ * NAT discovery payload (NAT-D).
+ */
+ NAT_D_V1 = 20,
+
+ /**
+ * NAT original address payload (NAT-OA)
+ */
+ NAT_OA_V1 = 21,
+
+ /**
+ * The security association (SA) payload containing proposals.
+ */
SECURITY_ASSOCIATION = 33,
/**
@@ -139,50 +223,60 @@ enum payload_type_t{
/**
* Header has a value of PRIVATE USE space.
*
- * This payload type is not sent over wire and just
- * used internally to handle IKEv2-Header like a payload.
+ * This type and all the following are never sent over wire and are
+ * used internally only.
*/
HEADER = 256,
/**
- * PROPOSAL_SUBSTRUCTURE has a value of PRIVATE USE space.
- *
- * This payload type is not sent over wire and just
- * used internally to handle a proposal substructure like a payload.
+ * PROPOSAL_SUBSTRUCTURE, IKEv2 proposals in a SA payload.
*/
- PROPOSAL_SUBSTRUCTURE = 257,
+ PROPOSAL_SUBSTRUCTURE,
/**
- * TRANSFORM_SUBSTRUCTURE has a value of PRIVATE USE space.
- *
- * This payload type is not sent over wire and just
- * used internally to handle a transform substructure like a payload.
+ * PROPOSAL_SUBSTRUCTURE_V1, IKEv1 proposals in a SA payload.
*/
- TRANSFORM_SUBSTRUCTURE = 258,
+ PROPOSAL_SUBSTRUCTURE_V1,
/**
- * TRANSFORM_ATTRIBUTE has a value of PRIVATE USE space.
- *
- * This payload type is not sent over wire and just
- * used internally to handle a transform attribute like a payload.
+ * TRANSFORM_SUBSTRUCTURE, IKEv2 transforms in a proposal substructure.
*/
- TRANSFORM_ATTRIBUTE = 259,
+ TRANSFORM_SUBSTRUCTURE,
/**
- * TRAFFIC_SELECTOR_SUBSTRUCTURE has a value of PRIVATE USE space.
- *
- * This payload type is not sent over wire and just
- * used internally to handle a transform selector like a payload.
+ * TRANSFORM_SUBSTRUCTURE_V1, IKEv1 transforms in a proposal substructure.
*/
- TRAFFIC_SELECTOR_SUBSTRUCTURE = 260,
+ TRANSFORM_SUBSTRUCTURE_V1,
/**
- * CONFIGURATION_ATTRIBUTE has a value of PRIVATE USE space.
- *
- * This payload type is not sent over wire and just
- * used internally to handle a transform attribute like a payload.
+ * TRANSFORM_ATTRIBUTE, IKEv2 attribute in a transform.
*/
- CONFIGURATION_ATTRIBUTE = 261,
+ TRANSFORM_ATTRIBUTE,
+
+ /**
+ * TRANSFORM_ATTRIBUTE_V1, IKEv1 attribute in a transform.
+ */
+ TRANSFORM_ATTRIBUTE_V1,
+
+ /**
+ * TRAFFIC_SELECTOR_SUBSTRUCTURE, traffic selector in a TS payload.
+ */
+ TRAFFIC_SELECTOR_SUBSTRUCTURE,
+
+ /**
+ * CONFIGURATION_ATTRIBUTE, IKEv2 attribute in a configuration payload.
+ */
+ CONFIGURATION_ATTRIBUTE,
+
+ /**
+ * CONFIGURATION_ATTRIBUTE_V1, IKEv1 attribute in a configuration payload.
+ */
+ CONFIGURATION_ATTRIBUTE_V1,
+
+ /**
+ * This is not really a payload, but rather the complete IKEv1 message.
+ */
+ ENCRYPTED_V1,
};
/**
@@ -207,43 +301,50 @@ struct payload_t {
/**
* Get encoding rules for this payload.
*
- * @param rules location to store pointer of first rule
- * @param rule_count location to store number of rules
+ * @param rules location to store pointer to rules
+ * @return number of rules
+ */
+ int (*get_encoding_rules) (payload_t *this, encoding_rule_t **rules);
+
+ /**
+ * Get non-variable header length for a variable length payload.
+ *
+ * @return fixed length of the payload
*/
- void (*get_encoding_rules) (payload_t *this, encoding_rule_t **rules, size_t *rule_count);
+ int (*get_header_length)(payload_t *this);
/**
* Get type of payload.
*
- * @return type of this payload
+ * @return type of this payload
*/
payload_type_t (*get_type) (payload_t *this);
/**
* Get type of next payload or NO_PAYLOAD (0) if this is the last one.
*
- * @return type of next payload
+ * @return type of next payload
*/
payload_type_t (*get_next_type) (payload_t *this);
/**
* Set type of next payload.
*
- * @param type type of next payload
+ * @param type type of next payload
*/
void (*set_next_type) (payload_t *this,payload_type_t type);
/**
* Get length of payload.
*
- * @return length of this payload
+ * @return length of this payload
*/
size_t (*get_length) (payload_t *this);
/**
* Verifies payload structure and makes consistence check.
*
- * @return SUCCESS, FAILED if consistence not given
+ * @return SUCCESS, FAILED if consistence not given
*/
status_t (*verify) (payload_t *this);
diff --git a/src/libcharon/encoding/payloads/proposal_substructure.c b/src/libcharon/encoding/payloads/proposal_substructure.c
index 4753d574d..653f51a46 100644
--- a/src/libcharon/encoding/payloads/proposal_substructure.c
+++ b/src/libcharon/encoding/payloads/proposal_substructure.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2005-2010 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -25,7 +26,7 @@
#include <daemon.h>
/**
- * IKEv1 Value for a proposal payload.
+ * IKEv2 Value for a proposal payload.
*/
#define PROPOSAL_TYPE_VALUE 2
@@ -84,16 +85,43 @@ struct private_proposal_substructure_t {
/**
* Transforms are stored in a linked_list_t.
*/
- linked_list_t * transforms;
+ linked_list_t *transforms;
+
+ /**
+ * Type of this payload, PROPOSAL_SUBSTRUCTURE or PROPOSAL_SUBSTRUCTURE_V1
+ */
+ payload_type_t type;
};
/**
- * Encoding rules to parse or generate a Proposal substructure.
- *
- * The defined offsets are the positions in a object of type
- * private_proposal_substructure_t.
+ * Encoding rules for a IKEv1 Proposal substructure.
+ */
+static encoding_rule_t encodings_v1[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_proposal_substructure_t, next_payload) },
+ /* 1 Reserved Byte */
+ { RESERVED_BYTE, offsetof(private_proposal_substructure_t, reserved) },
+ /* Length of the whole proposal substructure payload*/
+ { PAYLOAD_LENGTH, offsetof(private_proposal_substructure_t, proposal_length) },
+ /* proposal number is a number of 8 bit */
+ { U_INT_8, offsetof(private_proposal_substructure_t, proposal_number) },
+ /* protocol ID is a number of 8 bit */
+ { U_INT_8, offsetof(private_proposal_substructure_t, protocol_id) },
+ /* SPI Size has its own type */
+ { SPI_SIZE, offsetof(private_proposal_substructure_t, spi_size) },
+ /* Number of transforms is a number of 8 bit */
+ { U_INT_8, offsetof(private_proposal_substructure_t, transforms_count) },
+ /* SPI is a chunk of variable size*/
+ { SPI, offsetof(private_proposal_substructure_t, spi) },
+ /* Transforms are stored in a transform substructure list */
+ { PAYLOAD_LIST + TRANSFORM_SUBSTRUCTURE_V1,
+ offsetof(private_proposal_substructure_t, transforms) },
+};
+
+/**
+ * Encoding rules for a IKEv2 Proposal substructure.
*/
-encoding_rule_t proposal_substructure_encodings[] = {
+static encoding_rule_t encodings_v2[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_proposal_substructure_t, next_payload) },
/* 1 Reserved Byte */
@@ -110,9 +138,9 @@ encoding_rule_t proposal_substructure_encodings[] = {
{ U_INT_8, offsetof(private_proposal_substructure_t, transforms_count) },
/* SPI is a chunk of variable size*/
{ SPI, offsetof(private_proposal_substructure_t, spi) },
- /* Transforms are stored in a transform substructure,
- offset points to a linked_list_t pointer */
- { TRANSFORMS, offsetof(private_proposal_substructure_t, transforms) }
+ /* Transforms are stored in a transform substructure list */
+ { PAYLOAD_LIST + TRANSFORM_SUBSTRUCTURE,
+ offsetof(private_proposal_substructure_t, transforms) },
};
/*
@@ -131,6 +159,149 @@ encoding_rule_t proposal_substructure_encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
+/**
+ * Encryption.
+ */
+typedef enum {
+ IKEV1_ENCR_DES_CBC = 1,
+ IKEV1_ENCR_IDEA_CBC = 2,
+ IKEV1_ENCR_BLOWFISH_CBC = 3,
+ IKEV1_ENCR_RC5_R16_B64_CBC = 4,
+ IKEV1_ENCR_3DES_CBC = 5,
+ IKEV1_ENCR_CAST_CBC = 6,
+ IKEV1_ENCR_AES_CBC = 7,
+ IKEV1_ENCR_CAMELLIA_CBC = 8,
+ /* FreeS/WAN proprietary */
+ IKEV1_ENCR_SERPENT_CBC = 65004,
+ IKEV1_ENCR_TWOFISH_CBC = 65005,
+} ikev1_encryption_t;
+
+/**
+ * IKEv1 hash.
+ */
+typedef enum {
+ IKEV1_HASH_MD5 = 1,
+ IKEV1_HASH_SHA1 = 2,
+ IKEV1_HASH_TIGER = 3,
+ IKEV1_HASH_SHA2_256 = 4,
+ IKEV1_HASH_SHA2_384 = 5,
+ IKEV1_HASH_SHA2_512 = 6,
+} ikev1_hash_t;
+
+/**
+ * IKEv1 Transform ID IKE.
+ */
+typedef enum {
+ IKEV1_TRANSID_KEY_IKE = 1,
+} ikev1_ike_transid_t;
+
+/**
+ * IKEv1 Transform ID ESP encryption algorithm.
+ */
+typedef enum {
+ IKEV1_ESP_ENCR_DES_IV64 = 1,
+ IKEV1_ESP_ENCR_DES = 2,
+ IKEV1_ESP_ENCR_3DES = 3,
+ IKEV1_ESP_ENCR_RC5 = 4,
+ IKEV1_ESP_ENCR_IDEA = 5,
+ IKEV1_ESP_ENCR_CAST = 6,
+ IKEV1_ESP_ENCR_BLOWFISH = 7,
+ IKEV1_ESP_ENCR_3IDEA = 8,
+ IKEV1_ESP_ENCR_DES_IV32 = 9,
+ IKEV1_ESP_ENCR_RC4 = 10,
+ IKEV1_ESP_ENCR_NULL = 11,
+ IKEV1_ESP_ENCR_AES_CBC = 12,
+ IKEV1_ESP_ENCR_AES_CTR = 13,
+ IKEV1_ESP_ENCR_AES_CCM_8 = 14,
+ IKEV1_ESP_ENCR_AES_CCM_12 = 15,
+ IKEV1_ESP_ENCR_AES_CCM_16 = 16,
+ IKEV1_ESP_ENCR_AES_GCM_8 = 18,
+ IKEV1_ESP_ENCR_AES_GCM_12 = 19,
+ IKEV1_ESP_ENCR_AES_GCM_16 = 20,
+ IKEV1_ESP_ENCR_SEED_CBC = 21,
+ IKEV1_ESP_ENCR_CAMELLIA = 22,
+ IKEV1_ESP_ENCR_NULL_AUTH_AES_GMAC = 23,
+ /* FreeS/WAN proprietary */
+ IKEV1_ESP_ENCR_SERPENT = 252,
+ IKEV1_ESP_ENCR_TWOFISH = 253,
+} ikev1_esp_encr_transid_t;
+
+/**
+ * IKEv1 Transform ID ESP authentication algorithm.
+ */
+typedef enum {
+ IKEV1_ESP_AUTH_HMAC_MD5 = 1,
+ IKEV1_ESP_AUTH_HMAC_SHA = 2,
+ IKEV1_ESP_AUTH_DES_MAC = 3,
+ IKEV1_ESP_AUTH_KPDK = 4,
+ IKEV1_ESP_AUTH_HMAC_SHA2_256 = 5,
+ IKEV1_ESP_AUTH_HMAC_SHA2_384 = 6,
+ IKEV1_ESP_AUTH_HMAC_SHA2_512 = 7,
+ IKEV1_ESP_AUTH_HMAC_RIPEMD = 8,
+ IKEV1_ESP_AUTH_AES_XCBC_MAC = 9,
+ IKEV1_ESP_AUTH_SIG_RSA = 10,
+ IKEV1_ESP_AUTH_AES_128_GMAC = 11,
+ IKEV1_ESP_AUTH_AES_192_GMAC = 12,
+ IKEV1_ESP_AUTH_AES_256_GMAC = 13,
+} ikev1_esp_auth_transid_it;
+
+/**
+ * IKEv1 ESP Encapsulation mode.
+ */
+typedef enum {
+ IKEV1_ENCAP_TUNNEL = 1,
+ IKEV1_ENCAP_TRANSPORT = 2,
+ IKEV1_ENCAP_UDP_TUNNEL = 3,
+ IKEV1_ENCAP_UDP_TRANSPORT = 4,
+} ikev1_esp_encap_t;
+
+/**
+ * IKEv1 Life duration types.
+ */
+typedef enum {
+ IKEV1_LIFE_TYPE_SECONDS = 1,
+ IKEV1_LIFE_TYPE_KILOBYTES = 2,
+} ikev1_life_type_t;
+
+/**
+ * IKEv1 authentication methods
+ */
+typedef enum {
+ IKEV1_AUTH_PSK = 1,
+ IKEV1_AUTH_DSS_SIG = 2,
+ IKEV1_AUTH_RSA_SIG = 3,
+ IKEV1_AUTH_RSA_ENC = 4,
+ IKEV1_AUTH_RSA_ENC_REV = 5,
+ IKEV1_AUTH_ECDSA_256 = 9,
+ IKEV1_AUTH_ECDSA_384 = 10,
+ IKEV1_AUTH_ECDSA_521 = 11,
+ /* XAuth Modes */
+ IKEV1_AUTH_XAUTH_INIT_PSK = 65001,
+ IKEV1_AUTH_XAUTH_RESP_PSK = 65002,
+ IKEV1_AUTH_XAUTH_INIT_DSS = 65003,
+ IKEV1_AUTH_XAUTH_RESP_DSS = 65004,
+ IKEV1_AUTH_XAUTH_INIT_RSA = 65005,
+ IKEV1_AUTH_XAUTH_RESP_RSA = 65006,
+ IKEV1_AUTH_XAUTH_INIT_RSA_ENC = 65007,
+ IKEV1_AUTH_XAUTH_RESP_RSA_ENC = 65008,
+ IKEV1_AUTH_XAUTH_INIT_RSA_ENC_REV = 65009,
+ IKEV1_AUTH_XAUTH_RESP_RSA_ENC_REV = 65010,
+ /* Hybrid Modes */
+ IKEV1_AUTH_HYBRID_INIT_RSA = 64221,
+ IKEV1_AUTH_HYBRID_RESP_RSA = 64222,
+ IKEV1_AUTH_HYBRID_INIT_DSS = 64223,
+ IKEV1_AUTH_HYBRID_RESP_DSS = 64224,
+} ikev1_auth_method_t;
+
+/**
+ * IKEv1 IPComp transform IDs
+ */
+typedef enum {
+ IKEV1_IPCOMP_OUI = 1,
+ IKEV1_IPCOMP_DEFLATE = 2,
+ IKEV1_IPCOMP_LZS = 3,
+} ikev1_ipcomp_transform_t;
+
METHOD(payload_t, verify, status_t,
private_proposal_substructure_t *this)
{
@@ -153,12 +324,19 @@ METHOD(payload_t, verify, status_t,
switch (this->protocol_id)
{
+ case PROTO_IPCOMP:
+ if (this->spi.len != 2)
+ {
+ DBG1(DBG_ENC, "invalid CPI length in IPCOMP proposal");
+ return FAILED;
+ }
+ break;
case PROTO_AH:
case PROTO_ESP:
if (this->spi.len != 4)
{
DBG1(DBG_ENC, "invalid SPI length in %N proposal",
- protocol_id_names, this->protocol_id);
+ protocol_id_names, this->protocol_id);
return FAILED;
}
break;
@@ -188,18 +366,28 @@ METHOD(payload_t, verify, status_t,
return status;
}
-METHOD(payload_t, get_encoding_rules, void,
- private_proposal_substructure_t *this, encoding_rule_t **rules,
- size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, int,
+ private_proposal_substructure_t *this, encoding_rule_t **rules)
{
- *rules = proposal_substructure_encodings;
- *rule_count = countof(proposal_substructure_encodings);
+ if (this->type == PROPOSAL_SUBSTRUCTURE)
+ {
+ *rules = encodings_v2;
+ return countof(encodings_v2);
+ }
+ *rules = encodings_v1;
+ return countof(encodings_v1);
+}
+
+METHOD(payload_t, get_header_length, int,
+ private_proposal_substructure_t *this)
+{
+ return 8 + this->spi_size;
}
METHOD(payload_t, get_type, payload_type_t,
private_proposal_substructure_t *this)
{
- return PROPOSAL_SUBSTRUCTURE;
+ return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
@@ -222,7 +410,7 @@ static void compute_length(private_proposal_substructure_t *this)
payload_t *transform;
this->transforms_count = 0;
- this->proposal_length = PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH + this->spi.len;
+ this->proposal_length = get_header_length(this);
enumerator = this->transforms->create_enumerator(this->transforms);
while (enumerator->enumerate(enumerator, &transform))
{
@@ -301,45 +489,486 @@ METHOD(proposal_substructure_t, get_spi, chunk_t,
return this->spi;
}
-METHOD(proposal_substructure_t, get_proposal, proposal_t*,
- private_proposal_substructure_t *this)
+METHOD(proposal_substructure_t, get_cpi, bool,
+ private_proposal_substructure_t *this, u_int16_t *cpi)
{
- enumerator_t *enumerator;
+
transform_substructure_t *transform;
- proposal_t *proposal;
- u_int64_t spi;
+ enumerator_t *enumerator;
- proposal = proposal_create(this->protocol_id, this->proposal_number);
+ if (this->protocol_id != PROTO_IPCOMP)
+ {
+ return FALSE;
+ }
enumerator = this->transforms->create_enumerator(this->transforms);
while (enumerator->enumerate(enumerator, &transform))
{
- transform_type_t transform_type;
- u_int16_t transform_id;
- u_int16_t key_length = 0;
+ if (transform->get_transform_id(transform) == IKEV1_IPCOMP_DEFLATE)
+ {
+ if (cpi)
+ {
+ *cpi = *((u_int16_t*)this->spi.ptr);
+ }
+ enumerator->destroy(enumerator);
+ return TRUE;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return FALSE;
+}
- transform_type = transform->get_transform_type(transform);
- transform_id = transform->get_transform_id(transform);
- transform->get_key_length(transform, &key_length);
+/**
+ * Add a transform to a proposal for IKEv2
+ */
+static void add_to_proposal_v2(proposal_t *proposal,
+ transform_substructure_t *transform)
+{
+ transform_attribute_t *tattr;
+ enumerator_t *enumerator;
+ u_int16_t key_length = 0;
- proposal->add_algorithm(proposal, transform_type, transform_id, key_length);
+ enumerator = transform->create_attribute_enumerator(transform);
+ while (enumerator->enumerate(enumerator, &tattr))
+ {
+ if (tattr->get_attribute_type(tattr) == TATTR_IKEV2_KEY_LENGTH)
+ {
+ key_length = tattr->get_value(tattr);
+ break;
+ }
}
enumerator->destroy(enumerator);
+ proposal->add_algorithm(proposal,
+ transform->get_transform_type_or_number(transform),
+ transform->get_transform_id(transform), key_length);
+}
+
+/**
+ * Map IKEv1 to IKEv2 algorithms
+ */
+typedef struct {
+ u_int16_t ikev1;
+ u_int16_t ikev2;
+} algo_map_t;
+
+/**
+ * Encryption algorithm mapping
+ */
+static algo_map_t map_encr[] = {
+ { IKEV1_ENCR_DES_CBC, ENCR_DES },
+ { IKEV1_ENCR_IDEA_CBC, ENCR_IDEA },
+ { IKEV1_ENCR_BLOWFISH_CBC, ENCR_BLOWFISH },
+ { IKEV1_ENCR_3DES_CBC, ENCR_3DES },
+ { IKEV1_ENCR_CAST_CBC, ENCR_CAST },
+ { IKEV1_ENCR_AES_CBC, ENCR_AES_CBC },
+ { IKEV1_ENCR_CAMELLIA_CBC, ENCR_CAMELLIA_CBC },
+ { IKEV1_ENCR_SERPENT_CBC, ENCR_SERPENT_CBC },
+ { IKEV1_ENCR_TWOFISH_CBC, ENCR_TWOFISH_CBC },
+};
+
+/**
+ * Integrity algorithm mapping
+ */
+static algo_map_t map_integ[] = {
+ { IKEV1_HASH_MD5, AUTH_HMAC_MD5_96 },
+ { IKEV1_HASH_SHA1, AUTH_HMAC_SHA1_96 },
+ { IKEV1_HASH_SHA2_256, AUTH_HMAC_SHA2_256_128 },
+ { IKEV1_HASH_SHA2_384, AUTH_HMAC_SHA2_384_192 },
+ { IKEV1_HASH_SHA2_512, AUTH_HMAC_SHA2_512_256 },
+};
+
+/**
+ * PRF algorithm mapping
+ */
+static algo_map_t map_prf[] = {
+ { IKEV1_HASH_MD5, PRF_HMAC_MD5 },
+ { IKEV1_HASH_SHA1, PRF_HMAC_SHA1 },
+ { IKEV1_HASH_SHA2_256, PRF_HMAC_SHA2_256 },
+ { IKEV1_HASH_SHA2_384, PRF_HMAC_SHA2_384 },
+ { IKEV1_HASH_SHA2_512, PRF_HMAC_SHA2_512 },
+};
+
+/**
+ * ESP encryption algorithm mapping
+ */
+static algo_map_t map_esp_encr[] = {
+ { IKEV1_ESP_ENCR_DES_IV64, ENCR_DES_IV64 },
+ { IKEV1_ESP_ENCR_DES, ENCR_DES },
+ { IKEV1_ESP_ENCR_3DES, ENCR_3DES },
+ { IKEV1_ESP_ENCR_RC5, ENCR_RC5 },
+ { IKEV1_ESP_ENCR_IDEA, ENCR_IDEA },
+ { IKEV1_ESP_ENCR_CAST, ENCR_CAST },
+ { IKEV1_ESP_ENCR_BLOWFISH, ENCR_BLOWFISH },
+ { IKEV1_ESP_ENCR_3IDEA, ENCR_3IDEA },
+ { IKEV1_ESP_ENCR_DES_IV32, ENCR_DES_IV32 },
+ { IKEV1_ESP_ENCR_NULL, ENCR_NULL },
+ { IKEV1_ESP_ENCR_AES_CBC, ENCR_AES_CBC },
+ { IKEV1_ESP_ENCR_AES_CTR, ENCR_AES_CTR },
+ { IKEV1_ESP_ENCR_AES_CCM_8, ENCR_AES_CCM_ICV8 },
+ { IKEV1_ESP_ENCR_AES_CCM_12, ENCR_AES_CCM_ICV12 },
+ { IKEV1_ESP_ENCR_AES_CCM_16, ENCR_AES_CCM_ICV16 },
+ { IKEV1_ESP_ENCR_AES_GCM_8, ENCR_AES_GCM_ICV8 },
+ { IKEV1_ESP_ENCR_AES_GCM_12, ENCR_AES_GCM_ICV12 },
+ { IKEV1_ESP_ENCR_AES_GCM_16, ENCR_AES_GCM_ICV16 },
+ { IKEV1_ESP_ENCR_CAMELLIA, ENCR_CAMELLIA_CBC },
+ { IKEV1_ESP_ENCR_NULL_AUTH_AES_GMAC, ENCR_NULL_AUTH_AES_GMAC },
+ { IKEV1_ESP_ENCR_SERPENT, ENCR_SERPENT_CBC },
+ { IKEV1_ESP_ENCR_TWOFISH, ENCR_TWOFISH_CBC },
+};
+
+/**
+ * ESP authentication algorithm mapping
+ */
+static algo_map_t map_esp_auth[] = {
+ { IKEV1_ESP_AUTH_HMAC_MD5, AUTH_HMAC_MD5_96 },
+ { IKEV1_ESP_AUTH_HMAC_SHA, AUTH_HMAC_SHA1_96 },
+ { IKEV1_ESP_AUTH_DES_MAC, AUTH_DES_MAC },
+ { IKEV1_ESP_AUTH_KPDK, AUTH_KPDK_MD5 },
+ { IKEV1_ESP_AUTH_HMAC_SHA2_256, AUTH_HMAC_SHA2_256_128 },
+ { IKEV1_ESP_AUTH_HMAC_SHA2_384, AUTH_HMAC_SHA2_384_192 },
+ { IKEV1_ESP_AUTH_HMAC_SHA2_512, AUTH_HMAC_SHA2_512_256 },
+ { IKEV1_ESP_AUTH_AES_XCBC_MAC, AUTH_AES_XCBC_96 },
+ { IKEV1_ESP_AUTH_AES_128_GMAC, AUTH_AES_128_GMAC },
+ { IKEV1_ESP_AUTH_AES_192_GMAC, AUTH_AES_192_GMAC },
+ { IKEV1_ESP_AUTH_AES_256_GMAC, AUTH_AES_256_GMAC },
+};
+
+/**
+ * Get IKEv2 algorithm from IKEv1 identifier
+ */
+static u_int16_t get_alg_from_ikev1(transform_type_t type, u_int16_t value)
+{
+ algo_map_t *map;
+ u_int16_t def;
+ int i, count;
+
+ switch (type)
+ {
+ case ENCRYPTION_ALGORITHM:
+ map = map_encr;
+ count = countof(map_encr);
+ def = ENCR_UNDEFINED;
+ break;
+ case INTEGRITY_ALGORITHM:
+ map = map_integ;
+ count = countof(map_integ);
+ def = AUTH_UNDEFINED;
+ break;
+ case PSEUDO_RANDOM_FUNCTION:
+ map = map_prf;
+ count = countof(map_prf);
+ def = PRF_UNDEFINED;
+ break;
+ default:
+ return 0;
+ }
+ for (i = 0; i < count; i++)
+ {
+ if (map[i].ikev1 == value)
+ {
+ return map[i].ikev2;
+ }
+ }
+ return def;
+}
+
+/**
+ * Get IKEv1 algorithm from IKEv2 identifier
+ */
+static u_int16_t get_ikev1_from_alg(transform_type_t type, u_int16_t value)
+{
+ algo_map_t *map;
+ int i, count;
+
+ switch (type)
+ {
+ case ENCRYPTION_ALGORITHM:
+ map = map_encr;
+ count = countof(map_encr);
+ break;
+ case INTEGRITY_ALGORITHM:
+ map = map_integ;
+ count = countof(map_integ);
+ break;
+ case PSEUDO_RANDOM_FUNCTION:
+ map = map_prf;
+ count = countof(map_prf);
+ break;
+ default:
+ return 0;
+ }
+ for (i = 0; i < count; i++)
+ {
+ if (map[i].ikev2 == value)
+ {
+ return map[i].ikev1;
+ }
+ }
+ return 0;
+}
+
+/**
+ * Get IKEv2 algorithm from IKEv1 ESP transaction ID
+ */
+static u_int16_t get_alg_from_ikev1_transid(transform_type_t type, u_int16_t value)
+{
+ algo_map_t *map;
+ u_int16_t def;
+ int i, count;
+
+ switch (type)
+ {
+ case ENCRYPTION_ALGORITHM:
+ map = map_esp_encr;
+ count = countof(map_esp_encr);
+ def = ENCR_UNDEFINED;
+ break;
+ case INTEGRITY_ALGORITHM:
+ map = map_esp_auth;
+ count = countof(map_esp_auth);
+ def = AUTH_UNDEFINED;
+ break;
+ default:
+ return 0;
+ }
+ for (i = 0; i < count; i++)
+ {
+ if (map[i].ikev1 == value)
+ {
+ return map[i].ikev2;
+ }
+ }
+ return def;
+}
+
+/**
+ * Get IKEv1 ESP transaction ID from IKEv2 identifier
+ */
+static u_int16_t get_ikev1_transid_from_alg(transform_type_t type, u_int16_t value)
+{
+ algo_map_t *map;
+ int i, count;
+
+ switch (type)
+ {
+ case ENCRYPTION_ALGORITHM:
+ map = map_esp_encr;
+ count = countof(map_esp_encr);
+ break;
+ case INTEGRITY_ALGORITHM:
+ map = map_esp_auth;
+ count = countof(map_esp_auth);
+ break;
+ default:
+ return 0;
+ }
+ for (i = 0; i < count; i++)
+ {
+ if (map[i].ikev2 == value)
+ {
+ return map[i].ikev1;
+ }
+ }
+ return 0;
+}
+/**
+ * Get IKEv1 authentication attribute from auth_method_t
+ */
+static u_int16_t get_ikev1_auth(auth_method_t method)
+{
+ switch (method)
+ {
+ case AUTH_RSA:
+ return IKEV1_AUTH_RSA_SIG;
+ case AUTH_DSS:
+ return IKEV1_AUTH_DSS_SIG;
+ case AUTH_XAUTH_INIT_PSK:
+ return IKEV1_AUTH_XAUTH_INIT_PSK;
+ case AUTH_XAUTH_RESP_PSK:
+ return IKEV1_AUTH_XAUTH_RESP_PSK;
+ case AUTH_XAUTH_INIT_RSA:
+ return IKEV1_AUTH_XAUTH_INIT_RSA;
+ case AUTH_XAUTH_RESP_RSA:
+ return IKEV1_AUTH_XAUTH_RESP_RSA;
+ case AUTH_HYBRID_INIT_RSA:
+ return IKEV1_AUTH_HYBRID_INIT_RSA;
+ case AUTH_HYBRID_RESP_RSA:
+ return IKEV1_AUTH_HYBRID_RESP_RSA;
+ case AUTH_ECDSA_256:
+ return IKEV1_AUTH_ECDSA_256;
+ case AUTH_ECDSA_384:
+ return IKEV1_AUTH_ECDSA_384;
+ case AUTH_ECDSA_521:
+ return IKEV1_AUTH_ECDSA_521;
+ case AUTH_PSK:
+ default:
+ return IKEV1_AUTH_PSK;
+ }
+}
+
+/**
+ * Get IKEv1 encapsulation mode
+ */
+static u_int16_t get_ikev1_mode(ipsec_mode_t mode, bool udp)
+{
+ switch (mode)
+ {
+ case MODE_TUNNEL:
+ return udp ? IKEV1_ENCAP_UDP_TUNNEL : IKEV1_ENCAP_TUNNEL;
+ case MODE_TRANSPORT:
+ return udp ? IKEV1_ENCAP_UDP_TRANSPORT : IKEV1_ENCAP_TRANSPORT;
+ default:
+ return IKEV1_ENCAP_TUNNEL;
+ }
+}
+
+/**
+ * Add an IKE transform to a proposal for IKEv1
+ */
+static void add_to_proposal_v1_ike(proposal_t *proposal,
+ transform_substructure_t *transform)
+{
+ transform_attribute_type_t type;
+ transform_attribute_t *tattr;
+ enumerator_t *enumerator;
+ u_int16_t value, key_length = 0;
+ u_int16_t encr = ENCR_UNDEFINED;
+
+ enumerator = transform->create_attribute_enumerator(transform);
+ while (enumerator->enumerate(enumerator, &tattr))
+ {
+ type = tattr->get_attribute_type(tattr);
+ value = tattr->get_value(tattr);
+ switch (type)
+ {
+ case TATTR_PH1_ENCRYPTION_ALGORITHM:
+ encr = get_alg_from_ikev1(ENCRYPTION_ALGORITHM, value);
+ break;
+ case TATTR_PH1_KEY_LENGTH:
+ key_length = value;
+ break;
+ case TATTR_PH1_HASH_ALGORITHM:
+ proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM,
+ get_alg_from_ikev1(INTEGRITY_ALGORITHM, value), 0);
+ proposal->add_algorithm(proposal, PSEUDO_RANDOM_FUNCTION,
+ get_alg_from_ikev1(PSEUDO_RANDOM_FUNCTION, value), 0);
+ break;
+ case TATTR_PH1_GROUP:
+ proposal->add_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
+ value, 0);
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (encr != ENCR_UNDEFINED)
+ {
+ proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr, key_length);
+ }
+}
+
+/**
+ * Add an ESP transform to a proposal for IKEv1
+ */
+static void add_to_proposal_v1_esp(proposal_t *proposal,
+ transform_substructure_t *transform)
+{
+ transform_attribute_type_t type;
+ transform_attribute_t *tattr;
+ enumerator_t *enumerator;
+ u_int16_t encr, value, key_length = 0;
+
+ enumerator = transform->create_attribute_enumerator(transform);
+ while (enumerator->enumerate(enumerator, &tattr))
+ {
+ type = tattr->get_attribute_type(tattr);
+ value = tattr->get_value(tattr);
+ switch (type)
+ {
+ case TATTR_PH2_KEY_LENGTH:
+ key_length = value;
+ break;
+ case TATTR_PH2_AUTH_ALGORITHM:
+ proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM,
+ get_alg_from_ikev1_transid(INTEGRITY_ALGORITHM,
+ value), 0);
+ break;
+ case TATTR_PH2_GROUP:
+ proposal->add_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
+ value, 0);
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ /* TODO-IKEv1: handle ESN attribute */
+ proposal->add_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS,
+ NO_EXT_SEQ_NUMBERS, 0);
+ encr = get_alg_from_ikev1_transid(ENCRYPTION_ALGORITHM,
+ transform->get_transform_id(transform));
+ if (encr)
+ {
+ proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr,
+ key_length);
+ }
+}
+
+METHOD(proposal_substructure_t, get_proposals, void,
+ private_proposal_substructure_t *this, linked_list_t *proposals)
+{
+ transform_substructure_t *transform;
+ enumerator_t *enumerator;
+ proposal_t *proposal = NULL;
+ u_int64_t spi = 0;
+
switch (this->spi.len)
{
case 4:
- spi = *((u_int32_t*)this->spi.ptr);
+ spi = *((u_int32_t*)this->spi.ptr);
break;
case 8:
spi = *((u_int64_t*)this->spi.ptr);
break;
default:
- spi = 0;
+ break;
}
- proposal->set_spi(proposal, spi);
- return proposal;
+ enumerator = this->transforms->create_enumerator(this->transforms);
+ while (enumerator->enumerate(enumerator, &transform))
+ {
+ if (!proposal)
+ {
+ proposal = proposal_create(this->protocol_id, this->proposal_number);
+ proposal->set_spi(proposal, spi);
+ proposals->insert_last(proposals, proposal);
+ }
+ if (this->type == PROPOSAL_SUBSTRUCTURE)
+ {
+ add_to_proposal_v2(proposal, transform);
+ }
+ else
+ {
+ switch (this->protocol_id)
+ {
+ case PROTO_IKE:
+ add_to_proposal_v1_ike(proposal, transform);
+ break;
+ case PROTO_ESP:
+ add_to_proposal_v1_esp(proposal, transform);
+ break;
+ default:
+ break;
+ }
+ /* create a new proposal for each transform in IKEv1 */
+ proposal = NULL;
+ }
+ }
+ enumerator->destroy(enumerator);
}
METHOD(proposal_substructure_t, create_substructure_enumerator, enumerator_t*,
@@ -348,11 +977,170 @@ METHOD(proposal_substructure_t, create_substructure_enumerator, enumerator_t*,
return this->transforms->create_enumerator(this->transforms);
}
+/**
+ * Get an attribute from any transform, 0 if not found
+ */
+static u_int64_t get_attr(private_proposal_substructure_t *this,
+ transform_attribute_type_t type)
+{
+ enumerator_t *transforms, *attributes;
+ transform_substructure_t *transform;
+ transform_attribute_t *attr;
+
+ transforms = this->transforms->create_enumerator(this->transforms);
+ while (transforms->enumerate(transforms, &transform))
+ {
+ attributes = transform->create_attribute_enumerator(transform);
+ while (attributes->enumerate(attributes, &attr))
+ {
+ if (attr->get_attribute_type(attr) == type)
+ {
+ attributes->destroy(attributes);
+ transforms->destroy(transforms);
+ return attr->get_value(attr);
+ }
+ }
+ attributes->destroy(attributes);
+ }
+ transforms->destroy(transforms);
+ return 0;
+}
+
+/**
+ * Look up a lifetime duration of a given kind in all transforms
+ */
+static u_int64_t get_life_duration(private_proposal_substructure_t *this,
+ transform_attribute_type_t type_attr, ikev1_life_type_t type,
+ transform_attribute_type_t dur_attr)
+{
+ enumerator_t *transforms, *attributes;
+ transform_substructure_t *transform;
+ transform_attribute_t *attr;
+
+ transforms = this->transforms->create_enumerator(this->transforms);
+ while (transforms->enumerate(transforms, &transform))
+ {
+ attributes = transform->create_attribute_enumerator(transform);
+ while (attributes->enumerate(attributes, &attr))
+ {
+ if (attr->get_attribute_type(attr) == type_attr &&
+ attr->get_value(attr) == type)
+ { /* got type attribute, look for duration following next */
+ while (attributes->enumerate(attributes, &attr))
+ {
+ if (attr->get_attribute_type(attr) == dur_attr)
+ {
+ attributes->destroy(attributes);
+ transforms->destroy(transforms);
+ return attr->get_value(attr);
+ }
+ }
+ }
+ }
+ attributes->destroy(attributes);
+ }
+ transforms->destroy(transforms);
+ return 0;
+}
+
+METHOD(proposal_substructure_t, get_lifetime, u_int32_t,
+ private_proposal_substructure_t *this)
+{
+ u_int32_t duration;
+
+ switch (this->protocol_id)
+ {
+ case PROTO_IKE:
+ return get_life_duration(this, TATTR_PH1_LIFE_TYPE,
+ IKEV1_LIFE_TYPE_SECONDS, TATTR_PH1_LIFE_DURATION);
+ case PROTO_ESP:
+ duration = get_life_duration(this, TATTR_PH2_SA_LIFE_TYPE,
+ IKEV1_LIFE_TYPE_SECONDS, TATTR_PH2_SA_LIFE_DURATION);
+ if (!duration)
+ { /* default to 8 hours, RFC 2407 */
+ return 28800;
+ }
+ return duration;
+ default:
+ return 0;
+ }
+}
+
+METHOD(proposal_substructure_t, get_lifebytes, u_int64_t,
+ private_proposal_substructure_t *this)
+{
+ switch (this->protocol_id)
+ {
+ case PROTO_ESP:
+ return 1000 * get_life_duration(this, TATTR_PH2_SA_LIFE_TYPE,
+ IKEV1_LIFE_TYPE_KILOBYTES, TATTR_PH2_SA_LIFE_DURATION);
+ case PROTO_IKE:
+ default:
+ return 0;
+ }
+}
+
+METHOD(proposal_substructure_t, get_auth_method, auth_method_t,
+ private_proposal_substructure_t *this)
+{
+ switch (get_attr(this, TATTR_PH1_AUTH_METHOD))
+ {
+ case IKEV1_AUTH_PSK:
+ return AUTH_PSK;
+ case IKEV1_AUTH_RSA_SIG:
+ return AUTH_RSA;
+ case IKEV1_AUTH_DSS_SIG:
+ return AUTH_DSS;
+ case IKEV1_AUTH_XAUTH_INIT_PSK:
+ return AUTH_XAUTH_INIT_PSK;
+ case IKEV1_AUTH_XAUTH_RESP_PSK:
+ return AUTH_XAUTH_RESP_PSK;
+ case IKEV1_AUTH_XAUTH_INIT_RSA:
+ return AUTH_XAUTH_INIT_RSA;
+ case IKEV1_AUTH_XAUTH_RESP_RSA:
+ return AUTH_XAUTH_RESP_RSA;
+ case IKEV1_AUTH_HYBRID_INIT_RSA:
+ return AUTH_HYBRID_INIT_RSA;
+ case IKEV1_AUTH_HYBRID_RESP_RSA:
+ return AUTH_HYBRID_RESP_RSA;
+ case IKEV1_AUTH_ECDSA_256:
+ return AUTH_ECDSA_256;
+ case IKEV1_AUTH_ECDSA_384:
+ return AUTH_ECDSA_384;
+ case IKEV1_AUTH_ECDSA_521:
+ return AUTH_ECDSA_521;
+ default:
+ return AUTH_NONE;
+ }
+}
+
+METHOD(proposal_substructure_t, get_encap_mode, ipsec_mode_t,
+ private_proposal_substructure_t *this, bool *udp)
+{
+ *udp = FALSE;
+ switch (get_attr(this, TATTR_PH2_ENCAP_MODE))
+ {
+ case IKEV1_ENCAP_TRANSPORT:
+ return MODE_TRANSPORT;
+ case IKEV1_ENCAP_TUNNEL:
+ return MODE_TUNNEL;
+ case IKEV1_ENCAP_UDP_TRANSPORT:
+ *udp = TRUE;
+ return MODE_TRANSPORT;
+ case IKEV1_ENCAP_UDP_TUNNEL:
+ *udp = TRUE;
+ return MODE_TUNNEL;
+ default:
+ /* default to TUNNEL, RFC 2407 says implementation specific */
+ return MODE_TUNNEL;
+ }
+}
+
METHOD2(payload_t, proposal_substructure_t, destroy, void,
private_proposal_substructure_t *this)
{
this->transforms->destroy_offset(this->transforms,
- offsetof(transform_substructure_t, destroy));
+ offsetof(payload_t, destroy));
chunk_free(&this->spi);
free(this);
}
@@ -360,7 +1148,7 @@ METHOD2(payload_t, proposal_substructure_t, destroy, void,
/*
* Described in header.
*/
-proposal_substructure_t *proposal_substructure_create()
+proposal_substructure_t *proposal_substructure_create(payload_type_t type)
{
private_proposal_substructure_t *this;
@@ -369,6 +1157,7 @@ proposal_substructure_t *proposal_substructure_create()
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
+ .get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@@ -380,39 +1169,197 @@ proposal_substructure_t *proposal_substructure_create()
.set_protocol_id = _set_protocol_id,
.get_protocol_id = _get_protocol_id,
.set_is_last_proposal = _set_is_last_proposal,
- .get_proposal = _get_proposal,
+ .get_proposals = _get_proposals,
.create_substructure_enumerator = _create_substructure_enumerator,
.set_spi = _set_spi,
.get_spi = _get_spi,
+ .get_cpi = _get_cpi,
+ .get_lifetime = _get_lifetime,
+ .get_lifebytes = _get_lifebytes,
+ .get_auth_method = _get_auth_method,
+ .get_encap_mode = _get_encap_mode,
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
- .proposal_length = PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH,
.transforms = linked_list_create(),
+ .type = type,
);
+ compute_length(this);
return &this->public;
}
-/*
- * Described in header.
+/**
+ * Add an IKEv1 IKE proposal to the substructure
*/
-proposal_substructure_t *proposal_substructure_create_from_proposal(
- proposal_t *proposal)
+static void set_from_proposal_v1_ike(private_proposal_substructure_t *this,
+ proposal_t *proposal, u_int32_t lifetime,
+ auth_method_t method, int number)
{
transform_substructure_t *transform;
- private_proposal_substructure_t *this;
u_int16_t alg, key_size;
enumerator_t *enumerator;
- this = (private_proposal_substructure_t*)proposal_substructure_create();
+ transform = transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE_V1,
+ number, IKEV1_TRANSID_KEY_IKE);
+
+ enumerator = proposal->create_enumerator(proposal, ENCRYPTION_ALGORITHM);
+ if (enumerator->enumerate(enumerator, &alg, &key_size))
+ {
+ alg = get_ikev1_from_alg(ENCRYPTION_ALGORITHM, alg);
+ if (alg)
+ {
+ transform->add_transform_attribute(transform,
+ transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+ TATTR_PH1_ENCRYPTION_ALGORITHM, alg));
+ if (key_size)
+ {
+ transform->add_transform_attribute(transform,
+ transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+ TATTR_PH1_KEY_LENGTH, key_size));
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ /* encode the integrity algorithm as hash and assume use the same PRF */
+ enumerator = proposal->create_enumerator(proposal, INTEGRITY_ALGORITHM);
+ if (enumerator->enumerate(enumerator, &alg, &key_size))
+ {
+ alg = get_ikev1_from_alg(INTEGRITY_ALGORITHM, alg);
+ if (alg)
+ {
+ transform->add_transform_attribute(transform,
+ transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+ TATTR_PH1_HASH_ALGORITHM, alg));
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ enumerator = proposal->create_enumerator(proposal, DIFFIE_HELLMAN_GROUP);
+ if (enumerator->enumerate(enumerator, &alg, &key_size))
+ {
+ transform->add_transform_attribute(transform,
+ transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+ TATTR_PH1_GROUP, alg));
+ }
+ enumerator->destroy(enumerator);
+
+ transform->add_transform_attribute(transform,
+ transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+ TATTR_PH1_AUTH_METHOD, get_ikev1_auth(method)));
+ transform->add_transform_attribute(transform,
+ transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+ TATTR_PH1_LIFE_TYPE, IKEV1_LIFE_TYPE_SECONDS));
+ transform->add_transform_attribute(transform,
+ transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+ TATTR_PH1_LIFE_DURATION, lifetime));
+
+ add_transform_substructure(this, transform);
+}
+
+/**
+ * Add an IKEv1 ESP proposal to the substructure
+ */
+static void set_from_proposal_v1_esp(private_proposal_substructure_t *this,
+ proposal_t *proposal, u_int32_t lifetime, u_int64_t lifebytes,
+ ipsec_mode_t mode, bool udp, int number)
+{
+ transform_substructure_t *transform = NULL;
+ u_int16_t alg, key_size;
+ enumerator_t *enumerator;
+
+ enumerator = proposal->create_enumerator(proposal, ENCRYPTION_ALGORITHM);
+ if (enumerator->enumerate(enumerator, &alg, &key_size))
+ {
+ alg = get_ikev1_transid_from_alg(ENCRYPTION_ALGORITHM, alg);
+ if (alg)
+ {
+ transform = transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE_V1,
+ number, alg);
+ if (key_size)
+ {
+ transform->add_transform_attribute(transform,
+ transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+ TATTR_PH2_KEY_LENGTH, key_size));
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (!transform)
+ {
+ return;
+ }
+
+ enumerator = proposal->create_enumerator(proposal, INTEGRITY_ALGORITHM);
+ if (enumerator->enumerate(enumerator, &alg, &key_size))
+ {
+ alg = get_ikev1_transid_from_alg(INTEGRITY_ALGORITHM, alg);
+ if (alg)
+ {
+ transform->add_transform_attribute(transform,
+ transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+ TATTR_PH2_AUTH_ALGORITHM, alg));
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ enumerator = proposal->create_enumerator(proposal, DIFFIE_HELLMAN_GROUP);
+ if (enumerator->enumerate(enumerator, &alg, &key_size))
+ {
+ transform->add_transform_attribute(transform,
+ transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+ TATTR_PH2_GROUP, alg));
+ }
+ enumerator->destroy(enumerator);
+
+ transform->add_transform_attribute(transform,
+ transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+ TATTR_PH2_ENCAP_MODE, get_ikev1_mode(mode, udp)));
+ if (lifetime)
+ {
+ transform->add_transform_attribute(transform,
+ transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+ TATTR_PH2_SA_LIFE_TYPE, IKEV1_LIFE_TYPE_SECONDS));
+ transform->add_transform_attribute(transform,
+ transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+ TATTR_PH2_SA_LIFE_DURATION, lifetime));
+ }
+ if (lifebytes)
+ {
+ transform->add_transform_attribute(transform,
+ transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+ TATTR_PH2_SA_LIFE_TYPE, IKEV1_LIFE_TYPE_KILOBYTES));
+ transform->add_transform_attribute(transform,
+ transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+ TATTR_PH2_SA_LIFE_DURATION, lifebytes / 1000));
+ }
+
+ add_transform_substructure(this, transform);
+}
+
+/**
+ * Add an IKEv2 proposal to the substructure
+ */
+static void set_from_proposal_v2(private_proposal_substructure_t *this,
+ proposal_t *proposal)
+{
+ transform_substructure_t *transform;
+ u_int16_t alg, key_size;
+ enumerator_t *enumerator;
/* encryption algorithm is only available in ESP */
enumerator = proposal->create_enumerator(proposal, ENCRYPTION_ALGORITHM);
while (enumerator->enumerate(enumerator, &alg, &key_size))
{
- transform = transform_substructure_create_type(ENCRYPTION_ALGORITHM,
- alg, key_size);
+ transform = transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE,
+ ENCRYPTION_ALGORITHM, alg);
+ if (key_size)
+ {
+ transform->add_transform_attribute(transform,
+ transform_attribute_create_value(TRANSFORM_ATTRIBUTE,
+ TATTR_IKEV2_KEY_LENGTH, key_size));
+ }
add_transform_substructure(this, transform);
}
enumerator->destroy(enumerator);
@@ -421,8 +1368,8 @@ proposal_substructure_t *proposal_substructure_create_from_proposal(
enumerator = proposal->create_enumerator(proposal, INTEGRITY_ALGORITHM);
while (enumerator->enumerate(enumerator, &alg, &key_size))
{
- transform = transform_substructure_create_type(INTEGRITY_ALGORITHM,
- alg, key_size);
+ transform = transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE,
+ INTEGRITY_ALGORITHM, alg);
add_transform_substructure(this, transform);
}
enumerator->destroy(enumerator);
@@ -431,8 +1378,8 @@ proposal_substructure_t *proposal_substructure_create_from_proposal(
enumerator = proposal->create_enumerator(proposal, PSEUDO_RANDOM_FUNCTION);
while (enumerator->enumerate(enumerator, &alg, &key_size))
{
- transform = transform_substructure_create_type(PSEUDO_RANDOM_FUNCTION,
- alg, key_size);
+ transform = transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE,
+ PSEUDO_RANDOM_FUNCTION, alg);
add_transform_substructure(this, transform);
}
enumerator->destroy(enumerator);
@@ -441,8 +1388,8 @@ proposal_substructure_t *proposal_substructure_create_from_proposal(
enumerator = proposal->create_enumerator(proposal, DIFFIE_HELLMAN_GROUP);
while (enumerator->enumerate(enumerator, &alg, NULL))
{
- transform = transform_substructure_create_type(DIFFIE_HELLMAN_GROUP,
- alg, 0);
+ transform = transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE,
+ DIFFIE_HELLMAN_GROUP, alg);
add_transform_substructure(this, transform);
}
enumerator->destroy(enumerator);
@@ -451,27 +1398,36 @@ proposal_substructure_t *proposal_substructure_create_from_proposal(
enumerator = proposal->create_enumerator(proposal, EXTENDED_SEQUENCE_NUMBERS);
while (enumerator->enumerate(enumerator, &alg, NULL))
{
- transform = transform_substructure_create_type(EXTENDED_SEQUENCE_NUMBERS,
- alg, 0);
+ transform = transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE,
+ EXTENDED_SEQUENCE_NUMBERS, alg);
add_transform_substructure(this, transform);
}
enumerator->destroy(enumerator);
+}
+
+/**
+ * Set SPI and other data from proposal, compute length
+ */
+static void set_data(private_proposal_substructure_t *this, proposal_t *proposal)
+{
+ u_int64_t spi64;
+ u_int32_t spi32;
/* add SPI, if necessary */
switch (proposal->get_protocol(proposal))
{
case PROTO_AH:
case PROTO_ESP:
- this->spi_size = this->spi.len = 4;
- this->spi.ptr = malloc(this->spi_size);
- *((u_int32_t*)this->spi.ptr) = proposal->get_spi(proposal);
+ spi32 = proposal->get_spi(proposal);
+ this->spi = chunk_clone(chunk_from_thing(spi32));
+ this->spi_size = this->spi.len;
break;
case PROTO_IKE:
- if (proposal->get_spi(proposal))
+ spi64 = proposal->get_spi(proposal);
+ if (spi64)
{ /* IKE only uses SPIS when rekeying, but on initial setup */
- this->spi_size = this->spi.len = 8;
- this->spi.ptr = malloc(this->spi_size);
- *((u_int64_t*)this->spi.ptr) = proposal->get_spi(proposal);
+ this->spi = chunk_clone(chunk_from_thing(spi64));
+ this->spi_size = this->spi.len;
}
break;
default:
@@ -480,6 +1436,144 @@ proposal_substructure_t *proposal_substructure_create_from_proposal(
this->proposal_number = proposal->get_number(proposal);
this->protocol_id = proposal->get_protocol(proposal);
compute_length(this);
+}
+
+/*
+ * Described in header.
+ */
+proposal_substructure_t *proposal_substructure_create_from_proposal_v2(
+ proposal_t *proposal)
+{
+ private_proposal_substructure_t *this;
+
+ this = (private_proposal_substructure_t*)
+ proposal_substructure_create(SECURITY_ASSOCIATION);
+ set_from_proposal_v2(this, proposal);
+ set_data(this, proposal);
+
+ return &this->public;
+}
+
+/**
+ * See header.
+ */
+proposal_substructure_t *proposal_substructure_create_from_proposal_v1(
+ proposal_t *proposal, u_int32_t lifetime, u_int64_t lifebytes,
+ auth_method_t auth, ipsec_mode_t mode, bool udp)
+{
+ private_proposal_substructure_t *this;
+
+ this = (private_proposal_substructure_t*)
+ proposal_substructure_create(PROPOSAL_SUBSTRUCTURE_V1);
+ switch (proposal->get_protocol(proposal))
+ {
+ case PROTO_IKE:
+ set_from_proposal_v1_ike(this, proposal, lifetime, auth, 1);
+ break;
+ case PROTO_ESP:
+ set_from_proposal_v1_esp(this, proposal, lifetime,
+ lifebytes, mode, udp, 1);
+ break;
+ default:
+ break;
+ }
+ set_data(this, proposal);
+
+ return &this->public;
+}
+
+/**
+ * See header.
+ */
+proposal_substructure_t *proposal_substructure_create_from_proposals_v1(
+ linked_list_t *proposals, u_int32_t lifetime, u_int64_t lifebytes,
+ auth_method_t auth, ipsec_mode_t mode, bool udp)
+{
+ private_proposal_substructure_t *this = NULL;
+ enumerator_t *enumerator;
+ proposal_t *proposal;
+ int number = 0;
+
+ enumerator = proposals->create_enumerator(proposals);
+ while (enumerator->enumerate(enumerator, &proposal))
+ {
+ if (!this)
+ {
+ this = (private_proposal_substructure_t*)
+ proposal_substructure_create_from_proposal_v1(
+ proposal, lifetime, lifebytes, auth, mode, udp);
+ ++number;
+ }
+ else
+ {
+ switch (proposal->get_protocol(proposal))
+ {
+ case PROTO_IKE:
+ set_from_proposal_v1_ike(this, proposal, lifetime,
+ auth, ++number);
+ break;
+ case PROTO_ESP:
+ set_from_proposal_v1_esp(this, proposal, lifetime,
+ lifebytes, mode, udp, ++number);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return &this->public;
+}
+
+/**
+ * See header.
+ */
+proposal_substructure_t *proposal_substructure_create_for_ipcomp_v1(
+ u_int32_t lifetime, u_int64_t lifebytes, u_int16_t cpi,
+ ipsec_mode_t mode, bool udp, u_int8_t proposal_number)
+{
+ private_proposal_substructure_t *this;
+ transform_substructure_t *transform;
+
+
+ this = (private_proposal_substructure_t*)
+ proposal_substructure_create(PROPOSAL_SUBSTRUCTURE_V1);
+
+ /* we currently support DEFLATE only */
+ transform = transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE_V1,
+ 1, IKEV1_IPCOMP_DEFLATE);
+
+ transform->add_transform_attribute(transform,
+ transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+ TATTR_PH2_ENCAP_MODE, get_ikev1_mode(mode, udp)));
+ if (lifetime)
+ {
+ transform->add_transform_attribute(transform,
+ transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+ TATTR_PH2_SA_LIFE_TYPE, IKEV1_LIFE_TYPE_SECONDS));
+ transform->add_transform_attribute(transform,
+ transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+ TATTR_PH2_SA_LIFE_DURATION, lifetime));
+ }
+ if (lifebytes)
+ {
+ transform->add_transform_attribute(transform,
+ transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+ TATTR_PH2_SA_LIFE_TYPE, IKEV1_LIFE_TYPE_KILOBYTES));
+ transform->add_transform_attribute(transform,
+ transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+ TATTR_PH2_SA_LIFE_DURATION, lifebytes / 1000));
+ }
+
+ add_transform_substructure(this, transform);
+
+ this->spi = chunk_clone(chunk_from_thing(cpi));
+ this->spi_size = this->spi.len;
+ this->protocol_id = PROTO_IPCOMP;
+ this->proposal_number = proposal_number;
+
+ compute_length(this);
return &this->public;
}
diff --git a/src/libcharon/encoding/payloads/proposal_substructure.h b/src/libcharon/encoding/payloads/proposal_substructure.h
index d0ba1fd2a..5d42a6116 100644
--- a/src/libcharon/encoding/payloads/proposal_substructure.h
+++ b/src/libcharon/encoding/payloads/proposal_substructure.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -29,17 +30,11 @@ typedef struct proposal_substructure_t proposal_substructure_t;
#include <encoding/payloads/transform_substructure.h>
#include <config/proposal.h>
#include <utils/linked_list.h>
-
+#include <kernel/kernel_ipsec.h>
+#include <sa/authenticator.h>
/**
- * Length of the proposal substructure header (without spi).
- */
-#define PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH 8
-
-/**
- * Class representing an IKEv2-PROPOSAL SUBSTRUCTURE.
- *
- * The PROPOSAL SUBSTRUCTURE format is described in RFC section 3.3.1.
+ * Class representing an IKEv1/IKEv2 proposal substructure.
*/
struct proposal_substructure_t {
@@ -58,7 +53,7 @@ struct proposal_substructure_t {
/**
* get proposal number of current proposal.
*
- * @return proposal number of current proposal substructure.
+ * @return proposal number of current proposal substructure.
*/
u_int8_t (*get_proposal_number) (proposal_substructure_t *this);
@@ -73,7 +68,7 @@ struct proposal_substructure_t {
/**
* get protocol id of current proposal.
*
- * @return protocol id of current proposal substructure.
+ * @return protocol id of current proposal substructure.
*/
u_int8_t (*get_protocol_id) (proposal_substructure_t *this);
@@ -90,7 +85,7 @@ struct proposal_substructure_t {
/**
* Returns the currently set SPI of this proposal.
*
- * @return chunk_t pointing to the value
+ * @return chunk_t pointing to the value
*/
chunk_t (*get_spi) (proposal_substructure_t *this);
@@ -104,11 +99,19 @@ struct proposal_substructure_t {
void (*set_spi) (proposal_substructure_t *this, chunk_t spi);
/**
- * Get a proposal_t from the propsal_substructure_t.
+ * Gets the CPI of the current proposal (IKEv1 only).
+ *
+ * @param cpi the CPI if a supported algorithm is proposed
+ * @return TRUE if a supported algorithm is proposed
+ */
+ bool (*get_cpi) (proposal_substructure_t *this, u_int16_t *cpi);
+
+ /**
+ * Get proposals contained in a propsal_substructure_t.
*
- * @return proposal_t
+ * @param list list to add created proposals to
*/
- proposal_t * (*get_proposal) (proposal_substructure_t *this);
+ void (*get_proposals) (proposal_substructure_t *this, linked_list_t *list);
/**
* Create an enumerator over transform substructures.
@@ -118,6 +121,35 @@ struct proposal_substructure_t {
enumerator_t* (*create_substructure_enumerator)(proposal_substructure_t *this);
/**
+ * Get the (shortest) lifetime of a proposal (IKEv1 only).
+ *
+ * @return lifetime, in seconds
+ */
+ u_int32_t (*get_lifetime)(proposal_substructure_t *this);
+
+ /**
+ * Get the (shortest) life duration of a proposal (IKEv1 only).
+ *
+ * @return life duration, in bytes
+ */
+ u_int64_t (*get_lifebytes)(proposal_substructure_t *this);
+
+ /**
+ * Get the first authentication method from the proposal (IKEv1 only).
+ *
+ * @return auth method, or AUTH_NONE
+ */
+ auth_method_t (*get_auth_method)(proposal_substructure_t *this);
+
+ /**
+ * Get the (first) encapsulation mode from a proposal (IKEv1 only).
+ *
+ * @param udp set to TRUE if UDP encapsulation used
+ * @return ipsec encapsulation mode
+ */
+ ipsec_mode_t (*get_encap_mode)(proposal_substructure_t *this, bool *udp);
+
+ /**
* Destroys an proposal_substructure_t object.
*/
void (*destroy) (proposal_substructure_t *this);
@@ -126,17 +158,63 @@ struct proposal_substructure_t {
/**
* Creates an empty proposal_substructure_t object
*
- * @return proposal_substructure_t object
+ * @param type PROPOSAL_SUBSTRUCTURE or PROPOSAL_SUBSTRUCTURE_V1
+ * @return proposal_substructure_t object
*/
-proposal_substructure_t *proposal_substructure_create(void);
+proposal_substructure_t *proposal_substructure_create(payload_type_t type);
/**
- * Creates a proposal_substructure_t from a proposal_t.
+ * Creates an IKEv2 proposal_substructure_t from a proposal_t.
*
- * @param proposal proposal to build a substruct out of it
- * @return proposal_substructure_t object
+ * @param proposal proposal to build a substruct out of it
+ * @return proposal_substructure_t PROPOSAL_SUBSTRUCTURE
*/
-proposal_substructure_t *proposal_substructure_create_from_proposal(
+proposal_substructure_t *proposal_substructure_create_from_proposal_v2(
proposal_t *proposal);
+/**
+ * Creates an IKEv1 proposal_substructure_t from a proposal_t.
+ *
+ * @param proposal proposal to build a substruct out of it
+ * @param lifetime lifetime in seconds
+ * @param lifebytes lifebytes, in bytes
+ * @param auth authentication method to use, or AUTH_NONE
+ * @param mode IPsec encapsulation mode, TRANSPORT or TUNNEL
+ * @param udp TRUE to use UDP encapsulation
+ * @return proposal_substructure_t object PROPOSAL_SUBSTRUCTURE_V1
+ */
+proposal_substructure_t *proposal_substructure_create_from_proposal_v1(
+ proposal_t *proposal, u_int32_t lifetime, u_int64_t lifebytes,
+ auth_method_t auth, ipsec_mode_t mode, bool udp);
+
+/**
+ * Creates an IKEv1 proposal_substructure_t from a list of proposal_t.
+ *
+ * @param proposals list of proposal_t to encode in a substructure
+ * @param lifetime lifetime in seconds
+ * @param lifebytes lifebytes, in bytes
+ * @param auth authentication method to use, or AUTH_NONE
+ * @param mode IPsec encapsulation mode, TRANSPORT or TUNNEL
+ * @param udp TRUE to use UDP encapsulation
+ * @return IKEv1 proposal_substructure_t PROPOSAL_SUBSTRUCTURE_V1
+ */
+proposal_substructure_t *proposal_substructure_create_from_proposals_v1(
+ linked_list_t *proposals, u_int32_t lifetime, u_int64_t lifebytes,
+ auth_method_t auth, ipsec_mode_t mode, bool udp);
+
+/**
+ * Creates an IKEv1 proposal_substructure_t for IPComp with the given
+ * proposal_number (e.g. of a ESP proposal to bundle them).
+ *
+ * @param lifetime lifetime in seconds
+ * @param lifebytes lifebytes, in bytes
+ * @param cpi the CPI to be used
+ * @param mode IPsec encapsulation mode, TRANSPORT or TUNNEL
+ * @param udp TRUE to use UDP encapsulation
+ * @param proposal_number the proposal number of the proposal to be linked
+ * @return IKEv1 proposal_substructure_t PROPOSAL_SUBSTRUCTURE_V1
+ */
+proposal_substructure_t *proposal_substructure_create_for_ipcomp_v1(
+ u_int32_t lifetime, u_int64_t lifebytes, u_int16_t cpi,
+ ipsec_mode_t mode, bool udp, u_int8_t proposal_number);
#endif /** PROPOSAL_SUBSTRUCTURE_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/sa_payload.c b/src/libcharon/encoding/payloads/sa_payload.c
index 010f63cfd..adf19aa67 100644
--- a/src/libcharon/encoding/payloads/sa_payload.c
+++ b/src/libcharon/encoding/payloads/sa_payload.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2005-2010 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -22,6 +23,8 @@
#include <utils/linked_list.h>
#include <daemon.h>
+/* IKEv1 situation */
+#define SIT_IDENTITY_ONLY 1
typedef struct private_sa_payload_t private_sa_payload_t;
@@ -48,7 +51,7 @@ struct private_sa_payload_t {
/**
* Reserved bits
*/
- bool reserved[7];
+ bool reserved[8];
/**
* Length of this payload.
@@ -58,21 +61,75 @@ struct private_sa_payload_t {
/**
* Proposals in this payload are stored in a linked_list_t.
*/
- linked_list_t * proposals;
+ linked_list_t *proposals;
+
+ /**
+ * Type of this payload, V1 or V2
+ */
+ payload_type_t type;
+
+ /**
+ * IKEv1 DOI
+ */
+ u_int32_t doi;
+
+ /**
+ * IKEv1 situation
+ */
+ u_int32_t situation;
};
/**
- * Encoding rules to parse or generate a IKEv2-SA Payload
- *
- * The defined offsets are the positions in a object of type
- * private_sa_payload_t.
+ * Encoding rules for IKEv1 SA payload
*/
-encoding_rule_t sa_payload_encodings[] = {
+static encoding_rule_t encodings_v1[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_sa_payload_t, next_payload) },
+ /* 8 reserved bits */
+ { RESERVED_BIT, offsetof(private_sa_payload_t, reserved[0]) },
+ { RESERVED_BIT, offsetof(private_sa_payload_t, reserved[1]) },
+ { RESERVED_BIT, offsetof(private_sa_payload_t, reserved[2]) },
+ { RESERVED_BIT, offsetof(private_sa_payload_t, reserved[3]) },
+ { RESERVED_BIT, offsetof(private_sa_payload_t, reserved[4]) },
+ { RESERVED_BIT, offsetof(private_sa_payload_t, reserved[5]) },
+ { RESERVED_BIT, offsetof(private_sa_payload_t, reserved[6]) },
+ { RESERVED_BIT, offsetof(private_sa_payload_t, reserved[7]) },
+ /* Length of the whole SA payload*/
+ { PAYLOAD_LENGTH, offsetof(private_sa_payload_t, payload_length) },
+ /* DOI*/
+ { U_INT_32, offsetof(private_sa_payload_t, doi) },
+ /* Situation*/
+ { U_INT_32, offsetof(private_sa_payload_t, situation) },
+ /* Proposals are stored in a proposal substructure list */
+ { PAYLOAD_LIST + PROPOSAL_SUBSTRUCTURE_V1,
+ offsetof(private_sa_payload_t, proposals) },
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload ! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! DOI !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Situation !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ <Proposals> ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Encoding rules for IKEv2 SA payload
+ */
+static encoding_rule_t encodings_v2[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_sa_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_sa_payload_t, critical) },
- /* 7 Bit reserved bits, nowhere stored */
+ /* 7 Bit reserved bits */
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[0]) },
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[1]) },
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[2]) },
@@ -82,9 +139,9 @@ encoding_rule_t sa_payload_encodings[] = {
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[6]) },
/* Length of the whole SA payload*/
{ PAYLOAD_LENGTH, offsetof(private_sa_payload_t, payload_length) },
- /* Proposals are stored in a proposal substructure,
- offset points to a linked_list_t pointer */
- { PROPOSALS, offsetof(private_sa_payload_t, proposals) },
+ /* Proposals are stored in a proposal substructure list */
+ { PAYLOAD_LIST + PROPOSAL_SUBSTRUCTURE,
+ offsetof(private_sa_payload_t, proposals) },
};
/*
@@ -102,11 +159,16 @@ encoding_rule_t sa_payload_encodings[] = {
METHOD(payload_t, verify, status_t,
private_sa_payload_t *this)
{
- int expected_number = 1, current_number;
+ int expected_number = 0, current_number;
status_t status = SUCCESS;
enumerator_t *enumerator;
proposal_substructure_t *substruct;
+ if (this->type == SECURITY_ASSOCIATION)
+ {
+ expected_number = 1;
+ }
+
/* check proposal numbering */
enumerator = this->proposals->create_enumerator(this->proposals);
while (enumerator->enumerate(enumerator, (void**)&substruct))
@@ -131,17 +193,32 @@ METHOD(payload_t, verify, status_t,
return status;
}
-METHOD(payload_t, get_encoding_rules, void,
- private_sa_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, int,
+ private_sa_payload_t *this, encoding_rule_t **rules)
+{
+ if (this->type == SECURITY_ASSOCIATION_V1)
+ {
+ *rules = encodings_v1;
+ return countof(encodings_v1);
+ }
+ *rules = encodings_v2;
+ return countof(encodings_v2);
+}
+
+METHOD(payload_t, get_header_length, int,
+ private_sa_payload_t *this)
{
- *rules = sa_payload_encodings;
- *rule_count = countof(sa_payload_encodings);
+ if (this->type == SECURITY_ASSOCIATION_V1)
+ {
+ return 12;
+ }
+ return 4;
}
METHOD(payload_t, get_type, payload_type_t,
private_sa_payload_t *this)
{
- return SECURITY_ASSOCIATION;
+ return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
@@ -163,16 +240,15 @@ static void compute_length(private_sa_payload_t *this)
{
enumerator_t *enumerator;
payload_t *current;
- size_t length = SA_PAYLOAD_HEADER_LENGTH;
+
+ this->payload_length = get_header_length(this);
enumerator = this->proposals->create_enumerator(this->proposals);
while (enumerator->enumerate(enumerator, (void **)&current))
{
- length += current->get_length(current);
+ this->payload_length += current->get_length(current);
}
enumerator->destroy(enumerator);
-
- this->payload_length = length;
}
METHOD(payload_t, get_length, size_t,
@@ -181,14 +257,16 @@ METHOD(payload_t, get_length, size_t,
return this->payload_length;
}
-METHOD(sa_payload_t, add_proposal, void,
- private_sa_payload_t *this, proposal_t *proposal)
+/**
+ * Create a transform substructure from a proposal, add to payload
+ */
+static void add_proposal_v2(private_sa_payload_t *this, proposal_t *proposal)
{
proposal_substructure_t *substruct, *last;
u_int count;
+ substruct = proposal_substructure_create_from_proposal_v2(proposal);
count = this->proposals->get_count(this->proposals);
- substruct = proposal_substructure_create_from_proposal(proposal);
if (count > 0)
{
this->proposals->get_last(this->proposals, (void**)&last);
@@ -215,15 +293,19 @@ METHOD(sa_payload_t, get_proposals, linked_list_t*,
int ignore_struct_number = 0;
enumerator_t *enumerator;
proposal_substructure_t *substruct;
- linked_list_t *list;
- proposal_t *proposal;
+ linked_list_t *substructs, *list;
+
+ if (this->type == SECURITY_ASSOCIATION_V1)
+ { /* IKEv1 proposals start with 0 */
+ struct_number = ignore_struct_number = -1;
+ }
- list = linked_list_create();
/* we do not support proposals split up to two proposal substructures, as
* AH+ESP bundles are not supported in RFC4301 anymore.
* To handle such structures safely, we just skip proposals with multiple
* protocols.
*/
+ substructs = linked_list_create();
enumerator = this->proposals->create_enumerator(this->proposals);
while (enumerator->enumerate(enumerator, &substruct))
{
@@ -231,22 +313,80 @@ METHOD(sa_payload_t, get_proposals, linked_list_t*,
if (substruct->get_proposal_number(substruct) == struct_number)
{
if (ignore_struct_number < struct_number)
- {
- /* remove an already added, if first of series */
- list->remove_last(list, (void**)&proposal);
- proposal->destroy(proposal);
+ { /* remove an already added, if first of series */
+ substructs->remove_last(substructs, (void**)&substruct);
ignore_struct_number = struct_number;
}
continue;
}
struct_number++;
- proposal = substruct->get_proposal(substruct);
- if (proposal)
+ substructs->insert_last(substructs, substruct);
+ }
+ enumerator->destroy(enumerator);
+
+ /* generate proposals from substructs */
+ list = linked_list_create();
+ enumerator = substructs->create_enumerator(substructs);
+ while (enumerator->enumerate(enumerator, &substruct))
+ {
+ substruct->get_proposals(substruct, list);
+ }
+ enumerator->destroy(enumerator);
+ substructs->destroy(substructs);
+ return list;
+}
+
+METHOD(sa_payload_t, get_ipcomp_proposals, linked_list_t*,
+ private_sa_payload_t *this, u_int16_t *cpi)
+{
+ int current_proposal = -1, unsupported_proposal = -1;
+ enumerator_t *enumerator;
+ proposal_substructure_t *substruct, *esp = NULL, *ipcomp = NULL;
+ linked_list_t *list;
+
+ /* we currently only support the combination ESP+IPComp, find the first */
+ enumerator = this->proposals->create_enumerator(this->proposals);
+ while (enumerator->enumerate(enumerator, &substruct))
+ {
+ u_int8_t proposal_number = substruct->get_proposal_number(substruct);
+ u_int8_t protocol_id = substruct->get_protocol_id(substruct);
+
+ if (proposal_number == unsupported_proposal)
+ {
+ continue;
+ }
+ if (protocol_id != PROTO_ESP && protocol_id != PROTO_IPCOMP)
+ { /* unsupported combination */
+ esp = ipcomp = NULL;
+ unsupported_proposal = current_proposal;
+ continue;
+ }
+ if (proposal_number != current_proposal)
+ { /* start of a new proposal */
+ if (esp && ipcomp)
+ { /* previous proposal is valid */
+ break;
+ }
+ esp = ipcomp = NULL;
+ current_proposal = proposal_number;
+ }
+ switch (protocol_id)
{
- list->insert_last(list, proposal);
+ case PROTO_ESP:
+ esp = substruct;
+ break;
+ case PROTO_IPCOMP:
+ ipcomp = substruct;
+ break;
}
}
enumerator->destroy(enumerator);
+
+ list = linked_list_create();
+ if (esp && ipcomp && ipcomp->get_cpi(ipcomp, cpi))
+ {
+ esp->get_proposals(esp, list);
+ }
return list;
}
@@ -256,18 +396,86 @@ METHOD(sa_payload_t, create_substructure_enumerator, enumerator_t*,
return this->proposals->create_enumerator(this->proposals);
}
+METHOD(sa_payload_t, get_lifetime, u_int32_t,
+ private_sa_payload_t *this)
+{
+ proposal_substructure_t *substruct;
+ enumerator_t *enumerator;
+ u_int32_t lifetime = 0;
+
+ enumerator = this->proposals->create_enumerator(this->proposals);
+ if (enumerator->enumerate(enumerator, &substruct))
+ {
+ lifetime = substruct->get_lifetime(substruct);
+ }
+ enumerator->destroy(enumerator);
+
+ return lifetime;
+}
+
+METHOD(sa_payload_t, get_lifebytes, u_int64_t,
+ private_sa_payload_t *this)
+{
+ proposal_substructure_t *substruct;
+ enumerator_t *enumerator;
+ u_int64_t lifebytes = 0;
+
+ enumerator = this->proposals->create_enumerator(this->proposals);
+ if (enumerator->enumerate(enumerator, &substruct))
+ {
+ lifebytes = substruct->get_lifebytes(substruct);
+ }
+ enumerator->destroy(enumerator);
+
+ return lifebytes;
+}
+
+METHOD(sa_payload_t, get_auth_method, auth_method_t,
+ private_sa_payload_t *this)
+{
+ proposal_substructure_t *substruct;
+ enumerator_t *enumerator;
+ auth_method_t method = AUTH_NONE;
+
+ enumerator = this->proposals->create_enumerator(this->proposals);
+ if (enumerator->enumerate(enumerator, &substruct))
+ {
+ method = substruct->get_auth_method(substruct);
+ }
+ enumerator->destroy(enumerator);
+
+ return method;
+}
+
+METHOD(sa_payload_t, get_encap_mode, ipsec_mode_t,
+ private_sa_payload_t *this, bool *udp)
+{
+ proposal_substructure_t *substruct;
+ enumerator_t *enumerator;
+ ipsec_mode_t mode = MODE_NONE;
+
+ enumerator = this->proposals->create_enumerator(this->proposals);
+ if (enumerator->enumerate(enumerator, &substruct))
+ {
+ mode = substruct->get_encap_mode(substruct, udp);
+ }
+ enumerator->destroy(enumerator);
+
+ return mode;
+}
+
METHOD2(payload_t, sa_payload_t, destroy, void,
private_sa_payload_t *this)
{
this->proposals->destroy_offset(this->proposals,
- offsetof(proposal_substructure_t, destroy));
+ offsetof(payload_t, destroy));
free(this);
}
/*
* Described in header.
*/
-sa_payload_t *sa_payload_create()
+sa_payload_t *sa_payload_create(payload_type_t type)
{
private_sa_payload_t *this;
@@ -276,38 +484,49 @@ sa_payload_t *sa_payload_create()
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
+ .get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
.get_type = _get_type,
.destroy = _destroy,
},
- .add_proposal = _add_proposal,
.get_proposals = _get_proposals,
+ .get_ipcomp_proposals = _get_ipcomp_proposals,
.create_substructure_enumerator = _create_substructure_enumerator,
+ .get_lifetime = _get_lifetime,
+ .get_lifebytes = _get_lifebytes,
+ .get_auth_method = _get_auth_method,
+ .get_encap_mode = _get_encap_mode,
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
- .payload_length = SA_PAYLOAD_HEADER_LENGTH,
.proposals = linked_list_create(),
+ .type = type,
+ /* for IKEv1 only */
+ .doi = IKEV1_DOI_IPSEC,
+ .situation = SIT_IDENTITY_ONLY,
);
+
+ compute_length(this);
+
return &this->public;
}
/*
* Described in header.
*/
-sa_payload_t *sa_payload_create_from_proposal_list(linked_list_t *proposals)
+sa_payload_t *sa_payload_create_from_proposals_v2(linked_list_t *proposals)
{
private_sa_payload_t *this;
enumerator_t *enumerator;
proposal_t *proposal;
- this = (private_sa_payload_t*)sa_payload_create();
+ this = (private_sa_payload_t*)sa_payload_create(SECURITY_ASSOCIATION);
enumerator = proposals->create_enumerator(proposals);
while (enumerator->enumerate(enumerator, &proposal))
{
- add_proposal(this, proposal);
+ add_proposal_v2(this, proposal);
}
enumerator->destroy(enumerator);
@@ -317,12 +536,71 @@ sa_payload_t *sa_payload_create_from_proposal_list(linked_list_t *proposals)
/*
* Described in header.
*/
-sa_payload_t *sa_payload_create_from_proposal(proposal_t *proposal)
+sa_payload_t *sa_payload_create_from_proposal_v2(proposal_t *proposal)
+{
+ private_sa_payload_t *this;
+
+ this = (private_sa_payload_t*)sa_payload_create(SECURITY_ASSOCIATION);
+ add_proposal_v2(this, proposal);
+
+ return &this->public;
+
+}
+
+/*
+ * Described in header.
+ */
+sa_payload_t *sa_payload_create_from_proposals_v1(linked_list_t *proposals,
+ u_int32_t lifetime, u_int64_t lifebytes,
+ auth_method_t auth, ipsec_mode_t mode, bool udp,
+ u_int16_t cpi)
{
+ proposal_substructure_t *substruct;
private_sa_payload_t *this;
- this = (private_sa_payload_t*)sa_payload_create();
- add_proposal(this, proposal);
+ this = (private_sa_payload_t*)sa_payload_create(SECURITY_ASSOCIATION_V1);
+
+ /* IKEv1 encodes multiple proposals in a single substructure
+ * TODO-IKEv1: Encode ESP+AH proposals in two substructs with same num */
+ substruct = proposal_substructure_create_from_proposals_v1(proposals,
+ lifetime, lifebytes, auth, mode, udp);
+ this->proposals->insert_last(this->proposals, substruct);
+ substruct->set_is_last_proposal(substruct, FALSE);
+ if (cpi)
+ {
+ u_int8_t proposal_number = substruct->get_proposal_number(substruct);
+
+ substruct = proposal_substructure_create_for_ipcomp_v1(lifetime,
+ lifebytes, cpi, mode, udp, proposal_number);
+ this->proposals->insert_last(this->proposals, substruct);
+ substruct->set_is_last_proposal(substruct, FALSE);
+ /* add the proposals again without IPComp */
+ substruct = proposal_substructure_create_from_proposals_v1(proposals,
+ lifetime, lifebytes, auth, mode, udp);
+ substruct->set_proposal_number(substruct, proposal_number + 1);
+ this->proposals->insert_last(this->proposals, substruct);
+ }
+ substruct->set_is_last_proposal(substruct, TRUE);
+ compute_length(this);
+
+ return &this->public;
+}
+
+/*
+ * Described in header.
+ */
+sa_payload_t *sa_payload_create_from_proposal_v1(proposal_t *proposal,
+ u_int32_t lifetime, u_int64_t lifebytes,
+ auth_method_t auth, ipsec_mode_t mode, bool udp,
+ u_int16_t cpi)
+{
+ private_sa_payload_t *this;
+ linked_list_t *proposals;
+ proposals = linked_list_create();
+ proposals->insert_last(proposals, proposal);
+ this = (private_sa_payload_t*)sa_payload_create_from_proposals_v1(proposals,
+ lifetime, lifebytes, auth, mode, udp, cpi);
+ proposals->destroy(proposals);
return &this->public;
}
diff --git a/src/libcharon/encoding/payloads/sa_payload.h b/src/libcharon/encoding/payloads/sa_payload.h
index cc8c481c8..9a88cccd5 100644
--- a/src/libcharon/encoding/payloads/sa_payload.h
+++ b/src/libcharon/encoding/payloads/sa_payload.h
@@ -28,14 +28,11 @@ typedef struct sa_payload_t sa_payload_t;
#include <encoding/payloads/payload.h>
#include <encoding/payloads/proposal_substructure.h>
#include <utils/linked_list.h>
+#include <kernel/kernel_ipsec.h>
+#include <sa/authenticator.h>
/**
- * SA_PAYLOAD length in bytes without any proposal substructure.
- */
-#define SA_PAYLOAD_HEADER_LENGTH 4
-
-/**
- * Class representing an IKEv2-SA Payload.
+ * Class representing an IKEv1 or IKEv2 SA Payload.
*
* The SA Payload format is described in RFC section 3.3.
*/
@@ -49,16 +46,47 @@ struct sa_payload_t {
/**
* Gets the proposals in this payload as a list.
*
- * @return a list containing proposal_t s
+ * @return a list containing proposal_ts
*/
linked_list_t *(*get_proposals) (sa_payload_t *this);
/**
- * Add a child proposal (AH/ESP) to the payload.
+ * Gets the proposals from the first proposal in this payload with IPComp
+ * enabled (IKEv1 only).
+ *
+ * @param cpi the CPI of the first IPComp (sub)proposal
+ * @return a list containing proposal_ts
+ */
+ linked_list_t *(*get_ipcomp_proposals) (sa_payload_t *this, u_int16_t *cpi);
+
+ /**
+ * Get the (shortest) lifetime of a proposal (IKEv1 only).
+ *
+ * @return lifetime, in seconds
+ */
+ u_int32_t (*get_lifetime)(sa_payload_t *this);
+
+ /**
+ * Get the (shortest) life duration of a proposal (IKEv1 only).
+ *
+ * @return life duration, in bytes
+ */
+ u_int64_t (*get_lifebytes)(sa_payload_t *this);
+
+ /**
+ * Get the first authentication method from the proposal (IKEv1 only).
*
- * @param proposal child proposal to add to the payload
+ * @return auth method, or AUTH_NONE
*/
- void (*add_proposal) (sa_payload_t *this, proposal_t *proposal);
+ auth_method_t (*get_auth_method)(sa_payload_t *this);
+
+ /**
+ * Get the (first) encapsulation mode from a proposal (IKEv1 only).
+ *
+ * @param udp set to TRUE if UDP encapsulation used
+ * @return ipsec encapsulation mode
+ */
+ ipsec_mode_t (*get_encap_mode)(sa_payload_t *this, bool *udp);
/**
* Create an enumerator over all proposal substructures.
@@ -76,27 +104,59 @@ struct sa_payload_t {
/**
* Creates an empty sa_payload_t object
*
+ * @param type SECURITY_ASSOCIATION or SECURITY_ASSOCIATION_V1
* @return created sa_payload_t object
*/
-sa_payload_t *sa_payload_create(void);
+sa_payload_t *sa_payload_create(payload_type_t type);
/**
- * Creates a sa_payload_t object from a list of proposals.
+ * Creates an IKEv2 sa_payload_t object from a list of proposals.
*
* @param proposals list of proposals to build the payload from
* @return sa_payload_t object
*/
-sa_payload_t *sa_payload_create_from_proposal_list(linked_list_t *proposals);
+sa_payload_t *sa_payload_create_from_proposals_v2(linked_list_t *proposals);
/**
- * Creates a sa_payload_t object from a single proposal.
+ * Creates an IKEv2 sa_payload_t object from a single proposal.
*
- * This is only for convenience. Use sa_payload_create_from_proposal_list
- * if you want to add more than one proposal.
+ * @param proposal proposal from which the payload should be built.
+ * @return sa_payload_t object
+ */
+sa_payload_t *sa_payload_create_from_proposal_v2(proposal_t *proposal);
+
+/**
+ * Creates an IKEv1 sa_payload_t object from a list of proposals.
+ *
+ * @param proposals list of proposals to build the payload from
+ * @param lifetime lifetime in seconds
+ * @param lifebytes lifebytes, in bytes
+ * @param auth authentication method to use, or AUTH_NONE
+ * @param mode IPsec encapsulation mode, TRANSPORT or TUNNEL
+ * @param udp TRUE to use UDP encapsulation
+ * @param cpi CPI in case IPComp should be used
+ * @return sa_payload_t object
+ */
+sa_payload_t *sa_payload_create_from_proposals_v1(linked_list_t *proposals,
+ u_int32_t lifetime, u_int64_t lifebytes,
+ auth_method_t auth, ipsec_mode_t mode, bool udp,
+ u_int16_t cpi);
+
+/**
+ * Creates an IKEv1 sa_payload_t object from a single proposal.
*
* @param proposal proposal from which the payload should be built.
+ * @param lifetime lifetime in seconds
+ * @param lifebytes lifebytes, in bytes
+ * @param auth authentication method to use, or AUTH_NONE
+ * @param mode IPsec encapsulation mode, TRANSPORT or TUNNEL
+ * @param udp TRUE to use UDP encapsulation
+ * @param cpi CPI in case IPComp should be used
* @return sa_payload_t object
*/
-sa_payload_t *sa_payload_create_from_proposal(proposal_t *proposal);
+sa_payload_t *sa_payload_create_from_proposal_v1(proposal_t *proposal,
+ u_int32_t lifetime, u_int64_t lifebytes,
+ auth_method_t auth, ipsec_mode_t mode, bool udp,
+ u_int16_t cpi);
#endif /** SA_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/traffic_selector_substructure.c b/src/libcharon/encoding/payloads/traffic_selector_substructure.c
index df36e4383..378f5bbc3 100644
--- a/src/libcharon/encoding/payloads/traffic_selector_substructure.c
+++ b/src/libcharon/encoding/payloads/traffic_selector_substructure.c
@@ -74,7 +74,7 @@ struct private_traffic_selector_substructure_t {
* The defined offsets are the positions in a object of type
* private_traffic_selector_substructure_t.
*/
-encoding_rule_t traffic_selector_substructure_encodings[] = {
+static encoding_rule_t encodings[] = {
/* 1 Byte next ts type*/
{ TS_TYPE, offsetof(private_traffic_selector_substructure_t, ts_type) },
/* 1 Byte IP protocol id*/
@@ -148,12 +148,17 @@ METHOD(payload_t, verify, status_t,
return SUCCESS;
}
-METHOD(payload_t, get_encoding_rules, void,
- private_traffic_selector_substructure_t *this, encoding_rule_t **rules,
- size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, int,
+ private_traffic_selector_substructure_t *this, encoding_rule_t **rules)
{
- *rules = traffic_selector_substructure_encodings;
- *rule_count = countof(traffic_selector_substructure_encodings);
+ *rules = encodings;
+ return countof(encodings);
+}
+
+METHOD(payload_t, get_header_length, int,
+ private_traffic_selector_substructure_t *this)
+{
+ return 8;
}
METHOD(payload_t, get_type, payload_type_t,
@@ -208,6 +213,7 @@ traffic_selector_substructure_t *traffic_selector_substructure_create()
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
+ .get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@@ -217,7 +223,7 @@ traffic_selector_substructure_t *traffic_selector_substructure_create()
.get_traffic_selector = _get_traffic_selector,
.destroy = _destroy,
},
- .payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH,
+ .payload_length = get_header_length(this),
/* must be set to be valid */
.ts_type = TS_IPV4_ADDR_RANGE,
);
@@ -239,7 +245,7 @@ traffic_selector_substructure_t *traffic_selector_substructure_create_from_traff
this->end_port = ts->get_to_port(ts);
this->starting_address = chunk_clone(ts->get_from_address(ts));
this->ending_address = chunk_clone(ts->get_to_address(ts));
- this->payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH +
+ this->payload_length = get_header_length(this) +
this->ending_address.len + this->starting_address.len;
return &this->public;
diff --git a/src/libcharon/encoding/payloads/traffic_selector_substructure.h b/src/libcharon/encoding/payloads/traffic_selector_substructure.h
index 0109fd7f5..1ad5fb526 100644
--- a/src/libcharon/encoding/payloads/traffic_selector_substructure.h
+++ b/src/libcharon/encoding/payloads/traffic_selector_substructure.h
@@ -30,11 +30,6 @@ typedef struct traffic_selector_substructure_t traffic_selector_substructure_t;
#include <encoding/payloads/payload.h>
/**
- * Length of a TRAFFIC SELECTOR SUBSTRUCTURE without start and end address.
- */
-#define TRAFFIC_SELECTOR_HEADER_LENGTH 8
-
-/**
* Class representing an IKEv2 TRAFFIC SELECTOR.
*
* The TRAFFIC SELECTOR format is described in RFC section 3.13.1.
diff --git a/src/libcharon/encoding/payloads/transform_attribute.c b/src/libcharon/encoding/payloads/transform_attribute.c
index 7d21258b1..d20f77c59 100644
--- a/src/libcharon/encoding/payloads/transform_attribute.c
+++ b/src/libcharon/encoding/payloads/transform_attribute.c
@@ -17,12 +17,51 @@
#include <string.h>
#include <stddef.h>
+#include <stdint.h>
#include "transform_attribute.h"
#include <encoding/payloads/encodings.h>
#include <library.h>
+ENUM(tattr_ph1_names, TATTR_PH1_ENCRYPTION_ALGORITHM, TATTR_PH1_GROUP_ORDER,
+ "ENCRYPTION_ALGORITHM",
+ "HASH_ALGORITHM",
+ "AUTH_METHOD",
+ "GROUP",
+ "GROUP_TYPE",
+ "GROUP_PRIME",
+ "GROUP_GENONE",
+ "GROUP_GENTWO",
+ "GROUP_CURVE_A",
+ "GROUP_CURVE_B",
+ "LIFE_TYPE",
+ "LIFE_DURATION",
+ "PRF",
+ "KEY_LENGTH",
+ "FIELD_SIZE",
+ "GROUP_ORDER",
+);
+
+ENUM(tattr_ph2_names, TATTR_PH2_SA_LIFE_TYPE, TATTR_PH2_EXT_SEQ_NUMBER,
+ "SA_LIFE_TYPE",
+ "SA_LIFE_DURATION",
+ "GROUP",
+ "ENCAP_MODE",
+ "AUTH_ALGORITHM",
+ "KEY_LENGTH",
+ "KEY_ROUNDS",
+ "COMP_DICT_SIZE",
+ "COMP_PRIV_ALGORITHM",
+ "ECN_TUNNEL",
+ "EXT_SEQ_NUMBER",
+);
+
+ENUM(tattr_ikev2_names, TATTR_IKEV2_KEY_LENGTH, TATTR_IKEV2_KEY_LENGTH,
+ "KEY_LENGTH",
+);
+
+
typedef struct private_transform_attribute_t private_transform_attribute_t;
/**
@@ -57,30 +96,25 @@ struct private_transform_attribute_t {
* Attribute value as chunk if attribute_format is 0 (FALSE).
*/
chunk_t attribute_value;
-};
-
-ENUM_BEGIN(transform_attribute_type_name, ATTRIBUTE_UNDEFINED, ATTRIBUTE_UNDEFINED,
- "ATTRIBUTE_UNDEFINED");
-ENUM_NEXT(transform_attribute_type_name, KEY_LENGTH, KEY_LENGTH, ATTRIBUTE_UNDEFINED,
- "KEY_LENGTH");
-ENUM_END(transform_attribute_type_name, KEY_LENGTH);
+ /**
+ * Payload type, TRANSFORM_ATTRIBUTE or TRANSFORM_ATTRIBUTE_V1
+ */
+ payload_type_t type;
+};
/**
- * Encoding rules to parse or generate a Transform attribute.
- *
- * The defined offsets are the positions in a object of type
- * private_transform_attribute_t.
+ * Encoding rules for IKEv1/IKEv2 transform attributes
*/
-encoding_rule_t transform_attribute_encodings[] = {
+static encoding_rule_t encodings[] = {
/* Flag defining the format of this payload */
- { ATTRIBUTE_FORMAT, offsetof(private_transform_attribute_t, attribute_format) },
+ { ATTRIBUTE_FORMAT, offsetof(private_transform_attribute_t, attribute_format) },
/* type of the attribute as 15 bit unsigned integer */
{ ATTRIBUTE_TYPE, offsetof(private_transform_attribute_t, attribute_type) },
/* Length or value, depending on the attribute format flag */
{ ATTRIBUTE_LENGTH_OR_VALUE,offsetof(private_transform_attribute_t, attribute_length_or_value) },
/* Value of attribute if attribute format flag is zero */
- { ATTRIBUTE_VALUE, offsetof(private_transform_attribute_t, attribute_value) }
+ { ATTRIBUTE_VALUE, offsetof(private_transform_attribute_t, attribute_value) }
};
/*
@@ -101,18 +135,23 @@ METHOD(payload_t, verify, status_t,
return SUCCESS;
}
-METHOD(payload_t, get_encoding_rules, void,
- private_transform_attribute_t *this, encoding_rule_t **rules,
- size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, int,
+ private_transform_attribute_t *this, encoding_rule_t **rules)
{
- *rules = transform_attribute_encodings;
- *rule_count = countof(transform_attribute_encodings);
+ *rules = encodings;
+ return countof(encodings);
+}
+
+METHOD(payload_t, get_header_length, int,
+ private_transform_attribute_t *this)
+{
+ return 0;
}
METHOD(payload_t, get_type, payload_type_t,
private_transform_attribute_t *this)
{
- return TRANSFORM_ATTRIBUTE;
+ return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
@@ -136,31 +175,6 @@ METHOD(payload_t, get_length, size_t,
return this->attribute_length_or_value + 4;
}
-METHOD(transform_attribute_t, set_value_chunk, void,
- private_transform_attribute_t *this, chunk_t value)
-{
- chunk_free(&this->attribute_value);
-
- if (value.len != 2)
- {
- this->attribute_value = chunk_clone(value);
- this->attribute_length_or_value = value.len;
- this->attribute_format = FALSE;
- }
- else
- {
- memcpy(&this->attribute_length_or_value, value.ptr, value.len);
- }
-}
-
-METHOD(transform_attribute_t, set_value, void,
- private_transform_attribute_t *this, u_int16_t value)
-{
- chunk_free(&this->attribute_value);
- this->attribute_length_or_value = value;
- this->attribute_format = TRUE;
-}
-
METHOD(transform_attribute_t, get_value_chunk, chunk_t,
private_transform_attribute_t *this)
{
@@ -171,16 +185,22 @@ METHOD(transform_attribute_t, get_value_chunk, chunk_t,
return this->attribute_value;
}
-METHOD(transform_attribute_t, get_value, u_int16_t,
+METHOD(transform_attribute_t, get_value, u_int64_t,
private_transform_attribute_t *this)
{
- return this->attribute_length_or_value;
-}
+ u_int64_t value = 0;
-METHOD(transform_attribute_t, set_attribute_type, void,
- private_transform_attribute_t *this, u_int16_t type)
-{
- this->attribute_type = type & 0x7FFF;
+ if (this->attribute_format)
+ {
+ return this->attribute_length_or_value;
+ }
+ if (this->attribute_value.len > sizeof(value))
+ {
+ return UINT64_MAX;
+ }
+ memcpy(((char*)&value) + sizeof(value) - this->attribute_value.len,
+ this->attribute_value.ptr, this->attribute_value.len);
+ return untoh64((char*)&value);
}
METHOD(transform_attribute_t, get_attribute_type, u_int16_t,
@@ -189,24 +209,6 @@ METHOD(transform_attribute_t, get_attribute_type, u_int16_t,
return this->attribute_type;
}
-METHOD(transform_attribute_t, clone_, transform_attribute_t*,
- private_transform_attribute_t *this)
-{
- private_transform_attribute_t *new_clone;
-
- new_clone = (private_transform_attribute_t *)transform_attribute_create();
-
- new_clone->attribute_format = this->attribute_format;
- new_clone->attribute_type = this->attribute_type;
- new_clone->attribute_length_or_value = this->attribute_length_or_value;
-
- if (!new_clone->attribute_format)
- {
- new_clone->attribute_value = chunk_clone(this->attribute_value);
- }
- return &new_clone->public;
-}
-
METHOD2(payload_t, transform_attribute_t, destroy, void,
private_transform_attribute_t *this)
{
@@ -217,7 +219,7 @@ METHOD2(payload_t, transform_attribute_t, destroy, void,
/*
* Described in header.
*/
-transform_attribute_t *transform_attribute_create()
+transform_attribute_t *transform_attribute_create(payload_type_t type)
{
private_transform_attribute_t *this;
@@ -226,22 +228,20 @@ transform_attribute_t *transform_attribute_create()
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
+ .get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
.get_type = _get_type,
.destroy = _destroy,
},
- .set_value_chunk = _set_value_chunk,
- .set_value = _set_value,
.get_value_chunk = _get_value_chunk,
.get_value = _get_value,
- .set_attribute_type = _set_attribute_type,
.get_attribute_type = _get_attribute_type,
- .clone = _clone_,
.destroy = _destroy,
},
- .attribute_format = TRUE,
+ .attribute_format = FALSE,
+ .type = type,
);
return &this->public;
}
@@ -249,10 +249,33 @@ transform_attribute_t *transform_attribute_create()
/*
* Described in header.
*/
-transform_attribute_t *transform_attribute_create_key_length(u_int16_t key_length)
+transform_attribute_t *transform_attribute_create_value(payload_type_t type,
+ transform_attribute_type_t kind, u_int64_t value)
{
- transform_attribute_t *attribute = transform_attribute_create();
- attribute->set_attribute_type(attribute, KEY_LENGTH);
- attribute->set_value(attribute, key_length);
- return attribute;
+ private_transform_attribute_t *this;
+
+ this = (private_transform_attribute_t*)transform_attribute_create(type);
+
+ this->attribute_type = kind & 0x7FFF;
+
+ if (value <= UINT16_MAX)
+ {
+ this->attribute_length_or_value = value;
+ this->attribute_format = TRUE;
+ }
+ else if (value <= UINT32_MAX)
+ {
+ u_int32_t val32;
+
+ val32 = htonl(value);
+ this->attribute_value = chunk_clone(chunk_from_thing(val32));
+ this->attribute_length_or_value = sizeof(val32);
+ }
+ else
+ {
+ htoun64(&value, value);
+ this->attribute_value = chunk_clone(chunk_from_thing(value));
+ this->attribute_length_or_value = sizeof(value);
+ }
+ return &this->public;
}
diff --git a/src/libcharon/encoding/payloads/transform_attribute.h b/src/libcharon/encoding/payloads/transform_attribute.h
index a5fe0154b..23897a50a 100644
--- a/src/libcharon/encoding/payloads/transform_attribute.h
+++ b/src/libcharon/encoding/payloads/transform_attribute.h
@@ -28,26 +28,66 @@ typedef struct transform_attribute_t transform_attribute_t;
#include <library.h>
#include <encoding/payloads/payload.h>
-
/**
- * Type of the attribute, as in IKEv2 RFC 3.3.5.
+ * Type of the attribute.
*/
enum transform_attribute_type_t {
- ATTRIBUTE_UNDEFINED = 16384,
- KEY_LENGTH = 14
+ /** IKEv1 Phase 1 attributes */
+ TATTR_PH1_ENCRYPTION_ALGORITHM = 1,
+ TATTR_PH1_HASH_ALGORITHM = 2,
+ TATTR_PH1_AUTH_METHOD = 3,
+ TATTR_PH1_GROUP = 4,
+ TATTR_PH1_GROUP_TYPE = 5,
+ TATTR_PH1_GROUP_PRIME = 6,
+ TATTR_PH1_GROUP_GENONE = 7,
+ TATTR_PH1_GROUP_GENTWO = 8,
+ TATTR_PH1_GROUP_CURVE_A = 9,
+ TATTR_PH1_GROUP_CURVE_B = 10,
+ TATTR_PH1_LIFE_TYPE = 11,
+ TATTR_PH1_LIFE_DURATION = 12,
+ TATTR_PH1_PRF = 13,
+ TATTR_PH1_KEY_LENGTH = 14,
+ TATTR_PH1_FIELD_SIZE = 15,
+ TATTR_PH1_GROUP_ORDER = 16,
+ /** IKEv1 Phase 2 attributes */
+ TATTR_PH2_SA_LIFE_TYPE = 1,
+ TATTR_PH2_SA_LIFE_DURATION = 2,
+ TATTR_PH2_GROUP = 3,
+ TATTR_PH2_ENCAP_MODE = 4,
+ TATTR_PH2_AUTH_ALGORITHM = 5,
+ TATTR_PH2_KEY_LENGTH = 6,
+ TATTR_PH2_KEY_ROUNDS = 7,
+ TATTR_PH2_COMP_DICT_SIZE = 8,
+ TATTR_PH2_COMP_PRIV_ALGORITHM = 9,
+ TATTR_PH2_ECN_TUNNEL = 10,
+ TATTR_PH2_EXT_SEQ_NUMBER = 11,
+ /* IKEv2 key length attribute */
+ TATTR_IKEV2_KEY_LENGTH = 14,
+ /* undefined, private use attribute */
+ TATTR_UNDEFINED = 16384,
};
/**
- * enum name for transform_attribute_type_t.
+ * Enum names for IKEv1 Phase 1 transform_attribute_type_t.
*/
-extern enum_name_t *transform_attribute_type_names;
+extern enum_name_t *tattr_ph1_names;
/**
- * Class representing an IKEv2- TRANSFORM Attribute.
- *
- * The TRANSFORM ATTRIBUTE format is described in RFC section 3.3.5.
+ * Enum names for IKEv1 Phase 2 transform_attribute_type_t.
+ */
+extern enum_name_t *tattr_ph2_names;
+
+/**
+ * Enum names for IKEv2 transform_attribute_type_t.
+ */
+extern enum_name_t *tattr_ikev2_names;
+
+
+/**
+ * Class representing an IKEv1/IKEv2 TRANSFORM Attribute.
*/
struct transform_attribute_t {
+
/**
* The payload_t interface.
*/
@@ -58,7 +98,7 @@ struct transform_attribute_t {
*
* Returned data are not copied.
*
- * @return chunk_t pointing to the value
+ * @return chunk_t pointing to internal value
*/
chunk_t (*get_value_chunk) (transform_attribute_t *this);
@@ -69,30 +109,7 @@ struct transform_attribute_t {
*
* @return value
*/
- u_int16_t (*get_value) (transform_attribute_t *this);
-
- /**
- * Sets the value of the attribute.
- *
- * Value is getting copied.
- *
- * @param value chunk_t pointing to the value to set
- */
- void (*set_value_chunk) (transform_attribute_t *this, chunk_t value);
-
- /**
- * Sets the value of the attribute.
- *
- * @param value value to set
- */
- void (*set_value) (transform_attribute_t *this, u_int16_t value);
-
- /**
- * Sets the type of the attribute.
- *
- * @param type type to set (most significant bit is set to zero)
- */
- void (*set_attribute_type) (transform_attribute_t *this, u_int16_t type);
+ u_int64_t (*get_value) (transform_attribute_t *this);
/**
* get the type of the attribute.
@@ -102,13 +119,6 @@ struct transform_attribute_t {
u_int16_t (*get_attribute_type) (transform_attribute_t *this);
/**
- * Clones an transform_attribute_t object.
- *
- * @return cloned transform_attribute_t object
- */
- transform_attribute_t * (*clone) (transform_attribute_t *this);
-
- /**
* Destroys an transform_attribute_t object.
*/
void (*destroy) (transform_attribute_t *this);
@@ -117,16 +127,20 @@ struct transform_attribute_t {
/**
* Creates an empty transform_attribute_t object.
*
+ * @param type TRANSFORM_ATTRIBUTE or TRANSFORM_ATTRIBUTE_V1
* @return transform_attribute_t object
*/
-transform_attribute_t *transform_attribute_create(void);
+transform_attribute_t *transform_attribute_create(payload_type_t type);
/**
- * Creates an transform_attribute_t of type KEY_LENGTH.
+ * Creates a two byte value or a larger attribute for a given attribute kind.
*
- * @param key_length key length in bytes
+ * @param type TRANSFORM_ATTRIBUTE or TRANSFORM_ATTRIBUTE_V1
+ * @param kind attribute kind
+ * @param value fixed two byte value
* @return transform_attribute_t object
*/
-transform_attribute_t *transform_attribute_create_key_length(u_int16_t key_length);
+transform_attribute_t *transform_attribute_create_value(payload_type_t type,
+ transform_attribute_type_t kind, u_int64_t value);
#endif /** TRANSFORM_ATTRIBUTE_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/transform_substructure.c b/src/libcharon/encoding/payloads/transform_substructure.c
index 3f04b3539..a4a920b60 100644
--- a/src/libcharon/encoding/payloads/transform_substructure.c
+++ b/src/libcharon/encoding/payloads/transform_substructure.c
@@ -41,10 +41,11 @@ struct private_transform_substructure_t {
* Next payload type.
*/
u_int8_t next_payload;
+
/**
- * Reserved bytes
+ * Reserved byte
*/
- u_int8_t reserved[2];
+ u_int8_t reserved[3];
/**
* Length of this payload.
@@ -52,43 +53,72 @@ struct private_transform_substructure_t {
u_int16_t transform_length;
/**
- * Type of the transform.
+ * Type or number, Type of the transform in IKEv2, number in IKEv2.
+ */
+ u_int8_t transform_ton;
+
+ /**
+ * Transform ID, as encoded in IKEv1.
*/
- u_int8_t transform_type;
+ u_int8_t transform_id_v1;
/**
- * Transform ID.
+ * Transform ID, as encoded in IKEv2.
*/
- u_int16_t transform_id;
+ u_int16_t transform_id_v2;
/**
* Transforms Attributes are stored in a linked_list_t.
*/
linked_list_t *attributes;
+
+ /**
+ * Payload type, TRANSFORM_SUBSTRUCTURE or TRANSFORM_SUBSTRUCTURE_V1
+ */
+ payload_type_t type;
};
/**
- * Encoding rules to parse or generate a Transform substructure.
- *
- * The defined offsets are the positions in a object of type
- * private_transform_substructure_t.
+ * Encoding rules for TRANSFORM_SUBSTRUCTURE
*/
-encoding_rule_t transform_substructure_encodings[] = {
+static encoding_rule_t encodings_v2[] = {
/* 1 Byte next payload type, stored in the field next_payload */
- { U_INT_8, offsetof(private_transform_substructure_t, next_payload) },
+ { U_INT_8, offsetof(private_transform_substructure_t, next_payload) },
/* 1 Reserved Byte */
- { RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[0]) },
+ { RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[0]) },
/* Length of the whole transform substructure*/
- { PAYLOAD_LENGTH, offsetof(private_transform_substructure_t, transform_length)},
- /* transform type is a number of 8 bit */
- { U_INT_8, offsetof(private_transform_substructure_t, transform_type) },
+ { PAYLOAD_LENGTH, offsetof(private_transform_substructure_t, transform_length)},
+ /* transform type */
+ { U_INT_8, offsetof(private_transform_substructure_t, transform_ton) },
+ /* transform identifier, as used by IKEv1 */
+ { RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[1]) },
+ /* transform identifier, as used by IKEv2 */
+ { U_INT_16, offsetof(private_transform_substructure_t, transform_id_v2) },
+ /* Attributes in a transform attribute list */
+ { PAYLOAD_LIST + TRANSFORM_ATTRIBUTE,
+ offsetof(private_transform_substructure_t, attributes) }
+};
+
+/**
+ * Encoding rules for TRANSFORM_SUBSTRUCTURE_V1
+ */
+static encoding_rule_t encodings_v1[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_transform_substructure_t, next_payload) },
/* 1 Reserved Byte */
- { RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[1]) },
- /* transform ID is a number of 8 bit */
- { U_INT_16, offsetof(private_transform_substructure_t, transform_id) },
- /* Attributes are stored in a transform attribute,
- offset points to a linked_list_t pointer */
- { TRANSFORM_ATTRIBUTES, offsetof(private_transform_substructure_t, attributes) }
+ { RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[0]) },
+ /* Length of the whole transform substructure*/
+ { PAYLOAD_LENGTH, offsetof(private_transform_substructure_t, transform_length)},
+ /* transform number */
+ { U_INT_8, offsetof(private_transform_substructure_t, transform_ton)},
+ /* transform identifier, as used by IKEv1 */
+ { U_INT_8, offsetof(private_transform_substructure_t, transform_id_v1) },
+ /* transform identifier, as used by IKEv2 */
+ { RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[1]) },
+ { RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[2]) },
+ /* Attributes in a transform attribute list */
+ { PAYLOAD_LIST + TRANSFORM_ATTRIBUTE_V1,
+ offsetof(private_transform_substructure_t, attributes) }
};
/*
@@ -97,7 +127,7 @@ encoding_rule_t transform_substructure_encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 0 (last) or 3 ! RESERVED ! Transform Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- !Transform Type ! RESERVED ! Transform ID !
+ ! Tfrm Typ or # ! Tfrm ID IKEv1 ! Transform ID IKEv2 !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Transform Attributes ~
@@ -118,23 +148,6 @@ METHOD(payload_t, verify, status_t,
return FAILED;
}
- switch (this->transform_type)
- {
- case ENCRYPTION_ALGORITHM:
- case PSEUDO_RANDOM_FUNCTION:
- case INTEGRITY_ALGORITHM:
- case DIFFIE_HELLMAN_GROUP:
- case EXTENDED_SEQUENCE_NUMBERS:
- /* we don't check transform ID, we want to reply
- * cleanly with NO_PROPOSAL_CHOSEN or so if we don't support it */
- break;
- default:
- {
- DBG1(DBG_ENC, "invalid transform type: %d", this->transform_type);
- return FAILED;
- }
- }
-
enumerator = this->attributes->create_enumerator(this->attributes);
while (enumerator->enumerate(enumerator, &attribute))
{
@@ -151,18 +164,28 @@ METHOD(payload_t, verify, status_t,
return status;
}
-METHOD(payload_t, get_encoding_rules, void,
- private_transform_substructure_t *this, encoding_rule_t **rules,
- size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, int,
+ private_transform_substructure_t *this, encoding_rule_t **rules)
{
- *rules = transform_substructure_encodings;
- *rule_count = countof(transform_substructure_encodings);
+ if (this->type == TRANSFORM_SUBSTRUCTURE)
+ {
+ *rules = encodings_v2;
+ return countof(encodings_v2);
+ }
+ *rules = encodings_v1;
+ return countof(encodings_v1);
+}
+
+METHOD(payload_t, get_header_length, int,
+ private_transform_substructure_t *this)
+{
+ return 8;
}
METHOD(payload_t, get_type, payload_type_t,
private_transform_substructure_t *this)
{
- return TRANSFORM_SUBSTRUCTURE;
+ return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
@@ -174,12 +197,12 @@ METHOD(payload_t, get_next_type, payload_type_t,
/**
* recompute the length of the payload.
*/
-static void compute_length (private_transform_substructure_t *this)
+static void compute_length(private_transform_substructure_t *this)
{
enumerator_t *enumerator;
payload_t *attribute;
- this->transform_length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
+ this->transform_length = get_header_length(this);
enumerator = this->attributes->create_enumerator(this->attributes);
while (enumerator->enumerate(enumerator, &attribute))
{
@@ -194,6 +217,13 @@ METHOD(payload_t, get_length, size_t,
return this->transform_length;
}
+METHOD(transform_substructure_t, add_transform_attribute, void,
+ private_transform_substructure_t *this, transform_attribute_t *attribute)
+{
+ this->attributes->insert_last(this->attributes, attribute);
+ compute_length(this);
+}
+
METHOD(transform_substructure_t, set_is_last_transform, void,
private_transform_substructure_t *this, bool is_last)
{
@@ -205,50 +235,40 @@ METHOD(payload_t, set_next_type, void,
{
}
-METHOD(transform_substructure_t, get_transform_type, u_int8_t,
+METHOD(transform_substructure_t, get_transform_type_or_number, u_int8_t,
private_transform_substructure_t *this)
{
- return this->transform_type;
+ return this->transform_ton;
}
METHOD(transform_substructure_t, get_transform_id, u_int16_t,
private_transform_substructure_t *this)
{
- return this->transform_id;
+ if (this->type == TRANSFORM_SUBSTRUCTURE)
+ {
+ return this->transform_id_v2;
+ }
+ return this->transform_id_v1;
}
-METHOD(transform_substructure_t, get_key_length, status_t,
- private_transform_substructure_t *this, u_int16_t *key_length)
+METHOD(transform_substructure_t, create_attribute_enumerator, enumerator_t*,
+ private_transform_substructure_t *this)
{
- enumerator_t *enumerator;
- transform_attribute_t *attribute;
-
- enumerator = this->attributes->create_enumerator(this->attributes);
- while (enumerator->enumerate(enumerator, &attribute))
- {
- if (attribute->get_attribute_type(attribute) == KEY_LENGTH)
- {
- *key_length = attribute->get_value(attribute);
- enumerator->destroy(enumerator);
- return SUCCESS;
- }
- }
- enumerator->destroy(enumerator);
- return FAILED;
+ return this->attributes->create_enumerator(this->attributes);
}
METHOD2(payload_t, transform_substructure_t, destroy, void,
private_transform_substructure_t *this)
{
this->attributes->destroy_offset(this->attributes,
- offsetof(transform_attribute_t, destroy));
+ offsetof(payload_t, destroy));
free(this);
}
/*
* Described in header.
*/
-transform_substructure_t *transform_substructure_create()
+transform_substructure_t *transform_substructure_create(payload_type_t type)
{
private_transform_substructure_t *this;
@@ -257,21 +277,24 @@ transform_substructure_t *transform_substructure_create()
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
+ .get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
.get_type = _get_type,
.destroy = _destroy,
},
+ .add_transform_attribute = _add_transform_attribute,
.set_is_last_transform = _set_is_last_transform,
- .get_transform_type = _get_transform_type,
+ .get_transform_type_or_number = _get_transform_type_or_number,
.get_transform_id = _get_transform_id,
- .get_key_length = _get_key_length,
+ .create_attribute_enumerator = _create_attribute_enumerator,
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
- .transform_length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH,
+ .transform_length = get_header_length(this),
.attributes = linked_list_create(),
+ .type = type,
);
return &this->public;
}
@@ -279,20 +302,21 @@ transform_substructure_t *transform_substructure_create()
/*
* Described in header
*/
-transform_substructure_t *transform_substructure_create_type(
- transform_type_t type, u_int16_t id, u_int16_t key_length)
+transform_substructure_t *transform_substructure_create_type(payload_type_t type,
+ u_int8_t type_or_number, u_int16_t id)
{
private_transform_substructure_t *this;
- this = (private_transform_substructure_t*)transform_substructure_create();
+ this = (private_transform_substructure_t*)transform_substructure_create(type);
- this->transform_type = type;
- this->transform_id = id;
- if (key_length)
+ this->transform_ton = type_or_number;
+ if (type == TRANSFORM_SUBSTRUCTURE)
+ {
+ this->transform_id_v2 = id;
+ }
+ else
{
- this->attributes->insert_last(this->attributes,
- (void*)transform_attribute_create_key_length(key_length));
- compute_length(this);
+ this->transform_id_v1 = id;
}
return &this->public;
}
diff --git a/src/libcharon/encoding/payloads/transform_substructure.h b/src/libcharon/encoding/payloads/transform_substructure.h
index 102dbb3d3..947df24f9 100644
--- a/src/libcharon/encoding/payloads/transform_substructure.h
+++ b/src/libcharon/encoding/payloads/transform_substructure.h
@@ -40,14 +40,7 @@ typedef struct transform_substructure_t transform_substructure_t;
#define TRANSFORM_TYPE_VALUE 3
/**
- * Length of the transform substructure header in bytes.
- */
-#define TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH 8
-
-/**
- * Class representing an IKEv2- TRANSFORM SUBSTRUCTURE.
- *
- * The TRANSFORM SUBSTRUCTURE format is described in RFC section 3.3.2.
+ * Class representing an IKEv1/IKEv2 transform substructure.
*/
struct transform_substructure_t {
@@ -75,11 +68,11 @@ struct transform_substructure_t {
void (*set_is_last_transform) (transform_substructure_t *this, bool is_last);
/**
- * get transform type of the current transform.
+ * Get transform type (IKEv2) or the transform number (IKEv1).
*
* @return Transform type of current transform substructure.
*/
- u_int8_t (*get_transform_type) (transform_substructure_t *this);
+ u_int8_t (*get_transform_type_or_number) (transform_substructure_t *this);
/**
* Get transform id of the current transform.
@@ -89,16 +82,11 @@ struct transform_substructure_t {
u_int16_t (*get_transform_id) (transform_substructure_t *this);
/**
- * Get transform id of the current transform.
+ * Create an enumerator over transform attributes.
*
- * @param key_length The key length is written to this location
- * @return
- * - SUCCESS if a key length attribute is contained
- * - FAILED if no key length attribute is part of this
- * transform or key length uses more then 16 bit!
+ * @return enumerator over transform_attribute_t*
*/
- status_t (*get_key_length) (transform_substructure_t *this,
- u_int16_t *key_length);
+ enumerator_t* (*create_attribute_enumerator)(transform_substructure_t *this);
/**
* Destroys an transform_substructure_t object.
@@ -109,19 +97,20 @@ struct transform_substructure_t {
/**
* Creates an empty transform_substructure_t object.
*
+ * @param type TRANSFORM_SUBSTRUCTURE or TRANSFORM_SUBSTRUCTURE_V1
* @return created transform_substructure_t object
*/
-transform_substructure_t *transform_substructure_create(void);
+transform_substructure_t *transform_substructure_create(payload_type_t type);
/**
* Creates an empty transform_substructure_t object.
*
- * @param type type of transform to create
- * @param id transform id specifc for the transform type
- * @param key_length key length for key length attribute, 0 to omit
- * @return transform_substructure_t object
+ * @param type TRANSFORM_SUBSTRUCTURE or TRANSFORM_SUBSTRUCTURE_V1
+ * @param type_or_number Type (IKEv2) or number (IKEv1) of transform
+ * @param id transform id specifc for the transform type
+ * @return transform_substructure_t object
*/
-transform_substructure_t *transform_substructure_create_type(
- transform_type_t type, u_int16_t id, u_int16_t key_length);
+transform_substructure_t *transform_substructure_create_type(payload_type_t type,
+ u_int8_t type_or_number, u_int16_t id);
#endif /** TRANSFORM_SUBSTRUCTURE_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/ts_payload.c b/src/libcharon/encoding/payloads/ts_payload.c
index 28f760e40..a7678da73 100644
--- a/src/libcharon/encoding/payloads/ts_payload.c
+++ b/src/libcharon/encoding/payloads/ts_payload.c
@@ -81,7 +81,7 @@ struct private_ts_payload_t {
* The defined offsets are the positions in a object of type
* private_ts_payload_t.
*/
-encoding_rule_t ts_payload_encodings[] = {
+static encoding_rule_t encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_ts_payload_t, next_payload) },
/* the critical bit */
@@ -102,8 +102,9 @@ encoding_rule_t ts_payload_encodings[] = {
{ RESERVED_BYTE, offsetof(private_ts_payload_t, reserved_byte[0])},
{ RESERVED_BYTE, offsetof(private_ts_payload_t, reserved_byte[1])},
{ RESERVED_BYTE, offsetof(private_ts_payload_t, reserved_byte[2])},
- /* some ts data bytes, length is defined in PAYLOAD_LENGTH */
- { TRAFFIC_SELECTORS,offsetof(private_ts_payload_t, substrs) }
+ /* wrapped list of traffic selectors substructures */
+ { PAYLOAD_LIST + TRAFFIC_SELECTOR_SUBSTRUCTURE,
+ offsetof(private_ts_payload_t, substrs) },
};
/*
@@ -145,11 +146,17 @@ METHOD(payload_t, verify, status_t,
return status;
}
-METHOD(payload_t, get_encoding_rules, void,
- private_ts_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, int,
+ private_ts_payload_t *this, encoding_rule_t **rules)
{
- *rules = ts_payload_encodings;
- *rule_count = countof(ts_payload_encodings);
+ *rules = encodings;
+ return countof(encodings);
+}
+
+METHOD(payload_t, get_header_length, int,
+ private_ts_payload_t *this)
+{
+ return 8;
}
METHOD(payload_t, get_type, payload_type_t,
@@ -182,7 +189,7 @@ static void compute_length(private_ts_payload_t *this)
enumerator_t *enumerator;
payload_t *subst;
- this->payload_length = TS_PAYLOAD_HEADER_LENGTH;
+ this->payload_length = get_header_length(this);
this->ts_num = 0;
enumerator = this->substrs->create_enumerator(this->substrs);
while (enumerator->enumerate(enumerator, &subst))
@@ -250,6 +257,7 @@ ts_payload_t *ts_payload_create(bool is_initiator)
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
+ .get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@@ -262,7 +270,7 @@ ts_payload_t *ts_payload_create(bool is_initiator)
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
- .payload_length = TS_PAYLOAD_HEADER_LENGTH,
+ .payload_length = get_header_length(this),
.is_initiator = is_initiator,
.substrs = linked_list_create(),
);
diff --git a/src/libcharon/encoding/payloads/ts_payload.h b/src/libcharon/encoding/payloads/ts_payload.h
index 88ca00bc9..5a92655dc 100644
--- a/src/libcharon/encoding/payloads/ts_payload.h
+++ b/src/libcharon/encoding/payloads/ts_payload.h
@@ -31,11 +31,6 @@ typedef struct ts_payload_t ts_payload_t;
#include <encoding/payloads/traffic_selector_substructure.h>
/**
- * Length of a TS payload without the Traffic selectors.
- */
-#define TS_PAYLOAD_HEADER_LENGTH 8
-
-/**
* Class representing an IKEv2 TS payload.
*
* The TS payload format is described in RFC section 3.13.
diff --git a/src/libcharon/encoding/payloads/unknown_payload.c b/src/libcharon/encoding/payloads/unknown_payload.c
index 27af338b3..fe7ced20b 100644
--- a/src/libcharon/encoding/payloads/unknown_payload.c
+++ b/src/libcharon/encoding/payloads/unknown_payload.c
@@ -68,7 +68,7 @@ struct private_unknown_payload_t {
* private_unknown_payload_t.
*
*/
-encoding_rule_t unknown_payload_encodings[] = {
+static encoding_rule_t encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_unknown_payload_t, next_payload) },
/* the critical bit */
@@ -84,7 +84,7 @@ encoding_rule_t unknown_payload_encodings[] = {
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_unknown_payload_t, payload_length) },
/* some unknown data bytes, length is defined in PAYLOAD_LENGTH */
- { UNKNOWN_DATA, offsetof(private_unknown_payload_t, data) },
+ { CHUNK_DATA, offsetof(private_unknown_payload_t, data) },
};
/*
@@ -102,18 +102,20 @@ encoding_rule_t unknown_payload_encodings[] = {
METHOD(payload_t, verify, status_t,
private_unknown_payload_t *this)
{
- if (this->payload_length != UNKNOWN_PAYLOAD_HEADER_LENGTH + this->data.len)
- {
- return FAILED;
- }
return SUCCESS;
}
-METHOD(payload_t, get_encoding_rules, void,
- private_unknown_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, int,
+ private_unknown_payload_t *this, encoding_rule_t **rules)
{
- *rules = unknown_payload_encodings;
- *rule_count = sizeof(unknown_payload_encodings) / sizeof(encoding_rule_t);
+ *rules = encodings;
+ return countof(encodings);
+}
+
+METHOD(payload_t, get_header_length, int,
+ private_unknown_payload_t *this)
+{
+ return 4;
}
METHOD(payload_t, get_payload_type, payload_type_t,
@@ -171,6 +173,7 @@ unknown_payload_t *unknown_payload_create(payload_type_t type)
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
+ .get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@@ -182,7 +185,7 @@ unknown_payload_t *unknown_payload_create(payload_type_t type)
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
- .payload_length = UNKNOWN_PAYLOAD_HEADER_LENGTH,
+ .payload_length = get_header_length(this),
.type = type,
);
@@ -201,7 +204,7 @@ unknown_payload_t *unknown_payload_create_data(payload_type_t type,
this = (private_unknown_payload_t*)unknown_payload_create(type);
this->data = data;
this->critical = critical;
- this->payload_length = UNKNOWN_PAYLOAD_HEADER_LENGTH + data.len;
+ this->payload_length = get_header_length(this) + data.len;
return &this->public;
}
diff --git a/src/libcharon/encoding/payloads/unknown_payload.h b/src/libcharon/encoding/payloads/unknown_payload.h
index 5ae85331b..326b550cd 100644
--- a/src/libcharon/encoding/payloads/unknown_payload.h
+++ b/src/libcharon/encoding/payloads/unknown_payload.h
@@ -28,11 +28,6 @@ typedef struct unknown_payload_t unknown_payload_t;
#include <encoding/payloads/payload.h>
/**
- * Header length of the unknown payload.
- */
-#define UNKNOWN_PAYLOAD_HEADER_LENGTH 4
-
-/**
* Payload which can't be processed further.
*
* When the parser finds an unknown payload, he builds an instance of
diff --git a/src/libcharon/encoding/payloads/vendor_id_payload.c b/src/libcharon/encoding/payloads/vendor_id_payload.c
index e9e80e989..0c1df56e2 100644
--- a/src/libcharon/encoding/payloads/vendor_id_payload.c
+++ b/src/libcharon/encoding/payloads/vendor_id_payload.c
@@ -55,6 +55,11 @@ struct private_vendor_id_payload_t {
* The contained data.
*/
chunk_t data;
+
+ /**
+ * Either a IKEv1 or a IKEv2 vendor ID payload
+ */
+ payload_type_t type;
};
/**
@@ -63,7 +68,7 @@ struct private_vendor_id_payload_t {
* The defined offsets are the positions in a object of type
* private_vendor_id_payload_t.
*/
-encoding_rule_t vendor_id_payload_encodings[] = {
+static encoding_rule_t encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_vendor_id_payload_t, next_payload) },
/* the critical bit */
@@ -79,7 +84,7 @@ encoding_rule_t vendor_id_payload_encodings[] = {
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_vendor_id_payload_t, payload_length)},
/* some vendor_id data bytes, length is defined in PAYLOAD_LENGTH */
- { VID_DATA, offsetof(private_vendor_id_payload_t, data) }
+ { CHUNK_DATA, offsetof(private_vendor_id_payload_t, data) }
};
/*
@@ -100,18 +105,23 @@ METHOD(payload_t, verify, status_t,
return SUCCESS;
}
-METHOD(payload_t, get_encoding_rules, void,
- private_vendor_id_payload_t *this, encoding_rule_t **rules,
- size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, int,
+ private_vendor_id_payload_t *this, encoding_rule_t **rules)
+{
+ *rules = encodings;
+ return countof(encodings);
+}
+
+METHOD(payload_t, get_header_length, int,
+ private_vendor_id_payload_t *this)
{
- *rules = vendor_id_payload_encodings;
- *rule_count = countof(vendor_id_payload_encodings);
+ return 4;
}
METHOD(payload_t, get_type, payload_type_t,
private_vendor_id_payload_t *this)
{
- return VENDOR_ID;
+ return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
@@ -148,7 +158,8 @@ METHOD2(payload_t, vendor_id_payload_t, destroy, void,
/*
* Described in header
*/
-vendor_id_payload_t *vendor_id_payload_create_data(chunk_t data)
+vendor_id_payload_t *vendor_id_payload_create_data(payload_type_t type,
+ chunk_t data)
{
private_vendor_id_payload_t *this;
@@ -157,6 +168,7 @@ vendor_id_payload_t *vendor_id_payload_create_data(chunk_t data)
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
+ .get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@@ -167,8 +179,9 @@ vendor_id_payload_t *vendor_id_payload_create_data(chunk_t data)
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
- .payload_length = VENDOR_ID_PAYLOAD_HEADER_LENGTH + data.len,
+ .payload_length = get_header_length(this) + data.len,
.data = data,
+ .type = type,
);
return &this->public;
}
@@ -176,7 +189,7 @@ vendor_id_payload_t *vendor_id_payload_create_data(chunk_t data)
/*
* Described in header
*/
-vendor_id_payload_t *vendor_id_payload_create()
+vendor_id_payload_t *vendor_id_payload_create(payload_type_t type)
{
- return vendor_id_payload_create_data(chunk_empty);
+ return vendor_id_payload_create_data(type, chunk_empty);
}
diff --git a/src/libcharon/encoding/payloads/vendor_id_payload.h b/src/libcharon/encoding/payloads/vendor_id_payload.h
index 4e4e7d8eb..9a814777b 100644
--- a/src/libcharon/encoding/payloads/vendor_id_payload.h
+++ b/src/libcharon/encoding/payloads/vendor_id_payload.h
@@ -28,12 +28,7 @@ typedef struct vendor_id_payload_t vendor_id_payload_t;
#include <encoding/payloads/payload.h>
/**
- * Length of a VENDOR ID payload without the VID data in bytes.
- */
-#define VENDOR_ID_PAYLOAD_HEADER_LENGTH 4
-
-/**
- * Class representing an IKEv2 VENDOR ID payload.
+ * Class representing an IKEv1/IKEv2 VENDOR ID payload.
*
* The VENDOR ID payload format is described in RFC section 3.12.
*/
@@ -58,18 +53,21 @@ struct vendor_id_payload_t {
};
/**
- * Creates an empty Vendor ID payload.
+ * Creates an empty Vendor ID payload for IKEv1 or IKEv2.
*
+ * @@param type VENDOR_ID or VENDOR_ID_V1
* @return vendor ID payload
*/
-vendor_id_payload_t *vendor_id_payload_create();
+vendor_id_payload_t *vendor_id_payload_create(payload_type_t type);
/**
* Creates a vendor ID payload using a chunk of data
*
+ * @param type VENDOR_ID or VENDOR_ID_V1
* @param data data to use in vendor ID payload, gets owned by payload
* @return vendor ID payload
*/
-vendor_id_payload_t *vendor_id_payload_create_data(chunk_t data);
+vendor_id_payload_t *vendor_id_payload_create_data(payload_type_t type,
+ chunk_t data);
#endif /** VENDOR_ID_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/kernel/kernel_handler.c b/src/libcharon/kernel/kernel_handler.c
index 51fccb1ac..aa5c4e059 100644
--- a/src/libcharon/kernel/kernel_handler.c
+++ b/src/libcharon/kernel/kernel_handler.c
@@ -84,7 +84,7 @@ METHOD(kernel_listener_t, expire, bool,
protocol_id_names, proto, ntohl(spi), reqid);
if (hard)
{
- job = (job_t*)delete_child_sa_job_create(reqid, proto, spi);
+ job = (job_t*)delete_child_sa_job_create(reqid, proto, spi, hard);
}
else
{
diff --git a/src/libcharon/network/packet.h b/src/libcharon/network/packet.h
deleted file mode 100644
index 18d82c6fc..000000000
--- a/src/libcharon/network/packet.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2005-2006 Martin Willi
- * Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup packet packet
- * @{ @ingroup network
- */
-
-#ifndef PACKET_H_
-#define PACKET_H_
-
-typedef struct packet_t packet_t;
-
-#include <library.h>
-#include <utils/host.h>
-
-/**
- * Abstraction of an UDP-Packet, contains data, sender and receiver.
- */
-struct packet_t {
-
- /**
- * Set the source address.
- *
- * Set host_t is now owned by packet_t, it will destroy
- * it if necessary.
- *
- * @param source address to set as source
- */
- void (*set_source) (packet_t *packet, host_t *source);
-
- /**
- * Set the destination address.
- *
- * Set host_t is now owned by packet_t, it will destroy
- * it if necessary.
- *
- * @param source address to set as destination
- */
- void (*set_destination) (packet_t *packet, host_t *destination);
-
- /**
- * Get the source address.
- *
- * Set host_t is still owned by packet_t, clone it
- * if needed.
- *
- * @return source address
- */
- host_t *(*get_source) (packet_t *packet);
-
- /**
- * Get the destination address.
- *
- * Set host_t is still owned by packet_t, clone it
- * if needed.
- *
- * @return destination address
- */
- host_t *(*get_destination) (packet_t *packet);
-
- /**
- * Get the data from the packet.
- *
- * The data pointed by the chunk is still owned
- * by the packet. Clone it if needed.
- *
- * @return chunk containing the data
- */
- chunk_t (*get_data) (packet_t *packet);
-
- /**
- * Set the data in the packet.
- *
- * Supplied chunk data is now owned by the
- * packet. It will free it.
- *
- * @param data chunk with data to set
- */
- void (*set_data) (packet_t *packet, chunk_t data);
-
- /**
- * Clones a packet_t object.
- *
- * @param clone clone of the packet
- */
- packet_t* (*clone) (packet_t *packet);
-
- /**
- * Destroy the packet, freeing contained data.
- */
- void (*destroy) (packet_t *packet);
-};
-
-/**
- * create an empty packet
- *
- * @return packet_t object
- */
-packet_t *packet_create(void);
-
-#endif /** PACKET_H_ @}*/
diff --git a/src/libcharon/network/receiver.c b/src/libcharon/network/receiver.c
index cfb1408ef..2f87a5ecb 100644
--- a/src/libcharon/network/receiver.c
+++ b/src/libcharon/network/receiver.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2008-2012 Tobias Brunner
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -20,13 +20,15 @@
#include "receiver.h"
+#include <hydra.h>
#include <daemon.h>
#include <network/socket.h>
-#include <network/packet.h>
#include <processing/jobs/job.h>
#include <processing/jobs/process_message_job.h>
#include <processing/jobs/callback_job.h>
#include <crypto/hashers/hasher.h>
+#include <threading/mutex.h>
+#include <utils/packet.h>
/** lifetime of a cookie, in seconds */
#define COOKIE_LIFETIME 10
@@ -40,6 +42,8 @@
#define BLOCK_THRESHOLD_DEFAULT 5
/** length of the secret to use for cookie calculation */
#define SECRET_LENGTH 16
+/** Length of a notify payload header */
+#define NOTIFY_PAYLOAD_HEADER_LENGTH 8
typedef struct private_receiver_t private_receiver_t;
@@ -53,9 +57,17 @@ struct private_receiver_t {
receiver_t public;
/**
- * Threads job receiving packets
+ * Registered callback for ESP packets
*/
- callback_job_t *job;
+ struct {
+ receiver_esp_cb_t cb;
+ void *data;
+ } esp_cb;
+
+ /**
+ * Mutex for ESP callback
+ */
+ mutex_t *esp_cb_mutex;
/**
* current secret to use for cookie calculation
@@ -141,41 +153,41 @@ struct private_receiver_t {
/**
* send a notify back to the sender
*/
-static void send_notify(message_t *request, notify_type_t type, chunk_t data)
+static void send_notify(message_t *request, int major, exchange_type_t exchange,
+ notify_type_t type, chunk_t data)
{
- if (request->get_request(request) &&
- request->get_exchange_type(request) == IKE_SA_INIT)
+ ike_sa_id_t *ike_sa_id;
+ message_t *response;
+ host_t *src, *dst;
+ packet_t *packet;
+
+ response = message_create(major, 0);
+ response->set_exchange_type(response, exchange);
+ response->add_notify(response, FALSE, type, data);
+ dst = request->get_source(request);
+ src = request->get_destination(request);
+ response->set_source(response, src->clone(src));
+ response->set_destination(response, dst->clone(dst));
+ if (major == IKEV2_MAJOR_VERSION)
{
- message_t *response;
- host_t *src, *dst;
- packet_t *packet;
- ike_sa_id_t *ike_sa_id;
-
- response = message_create();
- dst = request->get_source(request);
- src = request->get_destination(request);
- response->set_source(response, src->clone(src));
- response->set_destination(response, dst->clone(dst));
- response->set_exchange_type(response, request->get_exchange_type(request));
response->set_request(response, FALSE);
- response->set_message_id(response, 0);
- ike_sa_id = request->get_ike_sa_id(request);
- ike_sa_id->switch_initiator(ike_sa_id);
- response->set_ike_sa_id(response, ike_sa_id);
- response->add_notify(response, FALSE, type, data);
- if (response->generate(response, NULL, &packet) == SUCCESS)
- {
- charon->sender->send(charon->sender, packet);
- response->destroy(response);
- }
}
+ response->set_message_id(response, 0);
+ ike_sa_id = request->get_ike_sa_id(request);
+ ike_sa_id->switch_initiator(ike_sa_id);
+ response->set_ike_sa_id(response, ike_sa_id);
+ if (response->generate(response, NULL, &packet) == SUCCESS)
+ {
+ charon->sender->send(charon->sender, packet);
+ }
+ response->destroy(response);
}
/**
* build a cookie
*/
-static chunk_t cookie_build(private_receiver_t *this, message_t *message,
- u_int32_t t, chunk_t secret)
+static bool cookie_build(private_receiver_t *this, message_t *message,
+ u_int32_t t, chunk_t secret, chunk_t *cookie)
{
u_int64_t spi = message->get_initiator_spi(message);
host_t *ip = message->get_source(message);
@@ -185,8 +197,12 @@ static chunk_t cookie_build(private_receiver_t *this, message_t *message,
input = chunk_cata("cccc", ip->get_address(ip), chunk_from_thing(spi),
chunk_from_thing(t), secret);
hash = chunk_alloca(this->hasher->get_hash_size(this->hasher));
- this->hasher->get_hash(this->hasher, input, hash.ptr);
- return chunk_cat("cc", chunk_from_thing(t), hash);
+ if (!this->hasher->get_hash(this->hasher, input, hash.ptr))
+ {
+ return FALSE;
+ }
+ *cookie = chunk_cat("cc", chunk_from_thing(t), hash);
+ return TRUE;
}
/**
@@ -221,7 +237,10 @@ static bool cookie_verify(private_receiver_t *this, message_t *message,
}
/* compare own calculation against received */
- reference = cookie_build(this, message, t, secret);
+ if (!cookie_build(this, message, t, secret, &reference))
+ {
+ return FALSE;
+ }
if (chunk_equals(reference, cookie))
{
chunk_free(&reference);
@@ -308,29 +327,42 @@ static bool drop_ike_sa_init(private_receiver_t *this, message_t *message)
half_open = charon->ike_sa_manager->get_half_open_count(
charon->ike_sa_manager, NULL);
- /* check for cookies */
- if (cookie_required(this, half_open, now) && !check_cookie(this, message))
+ /* check for cookies in IKEv2 */
+ if (message->get_major_version(message) == IKEV2_MAJOR_VERSION &&
+ cookie_required(this, half_open, now) && !check_cookie(this, message))
{
chunk_t cookie;
- cookie = cookie_build(this, message, now - this->secret_offset,
- chunk_from_thing(this->secret));
DBG2(DBG_NET, "received packet from: %#H to %#H",
message->get_source(message),
message->get_destination(message));
+ if (!cookie_build(this, message, now - this->secret_offset,
+ chunk_from_thing(this->secret), &cookie))
+ {
+ return TRUE;
+ }
DBG2(DBG_NET, "sending COOKIE notify to %H",
message->get_source(message));
- send_notify(message, COOKIE, cookie);
+ send_notify(message, IKEV2_MAJOR_VERSION, IKE_SA_INIT, COOKIE, cookie);
chunk_free(&cookie);
if (++this->secret_used > COOKIE_REUSE)
{
- /* create new cookie */
+ char secret[SECRET_LENGTH];
+
DBG1(DBG_NET, "generating new cookie secret after %d uses",
this->secret_used);
- memcpy(this->secret_old, this->secret, SECRET_LENGTH);
- this->rng->get_bytes(this->rng, SECRET_LENGTH, this->secret);
- this->secret_switch = now;
- this->secret_used = 0;
+ if (this->rng->get_bytes(this->rng, SECRET_LENGTH, secret))
+ {
+ memcpy(this->secret_old, this->secret, SECRET_LENGTH);
+ memcpy(this->secret, secret, SECRET_LENGTH);
+ memwipe(secret, SECRET_LENGTH);
+ this->secret_switch = now;
+ this->secret_used = 0;
+ }
+ else
+ {
+ DBG1(DBG_NET, "failed to allocated cookie secret, keeping old");
+ }
}
return TRUE;
}
@@ -380,16 +412,18 @@ static bool drop_ike_sa_init(private_receiver_t *this, message_t *message)
*/
static job_requeue_t receive_packets(private_receiver_t *this)
{
+ ike_sa_id_t *id;
packet_t *packet;
message_t *message;
+ host_t *src, *dst;
status_t status;
+ bool supported = TRUE;
+ chunk_t data, marker = chunk_from_chars(0x00, 0x00, 0x00, 0x00);
/* read in a packet */
status = charon->socket->receive(charon->socket, &packet);
if (status == NOT_SUPPORTED)
{
- /* the processor destroys this job */
- this->job = NULL;
return JOB_REQUEUE_NONE;
}
else if (status != SUCCESS)
@@ -398,6 +432,56 @@ static job_requeue_t receive_packets(private_receiver_t *this)
return JOB_REQUEUE_FAIR;
}
+ data = packet->get_data(packet);
+ if (data.len == 1 && data.ptr[0] == 0xFF)
+ { /* silently drop NAT-T keepalives */
+ packet->destroy(packet);
+ return JOB_REQUEUE_DIRECT;
+ }
+ else if (data.len < marker.len)
+ { /* drop packets that are too small */
+ DBG3(DBG_NET, "received packet is too short (%d bytes)", data.len);
+ packet->destroy(packet);
+ return JOB_REQUEUE_DIRECT;
+ }
+
+ dst = packet->get_destination(packet);
+ src = packet->get_source(packet);
+ if (!hydra->kernel_interface->all_interfaces_usable(hydra->kernel_interface)
+ && !hydra->kernel_interface->get_interface(hydra->kernel_interface,
+ dst, NULL))
+ {
+ DBG3(DBG_NET, "received packet from %#H to %#H on ignored interface",
+ src, dst);
+ packet->destroy(packet);
+ return JOB_REQUEUE_DIRECT;
+ }
+
+ /* if neither source nor destination port is 500 we assume an IKE packet
+ * with Non-ESP marker or an ESP packet */
+ if (dst->get_port(dst) != IKEV2_UDP_PORT &&
+ src->get_port(src) != IKEV2_UDP_PORT)
+ {
+ if (memeq(data.ptr, marker.ptr, marker.len))
+ { /* remove Non-ESP marker */
+ packet->skip_bytes(packet, marker.len);
+ }
+ else
+ { /* this seems to be an ESP packet */
+ this->esp_cb_mutex->lock(this->esp_cb_mutex);
+ if (this->esp_cb.cb)
+ {
+ this->esp_cb.cb(this->esp_cb.data, packet);
+ }
+ else
+ {
+ packet->destroy(packet);
+ }
+ this->esp_cb_mutex->unlock(this->esp_cb_mutex);
+ return JOB_REQUEUE_DIRECT;
+ }
+ }
+
/* parse message header */
message = message_create_from_packet(packet);
if (message->parse_header(message) != SUCCESS)
@@ -409,16 +493,50 @@ static job_requeue_t receive_packets(private_receiver_t *this)
}
/* check IKE major version */
- if (message->get_major_version(message) != IKE_MAJOR_VERSION)
+ switch (message->get_major_version(message))
{
- DBG1(DBG_NET, "received unsupported IKE version %d.%d from %H, "
- "sending INVALID_MAJOR_VERSION", message->get_major_version(message),
+ case IKEV2_MAJOR_VERSION:
+#ifndef USE_IKEV2
+ if (message->get_exchange_type(message) == IKE_SA_INIT &&
+ message->get_request(message))
+ {
+ send_notify(message, IKEV1_MAJOR_VERSION, INFORMATIONAL_V1,
+ INVALID_MAJOR_VERSION, chunk_empty);
+ supported = FALSE;
+ }
+#endif /* USE_IKEV2 */
+ break;
+ case IKEV1_MAJOR_VERSION:
+#ifndef USE_IKEV1
+ if (message->get_exchange_type(message) == ID_PROT ||
+ message->get_exchange_type(message) == AGGRESSIVE)
+ {
+ send_notify(message, IKEV2_MAJOR_VERSION, INFORMATIONAL,
+ INVALID_MAJOR_VERSION, chunk_empty);
+ supported = FALSE;
+ }
+#endif /* USE_IKEV1 */
+ break;
+ default:
+#ifdef USE_IKEV2
+ send_notify(message, IKEV2_MAJOR_VERSION, INFORMATIONAL,
+ INVALID_MAJOR_VERSION, chunk_empty);
+#endif /* USE_IKEV2 */
+#ifdef USE_IKEV1
+ send_notify(message, IKEV1_MAJOR_VERSION, INFORMATIONAL_V1,
+ INVALID_MAJOR_VERSION, chunk_empty);
+#endif /* USE_IKEV1 */
+ supported = FALSE;
+ break;
+ }
+ if (!supported)
+ {
+ DBG1(DBG_NET, "received unsupported IKE version %d.%d from %H, sending "
+ "INVALID_MAJOR_VERSION", message->get_major_version(message),
message->get_minor_version(message), packet->get_source(packet));
- send_notify(message, INVALID_MAJOR_VERSION, chunk_empty);
message->destroy(message);
return JOB_REQUEUE_DIRECT;
}
-
if (message->get_request(message) &&
message->get_exchange_type(message) == IKE_SA_INIT)
{
@@ -428,6 +546,18 @@ static job_requeue_t receive_packets(private_receiver_t *this)
return JOB_REQUEUE_DIRECT;
}
}
+ if (message->get_exchange_type(message) == ID_PROT ||
+ message->get_exchange_type(message) == AGGRESSIVE)
+ {
+ id = message->get_ike_sa_id(message);
+ if (id->get_responder_spi(id) == 0 &&
+ drop_ike_sa_init(this, message))
+ {
+ message->destroy(message);
+ return JOB_REQUEUE_DIRECT;
+ }
+ }
+
if (this->receive_delay)
{
if (this->receive_delay_type == 0 ||
@@ -450,15 +580,33 @@ static job_requeue_t receive_packets(private_receiver_t *this)
return JOB_REQUEUE_DIRECT;
}
-METHOD(receiver_t, destroy, void,
- private_receiver_t *this)
+METHOD(receiver_t, add_esp_cb, void,
+ private_receiver_t *this, receiver_esp_cb_t callback, void *data)
+{
+ this->esp_cb_mutex->lock(this->esp_cb_mutex);
+ this->esp_cb.cb = callback;
+ this->esp_cb.data = data;
+ this->esp_cb_mutex->unlock(this->esp_cb_mutex);
+}
+
+METHOD(receiver_t, del_esp_cb, void,
+ private_receiver_t *this, receiver_esp_cb_t callback)
{
- if (this->job)
+ this->esp_cb_mutex->lock(this->esp_cb_mutex);
+ if (this->esp_cb.cb == callback)
{
- this->job->cancel(this->job);
+ this->esp_cb.cb = NULL;
+ this->esp_cb.data = NULL;
}
+ this->esp_cb_mutex->unlock(this->esp_cb_mutex);
+}
+
+METHOD(receiver_t, destroy, void,
+ private_receiver_t *this)
+{
this->rng->destroy(this->rng);
this->hasher->destroy(this->hasher);
+ this->esp_cb_mutex->destroy(this->esp_cb_mutex);
free(this);
}
@@ -472,53 +620,62 @@ receiver_t *receiver_create()
INIT(this,
.public = {
+ .add_esp_cb = _add_esp_cb,
+ .del_esp_cb = _del_esp_cb,
.destroy = _destroy,
},
+ .esp_cb_mutex = mutex_create(MUTEX_TYPE_DEFAULT),
.secret_switch = now,
.secret_offset = random() % now,
);
- if (lib->settings->get_bool(lib->settings, "charon.dos_protection", TRUE))
+ if (lib->settings->get_bool(lib->settings,
+ "%s.dos_protection", TRUE, charon->name))
{
this->cookie_threshold = lib->settings->get_int(lib->settings,
- "charon.cookie_threshold", COOKIE_THRESHOLD_DEFAULT);
+ "%s.cookie_threshold", COOKIE_THRESHOLD_DEFAULT, charon->name);
this->block_threshold = lib->settings->get_int(lib->settings,
- "charon.block_threshold", BLOCK_THRESHOLD_DEFAULT);
+ "%s.block_threshold", BLOCK_THRESHOLD_DEFAULT, charon->name);
}
this->init_limit_job_load = lib->settings->get_int(lib->settings,
- "charon.init_limit_job_load", 0);
+ "%s.init_limit_job_load", 0, charon->name);
this->init_limit_half_open = lib->settings->get_int(lib->settings,
- "charon.init_limit_half_open", 0);
+ "%s.init_limit_half_open", 0, charon->name);
this->receive_delay = lib->settings->get_int(lib->settings,
- "charon.receive_delay", 0);
+ "%s.receive_delay", 0, charon->name);
this->receive_delay_type = lib->settings->get_int(lib->settings,
- "charon.receive_delay_type", 0),
+ "%s.receive_delay_type", 0, charon->name),
this->receive_delay_request = lib->settings->get_bool(lib->settings,
- "charon.receive_delay_request", TRUE),
- this->receive_delay_response = lib->settings->get_int(lib->settings,
- "charon.receive_delay_response", TRUE),
+ "%s.receive_delay_request", TRUE, charon->name),
+ this->receive_delay_response = lib->settings->get_bool(lib->settings,
+ "%s.receive_delay_response", TRUE, charon->name),
this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_PREFERRED);
- if (this->hasher == NULL)
+ if (!this->hasher)
{
DBG1(DBG_NET, "creating cookie hasher failed, no hashers supported");
free(this);
return NULL;
}
this->rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
- if (this->rng == NULL)
+ if (!this->rng)
{
DBG1(DBG_NET, "creating cookie RNG failed, no RNG supported");
this->hasher->destroy(this->hasher);
free(this);
return NULL;
}
- this->rng->get_bytes(this->rng, SECRET_LENGTH, this->secret);
+ if (!this->rng->get_bytes(this->rng, SECRET_LENGTH, this->secret))
+ {
+ DBG1(DBG_NET, "creating cookie secret failed");
+ destroy(this);
+ return NULL;
+ }
memcpy(this->secret_old, this->secret, SECRET_LENGTH);
- this->job = callback_job_create_with_prio((callback_job_cb_t)receive_packets,
- this, NULL, NULL, JOB_PRIO_CRITICAL);
- lib->processor->queue_job(lib->processor, (job_t*)this->job);
+ lib->processor->queue_job(lib->processor,
+ (job_t*)callback_job_create_with_prio((callback_job_cb_t)receive_packets,
+ this, NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
return &this->public;
}
diff --git a/src/libcharon/network/receiver.h b/src/libcharon/network/receiver.h
index 1d9d4871e..9e8edee45 100644
--- a/src/libcharon/network/receiver.h
+++ b/src/libcharon/network/receiver.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -26,14 +27,27 @@ typedef struct receiver_t receiver_t;
#include <library.h>
#include <utils/host.h>
+#include <utils/packet.h>
+
+/**
+ * Callback called for any received UDP encapsulated ESP packet.
+ *
+ * Implementation should be quick as the receiver doesn't receive any packets
+ * while calling this function.
+ *
+ * @param data data supplied during registration of the callback
+ * @param packet decapsulated ESP packet
+ */
+typedef void (*receiver_esp_cb_t)(void *data, packet_t *packet);
/**
* Receives packets from the socket and adds them to the job queue.
*
- * The receiver starts a thread, which reads on the blocking socket. A received
- * packet is preparsed and a process_message_job is queued in the job queue.
+ * The receiver uses a callback job, which reads on the blocking socket.
+ * A received packet is preparsed and a process_message_job is queued in the
+ * job queue.
*
- * To endure DoS attacks, cookies are enabled when to many IKE_SAs are half
+ * To endure DoS attacks, cookies are enabled when too many IKE_SAs are half
* open. The calculation of cookies is slightly different from the proposed
* method in RFC4306. We do not include a nonce, because we think the advantage
* we gain does not justify the overhead to parse the whole message.
@@ -47,14 +61,32 @@ typedef struct receiver_t receiver_t;
* secret is stored to allow a clean migration between secret changes.
*
* Further, the number of half-initiated IKE_SAs is limited per peer. This
- * mades it impossible for a peer to flood the server with its real IP address.
+ * makes it impossible for a peer to flood the server with its real IP address.
*/
struct receiver_t {
/**
+ * Register a callback which is called for any incoming ESP packets.
+ *
+ * @note Only the last callback registered will receive any packets.
+ *
+ * @param callback callback to register
+ * @param data data provided to callback
+ */
+ void (*add_esp_cb)(receiver_t *this, receiver_esp_cb_t callback,
+ void *data);
+
+ /**
+ * Unregister a previously registered callback for ESP packets.
+ *
+ * @param callback previously registered callback
+ */
+ void (*del_esp_cb)(receiver_t *this, receiver_esp_cb_t callback);
+
+ /**
* Destroys a receiver_t object.
*/
- void (*destroy) (receiver_t *receiver);
+ void (*destroy)(receiver_t *this);
};
/**
diff --git a/src/libcharon/network/sender.c b/src/libcharon/network/sender.c
index 4df930b15..059f24b39 100644
--- a/src/libcharon/network/sender.c
+++ b/src/libcharon/network/sender.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -39,11 +40,6 @@ struct private_sender_t {
sender_t public;
/**
- * Sender threads job.
- */
- callback_job_t *job;
-
- /**
* The packets are stored in a linked list
*/
linked_list_t *list;
@@ -84,11 +80,21 @@ struct private_sender_t {
bool send_delay_response;
};
+METHOD(sender_t, send_no_marker, void,
+ private_sender_t *this, packet_t *packet)
+{
+ this->mutex->lock(this->mutex);
+ this->list->insert_last(this->list, packet);
+ this->got->signal(this->got);
+ this->mutex->unlock(this->mutex);
+}
+
METHOD(sender_t, send_, void,
private_sender_t *this, packet_t *packet)
{
host_t *src, *dst;
+ /* if neither source nor destination port is 500 we add a Non-ESP marker */
src = packet->get_source(packet);
dst = packet->get_destination(packet);
DBG1(DBG_NET, "sending packet: from %#H to %#H", src, dst);
@@ -114,16 +120,22 @@ METHOD(sender_t, send_, void,
message->destroy(message);
}
- this->mutex->lock(this->mutex);
- this->list->insert_last(this->list, packet);
- this->got->signal(this->got);
- this->mutex->unlock(this->mutex);
+ if (dst->get_port(dst) != IKEV2_UDP_PORT &&
+ src->get_port(src) != IKEV2_UDP_PORT)
+ {
+ chunk_t data, marker = chunk_from_chars(0x00, 0x00, 0x00, 0x00);
+
+ data = chunk_cat("cc", marker, packet->get_data(packet));
+ packet->set_data(packet, data);
+ }
+
+ send_no_marker(this, packet);
}
/**
* Job callback function to send packets
*/
-static job_requeue_t send_packets(private_sender_t * this)
+static job_requeue_t send_packets(private_sender_t *this)
{
packet_t *packet;
bool oldstate;
@@ -149,7 +161,7 @@ static job_requeue_t send_packets(private_sender_t * this)
return JOB_REQUEUE_DIRECT;
}
-METHOD(sender_t, destroy, void,
+METHOD(sender_t, flush, void,
private_sender_t *this)
{
/* send all packets in the queue */
@@ -159,8 +171,12 @@ METHOD(sender_t, destroy, void,
this->sent->wait(this->sent, this->mutex);
}
this->mutex->unlock(this->mutex);
- this->job->cancel(this->job);
- this->list->destroy(this->list);
+}
+
+METHOD(sender_t, destroy, void,
+ private_sender_t *this)
+{
+ this->list->destroy_offset(this->list, offsetof(packet_t, destroy));
this->got->destroy(this->got);
this->sent->destroy(this->sent);
this->mutex->destroy(this->mutex);
@@ -177,25 +193,27 @@ sender_t * sender_create()
INIT(this,
.public = {
.send = _send_,
+ .send_no_marker = _send_no_marker,
+ .flush = _flush,
.destroy = _destroy,
},
.list = linked_list_create(),
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
.got = condvar_create(CONDVAR_TYPE_DEFAULT),
.sent = condvar_create(CONDVAR_TYPE_DEFAULT),
- .job = callback_job_create_with_prio((callback_job_cb_t)send_packets,
- this, NULL, NULL, JOB_PRIO_CRITICAL),
.send_delay = lib->settings->get_int(lib->settings,
- "charon.send_delay", 0),
+ "%s.send_delay", 0, charon->name),
.send_delay_type = lib->settings->get_int(lib->settings,
- "charon.send_delay_type", 0),
+ "%s.send_delay_type", 0, charon->name),
.send_delay_request = lib->settings->get_bool(lib->settings,
- "charon.send_delay_request", TRUE),
- .send_delay_response = lib->settings->get_int(lib->settings,
- "charon.send_delay_response", TRUE),
+ "%s.send_delay_request", TRUE, charon->name),
+ .send_delay_response = lib->settings->get_bool(lib->settings,
+ "%s.send_delay_response", TRUE, charon->name),
);
- lib->processor->queue_job(lib->processor, (job_t*)this->job);
+ lib->processor->queue_job(lib->processor,
+ (job_t*)callback_job_create_with_prio((callback_job_cb_t)send_packets,
+ this, NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
return &this->public;
}
diff --git a/src/libcharon/network/sender.h b/src/libcharon/network/sender.h
index f77fadab2..9b5c325cc 100644
--- a/src/libcharon/network/sender.h
+++ b/src/libcharon/network/sender.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -25,10 +26,10 @@
typedef struct sender_t sender_t;
#include <library.h>
-#include <network/packet.h>
+#include <utils/packet.h>
/**
- * Thread responsible for sending packets over the socket.
+ * Callback job responsible for sending IKE packets over the socket.
*/
struct sender_t {
@@ -44,6 +45,20 @@ struct sender_t {
void (*send) (sender_t *this, packet_t *packet);
/**
+ * The same as send() but does not add Non-ESP markers automatically.
+ *
+ * @param packet packet to send
+ */
+ void (*send_no_marker) (sender_t *this, packet_t *packet);
+
+ /**
+ * Enforce a flush of the send queue.
+ *
+ * This function blocks until all queued packets have been sent.
+ */
+ void (*flush)(sender_t *this);
+
+ /**
* Destroys a sender object.
*/
void (*destroy) (sender_t *this);
diff --git a/src/libcharon/network/socket.h b/src/libcharon/network/socket.h
index be875035b..b8850c6ed 100644
--- a/src/libcharon/network/socket.h
+++ b/src/libcharon/network/socket.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2010 Tobias Brunner
+ * Copyright (C) 2006-2012 Tobias Brunner
* Copyright (C) 2005-2010 Martin Willi
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005 Jan Hutter
@@ -27,7 +27,7 @@
typedef struct socket_t socket_t;
#include <library.h>
-#include <network/packet.h>
+#include <utils/packet.h>
#include <utils/enumerator.h>
#include <plugins/plugin.h>
@@ -68,6 +68,14 @@ struct socket_t {
status_t (*send) (socket_t *this, packet_t *packet);
/**
+ * Get the port this socket is listening on.
+ *
+ * @param nat_t TRUE to get the port used to float in case of NAT-T
+ * @return the port
+ */
+ u_int16_t (*get_port) (socket_t *this, bool nat_t);
+
+ /**
* Destroy a socket implementation.
*/
void (*destroy) (socket_t *this);
diff --git a/src/libcharon/network/socket_manager.c b/src/libcharon/network/socket_manager.c
index 72a454301..d2736de8e 100644
--- a/src/libcharon/network/socket_manager.c
+++ b/src/libcharon/network/socket_manager.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Tobias Brunner
+ * Copyright (C) 2010-2012 Tobias Brunner
* Hochschule fuer Technik Rapperswil
* Copyright (C) 2010 Martin Willi
* Copyright (C) 2010 revosec AG
@@ -89,6 +89,19 @@ METHOD(socket_manager_t, sender, status_t,
return status;
}
+METHOD(socket_manager_t, get_port, u_int16_t,
+ private_socket_manager_t *this, bool nat_t)
+{
+ u_int16_t port = 0;
+ this->lock->read_lock(this->lock);
+ if (this->socket)
+ {
+ port = this->socket->get_port(this->socket, nat_t);
+ }
+ this->lock->unlock(this->lock);
+ return port;
+}
+
static void create_socket(private_socket_manager_t *this)
{
socket_constructor_t create;
@@ -153,6 +166,7 @@ socket_manager_t *socket_manager_create()
.public = {
.send = _sender,
.receive = _receiver,
+ .get_port = _get_port,
.add_socket = _add_socket,
.remove_socket = _remove_socket,
.destroy = _destroy,
diff --git a/src/libcharon/network/socket_manager.h b/src/libcharon/network/socket_manager.h
index 94185d21c..1909d1f25 100644
--- a/src/libcharon/network/socket_manager.h
+++ b/src/libcharon/network/socket_manager.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Tobias Brunner
+ * Copyright (C) 2010-2012 Tobias Brunner
* Hochschule fuer Technik Rapperswil
* Copyright (C) 2010 Martin Willi
* Copyright (C) 2010 revosec AG
@@ -53,6 +53,14 @@ struct socket_manager_t {
status_t (*send) (socket_manager_t *this, packet_t *packet);
/**
+ * Get the port the registered socket is listening on.
+ *
+ * @param nat_t TRUE to get the port used to float in case of NAT-T
+ * @return the port, or 0, if no socket is registered
+ */
+ u_int16_t (*get_port) (socket_manager_t *this, bool nat_t);
+
+ /**
* Register a socket constructor.
*
* @param create constructor for the socket
diff --git a/src/libcharon/plugins/addrblock/Makefile.in b/src/libcharon/plugins/addrblock/Makefile.in
index 3139e20b0..8673e6ecd 100644
--- a/src/libcharon/plugins/addrblock/Makefile.in
+++ b/src/libcharon/plugins/addrblock/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -86,7 +87,7 @@ libstrongswan_addrblock_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_addrblock_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_addrblock_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -112,6 +113,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -206,11 +208,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -227,11 +232,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -247,6 +253,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -256,7 +263,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/android/Makefile.am b/src/libcharon/plugins/android/Makefile.am
index b922ef4af..b10cd9527 100644
--- a/src/libcharon/plugins/android/Makefile.am
+++ b/src/libcharon/plugins/android/Makefile.am
@@ -14,7 +14,6 @@ libstrongswan_android_la_SOURCES = \
android_plugin.c android_plugin.h \
android_service.c android_service.h \
android_handler.c android_handler.h \
- android_logger.c android_logger.h \
android_creds.c android_creds.h
libstrongswan_android_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/android/Makefile.in b/src/libcharon/plugins/android/Makefile.in
index 50e5f638e..ebe6ebb4d 100644
--- a/src/libcharon/plugins/android/Makefile.in
+++ b/src/libcharon/plugins/android/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -76,8 +77,7 @@ am__installdirs = "$(DESTDIR)$(plugindir)"
LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_android_la_DEPENDENCIES =
am_libstrongswan_android_la_OBJECTS = android_plugin.lo \
- android_service.lo android_handler.lo android_logger.lo \
- android_creds.lo
+ android_service.lo android_handler.lo android_creds.lo
libstrongswan_android_la_OBJECTS = \
$(am_libstrongswan_android_la_OBJECTS)
libstrongswan_android_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@@ -86,7 +86,7 @@ libstrongswan_android_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@MONOLITHIC_FALSE@am_libstrongswan_android_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_android_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -112,6 +112,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -206,11 +207,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -227,11 +231,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -247,6 +252,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -256,7 +262,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -294,7 +299,6 @@ libstrongswan_android_la_SOURCES = \
android_plugin.c android_plugin.h \
android_service.c android_service.h \
android_handler.c android_handler.h \
- android_logger.c android_logger.h \
android_creds.c android_creds.h
libstrongswan_android_la_LDFLAGS = -module -avoid-version
@@ -384,7 +388,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/android_creds.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/android_handler.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/android_logger.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/android_plugin.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/android_service.Plo@am__quote@
diff --git a/src/libcharon/plugins/android/android_handler.c b/src/libcharon/plugins/android/android_handler.c
index a53962f16..f1d3045ca 100644
--- a/src/libcharon/plugins/android/android_handler.c
+++ b/src/libcharon/plugins/android/android_handler.c
@@ -196,7 +196,7 @@ METHOD(enumerator_t, enumerate_dns, bool,
}
METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t *,
- android_handler_t *this, identification_t *id, host_t *vip)
+ android_handler_t *this, identification_t *id, linked_list_t *vips)
{
enumerator_t *enumerator;
diff --git a/src/libcharon/plugins/android/android_logger.c b/src/libcharon/plugins/android/android_logger.c
deleted file mode 100644
index f7624b2c7..000000000
--- a/src/libcharon/plugins/android/android_logger.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2010 Tobias Brunner
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <string.h>
-#include <android/log.h>
-
-#include "android_logger.h"
-
-#include <library.h>
-#include <daemon.h>
-
-typedef struct private_android_logger_t private_android_logger_t;
-
-/**
- * Private data of an android_logger_t object
- */
-struct private_android_logger_t {
-
- /**
- * Public interface
- */
- android_logger_t public;
-
- /**
- * logging level
- */
- int level;
-
-};
-
-
-METHOD(listener_t, log_, bool,
- private_android_logger_t *this, debug_t group, level_t level,
- int thread, ike_sa_t* ike_sa, char *format, va_list args)
-{
- if (level <= this->level)
- {
- int prio = level > 1 ? ANDROID_LOG_DEBUG : ANDROID_LOG_INFO;
- char sgroup[16], buffer[8192];
- char *current = buffer, *next;
- snprintf(sgroup, sizeof(sgroup), "%N", debug_names, group);
- vsnprintf(buffer, sizeof(buffer), format, args);
- while (current)
- { /* log each line separately */
- next = strchr(current, '\n');
- if (next)
- {
- *(next++) = '\0';
- }
- __android_log_print(prio, "charon", "%.2d[%s] %s\n",
- thread, sgroup, current);
- current = next;
- }
- }
- /* always stay registered */
- return TRUE;
-}
-
-METHOD(android_logger_t, destroy, void,
- private_android_logger_t *this)
-{
- free(this);
-}
-
-/**
- * Described in header.
- */
-android_logger_t *android_logger_create()
-{
- private_android_logger_t *this;
-
- INIT(this,
- .public = {
- .listener = {
- .log = _log_,
- },
- .destroy = _destroy,
- },
- .level = lib->settings->get_int(lib->settings,
- "charon.plugins.android.loglevel", 1),
- );
-
- return &this->public;
-}
-
diff --git a/src/libcharon/plugins/android/android_plugin.c b/src/libcharon/plugins/android/android_plugin.c
index 091f34a8e..c0f58e9b4 100644
--- a/src/libcharon/plugins/android/android_plugin.c
+++ b/src/libcharon/plugins/android/android_plugin.c
@@ -15,7 +15,6 @@
*/
#include "android_plugin.h"
-#include "android_logger.h"
#include "android_handler.h"
#include "android_creds.h"
#include "android_service.h"
@@ -36,11 +35,6 @@ struct private_android_plugin_t {
android_plugin_t public;
/**
- * Android specific logger
- */
- android_logger_t *logger;
-
- /**
* Android specific DNS handler
*/
android_handler_t *handler;
@@ -68,10 +62,8 @@ METHOD(plugin_t, destroy, void,
hydra->attributes->remove_handler(hydra->attributes,
&this->handler->handler);
lib->credmgr->remove_set(lib->credmgr, &this->creds->set);
- charon->bus->remove_listener(charon->bus, &this->logger->listener);
this->creds->destroy(this->creds);
this->handler->destroy(this->handler);
- this->logger->destroy(this->logger);
DESTROY_IF(this->service);
free(this);
}
@@ -91,14 +83,12 @@ plugin_t *android_plugin_create()
.destroy = _destroy,
},
},
- .logger = android_logger_create(),
.creds = android_creds_create(),
);
this->service = android_service_create(this->creds);
this->handler = android_handler_create(this->service != NULL);
- charon->bus->add_listener(charon->bus, &this->logger->listener);
lib->credmgr->add_set(lib->credmgr, &this->creds->set);
hydra->attributes->add_handler(hydra->attributes, &this->handler->handler);
diff --git a/src/libcharon/plugins/android/android_service.c b/src/libcharon/plugins/android/android_service.c
index 487567f2a..81628b80a 100644
--- a/src/libcharon/plugins/android/android_service.c
+++ b/src/libcharon/plugins/android/android_service.c
@@ -42,11 +42,6 @@ struct private_android_service_t {
ike_sa_t *ike_sa;
/**
- * job that handles requests from the Android control socket
- */
- callback_job_t *job;
-
- /**
* android credentials
*/
android_creds_t *creds;
@@ -269,17 +264,19 @@ static job_requeue_t initiate(private_android_service_t *this)
this->creds->set_username_password(this->creds, user, password);
}
- ike_cfg = ike_cfg_create(TRUE, FALSE, "0.0.0.0", IKEV2_UDP_PORT,
- hostname, IKEV2_UDP_PORT);
+ ike_cfg = ike_cfg_create(TRUE, FALSE, "0.0.0.0", FALSE,
+ charon->socket->get_port(charon->socket, FALSE),
+ hostname, FALSE, IKEV2_UDP_PORT);
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
- peer_cfg = peer_cfg_create("android", 2, ike_cfg, CERT_SEND_IF_ASKED,
+ peer_cfg = peer_cfg_create("android", IKEV2, ike_cfg, CERT_SEND_IF_ASKED,
UNIQUE_REPLACE, 1, /* keyingtries */
36000, 0, /* rekey 10h, reauth none */
600, 600, /* jitter, over 10min */
- TRUE, 0, /* mobike, DPD */
- host_create_from_string("0.0.0.0", 0) /* virt */,
- NULL, FALSE, NULL, NULL); /* pool, mediation */
+ TRUE, FALSE, /* mobike, aggressive */
+ 0, 0, /* DPD delay, timeout */
+ FALSE, NULL, NULL); /* mediation */
+ peer_cfg->add_virtual_ip(peer_cfg, host_create_from_string("0.0.0.0", 0));
auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
@@ -300,12 +297,17 @@ static job_requeue_t initiate(private_android_service_t *this)
0, "255.255.255.255", 65535);
child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
peer_cfg->add_child_cfg(peer_cfg, child_cfg);
- /* get an additional reference because initiate consumes one */
- child_cfg->get_ref(child_cfg);
/* get us an IKE_SA */
ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
peer_cfg);
+ if (!ike_sa)
+ {
+ peer_cfg->destroy(peer_cfg);
+ send_status(this, VPN_ERROR_CONNECTION_FAILED);
+ return JOB_REQUEUE_NONE;
+ }
+
if (!ike_sa->get_peer_cfg(ike_sa))
{
ike_sa->set_peer_cfg(ike_sa, peer_cfg);
@@ -318,6 +320,8 @@ static job_requeue_t initiate(private_android_service_t *this)
/* confirm that we received the request */
send_status(this, i);
+ /* get an additional reference because initiate consumes one */
+ child_cfg->get_ref(child_cfg);
if (ike_sa->initiate(ike_sa, child_cfg, 0, NULL, NULL) != SUCCESS)
{
DBG1(DBG_CFG, "failed to initiate tunnel");
@@ -376,9 +380,9 @@ android_service_t *android_service_create(android_creds_t *creds)
}
charon->bus->add_listener(charon->bus, &this->public.listener);
- this->job = callback_job_create((callback_job_cb_t)initiate, this,
- NULL, NULL);
- lib->processor->queue_job(lib->processor, (job_t*)this->job);
+ lib->processor->queue_job(lib->processor,
+ (job_t*)callback_job_create((callback_job_cb_t)initiate, this,
+ NULL, NULL));
return &this->public;
}
diff --git a/src/libcharon/plugins/android_log/Makefile.am b/src/libcharon/plugins/android_log/Makefile.am
new file mode 100644
index 000000000..3c180f1db
--- /dev/null
+++ b/src/libcharon/plugins/android_log/Makefile.am
@@ -0,0 +1,17 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-android-log.la
+else
+plugin_LTLIBRARIES = libstrongswan-android-log.la
+endif
+
+libstrongswan_android_log_la_SOURCES = \
+ android_log_plugin.c android_log_plugin.h \
+ android_log_logger.c android_log_logger.h
+
+libstrongswan_android_log_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/android_log/Makefile.in b/src/libcharon/plugins/android_log/Makefile.in
new file mode 100644
index 000000000..00f0eb869
--- /dev/null
+++ b/src/libcharon/plugins/android_log/Makefile.in
@@ -0,0 +1,622 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/libcharon/plugins/android_log
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
+ $(top_srcdir)/m4/config/ltoptions.m4 \
+ $(top_srcdir)/m4/config/ltsugar.m4 \
+ $(top_srcdir)/m4/config/ltversion.m4 \
+ $(top_srcdir)/m4/config/lt~obsolete.m4 \
+ $(top_srcdir)/m4/macros/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/m4/macros/add-plugin.m4 \
+ $(top_srcdir)/configure.in
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_android_log_la_LIBADD =
+am_libstrongswan_android_log_la_OBJECTS = android_log_plugin.lo \
+ android_log_logger.lo
+libstrongswan_android_log_la_OBJECTS = \
+ $(am_libstrongswan_android_log_la_OBJECTS)
+libstrongswan_android_log_la_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_android_log_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_android_log_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_android_log_la_rpath =
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_android_log_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_android_log_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BFDLIB = @BFDLIB@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+attest_plugins = @attest_plugins@
+axis2c_CFLAGS = @axis2c_CFLAGS@
+axis2c_LIBS = @axis2c_LIBS@
+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@
+datadir = @datadir@
+datarootdir = @datarootdir@
+dbusservicedir = @dbusservicedir@
+dev_headers = @dev_headers@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+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@
+libdir = @libdir@
+libexecdir = @libexecdir@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+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@
+openac_plugins = @openac_plugins@
+p_plugins = @p_plugins@
+pcsclite_CFLAGS = @pcsclite_CFLAGS@
+pcsclite_LIBS = @pcsclite_LIBS@
+pdfdir = @pdfdir@
+piddir = @piddir@
+pki_plugins = @pki_plugins@
+plugindir = @plugindir@
+pool_plugins = @pool_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+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@
+sysconfdir = @sysconfdir@
+systemdsystemunitdir = @systemdsystemunitdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-android-log.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-android-log.la
+libstrongswan_android_log_la_SOURCES = \
+ android_log_plugin.c android_log_plugin.h \
+ android_log_logger.c android_log_logger.h
+
+libstrongswan_android_log_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/android_log/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/android_log/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-android-log.la: $(libstrongswan_android_log_la_OBJECTS) $(libstrongswan_android_log_la_DEPENDENCIES)
+ $(libstrongswan_android_log_la_LINK) $(am_libstrongswan_android_log_la_rpath) $(libstrongswan_android_log_la_OBJECTS) $(libstrongswan_android_log_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/android_log_logger.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/android_log_plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/android_log/android_log_logger.c b/src/libcharon/plugins/android_log/android_log_logger.c
new file mode 100644
index 000000000..48bcaa577
--- /dev/null
+++ b/src/libcharon/plugins/android_log/android_log_logger.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2010-2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <string.h>
+#include <android/log.h>
+
+#include "android_log_logger.h"
+
+#include <library.h>
+#include <daemon.h>
+#include <threading/mutex.h>
+
+typedef struct private_android_log_logger_t private_android_log_logger_t;
+
+/**
+ * Private data of an android_log_logger_t object
+ */
+struct private_android_log_logger_t {
+
+ /**
+ * Public interface
+ */
+ android_log_logger_t public;
+
+ /**
+ * logging level
+ */
+ int level;
+
+ /**
+ * Mutex to ensure multi-line log messages are not torn apart
+ */
+ mutex_t *mutex;
+};
+
+METHOD(logger_t, log_, void,
+ private_android_log_logger_t *this, debug_t group, level_t level,
+ int thread, ike_sa_t* ike_sa, const char *message)
+{
+ int prio = level > 1 ? ANDROID_LOG_DEBUG : ANDROID_LOG_INFO;
+ char sgroup[16];
+ const char *current = message, *next;
+ snprintf(sgroup, sizeof(sgroup), "%N", debug_names, group);
+ this->mutex->lock(this->mutex);
+ while (TRUE)
+ { /* log each line separately */
+ next = strchr(current, '\n');
+ if (next == NULL)
+ {
+ __android_log_print(prio, "charon", "%.2d[%s] %s\n",
+ thread, sgroup, current);
+ break;
+ }
+ __android_log_print(prio, "charon", "%.2d[%s] %.*s\n",
+ thread, sgroup, (int)(next - current), current);
+ current = next + 1;
+ }
+ this->mutex->unlock(this->mutex);
+}
+
+METHOD(logger_t, get_level, level_t,
+ private_android_log_logger_t *this, debug_t group)
+{
+ return this->level;
+}
+
+METHOD(android_log_logger_t, destroy, void,
+ private_android_log_logger_t *this)
+{
+ this->mutex->destroy(this->mutex);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+android_log_logger_t *android_log_logger_create()
+{
+ private_android_log_logger_t *this;
+
+ INIT(this,
+ .public = {
+ .logger = {
+ .log = _log_,
+ .get_level = _get_level,
+ },
+ .destroy = _destroy,
+ },
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ .level = lib->settings->get_int(lib->settings,
+ "%s.plugins.android_log.loglevel", 1, charon->name),
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/android/android_logger.h b/src/libcharon/plugins/android_log/android_log_logger.h
index c6fe5aff3..ed271bf6c 100644
--- a/src/libcharon/plugins/android/android_logger.h
+++ b/src/libcharon/plugins/android_log/android_log_logger.h
@@ -14,31 +14,31 @@
*/
/**
- * @defgroup android_logger android_logger
- * @{ @ingroup android
+ * @defgroup android_log_logger android_log_logger
+ * @{ @ingroup android_log
*/
-#ifndef ANDROID_LOGGER_H_
-#define ANDROID_LOGGER_H_
+#ifndef ANDROID_LOG_LOGGER_H_
+#define ANDROID_LOG_LOGGER_H_
#include <bus/bus.h>
-typedef struct android_logger_t android_logger_t;
+typedef struct android_log_logger_t android_log_logger_t;
/**
* Android specific logger.
*/
-struct android_logger_t {
+struct android_log_logger_t {
/**
- * Implements bus_listener_t interface
+ * Implements logger_t interface
*/
- listener_t listener;
+ logger_t logger;
/**
* Destroy the logger.
*/
- void (*destroy)(android_logger_t *this);
+ void (*destroy)(android_log_logger_t *this);
};
@@ -47,6 +47,6 @@ struct android_logger_t {
*
* @return logger instance
*/
-android_logger_t *android_logger_create();
+android_log_logger_t *android_log_logger_create();
-#endif /** ANDROID_LOGGER_H_ @}*/
+#endif /** ANDROID_LOG_LOGGER_H_ @}*/
diff --git a/src/libcharon/plugins/android_log/android_log_plugin.c b/src/libcharon/plugins/android_log/android_log_plugin.c
new file mode 100644
index 000000000..6757c2210
--- /dev/null
+++ b/src/libcharon/plugins/android_log/android_log_plugin.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2012 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 "android_log_plugin.h"
+#include "android_log_logger.h"
+
+#include <daemon.h>
+
+typedef struct private_android_log_plugin_t private_android_log_plugin_t;
+
+/**
+ * Private data of an android_log_plugin_t object.
+ */
+struct private_android_log_plugin_t {
+
+ /**
+ * Public android_log_plugin_t interface.
+ */
+ android_log_plugin_t public;
+
+ /**
+ * Android specific logger
+ */
+ android_log_logger_t *logger;
+
+};
+
+METHOD(plugin_t, get_name, char*,
+ private_android_log_plugin_t *this)
+{
+ return "android-log";
+}
+
+METHOD(plugin_t, destroy, void,
+ private_android_log_plugin_t *this)
+{
+ charon->bus->remove_logger(charon->bus, &this->logger->logger);
+ this->logger->destroy(this->logger);
+ free(this);
+}
+
+/**
+ * See header
+ */
+plugin_t *android_log_plugin_create()
+{
+ private_android_log_plugin_t *this;
+
+ INIT(this,
+ .public = {
+ .plugin = {
+ .get_name = _get_name,
+ .reload = (void*)return_false,
+ .destroy = _destroy,
+ },
+ },
+ .logger = android_log_logger_create(),
+ );
+
+ charon->bus->add_logger(charon->bus, &this->logger->logger);
+
+ return &this->public.plugin;
+}
+
diff --git a/src/libcharon/plugins/android_log/android_log_plugin.h b/src/libcharon/plugins/android_log/android_log_plugin.h
new file mode 100644
index 000000000..32c4dc10b
--- /dev/null
+++ b/src/libcharon/plugins/android_log/android_log_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup android_log android_log
+ * @ingroup cplugins
+ *
+ * @defgroup android_log_plugin android_log_plugin
+ * @{ @ingroup android_log
+ */
+
+#ifndef ANDROID_LOG_PLUGIN_H_
+#define ANDROID_LOG_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct android_log_plugin_t android_log_plugin_t;
+
+/**
+ * Plugin providing an Android specific logger implementation.
+ */
+struct android_log_plugin_t {
+
+ /**
+ * Implements plugin interface.
+ */
+ plugin_t plugin;
+};
+
+#endif /** ANDROID_LOG_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/certexpire/Makefile.in b/src/libcharon/plugins/certexpire/Makefile.in
index 929cce20c..4c098fcc7 100644
--- a/src/libcharon/plugins/certexpire/Makefile.in
+++ b/src/libcharon/plugins/certexpire/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -86,7 +87,7 @@ libstrongswan_certexpire_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_certexpire_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_certexpire_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -112,6 +113,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -206,11 +208,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -227,11 +232,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -247,6 +253,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -256,7 +263,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/certexpire/certexpire_export.c b/src/libcharon/plugins/certexpire/certexpire_export.c
index c73b0beda..8e046d0fe 100644
--- a/src/libcharon/plugins/certexpire/certexpire_export.c
+++ b/src/libcharon/plugins/certexpire/certexpire_export.c
@@ -22,6 +22,7 @@
#include <errno.h>
#include <debug.h>
+#include <daemon.h>
#include <utils/hashtable.h>
#include <threading/mutex.h>
#include <credentials/certificates/x509.h>
@@ -364,21 +365,28 @@ certexpire_export_t *certexpire_export_create()
(hashtable_equals_t)equals, 32),
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
.local_path = lib->settings->get_str(lib->settings,
- "charon.plugins.certexpire.csv.local", NULL),
+ "%s.plugins.certexpire.csv.local",
+ NULL, charon->name),
.remote_path = lib->settings->get_str(lib->settings,
- "charon.plugins.certexpire.csv.remote", NULL),
+ "%s.plugins.certexpire.csv.remote",
+ NULL, charon->name),
.separator = lib->settings->get_str(lib->settings,
- "charon.plugins.certexpire.csv.separator", ","),
+ "%s.plugins.certexpire.csv.separator",
+ ",", charon->name),
.format = lib->settings->get_str(lib->settings,
- "charon.plugins.certexpire.csv.format", "%d:%m:%Y"),
+ "%s.plugins.certexpire.csv.format",
+ "%d:%m:%Y", charon->name),
.fixed_fields = lib->settings->get_bool(lib->settings,
- "charon.plugins.certexpire.csv.fixed_fields", TRUE),
+ "%s.plugins.certexpire.csv.fixed_fields",
+ TRUE, charon->name),
.empty_string = lib->settings->get_str(lib->settings,
- "charon.plugins.certexpire.csv.empty_string", ""),
+ "%s.plugins.certexpire.csv.empty_string",
+ "", charon->name),
);
cron = lib->settings->get_str(lib->settings,
- "charon.plugins.certexpire.csv.cron", NULL);
+ "%s.plugins.certexpire.csv.cron",
+ NULL, charon->name);
if (cron)
{
this->cron = certexpire_cron_create(cron,
diff --git a/src/libcharon/plugins/coupling/Makefile.in b/src/libcharon/plugins/coupling/Makefile.in
index df4420b04..9ad158b4c 100644
--- a/src/libcharon/plugins/coupling/Makefile.in
+++ b/src/libcharon/plugins/coupling/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -86,7 +87,7 @@ libstrongswan_coupling_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_coupling_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_coupling_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -112,6 +113,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -206,11 +208,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -227,11 +232,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -247,6 +253,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -256,7 +263,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/coupling/coupling_validator.c b/src/libcharon/plugins/coupling/coupling_validator.c
index 06b6f7d86..539be7548 100644
--- a/src/libcharon/plugins/coupling/coupling_validator.c
+++ b/src/libcharon/plugins/coupling/coupling_validator.c
@@ -70,7 +70,11 @@ static bool get_cert_hash(private_coupling_validator_t *this,
{
return FALSE;
}
- this->hasher->get_hash(this->hasher, encoding, buf);
+ if (!this->hasher->get_hash(this->hasher, encoding, buf))
+ {
+ free(encoding.ptr);
+ return FALSE;
+ }
free(encoding.ptr);
chunk_to_hex(chunk_create(buf, this->hasher->get_hash_size(this->hasher)),
hex, FALSE);
@@ -195,17 +199,6 @@ coupling_validator_t *coupling_validator_create()
{
private_coupling_validator_t *this;
char *path, *hash;
- int i;
- struct {
- hash_algorithm_t alg;
- char *name;
- } hash_types[] = {
- { HASH_MD5, "md5"},
- { HASH_SHA1, "sha1"},
- { HASH_SHA256, "sha256"},
- { HASH_SHA384, "sha384"},
- { HASH_SHA512, "sha512"},
- };
INIT(this,
.public = {
@@ -216,20 +209,15 @@ coupling_validator_t *coupling_validator_create()
},
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
.max_couplings = lib->settings->get_int(lib->settings,
- "charon.plugins.coupling.max", 1),
+ "%s.plugins.coupling.max", 1,
+ charon->name),
);
hash = lib->settings->get_str(lib->settings,
- "charon.plugins.coupling.hash", "sha1");
- for (i = 0; i < countof(hash_types); i++)
- {
- if (strcaseeq(hash_types[i].name, hash))
- {
- this->hasher = lib->crypto->create_hasher(lib->crypto,
- hash_types[i].alg);
- break;
- }
- }
+ "%s.plugins.coupling.hash", "sha1",
+ charon->name);
+ this->hasher = lib->crypto->create_hasher(lib->crypto,
+ enum_from_name(hash_algorithm_short_names, hash));
if (!this->hasher)
{
DBG1(DBG_CFG, "unsupported coupling hash algorithm: %s", hash);
@@ -238,7 +226,8 @@ coupling_validator_t *coupling_validator_create()
}
path = lib->settings->get_str(lib->settings,
- "charon.plugins.coupling.file", NULL);
+ "%s.plugins.coupling.file", NULL,
+ charon->name);
if (!path)
{
DBG1(DBG_CFG, "coupling file path unspecified");
diff --git a/src/libcharon/plugins/dhcp/Makefile.in b/src/libcharon/plugins/dhcp/Makefile.in
index 089afd39d..ec42d8de6 100644
--- a/src/libcharon/plugins/dhcp/Makefile.in
+++ b/src/libcharon/plugins/dhcp/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -83,7 +84,7 @@ libstrongswan_dhcp_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(libstrongswan_dhcp_la_LDFLAGS) $(LDFLAGS) -o $@
@MONOLITHIC_FALSE@am_libstrongswan_dhcp_la_rpath = -rpath $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_dhcp_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -109,6 +110,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -203,11 +205,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -224,11 +229,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -244,6 +250,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -253,7 +260,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/dhcp/dhcp_provider.c b/src/libcharon/plugins/dhcp/dhcp_provider.c
index a6a887780..8bc547462 100644
--- a/src/libcharon/plugins/dhcp/dhcp_provider.c
+++ b/src/libcharon/plugins/dhcp/dhcp_provider.c
@@ -81,18 +81,29 @@ static uintptr_t hash_transaction(dhcp_transaction_t *transaction)
}
METHOD(attribute_provider_t, acquire_address, host_t*,
- private_dhcp_provider_t *this, char *pool,
+ private_dhcp_provider_t *this, linked_list_t *pools,
identification_t *id, host_t *requested)
{
- if (streq(pool, "dhcp"))
- {
- dhcp_transaction_t *transaction, *old;
- host_t *vip;
+ dhcp_transaction_t *transaction, *old;
+ enumerator_t *enumerator;
+ char *pool;
+ host_t *vip = NULL;
+ if (requested->get_family(requested) != AF_INET)
+ {
+ return NULL;
+ }
+ enumerator = pools->create_enumerator(pools);
+ while (enumerator->enumerate(enumerator, &pool))
+ {
+ if (!streq(pool, "dhcp"))
+ {
+ continue;
+ }
transaction = this->socket->enroll(this->socket, id);
if (!transaction)
{
- return NULL;
+ continue;
}
vip = transaction->get_address(transaction);
vip = vip->clone(vip);
@@ -101,19 +112,32 @@ METHOD(attribute_provider_t, acquire_address, host_t*,
(void*)hash_transaction(transaction), transaction);
this->mutex->unlock(this->mutex);
DESTROY_IF(old);
- return vip;
+ break;
}
- return NULL;
+ enumerator->destroy(enumerator);
+ return vip;
}
METHOD(attribute_provider_t, release_address, bool,
- private_dhcp_provider_t *this, char *pool,
+ private_dhcp_provider_t *this, linked_list_t *pools,
host_t *address, identification_t *id)
{
- if (streq(pool, "dhcp"))
- {
- dhcp_transaction_t *transaction;
+ dhcp_transaction_t *transaction;
+ enumerator_t *enumerator;
+ bool found = FALSE;
+ char *pool;
+ if (address->get_family(address) != AF_INET)
+ {
+ return FALSE;
+ }
+ enumerator = pools->create_enumerator(pools);
+ while (enumerator->enumerate(enumerator, &pool))
+ {
+ if (!streq(pool, "dhcp"))
+ {
+ continue;
+ }
this->mutex->lock(this->mutex);
transaction = this->transactions->remove(this->transactions,
(void*)hash_id_host(id, address));
@@ -122,25 +146,34 @@ METHOD(attribute_provider_t, release_address, bool,
{
this->socket->release(this->socket, transaction);
transaction->destroy(transaction);
- return TRUE;
+ found = TRUE;
+ break;
}
}
- return FALSE;
+ enumerator->destroy(enumerator);
+ return found;
}
METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
- private_dhcp_provider_t *this, char *pool, identification_t *id,
- host_t *vip)
+ private_dhcp_provider_t *this, linked_list_t *pools, identification_t *id,
+ linked_list_t *vips)
{
- dhcp_transaction_t *transaction;
+ dhcp_transaction_t *transaction = NULL;
+ enumerator_t *enumerator;
+ host_t *vip;
- if (!vip)
+ this->mutex->lock(this->mutex);
+ enumerator = vips->create_enumerator(vips);
+ while (enumerator->enumerate(enumerator, &vip))
{
- return NULL;
+ transaction = this->transactions->get(this->transactions,
+ (void*)hash_id_host(id, vip));
+ if (transaction)
+ {
+ break;
+ }
}
- this->mutex->lock(this->mutex);
- transaction = this->transactions->get(this->transactions,
- (void*)hash_id_host(id, vip));
+ enumerator->destroy(enumerator);
if (!transaction)
{
this->mutex->unlock(this->mutex);
diff --git a/src/libcharon/plugins/dhcp/dhcp_socket.c b/src/libcharon/plugins/dhcp/dhcp_socket.c
index 5d98e5b8d..f469c5a35 100644
--- a/src/libcharon/plugins/dhcp/dhcp_socket.c
+++ b/src/libcharon/plugins/dhcp/dhcp_socket.c
@@ -107,9 +107,9 @@ struct private_dhcp_socket_t {
host_t *dst;
/**
- * Callback job receiving DHCP responses
+ * Force configured destination address
*/
- callback_job_t *job;
+ bool force_dst;
};
/**
@@ -271,7 +271,7 @@ static bool send_dhcp(private_dhcp_socket_t *this,
ssize_t len;
dst = transaction->get_server(transaction);
- if (!dst)
+ if (!dst || this->force_dst)
{
dst = this->dst;
}
@@ -371,7 +371,11 @@ METHOD(dhcp_socket_t, enroll, dhcp_transaction_t*,
u_int32_t id;
int try;
- this->rng->get_bytes(this->rng, sizeof(id), (u_int8_t*)&id);
+ if (!this->rng->get_bytes(this->rng, sizeof(id), (u_int8_t*)&id))
+ {
+ DBG1(DBG_CFG, "DHCP DISCOVER failed, no transaction ID");
+ return NULL;
+ }
transaction = dhcp_transaction_create(id, identity);
this->mutex->lock(this->mutex);
@@ -613,10 +617,6 @@ static job_requeue_t receive_dhcp(private_dhcp_socket_t *this)
METHOD(dhcp_socket_t, destroy, void,
private_dhcp_socket_t *this)
{
- if (this->job)
- {
- this->job->cancel(this->job);
- }
while (this->waiting)
{
this->condvar->signal(this->condvar);
@@ -648,7 +648,13 @@ METHOD(dhcp_socket_t, destroy, void,
dhcp_socket_t *dhcp_socket_create()
{
private_dhcp_socket_t *this;
- struct sockaddr_in src;
+ struct sockaddr_in src = {
+ .sin_family = AF_INET,
+ .sin_port = htons(DHCP_CLIENT_PORT),
+ .sin_addr = {
+ .s_addr = INADDR_ANY,
+ },
+ };
int on = 1;
struct sock_filter dhcp_filter_code[] = {
BPF_STMT(BPF_LD+BPF_B+BPF_ABS,
@@ -704,10 +710,14 @@ dhcp_socket_t *dhcp_socket_create()
return NULL;
}
this->identity_lease = lib->settings->get_bool(lib->settings,
- "charon.plugins.dhcp.identity_lease", FALSE);
+ "%s.plugins.dhcp.identity_lease", FALSE,
+ charon->name);
+ this->force_dst = lib->settings->get_str(lib->settings,
+ "%s.plugins.dhcp.force_server_address", FALSE,
+ charon->name);
this->dst = host_create_from_string(lib->settings->get_str(lib->settings,
- "charon.plugins.dhcp.server", "255.255.255.255"),
- DHCP_SERVER_PORT);
+ "%s.plugins.dhcp.server", "255.255.255.255",
+ charon->name), DHCP_SERVER_PORT);
if (!this->dst)
{
DBG1(DBG_CFG, "configured DHCP server address invalid");
@@ -734,9 +744,6 @@ dhcp_socket_t *dhcp_socket_create()
destroy(this);
return NULL;
}
- src.sin_family = AF_INET;
- src.sin_port = htons(DHCP_CLIENT_PORT);
- src.sin_addr.s_addr = INADDR_ANY;
if (bind(this->send, (struct sockaddr*)&src, sizeof(src)) == -1)
{
DBG1(DBG_CFG, "unable to bind DHCP send socket: %s", strerror(errno));
@@ -760,9 +767,9 @@ dhcp_socket_t *dhcp_socket_create()
return NULL;
}
- this->job = callback_job_create_with_prio((callback_job_cb_t)receive_dhcp,
- this, NULL, NULL, JOB_PRIO_CRITICAL);
- lib->processor->queue_job(lib->processor, (job_t*)this->job);
+ lib->processor->queue_job(lib->processor,
+ (job_t*)callback_job_create_with_prio((callback_job_cb_t)receive_dhcp,
+ this, NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
return &this->public;
}
diff --git a/src/libcharon/plugins/duplicheck/Makefile.in b/src/libcharon/plugins/duplicheck/Makefile.in
index 87984a182..d739660da 100644
--- a/src/libcharon/plugins/duplicheck/Makefile.in
+++ b/src/libcharon/plugins/duplicheck/Makefile.in
@@ -51,6 +51,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -92,7 +93,7 @@ PROGRAMS = $(ipsec_PROGRAMS)
am_duplicheck_OBJECTS = duplicheck.$(OBJEXT)
duplicheck_OBJECTS = $(am_duplicheck_OBJECTS)
duplicheck_LDADD = $(LDADD)
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -119,6 +120,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -213,11 +215,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -234,11 +239,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -254,6 +260,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -263,7 +270,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/duplicheck/duplicheck_listener.c b/src/libcharon/plugins/duplicheck/duplicheck_listener.c
index 226b2bd4e..4f59e034f 100644
--- a/src/libcharon/plugins/duplicheck/duplicheck_listener.c
+++ b/src/libcharon/plugins/duplicheck/duplicheck_listener.c
@@ -176,9 +176,9 @@ METHOD(listener_t, ike_updown, bool,
METHOD(listener_t, message_hook, bool,
private_duplicheck_listener_t *this, ike_sa_t *ike_sa,
- message_t *message, bool incoming)
+ message_t *message, bool incoming, bool plain)
{
- if (incoming && !message->get_request(message))
+ if (incoming && plain && !message->get_request(message))
{
identification_t *id;
entry_t *entry;
diff --git a/src/libcharon/plugins/duplicheck/duplicheck_notify.c b/src/libcharon/plugins/duplicheck/duplicheck_notify.c
index b86f1ef3d..06a88ed7d 100644
--- a/src/libcharon/plugins/duplicheck/duplicheck_notify.c
+++ b/src/libcharon/plugins/duplicheck/duplicheck_notify.c
@@ -43,11 +43,6 @@ struct private_duplicheck_notify_t {
duplicheck_notify_t public;
/**
- * Callback job dispatching connections
- */
- callback_job_t *job;
-
- /**
* Mutex to lock list
*/
mutex_t *mutex;
@@ -89,7 +84,8 @@ static bool open_socket(private_duplicheck_notify_t *this)
return FALSE;
}
umask(old);
- if (chown(addr.sun_path, charon->uid, charon->gid) != 0)
+ if (chown(addr.sun_path, charon->caps->get_uid(charon->caps),
+ charon->caps->get_gid(charon->caps)) != 0)
{
DBG1(DBG_CFG, "changing duplicheck socket permissions failed: %s",
strerror(errno));
@@ -167,10 +163,6 @@ METHOD(duplicheck_notify_t, destroy, void,
enumerator_t *enumerator;
uintptr_t fd;
- if (this->job)
- {
- this->job->cancel(this->job);
- }
enumerator = this->connected->create_enumerator(this->connected);
while (enumerator->enumerate(enumerator, &fd))
{
@@ -203,9 +195,9 @@ duplicheck_notify_t *duplicheck_notify_create()
destroy(this);
return NULL;
}
- this->job = callback_job_create_with_prio((callback_job_cb_t)receive,
- this, NULL, NULL, JOB_PRIO_CRITICAL);
- lib->processor->queue_job(lib->processor, (job_t*)this->job);
+ lib->processor->queue_job(lib->processor,
+ (job_t*)callback_job_create_with_prio((callback_job_cb_t)receive, this,
+ NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
return &this->public;
}
diff --git a/src/libcharon/plugins/duplicheck/duplicheck_plugin.c b/src/libcharon/plugins/duplicheck/duplicheck_plugin.c
index df28e7f12..100ef0c2d 100644
--- a/src/libcharon/plugins/duplicheck/duplicheck_plugin.c
+++ b/src/libcharon/plugins/duplicheck/duplicheck_plugin.c
@@ -66,7 +66,7 @@ plugin_t *duplicheck_plugin_create()
private_duplicheck_plugin_t *this;
if (!lib->settings->get_bool(lib->settings,
- "charon.plugins.duplicheck.enable", TRUE))
+ "%s.plugins.duplicheck.enable", TRUE, charon->name))
{
return NULL;
}
diff --git a/src/libcharon/plugins/eap_aka/Makefile.in b/src/libcharon/plugins/eap_aka/Makefile.in
index e7a3d780a..e098c2c75 100644
--- a/src/libcharon/plugins/eap_aka/Makefile.in
+++ b/src/libcharon/plugins/eap_aka/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -86,7 +87,7 @@ libstrongswan_eap_aka_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@MONOLITHIC_FALSE@am_libstrongswan_eap_aka_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_eap_aka_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -112,6 +113,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -206,11 +208,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -227,11 +232,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -247,6 +253,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -256,7 +263,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/eap_aka/eap_aka_peer.c b/src/libcharon/plugins/eap_aka/eap_aka_peer.c
index 8c392405e..810a19c55 100644
--- a/src/libcharon/plugins/eap_aka/eap_aka_peer.c
+++ b/src/libcharon/plugins/eap_aka/eap_aka_peer.c
@@ -81,12 +81,30 @@ struct private_eap_aka_peer_t {
};
/**
+ * Generate a payload from a message, destroy message
+ */
+static bool generate_payload(simaka_message_t *message, chunk_t data,
+ eap_payload_t **out)
+{
+ chunk_t chunk;
+ bool ok;
+
+ ok = message->generate(message, data, &chunk);
+ if (ok)
+ {
+ *out = eap_payload_create_data_own(chunk);
+ }
+ message->destroy(message);
+ return ok;
+}
+
+/**
* Create a AKA_CLIENT_ERROR: "Unable to process"
*/
-static eap_payload_t* create_client_error(private_eap_aka_peer_t *this)
+static bool create_client_error(private_eap_aka_peer_t *this,
+ eap_payload_t **out)
{
simaka_message_t *message;
- eap_payload_t *out;
u_int16_t encoded;
DBG1(DBG_IKE, "sending client error '%N'",
@@ -97,9 +115,8 @@ static eap_payload_t* create_client_error(private_eap_aka_peer_t *this)
encoded = htons(AKA_UNABLE_TO_PROCESS);
message->add_attribute(message, AT_CLIENT_ERROR_CODE,
chunk_create((char*)&encoded, sizeof(encoded)));
- out = eap_payload_create_data_own(message->generate(message, chunk_empty));
- message->destroy(message);
- return out;
+
+ return generate_payload(message, chunk_empty, out);
}
/**
@@ -134,8 +151,11 @@ static status_t process_identity(private_eap_aka_peer_t *this,
default:
if (!simaka_attribute_skippable(type))
{
- *out = create_client_error(this);
enumerator->destroy(enumerator);
+ if (!create_client_error(this, out))
+ {
+ return FAILED;
+ }
return NEED_MORE;
}
break;
@@ -175,9 +195,10 @@ static status_t process_identity(private_eap_aka_peer_t *this,
{
message->add_attribute(message, AT_IDENTITY, id);
}
- *out = eap_payload_create_data_own(message->generate(message, chunk_empty));
- message->destroy(message);
-
+ if (!generate_payload(message, chunk_empty, out))
+ {
+ return FAILED;
+ }
return NEED_MORE;
}
@@ -210,8 +231,11 @@ static status_t process_challenge(private_eap_aka_peer_t *this,
default:
if (!simaka_attribute_skippable(type))
{
- *out = create_client_error(this);
enumerator->destroy(enumerator);
+ if (!create_client_error(this, out))
+ {
+ return FAILED;
+ }
return NEED_MORE;
}
break;
@@ -222,7 +246,10 @@ static status_t process_challenge(private_eap_aka_peer_t *this,
if (!rand.len || !autn.len)
{
DBG1(DBG_IKE, "received invalid EAP-AKA challenge message");
- *out = create_client_error(this);
+ if (!create_client_error(this, out))
+ {
+ return FAILED;
+ }
return NEED_MORE;
}
@@ -237,9 +264,10 @@ static status_t process_challenge(private_eap_aka_peer_t *this,
AKA_SYNCHRONIZATION_FAILURE, this->crypto);
message->add_attribute(message, AT_AUTS,
chunk_create(auts, AKA_AUTS_LEN));
- *out = eap_payload_create_data_own(message->generate(message,
- chunk_empty));
- message->destroy(message);
+ if (!generate_payload(message, chunk_empty, out))
+ {
+ return FAILED;
+ }
return NEED_MORE;
}
if (status != SUCCESS)
@@ -248,9 +276,10 @@ static status_t process_challenge(private_eap_aka_peer_t *this,
this->permanent, simaka_subtype_names, AKA_AUTHENTICATION_REJECT);
message = simaka_message_create(FALSE, in->get_identifier(in), EAP_AKA,
AKA_AUTHENTICATION_REJECT, this->crypto);
- *out = eap_payload_create_data_own(message->generate(message,
- chunk_empty));
- message->destroy(message);
+ if (!generate_payload(message, chunk_empty, out))
+ {
+ return FAILED;
+ }
return NEED_MORE;
}
@@ -261,16 +290,22 @@ static status_t process_challenge(private_eap_aka_peer_t *this,
}
data = chunk_cata("cc", chunk_create(ik, AKA_IK_LEN),
chunk_create(ck, AKA_CK_LEN));
- free(this->msk.ptr);
- this->msk = this->crypto->derive_keys_full(this->crypto, id, data, &mk);
+ chunk_clear(&this->msk);
+ if (!this->crypto->derive_keys_full(this->crypto, id, data, &mk, &this->msk))
+ {
+ return FAILED;
+ }
memcpy(this->mk, mk.ptr, mk.len);
- free(mk.ptr);
+ chunk_clear(&mk);
/* Verify AT_MAC attribute and parse() again after key derivation,
* reading encrypted attributes */
if (!in->verify(in, chunk_empty) || !in->parse(in))
{
- *out = create_client_error(this);
+ if (!create_client_error(this, out))
+ {
+ return FAILED;
+ }
return NEED_MORE;
}
@@ -300,8 +335,10 @@ static status_t process_challenge(private_eap_aka_peer_t *this,
message = simaka_message_create(FALSE, this->identifier, EAP_AKA,
AKA_CHALLENGE, this->crypto);
message->add_attribute(message, AT_RES, chunk_create(res, res_len));
- *out = eap_payload_create_data_own(message->generate(message, chunk_empty));
- message->destroy(message);
+ if (!generate_payload(message, chunk_empty, out))
+ {
+ return FAILED;
+ }
return NEED_MORE;
}
@@ -332,17 +369,26 @@ static status_t process_reauthentication(private_eap_aka_peer_t *this,
{
DBG1(DBG_IKE, "received %N, but not expected",
simaka_subtype_names, AKA_REAUTHENTICATION);
- *out = create_client_error(this);
+ if (!create_client_error(this, out))
+ {
+ return FAILED;
+ }
return NEED_MORE;
}
- this->crypto->derive_keys_reauth(this->crypto,
- chunk_create(this->mk, HASH_SIZE_SHA1));
+ if (!this->crypto->derive_keys_reauth(this->crypto,
+ chunk_create(this->mk, HASH_SIZE_SHA1)))
+ {
+ return FAILED;
+ }
/* verify MAC and parse again with decryption key */
if (!in->verify(in, chunk_empty) || !in->parse(in))
{
- *out = create_client_error(this);
+ if (!create_client_error(this, out))
+ {
+ return FAILED;
+ }
return NEED_MORE;
}
@@ -363,8 +409,11 @@ static status_t process_reauthentication(private_eap_aka_peer_t *this,
default:
if (!simaka_attribute_skippable(type))
{
- *out = create_client_error(this);
enumerator->destroy(enumerator);
+ if (!create_client_error(this, out))
+ {
+ return FAILED;
+ }
return NEED_MORE;
}
break;
@@ -375,7 +424,10 @@ static status_t process_reauthentication(private_eap_aka_peer_t *this,
if (!nonce.len || !counter.len)
{
DBG1(DBG_IKE, "EAP-AKA/Request/Reauthentication message incomplete");
- *out = create_client_error(this);
+ if (!create_client_error(this, out))
+ {
+ return FAILED;
+ }
return NEED_MORE;
}
@@ -388,10 +440,14 @@ static status_t process_reauthentication(private_eap_aka_peer_t *this,
}
else
{
- free(this->msk.ptr);
- this->msk = this->crypto->derive_keys_reauth_msk(this->crypto,
- this->reauth, counter, nonce,
- chunk_create(this->mk, HASH_SIZE_SHA1));
+ chunk_clear(&this->msk);
+ if (!this->crypto->derive_keys_reauth_msk(this->crypto,
+ this->reauth, counter, nonce,
+ chunk_create(this->mk, HASH_SIZE_SHA1), &this->msk))
+ {
+ message->destroy(message);
+ return FAILED;
+ }
if (id.len)
{
identification_t *reauth;
@@ -403,8 +459,10 @@ static status_t process_reauthentication(private_eap_aka_peer_t *this,
}
}
message->add_attribute(message, AT_COUNTER, counter);
- *out = eap_payload_create_data_own(message->generate(message, nonce));
- message->destroy(message);
+ if (!generate_payload(message, nonce, out))
+ {
+ return FAILED;
+ }
return NEED_MORE;
}
@@ -454,13 +512,17 @@ static status_t process_notification(private_eap_aka_peer_t *this,
{ /* empty notification reply */
message = simaka_message_create(FALSE, this->identifier, EAP_AKA,
AKA_NOTIFICATION, this->crypto);
- *out = eap_payload_create_data_own(message->generate(message,
- chunk_empty));
- message->destroy(message);
+ if (!generate_payload(message, chunk_empty, out))
+ {
+ return FAILED;
+ }
}
else
{
- *out = create_client_error(this);
+ if (!create_client_error(this, out))
+ {
+ return FAILED;
+ }
}
return NEED_MORE;
}
@@ -478,13 +540,19 @@ METHOD(eap_method_t, process, status_t,
message = simaka_message_create_from_payload(in->get_data(in), this->crypto);
if (!message)
{
- *out = create_client_error(this);
+ if (!create_client_error(this, out))
+ {
+ return FAILED;
+ }
return NEED_MORE;
}
if (!message->parse(message))
{
message->destroy(message);
- *out = create_client_error(this);
+ if (!create_client_error(this, out))
+ {
+ return FAILED;
+ }
return NEED_MORE;
}
switch (message->get_subtype(message))
@@ -504,8 +572,14 @@ METHOD(eap_method_t, process, status_t,
default:
DBG1(DBG_IKE, "unable to process EAP-AKA subtype %N",
simaka_subtype_names, message->get_subtype(message));
- *out = create_client_error(this);
- status = NEED_MORE;
+ if (!create_client_error(this, out))
+ {
+ status = FAILED;
+ }
+ else
+ {
+ status = NEED_MORE;
+ }
break;
}
message->destroy(message);
diff --git a/src/libcharon/plugins/eap_aka/eap_aka_peer.h b/src/libcharon/plugins/eap_aka/eap_aka_peer.h
index 974ba2721..b6ab5cdc5 100644
--- a/src/libcharon/plugins/eap_aka/eap_aka_peer.h
+++ b/src/libcharon/plugins/eap_aka/eap_aka_peer.h
@@ -23,7 +23,7 @@
typedef struct eap_aka_peer_t eap_aka_peer_t;
-#include <sa/authenticators/eap/eap_method.h>
+#include <sa/eap/eap_method.h>
/**
* EAP-AKA peer implementation.
diff --git a/src/libcharon/plugins/eap_aka/eap_aka_server.c b/src/libcharon/plugins/eap_aka/eap_aka_server.c
index d8e85ceef..b7608382d 100644
--- a/src/libcharon/plugins/eap_aka/eap_aka_server.c
+++ b/src/libcharon/plugins/eap_aka/eap_aka_server.c
@@ -119,6 +119,24 @@ struct private_eap_aka_server_t {
};
/**
+ * Generate a payload from a message, destroy message
+ */
+static bool generate_payload(simaka_message_t *message, chunk_t data,
+ eap_payload_t **out)
+{
+ chunk_t chunk;
+ bool ok;
+
+ ok = message->generate(message, data, &chunk);
+ if (ok)
+ {
+ *out = eap_payload_create_data_own(chunk);
+ }
+ message->destroy(message);
+ return ok;
+}
+
+/**
* Create EAP-AKA/Request/Identity message
*/
static status_t identity(private_eap_aka_server_t *this, eap_payload_t **out)
@@ -139,9 +157,10 @@ static status_t identity(private_eap_aka_server_t *this, eap_payload_t **out)
{
message->add_attribute(message, AT_PERMANENT_ID_REQ, chunk_empty);
}
- *out = eap_payload_create_data_own(message->generate(message, chunk_empty));
- message->destroy(message);
-
+ if (!generate_payload(message, chunk_empty, out))
+ {
+ return FAILED;
+ }
this->pending = AKA_IDENTITY;
return NEED_MORE;
}
@@ -180,8 +199,11 @@ static status_t challenge(private_eap_aka_server_t *this, eap_payload_t **out)
}
data = chunk_cata("cc", chunk_create(ik, AKA_IK_LEN),
chunk_create(ck, AKA_CK_LEN));
- free(this->msk.ptr);
- this->msk = this->crypto->derive_keys_full(this->crypto, id, data, &mk);
+ chunk_clear(&this->msk);
+ if (!this->crypto->derive_keys_full(this->crypto, id, data, &mk, &this->msk))
+ {
+ return FAILED;
+ }
this->rand = chunk_clone(chunk_create(rand, AKA_RAND_LEN));
this->xres = chunk_clone(chunk_create(xres, xres_len));
@@ -190,6 +212,7 @@ static status_t challenge(private_eap_aka_server_t *this, eap_payload_t **out)
message->add_attribute(message, AT_RAND, this->rand);
message->add_attribute(message, AT_AUTN, chunk_create(autn, AKA_AUTN_LEN));
id = this->mgr->provider_gen_reauth(this->mgr, this->permanent, mk.ptr);
+ free(mk.ptr);
if (id)
{
message->add_attribute(message, AT_NEXT_REAUTH_ID,
@@ -203,10 +226,10 @@ static status_t challenge(private_eap_aka_server_t *this, eap_payload_t **out)
id->get_encoding(id));
id->destroy(id);
}
- *out = eap_payload_create_data_own(message->generate(message, chunk_empty));
- message->destroy(message);
-
- free(mk.ptr);
+ if (!generate_payload(message, chunk_empty, out))
+ {
+ return FAILED;
+ }
this->pending = AKA_CHALLENGE;
return NEED_MORE;
}
@@ -226,15 +249,21 @@ static status_t reauthenticate(private_eap_aka_server_t *this,
DBG1(DBG_IKE, "initiating EAP-AKA reauthentication");
rng = this->crypto->get_rng(this->crypto);
- rng->allocate_bytes(rng, NONCE_LEN, &this->nonce);
+ if (!rng->allocate_bytes(rng, NONCE_LEN, &this->nonce))
+ {
+ return FAILED;
+ }
mkc = chunk_create(mk, HASH_SIZE_SHA1);
counter = htons(counter);
this->counter = chunk_clone(chunk_create((char*)&counter, sizeof(counter)));
- this->crypto->derive_keys_reauth(this->crypto, mkc);
- this->msk = this->crypto->derive_keys_reauth_msk(this->crypto,
- this->reauth, this->counter, this->nonce, mkc);
+ if (!this->crypto->derive_keys_reauth(this->crypto, mkc) ||
+ !this->crypto->derive_keys_reauth_msk(this->crypto,
+ this->reauth, this->counter, this->nonce, mkc, &this->msk))
+ {
+ return FAILED;
+ }
message = simaka_message_create(TRUE, this->identifier++, EAP_AKA,
AKA_REAUTHENTICATION, this->crypto);
@@ -247,9 +276,10 @@ static status_t reauthenticate(private_eap_aka_server_t *this,
next->get_encoding(next));
next->destroy(next);
}
- *out = eap_payload_create_data_own(message->generate(message, chunk_empty));
- message->destroy(message);
-
+ if (!generate_payload(message, chunk_empty, out))
+ {
+ return FAILED;
+ }
this->pending = SIM_REAUTHENTICATION;
return NEED_MORE;
}
@@ -691,7 +721,7 @@ eap_aka_server_t *eap_aka_server_create(identification_t *server,
this->permanent = peer->clone(peer);
this->use_reauth = this->use_pseudonym = this->use_permanent =
lib->settings->get_bool(lib->settings,
- "charon.plugins.eap-aka.request_identity", TRUE);
+ "%s.plugins.eap-aka.request_identity", TRUE, charon->name);
/* generate a non-zero identifier */
do {
diff --git a/src/libcharon/plugins/eap_aka/eap_aka_server.h b/src/libcharon/plugins/eap_aka/eap_aka_server.h
index 5ab1c4dfd..5c95180ac 100644
--- a/src/libcharon/plugins/eap_aka/eap_aka_server.h
+++ b/src/libcharon/plugins/eap_aka/eap_aka_server.h
@@ -23,7 +23,7 @@
typedef struct eap_aka_server_t eap_aka_server_t;
-#include <sa/authenticators/eap/eap_method.h>
+#include <sa/eap/eap_method.h>
/**
* EAP-AKA server implementation.
diff --git a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in
index b0890fb39..4655d341b 100644
--- a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in
+++ b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in
@@ -50,6 +50,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -88,7 +89,7 @@ libstrongswan_eap_aka_3gpp2_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_eap_aka_3gpp2_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_eap_aka_3gpp2_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -114,6 +115,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -208,11 +210,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -229,11 +234,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -249,6 +255,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -258,7 +265,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.c b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.c
index cec06fbd7..1bfc39e5a 100644
--- a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.c
+++ b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.c
@@ -74,13 +74,19 @@ METHOD(simaka_card_t, get_quintuplet, status_t,
mac = autn + AKA_SQN_LEN + AKA_AMF_LEN;
/* XOR anonymity key AK into SQN to decrypt it */
- this->f->f5(this->f, k, rand, ak);
+ if (!this->f->f5(this->f, k, rand, ak))
+ {
+ return FAILED;
+ }
DBG3(DBG_IKE, "using ak %b", ak, AKA_AK_LEN);
memxor(sqn, ak, AKA_SQN_LEN);
DBG3(DBG_IKE, "using sqn %b", sqn, AKA_SQN_LEN);
/* calculate expected MAC and compare against received one */
- this->f->f1(this->f, k, rand, sqn, amf, xmac);
+ if (!this->f->f1(this->f, k, rand, sqn, amf, xmac))
+ {
+ return FAILED;
+ }
if (!memeq(mac, xmac, AKA_MAC_LEN))
{
DBG1(DBG_IKE, "received MAC does not match XMAC");
@@ -98,11 +104,13 @@ METHOD(simaka_card_t, get_quintuplet, status_t,
/* update stored SQN to the received one */
memcpy(this->sqn, sqn, AKA_SQN_LEN);
- /* CK/IK */
- this->f->f3(this->f, k, rand, ck);
- this->f->f4(this->f, k, rand, ik);
- /* calculate RES */
- this->f->f2(this->f, k, rand, res);
+ /* CK/IK, calculate RES */
+ if (!this->f->f3(this->f, k, rand, ck) ||
+ !this->f->f4(this->f, k, rand, ik) ||
+ !this->f->f2(this->f, k, rand, res))
+ {
+ return FAILED;
+ }
*res_len = AKA_RES_MAX;
return SUCCESS;
@@ -122,8 +130,11 @@ METHOD(simaka_card_t, resync, bool,
/* AMF is set to zero in resync */
memset(amf, 0, AKA_AMF_LEN);
- this->f->f5star(this->f, k, rand, aks);
- this->f->f1star(this->f, k, rand, this->sqn, amf, macs);
+ if (!this->f->f5star(this->f, k, rand, aks) ||
+ !this->f->f1star(this->f, k, rand, this->sqn, amf, macs))
+ {
+ return FALSE;
+ }
/* AUTS = SQN xor AKS | MACS */
memcpy(auts, this->sqn, AKA_SQN_LEN);
memxor(auts, aks, AKA_AK_LEN);
@@ -160,12 +171,13 @@ eap_aka_3gpp2_card_t *eap_aka_3gpp2_card_create(eap_aka_3gpp2_functions_t *f)
},
.f = f,
.seq_check = lib->settings->get_bool(lib->settings,
- "charon.plugins.eap-aka-3gpp2.seq_check",
+ "%s.plugins.eap-aka-3gpp2.seq_check",
#ifdef SEQ_CHECK /* handle legacy compile time configuration as default */
- TRUE),
+ TRUE,
#else /* !SEQ_CHECK */
- FALSE),
+ FALSE,
#endif /* SEQ_CHECK */
+ charon->name),
);
eap_aka_3gpp2_get_sqn(this->sqn, 0);
diff --git a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_functions.c b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_functions.c
index d000bebbb..93ea8d08c 100644
--- a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_functions.c
+++ b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_functions.c
@@ -170,12 +170,12 @@ static void mpz_mod_poly(mpz_t r, mpz_t a, mpz_t b)
* Step 3 of the various fx() functions:
* XOR the key into the SHA1 IV
*/
-static void step3(prf_t *prf, u_char k[AKA_K_LEN],
+static bool step3(prf_t *prf, u_char k[AKA_K_LEN],
u_char payload[AKA_PAYLOAD_LEN], u_int8_t h[HASH_SIZE_SHA1])
{
/* use the keyed hasher to build the hash */
- prf->set_key(prf, chunk_create(k, AKA_K_LEN));
- prf->get_bytes(prf, chunk_create(payload, AKA_PAYLOAD_LEN), h);
+ return prf->set_key(prf, chunk_create(k, AKA_K_LEN)) &&
+ prf->get_bytes(prf, chunk_create(payload, AKA_PAYLOAD_LEN), h);
}
/**
@@ -211,7 +211,7 @@ static void step4(u_char x[HASH_SIZE_SHA1])
/**
* Calculation function for f2(), f3(), f4()
*/
-static void fx(prf_t *prf, u_char f, u_char k[AKA_K_LEN],
+static bool fx(prf_t *prf, u_char f, u_char k[AKA_K_LEN],
u_char rand[AKA_RAND_LEN], u_char out[AKA_MAC_LEN])
{
u_char payload[AKA_PAYLOAD_LEN];
@@ -230,16 +230,20 @@ static void fx(prf_t *prf, u_char f, u_char k[AKA_K_LEN],
payload[35] ^= i;
payload[51] ^= i;
- step3(prf, k, payload, h);
+ if (!step3(prf, k, payload, h))
+ {
+ return FALSE;
+ }
step4(h);
memcpy(out + i * 8, h, 8);
}
+ return TRUE;
}
/**
* Calculation function of f1() and f1star()
*/
-static void f1x(prf_t *prf, u_int8_t f, u_char k[AKA_K_LEN],
+static bool f1x(prf_t *prf, u_int8_t f, u_char k[AKA_K_LEN],
u_char rand[AKA_RAND_LEN], u_char sqn[AKA_SQN_LEN],
u_char amf[AKA_AMF_LEN], u_char mac[AKA_MAC_LEN])
{
@@ -257,15 +261,19 @@ static void f1x(prf_t *prf, u_int8_t f, u_char k[AKA_K_LEN],
memxor(payload + 34, sqn, AKA_SQN_LEN);
memxor(payload + 42, amf, AKA_AMF_LEN);
- step3(prf, k, payload, h);
+ if (!step3(prf, k, payload, h))
+ {
+ return FALSE;
+ }
step4(h);
memcpy(mac, h, AKA_MAC_LEN);
+ return TRUE;
}
/**
* Calculation function of f5() and f5star()
*/
-static void f5x(prf_t *prf, u_char f, u_char k[AKA_K_LEN],
+static bool f5x(prf_t *prf, u_char f, u_char k[AKA_K_LEN],
u_char rand[AKA_RAND_LEN], u_char ak[AKA_AK_LEN])
{
u_char payload[AKA_PAYLOAD_LEN];
@@ -276,88 +284,120 @@ static void f5x(prf_t *prf, u_char f, u_char k[AKA_K_LEN],
memxor(payload + 12, fmk.ptr, fmk.len);
memxor(payload + 16, rand, AKA_RAND_LEN);
- step3(prf, k, payload, h);
+ if (!step3(prf, k, payload, h))
+ {
+ return FALSE;
+ }
step4(h);
memcpy(ak, h, AKA_AK_LEN);
+ return TRUE;
}
/**
* Calculate MAC from RAND, SQN, AMF using K
*/
-METHOD(eap_aka_3gpp2_functions_t, f1, void,
+METHOD(eap_aka_3gpp2_functions_t, f1, bool,
private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
u_char rand[AKA_RAND_LEN], u_char sqn[AKA_SQN_LEN],
u_char amf[AKA_AMF_LEN], u_char mac[AKA_MAC_LEN])
{
- f1x(this->prf, F1, k, rand, sqn, amf, mac);
- DBG3(DBG_IKE, "MAC %b", mac, AKA_MAC_LEN);
+ if (f1x(this->prf, F1, k, rand, sqn, amf, mac))
+ {
+ DBG3(DBG_IKE, "MAC %b", mac, AKA_MAC_LEN);
+ return TRUE;
+ }
+ return FALSE;
}
/**
* Calculate MACS from RAND, SQN, AMF using K
*/
-METHOD(eap_aka_3gpp2_functions_t, f1star, void,
+METHOD(eap_aka_3gpp2_functions_t, f1star, bool,
private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
u_char rand[AKA_RAND_LEN], u_char sqn[AKA_SQN_LEN],
u_char amf[AKA_AMF_LEN], u_char macs[AKA_MAC_LEN])
{
- f1x(this->prf, F1STAR, k, rand, sqn, amf, macs);
- DBG3(DBG_IKE, "MACS %b", macs, AKA_MAC_LEN);
+ if (f1x(this->prf, F1STAR, k, rand, sqn, amf, macs))
+ {
+ DBG3(DBG_IKE, "MACS %b", macs, AKA_MAC_LEN);
+ return TRUE;
+ }
+ return FALSE;
}
/**
* Calculate RES from RAND using K
*/
-METHOD(eap_aka_3gpp2_functions_t, f2, void,
+METHOD(eap_aka_3gpp2_functions_t, f2, bool,
private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
u_char rand[AKA_RAND_LEN], u_char res[AKA_RES_MAX])
{
- fx(this->prf, F2, k, rand, res);
- DBG3(DBG_IKE, "RES %b", res, AKA_RES_MAX);
+ if (fx(this->prf, F2, k, rand, res))
+ {
+ DBG3(DBG_IKE, "RES %b", res, AKA_RES_MAX);
+ return TRUE;
+ }
+ return FALSE;
}
/**
* Calculate CK from RAND using K
*/
-METHOD(eap_aka_3gpp2_functions_t, f3, void,
+METHOD(eap_aka_3gpp2_functions_t, f3, bool,
private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
u_char rand[AKA_RAND_LEN], u_char ck[AKA_CK_LEN])
{
- fx(this->prf, F3, k, rand, ck);
- DBG3(DBG_IKE, "CK %b", ck, AKA_CK_LEN);
+ if (fx(this->prf, F3, k, rand, ck))
+ {
+ DBG3(DBG_IKE, "CK %b", ck, AKA_CK_LEN);
+ return TRUE;
+ }
+ return FALSE;
}
/**
* Calculate IK from RAND using K
*/
-METHOD(eap_aka_3gpp2_functions_t, f4, void,
+METHOD(eap_aka_3gpp2_functions_t, f4, bool,
private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
u_char rand[AKA_RAND_LEN], u_char ik[AKA_IK_LEN])
{
- fx(this->prf, F4, k, rand, ik);
- DBG3(DBG_IKE, "IK %b", ik, AKA_IK_LEN);
+ if (fx(this->prf, F4, k, rand, ik))
+ {
+ DBG3(DBG_IKE, "IK %b", ik, AKA_IK_LEN);
+ return TRUE;
+ }
+ return FALSE;
}
/**
* Calculate AK from a RAND using K
*/
-METHOD(eap_aka_3gpp2_functions_t, f5, void,
+METHOD(eap_aka_3gpp2_functions_t, f5, bool,
private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
u_char rand[AKA_RAND_LEN], u_char ak[AKA_AK_LEN])
{
- f5x(this->prf, F5, k, rand, ak);
- DBG3(DBG_IKE, "AK %b", ak, AKA_AK_LEN);
+ if (f5x(this->prf, F5, k, rand, ak))
+ {
+ DBG3(DBG_IKE, "AK %b", ak, AKA_AK_LEN);
+ return TRUE;
+ }
+ return FALSE;
}
/**
* Calculate AKS from a RAND using K
*/
-METHOD(eap_aka_3gpp2_functions_t, f5star, void,
+METHOD(eap_aka_3gpp2_functions_t, f5star, bool,
private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
u_char rand[AKA_RAND_LEN], u_char aks[AKA_AK_LEN])
{
- f5x(this->prf, F5STAR, k, rand, aks);
- DBG3(DBG_IKE, "AKS %b", aks, AKA_AK_LEN);
+ if (f5x(this->prf, F5STAR, k, rand, aks))
+ {
+ DBG3(DBG_IKE, "AKS %b", aks, AKA_AK_LEN);
+ return TRUE;
+ }
+ return FALSE;
}
METHOD(eap_aka_3gpp2_functions_t, destroy, void,
diff --git a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_functions.h b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_functions.h
index 855efec3e..2706da349 100644
--- a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_functions.h
+++ b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_functions.h
@@ -45,8 +45,9 @@ struct eap_aka_3gpp2_functions_t {
* @param sqn sequence number
* @param amf authentication management field
* @param mac buffer receiving mac MAC
+ * @return TRUE if calculations successful
*/
- void (*f1)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
+ bool (*f1)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
u_char rand[AKA_RAND_LEN], u_char sqn[AKA_SQN_LEN],
u_char amf[AKA_AMF_LEN], u_char mac[AKA_MAC_LEN]);
@@ -58,8 +59,9 @@ struct eap_aka_3gpp2_functions_t {
* @param sqn sequence number
* @param amf authentication management field
* @param macs buffer receiving resynchronization mac MACS
+ * @return TRUE if calculations successful
*/
- void (*f1star)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
+ bool (*f1star)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
u_char rand[AKA_RAND_LEN], u_char sqn[AKA_SQN_LEN],
u_char amf[AKA_AMF_LEN], u_char macs[AKA_MAC_LEN]);
@@ -69,8 +71,9 @@ struct eap_aka_3gpp2_functions_t {
* @param k secret key K
* @param rand random value RAND
* @param res buffer receiving result RES, uses full 128 bit
+ * @return TRUE if calculations successful
*/
- void (*f2)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
+ bool (*f2)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
u_char rand[AKA_RAND_LEN], u_char res[AKA_RES_MAX]);
/**
* Calculate CK from RAND using K
@@ -78,8 +81,9 @@ struct eap_aka_3gpp2_functions_t {
* @param k secret key K
* @param rand random value RAND
* @param macs buffer receiving encryption key CK
+ * @return TRUE if calculations successful
*/
- void (*f3)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
+ bool (*f3)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
u_char rand[AKA_RAND_LEN], u_char ck[AKA_CK_LEN]);
/**
* Calculate IK from RAND using K
@@ -87,8 +91,9 @@ struct eap_aka_3gpp2_functions_t {
* @param k secret key K
* @param rand random value RAND
* @param macs buffer receiving integrity key IK
+ * @return TRUE if calculations successful
*/
- void (*f4)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
+ bool (*f4)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
u_char rand[AKA_RAND_LEN], u_char ik[AKA_IK_LEN]);
/**
* Calculate AK from a RAND using K
@@ -96,8 +101,9 @@ struct eap_aka_3gpp2_functions_t {
* @param k secret key K
* @param rand random value RAND
* @param macs buffer receiving anonymity key AK
+ * @return TRUE if calculations successful
*/
- void (*f5)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
+ bool (*f5)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
u_char rand[AKA_RAND_LEN], u_char ak[AKA_AK_LEN]);
/**
* Calculate AKS from a RAND using K
@@ -105,8 +111,9 @@ struct eap_aka_3gpp2_functions_t {
* @param k secret key K
* @param rand random value RAND
* @param macs buffer receiving resynchronization anonymity key AKS
+ * @return TRUE if calculations successful
*/
- void (*f5star)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
+ bool (*f5star)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
u_char rand[AKA_RAND_LEN], u_char aks[AKA_AK_LEN]);
/**
diff --git a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c
index b2b43da2a..0be122158 100644
--- a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c
+++ b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c
@@ -90,12 +90,12 @@ METHOD(simaka_provider_t, get_quintuplet, bool,
/* generate RAND: we use a registered RNG, not f0() proposed in S.S0055 */
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
- if (!rng)
+ if (!rng || !rng->get_bytes(rng, AKA_RAND_LEN, rand))
{
DBG1(DBG_IKE, "generating RAND for AKA failed");
+ DESTROY_IF(rng);
return FALSE;
}
- rng->get_bytes(rng, AKA_RAND_LEN, rand);
rng->destroy(rng);
if (!eap_aka_3gpp2_get_k(id, k))
@@ -107,12 +107,13 @@ METHOD(simaka_provider_t, get_quintuplet, bool,
DBG3(DBG_IKE, "generated rand %b", rand, AKA_RAND_LEN);
DBG3(DBG_IKE, "using K %b", k, AKA_K_LEN);
- /* MAC */
- this->f->f1(this->f, k, rand, this->sqn, amf, mac);
- /* AK */
- this->f->f5(this->f, k, rand, ak);
- /* XRES as expected from client */
- this->f->f2(this->f, k, rand, xres);
+ /* MAC, AK, XRES as expected from client */
+ if (!this->f->f1(this->f, k, rand, this->sqn, amf, mac) ||
+ !this->f->f5(this->f, k, rand, ak) ||
+ !this->f->f2(this->f, k, rand, xres))
+ {
+ return FALSE;
+ }
*xres_len = AKA_RES_MAX;
/* AUTN = (SQN xor AK) || AMF || MAC */
memcpy(autn, this->sqn, AKA_SQN_LEN);
@@ -121,9 +122,11 @@ METHOD(simaka_provider_t, get_quintuplet, bool,
memcpy(autn + AKA_SQN_LEN + AKA_AMF_LEN, mac, AKA_MAC_LEN);
DBG3(DBG_IKE, "AUTN %b", autn, AKA_AUTN_LEN);
/* CK/IK */
- this->f->f3(this->f, k, rand, ck);
- this->f->f4(this->f, k, rand, ik);
-
+ if (!this->f->f3(this->f, k, rand, ck) ||
+ !this->f->f4(this->f, k, rand, ik))
+ {
+ return FALSE;
+ }
return TRUE;
}
@@ -143,12 +146,18 @@ METHOD(simaka_provider_t, resync, bool,
/* AUTHS = (AK xor SQN) | MAC */
sqn = auts;
macs = auts + AKA_SQN_LEN;
- this->f->f5star(this->f, k, rand, aks);
+ if (!this->f->f5star(this->f, k, rand, aks))
+ {
+ return FALSE;
+ }
memxor(sqn, aks, AKA_AK_LEN);
/* verify XMACS, AMF of zero is used in resynchronization */
memset(amf, 0, AKA_AMF_LEN);
- this->f->f1star(this->f, k, rand, sqn, amf, xmacs);
+ if (!this->f->f1star(this->f, k, rand, sqn, amf, xmacs))
+ {
+ return FALSE;
+ }
if (!memeq(macs, xmacs, AKA_MAC_LEN))
{
DBG1(DBG_IKE, "received MACS does not match XMACS");
diff --git a/src/libcharon/plugins/eap_dynamic/Makefile.am b/src/libcharon/plugins/eap_dynamic/Makefile.am
new file mode 100644
index 000000000..0d07fbf35
--- /dev/null
+++ b/src/libcharon/plugins/eap_dynamic/Makefile.am
@@ -0,0 +1,16 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-eap-dynamic.la
+else
+plugin_LTLIBRARIES = libstrongswan-eap-dynamic.la
+endif
+
+libstrongswan_eap_dynamic_la_SOURCES = \
+ eap_dynamic_plugin.h eap_dynamic_plugin.c eap_dynamic.h eap_dynamic.c
+
+libstrongswan_eap_dynamic_la_LDFLAGS = -module -avoid-version
diff --git a/src/whack/Makefile.in b/src/libcharon/plugins/eap_dynamic/Makefile.in
index fd768e995..bf467ebeb 100644
--- a/src/whack/Makefile.in
+++ b/src/libcharon/plugins/eap_dynamic/Makefile.in
@@ -34,8 +34,7 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-ipsec_PROGRAMS = whack$(EXEEXT)
-subdir = src/whack
+subdir = src/libcharon/plugins/eap_dynamic
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
@@ -50,16 +49,45 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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__installdirs = "$(DESTDIR)$(ipsecdir)"
-PROGRAMS = $(ipsec_PROGRAMS)
-am_whack_OBJECTS = whack.$(OBJEXT)
-whack_OBJECTS = $(am_whack_OBJECTS)
-whack_DEPENDENCIES = \
- $(top_builddir)/src/libstrongswan/libstrongswan.la \
- $(top_builddir)/src/libfreeswan/libfreeswan.a
-DEFAULT_INCLUDES = -I.@am__isrc@
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_eap_dynamic_la_LIBADD =
+am_libstrongswan_eap_dynamic_la_OBJECTS = eap_dynamic_plugin.lo \
+ eap_dynamic.lo
+libstrongswan_eap_dynamic_la_OBJECTS = \
+ $(am_libstrongswan_eap_dynamic_la_OBJECTS)
+libstrongswan_eap_dynamic_la_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_eap_dynamic_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_eap_dynamic_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_eap_dynamic_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -72,8 +100,8 @@ CCLD = $(CC)
LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
-SOURCES = $(whack_SOURCES)
-DIST_SOURCES = $(whack_SOURCES)
+SOURCES = $(libstrongswan_eap_dynamic_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_eap_dynamic_la_SOURCES)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -85,6 +113,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -179,11 +208,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -200,11 +232,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -220,6 +253,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -229,7 +263,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -257,21 +290,16 @@ top_srcdir = @top_srcdir@
urandom_device = @urandom_device@
xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
-whack_SOURCES = \
-whack.c whack.h
-
-INCLUDES = \
--I$(top_srcdir)/src/libstrongswan \
--I$(top_srcdir)/src/libfreeswan \
--I$(top_srcdir)/src/libhydra \
--I$(top_srcdir)/src/pluto
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
-whack_LDADD = \
-$(top_builddir)/src/libstrongswan/libstrongswan.la \
-$(top_builddir)/src/libfreeswan/libfreeswan.a
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-dynamic.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-dynamic.la
+libstrongswan_eap_dynamic_la_SOURCES = \
+ eap_dynamic_plugin.h eap_dynamic_plugin.c eap_dynamic.h eap_dynamic.c
-AM_CFLAGS = -DDEBUG -DIPSEC_PIDDIR=\"${piddir}\"
-EXTRA_DIST = Android.mk
+libstrongswan_eap_dynamic_la_LDFLAGS = -module -avoid-version
all: all-am
.SUFFIXES:
@@ -285,9 +313,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/whack/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/eap_dynamic/Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --gnu src/whack/Makefile
+ $(AUTOMAKE) --gnu src/libcharon/plugins/eap_dynamic/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
@@ -306,52 +334,48 @@ $(top_srcdir)/configure: $(am__configure_deps)
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
-install-ipsecPROGRAMS: $(ipsec_PROGRAMS)
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
- test -z "$(ipsecdir)" || $(MKDIR_P) "$(DESTDIR)$(ipsecdir)"
- @list='$(ipsec_PROGRAMS)'; test -n "$(ipsecdir)" || list=; \
- for p in $$list; do echo "$$p $$p"; done | \
- sed 's/$(EXEEXT)$$//' | \
- while read p p1; do if test -f $$p || test -f $$p1; \
- then echo "$$p"; echo "$$p"; else :; fi; \
- done | \
- sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
- -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
- sed 'N;N;N;s,\n, ,g' | \
- $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
- { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
- if ($$2 == $$4) files[d] = files[d] " " $$1; \
- else { print "f", $$3 "/" $$4, $$1; } } \
- END { for (d in files) print "f", d, files[d] }' | \
- while read type dir files; do \
- if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
- test -z "$$files" || { \
- echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(ipsecdir)$$dir'"; \
- $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(ipsecdir)$$dir" || exit $$?; \
- } \
- ; done
-
-uninstall-ipsecPROGRAMS:
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
@$(NORMAL_UNINSTALL)
- @list='$(ipsec_PROGRAMS)'; test -n "$(ipsecdir)" || list=; \
- files=`for p in $$list; do echo "$$p"; done | \
- sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
- -e 's/$$/$(EXEEXT)/' `; \
- test -n "$$list" || exit 0; \
- echo " ( cd '$(DESTDIR)$(ipsecdir)' && rm -f" $$files ")"; \
- cd "$(DESTDIR)$(ipsecdir)" && rm -f $$files
-
-clean-ipsecPROGRAMS:
- @list='$(ipsec_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
-whack$(EXEEXT): $(whack_OBJECTS) $(whack_DEPENDENCIES)
- @rm -f whack$(EXEEXT)
- $(LINK) $(whack_OBJECTS) $(whack_LDADD) $(LIBS)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-eap-dynamic.la: $(libstrongswan_eap_dynamic_la_OBJECTS) $(libstrongswan_eap_dynamic_la_DEPENDENCIES)
+ $(libstrongswan_eap_dynamic_la_LINK) $(am_libstrongswan_eap_dynamic_la_rpath) $(libstrongswan_eap_dynamic_la_OBJECTS) $(libstrongswan_eap_dynamic_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -359,7 +383,8 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/whack.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_dynamic.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_dynamic_plugin.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@@ -472,9 +497,9 @@ distdir: $(DISTFILES)
done
check-am: all-am
check: check-am
-all-am: Makefile $(PROGRAMS)
+all-am: Makefile $(LTLIBRARIES)
installdirs:
- for dir in "$(DESTDIR)$(ipsecdir)"; do \
+ for dir in "$(DESTDIR)$(plugindir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
@@ -504,8 +529,8 @@ maintainer-clean-generic:
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
-clean-am: clean-generic clean-ipsecPROGRAMS clean-libtool \
- mostlyclean-am
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
@@ -525,7 +550,7 @@ info: info-am
info-am:
-install-data-am: install-ipsecPROGRAMS
+install-data-am: install-pluginLTLIBRARIES
install-dvi: install-dvi-am
@@ -571,23 +596,24 @@ ps: ps-am
ps-am:
-uninstall-am: uninstall-ipsecPROGRAMS
+uninstall-am: uninstall-pluginLTLIBRARIES
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-ipsecPROGRAMS clean-libtool ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am \
- install-ipsecPROGRAMS 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 uninstall uninstall-am uninstall-ipsecPROGRAMS
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libcharon/plugins/eap_dynamic/eap_dynamic.c b/src/libcharon/plugins/eap_dynamic/eap_dynamic.c
new file mode 100644
index 000000000..d24cbd128
--- /dev/null
+++ b/src/libcharon/plugins/eap_dynamic/eap_dynamic.c
@@ -0,0 +1,393 @@
+/*
+ * Copyright (C) 2012 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 "eap_dynamic.h"
+
+#include <daemon.h>
+#include <library.h>
+
+typedef struct private_eap_dynamic_t private_eap_dynamic_t;
+
+/**
+ * Private data of an eap_dynamic_t object.
+ */
+struct private_eap_dynamic_t {
+
+ /**
+ * Public authenticator_t interface.
+ */
+ eap_dynamic_t public;
+
+ /**
+ * ID of the server
+ */
+ identification_t *server;
+
+ /**
+ * ID of the peer
+ */
+ identification_t *peer;
+
+ /**
+ * Our supported EAP types (as eap_vendor_type_t*)
+ */
+ linked_list_t *types;
+
+ /**
+ * EAP types supported by peer, if any
+ */
+ linked_list_t *other_types;
+
+ /**
+ * Prefer types sent by peer
+ */
+ bool prefer_peer;
+
+ /**
+ * The proxied EAP method
+ */
+ eap_method_t *method;
+};
+
+/**
+ * Compare two eap_vendor_type_t objects
+ */
+static bool entry_matches(eap_vendor_type_t *item, eap_vendor_type_t *other)
+{
+ return item->type == other->type && item->vendor == other->vendor;
+}
+
+/**
+ * Load the given EAP method
+ */
+static eap_method_t *load_method(private_eap_dynamic_t *this,
+ eap_type_t type, u_int32_t vendor)
+{
+ eap_method_t *method;
+
+ method = charon->eap->create_instance(charon->eap, type, vendor, EAP_SERVER,
+ this->server, this->peer);
+ if (!method)
+ {
+ if (vendor)
+ {
+ DBG1(DBG_IKE, "loading vendor specific EAP method %d-%d failed",
+ type, vendor);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "loading %N method failed", eap_type_names, type);
+ }
+ }
+ return method;
+}
+
+/**
+ * Select the first method we can instantiate and is supported by both peers.
+ */
+static void select_method(private_eap_dynamic_t *this)
+{
+ eap_vendor_type_t *entry;
+ linked_list_t *outer = this->types, *inner = this->other_types;
+ char *who = "peer";
+
+ if (this->other_types && this->prefer_peer)
+ {
+ outer = this->other_types;
+ inner = this->types;
+ who = "us";
+ }
+
+ while (outer->remove_first(outer, (void*)&entry) == SUCCESS)
+ {
+ if (inner)
+ {
+ if (inner->find_first(inner, (void*)entry_matches,
+ NULL, entry) != SUCCESS)
+ {
+ if (entry->vendor)
+ {
+ DBG2(DBG_IKE, "proposed vendor specific EAP method %d-%d "
+ "not supported by %s, skipped", entry->type,
+ entry->vendor, who);
+ }
+ else
+ {
+ DBG2(DBG_IKE, "proposed %N method not supported by %s, "
+ "skipped", eap_type_names, entry->type, who);
+ }
+ free(entry);
+ continue;
+ }
+ }
+ this->method = load_method(this, entry->type, entry->vendor);
+ if (this->method)
+ {
+ if (entry->vendor)
+ {
+ DBG1(DBG_IKE, "vendor specific EAP method %d-%d selected",
+ entry->type, entry->vendor);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "%N method selected", eap_type_names,
+ entry->type);
+ }
+ free(entry);
+ break;
+ }
+ free(entry);
+ }
+}
+
+METHOD(eap_method_t, initiate, status_t,
+ private_eap_dynamic_t *this, eap_payload_t **out)
+{
+ if (!this->method)
+ {
+ select_method(this);
+ if (!this->method)
+ {
+ DBG1(DBG_IKE, "no supported EAP method found");
+ return FAILED;
+ }
+ }
+ return this->method->initiate(this->method, out);
+}
+
+METHOD(eap_method_t, process, status_t,
+ private_eap_dynamic_t *this, eap_payload_t *in, eap_payload_t **out)
+{
+ eap_type_t received_type, type;
+ u_int32_t received_vendor, vendor;
+
+ received_type = in->get_type(in, &received_vendor);
+ if (received_vendor == 0 && received_type == EAP_NAK)
+ {
+ enumerator_t *enumerator;
+
+ DBG1(DBG_IKE, "received %N, selecting a different EAP method",
+ eap_type_names, EAP_NAK);
+
+ if (this->other_types)
+ { /* we already received a Nak or a proper response before */
+ DBG1(DBG_IKE, "%N is not supported in this state", eap_type_names,
+ EAP_NAK);
+ return FAILED;
+ }
+
+ this->other_types = linked_list_create();
+ enumerator = in->get_types(in);
+ while (enumerator->enumerate(enumerator, &type, &vendor))
+ {
+ eap_vendor_type_t *entry;
+
+ if (!type)
+ {
+ DBG1(DBG_IKE, "peer does not support any other EAP methods");
+ enumerator->destroy(enumerator);
+ return FAILED;
+ }
+ INIT(entry,
+ .type = type,
+ .vendor = vendor,
+ );
+ this->other_types->insert_last(this->other_types, entry);
+ }
+ enumerator->destroy(enumerator);
+
+ /* restart with a different method */
+ this->method->destroy(this->method);
+ this->method = NULL;
+ return initiate(this, out);
+ }
+ if (!this->other_types)
+ { /* so we don't handle EAP-Naks later */
+ this->other_types = linked_list_create();
+ }
+ if (this->method)
+ {
+ return this->method->process(this->method, in, out);
+ }
+ return FAILED;
+}
+
+METHOD(eap_method_t, get_type, eap_type_t,
+ private_eap_dynamic_t *this, u_int32_t *vendor)
+{
+ if (this->method)
+ {
+ return this->method->get_type(this->method, vendor);
+ }
+ *vendor = 0;
+ return EAP_DYNAMIC;
+}
+
+METHOD(eap_method_t, get_msk, status_t,
+ private_eap_dynamic_t *this, chunk_t *msk)
+{
+ if (this->method)
+ {
+ return this->method->get_msk(this->method, msk);
+ }
+ return FAILED;
+}
+
+METHOD(eap_method_t, get_identifier, u_int8_t,
+ private_eap_dynamic_t *this)
+{
+ if (this->method)
+ {
+ return this->method->get_identifier(this->method);
+ }
+ return 0;
+}
+
+METHOD(eap_method_t, set_identifier, void,
+ private_eap_dynamic_t *this, u_int8_t identifier)
+{
+ if (this->method)
+ {
+ this->method->set_identifier(this->method, identifier);
+ }
+}
+
+METHOD(eap_method_t, is_mutual, bool,
+ private_eap_dynamic_t *this)
+{
+ if (this->method)
+ {
+ return this->method->is_mutual(this->method);
+ }
+ return FALSE;
+}
+
+METHOD(eap_method_t, destroy, void,
+ private_eap_dynamic_t *this)
+{
+ DESTROY_IF(this->method);
+ this->types->destroy_function(this->types, (void*)free);
+ DESTROY_FUNCTION_IF(this->other_types, (void*)free);
+ this->server->destroy(this->server);
+ this->peer->destroy(this->peer);
+ free(this);
+}
+
+/**
+ * Parse preferred EAP types
+ */
+static void handle_preferred_eap_types(private_eap_dynamic_t *this,
+ char *methods)
+{
+ enumerator_t *enumerator;
+ eap_vendor_type_t *type, *entry;
+ linked_list_t *preferred;
+ char *method;
+
+ /* parse preferred EAP methods, format: type[-vendor], ... */
+ preferred = linked_list_create();
+ enumerator = enumerator_create_token(methods, ",", " ");
+ while (enumerator->enumerate(enumerator, &method))
+ {
+ type = eap_vendor_type_from_string(method);
+ if (type)
+ {
+ preferred->insert_last(preferred, type);
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ enumerator = this->types->create_enumerator(this->types);
+ while (preferred->remove_last(preferred, (void**)&type) == SUCCESS)
+ { /* move (supported) types to the front, maintain the preferred order */
+ this->types->reset_enumerator(this->types, enumerator);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry_matches(entry, type))
+ {
+ this->types->remove_at(this->types, enumerator);
+ this->types->insert_first(this->types, entry);
+ break;
+ }
+ }
+ free(type);
+ }
+ enumerator->destroy(enumerator);
+ preferred->destroy(preferred);
+}
+
+/**
+ * Get all supported EAP methods
+ */
+static void get_supported_eap_types(private_eap_dynamic_t *this)
+{
+ enumerator_t *enumerator;
+ eap_type_t type;
+ u_int32_t vendor;
+
+ enumerator = charon->eap->create_enumerator(charon->eap, EAP_SERVER);
+ while (enumerator->enumerate(enumerator, &type, &vendor))
+ {
+ eap_vendor_type_t *entry;
+
+ INIT(entry,
+ .type = type,
+ .vendor = vendor,
+ );
+ this->types->insert_last(this->types, entry);
+ }
+ enumerator->destroy(enumerator);
+}
+
+/*
+ * Defined in header
+ */
+eap_dynamic_t *eap_dynamic_create(identification_t *server,
+ identification_t *peer)
+{
+ private_eap_dynamic_t *this;
+ char *preferred;
+
+ INIT(this,
+ .public = {
+ .interface = {
+ .initiate = _initiate,
+ .process = _process,
+ .get_type = _get_type,
+ .is_mutual = _is_mutual,
+ .get_msk = _get_msk,
+ .get_identifier = _get_identifier,
+ .set_identifier = _set_identifier,
+ .destroy = _destroy,
+ },
+ },
+ .peer = peer->clone(peer),
+ .server = server->clone(server),
+ .types = linked_list_create(),
+ .prefer_peer = lib->settings->get_bool(lib->settings,
+ "%s.plugins.eap-dynamic.prefer_peer", FALSE, charon->name),
+ );
+
+ /* get all supported EAP methods */
+ get_supported_eap_types(this);
+ /* move preferred methods to the front */
+ preferred = lib->settings->get_str(lib->settings,
+ "%s.plugins.eap-dynamic.preferred", NULL, charon->name);
+ if (preferred)
+ {
+ handle_preferred_eap_types(this, preferred);
+ }
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/eap_dynamic/eap_dynamic.h b/src/libcharon/plugins/eap_dynamic/eap_dynamic.h
new file mode 100644
index 000000000..35db4fa26
--- /dev/null
+++ b/src/libcharon/plugins/eap_dynamic/eap_dynamic.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup eap_dynamic_i eap_dynamic
+ * @{ @ingroup eap_dynamic
+ */
+
+#ifndef EAP_DYNAMIC_H_
+#define EAP_DYNAMIC_H_
+
+typedef struct eap_dynamic_t eap_dynamic_t;
+
+#include <sa/eap/eap_method.h>
+
+/**
+ * Implementation of the eap_method_t interface for a virtual EAP method that
+ * proxies other EAP methods and supports the selection of the actual method
+ * by the client.
+ */
+struct eap_dynamic_t {
+
+ /**
+ * Implemented eap_method_t interface
+ */
+ eap_method_t interface;
+};
+
+/**
+ * Create a dynamic EAP proxy serving any supported real method which is also
+ * supported (or selected) by the client.
+ *
+ * @param server ID of the EAP server
+ * @param peer ID of the EAP client
+ * @return eap_dynamic_t object
+ */
+eap_dynamic_t *eap_dynamic_create(identification_t *server,
+ identification_t *peer);
+
+#endif /** EAP_DYNAMIC_H_ @}*/
diff --git a/src/pluto/plugins/xauth/xauth_plugin.c b/src/libcharon/plugins/eap_dynamic/eap_dynamic_plugin.c
index bfc4820ed..d6f38b666 100644
--- a/src/pluto/plugins/xauth/xauth_plugin.c
+++ b/src/libcharon/plugins/eap_dynamic/eap_dynamic_plugin.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Andreas Steffen
+ * Copyright (C) 2012 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -13,20 +13,31 @@
* for more details.
*/
-#include <pluto.h>
+#include "eap_dynamic_plugin.h"
-#include "xauth_plugin.h"
-#include "xauth_default_provider.h"
-#include "xauth_default_verifier.h"
+#include "eap_dynamic.h"
+
+#include <daemon.h>
METHOD(plugin_t, get_name, char*,
- xauth_plugin_t *this)
+ eap_dynamic_plugin_t *this)
{
- return "xauth";
+ return "eap-dynamic";
+}
+
+METHOD(plugin_t, get_features, int,
+ eap_dynamic_plugin_t *this, plugin_feature_t *features[])
+{
+ static plugin_feature_t f[] = {
+ PLUGIN_CALLBACK(eap_method_register, eap_dynamic_create),
+ PLUGIN_PROVIDE(EAP_SERVER, EAP_DYNAMIC),
+ };
+ *features = f;
+ return countof(f);
}
METHOD(plugin_t, destroy, void,
- xauth_plugin_t *this)
+ eap_dynamic_plugin_t *this)
{
free(this);
}
@@ -34,21 +45,18 @@ METHOD(plugin_t, destroy, void,
/*
* see header file
*/
-plugin_t *xauth_plugin_create()
+plugin_t *eap_dynamic_plugin_create()
{
- xauth_plugin_t *this;
+ eap_dynamic_plugin_t *this;
INIT(this,
.plugin = {
.get_name = _get_name,
- .reload = (void*)return_false,
+ .get_features = _get_features,
.destroy = _destroy,
},
);
- pluto->xauth->add_provider(pluto->xauth, xauth_default_provider_create());
- pluto->xauth->add_verifier(pluto->xauth, xauth_default_verifier_create());
-
return &this->plugin;
}
diff --git a/src/libcharon/plugins/eap_dynamic/eap_dynamic_plugin.h b/src/libcharon/plugins/eap_dynamic/eap_dynamic_plugin.h
new file mode 100644
index 000000000..9b124d8d2
--- /dev/null
+++ b/src/libcharon/plugins/eap_dynamic/eap_dynamic_plugin.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup eap_dynamic eap_dynamic
+ * @ingroup cplugins
+ *
+ * @defgroup eap_dynamic_plugin eap_dynamic_plugin
+ * @{ @ingroup eap_dynamic
+ */
+
+#ifndef EAP_DYNAMIC_PLUGIN_H_
+#define EAP_DYNAMIC_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct eap_dynamic_plugin_t eap_dynamic_plugin_t;
+
+/**
+ * EAP plugin that can use any supported EAP method the client supports or
+ * prefers to use.
+ */
+struct eap_dynamic_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** EAP_DYNAMIC_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/eap_gtc/Makefile.am b/src/libcharon/plugins/eap_gtc/Makefile.am
index d8722bf9d..e4234fab2 100644
--- a/src/libcharon/plugins/eap_gtc/Makefile.am
+++ b/src/libcharon/plugins/eap_gtc/Makefile.am
@@ -13,4 +13,4 @@ endif
libstrongswan_eap_gtc_la_SOURCES = \
eap_gtc_plugin.h eap_gtc_plugin.c eap_gtc.h eap_gtc.c
-libstrongswan_eap_gtc_la_LDFLAGS = -module -avoid-version -lpam
+libstrongswan_eap_gtc_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/eap_gtc/Makefile.in b/src/libcharon/plugins/eap_gtc/Makefile.in
index b3f989e38..8a334983b 100644
--- a/src/libcharon/plugins/eap_gtc/Makefile.in
+++ b/src/libcharon/plugins/eap_gtc/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -84,7 +85,7 @@ libstrongswan_eap_gtc_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@MONOLITHIC_FALSE@am_libstrongswan_eap_gtc_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_eap_gtc_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -110,6 +111,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -204,11 +206,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -225,11 +230,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -245,6 +251,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -254,7 +261,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -291,7 +297,7 @@ AM_CFLAGS = -rdynamic
libstrongswan_eap_gtc_la_SOURCES = \
eap_gtc_plugin.h eap_gtc_plugin.c eap_gtc.h eap_gtc.c
-libstrongswan_eap_gtc_la_LDFLAGS = -module -avoid-version -lpam
+libstrongswan_eap_gtc_la_LDFLAGS = -module -avoid-version
all: all-am
.SUFFIXES:
diff --git a/src/libcharon/plugins/eap_gtc/eap_gtc.c b/src/libcharon/plugins/eap_gtc/eap_gtc.c
index c3ab07de0..f090e94a8 100644
--- a/src/libcharon/plugins/eap_gtc/eap_gtc.c
+++ b/src/libcharon/plugins/eap_gtc/eap_gtc.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2007 Martin Willi
+ * Copyright (C) 2007-2012 Martin Willi
+ * Copyright (C) 2012 revosec AG
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -17,12 +18,8 @@
#include <daemon.h>
#include <library.h>
-#include <crypto/hashers/hasher.h>
-
-#include <security/pam_appl.h>
#define GTC_REQUEST_MSG "password"
-#define GTC_PAM_SERVICE "login"
typedef struct private_eap_gtc_t private_eap_gtc_t;
@@ -77,63 +74,6 @@ METHOD(eap_method_t, initiate_peer, status_t,
return FAILED;
}
-/**
- * PAM conv callback function
- */
-static int auth_conv(int num_msg, const struct pam_message **msg,
- struct pam_response **resp, char *password)
-{
- struct pam_response *response;
-
- if (num_msg != 1)
- {
- return PAM_CONV_ERR;
- }
- response = malloc(sizeof(struct pam_response));
- response->resp = strdup(password);
- response->resp_retcode = 0;
- *resp = response;
- return PAM_SUCCESS;
-}
-
-/**
- * Authenticate a username/password using PAM
- */
-static bool authenticate(char *service, char *user, char *password)
-{
- pam_handle_t *pamh = NULL;
- static struct pam_conv conv;
- int ret;
-
- conv.conv = (void*)auth_conv;
- conv.appdata_ptr = password;
-
- ret = pam_start(service, user, &conv, &pamh);
- if (ret != PAM_SUCCESS)
- {
- DBG1(DBG_IKE, "EAP-GTC pam_start failed: %s",
- pam_strerror(pamh, ret));
- return FALSE;
- }
- ret = pam_authenticate(pamh, 0);
- if (ret == PAM_SUCCESS)
- {
- ret = pam_acct_mgmt(pamh, 0);
- if (ret != PAM_SUCCESS)
- {
- DBG1(DBG_IKE, "EAP-GTC pam_acct_mgmt failed: %s",
- pam_strerror(pamh, ret));
- }
- }
- else
- {
- DBG1(DBG_IKE, "EAP-GTC pam_authenticate failed: %s",
- pam_strerror(pamh, ret));
- }
- pam_end(pamh, ret);
- return ret == PAM_SUCCESS;
-}
-
METHOD(eap_method_t, initiate_server, status_t,
private_eap_gtc_t *this, eap_payload_t **out)
{
@@ -192,39 +132,57 @@ METHOD(eap_method_t, process_peer, status_t,
METHOD(eap_method_t, process_server, status_t,
private_eap_gtc_t *this, eap_payload_t *in, eap_payload_t **out)
{
- chunk_t data, encoding;
- char *user, *password, *service, *pos;
-
- data = chunk_skip(in->get_data(in), 5);
- if (this->identifier != in->get_identifier(in) || !data.len)
+ status_t status = FAILED;
+ chunk_t user, pass;
+ xauth_method_t *xauth;
+ cp_payload_t *ci, *co;
+ char *backend;
+
+ user = this->peer->get_encoding(this->peer);
+ pass = chunk_skip(in->get_data(in), 5);
+ if (this->identifier != in->get_identifier(in) || !pass.len)
{
DBG1(DBG_IKE, "received invalid EAP-GTC message");
return FAILED;
}
- encoding = this->peer->get_encoding(this->peer);
- /* if a RFC822_ADDR id is provided, we use the username part only */
- pos = memchr(encoding.ptr, '@', encoding.len);
- if (pos)
+ /* get XAuth backend to use for credential verification. Default to PAM
+ * to support legacy EAP-GTC configurations */
+ backend = lib->settings->get_str(lib->settings,
+ "%s.plugins.eap-gtc.backend", "pam", charon->name);
+ xauth = charon->xauth->create_instance(charon->xauth, backend, XAUTH_SERVER,
+ this->server, this->peer);
+ if (!xauth)
{
- encoding.len = (u_char*)pos - encoding.ptr;
+ DBG1(DBG_IKE, "creating EAP-GTC XAuth backend '%s' failed", backend);
+ return FAILED;
}
- user = alloca(encoding.len + 1);
- memcpy(user, encoding.ptr, encoding.len);
- user[encoding.len] = '\0';
-
- password = alloca(data.len + 1);
- memcpy(password, data.ptr, data.len);
- password[data.len] = '\0';
-
- service = lib->settings->get_str(lib->settings,
- "charon.plugins.eap-gtc.pam_service", GTC_PAM_SERVICE);
-
- if (!authenticate(service, user, password))
+ if (xauth->initiate(xauth, &co) == NEED_MORE)
{
- return FAILED;
+ /* assume that "out" contains username/password attributes */
+ co->destroy(co);
+ ci = cp_payload_create_type(CONFIGURATION_V1, CFG_REPLY);
+ ci->add_attribute(ci, configuration_attribute_create_chunk(
+ CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_NAME, user));
+ ci->add_attribute(ci, configuration_attribute_create_chunk(
+ CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_PASSWORD, pass));
+ switch (xauth->process(xauth, ci, &co))
+ {
+ case SUCCESS:
+ status = SUCCESS;
+ break;
+ case NEED_MORE:
+ /* TODO: multiple exchanges currently not supported */
+ co->destroy(co);
+ break;
+ case FAILED:
+ default:
+ break;
+ }
+ ci->destroy(ci);
}
- return SUCCESS;
+ xauth->destroy(xauth);
+ return status;
}
METHOD(eap_method_t, get_type, eap_type_t,
diff --git a/src/libcharon/plugins/eap_gtc/eap_gtc.h b/src/libcharon/plugins/eap_gtc/eap_gtc.h
index 2eb8482f8..4dac53cfb 100644
--- a/src/libcharon/plugins/eap_gtc/eap_gtc.h
+++ b/src/libcharon/plugins/eap_gtc/eap_gtc.h
@@ -23,7 +23,7 @@
typedef struct eap_gtc_t eap_gtc_t;
-#include <sa/authenticators/eap/eap_method.h>
+#include <sa/eap/eap_method.h>
/**
* Implementation of the eap_method_t interface using EAP-GTC.
diff --git a/src/libcharon/plugins/eap_gtc/eap_gtc_plugin.c b/src/libcharon/plugins/eap_gtc/eap_gtc_plugin.c
index bd70b757a..d579eaa5a 100644
--- a/src/libcharon/plugins/eap_gtc/eap_gtc_plugin.c
+++ b/src/libcharon/plugins/eap_gtc/eap_gtc_plugin.c
@@ -19,9 +19,6 @@
#include <daemon.h>
-/* missing in cababilities.h */
-#define CAP_AUDIT_WRITE 29
-
METHOD(plugin_t, get_name, char*,
eap_gtc_plugin_t *this)
{
@@ -62,14 +59,6 @@ plugin_t *eap_gtc_plugin_create()
},
);
- /* required for PAM authentication */
- charon->keep_cap(charon, CAP_AUDIT_WRITE);
-
- charon->eap->add_method(charon->eap, EAP_GTC, 0, EAP_SERVER,
- (eap_constructor_t)eap_gtc_create_server);
- charon->eap->add_method(charon->eap, EAP_GTC, 0, EAP_PEER,
- (eap_constructor_t)eap_gtc_create_peer);
-
return &this->plugin;
}
diff --git a/src/libcharon/plugins/eap_identity/Makefile.in b/src/libcharon/plugins/eap_identity/Makefile.in
index b348b5fb5..2f4494c39 100644
--- a/src/libcharon/plugins/eap_identity/Makefile.in
+++ b/src/libcharon/plugins/eap_identity/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -86,7 +87,7 @@ libstrongswan_eap_identity_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_eap_identity_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_eap_identity_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -112,6 +113,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -206,11 +208,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -227,11 +232,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -247,6 +253,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -256,7 +263,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/eap_identity/eap_identity.h b/src/libcharon/plugins/eap_identity/eap_identity.h
index 9a7f28574..4e7f6fd9d 100644
--- a/src/libcharon/plugins/eap_identity/eap_identity.h
+++ b/src/libcharon/plugins/eap_identity/eap_identity.h
@@ -23,7 +23,7 @@
typedef struct eap_identity_t eap_identity_t;
-#include <sa/authenticators/eap/eap_method.h>
+#include <sa/eap/eap_method.h>
/**
* Implementation of the eap_method_t interface using EAP Identity.
diff --git a/src/libcharon/plugins/eap_md5/Makefile.in b/src/libcharon/plugins/eap_md5/Makefile.in
index 209753b2d..dcf95198f 100644
--- a/src/libcharon/plugins/eap_md5/Makefile.in
+++ b/src/libcharon/plugins/eap_md5/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -84,7 +85,7 @@ libstrongswan_eap_md5_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@MONOLITHIC_FALSE@am_libstrongswan_eap_md5_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_eap_md5_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -110,6 +111,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -204,11 +206,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -225,11 +230,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -245,6 +251,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -254,7 +261,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/eap_md5/eap_md5.c b/src/libcharon/plugins/eap_md5/eap_md5.c
index b0a234527..b2640d104 100644
--- a/src/libcharon/plugins/eap_md5/eap_md5.c
+++ b/src/libcharon/plugins/eap_md5/eap_md5.c
@@ -100,7 +100,11 @@ static status_t hash_challenge(private_eap_md5_t *this, chunk_t *response,
DBG1(DBG_IKE, "EAP-MD5 failed, MD5 not supported");
return FAILED;
}
- hasher->allocate_hash(hasher, concat, response);
+ if (!hasher->allocate_hash(hasher, concat, response))
+ {
+ hasher->destroy(hasher);
+ return FAILED;
+ }
hasher->destroy(hasher);
return SUCCESS;
}
@@ -119,11 +123,11 @@ METHOD(eap_method_t, initiate_server, status_t,
eap_md5_header_t *req;
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
- if (!rng)
+ if (!rng || !rng->allocate_bytes(rng, CHALLENGE_LEN, &this->challenge))
{
+ DESTROY_IF(rng);
return FAILED;
}
- rng->allocate_bytes(rng, CHALLENGE_LEN, &this->challenge);
rng->destroy(rng);
req = alloca(PAYLOAD_LEN);
diff --git a/src/libcharon/plugins/eap_md5/eap_md5.h b/src/libcharon/plugins/eap_md5/eap_md5.h
index c6687149a..5396535e1 100644
--- a/src/libcharon/plugins/eap_md5/eap_md5.h
+++ b/src/libcharon/plugins/eap_md5/eap_md5.h
@@ -23,7 +23,7 @@
typedef struct eap_md5_t eap_md5_t;
-#include <sa/authenticators/eap/eap_method.h>
+#include <sa/eap/eap_method.h>
/**
* Implementation of the eap_method_t interface using EAP-MD5 (CHAP).
diff --git a/src/libcharon/plugins/eap_mschapv2/Makefile.in b/src/libcharon/plugins/eap_mschapv2/Makefile.in
index 6d3d7f8db..e954396ec 100644
--- a/src/libcharon/plugins/eap_mschapv2/Makefile.in
+++ b/src/libcharon/plugins/eap_mschapv2/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -86,7 +87,7 @@ libstrongswan_eap_mschapv2_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_eap_mschapv2_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_eap_mschapv2_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -112,6 +113,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -206,11 +208,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -227,11 +232,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -247,6 +253,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -256,7 +263,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c
index 9dfc69205..0d71c3d97 100644
--- a/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c
+++ b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c
@@ -281,7 +281,11 @@ static status_t NtPasswordHash(chunk_t password, chunk_t *password_hash)
DBG1(DBG_IKE, "EAP-MS-CHAPv2 failed, no MD4 hasher available");
return FAILED;
}
- hasher->allocate_hash(hasher, password, password_hash);
+ if (!hasher->allocate_hash(hasher, password, password_hash))
+ {
+ hasher->destroy(hasher);
+ return FAILED;
+ }
hasher->destroy(hasher);
return SUCCESS;
}
@@ -302,7 +306,11 @@ static status_t ChallengeHash(chunk_t peer_challenge, chunk_t server_challenge,
return FAILED;
}
concat = chunk_cata("ccc", peer_challenge, server_challenge, username);
- hasher->allocate_hash(hasher, concat, challenge_hash);
+ if (!hasher->allocate_hash(hasher, concat, challenge_hash))
+ {
+ hasher->destroy(hasher);
+ return FAILED;
+ }
hasher->destroy(hasher);
/* we need only the first 8 octets */
challenge_hash->len = 8;
@@ -337,9 +345,15 @@ static status_t ChallengeResponse(chunk_t challenge_hash, chunk_t password_hash,
for (i = 0; i < 3; i++)
{
chunk_t expanded, encrypted;
+
expanded = ExpandDESKey(keys[i]);
- crypter->set_key(crypter, expanded);
- crypter->encrypt(crypter, challenge_hash, chunk_empty, &encrypted);
+ if (!crypter->set_key(crypter, expanded) ||
+ !crypter->encrypt(crypter, challenge_hash, chunk_empty, &encrypted))
+ {
+ chunk_clear(&expanded);
+ crypter->destroy(crypter);
+ return FAILED;
+ }
memcpy(&response->ptr[i * 8], encrypted.ptr, encrypted.len);
chunk_clear(&encrypted);
chunk_clear(&expanded);
@@ -376,10 +390,17 @@ static status_t AuthenticatorResponse(chunk_t password_hash_hash,
}
concat = chunk_cata("ccc", password_hash_hash, nt_response, magic1);
- hasher->allocate_hash(hasher, concat, &digest);
+ if (!hasher->allocate_hash(hasher, concat, &digest))
+ {
+ hasher->destroy(hasher);
+ return FAILED;
+ }
concat = chunk_cata("ccc", digest, challenge_hash, magic2);
- hasher->allocate_hash(hasher, concat, response);
-
+ if (!hasher->allocate_hash(hasher, concat, response))
+ {
+ hasher->destroy(hasher);
+ return FAILED;
+ }
hasher->destroy(hasher);
chunk_free(&digest);
return SUCCESS;
@@ -428,7 +449,9 @@ static status_t GenerateMSK(chunk_t password_hash_hash,
chunk_t keypad = chunk_from_chars(
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
- chunk_t concat, master_key, master_receive_key, master_send_key;
+ char master_key[HASH_SIZE_SHA1];
+ char master_receive_key[HASH_SIZE_SHA1], master_send_key[HASH_SIZE_SHA1];
+ chunk_t concat, master;
hasher_t *hasher;
hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
@@ -439,23 +462,29 @@ static status_t GenerateMSK(chunk_t password_hash_hash,
}
concat = chunk_cata("ccc", password_hash_hash, nt_response, magic1);
- hasher->allocate_hash(hasher, concat, &master_key);
- master_key.len = 16;
-
- concat = chunk_cata("cccc", master_key, shapad1, magic2, shapad2);
- hasher->allocate_hash(hasher, concat, &master_receive_key);
- master_receive_key.len = 16;
-
- concat = chunk_cata("cccc", master_key, shapad1, magic3, shapad2);
- hasher->allocate_hash(hasher, concat, &master_send_key);
- master_send_key.len = 16;
+ if (!hasher->get_hash(hasher, concat, master_key))
+ {
+ hasher->destroy(hasher);
+ return FAILED;
+ }
+ master = chunk_create(master_key, 16);
+ concat = chunk_cata("cccc", master, shapad1, magic2, shapad2);
+ if (!hasher->get_hash(hasher, concat, master_receive_key))
+ {
+ hasher->destroy(hasher);
+ return FAILED;
+ }
+ concat = chunk_cata("cccc", master, shapad1, magic3, shapad2);
+ if (!hasher->get_hash(hasher, concat, master_send_key))
+ {
+ hasher->destroy(hasher);
+ return FAILED;
+ }
- *msk = chunk_cat("cccc", master_receive_key, master_send_key, keypad, keypad);
+ *msk = chunk_cat("cccc", chunk_create(master_receive_key, 16),
+ chunk_create(master_send_key, 16), keypad, keypad);
hasher->destroy(hasher);
- chunk_free(&master_key);
- chunk_free(&master_receive_key);
- chunk_free(&master_send_key);
return SUCCESS;
}
@@ -533,13 +562,12 @@ static char* sanitize(char *str)
/**
* Returns a chunk of just the username part of the given user identity.
- * Note: the chunk points to internal data of the identification.
+ * Note: the chunk points to internal data of the given chunk
*/
-static chunk_t extract_username(identification_t* identification)
+static chunk_t extract_username(chunk_t id)
{
char *has_domain;
- chunk_t id;
- id = identification->get_encoding(identification);
+
has_domain = (char*)memchr(id.ptr, '\\', id.len);
if (has_domain)
{
@@ -577,12 +605,12 @@ METHOD(eap_method_t, initiate_server, status_t,
u_int16_t len = CHALLENGE_PAYLOAD_LEN + sizeof(MSCHAPV2_HOST_NAME) - 1;
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
- if (!rng)
+ if (!rng || !rng->allocate_bytes(rng, CHALLENGE_LEN, &this->challenge))
{
- DBG1(DBG_IKE, "EAP-MS-CHAPv2 failed, no RNG");
+ DBG1(DBG_IKE, "EAP-MS-CHAPv2 failed, no challenge");
+ DESTROY_IF(rng);
return FAILED;
}
- rng->allocate_bytes(rng, CHALLENGE_LEN, &this->challenge);
rng->destroy(rng);
eap = alloca(len);
@@ -645,7 +673,7 @@ static status_t process_peer_challenge(private_eap_mschapv2_t *this,
eap_mschapv2_header_t *eap;
eap_mschapv2_challenge_t *cha;
eap_mschapv2_response_t *res;
- chunk_t data, peer_challenge, username, nt_hash;
+ chunk_t data, peer_challenge, userid, username, nt_hash;
u_int16_t len = RESPONSE_PAYLOAD_LEN;
data = in->get_data(in);
@@ -670,14 +698,14 @@ static status_t process_peer_challenge(private_eap_mschapv2_t *this,
this->mschapv2id = eap->ms_chapv2_id;
this->challenge = chunk_clone(chunk_create(cha->challenge, CHALLENGE_LEN));
+ peer_challenge = chunk_alloca(CHALLENGE_LEN);
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
- if (!rng)
+ if (!rng || !rng->get_bytes(rng, CHALLENGE_LEN, peer_challenge.ptr))
{
- DBG1(DBG_IKE, "EAP-MS-CHAPv2 failed, no RNG");
+ DBG1(DBG_IKE, "EAP-MS-CHAPv2 failed, allocating challenge failed");
+ DESTROY_IF(rng);
return FAILED;
}
- peer_challenge = chunk_alloca(CHALLENGE_LEN);
- rng->get_bytes(rng, CHALLENGE_LEN, peer_challenge.ptr);
rng->destroy(rng);
if (!get_nt_hash(this, this->peer, this->server, &nt_hash))
@@ -687,8 +715,11 @@ static status_t process_peer_challenge(private_eap_mschapv2_t *this,
return NOT_FOUND;
}
- username = extract_username(this->peer);
- len += username.len;
+ /* we transmit the whole user identity (including the domain part) but
+ * only use the user part when calculating the challenge hash */
+ userid = this->peer->get_encoding(this->peer);
+ len += userid.len;
+ username = extract_username(userid);
if (GenerateStuff(this, this->challenge, peer_challenge,
username, nt_hash) != SUCCESS)
@@ -713,9 +744,7 @@ static status_t process_peer_challenge(private_eap_mschapv2_t *this,
memset(&res->response, 0, RESPONSE_LEN);
memcpy(res->response.peer_challenge, peer_challenge.ptr, peer_challenge.len);
memcpy(res->response.nt_response, this->nt_response.ptr, this->nt_response.len);
-
- username = this->peer->get_encoding(this->peer);
- memcpy(res->name, username.ptr, username.len);
+ memcpy(res->name, userid.ptr, userid.len);
*out = eap_payload_create_data(chunk_create((void*) eap, len));
return NEED_MORE;
@@ -964,12 +993,12 @@ static status_t process_server_retry(private_eap_mschapv2_t *this,
DBG1(DBG_IKE, "EAP-MS-CHAPv2 verification failed, retry (%d)", this->retries);
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
- if (!rng)
+ if (!rng || !rng->get_bytes(rng, CHALLENGE_LEN, this->challenge.ptr))
{
- DBG1(DBG_IKE, "EAP-MS-CHAPv2 failed, no RNG");
+ DBG1(DBG_IKE, "EAP-MS-CHAPv2 failed, allocating challenge failed");
+ DESTROY_IF(rng);
return FAILED;
}
- rng->get_bytes(rng, CHALLENGE_LEN, this->challenge.ptr);
rng->destroy(rng);
chunk_free(&this->nt_response);
@@ -1026,7 +1055,8 @@ static status_t process_server_response(private_eap_mschapv2_t *this,
snprintf(buf, sizeof(buf), "%.*s", name_len, res->name);
userid = identification_create_from_string(buf);
DBG2(DBG_IKE, "EAP-MS-CHAPv2 username: '%Y'", userid);
- username = extract_username(userid);
+ /* userid can only be destroyed after the last use of username */
+ username = extract_username(userid->get_encoding(userid));
if (!get_nt_hash(this, this->server, userid, &nt_hash))
{
diff --git a/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.h b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.h
index 34cc1141e..0e7abc397 100644
--- a/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.h
+++ b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.h
@@ -23,7 +23,7 @@
typedef struct eap_mschapv2_t eap_mschapv2_t;
-#include <sa/authenticators/eap/eap_method.h>
+#include <sa/eap/eap_method.h>
/**
* Implementation of the eap_method_t interface using EAP-MS-CHAPv2.
diff --git a/src/libcharon/plugins/eap_peap/Makefile.in b/src/libcharon/plugins/eap_peap/Makefile.in
index 4f860e175..82aa990ae 100644
--- a/src/libcharon/plugins/eap_peap/Makefile.in
+++ b/src/libcharon/plugins/eap_peap/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -87,7 +88,7 @@ libstrongswan_eap_peap_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_eap_peap_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_eap_peap_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -113,6 +114,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -207,11 +209,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -228,11 +233,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -248,6 +254,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -257,7 +264,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/eap_peap/eap_peap.c b/src/libcharon/plugins/eap_peap/eap_peap.c
index bd426bba7..8aba703c5 100644
--- a/src/libcharon/plugins/eap_peap/eap_peap.c
+++ b/src/libcharon/plugins/eap_peap/eap_peap.c
@@ -156,16 +156,19 @@ static eap_peap_t *eap_peap_create(private_eap_peap_t * this,
tls_t *tls;
if (is_server && !lib->settings->get_bool(lib->settings,
- "charon.plugins.eap-peap.request_peer_auth", FALSE))
+ "%s.plugins.eap-peap.request_peer_auth", FALSE,
+ charon->name))
{
peer = NULL;
}
frag_size = lib->settings->get_int(lib->settings,
- "charon.plugins.eap-peap.fragment_size", MAX_FRAGMENT_LEN);
+ "%s.plugins.eap-peap.fragment_size", MAX_FRAGMENT_LEN,
+ charon->name);
max_msg_count = lib->settings->get_int(lib->settings,
- "charon.plugins.eap-peap.max_message_count", MAX_MESSAGE_COUNT);
+ "%s.plugins.eap-peap.max_message_count", MAX_MESSAGE_COUNT,
+ charon->name);
include_length = lib->settings->get_bool(lib->settings,
- "charon.plugins.eap-peap.include_length", FALSE);
+ "%s.plugins.eap-peap.include_length", FALSE, charon->name);
tls = tls_create(is_server, server, peer, TLS_PURPOSE_EAP_PEAP,
application, NULL);
this->tls_eap = tls_eap_create(EAP_PEAP, tls, frag_size, max_msg_count,
@@ -180,7 +183,7 @@ static eap_peap_t *eap_peap_create(private_eap_peap_t * this,
}
eap_peap_t *eap_peap_create_server(identification_t *server,
- identification_t *peer)
+ identification_t *peer)
{
private_eap_peap_t *eap_peap;
eap_method_t *eap_method;
diff --git a/src/libcharon/plugins/eap_peap/eap_peap.h b/src/libcharon/plugins/eap_peap/eap_peap.h
index f47bad561..2756ad3e6 100644
--- a/src/libcharon/plugins/eap_peap/eap_peap.h
+++ b/src/libcharon/plugins/eap_peap/eap_peap.h
@@ -23,7 +23,7 @@
typedef struct eap_peap_t eap_peap_t;
-#include <sa/authenticators/eap/eap_method.h>
+#include <sa/eap/eap_method.h>
/**
* Implementation of eap_method_t using EAP-PEAP.
diff --git a/src/libcharon/plugins/eap_peap/eap_peap_peer.c b/src/libcharon/plugins/eap_peap/eap_peap_peer.c
index 72e201fb6..79fd667cb 100644
--- a/src/libcharon/plugins/eap_peap/eap_peap_peer.c
+++ b/src/libcharon/plugins/eap_peap/eap_peap_peer.c
@@ -85,7 +85,7 @@ METHOD(tls_application_t, process, status_t,
default:
return FAILED;
}
-
+
in = eap_payload_create_data(data);
DBG3(DBG_IKE, "%B", &data);
chunk_free(&data);
@@ -151,7 +151,8 @@ METHOD(tls_application_t, process, status_t,
if (!this->ph2_method)
{
DBG1(DBG_IKE, "EAP method not supported");
- this->out = eap_payload_create_nak(in->get_identifier(in));
+ this->out = eap_payload_create_nak(in->get_identifier(in), 0, 0,
+ in->is_expanded(in));
in->destroy(in);
return NEED_MORE;
}
diff --git a/src/libcharon/plugins/eap_peap/eap_peap_peer.h b/src/libcharon/plugins/eap_peap/eap_peap_peer.h
index a87544209..196d4e2c4 100644
--- a/src/libcharon/plugins/eap_peap/eap_peap_peer.h
+++ b/src/libcharon/plugins/eap_peap/eap_peap_peer.h
@@ -26,7 +26,7 @@ typedef struct eap_peap_peer_t eap_peap_peer_t;
#include "tls_application.h"
#include <library.h>
-#include <sa/authenticators/eap/eap_method.h>
+#include <sa/eap/eap_method.h>
/**
* TLS application data handler as peer.
diff --git a/src/libcharon/plugins/eap_peap/eap_peap_server.c b/src/libcharon/plugins/eap_peap/eap_peap_server.c
index 4acdd9f07..0e8046501 100644
--- a/src/libcharon/plugins/eap_peap/eap_peap_server.c
+++ b/src/libcharon/plugins/eap_peap/eap_peap_server.c
@@ -91,7 +91,8 @@ static status_t start_phase2_auth(private_eap_peap_server_t *this)
eap_type_t type;
eap_type_str = lib->settings->get_str(lib->settings,
- "charon.plugins.eap-peap.phase2_method", "mschapv2");
+ "%s.plugins.eap-peap.phase2_method", "mschapv2",
+ charon->name);
type = eap_type_from_string(eap_type_str);
if (type == 0)
{
@@ -128,7 +129,7 @@ static status_t start_phase2_auth(private_eap_peap_server_t *this)
static status_t start_phase2_tnc(private_eap_peap_server_t *this)
{
if (this->start_phase2_tnc && lib->settings->get_bool(lib->settings,
- "charon.plugins.eap-peap.phase2_tnc", FALSE))
+ "%s.plugins.eap-peap.phase2_tnc", FALSE, charon->name))
{
DBG1(DBG_IKE, "phase2 method %N selected", eap_type_names, EAP_TNC);
this->ph2_method = charon->eap->create_instance(charon->eap, EAP_TNC,
@@ -197,7 +198,7 @@ METHOD(tls_application_t, process, status_t,
{
received_type = in->get_type(in, &received_vendor);
DBG1(DBG_IKE, "received tunneled EAP-PEAP AVP [EAP/%N/%N]",
- eap_code_short_names, code,
+ eap_code_short_names, code,
eap_type_short_names, received_type);
if (code != EAP_RESPONSE)
{
@@ -209,7 +210,7 @@ METHOD(tls_application_t, process, status_t,
else
{
DBG1(DBG_IKE, "received tunneled EAP-PEAP AVP [EAP/%N]",
- eap_code_short_names, code);
+ eap_code_short_names, code);
/* if EAP_SUCCESS check if to continue phase2 with EAP-TNC */
return (this->phase2_result == EAP_SUCCESS && code == EAP_SUCCESS) ?
@@ -273,7 +274,7 @@ METHOD(tls_application_t, process, status_t,
/* Start Phase 2 of EAP-PEAP authentication */
if (lib->settings->get_bool(lib->settings,
- "charon.plugins.eap-peap.request_peer_auth", FALSE))
+ "%s.plugins.eap-peap.request_peer_auth", FALSE, charon->name))
{
return start_phase2_tnc(this);
}
@@ -302,10 +303,10 @@ METHOD(tls_application_t, process, status_t,
this->ph2_method->destroy(this->ph2_method);
this->ph2_method = NULL;
- /* EAP-PEAP requires the sending of an inner EAP_SUCCESS message */
- this->phase2_result = EAP_SUCCESS;
+ /* EAP-PEAP requires the sending of an inner EAP_SUCCESS message */
+ this->phase2_result = EAP_SUCCESS;
this->out = eap_payload_create_code(this->phase2_result, 1 +
- this->ph1_method->get_identifier(this->ph1_method));
+ this->ph1_method->get_identifier(this->ph1_method));
return NEED_MORE;
case NEED_MORE:
break;
@@ -321,9 +322,9 @@ METHOD(tls_application_t, process, status_t,
DBG1(DBG_IKE, "%N method failed", eap_type_names, type);
}
/* EAP-PEAP requires the sending of an inner EAP_FAILURE message */
- this->phase2_result = EAP_FAILURE;
+ this->phase2_result = EAP_FAILURE;
this->out = eap_payload_create_code(this->phase2_result, 1 +
- this->ph1_method->get_identifier(this->ph1_method));
+ this->ph1_method->get_identifier(this->ph1_method));
return NEED_MORE;
}
return status;
@@ -360,7 +361,7 @@ METHOD(tls_application_t, build, status_t,
this->ph2_method->initiate(this->ph2_method, &this->out);
this->start_phase2 = FALSE;
}
-
+
this->start_phase2_id = TRUE;
if (this->out)
@@ -423,7 +424,8 @@ eap_peap_server_t *eap_peap_server_create(identification_t *server,
.start_phase2 = TRUE,
.start_phase2_tnc = TRUE,
.start_phase2_id = lib->settings->get_bool(lib->settings,
- "charon.plugins.eap-peap.phase2_piggyback", FALSE),
+ "%s.plugins.eap-peap.phase2_piggyback",
+ FALSE, charon->name),
.phase2_result = EAP_FAILURE,
.avp = eap_peap_avp_create(TRUE),
);
diff --git a/src/libcharon/plugins/eap_peap/eap_peap_server.h b/src/libcharon/plugins/eap_peap/eap_peap_server.h
index 93141d62b..4585a622a 100644
--- a/src/libcharon/plugins/eap_peap/eap_peap_server.h
+++ b/src/libcharon/plugins/eap_peap/eap_peap_server.h
@@ -26,7 +26,7 @@ typedef struct eap_peap_server_t eap_peap_server_t;
#include "tls_application.h"
#include <library.h>
-#include <sa/authenticators/eap/eap_method.h>
+#include <sa/eap/eap_method.h>
/**
* TLS application data handler as server.
diff --git a/src/libcharon/plugins/eap_radius/Makefile.in b/src/libcharon/plugins/eap_radius/Makefile.in
index 0bef44042..1bdf24c2c 100644
--- a/src/libcharon/plugins/eap_radius/Makefile.in
+++ b/src/libcharon/plugins/eap_radius/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -88,7 +89,7 @@ libstrongswan_eap_radius_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_eap_radius_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_eap_radius_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -114,6 +115,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -208,11 +210,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -229,11 +234,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -249,6 +255,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -258,7 +265,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/eap_radius/eap_radius.c b/src/libcharon/plugins/eap_radius/eap_radius.c
index c0a3703b6..870ed1fc0 100644
--- a/src/libcharon/plugins/eap_radius/eap_radius.c
+++ b/src/libcharon/plugins/eap_radius/eap_radius.c
@@ -264,7 +264,7 @@ static void process_filter_id(private_eap_radius_t *this, radius_message_t *msg)
case RAT_FILTER_ID:
filter_id = data;
DBG1(DBG_IKE, "received RADIUS attribute Filter-Id: "
- "'%.*s'", filter_id.len, filter_id.ptr);
+ "'%.*s'", (int)filter_id.len, filter_id.ptr);
break;
default:
break;
@@ -453,14 +453,17 @@ eap_radius_t *eap_radius_create(identification_t *server, identification_t *peer
/* initially EAP_RADIUS, but is set to the method selected by RADIUS */
.type = EAP_RADIUS,
.eap_start = lib->settings->get_bool(lib->settings,
- "charon.plugins.eap-radius.eap_start", FALSE),
+ "%s.plugins.eap-radius.eap_start", FALSE,
+ charon->name),
.id_prefix = lib->settings->get_str(lib->settings,
- "charon.plugins.eap-radius.id_prefix", ""),
+ "%s.plugins.eap-radius.id_prefix", "",
+ charon->name),
.class_group = lib->settings->get_bool(lib->settings,
- "charon.plugins.eap-radius.class_group", FALSE),
+ "%s.plugins.eap-radius.class_group", FALSE,
+ charon->name),
.filter_id = lib->settings->get_bool(lib->settings,
- "charon.plugins.eap-radius.filter_id", FALSE),
-
+ "%s.plugins.eap-radius.filter_id", FALSE,
+ charon->name),
);
this->client = eap_radius_create_client();
if (!this->client)
diff --git a/src/libcharon/plugins/eap_radius/eap_radius.h b/src/libcharon/plugins/eap_radius/eap_radius.h
index e98cb06e3..875543554 100644
--- a/src/libcharon/plugins/eap_radius/eap_radius.h
+++ b/src/libcharon/plugins/eap_radius/eap_radius.h
@@ -23,7 +23,7 @@
typedef struct eap_radius_t eap_radius_t;
-#include <sa/authenticators/eap/eap_method.h>
+#include <sa/eap/eap_method.h>
/**
* Implementation of the eap_method_t interface using a RADIUS server.
diff --git a/src/libcharon/plugins/eap_radius/eap_radius_accounting.c b/src/libcharon/plugins/eap_radius/eap_radius_accounting.c
index 45be22704..f164f67ed 100644
--- a/src/libcharon/plugins/eap_radius/eap_radius_accounting.c
+++ b/src/libcharon/plugins/eap_radius/eap_radius_accounting.c
@@ -149,6 +149,7 @@ static bool send_message(private_eap_radius_accounting_t *this,
*/
static void add_ike_sa_parameters(radius_message_t *message, ike_sa_t *ike_sa)
{
+ enumerator_t *enumerator;
host_t *vip;
char buf[64];
chunk_t data;
@@ -157,18 +158,27 @@ static void add_ike_sa_parameters(radius_message_t *message, ike_sa_t *ike_sa)
message->add(message, RAT_USER_NAME, chunk_create(buf, strlen(buf)));
snprintf(buf, sizeof(buf), "%#H", ike_sa->get_other_host(ike_sa));
message->add(message, RAT_CALLING_STATION_ID, chunk_create(buf, strlen(buf)));
- vip = ike_sa->get_virtual_ip(ike_sa, FALSE);
- if (vip && vip->get_family(vip) == AF_INET)
- {
- message->add(message, RAT_FRAMED_IP_ADDRESS, vip->get_address(vip));
- }
- if (vip && vip->get_family(vip) == AF_INET6)
+
+ enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, FALSE);
+ while (enumerator->enumerate(enumerator, &vip))
{
- /* 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);
+ switch (vip->get_family(vip))
+ {
+ case AF_INET:
+ message->add(message, RAT_FRAMED_IP_ADDRESS,
+ 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);
+ break;
+ default:
+ break;
+ }
}
+ enumerator->destroy(enumerator);
}
/**
@@ -197,9 +207,9 @@ static void send_start(private_eap_radius_accounting_t *this, ike_sa_t *ike_sa)
this->mutex->lock(this->mutex);
entry = this->sessions->put(this->sessions, (void*)(uintptr_t)id, entry);
this->mutex->unlock(this->mutex);
- free(entry);
}
message->destroy(message);
+ free(entry);
}
/**
@@ -271,14 +281,22 @@ METHOD(listener_t, ike_updown, bool,
METHOD(listener_t, message_hook, bool,
private_eap_radius_accounting_t *this, ike_sa_t *ike_sa,
- message_t *message, bool incoming)
+ message_t *message, bool incoming, bool plain)
{
/* start accounting here, virtual IP now is set */
- if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
- message->get_exchange_type(message) == IKE_AUTH &&
+ if (plain && ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
!incoming && !message->get_request(message))
{
- send_start(this, ike_sa);
+ 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)
+ {
+ send_start(this, ike_sa);
+ }
}
return TRUE;
}
diff --git a/src/libcharon/plugins/eap_radius/eap_radius_dae.c b/src/libcharon/plugins/eap_radius/eap_radius_dae.c
index e84fe5b9c..2ea2b059c 100644
--- a/src/libcharon/plugins/eap_radius/eap_radius_dae.c
+++ b/src/libcharon/plugins/eap_radius/eap_radius_dae.c
@@ -53,11 +53,6 @@ struct private_eap_radius_dae_t {
int fd;
/**
- * Listen job
- */
- callback_job_t *job;
-
- /**
* RADIUS shared secret for DAE exchanges
*/
chunk_t secret;
@@ -189,11 +184,16 @@ static void send_response(private_eap_radius_dae_t *this,
response = radius_message_create(code);
response->set_identifier(response, request->get_identifier(request));
- response->sign(response, request->get_authenticator(request),
- this->secret, this->hasher, this->signer, NULL, FALSE);
-
- send_message(this, response, client);
- save_retransmit(this, response, client);
+ if (response->sign(response, request->get_authenticator(request),
+ this->secret, this->hasher, this->signer, NULL, FALSE))
+ {
+ send_message(this, response, client);
+ save_retransmit(this, response, client);
+ }
+ else
+ {
+ response->destroy(response);
+ }
}
/**
@@ -456,9 +456,11 @@ static bool open_socket(private_eap_radius_dae_t *this)
host = host_create_from_string(
lib->settings->get_str(lib->settings,
- "charon.plugins.eap-radius.dae.listen", "0.0.0.0"),
+ "%s.plugins.eap-radius.dae.listen", "0.0.0.0",
+ charon->name),
lib->settings->get_int(lib->settings,
- "charon.plugins.eap-radius.dae.port", RADIUS_DAE_PORT));
+ "%s.plugins.eap-radius.dae.port", RADIUS_DAE_PORT,
+ charon->name));
if (!host)
{
DBG1(DBG_CFG, "invalid RADIUS DAE listen address");
@@ -479,10 +481,6 @@ static bool open_socket(private_eap_radius_dae_t *this)
METHOD(eap_radius_dae_t, destroy, void,
private_eap_radius_dae_t *this)
{
- if (this->job)
- {
- this->job->cancel(this->job);
- }
if (this->fd != -1)
{
close(this->fd);
@@ -508,7 +506,8 @@ eap_radius_dae_t *eap_radius_dae_create(eap_radius_accounting_t *accounting)
.fd = -1,
.secret = {
.ptr = lib->settings->get_str(lib->settings,
- "charon.plugins.eap-radius.dae.secret", NULL),
+ "%s.plugins.eap-radius.dae.secret", NULL,
+ charon->name),
},
.hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5),
.signer = lib->crypto->create_signer(lib->crypto, AUTH_HMAC_MD5_128),
@@ -527,17 +526,16 @@ eap_radius_dae_t *eap_radius_dae_create(eap_radius_accounting_t *accounting)
return NULL;
}
this->secret.len = strlen(this->secret.ptr);
- this->signer->set_key(this->signer, this->secret);
-
- if (!open_socket(this))
+ if (!this->signer->set_key(this->signer, this->secret) ||
+ !open_socket(this))
{
destroy(this);
return NULL;
}
- this->job = callback_job_create_with_prio((callback_job_cb_t)receive,
- this, NULL, NULL, JOB_PRIO_CRITICAL);
- lib->processor->queue_job(lib->processor, (job_t*)this->job);
+ lib->processor->queue_job(lib->processor,
+ (job_t*)callback_job_create_with_prio((callback_job_cb_t)receive,
+ this, NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
return &this->public;
}
diff --git a/src/libcharon/plugins/eap_radius/eap_radius_forward.c b/src/libcharon/plugins/eap_radius/eap_radius_forward.c
index cb4ca74e3..2dd38ea2f 100644
--- a/src/libcharon/plugins/eap_radius/eap_radius_forward.c
+++ b/src/libcharon/plugins/eap_radius/eap_radius_forward.c
@@ -319,11 +319,11 @@ void eap_radius_forward_to_ike(radius_message_t *response)
METHOD(listener_t, message, bool,
private_eap_radius_forward_t *this,
- ike_sa_t *ike_sa, message_t *message, bool incoming)
+ ike_sa_t *ike_sa, message_t *message, bool incoming, bool plain)
{
linked_list_t *queue;
- if (message->get_exchange_type(message) == IKE_AUTH)
+ if (plain && message->get_exchange_type(message) == IKE_AUTH)
{
if (incoming)
{
@@ -436,9 +436,11 @@ eap_radius_forward_t *eap_radius_forward_create()
.destroy = _destroy,
},
.from_attr = parse_selector(lib->settings->get_str(lib->settings,
- "charon.plugins.eap-radius.forward.ike_to_radius", "")),
+ "%s.plugins.eap-radius.forward.ike_to_radius", "",
+ charon->name)),
.to_attr = parse_selector(lib->settings->get_str(lib->settings,
- "charon.plugins.eap-radius.forward.radius_to_ike", "")),
+ "%s.plugins.eap-radius.forward.radius_to_ike", "",
+ charon->name)),
.from = hashtable_create((hashtable_hash_t)hash,
(hashtable_equals_t)equals, 8),
.to = hashtable_create((hashtable_hash_t)hash,
diff --git a/src/libcharon/plugins/eap_radius/eap_radius_plugin.c b/src/libcharon/plugins/eap_radius/eap_radius_plugin.c
index 8ee0ab81a..9d4bbe1f3 100644
--- a/src/libcharon/plugins/eap_radius/eap_radius_plugin.c
+++ b/src/libcharon/plugins/eap_radius/eap_radius_plugin.c
@@ -90,22 +90,23 @@ static void load_configs(private_eap_radius_plugin_t *this)
int auth_port, acct_port, sockets, preference;
address = lib->settings->get_str(lib->settings,
- "charon.plugins.eap-radius.server", NULL);
+ "%s.plugins.eap-radius.server", NULL, charon->name);
if (address)
{ /* legacy configuration */
secret = lib->settings->get_str(lib->settings,
- "charon.plugins.eap-radius.secret", NULL);
+ "%s.plugins.eap-radius.secret", NULL, charon->name);
if (!secret)
{
DBG1(DBG_CFG, "no RADUIS secret defined");
return;
}
nas_identifier = lib->settings->get_str(lib->settings,
- "charon.plugins.eap-radius.nas_identifier", "strongSwan");
+ "%s.plugins.eap-radius.nas_identifier", "strongSwan",
+ charon->name);
auth_port = lib->settings->get_int(lib->settings,
- "charon.plugins.eap-radius.port", AUTH_PORT);
+ "%s.plugins.eap-radius.port", AUTH_PORT, charon->name);
sockets = lib->settings->get_int(lib->settings,
- "charon.plugins.eap-radius.sockets", 1);
+ "%s.plugins.eap-radius.sockets", 1, charon->name);
config = radius_config_create(address, address, auth_port, ACCT_PORT,
nas_identifier, secret, sockets, 0);
if (!config)
@@ -118,38 +119,43 @@ static void load_configs(private_eap_radius_plugin_t *this)
}
enumerator = lib->settings->create_section_enumerator(lib->settings,
- "charon.plugins.eap-radius.servers");
+ "%s.plugins.eap-radius.servers", charon->name);
while (enumerator->enumerate(enumerator, &section))
{
address = lib->settings->get_str(lib->settings,
- "charon.plugins.eap-radius.servers.%s.address", NULL, section);
+ "%s.plugins.eap-radius.servers.%s.address", NULL,
+ charon->name, section);
if (!address)
{
DBG1(DBG_CFG, "RADIUS server '%s' misses address, skipped", section);
continue;
}
secret = lib->settings->get_str(lib->settings,
- "charon.plugins.eap-radius.servers.%s.secret", NULL, section);
+ "%s.plugins.eap-radius.servers.%s.secret", NULL,
+ charon->name, section);
if (!secret)
{
DBG1(DBG_CFG, "RADIUS server '%s' misses secret, skipped", section);
continue;
}
nas_identifier = lib->settings->get_str(lib->settings,
- "charon.plugins.eap-radius.servers.%s.nas_identifier",
- "strongSwan", section);
+ "%s.plugins.eap-radius.servers.%s.nas_identifier", "strongSwan",
+ charon->name, section);
auth_port = lib->settings->get_int(lib->settings,
- "charon.plugins.eap-radius.servers.%s.auth_port",
+ "%s.plugins.eap-radius.servers.%s.auth_port",
lib->settings->get_int(lib->settings,
- "charon.plugins.eap-radius.servers.%s.port",
- AUTH_PORT, section),
- section);
+ "%s.plugins.eap-radius.servers.%s.port",
+ AUTH_PORT, charon->name, section),
+ charon->name, section);
acct_port = lib->settings->get_int(lib->settings,
- "charon.plugins.eap-radius.servers.%s.acct_port", ACCT_PORT, section);
+ "%s.plugins.eap-radius.servers.%s.acct_port", ACCT_PORT,
+ charon->name, section);
sockets = lib->settings->get_int(lib->settings,
- "charon.plugins.eap-radius.servers.%s.sockets", 1, section);
+ "%s.plugins.eap-radius.servers.%s.sockets", 1,
+ charon->name, section);
preference = lib->settings->get_int(lib->settings,
- "charon.plugins.eap-radius.servers.%s.preference", 0, section);
+ "%s.plugins.eap-radius.servers.%s.preference", 0,
+ charon->name, section);
config = radius_config_create(section, address, auth_port, acct_port,
nas_identifier, secret, sockets, preference);
if (!config)
@@ -242,12 +248,12 @@ plugin_t *eap_radius_plugin_create()
instance = this;
if (lib->settings->get_bool(lib->settings,
- "charon.plugins.eap-radius.accounting", FALSE))
+ "%s.plugins.eap-radius.accounting", FALSE, charon->name))
{
charon->bus->add_listener(charon->bus, &this->accounting->listener);
}
if (lib->settings->get_bool(lib->settings,
- "charon.plugins.eap-radius.dae.enable", FALSE))
+ "%s.plugins.eap-radius.dae.enable", FALSE, charon->name))
{
this->dae = eap_radius_dae_create(this->accounting);
}
diff --git a/src/libcharon/plugins/eap_sim/Makefile.in b/src/libcharon/plugins/eap_sim/Makefile.in
index d06929522..99a5c1cc5 100644
--- a/src/libcharon/plugins/eap_sim/Makefile.in
+++ b/src/libcharon/plugins/eap_sim/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -86,7 +87,7 @@ libstrongswan_eap_sim_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@MONOLITHIC_FALSE@am_libstrongswan_eap_sim_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_eap_sim_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -112,6 +113,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -206,11 +208,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -227,11 +232,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -247,6 +253,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -256,7 +263,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/eap_sim/eap_sim_peer.c b/src/libcharon/plugins/eap_sim/eap_sim_peer.c
index 1d1ab99e0..ff96e9279 100644
--- a/src/libcharon/plugins/eap_sim/eap_sim_peer.c
+++ b/src/libcharon/plugins/eap_sim/eap_sim_peer.c
@@ -106,13 +106,30 @@ struct private_eap_sim_peer_t {
static chunk_t version = chunk_from_chars(0x00,0x01);
/**
+ * Generate a payload from a message, destroy message
+ */
+static bool generate_payload(simaka_message_t *message, chunk_t data,
+ eap_payload_t **out)
+{
+ chunk_t chunk;
+ bool ok;
+
+ ok = message->generate(message, data, &chunk);
+ if (ok)
+ {
+ *out = eap_payload_create_data_own(chunk);
+ }
+ message->destroy(message);
+ return ok;
+}
+
+/**
* Create a SIM_CLIENT_ERROR
*/
-static eap_payload_t* create_client_error(private_eap_sim_peer_t *this,
- simaka_client_error_t code)
+static bool create_client_error(private_eap_sim_peer_t *this,
+ simaka_client_error_t code, eap_payload_t **out)
{
simaka_message_t *message;
- eap_payload_t *out;
u_int16_t encoded;
DBG1(DBG_IKE, "sending client error '%N'", simaka_client_error_names, code);
@@ -122,9 +139,7 @@ static eap_payload_t* create_client_error(private_eap_sim_peer_t *this,
encoded = htons(code);
message->add_attribute(message, AT_CLIENT_ERROR_CODE,
chunk_create((char*)&encoded, sizeof(encoded)));
- out = eap_payload_create_data_own(message->generate(message, chunk_empty));
- message->destroy(message);
- return out;
+ return generate_payload(message, chunk_empty, out);
}
/**
@@ -175,8 +190,11 @@ static status_t process_start(private_eap_sim_peer_t *this,
default:
if (!simaka_attribute_skippable(type))
{
- *out = create_client_error(this, SIM_UNABLE_TO_PROCESS);
enumerator->destroy(enumerator);
+ if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
+ {
+ return FAILED;
+ }
return NEED_MORE;
}
break;
@@ -187,7 +205,10 @@ static status_t process_start(private_eap_sim_peer_t *this,
if (!supported)
{
DBG1(DBG_IKE, "server does not support EAP-SIM version number 1");
- *out = create_client_error(this, SIM_UNSUPPORTED_VERSION);
+ if (!create_client_error(this, SIM_UNSUPPORTED_VERSION, out))
+ {
+ return FAILED;
+ }
return NEED_MORE;
}
@@ -221,7 +242,10 @@ static status_t process_start(private_eap_sim_peer_t *this,
/* generate AT_NONCE_MT value */
rng = this->crypto->get_rng(this->crypto);
free(this->nonce.ptr);
- rng->allocate_bytes(rng, NONCE_LEN, &this->nonce);
+ if (!rng->allocate_bytes(rng, NONCE_LEN, &this->nonce))
+ {
+ return FAILED;
+ }
message = simaka_message_create(FALSE, this->identifier, EAP_SIM,
SIM_START, this->crypto);
@@ -234,9 +258,10 @@ static status_t process_start(private_eap_sim_peer_t *this,
{
message->add_attribute(message, AT_IDENTITY, id);
}
- *out = eap_payload_create_data_own(message->generate(message, chunk_empty));
- message->destroy(message);
-
+ if (!generate_payload(message, chunk_empty, out))
+ {
+ return FAILED;
+ }
return NEED_MORE;
}
@@ -270,8 +295,11 @@ static status_t process_challenge(private_eap_sim_peer_t *this,
default:
if (!simaka_attribute_skippable(type))
{
- *out = create_client_error(this, SIM_UNABLE_TO_PROCESS);
enumerator->destroy(enumerator);
+ if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
+ {
+ return FAILED;
+ }
return NEED_MORE;
}
break;
@@ -285,7 +313,10 @@ static status_t process_challenge(private_eap_sim_peer_t *this,
memeq(rands.ptr, rands.ptr + SIM_RAND_LEN, SIM_RAND_LEN))
{
DBG1(DBG_IKE, "no valid AT_RAND received");
- *out = create_client_error(this, SIM_INSUFFICIENT_CHALLENGES);
+ if (!create_client_error(this, SIM_INSUFFICIENT_CHALLENGES, out))
+ {
+ return FAILED;
+ }
return NEED_MORE;
}
/* get two or three KCs/SRESes from SIM using RANDs */
@@ -297,7 +328,10 @@ static status_t process_challenge(private_eap_sim_peer_t *this,
rands.ptr, sres.ptr, kc.ptr))
{
DBG1(DBG_IKE, "unable to get EAP-SIM triplet");
- *out = create_client_error(this, SIM_UNABLE_TO_PROCESS);
+ if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
+ {
+ return FAILED;
+ }
return NEED_MORE;
}
DBG3(DBG_IKE, "got triplet for RAND %b\n Kc %b\n SRES %b",
@@ -313,16 +347,22 @@ static status_t process_challenge(private_eap_sim_peer_t *this,
id = this->pseudonym;
}
data = chunk_cata("cccc", kcs, this->nonce, this->version_list, version);
- free(this->msk.ptr);
- this->msk = this->crypto->derive_keys_full(this->crypto, id, data, &mk);
+ chunk_clear(&this->msk);
+ if (!this->crypto->derive_keys_full(this->crypto, id, data, &mk, &this->msk))
+ {
+ return FAILED;
+ }
memcpy(this->mk, mk.ptr, mk.len);
- free(mk.ptr);
+ chunk_clear(&mk);
/* Verify AT_MAC attribute, signature is over "EAP packet | NONCE_MT", and
* parse() again after key derivation, reading encrypted attributes */
if (!in->verify(in, this->nonce) || !in->parse(in))
{
- *out = create_client_error(this, SIM_UNABLE_TO_PROCESS);
+ if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
+ {
+ return FAILED;
+ }
return NEED_MORE;
}
@@ -352,8 +392,10 @@ static status_t process_challenge(private_eap_sim_peer_t *this,
/* build response with AT_MAC, built over "EAP packet | n*SRES" */
message = simaka_message_create(FALSE, this->identifier, EAP_SIM,
SIM_CHALLENGE, this->crypto);
- *out = eap_payload_create_data_own(message->generate(message, sreses));
- message->destroy(message);
+ if (!generate_payload(message, sreses, out))
+ {
+ return FAILED;
+ }
return NEED_MORE;
}
@@ -384,17 +426,26 @@ static status_t process_reauthentication(private_eap_sim_peer_t *this,
{
DBG1(DBG_IKE, "received %N, but not expected",
simaka_subtype_names, SIM_REAUTHENTICATION);
- *out = create_client_error(this, SIM_UNABLE_TO_PROCESS);
+ if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
+ {
+ return FAILED;
+ }
return NEED_MORE;
}
- this->crypto->derive_keys_reauth(this->crypto,
- chunk_create(this->mk, HASH_SIZE_SHA1));
+ if (!this->crypto->derive_keys_reauth(this->crypto,
+ chunk_create(this->mk, HASH_SIZE_SHA1)))
+ {
+ return FAILED;
+ }
/* verify MAC and parse again with decryption key */
if (!in->verify(in, chunk_empty) || !in->parse(in))
{
- *out = create_client_error(this, SIM_UNABLE_TO_PROCESS);
+ if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
+ {
+ return FAILED;
+ }
return NEED_MORE;
}
@@ -415,8 +466,11 @@ static status_t process_reauthentication(private_eap_sim_peer_t *this,
default:
if (!simaka_attribute_skippable(type))
{
- *out = create_client_error(this, SIM_UNABLE_TO_PROCESS);
enumerator->destroy(enumerator);
+ if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
+ {
+ return FAILED;
+ }
return NEED_MORE;
}
break;
@@ -427,7 +481,10 @@ static status_t process_reauthentication(private_eap_sim_peer_t *this,
if (!nonce.len || !counter.len)
{
DBG1(DBG_IKE, "EAP-SIM/Request/Re-Authentication message incomplete");
- *out = create_client_error(this, SIM_UNABLE_TO_PROCESS);
+ if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
+ {
+ return FAILED;
+ }
return NEED_MORE;
}
@@ -440,10 +497,14 @@ static status_t process_reauthentication(private_eap_sim_peer_t *this,
}
else
{
- free(this->msk.ptr);
- this->msk = this->crypto->derive_keys_reauth_msk(this->crypto,
- this->reauth, counter, nonce,
- chunk_create(this->mk, HASH_SIZE_SHA1));
+ chunk_clear(&this->msk);
+ if (!this->crypto->derive_keys_reauth_msk(this->crypto,
+ this->reauth, counter, nonce,
+ chunk_create(this->mk, HASH_SIZE_SHA1), &this->msk))
+ {
+ message->destroy(message);
+ return FAILED;
+ }
if (id.len)
{
identification_t *reauth;
@@ -455,8 +516,10 @@ static status_t process_reauthentication(private_eap_sim_peer_t *this,
}
}
message->add_attribute(message, AT_COUNTER, counter);
- *out = eap_payload_create_data_own(message->generate(message, nonce));
- message->destroy(message);
+ if (!generate_payload(message, nonce, out))
+ {
+ return FAILED;
+ }
return NEED_MORE;
}
@@ -506,13 +569,17 @@ static status_t process_notification(private_eap_sim_peer_t *this,
{ /* empty notification reply */
message = simaka_message_create(FALSE, this->identifier, EAP_SIM,
SIM_NOTIFICATION, this->crypto);
- *out = eap_payload_create_data_own(message->generate(message,
- chunk_empty));
- message->destroy(message);
+ if (!generate_payload(message, chunk_empty, out))
+ {
+ return FAILED;
+ }
}
else
{
- *out = create_client_error(this, SIM_UNABLE_TO_PROCESS);
+ if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
+ {
+ return FAILED;
+ }
}
return NEED_MORE;
}
@@ -529,13 +596,19 @@ METHOD(eap_method_t, process, status_t,
message = simaka_message_create_from_payload(in->get_data(in), this->crypto);
if (!message)
{
- *out = create_client_error(this, SIM_UNABLE_TO_PROCESS);
+ if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
+ {
+ return FAILED;
+ }
return NEED_MORE;
}
if (!message->parse(message))
{
message->destroy(message);
- *out = create_client_error(this, SIM_UNABLE_TO_PROCESS);
+ if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
+ {
+ return FAILED;
+ }
return NEED_MORE;
}
switch (message->get_subtype(message))
@@ -555,8 +628,14 @@ METHOD(eap_method_t, process, status_t,
default:
DBG1(DBG_IKE, "unable to process EAP-SIM subtype %N",
simaka_subtype_names, message->get_subtype(message));
- *out = create_client_error(this, SIM_UNABLE_TO_PROCESS);
- status = NEED_MORE;
+ if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
+ {
+ status = FAILED;
+ }
+ else
+ {
+ status = NEED_MORE;
+ }
break;
}
message->destroy(message);
diff --git a/src/libcharon/plugins/eap_sim/eap_sim_peer.h b/src/libcharon/plugins/eap_sim/eap_sim_peer.h
index ba72ce484..38315b75a 100644
--- a/src/libcharon/plugins/eap_sim/eap_sim_peer.h
+++ b/src/libcharon/plugins/eap_sim/eap_sim_peer.h
@@ -21,7 +21,7 @@
#ifndef EAP_SIM_PEER_H_
#define EAP_SIM_PEER_H_
-#include <sa/authenticators/eap/eap_method.h>
+#include <sa/eap/eap_method.h>
typedef struct eap_sim_peer_t eap_sim_peer_t;
diff --git a/src/libcharon/plugins/eap_sim/eap_sim_server.c b/src/libcharon/plugins/eap_sim/eap_sim_server.c
index e0f7e92ad..334e2df1d 100644
--- a/src/libcharon/plugins/eap_sim/eap_sim_server.c
+++ b/src/libcharon/plugins/eap_sim/eap_sim_server.c
@@ -113,6 +113,24 @@ struct private_eap_sim_server_t {
/* version of SIM protocol we speak */
static chunk_t version = chunk_from_chars(0x00,0x01);
+/**
+ * Generate a payload from a message, destroy message
+ */
+static bool generate_payload(simaka_message_t *message, chunk_t data,
+ eap_payload_t **out)
+{
+ chunk_t chunk;
+ bool ok;
+
+ ok = message->generate(message, data, &chunk);
+ if (ok)
+ {
+ *out = eap_payload_create_data_own(chunk);
+ }
+ message->destroy(message);
+ return ok;
+}
+
METHOD(eap_method_t, initiate, status_t,
private_eap_sim_server_t *this, eap_payload_t **out)
{
@@ -133,9 +151,10 @@ METHOD(eap_method_t, initiate, status_t,
{
message->add_attribute(message, AT_PERMANENT_ID_REQ, chunk_empty);
}
- *out = eap_payload_create_data_own(message->generate(message, chunk_empty));
- message->destroy(message);
-
+ if (!generate_payload(message, chunk_empty, out))
+ {
+ return FAILED;
+ }
this->pending = SIM_START;
return NEED_MORE;
}
@@ -155,15 +174,21 @@ static status_t reauthenticate(private_eap_sim_server_t *this,
DBG1(DBG_IKE, "initiating EAP-SIM reauthentication");
rng = this->crypto->get_rng(this->crypto);
- rng->allocate_bytes(rng, NONCE_LEN, &this->nonce);
+ if (!rng->allocate_bytes(rng, NONCE_LEN, &this->nonce))
+ {
+ return FAILED;
+ }
mkc = chunk_create(mk, HASH_SIZE_SHA1);
counter = htons(counter);
this->counter = chunk_clone(chunk_create((char*)&counter, sizeof(counter)));
- this->crypto->derive_keys_reauth(this->crypto, mkc);
- this->msk = this->crypto->derive_keys_reauth_msk(this->crypto,
- this->reauth, this->counter, this->nonce, mkc);
+ if (!this->crypto->derive_keys_reauth(this->crypto, mkc) ||
+ !this->crypto->derive_keys_reauth_msk(this->crypto,
+ this->reauth, this->counter, this->nonce, mkc, &this->msk))
+ {
+ return FAILED;
+ }
message = simaka_message_create(TRUE, this->identifier++, EAP_SIM,
SIM_REAUTHENTICATION, this->crypto);
@@ -176,9 +201,10 @@ static status_t reauthenticate(private_eap_sim_server_t *this,
next->get_encoding(next));
next->destroy(next);
}
- *out = eap_payload_create_data_own(message->generate(message, chunk_empty));
- message->destroy(message);
-
+ if (!generate_payload(message, chunk_empty, out))
+ {
+ return FAILED;
+ }
this->pending = SIM_REAUTHENTICATION;
return NEED_MORE;
}
@@ -386,13 +412,17 @@ static status_t process_start(private_eap_sim_server_t *this,
{
id = this->pseudonym;
}
- this->msk = this->crypto->derive_keys_full(this->crypto, id, data, &mk);
+ if (!this->crypto->derive_keys_full(this->crypto, id, data, &mk, &this->msk))
+ {
+ return FAILED;
+ }
/* build response with AT_MAC, built over "EAP packet | NONCE_MT" */
message = simaka_message_create(TRUE, this->identifier++, EAP_SIM,
SIM_CHALLENGE, this->crypto);
message->add_attribute(message, AT_RAND, rands);
id = this->mgr->provider_gen_reauth(this->mgr, this->permanent, mk.ptr);
+ free(mk.ptr);
if (id)
{
message->add_attribute(message, AT_NEXT_REAUTH_ID,
@@ -406,10 +436,10 @@ static status_t process_start(private_eap_sim_server_t *this,
id->get_encoding(id));
id->destroy(id);
}
- *out = eap_payload_create_data_own(message->generate(message, nonce));
- message->destroy(message);
-
- free(mk.ptr);
+ if (!generate_payload(message, nonce, out))
+ {
+ return FAILED;
+ }
this->pending = SIM_CHALLENGE;
return NEED_MORE;
}
@@ -604,7 +634,8 @@ eap_sim_server_t *eap_sim_server_create(identification_t *server,
this->permanent = peer->clone(peer);
this->use_reauth = this->use_pseudonym = this->use_permanent =
lib->settings->get_bool(lib->settings,
- "charon.plugins.eap-sim.request_identity", TRUE);
+ "%s.plugins.eap-sim.request_identity", TRUE,
+ charon->name);
/* generate a non-zero identifier */
do {
diff --git a/src/libcharon/plugins/eap_sim/eap_sim_server.h b/src/libcharon/plugins/eap_sim/eap_sim_server.h
index c0ed64ff2..84408c43c 100644
--- a/src/libcharon/plugins/eap_sim/eap_sim_server.h
+++ b/src/libcharon/plugins/eap_sim/eap_sim_server.h
@@ -21,7 +21,7 @@
#ifndef EAP_SIM_SERVER_H_
#define EAP_SIM_SERVER_H_
-#include <sa/authenticators/eap/eap_method.h>
+#include <sa/eap/eap_method.h>
typedef struct eap_sim_server_t eap_sim_server_t;
diff --git a/src/libcharon/plugins/eap_sim_file/Makefile.in b/src/libcharon/plugins/eap_sim_file/Makefile.in
index bebf62e5b..d1caa30c4 100644
--- a/src/libcharon/plugins/eap_sim_file/Makefile.in
+++ b/src/libcharon/plugins/eap_sim_file/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -88,7 +89,7 @@ libstrongswan_eap_sim_file_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_eap_sim_file_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_eap_sim_file_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -114,6 +115,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -208,11 +210,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -229,11 +234,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -249,6 +255,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -258,7 +265,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/eap_sim_pcsc/Makefile.in b/src/libcharon/plugins/eap_sim_pcsc/Makefile.in
index 5c05b2bf1..83d931883 100644
--- a/src/libcharon/plugins/eap_sim_pcsc/Makefile.in
+++ b/src/libcharon/plugins/eap_sim_pcsc/Makefile.in
@@ -50,6 +50,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -89,7 +90,7 @@ libstrongswan_eap_sim_pcsc_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_eap_sim_pcsc_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_eap_sim_pcsc_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -115,6 +116,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -209,11 +211,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -230,11 +235,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -250,6 +256,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -259,7 +266,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in
index 0d7c32c14..e8436f2b6 100644
--- a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in
+++ b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -89,7 +90,7 @@ libstrongswan_eap_simaka_pseudonym_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_eap_simaka_pseudonym_la_rpath = \
@MONOLITHIC_FALSE@ -rpath $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_eap_simaka_pseudonym_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -115,6 +116,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -209,11 +211,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -230,11 +235,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -250,6 +256,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -259,7 +266,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_provider.c b/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_provider.c
index 49c3ad328..3070b808a 100644
--- a/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_provider.c
+++ b/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_provider.c
@@ -15,6 +15,7 @@
#include "eap_simaka_pseudonym_provider.h"
+#include <debug.h>
#include <utils/hashtable.h>
typedef struct private_eap_simaka_pseudonym_provider_t private_eap_simaka_pseudonym_provider_t;
@@ -82,7 +83,10 @@ static identification_t *gen_identity(
{
char buf[8], hex[sizeof(buf) * 2 + 1];
- this->rng->get_bytes(this->rng, sizeof(buf), buf);
+ if (!this->rng->get_bytes(this->rng, sizeof(buf), buf))
+ {
+ return NULL;
+ }
chunk_to_hex(chunk_create(buf, sizeof(buf)), hex, FALSE);
return identification_create_from_string(hex);
@@ -106,6 +110,11 @@ METHOD(simaka_provider_t, gen_pseudonym, identification_t*,
}
pseudonym = gen_identity(this);
+ if (!pseudonym)
+ {
+ DBG1(DBG_CFG, "failed to generate pseudonym");
+ return NULL;
+ }
/* create new entries */
id = id->clone(id);
diff --git a/src/libcharon/plugins/eap_simaka_reauth/Makefile.in b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in
index 6177f3b3a..627f8c12e 100644
--- a/src/libcharon/plugins/eap_simaka_reauth/Makefile.in
+++ b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -88,7 +89,7 @@ libstrongswan_eap_simaka_reauth_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_eap_simaka_reauth_la_rpath = \
@MONOLITHIC_FALSE@ -rpath $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_eap_simaka_reauth_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -114,6 +115,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -208,11 +210,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -229,11 +234,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -249,6 +255,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -258,7 +265,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_provider.c b/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_provider.c
index ba1a32778..b1a9a7f7c 100644
--- a/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_provider.c
+++ b/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_provider.c
@@ -81,7 +81,10 @@ static identification_t *gen_identity(private_eap_simaka_reauth_provider_t *this
{
char buf[8], hex[sizeof(buf) * 2 + 1];
- this->rng->get_bytes(this->rng, sizeof(buf), buf);
+ if (!this->rng->get_bytes(this->rng, sizeof(buf), buf))
+ {
+ return NULL;
+ }
chunk_to_hex(chunk_create(buf, sizeof(buf)), hex, FALSE);
return identification_create_from_string(hex);
@@ -116,7 +119,14 @@ METHOD(simaka_provider_t, gen_reauth, identification_t*,
char mk[HASH_SIZE_SHA1])
{
reauth_data_t *data;
- identification_t *permanent;
+ identification_t *permanent, *new_id;
+
+ new_id = gen_identity(this);
+ if (!new_id)
+ {
+ DBG1(DBG_CFG, "failed to generate identity");
+ return NULL;
+ }
data = this->reauth->get(this->reauth, id);
if (data)
@@ -125,14 +135,18 @@ METHOD(simaka_provider_t, gen_reauth, identification_t*,
if (permanent)
{
data->id->destroy(data->id);
- data->id = gen_identity(this);
+ data->id = new_id;
this->permanent->put(this->permanent, data->id, permanent);
}
+ else
+ {
+ new_id->destroy(new_id);
+ }
}
else
{ /* generate new entry */
INIT(data,
- .id = gen_identity(this),
+ .id = new_id,
);
id = id->clone(id);
this->reauth->put(this->reauth, id, data);
diff --git a/src/libcharon/plugins/eap_simaka_sql/Makefile.in b/src/libcharon/plugins/eap_simaka_sql/Makefile.in
index 3639e24e8..8030190f8 100644
--- a/src/libcharon/plugins/eap_simaka_sql/Makefile.in
+++ b/src/libcharon/plugins/eap_simaka_sql/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -87,7 +88,7 @@ libstrongswan_eap_simaka_sql_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_eap_simaka_sql_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_eap_simaka_sql_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -113,6 +114,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -207,11 +209,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -228,11 +233,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -248,6 +254,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -257,7 +264,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_plugin.c b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_plugin.c
index 6e590fae7..6bcc58e66 100644
--- a/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_plugin.c
+++ b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_plugin.c
@@ -65,7 +65,8 @@ static bool load_db(private_eap_simaka_sql_t *this,
char *uri;
uri = lib->settings->get_str(lib->settings,
- "charon.plugins.eap-simaka-sql.database", NULL);
+ "%s.plugins.eap-simaka-sql.database", NULL,
+ charon->name);
if (!uri)
{
DBG1(DBG_CFG, "eap-simaka-sql database URI missing");
@@ -78,7 +79,8 @@ static bool load_db(private_eap_simaka_sql_t *this,
return FALSE;
}
remove_used = lib->settings->get_bool(lib->settings,
- "charon.plugins.eap-simaka-sql.remove_used", FALSE);
+ "%s.plugins.eap-simaka-sql.remove_used", FALSE,
+ charon->name);
this->provider = eap_simaka_sql_provider_create(this->db, remove_used);
this->card = eap_simaka_sql_card_create(this->db, remove_used);
diff --git a/src/libcharon/plugins/eap_tls/Makefile.in b/src/libcharon/plugins/eap_tls/Makefile.in
index 67e2c0cb0..55e03b2f7 100644
--- a/src/libcharon/plugins/eap_tls/Makefile.in
+++ b/src/libcharon/plugins/eap_tls/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -85,7 +86,7 @@ libstrongswan_eap_tls_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@MONOLITHIC_FALSE@am_libstrongswan_eap_tls_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_eap_tls_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -111,6 +112,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -205,11 +207,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -226,11 +231,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -246,6 +252,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -255,7 +262,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/eap_tls/eap_tls.c b/src/libcharon/plugins/eap_tls/eap_tls.c
index dc0289ba2..48e38755d 100644
--- a/src/libcharon/plugins/eap_tls/eap_tls.c
+++ b/src/libcharon/plugins/eap_tls/eap_tls.c
@@ -144,11 +144,13 @@ static eap_tls_t *eap_tls_create(identification_t *server,
);
frag_size = lib->settings->get_int(lib->settings,
- "charon.plugins.eap-tls.fragment_size", MAX_FRAGMENT_LEN);
+ "%s.plugins.eap-tls.fragment_size", MAX_FRAGMENT_LEN,
+ charon->name);
max_msg_count = lib->settings->get_int(lib->settings,
- "charon.plugins.eap-tls.max_message_count", MAX_MESSAGE_COUNT);
+ "%s.plugins.eap-tls.max_message_count", MAX_MESSAGE_COUNT,
+ charon->name);
include_length = lib->settings->get_bool(lib->settings,
- "charon.plugins.eap-tls.include_length", TRUE);
+ "%s.plugins.eap-tls.include_length", TRUE, charon->name);
tls = tls_create(is_server, server, peer, TLS_PURPOSE_EAP_TLS, NULL, NULL);
this->tls_eap = tls_eap_create(EAP_TLS, tls, frag_size, max_msg_count,
include_length);
diff --git a/src/libcharon/plugins/eap_tls/eap_tls.h b/src/libcharon/plugins/eap_tls/eap_tls.h
index 7e080230a..6779c3994 100644
--- a/src/libcharon/plugins/eap_tls/eap_tls.h
+++ b/src/libcharon/plugins/eap_tls/eap_tls.h
@@ -23,7 +23,7 @@
typedef struct eap_tls_t eap_tls_t;
-#include <sa/authenticators/eap/eap_method.h>
+#include <sa/eap/eap_method.h>
/**
* Implementation of eap_method_t using EAP-TLS.
diff --git a/src/libcharon/plugins/eap_tnc/Makefile.in b/src/libcharon/plugins/eap_tnc/Makefile.in
index 62278f835..c452f7e16 100644
--- a/src/libcharon/plugins/eap_tnc/Makefile.in
+++ b/src/libcharon/plugins/eap_tnc/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -86,7 +87,7 @@ libstrongswan_eap_tnc_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@MONOLITHIC_FALSE@am_libstrongswan_eap_tnc_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_eap_tnc_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -112,6 +113,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -206,11 +208,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -227,11 +232,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -247,6 +253,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -256,7 +263,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/eap_tnc/eap_tnc.c b/src/libcharon/plugins/eap_tnc/eap_tnc.c
index 33a83ba18..7efc0fec5 100644
--- a/src/libcharon/plugins/eap_tnc/eap_tnc.c
+++ b/src/libcharon/plugins/eap_tnc/eap_tnc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Andreas Steffen
+ * Copyright (C) 2010-2012 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -19,6 +19,17 @@
#include <tnc/tnccs/tnccs_manager.h>
#include <tls_eap.h>
#include <debug.h>
+#include <daemon.h>
+
+/**
+ * Maximum size of an EAP-TNC message
+ */
+#define EAP_TNC_MAX_MESSAGE_LEN 65535
+
+/**
+ * Maximum number of EAP-TNC messages allowed
+ */
+#define EAP_TNC_MAX_MESSAGE_COUNT 10
typedef struct private_eap_tnc_t private_eap_tnc_t;
@@ -38,12 +49,6 @@ struct private_eap_tnc_t {
tls_eap_t *tls_eap;
};
-
-/** Maximum number of EAP-TNC messages/fragments allowed */
-#define MAX_MESSAGE_COUNT 10
-/** Default size of a EAP-TNC fragment */
-#define MAX_FRAGMENT_LEN 50000
-
METHOD(eap_method_t, initiate, status_t,
private_eap_tnc_t *this, eap_payload_t **out)
{
@@ -124,9 +129,7 @@ static eap_tnc_t *eap_tnc_create(identification_t *server,
identification_t *peer, bool is_server)
{
private_eap_tnc_t *this;
- size_t frag_size;
int max_msg_count;
- bool include_length;
char* protocol;
tnccs_type_t type;
tnccs_t *tnccs;
@@ -146,14 +149,11 @@ static eap_tnc_t *eap_tnc_create(identification_t *server,
},
);
- frag_size = lib->settings->get_int(lib->settings,
- "charon.plugins.eap-tnc.fragment_size", MAX_FRAGMENT_LEN);
max_msg_count = lib->settings->get_int(lib->settings,
- "charon.plugins.eap-tnc.max_message_count", MAX_MESSAGE_COUNT);
- include_length = lib->settings->get_bool(lib->settings,
- "charon.plugins.eap-tnc.include_length", TRUE);
- protocol = lib->settings->get_str(lib->settings,
- "charon.plugins.eap-tnc.protocol", "tnccs-1.1");
+ "%s.plugins.eap-tnc.max_message_count",
+ EAP_TNC_MAX_MESSAGE_COUNT, charon->name);
+ protocol = lib->settings->get_str(lib->settings,
+ "%s.plugins.eap-tnc.protocol", "tnccs-1.1", charon->name);
if (strcaseeq(protocol, "tnccs-2.0"))
{
type = TNCCS_2_0;
@@ -173,8 +173,9 @@ static eap_tnc_t *eap_tnc_create(identification_t *server,
return NULL;
}
tnccs = tnc->tnccs->create_instance(tnc->tnccs, type, is_server);
- this->tls_eap = tls_eap_create(EAP_TNC, (tls_t*)tnccs, frag_size,
- max_msg_count, include_length);
+ this->tls_eap = tls_eap_create(EAP_TNC, (tls_t*)tnccs,
+ EAP_TNC_MAX_MESSAGE_LEN,
+ max_msg_count, FALSE);
if (!this->tls_eap)
{
free(this);
diff --git a/src/libcharon/plugins/eap_tnc/eap_tnc.h b/src/libcharon/plugins/eap_tnc/eap_tnc.h
index 7e166fb60..09abe60fc 100644
--- a/src/libcharon/plugins/eap_tnc/eap_tnc.h
+++ b/src/libcharon/plugins/eap_tnc/eap_tnc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Andreas Steffen
+ * Copyright (C) 2010-2012 Andreas Steffen
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
typedef struct eap_tnc_t eap_tnc_t;
-#include <sa/authenticators/eap/eap_method.h>
+#include <sa/eap/eap_method.h>
/**
* Implementation of the eap_method_t interface using EAP-TNC.
diff --git a/src/libcharon/plugins/eap_ttls/Makefile.in b/src/libcharon/plugins/eap_ttls/Makefile.in
index b41fbd719..95a5c1fda 100644
--- a/src/libcharon/plugins/eap_ttls/Makefile.in
+++ b/src/libcharon/plugins/eap_ttls/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -88,7 +89,7 @@ libstrongswan_eap_ttls_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_eap_ttls_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_eap_ttls_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -114,6 +115,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -208,11 +210,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -229,11 +234,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -249,6 +255,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -258,7 +265,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls.c b/src/libcharon/plugins/eap_ttls/eap_ttls.c
index ace62f6b9..ebd1c5479 100644
--- a/src/libcharon/plugins/eap_ttls/eap_ttls.c
+++ b/src/libcharon/plugins/eap_ttls/eap_ttls.c
@@ -146,16 +146,19 @@ static eap_ttls_t *eap_ttls_create(identification_t *server,
},
);
if (is_server && !lib->settings->get_bool(lib->settings,
- "charon.plugins.eap-ttls.request_peer_auth", FALSE))
+ "%s.plugins.eap-ttls.request_peer_auth", FALSE,
+ charon->name))
{
peer = NULL;
}
frag_size = lib->settings->get_int(lib->settings,
- "charon.plugins.eap-ttls.fragment_size", MAX_FRAGMENT_LEN);
+ "%s.plugins.eap-ttls.fragment_size", MAX_FRAGMENT_LEN,
+ charon->name);
max_msg_count = lib->settings->get_int(lib->settings,
- "charon.plugins.eap-ttls.max_message_count", MAX_MESSAGE_COUNT);
+ "%s.plugins.eap-ttls.max_message_count", MAX_MESSAGE_COUNT,
+ charon->name);
include_length = lib->settings->get_bool(lib->settings,
- "charon.plugins.eap-ttls.include_length", TRUE);
+ "%s.plugins.eap-ttls.include_length", TRUE, charon->name);
tls = tls_create(is_server, server, peer, TLS_PURPOSE_EAP_TTLS,
application, NULL);
this->tls_eap = tls_eap_create(EAP_TTLS, tls, frag_size, max_msg_count,
@@ -170,7 +173,7 @@ static eap_ttls_t *eap_ttls_create(identification_t *server,
}
eap_ttls_t *eap_ttls_create_server(identification_t *server,
- identification_t *peer)
+ identification_t *peer)
{
return eap_ttls_create(server, peer, TRUE,
&eap_ttls_server_create(server, peer)->application);
diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls.h b/src/libcharon/plugins/eap_ttls/eap_ttls.h
index 6e3bf2ceb..84b1a2d19 100644
--- a/src/libcharon/plugins/eap_ttls/eap_ttls.h
+++ b/src/libcharon/plugins/eap_ttls/eap_ttls.h
@@ -23,7 +23,7 @@
typedef struct eap_ttls_t eap_ttls_t;
-#include <sa/authenticators/eap/eap_method.h>
+#include <sa/eap/eap_method.h>
/**
* Implementation of eap_method_t using EAP-TTLS.
diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c b/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c
index 4b6897b1d..00a4da3f8 100644
--- a/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c
+++ b/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c
@@ -19,7 +19,7 @@
#include <debug.h>
#include <daemon.h>
#include <radius_message.h>
-#include <sa/authenticators/eap/eap_method.h>
+#include <sa/eap/eap_method.h>
typedef struct private_eap_ttls_peer_t private_eap_ttls_peer_t;
@@ -138,7 +138,7 @@ METHOD(tls_application_t, process, status_t,
chunk_free(&avp_data);
}
while (eap_pos < eap_data.len);
-
+
in = eap_payload_create_data(eap_data);
chunk_free(&eap_data);
payload = (payload_t*)in;
@@ -192,7 +192,8 @@ METHOD(tls_application_t, process, status_t,
if (!this->method)
{
DBG1(DBG_IKE, "EAP method not supported");
- this->out = eap_payload_create_nak(in->get_identifier(in));
+ this->out = eap_payload_create_nak(in->get_identifier(in), 0, 0,
+ in->is_expanded(in));
in->destroy(in);
return NEED_MORE;
}
diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls_server.c b/src/libcharon/plugins/eap_ttls/eap_ttls_server.c
index 3c46993b7..1418d6a4d 100644
--- a/src/libcharon/plugins/eap_ttls/eap_ttls_server.c
+++ b/src/libcharon/plugins/eap_ttls/eap_ttls_server.c
@@ -19,7 +19,7 @@
#include <debug.h>
#include <daemon.h>
-#include <sa/authenticators/eap/eap_method.h>
+#include <sa/eap/eap_method.h>
typedef struct private_eap_ttls_server_t private_eap_ttls_server_t;
@@ -78,7 +78,8 @@ static status_t start_phase2_auth(private_eap_ttls_server_t *this)
eap_type_t type;
eap_type_str = lib->settings->get_str(lib->settings,
- "charon.plugins.eap-ttls.phase2_method", "md5");
+ "%s.plugins.eap-ttls.phase2_method", "md5",
+ charon->name);
type = eap_type_from_string(eap_type_str);
if (type == 0)
{
@@ -110,7 +111,7 @@ static status_t start_phase2_auth(private_eap_ttls_server_t *this)
static status_t start_phase2_tnc(private_eap_ttls_server_t *this)
{
if (this->start_phase2_tnc && lib->settings->get_bool(lib->settings,
- "charon.plugins.eap-ttls.phase2_tnc", FALSE))
+ "%s.plugins.eap-ttls.phase2_tnc", FALSE, charon->name))
{
DBG1(DBG_IKE, "phase2 method %N selected", eap_type_names, EAP_TNC);
this->method = charon->eap->create_instance(charon->eap, EAP_TNC,
@@ -168,7 +169,7 @@ METHOD(tls_application_t, process, status_t,
code = in->get_code(in);
received_type = in->get_type(in, &received_vendor);
DBG1(DBG_IKE, "received tunneled EAP-TTLS AVP [EAP/%N/%N]",
- eap_code_short_names, code,
+ eap_code_short_names, code,
eap_type_short_names, received_type);
if (code != EAP_RESPONSE)
{
@@ -234,7 +235,7 @@ METHOD(tls_application_t, process, status_t,
/* Start Phase 2 of EAP-TTLS authentication */
if (lib->settings->get_bool(lib->settings,
- "charon.plugins.eap-ttls.request_peer_auth", FALSE))
+ "%s.plugins.eap-ttls.request_peer_auth", FALSE, charon->name))
{
return start_phase2_tnc(this);
}
@@ -279,7 +280,7 @@ METHOD(tls_application_t, process, status_t,
DBG1(DBG_IKE, "%N method failed", eap_type_names, type);
}
return FAILED;
- }
+ }
return status;
}
@@ -293,7 +294,7 @@ METHOD(tls_application_t, build, status_t,
if (this->method == NULL && this->start_phase2 &&
lib->settings->get_bool(lib->settings,
- "charon.plugins.eap-ttls.phase2_piggyback", FALSE))
+ "%s.plugins.eap-ttls.phase2_piggyback", FALSE, charon->name))
{
/* generate an EAP Identity request which will be piggybacked right
* onto the TLS Finished message thus initiating EAP-TTLS phase2
diff --git a/src/libcharon/plugins/farp/Makefile.in b/src/libcharon/plugins/farp/Makefile.in
index cfb51933c..c26bd7856 100644
--- a/src/libcharon/plugins/farp/Makefile.in
+++ b/src/libcharon/plugins/farp/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -83,7 +84,7 @@ libstrongswan_farp_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(libstrongswan_farp_la_LDFLAGS) $(LDFLAGS) -o $@
@MONOLITHIC_FALSE@am_libstrongswan_farp_la_rpath = -rpath $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_farp_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -109,6 +110,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -203,11 +205,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -224,11 +229,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -244,6 +250,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -253,7 +260,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/farp/farp_spoofer.c b/src/libcharon/plugins/farp/farp_spoofer.c
index 587a3a74e..52b037c19 100644
--- a/src/libcharon/plugins/farp/farp_spoofer.c
+++ b/src/libcharon/plugins/farp/farp_spoofer.c
@@ -45,11 +45,6 @@ struct private_farp_spoofer_t {
farp_listener_t *listener;
/**
- * Callback job to read ARP requests
- */
- callback_job_t *job;
-
- /**
* RAW socket for ARP requests
*/
int skt;
@@ -135,7 +130,6 @@ static job_requeue_t receive_arp(private_farp_spoofer_t *this)
METHOD(farp_spoofer_t, destroy, void,
private_farp_spoofer_t *this)
{
- this->job->cancel(this->job);
close(this->skt);
free(this);
}
@@ -189,9 +183,9 @@ farp_spoofer_t *farp_spoofer_create(farp_listener_t *listener)
return NULL;
}
- this->job = callback_job_create_with_prio((callback_job_cb_t)receive_arp,
- this, NULL, NULL, JOB_PRIO_CRITICAL);
- lib->processor->queue_job(lib->processor, (job_t*)this->job);
+ lib->processor->queue_job(lib->processor,
+ (job_t*)callback_job_create_with_prio((callback_job_cb_t)receive_arp,
+ this, NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
return &this->public;
}
diff --git a/src/libcharon/plugins/ha/Makefile.in b/src/libcharon/plugins/ha/Makefile.in
index c66a550cd..0ac139ca0 100644
--- a/src/libcharon/plugins/ha/Makefile.in
+++ b/src/libcharon/plugins/ha/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -85,7 +86,7 @@ libstrongswan_ha_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(libstrongswan_ha_la_LDFLAGS) $(LDFLAGS) -o $@
@MONOLITHIC_FALSE@am_libstrongswan_ha_la_rpath = -rpath $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_ha_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -111,6 +112,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -205,11 +207,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -226,11 +231,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -246,6 +252,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -255,7 +262,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/ha/ha_attribute.c b/src/libcharon/plugins/ha/ha_attribute.c
index b08abe1a9..ae6296462 100644
--- a/src/libcharon/plugins/ha/ha_attribute.c
+++ b/src/libcharon/plugins/ha/ha_attribute.c
@@ -170,17 +170,29 @@ static bool responsible_for(private_ha_attribute_t *this, int bit)
}
METHOD(attribute_provider_t, acquire_address, host_t*,
- private_ha_attribute_t *this, char *name, identification_t *id,
+ private_ha_attribute_t *this, linked_list_t *pools, identification_t *id,
host_t *requested)
{
+ enumerator_t *enumerator;
pool_t *pool;
int offset = -1, byte, bit;
host_t *address;
+ char *name;
+ enumerator = pools->create_enumerator(pools);
this->mutex->lock(this->mutex);
- pool = get_pool(this, name);
- if (pool)
+ while (enumerator->enumerate(enumerator, &name))
{
+ pool = get_pool(this, name);
+ if (!pool)
+ {
+ continue;
+ }
+ if (pool->base->get_family(pool->base) !=
+ requested->get_family(requested))
+ {
+ continue;
+ }
for (byte = 0; byte < pool->size / 8; byte++)
{
if (pool->mask[byte] != 0xFF)
@@ -208,6 +220,8 @@ METHOD(attribute_provider_t, acquire_address, host_t*,
}
}
this->mutex->unlock(this->mutex);
+ enumerator->destroy(enumerator);
+
if (offset != -1)
{
address = offset2host(pool, offset);
@@ -218,26 +232,40 @@ METHOD(attribute_provider_t, acquire_address, host_t*,
}
METHOD(attribute_provider_t, release_address, bool,
- private_ha_attribute_t *this, char *name, host_t *address,
+ private_ha_attribute_t *this, linked_list_t *pools, host_t *address,
identification_t *id)
{
+ enumerator_t *enumerator;
pool_t *pool;
int offset;
+ char *name;
bool found = FALSE;
+ enumerator = pools->create_enumerator(pools);
this->mutex->lock(this->mutex);
- pool = get_pool(this, name);
- if (pool)
+ while (enumerator->enumerate(enumerator, &name))
{
+ pool = get_pool(this, name);
+ if (!pool)
+ {
+ continue;
+ }
+ if (pool->base->get_family(pool->base) != address->get_family(address))
+ {
+ continue;
+ }
offset = host2offset(pool, address);
if (offset > 0 && offset < pool->size)
{
pool->mask[offset / 8] &= ~(1 << (offset % 8));
DBG1(DBG_CFG, "released address %H to HA pool '%s'", address, name);
found = TRUE;
+ break;
}
}
this->mutex->unlock(this->mutex);
+ enumerator->destroy(enumerator);
+
return found;
}
@@ -281,7 +309,7 @@ static void load_pools(private_ha_attribute_t *this)
pool_t *pool;
enumerator = lib->settings->create_key_value_enumerator(lib->settings,
- "charon.plugins.ha.pools");
+ "%s.plugins.ha.pools", charon->name);
while (enumerator->enumerate(enumerator, &name, &net))
{
net = strdup(net);
diff --git a/src/libcharon/plugins/ha/ha_cache.c b/src/libcharon/plugins/ha/ha_cache.c
index 970a8a2b9..e21b461a7 100644
--- a/src/libcharon/plugins/ha/ha_cache.c
+++ b/src/libcharon/plugins/ha/ha_cache.c
@@ -88,6 +88,8 @@ typedef struct {
ha_message_t *midi;
/* last responder mid */
ha_message_t *midr;
+ /* last IV update */
+ ha_message_t *iv;
} entry_t;
/**
@@ -114,6 +116,7 @@ static void entry_destroy(entry_t *entry)
entry->add->destroy(entry->add);
DESTROY_IF(entry->midi);
DESTROY_IF(entry->midr);
+ DESTROY_IF(entry->iv);
free(entry);
}
@@ -164,6 +167,16 @@ METHOD(ha_cache_t, cache, void,
}
message->destroy(message);
break;
+ case HA_IKE_IV:
+ entry = this->cache->get(this->cache, ike_sa);
+ if (entry)
+ {
+ DESTROY_IF(entry->iv);
+ entry->iv = message;
+ break;
+ }
+ message->destroy(message);
+ break;
case HA_IKE_DELETE:
entry = this->cache->remove(this->cache, ike_sa);
if (entry)
@@ -212,7 +225,8 @@ static status_t rekey_children(ike_sa_t *ike_sa)
DBG1(DBG_CFG, "resyncing CHILD_SA using a delete");
status = ike_sa->delete_child_sa(ike_sa,
child_sa->get_protocol(child_sa),
- child_sa->get_spi(child_sa, TRUE));
+ child_sa->get_spi(child_sa, TRUE),
+ FALSE);
}
else
{
@@ -308,6 +322,10 @@ METHOD(ha_cache_t, resync, void,
{
this->socket->push(this->socket, entry->midr);
}
+ if (entry->iv)
+ {
+ this->socket->push(this->socket, entry->iv);
+ }
}
}
enumerator->destroy(enumerator);
diff --git a/src/libcharon/plugins/ha/ha_ctl.c b/src/libcharon/plugins/ha/ha_ctl.c
index 9c99807ed..cb9af3aed 100644
--- a/src/libcharon/plugins/ha/ha_ctl.c
+++ b/src/libcharon/plugins/ha/ha_ctl.c
@@ -48,11 +48,6 @@ struct private_ha_ctl_t {
* Resynchronization message cache
*/
ha_cache_t *cache;
-
- /**
- * FIFO reader thread
- */
- callback_job_t *job;
};
/**
@@ -105,7 +100,6 @@ static job_requeue_t dispatch_fifo(private_ha_ctl_t *this)
METHOD(ha_ctl_t, destroy, void,
private_ha_ctl_t *this)
{
- this->job->cancel(this->job);
free(this);
}
@@ -135,15 +129,16 @@ ha_ctl_t *ha_ctl_create(ha_segments_t *segments, ha_cache_t *cache)
}
umask(old);
}
- if (chown(HA_FIFO, charon->uid, charon->gid) != 0)
+ if (chown(HA_FIFO, charon->caps->get_uid(charon->caps),
+ charon->caps->get_gid(charon->caps)) != 0)
{
DBG1(DBG_CFG, "changing HA FIFO permissions failed: %s",
strerror(errno));
}
- this->job = callback_job_create_with_prio((callback_job_cb_t)dispatch_fifo,
- this, NULL, NULL, JOB_PRIO_CRITICAL);
- lib->processor->queue_job(lib->processor, (job_t*)this->job);
+ lib->processor->queue_job(lib->processor,
+ (job_t*)callback_job_create_with_prio((callback_job_cb_t)dispatch_fifo,
+ 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 994f91d20..97ed13111 100644
--- a/src/libcharon/plugins/ha/ha_dispatcher.c
+++ b/src/libcharon/plugins/ha/ha_dispatcher.c
@@ -16,9 +16,13 @@
#include "ha_dispatcher.h"
#include <daemon.h>
+#include <sa/ikev2/keymat_v2.h>
+#include <sa/ikev1/keymat_v1.h>
#include <processing/jobs/callback_job.h>
+#include <processing/jobs/adopt_children_job.h>
typedef struct private_ha_dispatcher_t private_ha_dispatcher_t;
+typedef struct ha_diffie_hellman_t ha_diffie_hellman_t;
/**
* Private data of an ha_dispatcher_t object.
@@ -54,20 +58,66 @@ struct private_ha_dispatcher_t {
* HA enabled pool
*/
ha_attribute_t *attr;
+};
+
+/**
+ * DH implementation for HA synced DH values
+ */
+struct ha_diffie_hellman_t {
+
+ /**
+ * Implements diffie_hellman_t
+ */
+ diffie_hellman_t dh;
/**
- * Dispatcher job
+ * Shared secret
*/
- callback_job_t *job;
+ chunk_t secret;
+
+ /**
+ * Own public value
+ */
+ chunk_t pub;
};
+METHOD(diffie_hellman_t, dh_get_shared_secret, status_t,
+ ha_diffie_hellman_t *this, chunk_t *secret)
+{
+ *secret = chunk_clone(this->secret);
+ return SUCCESS;
+}
+
+METHOD(diffie_hellman_t, dh_get_my_public_value, void,
+ ha_diffie_hellman_t *this, chunk_t *value)
+{
+ *value = chunk_clone(this->pub);
+}
+
+METHOD(diffie_hellman_t, dh_destroy, void,
+ ha_diffie_hellman_t *this)
+{
+ free(this);
+}
+
/**
- * Quick and dirty hack implementation of diffie_hellman_t.get_shared_secret
+ * Create a HA synced DH implementation
*/
-static status_t get_shared_secret(diffie_hellman_t *this, chunk_t *secret)
+static diffie_hellman_t *ha_diffie_hellman_create(chunk_t secret, chunk_t pub)
{
- *secret = chunk_clone((*(chunk_t*)this->destroy));
- return SUCCESS;
+ ha_diffie_hellman_t *this;
+
+ INIT(this,
+ .dh = {
+ .get_shared_secret = _dh_get_shared_secret,
+ .get_my_public_value = _dh_get_my_public_value,
+ .destroy = _dh_destroy,
+ },
+ .secret = secret,
+ .pub = pub,
+ );
+
+ return &this->dh;
}
/**
@@ -79,9 +129,12 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
ha_message_value_t value;
enumerator_t *enumerator;
ike_sa_t *ike_sa = NULL, *old_sa = NULL;
+ ike_version_t version = IKEV2;
u_int16_t encr = 0, len = 0, integ = 0, prf = 0, old_prf = PRF_UNDEFINED;
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;
+ bool ok = FALSE;
enumerator = message->create_attribute_enumerator(message);
while (enumerator->enumerate(enumerator, &attribute, &value))
@@ -89,12 +142,16 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
switch (attribute)
{
case HA_IKE_ID:
- ike_sa = ike_sa_create(value.ike_sa_id);
+ ike_sa = ike_sa_create(value.ike_sa_id,
+ value.ike_sa_id->is_initiator(value.ike_sa_id), version);
break;
case HA_IKE_REKEY_ID:
old_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
value.ike_sa_id);
break;
+ case HA_IKE_VERSION:
+ version = value.u8;
+ break;
case HA_NONCE_I:
nonce_i = value.chunk;
break;
@@ -104,6 +161,15 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
case HA_SECRET:
secret = value.chunk;
break;
+ case HA_LOCAL_DH:
+ dh_local = value.chunk;
+ break;
+ case HA_REMOTE_DH:
+ dh_remote = value.chunk;
+ break;
+ case HA_PSK:
+ psk = value.chunk;
+ break;
case HA_OLD_SKD:
old_skd = value.chunk;
break;
@@ -131,13 +197,9 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
if (ike_sa)
{
proposal_t *proposal;
- keymat_t *keymat;
- /* quick and dirty hack of a DH implementation ;-) */
- diffie_hellman_t dh = { .get_shared_secret = get_shared_secret,
- .destroy = (void*)&secret };
+ diffie_hellman_t *dh;
proposal = proposal_create(PROTO_IKE, 0);
- keymat = ike_sa->get_keymat(ike_sa);
if (integ)
{
proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM, integ, 0);
@@ -151,8 +213,35 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
proposal->add_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, prf, 0);
}
charon->bus->set_sa(charon->bus, ike_sa);
- if (keymat->derive_ike_keys(keymat, proposal, &dh, nonce_i, nonce_r,
- ike_sa->get_id(ike_sa), old_prf, old_skd))
+ dh = ha_diffie_hellman_create(secret, dh_local);
+ if (ike_sa->get_version(ike_sa) == IKEV2)
+ {
+ keymat_v2_t *keymat_v2 = (keymat_v2_t*)ike_sa->get_keymat(ike_sa);
+
+ ok = keymat_v2->derive_ike_keys(keymat_v2, proposal, dh, nonce_i,
+ nonce_r, ike_sa->get_id(ike_sa), old_prf, old_skd);
+ }
+ if (ike_sa->get_version(ike_sa) == IKEV1)
+ {
+ keymat_v1_t *keymat_v1 = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
+ shared_key_t *shared = NULL;
+ auth_method_t method = AUTH_RSA;
+
+ if (psk.len)
+ {
+ method = AUTH_PSK;
+ shared = shared_key_create(SHARED_IKE, chunk_clone(psk));
+ }
+ if (keymat_v1->create_hasher(keymat_v1, proposal))
+ {
+ ok = keymat_v1->derive_ike_keys(keymat_v1, proposal,
+ dh, dh_remote, nonce_i, nonce_r,
+ ike_sa->get_id(ike_sa), method, shared);
+ }
+ DESTROY_IF(shared);
+ }
+ dh->destroy(dh);
+ if (ok)
{
if (old_sa)
{
@@ -168,6 +257,7 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
old_sa = NULL;
}
ike_sa->set_state(ike_sa, IKE_CONNECTING);
+ ike_sa->set_proposal(ike_sa, proposal);
this->cache->cache(this->cache, ike_sa, message);
message = NULL;
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
@@ -220,7 +310,7 @@ static void process_ike_update(private_ha_dispatcher_t *this,
ike_sa_t *ike_sa = NULL;
peer_cfg_t *peer_cfg = NULL;
auth_cfg_t *auth;
- bool received_vip = FALSE, first_peer_addr = TRUE;
+ bool received_vip = FALSE, first_local_vip = TRUE, first_peer_addr = TRUE;
enumerator = message->create_attribute_enumerator(message);
while (enumerator->enumerate(enumerator, &attribute, &value))
@@ -254,10 +344,19 @@ static void process_ike_update(private_ha_dispatcher_t *this,
ike_sa->set_other_host(ike_sa, value.host->clone(value.host));
break;
case HA_LOCAL_VIP:
- ike_sa->set_virtual_ip(ike_sa, TRUE, value.host);
+ if (first_local_vip)
+ {
+ ike_sa->clear_virtual_ips(ike_sa, TRUE);
+ first_local_vip = FALSE;
+ }
+ ike_sa->add_virtual_ip(ike_sa, TRUE, value.host);
break;
case HA_REMOTE_VIP:
- ike_sa->set_virtual_ip(ike_sa, FALSE, value.host);
+ if (!received_vip)
+ {
+ ike_sa->clear_virtual_ips(ike_sa, FALSE);
+ }
+ ike_sa->add_virtual_ip(ike_sa, FALSE, value.host);
received_vip = TRUE;
break;
case HA_PEER_ADDR:
@@ -289,6 +388,8 @@ static void process_ike_update(private_ha_dispatcher_t *this,
set_extension(ike_sa, value.u32, EXT_STRONGSWAN);
set_extension(ike_sa, value.u32, EXT_EAP_ONLY_AUTHENTICATION);
set_extension(ike_sa, value.u32, EXT_MS_WINDOWS);
+ set_extension(ike_sa, value.u32, EXT_XAUTH);
+ set_extension(ike_sa, value.u32, EXT_DPD);
break;
case HA_CONDITIONS:
set_condition(ike_sa, value.u32, COND_NAT_ANY);
@@ -299,6 +400,8 @@ static void process_ike_update(private_ha_dispatcher_t *this,
set_condition(ike_sa, value.u32, COND_CERTREQ_SEEN);
set_condition(ike_sa, value.u32, COND_ORIGINAL_INITIATOR);
set_condition(ike_sa, value.u32, COND_STALE);
+ set_condition(ike_sa, value.u32, COND_INIT_CONTACT_SEEN);
+ set_condition(ike_sa, value.u32, COND_XAUTH_AUTHENTICATED);
break;
default:
break;
@@ -319,20 +422,31 @@ static void process_ike_update(private_ha_dispatcher_t *this,
}
if (received_vip)
{
+ enumerator_t *pools, *vips;
host_t *vip;
char *pool;
peer_cfg = ike_sa->get_peer_cfg(ike_sa);
- vip = ike_sa->get_virtual_ip(ike_sa, FALSE);
- if (peer_cfg && vip)
+ if (peer_cfg)
{
- pool = peer_cfg->get_pool(peer_cfg);
- if (pool)
+ pools = peer_cfg->create_pool_enumerator(peer_cfg);
+ while (pools->enumerate(pools, &pool))
{
- this->attr->reserve(this->attr, pool, vip);
+ vips = ike_sa->create_virtual_ip_enumerator(ike_sa, FALSE);
+ while (vips->enumerate(vips, &vip))
+ {
+ this->attr->reserve(this->attr, pool, vip);
+ }
+ vips->destroy(vips);
}
+ pools->destroy(pools);
}
}
+ if (ike_sa->get_version(ike_sa) == IKEV1)
+ {
+ lib->processor->queue_job(lib->processor, (job_t*)
+ adopt_children_job_create(ike_sa->get_id(ike_sa)));
+ }
this->cache->cache(this->cache, ike_sa, message);
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
}
@@ -389,6 +503,59 @@ static void process_ike_mid(private_ha_dispatcher_t *this,
}
/**
+ * Process messages of type IKE_IV
+ */
+static void process_ike_iv(private_ha_dispatcher_t *this, ha_message_t *message)
+{
+ ha_message_attribute_t attribute;
+ ha_message_value_t value;
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa = NULL;
+ chunk_t iv = chunk_empty;
+
+ enumerator = message->create_attribute_enumerator(message);
+ while (enumerator->enumerate(enumerator, &attribute, &value))
+ {
+ switch (attribute)
+ {
+ case HA_IKE_ID:
+ ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
+ value.ike_sa_id);
+ break;
+ case HA_IV:
+ iv = value.chunk;
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (ike_sa)
+ {
+ if (ike_sa->get_version(ike_sa) == IKEV1)
+ {
+ if (iv.len)
+ {
+ keymat_v1_t *keymat;
+
+ keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
+ if (keymat->update_iv(keymat, 0, iv))
+ {
+ keymat->confirm_iv(keymat, 0);
+ }
+ }
+ }
+ this->cache->cache(this->cache, ike_sa, message);
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ }
+ else
+ {
+ message->destroy(message);
+ }
+}
+
+/**
* Process messages of type IKE_DELETE
*/
static void process_ike_delete(private_ha_dispatcher_t *this,
@@ -465,8 +632,7 @@ static void process_child_add(private_ha_dispatcher_t *this,
child_cfg_t *config = NULL;
child_sa_t *child_sa;
proposal_t *proposal;
- keymat_t *keymat;
- bool initiator = FALSE, failed = FALSE;
+ bool initiator = FALSE, failed = FALSE, ok = FALSE;
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;
@@ -476,9 +642,7 @@ static void process_child_add(private_ha_dispatcher_t *this,
chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty, secret = chunk_empty;
chunk_t encr_i, integ_i, encr_r, integ_r;
linked_list_t *local_ts, *remote_ts;
- /* quick and dirty hack of a DH implementation */
- diffie_hellman_t dh = { .get_shared_secret = get_shared_secret,
- .destroy = (void*)&secret };
+ diffie_hellman_t *dh = NULL;
enumerator = message->create_attribute_enumerator(message);
while (enumerator->enumerate(enumerator, &attribute, &value))
@@ -572,10 +736,30 @@ static void process_child_add(private_ha_dispatcher_t *this,
proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr, len);
}
proposal->add_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS, esn, 0);
- keymat = ike_sa->get_keymat(ike_sa);
+ if (secret.len)
+ {
+ dh = ha_diffie_hellman_create(secret, chunk_empty);
+ }
+ if (ike_sa->get_version(ike_sa) == IKEV2)
+ {
+ keymat_v2_t *keymat_v2 = (keymat_v2_t*)ike_sa->get_keymat(ike_sa);
- if (!keymat->derive_child_keys(keymat, proposal, secret.ptr ? &dh : NULL,
- nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r))
+ ok = keymat_v2->derive_child_keys(keymat_v2, proposal, dh,
+ nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r);
+ }
+ if (ike_sa->get_version(ike_sa) == IKEV1)
+ {
+ keymat_v1_t *keymat_v1 = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
+ u_int32_t spi_i, spi_r;
+
+ spi_i = initiator ? inbound_spi : outbound_spi;
+ spi_r = initiator ? outbound_spi : inbound_spi;
+
+ ok = keymat_v1->derive_child_keys(keymat_v1, proposal, dh, spi_i, spi_r,
+ nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r);
+ }
+ DESTROY_IF(dh);
+ if (!ok)
{
DBG1(DBG_CHD, "HA CHILD_SA key derivation failed");
child_sa->destroy(child_sa);
@@ -825,6 +1009,9 @@ static job_requeue_t dispatch(private_ha_dispatcher_t *this)
case HA_IKE_MID_RESPONDER:
process_ike_mid(this, message, FALSE);
break;
+ case HA_IKE_IV:
+ process_ike_iv(this, message);
+ break;
case HA_IKE_DELETE:
process_ike_delete(this, message);
break;
@@ -857,7 +1044,6 @@ static job_requeue_t dispatch(private_ha_dispatcher_t *this)
METHOD(ha_dispatcher_t, destroy, void,
private_ha_dispatcher_t *this)
{
- this->job->cancel(this->job);
free(this);
}
@@ -881,9 +1067,9 @@ ha_dispatcher_t *ha_dispatcher_create(ha_socket_t *socket,
.kernel = kernel,
.attr = attr,
);
- this->job = callback_job_create_with_prio((callback_job_cb_t)dispatch,
- this, NULL, NULL, JOB_PRIO_CRITICAL);
- lib->processor->queue_job(lib->processor, (job_t*)this->job);
+ lib->processor->queue_job(lib->processor,
+ (job_t*)callback_job_create_with_prio((callback_job_cb_t)dispatch, this,
+ NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
return &this->public;
}
diff --git a/src/libcharon/plugins/ha/ha_ike.c b/src/libcharon/plugins/ha/ha_ike.c
index e818aec9c..442a3a23d 100644
--- a/src/libcharon/plugins/ha/ha_ike.c
+++ b/src/libcharon/plugins/ha/ha_ike.c
@@ -15,6 +15,9 @@
#include "ha_ike.h"
+#include <sa/ikev2/keymat_v2.h>
+#include <sa/ikev1/keymat_v1.h>
+
typedef struct private_ha_ike_t private_ha_ike_t;
/**
@@ -69,7 +72,8 @@ static ike_extension_t copy_extension(ike_sa_t *ike_sa, ike_extension_t ext)
METHOD(listener_t, ike_keys, bool,
private_ha_ike_t *this, ike_sa_t *ike_sa, diffie_hellman_t *dh,
- chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey)
+ chunk_t dh_other, chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey,
+ shared_key_t *shared)
{
ha_message_t *m;
chunk_t secret;
@@ -86,14 +90,15 @@ METHOD(listener_t, ike_keys, bool,
}
m = ha_message_create(HA_IKE_ADD);
+ m->add_attribute(m, HA_IKE_VERSION, ike_sa->get_version(ike_sa));
m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
- if (rekey)
+ if (rekey && rekey->get_version(rekey) == IKEV2)
{
chunk_t skd;
- keymat_t *keymat;
+ keymat_v2_t *keymat;
- keymat = rekey->get_keymat(rekey);
+ keymat = (keymat_v2_t*)rekey->get_keymat(rekey);
m->add_attribute(m, HA_IKE_REKEY_ID, rekey->get_id(rekey));
m->add_attribute(m, HA_ALG_OLD_PRF, keymat->get_skd(keymat, &skd));
m->add_attribute(m, HA_OLD_SKD, skd);
@@ -120,6 +125,17 @@ METHOD(listener_t, ike_keys, bool,
m->add_attribute(m, HA_NONCE_R, nonce_r);
m->add_attribute(m, HA_SECRET, secret);
chunk_clear(&secret);
+ if (ike_sa->get_version(ike_sa) == IKEV1)
+ {
+ dh->get_my_public_value(dh, &secret);
+ m->add_attribute(m, HA_LOCAL_DH, secret);
+ chunk_free(&secret);
+ m->add_attribute(m, HA_REMOTE_DH, dh_other);
+ if (shared)
+ {
+ m->add_attribute(m, HA_PSK, shared->get_key(shared));
+ }
+ }
this->socket->push(this->socket, m);
this->cache->cache(this->cache, ike_sa, m);
@@ -159,7 +175,9 @@ METHOD(listener_t, ike_updown, bool,
| copy_condition(ike_sa, COND_EAP_AUTHENTICATED)
| copy_condition(ike_sa, COND_CERTREQ_SEEN)
| copy_condition(ike_sa, COND_ORIGINAL_INITIATOR)
- | copy_condition(ike_sa, COND_STALE);
+ | copy_condition(ike_sa, COND_STALE)
+ | copy_condition(ike_sa, COND_INIT_CONTACT_SEEN)
+ | copy_condition(ike_sa, COND_XAUTH_AUTHENTICATED);
extension = copy_extension(ike_sa, EXT_NATT)
| copy_extension(ike_sa, EXT_MOBIKE)
@@ -167,7 +185,9 @@ METHOD(listener_t, ike_updown, bool,
| copy_extension(ike_sa, EXT_MULTIPLE_AUTH)
| copy_extension(ike_sa, EXT_STRONGSWAN)
| copy_extension(ike_sa, EXT_EAP_ONLY_AUTHENTICATION)
- | copy_extension(ike_sa, EXT_MS_WINDOWS);
+ | copy_extension(ike_sa, EXT_MS_WINDOWS)
+ | copy_extension(ike_sa, EXT_XAUTH)
+ | copy_extension(ike_sa, EXT_DPD);
id = ike_sa->get_id(ike_sa);
@@ -221,49 +241,125 @@ METHOD(listener_t, ike_state_change, bool,
return TRUE;
}
+/**
+ * Send a virtual IP sync message for remote VIPs
+ */
+static void sync_vips(private_ha_ike_t *this, ike_sa_t *ike_sa)
+{
+ ha_message_t *m = NULL;
+ enumerator_t *enumerator;
+ host_t *vip;
+
+ enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, FALSE);
+ while (enumerator->enumerate(enumerator, &vip))
+ {
+ if (!m)
+ {
+ m = ha_message_create(HA_IKE_UPDATE);
+ m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
+ }
+ m->add_attribute(m, HA_REMOTE_VIP, vip);
+ }
+ enumerator->destroy(enumerator);
+
+ if (m)
+ {
+ this->socket->push(this->socket, m);
+ this->cache->cache(this->cache, ike_sa, m);
+ }
+}
+
METHOD(listener_t, message_hook, bool,
- private_ha_ike_t *this, ike_sa_t *ike_sa, message_t *message, bool incoming)
+ private_ha_ike_t *this, ike_sa_t *ike_sa, message_t *message,
+ bool incoming, bool plain)
{
if (this->tunnel && this->tunnel->is_sa(this->tunnel, ike_sa))
{ /* do not sync SA between nodes */
return TRUE;
}
- if (message->get_exchange_type(message) != IKE_SA_INIT &&
- message->get_request(message))
- { /* we sync on requests, but skip it on IKE_SA_INIT */
+ if (plain && ike_sa->get_version(ike_sa) == IKEV2)
+ {
+ if (message->get_exchange_type(message) != IKE_SA_INIT &&
+ message->get_request(message))
+ { /* we sync on requests, but skip it on IKE_SA_INIT */
+ ha_message_t *m;
+
+ if (incoming)
+ {
+ m = ha_message_create(HA_IKE_MID_RESPONDER);
+ }
+ else
+ {
+ m = ha_message_create(HA_IKE_MID_INITIATOR);
+ }
+ m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
+ m->add_attribute(m, HA_MID, message->get_message_id(message) + 1);
+ this->socket->push(this->socket, m);
+ this->cache->cache(this->cache, ike_sa, m);
+ }
+ if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
+ message->get_exchange_type(message) == IKE_AUTH &&
+ !message->get_request(message))
+ { /* After IKE_SA has been established, sync peers virtual IP.
+ * We cannot sync it in the state_change hook, it is installed later.
+ * TODO: where to sync local VIP? */
+ sync_vips(this, ike_sa);
+ }
+ }
+ if (!plain && ike_sa->get_version(ike_sa) == IKEV1)
+ {
ha_message_t *m;
+ keymat_v1_t *keymat;
+ u_int32_t mid;
+ chunk_t iv;
- if (incoming)
+ mid = message->get_message_id(message);
+ if (mid == 0)
{
- m = ha_message_create(HA_IKE_MID_RESPONDER);
+ keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
+ if (keymat->get_iv(keymat, mid, &iv))
+ {
+ m = ha_message_create(HA_IKE_IV);
+ m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
+ m->add_attribute(m, HA_IV, iv);
+ this->socket->push(this->socket, m);
+ this->cache->cache(this->cache, ike_sa, m);
+ }
}
- else
+ if (!incoming && message->get_exchange_type(message) == TRANSACTION)
{
- m = ha_message_create(HA_IKE_MID_INITIATOR);
+ sync_vips(this, ike_sa);
}
- m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
- m->add_attribute(m, HA_MID, message->get_message_id(message) + 1);
- this->socket->push(this->socket, m);
- this->cache->cache(this->cache, ike_sa, m);
}
- if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
- message->get_exchange_type(message) == IKE_AUTH &&
- !message->get_request(message))
- { /* After IKE_SA has been established, sync peers virtual IP.
- * We cannot sync it in the state_change hook, it is installed later.
- * TODO: where to sync local VIP? */
+ if (plain && ike_sa->get_version(ike_sa) == IKEV1 &&
+ message->get_exchange_type(message) == INFORMATIONAL_V1)
+ {
ha_message_t *m;
- host_t *vip;
+ notify_payload_t *notify;
+ chunk_t data;
+ u_int32_t seq;
- vip = ike_sa->get_virtual_ip(ike_sa, FALSE);
- if (vip)
+ notify = message->get_notify(message, DPD_R_U_THERE);
+ if (notify)
{
- m = ha_message_create(HA_IKE_UPDATE);
- m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
- m->add_attribute(m, HA_REMOTE_VIP, vip);
- this->socket->push(this->socket, m);
- this->cache->cache(this->cache, ike_sa, m);
+ data = notify->get_notification_data(notify);
+ if (data.len == 4)
+ {
+ seq = untoh32(data.ptr);
+ if (incoming)
+ {
+ m = ha_message_create(HA_IKE_MID_RESPONDER);
+ }
+ else
+ {
+ m = ha_message_create(HA_IKE_MID_INITIATOR);
+ }
+ m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
+ m->add_attribute(m, HA_MID, seq + 1);
+ this->socket->push(this->socket, m);
+ this->cache->cache(this->cache, ike_sa, m);
+ }
}
}
return TRUE;
diff --git a/src/libcharon/plugins/ha/ha_kernel.c b/src/libcharon/plugins/ha/ha_kernel.c
index 2377a2630..c45339690 100644
--- a/src/libcharon/plugins/ha/ha_kernel.c
+++ b/src/libcharon/plugins/ha/ha_kernel.c
@@ -316,7 +316,8 @@ static void disable_all(private_ha_kernel_t *this)
{
while (enumerator->enumerate(enumerator, NULL, &file, NULL))
{
- if (chown(file, charon->uid, charon->gid) != 0)
+ if (chown(file, charon->caps->get_uid(charon->caps),
+ charon->caps->get_gid(charon->caps)) != 0)
{
DBG1(DBG_CFG, "changing ClusterIP permissions failed: %s",
strerror(errno));
diff --git a/src/libcharon/plugins/ha/ha_message.c b/src/libcharon/plugins/ha/ha_message.c
index 810109a5d..6b00ed83f 100644
--- a/src/libcharon/plugins/ha/ha_message.c
+++ b/src/libcharon/plugins/ha/ha_message.c
@@ -46,7 +46,7 @@ struct private_ha_message_t {
chunk_t buf;
};
-ENUM(ha_message_type_names, HA_IKE_ADD, HA_RESYNC,
+ENUM(ha_message_type_names, HA_IKE_ADD, HA_IKE_IV,
"IKE_ADD",
"IKE_UPDATE",
"IKE_MID_INITIATOR",
@@ -58,6 +58,7 @@ ENUM(ha_message_type_names, HA_IKE_ADD, HA_RESYNC,
"SEGMENT_TAKE",
"STATUS",
"RESYNC",
+ "IKE_IV",
);
typedef struct ike_sa_id_encoding_t ike_sa_id_encoding_t;
@@ -66,6 +67,7 @@ typedef struct ike_sa_id_encoding_t ike_sa_id_encoding_t;
* Encoding if an ike_sa_id_t
*/
struct ike_sa_id_encoding_t {
+ u_int8_t ike_version;
u_int64_t initiator_spi;
u_int64_t responder_spi;
u_int8_t initiator;
@@ -156,6 +158,7 @@ METHOD(ha_message_t, add_attribute, void,
enc = (ike_sa_id_encoding_t*)(this->buf.ptr + this->buf.len);
this->buf.len += sizeof(ike_sa_id_encoding_t);
enc->initiator = id->is_initiator(id);
+ enc->ike_version = id->get_ike_version(id);
enc->initiator_spi = id->get_initiator_spi(id);
enc->responder_spi = id->get_responder_spi(id);
break;
@@ -213,6 +216,7 @@ METHOD(ha_message_t, add_attribute, void,
break;
}
/* u_int8_t */
+ case HA_IKE_VERSION:
case HA_INITIATOR:
case HA_IPSEC_MODE:
case HA_IPCOMP:
@@ -263,6 +267,10 @@ METHOD(ha_message_t, add_attribute, void,
case HA_NONCE_I:
case HA_NONCE_R:
case HA_SECRET:
+ case HA_LOCAL_DH:
+ case HA_REMOTE_DH:
+ case HA_PSK:
+ case HA_IV:
case HA_OLD_SKD:
{
chunk_t chunk;
@@ -351,8 +359,9 @@ METHOD(enumerator_t, attribute_enumerate, bool,
return FALSE;
}
enc = (ike_sa_id_encoding_t*)(this->buf.ptr);
- value->ike_sa_id = ike_sa_id_create(enc->initiator_spi,
- enc->responder_spi, enc->initiator);
+ value->ike_sa_id = ike_sa_id_create(enc->ike_version,
+ enc->initiator_spi, enc->responder_spi,
+ enc->initiator);
*attr_out = attr;
this->cleanup = (void*)value->ike_sa_id->destroy;
this->cleanup_data = value->ike_sa_id;
@@ -426,6 +435,7 @@ METHOD(enumerator_t, attribute_enumerate, bool,
return TRUE;
}
/* u_int8_t */
+ case HA_IKE_VERSION:
case HA_INITIATOR:
case HA_IPSEC_MODE:
case HA_IPCOMP:
@@ -479,6 +489,10 @@ METHOD(enumerator_t, attribute_enumerate, bool,
case HA_NONCE_I:
case HA_NONCE_R:
case HA_SECRET:
+ case HA_LOCAL_DH:
+ case HA_REMOTE_DH:
+ case HA_PSK:
+ case HA_IV:
case HA_OLD_SKD:
{
size_t len;
diff --git a/src/libcharon/plugins/ha/ha_message.h b/src/libcharon/plugins/ha/ha_message.h
index d0323d7a0..8cd30f711 100644
--- a/src/libcharon/plugins/ha/ha_message.h
+++ b/src/libcharon/plugins/ha/ha_message.h
@@ -30,7 +30,7 @@
/**
* Protocol version of this implementation
*/
-#define HA_MESSAGE_VERSION 2
+#define HA_MESSAGE_VERSION 3
typedef struct ha_message_t ha_message_t;
typedef enum ha_message_type_t ha_message_type_t;
@@ -63,6 +63,8 @@ enum ha_message_type_t {
HA_STATUS,
/** segments the receiving node is requested to resync */
HA_RESYNC,
+ /** IV synchronization for IKEv1 Main/Aggressive mode */
+ HA_IKE_IV,
};
/**
@@ -76,7 +78,7 @@ extern enum_name_t *ha_message_type_names;
enum ha_message_attribute_t {
/** ike_sa_id_t*, to identify IKE_SA */
HA_IKE_ID = 1,
- /** ike_Sa_id_t*, identifies IKE_SA which gets rekeyed */
+ /** ike_sa_id_t*, identifies IKE_SA which gets rekeyed */
HA_IKE_REKEY_ID,
/** identification_t*, local identity */
HA_LOCAL_ID,
@@ -142,6 +144,16 @@ enum ha_message_attribute_t {
HA_SEGMENT,
/** u_int16_t, Extended Sequence numbers */
HA_ESN,
+ /** u_int8_t, IKE version */
+ HA_IKE_VERSION,
+ /** chunk_t, own DH public value */
+ HA_LOCAL_DH,
+ /** chunk_t, remote DH public value */
+ HA_REMOTE_DH,
+ /** chunk_t, shared secret for IKEv1 key derivation */
+ HA_PSK,
+ /** chunk_t, IV for next IKEv1 message */
+ HA_IV,
};
/**
diff --git a/src/libcharon/plugins/ha/ha_plugin.c b/src/libcharon/plugins/ha/ha_plugin.c
index b4bde5ea5..255eeafc0 100644
--- a/src/libcharon/plugins/ha/ha_plugin.c
+++ b/src/libcharon/plugins/ha/ha_plugin.c
@@ -128,19 +128,19 @@ plugin_t *ha_plugin_create()
bool fifo, monitor, resync;
local = lib->settings->get_str(lib->settings,
- "charon.plugins.ha.local", NULL);
+ "%s.plugins.ha.local", NULL, charon->name);
remote = lib->settings->get_str(lib->settings,
- "charon.plugins.ha.remote", NULL);
+ "%s.plugins.ha.remote", NULL, charon->name);
secret = lib->settings->get_str(lib->settings,
- "charon.plugins.ha.secret", NULL);
+ "%s.plugins.ha.secret", NULL, charon->name);
fifo = lib->settings->get_bool(lib->settings,
- "charon.plugins.ha.fifo_interface", TRUE);
+ "%s.plugins.ha.fifo_interface", TRUE, charon->name);
monitor = lib->settings->get_bool(lib->settings,
- "charon.plugins.ha.monitor", TRUE);
+ "%s.plugins.ha.monitor", TRUE, charon->name);
resync = lib->settings->get_bool(lib->settings,
- "charon.plugins.ha.resync", TRUE);
+ "%s.plugins.ha.resync", TRUE, charon->name);
count = min(SEGMENTS_MAX, lib->settings->get_int(lib->settings,
- "charon.plugins.ha.segment_count", 1));
+ "%s.plugins.ha.segment_count", 1, charon->name));
if (!local || !remote)
{
DBG1(DBG_CFG, "HA config misses local/remote address");
diff --git a/src/libcharon/plugins/ha/ha_segments.c b/src/libcharon/plugins/ha/ha_segments.c
index c5a180683..fb07809ef 100644
--- a/src/libcharon/plugins/ha/ha_segments.c
+++ b/src/libcharon/plugins/ha/ha_segments.c
@@ -62,11 +62,6 @@ struct private_ha_segments_t {
condvar_t *condvar;
/**
- * Job checking for heartbeats
- */
- callback_job_t *job;
-
- /**
* Total number of ClusterIP segments
*/
u_int count;
@@ -82,6 +77,11 @@ struct private_ha_segments_t {
u_int node;
/**
+ * Are we checking for heartbeats?
+ */
+ bool heartbeat_active;
+
+ /**
* Interval we send hearbeats
*/
int heartbeat_delay;
@@ -237,7 +237,7 @@ METHOD(listener_t, alert_hook, bool,
{
if (alert == ALERT_SHUTDOWN_SIGNAL)
{
- if (this->job)
+ if (this->heartbeat_active)
{
DBG1(DBG_CFG, "HA heartbeat active, dropping all segments");
deactivate(this, 0, TRUE);
@@ -269,7 +269,7 @@ static job_requeue_t watchdog(private_ha_segments_t *this)
DBG1(DBG_CFG, "no heartbeat received, taking all segments");
activate(this, 0, TRUE);
/* disable heartbeat detection util we get one */
- this->job = NULL;
+ this->heartbeat_active = FALSE;
return JOB_REQUEUE_NONE;
}
return JOB_REQUEUE_DIRECT;
@@ -280,9 +280,10 @@ static job_requeue_t watchdog(private_ha_segments_t *this)
*/
static void start_watchdog(private_ha_segments_t *this)
{
- this->job = callback_job_create_with_prio((callback_job_cb_t)watchdog,
- this, NULL, NULL, JOB_PRIO_CRITICAL);
- lib->processor->queue_job(lib->processor, (job_t*)this->job);
+ this->heartbeat_active = TRUE;
+ lib->processor->queue_job(lib->processor,
+ (job_t*)callback_job_create_with_prio((callback_job_cb_t)watchdog, this,
+ NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
}
METHOD(ha_segments_t, handle_status, void,
@@ -312,10 +313,10 @@ METHOD(ha_segments_t, handle_status, void,
}
}
- this->mutex->unlock(this->mutex);
this->condvar->signal(this->condvar);
+ this->mutex->unlock(this->mutex);
- if (!this->job)
+ if (!this->heartbeat_active)
{
DBG1(DBG_CFG, "received heartbeat, reenabling watchdog");
start_watchdog(this);
@@ -344,12 +345,7 @@ static job_requeue_t send_status(private_ha_segments_t *this)
message->destroy(message);
/* schedule next invocation */
- lib->scheduler->schedule_job_ms(lib->scheduler, (job_t*)
- callback_job_create((callback_job_cb_t)
- send_status, this, NULL, NULL),
- this->heartbeat_delay);
-
- return JOB_REQUEUE_NONE;
+ return JOB_RESCHEDULE_MS(this->heartbeat_delay);
}
METHOD(ha_segments_t, is_active, bool,
@@ -361,10 +357,6 @@ METHOD(ha_segments_t, is_active, bool,
METHOD(ha_segments_t, destroy, void,
private_ha_segments_t *this)
{
- if (this->job)
- {
- this->job->cancel(this->job);
- }
this->mutex->destroy(this->mutex);
this->condvar->destroy(this->condvar);
free(this);
@@ -398,9 +390,11 @@ ha_segments_t *ha_segments_create(ha_socket_t *socket, ha_kernel_t *kernel,
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
.condvar = condvar_create(CONDVAR_TYPE_DEFAULT),
.heartbeat_delay = lib->settings->get_int(lib->settings,
- "charon.plugins.ha.heartbeat_delay", DEFAULT_HEARTBEAT_DELAY),
+ "%s.plugins.ha.heartbeat_delay", DEFAULT_HEARTBEAT_DELAY,
+ charon->name),
.heartbeat_timeout = lib->settings->get_int(lib->settings,
- "charon.plugins.ha.heartbeat_timeout", DEFAULT_HEARTBEAT_TIMEOUT),
+ "%s.plugins.ha.heartbeat_timeout", DEFAULT_HEARTBEAT_TIMEOUT,
+ charon->name),
);
if (monitor)
diff --git a/src/libcharon/plugins/ha/ha_socket.c b/src/libcharon/plugins/ha/ha_socket.c
index c02cf1021..5196a5dc7 100644
--- a/src/libcharon/plugins/ha/ha_socket.c
+++ b/src/libcharon/plugins/ha/ha_socket.c
@@ -138,6 +138,7 @@ METHOD(ha_socket_t, pull, ha_message_t*,
DBG1(DBG_CFG, "pulling HA message failed: %s",
strerror(errno));
sleep(1);
+ continue;
}
}
message = ha_message_parse(chunk_create(buf, len));
diff --git a/src/libcharon/plugins/ha/ha_tunnel.c b/src/libcharon/plugins/ha/ha_tunnel.c
index 299053ec1..541dd9313 100644
--- a/src/libcharon/plugins/ha/ha_tunnel.c
+++ b/src/libcharon/plugins/ha/ha_tunnel.c
@@ -203,12 +203,13 @@ static void setup_tunnel(private_ha_tunnel_t *this,
lib->credmgr->add_set(lib->credmgr, &this->creds.public);
/* create config and backend */
- ike_cfg = ike_cfg_create(FALSE, FALSE, local, IKEV2_UDP_PORT,
- remote, IKEV2_UDP_PORT);
+ ike_cfg = ike_cfg_create(FALSE, FALSE, local, FALSE,
+ charon->socket->get_port(charon->socket, FALSE),
+ remote, FALSE, IKEV2_UDP_PORT);
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
- peer_cfg = peer_cfg_create("ha", 2, ike_cfg, CERT_NEVER_SEND,
- UNIQUE_KEEP, 0, 86400, 0, 7200, 3600, FALSE, 30,
- NULL, NULL, FALSE, NULL, NULL);
+ peer_cfg = peer_cfg_create("ha", IKEV2, ike_cfg, CERT_NEVER_SEND,
+ UNIQUE_KEEP, 0, 86400, 0, 7200, 3600, FALSE, FALSE, 30,
+ 0, FALSE, NULL, NULL);
auth_cfg = auth_cfg_create();
auth_cfg->add(auth_cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
diff --git a/src/libcharon/plugins/led/Makefile.in b/src/libcharon/plugins/led/Makefile.in
index 56684ee11..a78ca9701 100644
--- a/src/libcharon/plugins/led/Makefile.in
+++ b/src/libcharon/plugins/led/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -82,7 +83,7 @@ libstrongswan_led_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(libstrongswan_led_la_LDFLAGS) $(LDFLAGS) -o $@
@MONOLITHIC_FALSE@am_libstrongswan_led_la_rpath = -rpath $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_led_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -108,6 +109,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -202,11 +204,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -223,11 +228,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -243,6 +249,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -252,7 +259,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/led/led_listener.c b/src/libcharon/plugins/led/led_listener.c
index 4aae2abe5..be80bcde2 100644
--- a/src/libcharon/plugins/led/led_listener.c
+++ b/src/libcharon/plugins/led/led_listener.c
@@ -189,9 +189,9 @@ METHOD(listener_t, ike_state_change, bool,
METHOD(listener_t, message_hook, bool,
private_led_listener_t *this, ike_sa_t *ike_sa,
- message_t *message, bool incoming)
+ message_t *message, bool incoming, bool plain)
{
- if (incoming || message->get_request(message))
+ if (plain && (incoming || message->get_request(message)))
{
blink_activity(this);
}
@@ -230,11 +230,12 @@ led_listener_t *led_listener_create()
},
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
.blink_time = lib->settings->get_int(lib->settings,
- "charon.plugins.led.blink_time", 50),
+ "%s.plugins.led.blink_time", 50, charon->name),
);
this->activity = open_led(lib->settings->get_str(lib->settings,
- "charon.plugins.led.activity_led", NULL), &this->activity_max);
+ "%s.plugins.led.activity_led", NULL, charon->name),
+ &this->activity_max);
set_led(this->activity, 0);
return &this->public;
diff --git a/src/libcharon/plugins/load_tester/Makefile.in b/src/libcharon/plugins/load_tester/Makefile.in
index bbd20d4b9..cb11cff28 100644
--- a/src/libcharon/plugins/load_tester/Makefile.in
+++ b/src/libcharon/plugins/load_tester/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -88,7 +89,7 @@ libstrongswan_load_tester_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_load_tester_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_load_tester_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -114,6 +115,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -208,11 +210,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -229,11 +234,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -249,6 +255,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -258,7 +265,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/load_tester/load_tester_config.c b/src/libcharon/plugins/load_tester/load_tester_config.c
index 6bc6f91e4..735f17985 100644
--- a/src/libcharon/plugins/load_tester/load_tester_config.c
+++ b/src/libcharon/plugins/load_tester/load_tester_config.c
@@ -45,6 +45,11 @@ struct private_load_tester_config_t {
char *remote;
/**
+ * Local address
+ */
+ char *local;
+
+ /**
* IP address pool
*/
char *pool;
@@ -90,6 +95,11 @@ struct private_load_tester_config_t {
u_int dpd_delay;
/**
+ * DPD timeout (IKEv1 only)
+ */
+ u_int dpd_timeout;
+
+ /**
* incremental numbering of generated configs
*/
u_int num;
@@ -241,21 +251,32 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num)
if (this->port && num)
{
ike_cfg = ike_cfg_create(FALSE, FALSE,
- "0.0.0.0", this->port + num - 1, this->remote, IKEV2_NATT_PORT);
+ this->local, FALSE, this->port + num - 1,
+ this->remote, FALSE, IKEV2_NATT_PORT);
}
else
{
ike_cfg = ike_cfg_create(FALSE, FALSE,
- "0.0.0.0", IKEV2_UDP_PORT, this->remote, IKEV2_UDP_PORT);
+ this->local, FALSE, charon->socket->get_port(charon->socket, FALSE),
+ this->remote, FALSE, IKEV2_UDP_PORT);
}
ike_cfg->add_proposal(ike_cfg, this->proposal->clone(this->proposal));
- peer_cfg = peer_cfg_create("load-test", 2, ike_cfg,
+ peer_cfg = peer_cfg_create("load-test", IKEV2, ike_cfg,
CERT_SEND_IF_ASKED, UNIQUE_NO, 1, /* keytries */
this->ike_rekey, 0, /* rekey, reauth */
0, this->ike_rekey, /* jitter, overtime */
- FALSE, this->dpd_delay, /* mobike, dpddelay */
- this->vip ? this->vip->clone(this->vip) : NULL,
- this->pool, FALSE, NULL, NULL);
+ FALSE, FALSE, /* mobike, aggressive mode */
+ this->dpd_delay, /* dpd_delay */
+ this->dpd_timeout, /* dpd_timeout */
+ FALSE, NULL, NULL);
+ if (this->vip)
+ {
+ peer_cfg->add_virtual_ip(peer_cfg, this->vip->clone(this->vip));
+ }
+ if (this->pool)
+ {
+ peer_cfg->add_pool(peer_cfg, this->pool);
+ }
if (num)
{ /* initiator */
generate_auth_cfg(this, this->initiator_auth, peer_cfg, TRUE, num);
@@ -335,41 +356,46 @@ load_tester_config_t *load_tester_config_create()
);
if (lib->settings->get_bool(lib->settings,
- "charon.plugins.load-tester.request_virtual_ip", FALSE))
+ "%s.plugins.load-tester.request_virtual_ip", FALSE, charon->name))
{
this->vip = host_create_from_string("0.0.0.0", 0);
}
this->pool = lib->settings->get_str(lib->settings,
- "charon.plugins.load-tester.pool", NULL);
+ "%s.plugins.load-tester.pool", NULL, charon->name);
this->remote = lib->settings->get_str(lib->settings,
- "charon.plugins.load-tester.remote", "127.0.0.1");
+ "%s.plugins.load-tester.remote", "127.0.0.1", charon->name);
+ this->local = lib->settings->get_str(lib->settings,
+ "%s.plugins.load-tester.local", "0.0.0.0", charon->name);
this->proposal = proposal_create_from_string(PROTO_IKE,
- lib->settings->get_str(lib->settings,
- "charon.plugins.load-tester.proposal", "aes128-sha1-modp768"));
+ lib->settings->get_str(lib->settings,
+ "%s.plugins.load-tester.proposal", "aes128-sha1-modp768",
+ charon->name));
if (!this->proposal)
{ /* fallback */
this->proposal = proposal_create_from_string(PROTO_IKE,
"aes128-sha1-modp768");
}
this->ike_rekey = lib->settings->get_int(lib->settings,
- "charon.plugins.load-tester.ike_rekey", 0);
+ "%s.plugins.load-tester.ike_rekey", 0, charon->name);
this->child_rekey = lib->settings->get_int(lib->settings,
- "charon.plugins.load-tester.child_rekey", 600);
+ "%s.plugins.load-tester.child_rekey", 600, charon->name);
this->dpd_delay = lib->settings->get_int(lib->settings,
- "charon.plugins.load-tester.dpd_delay", 0);
+ "%s.plugins.load-tester.dpd_delay", 0, charon->name);
+ this->dpd_timeout = lib->settings->get_int(lib->settings,
+ "%s.plugins.load-tester.dpd_timeout", 0, charon->name);
this->initiator_auth = lib->settings->get_str(lib->settings,
- "charon.plugins.load-tester.initiator_auth", "pubkey");
+ "%s.plugins.load-tester.initiator_auth", "pubkey", charon->name);
this->responder_auth = lib->settings->get_str(lib->settings,
- "charon.plugins.load-tester.responder_auth", "pubkey");
+ "%s.plugins.load-tester.responder_auth", "pubkey", charon->name);
this->initiator_id = lib->settings->get_str(lib->settings,
- "charon.plugins.load-tester.initiator_id", NULL);
+ "%s.plugins.load-tester.initiator_id", NULL, charon->name);
this->responder_id = lib->settings->get_str(lib->settings,
- "charon.plugins.load-tester.responder_id", NULL);
+ "%s.plugins.load-tester.responder_id", NULL, charon->name);
this->port = lib->settings->get_int(lib->settings,
- "charon.plugins.load-tester.dynamic_port", 0);
+ "%s.plugins.load-tester.dynamic_port", 0, charon->name);
this->peer_cfg = generate_config(this, 0);
diff --git a/src/libcharon/plugins/load_tester/load_tester_creds.c b/src/libcharon/plugins/load_tester/load_tester_creds.c
index c34ea73c5..6d3b6933d 100644
--- a/src/libcharon/plugins/load_tester/load_tester_creds.c
+++ b/src/libcharon/plugins/load_tester/load_tester_creds.c
@@ -321,9 +321,9 @@ load_tester_creds_t *load_tester_creds_create()
char *pwd, *psk;
psk = lib->settings->get_str(lib->settings,
- "charon.plugins.load-tester.preshared_key", default_psk);
+ "%s.plugins.load-tester.preshared_key", default_psk, charon->name);
pwd = lib->settings->get_str(lib->settings,
- "charon.plugins.load-tester.eap_password", default_pwd);
+ "%s.plugins.load-tester.eap_password", default_pwd, charon->name);
INIT(this,
.public = {
diff --git a/src/libcharon/plugins/load_tester/load_tester_ipsec.c b/src/libcharon/plugins/load_tester/load_tester_ipsec.c
index 440197260..ded6b2d20 100644
--- a/src/libcharon/plugins/load_tester/load_tester_ipsec.c
+++ b/src/libcharon/plugins/load_tester/load_tester_ipsec.c
@@ -108,12 +108,6 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
return SUCCESS;
}
-METHOD(kernel_ipsec_t, bypass_socket, bool,
- private_load_tester_ipsec_t *this, int fd, int family)
-{
- return TRUE;
-}
-
METHOD(kernel_ipsec_t, destroy, void,
private_load_tester_ipsec_t *this)
{
@@ -141,7 +135,8 @@ load_tester_ipsec_t *load_tester_ipsec_create()
.query_policy = _query_policy,
.del_policy = _del_policy,
.flush_policies = (void*)return_failed,
- .bypass_socket = _bypass_socket,
+ .bypass_socket = (void*)return_true,
+ .enable_udp_decap = (void*)return_true,
.destroy = _destroy,
},
},
diff --git a/src/libcharon/plugins/load_tester/load_tester_listener.c b/src/libcharon/plugins/load_tester/load_tester_listener.c
index 7c96f7d97..92073e62c 100644
--- a/src/libcharon/plugins/load_tester/load_tester_listener.c
+++ b/src/libcharon/plugins/load_tester/load_tester_listener.c
@@ -108,7 +108,8 @@ load_tester_listener_t *load_tester_listener_create(u_int shutdown_on)
.destroy = _destroy,
},
.delete_after_established = lib->settings->get_bool(lib->settings,
- "charon.plugins.load-tester.delete_after_established", FALSE),
+ "%s.plugins.load-tester.delete_after_established", FALSE,
+ charon->name),
.shutdown_on = shutdown_on,
);
diff --git a/src/libcharon/plugins/load_tester/load_tester_plugin.c b/src/libcharon/plugins/load_tester/load_tester_plugin.c
index b260a9741..4a982d4b7 100644
--- a/src/libcharon/plugins/load_tester/load_tester_plugin.c
+++ b/src/libcharon/plugins/load_tester/load_tester_plugin.c
@@ -28,8 +28,6 @@
#include <threading/condvar.h>
#include <threading/mutex.h>
-static const char *plugin_name = "load_tester";
-
typedef struct private_load_tester_plugin_t private_load_tester_plugin_t;
/**
@@ -171,26 +169,78 @@ METHOD(plugin_t, get_name, char*,
return "load-tester";
}
-METHOD(plugin_t, destroy, void,
- private_load_tester_plugin_t *this)
+/**
+ * Register load_tester plugin features
+ */
+static bool register_load_tester(private_load_tester_plugin_t *this,
+ plugin_feature_t *feature, bool reg, void *data)
{
- this->iterations = -1;
- this->mutex->lock(this->mutex);
- while (this->running)
+ if (reg)
{
- this->condvar->wait(this->condvar, this->mutex);
+ u_int i, shutdown_on = 0;
+
+ this->config = load_tester_config_create();
+ this->creds = load_tester_creds_create();
+
+ charon->backends->add_backend(charon->backends, &this->config->backend);
+ lib->credmgr->add_set(lib->credmgr, &this->creds->credential_set);
+
+ if (lib->settings->get_bool(lib->settings,
+ "%s.plugins.load-tester.shutdown_when_complete", 0, charon->name))
+ {
+ shutdown_on = this->iterations * this->initiators;
+ }
+ this->listener = load_tester_listener_create(shutdown_on);
+ charon->bus->add_listener(charon->bus, &this->listener->listener);
+
+ for (i = 0; i < this->initiators; i++)
+ {
+ lib->processor->queue_job(lib->processor, (job_t*)
+ callback_job_create_with_prio((callback_job_cb_t)do_load_test,
+ this, NULL, NULL, JOB_PRIO_CRITICAL));
+ }
}
- this->mutex->unlock(this->mutex);
+ else
+ {
+ this->iterations = -1;
+ this->mutex->lock(this->mutex);
+ while (this->running)
+ {
+ this->condvar->wait(this->condvar, this->mutex);
+ }
+ this->mutex->unlock(this->mutex);
+ charon->backends->remove_backend(charon->backends, &this->config->backend);
+ lib->credmgr->remove_set(lib->credmgr, &this->creds->credential_set);
+ charon->bus->remove_listener(charon->bus, &this->listener->listener);
+ this->config->destroy(this->config);
+ this->creds->destroy(this->creds);
+ this->listener->destroy(this->listener);
+ }
+ return TRUE;
+}
+
+METHOD(plugin_t, get_features, int,
+ private_load_tester_plugin_t *this, plugin_feature_t *features[])
+{
+ static plugin_feature_t f[] = {
+ PLUGIN_REGISTER(DH, load_tester_diffie_hellman_create),
+ PLUGIN_PROVIDE(DH, MODP_NULL),
+ PLUGIN_DEPENDS(CUSTOM, "load-tester"),
+ PLUGIN_CALLBACK((plugin_feature_callback_t)register_load_tester, NULL),
+ PLUGIN_PROVIDE(CUSTOM, "load-tester"),
+ PLUGIN_SDEPEND(PRIVKEY, KEY_RSA),
+ PLUGIN_SDEPEND(CERT_DECODE, CERT_ANY),
+ PLUGIN_SDEPEND(CERT_DECODE, CERT_X509),
+ };
+ *features = f;
+ return countof(f);
+}
+
+METHOD(plugin_t, destroy, void,
+ private_load_tester_plugin_t *this)
+{
hydra->kernel_interface->remove_ipsec_interface(hydra->kernel_interface,
(kernel_ipsec_constructor_t)load_tester_ipsec_create);
- charon->backends->remove_backend(charon->backends, &this->config->backend);
- lib->credmgr->remove_set(lib->credmgr, &this->creds->credential_set);
- charon->bus->remove_listener(charon->bus, &this->listener->listener);
- this->config->destroy(this->config);
- this->creds->destroy(this->creds);
- this->listener->destroy(this->listener);
- lib->crypto->remove_dh(lib->crypto,
- (dh_constructor_t)load_tester_diffie_hellman_create);
this->mutex->destroy(this->mutex);
this->condvar->destroy(this->condvar);
free(this);
@@ -202,10 +252,9 @@ METHOD(plugin_t, destroy, void,
plugin_t *load_tester_plugin_create()
{
private_load_tester_plugin_t *this;
- u_int i, shutdown_on = 0;
if (!lib->settings->get_bool(lib->settings,
- "charon.plugins.load-tester.enable", FALSE))
+ "%s.plugins.load-tester.enable", FALSE, charon->name))
{
DBG1(DBG_CFG, "disabling load-tester plugin, not configured");
return NULL;
@@ -215,49 +264,29 @@ plugin_t *load_tester_plugin_create()
.public = {
.plugin = {
.get_name = _get_name,
+ .get_features = _get_features,
.reload = (void*)return_false,
.destroy = _destroy,
},
},
.delay = lib->settings->get_int(lib->settings,
- "charon.plugins.load-tester.delay", 0),
+ "%s.plugins.load-tester.delay", 0, charon->name),
.iterations = lib->settings->get_int(lib->settings,
- "charon.plugins.load-tester.iterations", 1),
+ "%s.plugins.load-tester.iterations", 1, charon->name),
.initiators = lib->settings->get_int(lib->settings,
- "charon.plugins.load-tester.initiators", 0),
+ "%s.plugins.load-tester.initiators", 0, charon->name),
.init_limit = lib->settings->get_int(lib->settings,
- "charon.plugins.load-tester.init_limit", 0),
+ "%s.plugins.load-tester.init_limit", 0, charon->name),
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
.condvar = condvar_create(CONDVAR_TYPE_DEFAULT),
- .config = load_tester_config_create(),
- .creds = load_tester_creds_create(),
);
- lib->crypto->add_dh(lib->crypto, MODP_NULL, plugin_name,
- (dh_constructor_t)load_tester_diffie_hellman_create);
- charon->backends->add_backend(charon->backends, &this->config->backend);
- lib->credmgr->add_set(lib->credmgr, &this->creds->credential_set);
-
- if (lib->settings->get_bool(lib->settings,
- "charon.plugins.load-tester.shutdown_when_complete", 0))
- {
- shutdown_on = this->iterations * this->initiators;
- }
- this->listener = load_tester_listener_create(shutdown_on);
- charon->bus->add_listener(charon->bus, &this->listener->listener);
-
if (lib->settings->get_bool(lib->settings,
- "charon.plugins.load-tester.fake_kernel", FALSE))
+ "%s.plugins.load-tester.fake_kernel", FALSE, charon->name))
{
hydra->kernel_interface->add_ipsec_interface(hydra->kernel_interface,
(kernel_ipsec_constructor_t)load_tester_ipsec_create);
}
- for (i = 0; i < this->initiators; i++)
- {
- lib->processor->queue_job(lib->processor, (job_t*)
- callback_job_create_with_prio((callback_job_cb_t)do_load_test,
- this, NULL, NULL, JOB_PRIO_CRITICAL));
- }
return &this->public.plugin;
}
diff --git a/src/libcharon/plugins/maemo/Makefile.in b/src/libcharon/plugins/maemo/Makefile.in
index d2b9d9a34..dfcd1f6ef 100644
--- a/src/libcharon/plugins/maemo/Makefile.in
+++ b/src/libcharon/plugins/maemo/Makefile.in
@@ -50,6 +50,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -86,7 +87,7 @@ libstrongswan_maemo_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@MONOLITHIC_FALSE@am_libstrongswan_maemo_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_maemo_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -113,6 +114,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -207,11 +209,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -228,11 +233,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -248,6 +254,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -257,7 +264,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/maemo/maemo_service.c b/src/libcharon/plugins/maemo/maemo_service.c
index 6675e1d21..cb2fc9ebb 100644
--- a/src/libcharon/plugins/maemo/maemo_service.c
+++ b/src/libcharon/plugins/maemo/maemo_service.c
@@ -323,17 +323,20 @@ static gboolean initiate_connection(private_maemo_service_t *this,
NULL);
}
- ike_cfg = ike_cfg_create(TRUE, FALSE, "0.0.0.0", IKEV2_UDP_PORT,
- hostname, IKEV2_UDP_PORT);
+ ike_cfg = ike_cfg_create(TRUE, FALSE, "0.0.0.0", FALSE,
+ charon->socket->get_port(charon->socket, FALSE),
+ hostname, FALSE, IKEV2_UDP_PORT);
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
- peer_cfg = peer_cfg_create(this->current, 2, ike_cfg, CERT_SEND_IF_ASKED,
+ peer_cfg = peer_cfg_create(this->current, IKEV2, ike_cfg,
+ CERT_SEND_IF_ASKED,
UNIQUE_REPLACE, 1, /* keyingtries */
36000, 0, /* rekey 10h, reauth none */
600, 600, /* jitter, over 10min */
- TRUE, 0, /* mobike, DPD */
- host_create_from_string("0.0.0.0", 0) /* virt */,
- NULL, FALSE, NULL, NULL); /* pool, mediation */
+ TRUE, FALSE, /* mobike, aggressive */
+ 0, 0, /* DPD delay, timeout */
+ FALSE, NULL, NULL); /* mediation */
+ peer_cfg->add_virtual_ip(peer_cfg, host_create_from_string("0.0.0.0", 0));
auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
@@ -354,12 +357,16 @@ static gboolean initiate_connection(private_maemo_service_t *this,
0, "255.255.255.255", 65535);
child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
peer_cfg->add_child_cfg(peer_cfg, child_cfg);
- /* get an additional reference because initiate consumes one */
- child_cfg->get_ref(child_cfg);
/* get us an IKE_SA */
ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
peer_cfg);
+ if (!ike_sa)
+ {
+ peer_cfg->destroy(peer_cfg);
+ this->status = VPN_STATUS_CONNECTION_FAILED;
+ return FALSE;
+ }
if (!ike_sa->get_peer_cfg(ike_sa))
{
ike_sa->set_peer_cfg(ike_sa, peer_cfg);
@@ -373,6 +380,8 @@ static gboolean initiate_connection(private_maemo_service_t *this,
this->public.listener.ike_state_change = _ike_state_change;
charon->bus->add_listener(charon->bus, &this->public.listener);
+ /* get an additional reference because initiate consumes one */
+ child_cfg->get_ref(child_cfg);
if (ike_sa->initiate(ike_sa, child_cfg, 0, NULL, NULL) != SUCCESS)
{
DBG1(DBG_CFG, "failed to initiate tunnel");
@@ -423,8 +432,10 @@ static job_requeue_t run(private_maemo_service_t *this)
return JOB_REQUEUE_NONE;
}
-METHOD(maemo_service_t, destroy, void,
- private_maemo_service_t *this)
+/**
+ * Cancel the GLib Main Event Loop
+ */
+static bool cancel(private_maemo_service_t *this)
{
if (this->loop)
{
@@ -434,6 +445,12 @@ METHOD(maemo_service_t, destroy, void,
}
g_main_loop_unref(this->loop);
}
+ return TRUE;
+}
+
+METHOD(maemo_service_t, destroy, void,
+ private_maemo_service_t *this)
+{
if (this->context)
{
osso_rpc_unset_cb_f(this->context,
@@ -502,8 +519,8 @@ maemo_service_t *maemo_service_create()
}
lib->processor->queue_job(lib->processor,
- (job_t*)callback_job_create_with_prio((callback_job_cb_t)run,
- this, NULL, NULL, JOB_PRIO_CRITICAL));
+ (job_t*)callback_job_create_with_prio((callback_job_cb_t)run, this,
+ NULL, (callback_job_cancel_t)cancel, JOB_PRIO_CRITICAL));
return &this->public;
}
diff --git a/src/libcharon/plugins/medcli/Makefile.in b/src/libcharon/plugins/medcli/Makefile.in
index b8983ad21..359533a60 100644
--- a/src/libcharon/plugins/medcli/Makefile.in
+++ b/src/libcharon/plugins/medcli/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -85,7 +86,7 @@ libstrongswan_medcli_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@MONOLITHIC_FALSE@am_libstrongswan_medcli_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_medcli_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -111,6 +112,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -205,11 +207,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -226,11 +231,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -246,6 +252,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -255,7 +262,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/medcli/medcli_config.c b/src/libcharon/plugins/medcli/medcli_config.c
index ee3e95422..a1825effc 100644
--- a/src/libcharon/plugins/medcli/medcli_config.c
+++ b/src/libcharon/plugins/medcli/medcli_config.c
@@ -119,15 +119,16 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
return NULL;
}
ike_cfg = ike_cfg_create(FALSE, FALSE,
- "0.0.0.0", IKEV2_UDP_PORT, address, IKEV2_UDP_PORT);
+ "0.0.0.0", FALSE, charon->socket->get_port(charon->socket, FALSE),
+ address, FALSE, IKEV2_UDP_PORT);
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
med_cfg = peer_cfg_create(
- "mediation", 2, ike_cfg,
+ "mediation", IKEV2, ike_cfg,
CERT_NEVER_SEND, UNIQUE_REPLACE,
1, this->rekey*60, 0, /* keytries, rekey, reauth */
this->rekey*5, this->rekey*3, /* jitter, overtime */
- TRUE, this->dpd, /* mobike, dpddelay */
- NULL, NULL, /* vip, pool */
+ TRUE, FALSE, /* mobike, aggressive */
+ this->dpd, 0, /* DPD delay, timeout */
TRUE, NULL, NULL); /* mediation, med by, peer id */
e->destroy(e);
@@ -159,12 +160,12 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
return NULL;
}
peer_cfg = peer_cfg_create(
- name, 2, this->ike->get_ref(this->ike),
+ name, IKEV2, this->ike->get_ref(this->ike),
CERT_NEVER_SEND, UNIQUE_REPLACE,
1, this->rekey*60, 0, /* keytries, rekey, reauth */
this->rekey*5, this->rekey*3, /* jitter, overtime */
- TRUE, this->dpd, /* mobike, dpddelay */
- NULL, NULL, /* vip, pool */
+ TRUE, FALSE, /* mobike, aggressive */
+ this->dpd, 0, /* DPD delay, timeout */
FALSE, med_cfg, /* mediation, med by */
identification_create_from_encoding(ID_KEY_ID, other));
@@ -234,12 +235,12 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool,
return FALSE;
}
this->current = peer_cfg_create(
- name, 2, this->ike->get_ref(this->ike),
+ name, IKEV2, this->ike->get_ref(this->ike),
CERT_NEVER_SEND, UNIQUE_REPLACE,
1, this->rekey*60, 0, /* keytries, rekey, reauth */
this->rekey*5, this->rekey*3, /* jitter, overtime */
- TRUE, this->dpd, /* mobike, dpddelay */
- NULL, NULL, /* vip, pool */
+ TRUE, FALSE, /* mobike, aggressive */
+ this->dpd, 0, /* DPD delay, timeout */
FALSE, NULL, NULL); /* mediation, med by, peer id */
auth = auth_cfg_create();
@@ -391,8 +392,9 @@ medcli_config_t *medcli_config_create(database_t *db)
.db = db,
.rekey = lib->settings->get_time(lib->settings, "medcli.rekey", 1200),
.dpd = lib->settings->get_time(lib->settings, "medcli.dpd", 300),
- .ike = ike_cfg_create(FALSE, FALSE, "0.0.0.0", IKEV2_UDP_PORT,
- "0.0.0.0", IKEV2_UDP_PORT),
+ .ike = ike_cfg_create(FALSE, FALSE,
+ "0.0.0.0", FALSE, charon->socket->get_port(charon->socket, FALSE),
+ "0.0.0.0", FALSE, IKEV2_UDP_PORT),
);
this->ike->add_proposal(this->ike, proposal_create_default(PROTO_IKE));
diff --git a/src/libcharon/plugins/medsrv/Makefile.in b/src/libcharon/plugins/medsrv/Makefile.in
index 91df95cf0..ba27b8570 100644
--- a/src/libcharon/plugins/medsrv/Makefile.in
+++ b/src/libcharon/plugins/medsrv/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -85,7 +86,7 @@ libstrongswan_medsrv_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@MONOLITHIC_FALSE@am_libstrongswan_medsrv_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_medsrv_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -111,6 +112,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -205,11 +207,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -226,11 +231,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -246,6 +252,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -255,7 +262,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/medsrv/medsrv_config.c b/src/libcharon/plugins/medsrv/medsrv_config.c
index 6cacb34f6..ff33c53e1 100644
--- a/src/libcharon/plugins/medsrv/medsrv_config.c
+++ b/src/libcharon/plugins/medsrv/medsrv_config.c
@@ -88,12 +88,12 @@ METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
if (e->enumerate(e, &name))
{
peer_cfg = peer_cfg_create(
- name, 2, this->ike->get_ref(this->ike),
+ name, IKEV2, this->ike->get_ref(this->ike),
CERT_NEVER_SEND, UNIQUE_REPLACE,
1, this->rekey*60, 0, /* keytries, rekey, reauth */
this->rekey*5, this->rekey*3, /* jitter, overtime */
- TRUE, this->dpd, /* mobike, dpddelay */
- NULL, NULL, /* vip, pool */
+ TRUE, FALSE, /* mobike, aggressiv */
+ this->dpd, 0, /* DPD delay, timeout */
TRUE, NULL, NULL); /* mediation, med by, peer id */
e->destroy(e);
@@ -140,7 +140,8 @@ medsrv_config_t *medsrv_config_create(database_t *db)
.rekey = lib->settings->get_time(lib->settings, "medsrv.rekey", 1200),
.dpd = lib->settings->get_time(lib->settings, "medsrv.dpd", 300),
.ike = ike_cfg_create(FALSE, FALSE,
- "0.0.0.0", IKEV2_UDP_PORT, "0.0.0.0", IKEV2_UDP_PORT),
+ "0.0.0.0", FALSE, charon->socket->get_port(charon->socket, FALSE),
+ "0.0.0.0", FALSE, IKEV2_UDP_PORT),
);
this->ike->add_proposal(this->ike, proposal_create_default(PROTO_IKE));
diff --git a/src/libcharon/plugins/nm/Makefile.am b/src/libcharon/plugins/nm/Makefile.am
deleted file mode 100644
index 8e12a72be..000000000
--- a/src/libcharon/plugins/nm/Makefile.am
+++ /dev/null
@@ -1,21 +0,0 @@
-
-INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
- -I$(top_srcdir)/src/libcharon ${nm_CFLAGS}
-
-AM_CFLAGS = -rdynamic \
- -DNM_CA_DIR=\"${nm_ca_dir}\"
-
-if MONOLITHIC
-noinst_LTLIBRARIES = libstrongswan-nm.la
-else
-plugin_LTLIBRARIES = libstrongswan-nm.la
-endif
-
-libstrongswan_nm_la_SOURCES = \
- nm_plugin.h nm_plugin.c \
- nm_service.h nm_service.c \
- nm_creds.h nm_creds.c \
- nm_handler.h nm_handler.c
-
-libstrongswan_nm_la_LDFLAGS = -module -avoid-version
-libstrongswan_nm_la_LIBADD = ${nm_LIBS}
diff --git a/src/libcharon/plugins/radattr/Makefile.in b/src/libcharon/plugins/radattr/Makefile.in
index ecea0df16..32bdad00c 100644
--- a/src/libcharon/plugins/radattr/Makefile.in
+++ b/src/libcharon/plugins/radattr/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -86,7 +87,7 @@ libstrongswan_radattr_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@MONOLITHIC_FALSE@am_libstrongswan_radattr_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_radattr_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -112,6 +113,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -206,11 +208,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -227,11 +232,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -247,6 +253,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -256,7 +263,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/radattr/radattr_listener.c b/src/libcharon/plugins/radattr/radattr_listener.c
index 94b718a1b..5443800e5 100644
--- a/src/libcharon/plugins/radattr/radattr_listener.c
+++ b/src/libcharon/plugins/radattr/radattr_listener.c
@@ -172,9 +172,9 @@ static void add_radius_attribute(private_radattr_listener_t *this,
METHOD(listener_t, message, bool,
private_radattr_listener_t *this,
- ike_sa_t *ike_sa, message_t *message, bool incoming)
+ ike_sa_t *ike_sa, message_t *message, bool incoming, bool plain)
{
- if (ike_sa->supports_extension(ike_sa, EXT_STRONGSWAN) &&
+ if (plain && ike_sa->supports_extension(ike_sa, EXT_STRONGSWAN) &&
message->get_exchange_type(message) == IKE_AUTH &&
message->get_payload(message, EXTENSIBLE_AUTHENTICATION))
{
@@ -212,9 +212,9 @@ radattr_listener_t *radattr_listener_create()
.destroy = _destroy,
},
.dir = lib->settings->get_str(lib->settings,
- "charon.plugins.radattr.dir", NULL),
+ "%s.plugins.radattr.dir", NULL, charon->name),
.mid = lib->settings->get_int(lib->settings,
- "charon.plugins.radattr.message_id", -1),
+ "%s.plugins.radattr.message_id", -1, charon->name),
);
return &this->public;
diff --git a/src/libcharon/plugins/smp/Makefile.in b/src/libcharon/plugins/smp/Makefile.in
index 59a560b86..19cb7987b 100644
--- a/src/libcharon/plugins/smp/Makefile.in
+++ b/src/libcharon/plugins/smp/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -83,7 +84,7 @@ libstrongswan_smp_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(libstrongswan_smp_la_LDFLAGS) $(LDFLAGS) -o $@
@MONOLITHIC_FALSE@am_libstrongswan_smp_la_rpath = -rpath $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_smp_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -109,6 +110,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -203,11 +205,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -224,11 +229,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -244,6 +250,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -253,7 +260,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/smp/smp.c b/src/libcharon/plugins/smp/smp.c
index 2b830012d..db5295230 100644
--- a/src/libcharon/plugins/smp/smp.c
+++ b/src/libcharon/plugins/smp/smp.c
@@ -49,11 +49,6 @@ struct private_smp_t {
* XML unix socket fd
*/
int socket;
-
- /**
- * job accepting stroke messages
- */
- callback_job_t *job;
};
ENUM(ike_sa_state_lower_names, IKE_CREATED, IKE_DELETING,
@@ -168,7 +163,7 @@ static void write_childend(xmlTextWriterPtr writer, child_sa_t *child, bool loca
{
linked_list_t *list;
- xmlTextWriterWriteFormatElement(writer, "spi", "%lx",
+ xmlTextWriterWriteFormatElement(writer, "spi", "%x",
htonl(child->get_spi(child, local)));
list = child->get_traffic_selectors(child, local);
write_networks(writer, "networks", list);
@@ -294,7 +289,7 @@ static void request_query_config(xmlTextReaderPtr reader, xmlTextWriterPtr write
xmlTextWriterStartElement(writer, "configlist");
enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
- NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL, IKE_ANY);
while (enumerator->enumerate(enumerator, &peer_cfg))
{
enumerator_t *children;
@@ -302,11 +297,6 @@ static void request_query_config(xmlTextReaderPtr reader, xmlTextWriterPtr write
ike_cfg_t *ike_cfg;
linked_list_t *list;
- if (peer_cfg->get_ike_version(peer_cfg) != 2)
- { /* only IKEv2 connections yet */
- continue;
- }
-
/* <peerconfig> */
xmlTextWriterStartElement(writer, "peerconfig");
xmlTextWriterWriteElement(writer, "name", peer_cfg->get_name(peer_cfg));
@@ -316,8 +306,10 @@ static void request_query_config(xmlTextReaderPtr reader, xmlTextWriterPtr write
/* <ikeconfig> */
ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
xmlTextWriterStartElement(writer, "ikeconfig");
- xmlTextWriterWriteElement(writer, "local", ike_cfg->get_my_addr(ike_cfg));
- xmlTextWriterWriteElement(writer, "remote", ike_cfg->get_other_addr(ike_cfg));
+ xmlTextWriterWriteElement(writer, "local",
+ ike_cfg->get_my_addr(ike_cfg, NULL));
+ xmlTextWriterWriteElement(writer, "remote",
+ ike_cfg->get_other_addr(ike_cfg, NULL));
xmlTextWriterEndElement(writer);
/* </ikeconfig> */
@@ -354,7 +346,7 @@ static void request_query_config(xmlTextReaderPtr reader, xmlTextWriterPtr write
* callback which logs to a XML writer
*/
static bool xml_callback(xmlTextWriterPtr writer, debug_t group, level_t level,
- ike_sa_t* ike_sa, char* format, va_list args)
+ ike_sa_t* ike_sa, char* message)
{
if (level <= 1)
{
@@ -363,7 +355,7 @@ static bool xml_callback(xmlTextWriterPtr writer, debug_t group, level_t level,
xmlTextWriterWriteFormatAttribute(writer, "level", "%d", level);
xmlTextWriterWriteFormatAttribute(writer, "source", "%N", debug_names, group);
xmlTextWriterWriteFormatAttribute(writer, "thread", "%u", thread_current_id());
- xmlTextWriterWriteVFormatString(writer, format, args);
+ xmlTextWriterWriteString(writer, message);
xmlTextWriterEndElement(writer);
/* </item> */
}
@@ -707,7 +699,8 @@ static job_requeue_t dispatch(private_smp_t *this)
fdp = malloc_thing(int);
*fdp = fd;
- job = callback_job_create((callback_job_cb_t)process, fdp, free, this->job);
+ job = callback_job_create((callback_job_cb_t)process, fdp, free,
+ (callback_job_cancel_t)return_false);
lib->processor->queue_job(lib->processor, (job_t*)job);
return JOB_REQUEUE_DIRECT;
@@ -722,7 +715,6 @@ METHOD(plugin_t, get_name, char*,
METHOD(plugin_t, destroy, void,
private_smp_t *this)
{
- this->job->cancel(this->job);
close(this->socket);
free(this);
}
@@ -765,7 +757,8 @@ plugin_t *smp_plugin_create()
return NULL;
}
umask(old);
- if (chown(unix_addr.sun_path, charon->uid, charon->gid) != 0)
+ if (chown(unix_addr.sun_path, charon->caps->get_uid(charon->caps),
+ charon->caps->get_gid(charon->caps)) != 0)
{
DBG1(DBG_CFG, "changing XML socket permissions failed: %s", strerror(errno));
}
@@ -778,9 +771,9 @@ plugin_t *smp_plugin_create()
return NULL;
}
- this->job = callback_job_create_with_prio((callback_job_cb_t)dispatch,
- this, NULL, NULL, JOB_PRIO_CRITICAL);
- lib->processor->queue_job(lib->processor, (job_t*)this->job);
+ lib->processor->queue_job(lib->processor,
+ (job_t*)callback_job_create_with_prio((callback_job_cb_t)dispatch, this,
+ NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
return &this->public.plugin;
}
diff --git a/src/libcharon/plugins/socket_default/Makefile.in b/src/libcharon/plugins/socket_default/Makefile.in
index 9c4e5e7b4..3919e053a 100644
--- a/src/libcharon/plugins/socket_default/Makefile.in
+++ b/src/libcharon/plugins/socket_default/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -86,7 +87,7 @@ libstrongswan_socket_default_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_socket_default_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_socket_default_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -112,6 +113,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -206,11 +208,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -227,11 +232,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -247,6 +253,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -256,7 +263,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/socket_default/socket_default_socket.c b/src/libcharon/plugins/socket_default/socket_default_socket.c
index 76ca1df42..51432c960 100644
--- a/src/libcharon/plugins/socket_default/socket_default_socket.c
+++ b/src/libcharon/plugins/socket_default/socket_default_socket.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2010 Tobias Brunner
+ * Copyright (C) 2006-2012 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005-2010 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -22,6 +22,8 @@
#define _XPG4_2
#define __EXTENSIONS__
#endif
+/* make sure to use the proper defs on Mac OS X */
+#define __APPLE_USE_RFC_3542
#include "socket_default_socket.h"
@@ -38,9 +40,6 @@
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <net/if.h>
-#ifdef __APPLE__
-#include <sys/sysctl.h>
-#endif
#include <hydra.h>
#include <daemon.h>
@@ -49,18 +48,6 @@
/* Maximum size of a packet */
#define MAX_PACKET 10000
-/* length of non-esp marker */
-#define MARKER_LEN sizeof(u_int32_t)
-
-/* from linux/udp.h */
-#ifndef UDP_ENCAP
-#define UDP_ENCAP 100
-#endif /*UDP_ENCAP*/
-
-#ifndef UDP_ENCAP_ESPINUDP
-#define UDP_ENCAP_ESPINUDP 2
-#endif /*UDP_ENCAP_ESPINUDP*/
-
/* these are not defined on some platforms */
#ifndef SOL_IP
#define SOL_IP IPPROTO_IP
@@ -68,9 +55,6 @@
#ifndef SOL_IPV6
#define SOL_IPV6 IPPROTO_IPV6
#endif
-#ifndef SOL_UDP
-#define SOL_UDP IPPROTO_UDP
-#endif
/* IPV6_RECVPKTINFO is defined in RFC 3542 which obsoletes RFC 2292 that
* previously defined IPV6_PKTINFO */
@@ -99,22 +83,32 @@ struct private_socket_default_socket_t {
socket_default_socket_t public;
/**
- * IPv4 socket (500)
+ * Configured port (or random, if initially 0)
+ */
+ u_int16_t port;
+
+ /**
+ * Configured port for NAT-T (or random, if initially 0)
+ */
+ u_int16_t natt;
+
+ /**
+ * IPv4 socket (500 or port)
*/
int ipv4;
/**
- * IPv4 socket for NATT (4500)
+ * IPv4 socket for NAT-T (4500 or natt)
*/
int ipv4_natt;
/**
- * IPv6 socket (500)
+ * IPv6 socket (500 or port)
*/
int ipv6;
/**
- * IPv6 socket for NATT (4500)
+ * IPv6 socket for NAT-T (4500 or natt)
*/
int ipv6_natt;
@@ -122,6 +116,11 @@ struct private_socket_default_socket_t {
* Maximum packet size to receive
*/
int max_packet;
+
+ /**
+ * TRUE if the source address should be set on outbound packets
+ */
+ bool set_source;
};
METHOD(socket_t, receiver, status_t,
@@ -131,7 +130,7 @@ METHOD(socket_t, receiver, status_t,
chunk_t data;
packet_t *pkt;
host_t *source = NULL, *dest = NULL;
- int bytes_read = 0, data_offset;
+ int bytes_read = 0;
bool oldstate;
fd_set rfds;
@@ -169,22 +168,22 @@ METHOD(socket_t, receiver, status_t,
if (FD_ISSET(this->ipv4, &rfds))
{
- port = IKEV2_UDP_PORT;
+ port = this->port;
selected = this->ipv4;
}
if (FD_ISSET(this->ipv4_natt, &rfds))
{
- port = IKEV2_NATT_PORT;
+ port = this->natt;
selected = this->ipv4_natt;
}
if (FD_ISSET(this->ipv6, &rfds))
{
- port = IKEV2_UDP_PORT;
+ port = this->port;
selected = this->ipv6;
}
if (FD_ISSET(this->ipv6_natt, &rfds))
{
- port = IKEV2_NATT_PORT;
+ port = this->natt;
selected = this->ipv6_natt;
}
if (selected)
@@ -220,13 +219,6 @@ METHOD(socket_t, receiver, status_t,
}
DBG3(DBG_NET, "received packet %b", buffer, bytes_read);
- if (bytes_read < MARKER_LEN)
- {
- DBG3(DBG_NET, "received packet too short (%d bytes)",
- bytes_read);
- return FAILED;
- }
-
/* read ancillary data to get destination address */
for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
cmsgptr = CMSG_NXTHDR(&msg, cmsgptr))
@@ -295,17 +287,8 @@ METHOD(socket_t, receiver, status_t,
pkt->set_source(pkt, source);
pkt->set_destination(pkt, dest);
DBG2(DBG_NET, "received packet: from %#H to %#H", source, dest);
- data_offset = 0;
- /* remove non esp marker */
- if (dest->get_port(dest) == IKEV2_NATT_PORT)
- {
- data_offset += MARKER_LEN;
- }
- /* fill in packet */
- data.len = bytes_read - data_offset;
- data.ptr = malloc(data.len);
- memcpy(data.ptr, buffer + data_offset, data.len);
- pkt->set_data(pkt, data);
+ data = chunk_create(buffer, bytes_read);
+ pkt->set_data(pkt, chunk_clone(data));
}
else
{
@@ -322,7 +305,7 @@ METHOD(socket_t, sender, status_t,
{
int sport, skt, family;
ssize_t bytes_sent;
- chunk_t data, marked;
+ chunk_t data;
host_t *src, *dst;
struct msghdr msg;
struct cmsghdr *cmsg;
@@ -337,7 +320,7 @@ METHOD(socket_t, sender, status_t,
/* send data */
sport = src->get_port(src);
family = dst->get_family(dst);
- if (sport == IKEV2_UDP_PORT)
+ if (sport == 0 || sport == this->port)
{
if (family == AF_INET)
{
@@ -348,7 +331,7 @@ METHOD(socket_t, sender, status_t,
skt = this->ipv6;
}
}
- else if (sport == IKEV2_NATT_PORT)
+ else if (sport == this->natt)
{
if (family == AF_INET)
{
@@ -358,17 +341,6 @@ METHOD(socket_t, sender, status_t,
{
skt = this->ipv6_natt;
}
- /* NAT keepalives without marker */
- if (data.len != 1 || data.ptr[0] != 0xFF)
- {
- /* add non esp marker to packet */
- marked = chunk_alloc(data.len + MARKER_LEN);
- memset(marked.ptr, 0, MARKER_LEN);
- memcpy(marked.ptr + MARKER_LEN, data.ptr, data.len);
- /* let the packet do the clean up for us */
- packet->set_data(packet, marked);
- data = marked;
- }
}
else
{
@@ -385,7 +357,7 @@ METHOD(socket_t, sender, status_t,
msg.msg_iovlen = 1;
msg.msg_flags = 0;
- if (!src->is_anyaddr(src))
+ if (this->set_source && !src->is_anyaddr(src))
{
if (family == AF_INET)
{
@@ -448,11 +420,17 @@ METHOD(socket_t, sender, status_t,
return SUCCESS;
}
+METHOD(socket_t, get_port, u_int16_t,
+ private_socket_default_socket_t *this, bool nat_t)
+{
+ return nat_t ? this->natt : this->port;
+}
+
/**
* open a socket to send and receive packets
*/
static int open_socket(private_socket_default_socket_t *this,
- int family, u_int16_t port)
+ int family, u_int16_t *port)
{
int on = TRUE;
struct sockaddr_storage addr;
@@ -469,7 +447,7 @@ static int open_socket(private_socket_default_socket_t *this,
{
struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
htoun32(&sin->sin_addr.s_addr, INADDR_ANY);
- htoun16(&sin->sin_port, port);
+ htoun16(&sin->sin_port, *port);
addrlen = sizeof(struct sockaddr_in);
sol = SOL_IP;
#ifdef IP_PKTINFO
@@ -483,7 +461,7 @@ static int open_socket(private_socket_default_socket_t *this,
{
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr;
memcpy(&sin6->sin6_addr, &in6addr_any, sizeof(in6addr_any));
- htoun16(&sin6->sin6_port, port);
+ htoun16(&sin6->sin6_port, *port);
addrlen = sizeof(struct sockaddr_in6);
sol = SOL_IPV6;
pktinfo = IPV6_RECVPKTINFO;
@@ -514,6 +492,32 @@ static int open_socket(private_socket_default_socket_t *this,
return 0;
}
+ /* retrieve randomly allocated port if needed */
+ if (*port == 0)
+ {
+ if (getsockname(skt, (struct sockaddr *)&addr, &addrlen) < 0)
+ {
+ DBG1(DBG_NET, "unable to determine port: %s", strerror(errno));
+ close(skt);
+ return 0;
+ }
+ switch (family)
+ {
+ case AF_INET:
+ {
+ struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
+ *port = untoh16(&sin->sin_port);
+ break;
+ }
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr;
+ *port = untoh16(&sin6->sin6_port);
+ break;
+ }
+ }
+ }
+
/* get additional packet info on receive */
if (pktinfo > 0)
{
@@ -531,17 +535,15 @@ static int open_socket(private_socket_default_socket_t *this,
DBG1(DBG_NET, "installing IKE bypass policy failed");
}
-#ifndef __APPLE__
+ /* enable UDP decapsulation for NAT-T sockets */
+ if (port == &this->natt &&
+ !hydra->kernel_interface->enable_udp_decap(hydra->kernel_interface,
+ skt, family, this->natt))
{
- /* enable UDP decapsulation globally, only for one socket needed */
- int type = UDP_ENCAP_ESPINUDP;
- if (family == AF_INET && port == IKEV2_NATT_PORT &&
- setsockopt(skt, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0)
- {
- DBG1(DBG_NET, "unable to set UDP_ENCAP: %s", strerror(errno));
- }
+ DBG1(DBG_NET, "enabling UDP decapsulation for %s on port %d failed",
+ family == AF_INET ? "IPv4" : "IPv6", this->natt);
}
-#endif
+
return skt;
}
@@ -579,50 +581,55 @@ socket_default_socket_t *socket_default_socket_create()
.socket = {
.send = _sender,
.receive = _receiver,
+ .get_port = _get_port,
.destroy = _destroy,
},
},
+ .port = lib->settings->get_int(lib->settings,
+ "%s.port", CHARON_UDP_PORT, charon->name),
+ .natt = lib->settings->get_int(lib->settings,
+ "%s.port_nat_t", CHARON_NATT_PORT, charon->name),
.max_packet = lib->settings->get_int(lib->settings,
- "charon.max_packet", MAX_PACKET),
+ "%s.max_packet", MAX_PACKET, charon->name),
+ .set_source = lib->settings->get_bool(lib->settings,
+ "%s.plugins.socket-default.set_source", TRUE,
+ charon->name),
);
-#ifdef __APPLE__
+ if (this->port && this->port == this->natt)
{
- int natt_port = IKEV2_NATT_PORT;
- if (sysctlbyname("net.inet.ipsec.esp_port", NULL, NULL, &natt_port,
- sizeof(natt_port)) != 0)
- {
- DBG1(DBG_NET, "could not set net.inet.ipsec.esp_port to %d: %s",
- natt_port, strerror(errno));
- }
+ DBG1(DBG_NET, "IKE ports can't be equal, will allocate NAT-T "
+ "port randomly");
+ this->natt = 0;
}
-#endif
- this->ipv4 = open_socket(this, AF_INET, IKEV2_UDP_PORT);
- if (this->ipv4 == 0)
+ /* we allocate IPv6 sockets first as that will reserve randomly allocated
+ * ports also for IPv4 */
+ this->ipv6 = open_socket(this, AF_INET6, &this->port);
+ if (this->ipv6 == 0)
{
- DBG1(DBG_NET, "could not open IPv4 socket, IPv4 disabled");
+ DBG1(DBG_NET, "could not open IPv6 socket, IPv6 disabled");
}
else
{
- this->ipv4_natt = open_socket(this, AF_INET, IKEV2_NATT_PORT);
- if (this->ipv4_natt == 0)
+ this->ipv6_natt = open_socket(this, AF_INET6, &this->natt);
+ if (this->ipv6_natt == 0)
{
- DBG1(DBG_NET, "could not open IPv4 NAT-T socket");
+ DBG1(DBG_NET, "could not open IPv6 NAT-T socket");
}
}
- this->ipv6 = open_socket(this, AF_INET6, IKEV2_UDP_PORT);
- if (this->ipv6 == 0)
+ this->ipv4 = open_socket(this, AF_INET, &this->port);
+ if (this->ipv4 == 0)
{
- DBG1(DBG_NET, "could not open IPv6 socket, IPv6 disabled");
+ DBG1(DBG_NET, "could not open IPv4 socket, IPv4 disabled");
}
else
{
- this->ipv6_natt = open_socket(this, AF_INET6, IKEV2_NATT_PORT);
- if (this->ipv6_natt == 0)
+ this->ipv4_natt = open_socket(this, AF_INET, &this->natt);
+ if (this->ipv4_natt == 0)
{
- DBG1(DBG_NET, "could not open IPv6 NAT-T socket");
+ DBG1(DBG_NET, "could not open IPv4 NAT-T socket");
}
}
@@ -632,6 +639,7 @@ socket_default_socket_t *socket_default_socket_create()
destroy(this);
return NULL;
}
+
return &this->public;
}
diff --git a/src/libcharon/plugins/socket_dynamic/Makefile.in b/src/libcharon/plugins/socket_dynamic/Makefile.in
index f45e3d255..dfde282b2 100644
--- a/src/libcharon/plugins/socket_dynamic/Makefile.in
+++ b/src/libcharon/plugins/socket_dynamic/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -86,7 +87,7 @@ libstrongswan_socket_dynamic_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_socket_dynamic_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_socket_dynamic_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -112,6 +113,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -206,11 +208,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -227,11 +232,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -247,6 +253,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -256,7 +263,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c
index eee3814a8..33f16cc45 100644
--- a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c
+++ b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2010 Tobias Brunner
+ * Copyright (C) 2006-2012 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005-2010 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -45,18 +45,6 @@
/* Maximum size of a packet */
#define MAX_PACKET 10000
-/* length of non-esp marker */
-#define MARKER_LEN sizeof(u_int32_t)
-
-/* from linux/udp.h */
-#ifndef UDP_ENCAP
-#define UDP_ENCAP 100
-#endif /*UDP_ENCAP*/
-
-#ifndef UDP_ENCAP_ESPINUDP
-#define UDP_ENCAP_ESPINUDP 2
-#endif /*UDP_ENCAP_ESPINUDP*/
-
/* these are not defined on some platforms */
#ifndef SOL_IP
#define SOL_IP IPPROTO_IP
@@ -64,9 +52,6 @@
#ifndef SOL_IPV6
#define SOL_IPV6 IPPROTO_IPV6
#endif
-#ifndef SOL_UDP
-#define SOL_UDP IPPROTO_UDP
-#endif
/* IPV6_RECVPKTINFO is defined in RFC 3542 which obsoletes RFC 2292 that
* previously defined IPV6_PKTINFO */
@@ -237,12 +222,6 @@ static packet_t *receive_packet(private_socket_dynamic_socket_t *this,
}
DBG3(DBG_NET, "received packet %b", buffer, (u_int)len);
- if (len < MARKER_LEN)
- {
- DBG3(DBG_NET, "received packet too short (%d bytes)", len);
- return NULL;
- }
-
/* read ancillary data to get destination address */
for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
cmsgptr = CMSG_NXTHDR(&msg, cmsgptr))
@@ -297,12 +276,6 @@ static packet_t *receive_packet(private_socket_dynamic_socket_t *this,
packet = packet_create();
packet->set_source(packet, source);
packet->set_destination(packet, dest);
- /* we assume a non-ESP marker if none of the ports is on 500 */
- if (dest->get_port(dest) != IKEV2_UDP_PORT &&
- source->get_port(source) != IKEV2_UDP_PORT)
- {
- data = chunk_skip(data, MARKER_LEN);
- }
packet->set_data(packet, chunk_clone(data));
return packet;
}
@@ -358,7 +331,7 @@ METHOD(socket_t, receiver, status_t,
static int open_socket(private_socket_dynamic_socket_t *this,
int family, u_int16_t port)
{
- int on = TRUE, type = UDP_ENCAP_ESPINUDP;
+ int on = TRUE;
struct sockaddr_storage addr;
socklen_t addrlen;
u_int sol, pktinfo = 0;
@@ -430,10 +403,13 @@ static int open_socket(private_socket_dynamic_socket_t *this,
}
/* enable UDP decapsulation on each socket */
- if (setsockopt(fd, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0)
+ if (!hydra->kernel_interface->enable_udp_decap(hydra->kernel_interface,
+ fd, family, port))
{
- DBG1(DBG_NET, "unable to set UDP_ENCAP: %s", strerror(errno));
+ DBG1(DBG_NET, "enabling UDP decapsulation for %s on port %d failed",
+ family == AF_INET ? "IPv4" : "IPv6", port);
}
+
return fd;
}
@@ -483,7 +459,7 @@ METHOD(socket_t, sender, status_t,
host_t *src, *dst;
int port, family;
ssize_t len;
- chunk_t data, marked;
+ chunk_t data;
struct msghdr msg;
struct cmsghdr *cmsg;
struct iovec iov;
@@ -492,6 +468,7 @@ METHOD(socket_t, sender, status_t,
dst = packet->get_destination(packet);
family = src->get_family(src);
port = src->get_port(src);
+ port = port ?: CHARON_UDP_PORT;
skt = find_socket(this, family, port);
if (!skt)
{
@@ -501,19 +478,6 @@ METHOD(socket_t, sender, status_t,
data = packet->get_data(packet);
DBG2(DBG_NET, "sending packet: from %#H to %#H", src, dst);
- /* use non-ESP marker if none of the ports is 500, not for keep alives */
- if (port != IKEV2_UDP_PORT && dst->get_port(dst) != IKEV2_UDP_PORT &&
- !(data.len == 1 && data.ptr[0] == 0xFF))
- {
- /* add non esp marker to packet */
- marked = chunk_alloc(data.len + MARKER_LEN);
- memset(marked.ptr, 0, MARKER_LEN);
- memcpy(marked.ptr + MARKER_LEN, data.ptr, data.len);
- /* let the packet do the clean up for us */
- packet->set_data(packet, marked);
- data = marked;
- }
-
memset(&msg, 0, sizeof(struct msghdr));
msg.msg_name = dst->get_sockaddr(dst);;
msg.msg_namelen = *dst->get_sockaddr_len(dst);
@@ -572,6 +536,14 @@ METHOD(socket_t, sender, status_t,
return SUCCESS;
}
+METHOD(socket_t, get_port, u_int16_t,
+ private_socket_dynamic_socket_t *this, bool nat_t)
+{
+ /* we return 0 here for users that have no explicit port configured, the
+ * sender will default to the default port in this case */
+ return 0;
+}
+
METHOD(socket_t, destroy, void,
private_socket_dynamic_socket_t *this)
{
@@ -605,12 +577,13 @@ socket_dynamic_socket_t *socket_dynamic_socket_create()
.socket = {
.send = _sender,
.receive = _receiver,
+ .get_port = _get_port,
.destroy = _destroy,
},
},
.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
.max_packet = lib->settings->get_int(lib->settings,
- "charon.max_packet", MAX_PACKET),
+ "%s.max_packet", MAX_PACKET, charon->name),
);
if (pipe(this->notify) != 0)
diff --git a/src/libcharon/plugins/socket_raw/Makefile.am b/src/libcharon/plugins/socket_raw/Makefile.am
deleted file mode 100644
index 2109ae5f3..000000000
--- a/src/libcharon/plugins/socket_raw/Makefile.am
+++ /dev/null
@@ -1,17 +0,0 @@
-
-INCLUDES = -I${linux_headers} -I$(top_srcdir)/src/libstrongswan \
- -I$(top_srcdir)/src/libhydra -I$(top_srcdir)/src/libcharon
-
-AM_CFLAGS = -rdynamic
-
-if MONOLITHIC
-noinst_LTLIBRARIES = libstrongswan-socket-raw.la
-else
-plugin_LTLIBRARIES = libstrongswan-socket-raw.la
-endif
-
-libstrongswan_socket_raw_la_SOURCES = \
- socket_raw_plugin.h socket_raw_plugin.c \
- socket_raw_socket.h socket_raw_socket.c
-
-libstrongswan_socket_raw_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/socket_raw/socket_raw_socket.c b/src/libcharon/plugins/socket_raw/socket_raw_socket.c
deleted file mode 100644
index ae37d8f2b..000000000
--- a/src/libcharon/plugins/socket_raw/socket_raw_socket.c
+++ /dev/null
@@ -1,717 +0,0 @@
-/*
- * Copyright (C) 2006-2010 Tobias Brunner
- * Copyright (C) 2005-2010 Martin Willi
- * Copyright (C) 2006 Daniel Roethlisberger
- * Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/* for struct in6_pktinfo */
-#define _GNU_SOURCE
-
-#include "socket_raw_socket.h"
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <netinet/udp.h>
-#include <linux/types.h>
-#include <linux/filter.h>
-#include <net/if.h>
-
-#include <hydra.h>
-#include <daemon.h>
-#include <threading/thread.h>
-
-/* Maximum size of a packet */
-#define MAX_PACKET 10000
-
-/* constants for packet handling */
-#define IP_LEN sizeof(struct iphdr)
-#define IP6_LEN sizeof(struct ip6_hdr)
-#define UDP_LEN sizeof(struct udphdr)
-#define MARKER_LEN sizeof(u_int32_t)
-
-/* offsets for packet handling */
-#define IP_PROTO_OFFSET 9
-#define IP6_PROTO_OFFSET 6
-#define IKE_VERSION_OFFSET 17
-#define IKE_LENGTH_OFFSET 24
-
-/* from linux/udp.h */
-#ifndef UDP_ENCAP
-#define UDP_ENCAP 100
-#endif /*UDP_ENCAP*/
-
-#ifndef UDP_ENCAP_ESPINUDP
-#define UDP_ENCAP_ESPINUDP 2
-#endif /*UDP_ENCAP_ESPINUDP*/
-
-/* needed for older kernel headers */
-#ifndef IPV6_2292PKTINFO
-#define IPV6_2292PKTINFO 2
-#endif /*IPV6_2292PKTINFO*/
-
-typedef struct private_socket_raw_socket_t private_socket_raw_socket_t;
-
-/**
- * Private data of an socket_t object
- */
-struct private_socket_raw_socket_t {
-
- /**
- * public functions
- */
- socket_raw_socket_t public;
-
- /**
- * regular port
- */
- int port;
-
- /**
- * port used for nat-t
- */
- int natt_port;
-
- /**
- * raw receiver socket for IPv4
- */
- int recv4;
-
- /**
- * raw receiver socket for IPv6
- */
- int recv6;
-
- /**
- * send socket on regular port for IPv4
- */
- int send4;
-
- /**
- * send socket on regular port for IPv6
- */
- int send6;
-
- /**
- * send socket on nat-t port for IPv4
- */
- int send4_natt;
-
- /**
- * send socket on nat-t port for IPv6
- */
- int send6_natt;
-
- /**
- * Maximum packet size to receive
- */
- int max_packet;
-};
-
-METHOD(socket_t, receiver, status_t,
- private_socket_raw_socket_t *this, packet_t **packet)
-{
- char buffer[this->max_packet];
- chunk_t data;
- packet_t *pkt;
- struct udphdr *udp;
- host_t *source = NULL, *dest = NULL;
- int bytes_read = 0, data_offset;
- bool oldstate;
- fd_set rfds;
-
- FD_ZERO(&rfds);
-
- if (this->recv4)
- {
- FD_SET(this->recv4, &rfds);
- }
- if (this->recv6)
- {
- FD_SET(this->recv6, &rfds);
- }
-
- DBG2(DBG_NET, "waiting for data on raw sockets");
-
- oldstate = thread_cancelability(TRUE);
- if (select(max(this->recv4, this->recv6) + 1, &rfds, NULL, NULL, NULL) <= 0)
- {
- thread_cancelability(oldstate);
- return FAILED;
- }
- thread_cancelability(oldstate);
-
- if (this->recv4 && FD_ISSET(this->recv4, &rfds))
- {
- /* IPv4 raw sockets return the IP header. We read src/dest
- * information directly from the raw header */
- struct iphdr *ip;
- struct sockaddr_in src, dst;
-
- bytes_read = recv(this->recv4, buffer, this->max_packet, 0);
- if (bytes_read < 0)
- {
- DBG1(DBG_NET, "error reading from IPv4 socket: %s", strerror(errno));
- return FAILED;
- }
- if (bytes_read == this->max_packet)
- {
- DBG1(DBG_NET, "receive buffer too small, packet discarded");
- return FAILED;
- }
- DBG3(DBG_NET, "received IPv4 packet %b", buffer, bytes_read);
-
- /* read source/dest from raw IP/UDP header */
- if (bytes_read < IP_LEN + UDP_LEN + MARKER_LEN)
- {
- DBG1(DBG_NET, "received IPv4 packet too short (%d bytes)",
- bytes_read);
- return FAILED;
- }
- ip = (struct iphdr*) buffer;
- udp = (struct udphdr*) (buffer + IP_LEN);
- src.sin_family = AF_INET;
- src.sin_addr.s_addr = ip->saddr;
- src.sin_port = udp->source;
- dst.sin_family = AF_INET;
- dst.sin_addr.s_addr = ip->daddr;
- dst.sin_port = udp->dest;
- source = host_create_from_sockaddr((sockaddr_t*)&src);
- dest = host_create_from_sockaddr((sockaddr_t*)&dst);
-
- pkt = packet_create();
- pkt->set_source(pkt, source);
- pkt->set_destination(pkt, dest);
- DBG2(DBG_NET, "received packet: from %#H to %#H", source, dest);
- data_offset = IP_LEN + UDP_LEN;
- /* remove non esp marker */
- if (dest->get_port(dest) == IKEV2_NATT_PORT)
- {
- data_offset += MARKER_LEN;
- }
- /* fill in packet */
- data.len = bytes_read - data_offset;
- data.ptr = malloc(data.len);
- memcpy(data.ptr, buffer + data_offset, data.len);
- pkt->set_data(pkt, data);
- }
- else if (this->recv6 && FD_ISSET(this->recv6, &rfds))
- {
- /* IPv6 raw sockets return no IP header. We must query
- * src/dest via socket options/ancillary data */
- struct msghdr msg;
- struct cmsghdr *cmsgptr;
- struct sockaddr_in6 src, dst;
- struct iovec iov;
- char ancillary[64];
-
- msg.msg_name = &src;
- msg.msg_namelen = sizeof(src);
- iov.iov_base = buffer;
- iov.iov_len = this->max_packet;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- msg.msg_control = ancillary;
- msg.msg_controllen = sizeof(ancillary);
- msg.msg_flags = 0;
-
- bytes_read = recvmsg(this->recv6, &msg, 0);
- if (bytes_read < 0)
- {
- DBG1(DBG_NET, "error reading from IPv6 socket: %s", strerror(errno));
- return FAILED;
- }
- DBG3(DBG_NET, "received IPv6 packet %b", buffer, bytes_read);
-
- if (bytes_read < IP_LEN + UDP_LEN + MARKER_LEN)
- {
- DBG3(DBG_NET, "received IPv6 packet too short (%d bytes)",
- bytes_read);
- return FAILED;
- }
-
- /* read ancillary data to get destination address */
- for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
- cmsgptr = CMSG_NXTHDR(&msg, cmsgptr))
- {
- if (cmsgptr->cmsg_len == 0)
- {
- DBG1(DBG_NET, "error reading IPv6 ancillary data");
- return FAILED;
- }
-
-#ifdef HAVE_IN6_PKTINFO
- if (cmsgptr->cmsg_level == SOL_IPV6 &&
- cmsgptr->cmsg_type == IPV6_2292PKTINFO)
- {
- struct in6_pktinfo *pktinfo;
- pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsgptr);
-
- memset(&dst, 0, sizeof(dst));
- memcpy(&dst.sin6_addr, &pktinfo->ipi6_addr, sizeof(dst.sin6_addr));
- dst.sin6_family = AF_INET6;
- udp = (struct udphdr*) (buffer);
- dst.sin6_port = udp->dest;
- src.sin6_port = udp->source;
- dest = host_create_from_sockaddr((sockaddr_t*)&dst);
- }
-#endif /* HAVE_IN6_PKTINFO */
- }
- /* ancillary data missing? */
- if (dest == NULL)
- {
- DBG1(DBG_NET, "error reading IPv6 packet header");
- return FAILED;
- }
-
- source = host_create_from_sockaddr((sockaddr_t*)&src);
-
- pkt = packet_create();
- pkt->set_source(pkt, source);
- pkt->set_destination(pkt, dest);
- DBG2(DBG_NET, "received packet: from %#H to %#H", source, dest);
- data_offset = UDP_LEN;
- /* remove non esp marker */
- if (dest->get_port(dest) == IKEV2_NATT_PORT)
- {
- data_offset += MARKER_LEN;
- }
- /* fill in packet */
- data.len = bytes_read - data_offset;
- data.ptr = malloc(data.len);
- memcpy(data.ptr, buffer + data_offset, data.len);
- pkt->set_data(pkt, data);
- }
- else
- {
- /* oops, shouldn't happen */
- return FAILED;
- }
-
- /* return packet */
- *packet = pkt;
- return SUCCESS;
-}
-
-METHOD(socket_t, sender, status_t,
- private_socket_raw_socket_t *this, packet_t *packet)
-{
- int sport, skt, family;
- ssize_t bytes_sent;
- chunk_t data, marked;
- host_t *src, *dst;
- struct msghdr msg;
- struct cmsghdr *cmsg;
- struct iovec iov;
-
- src = packet->get_source(packet);
- dst = packet->get_destination(packet);
- data = packet->get_data(packet);
-
- DBG2(DBG_NET, "sending packet: from %#H to %#H", src, dst);
-
- /* send data */
- sport = src->get_port(src);
- family = dst->get_family(dst);
- if (sport == IKEV2_UDP_PORT)
- {
- if (family == AF_INET)
- {
- skt = this->send4;
- }
- else
- {
- skt = this->send6;
- }
- }
- else if (sport == IKEV2_NATT_PORT)
- {
- if (family == AF_INET)
- {
- skt = this->send4_natt;
- }
- else
- {
- skt = this->send6_natt;
- }
- /* NAT keepalives without marker */
- if (data.len != 1 || data.ptr[0] != 0xFF)
- {
- /* add non esp marker to packet */
- marked = chunk_alloc(data.len + MARKER_LEN);
- memset(marked.ptr, 0, MARKER_LEN);
- memcpy(marked.ptr + MARKER_LEN, data.ptr, data.len);
- /* let the packet do the clean up for us */
- packet->set_data(packet, marked);
- data = marked;
- }
- }
- else
- {
- DBG1(DBG_NET, "unable to locate a send socket for port %d", sport);
- return FAILED;
- }
-
- memset(&msg, 0, sizeof(struct msghdr));
- msg.msg_name = dst->get_sockaddr(dst);;
- msg.msg_namelen = *dst->get_sockaddr_len(dst);
- iov.iov_base = data.ptr;
- iov.iov_len = data.len;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- msg.msg_flags = 0;
-
- if (!src->is_anyaddr(src))
- {
- if (family == AF_INET)
- {
- char buf[CMSG_SPACE(sizeof(struct in_pktinfo))];
- struct in_pktinfo *pktinfo;
- struct sockaddr_in *sin;
-
- msg.msg_control = buf;
- msg.msg_controllen = sizeof(buf);
- cmsg = CMSG_FIRSTHDR(&msg);
- cmsg->cmsg_level = SOL_IP;
- cmsg->cmsg_type = IP_PKTINFO;
- cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
- pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsg);
- memset(pktinfo, 0, sizeof(struct in_pktinfo));
- sin = (struct sockaddr_in*)src->get_sockaddr(src);
- memcpy(&pktinfo->ipi_spec_dst, &sin->sin_addr, sizeof(struct in_addr));
- }
-#ifdef HAVE_IN6_PKTINFO
- else
- {
- char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
- struct in6_pktinfo *pktinfo;
- struct sockaddr_in6 *sin;
-
- msg.msg_control = buf;
- msg.msg_controllen = sizeof(buf);
- cmsg = CMSG_FIRSTHDR(&msg);
- cmsg->cmsg_level = SOL_IPV6;
- cmsg->cmsg_type = IPV6_2292PKTINFO;
- cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
- pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsg);
- memset(pktinfo, 0, sizeof(struct in6_pktinfo));
- sin = (struct sockaddr_in6*)src->get_sockaddr(src);
- memcpy(&pktinfo->ipi6_addr, &sin->sin6_addr, sizeof(struct in6_addr));
- }
-#endif /* HAVE_IN6_PKTINFO */
- }
-
- bytes_sent = sendmsg(skt, &msg, 0);
-
- if (bytes_sent != data.len)
- {
- DBG1(DBG_NET, "error writing to socket: %s", strerror(errno));
- return FAILED;
- }
- return SUCCESS;
-}
-
-/**
- * open a socket to send packets
- */
-static int open_send_socket(private_socket_raw_socket_t *this,
- int family, u_int16_t port)
-{
- int on = TRUE;
- int type = UDP_ENCAP_ESPINUDP;
- struct sockaddr_storage addr;
- int skt;
-
- memset(&addr, 0, sizeof(addr));
- addr.ss_family = family;
- /* precalculate constants depending on address family */
- switch (family)
- {
- case AF_INET:
- {
- struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
- htoun32(&sin->sin_addr.s_addr, INADDR_ANY);
- htoun16(&sin->sin_port, port);
- break;
- }
- case AF_INET6:
- {
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr;
- memcpy(&sin6->sin6_addr, &in6addr_any, sizeof(in6addr_any));
- htoun16(&sin6->sin6_port, port);
- break;
- }
- default:
- return 0;
- }
-
- skt = socket(family, SOCK_DGRAM, IPPROTO_UDP);
- if (skt < 0)
- {
- DBG1(DBG_NET, "could not open send socket: %s", strerror(errno));
- return 0;
- }
-
- if (setsockopt(skt, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0)
- {
- DBG1(DBG_NET, "unable to set SO_REUSEADDR on send socket: %s",
- strerror(errno));
- close(skt);
- return 0;
- }
-
- /* bind the send socket */
- if (bind(skt, (struct sockaddr *)&addr, sizeof(addr)) < 0)
- {
- DBG1(DBG_NET, "unable to bind send socket: %s",
- strerror(errno));
- close(skt);
- return 0;
- }
-
- if (family == AF_INET)
- {
- /* enable UDP decapsulation globally, only for one socket needed */
- if (setsockopt(skt, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0)
- {
- DBG1(DBG_NET, "unable to set UDP_ENCAP: %s; NAT-T may fail",
- strerror(errno));
- }
- }
-
- if (!hydra->kernel_interface->bypass_socket(hydra->kernel_interface,
- skt, family))
- {
- DBG1(DBG_NET, "installing bypass policy on send socket failed");
- }
-
- return skt;
-}
-
-/**
- * open a socket to receive packets
- */
-static int open_recv_socket(private_socket_raw_socket_t *this, int family)
-{
- int skt;
- int on = TRUE;
- u_int ip_len, sol, udp_header, ike_header;
-
- /* precalculate constants depending on address family */
- switch (family)
- {
- case AF_INET:
- ip_len = IP_LEN;
- sol = SOL_IP;
- break;
- case AF_INET6:
- ip_len = 0; /* IPv6 raw sockets contain no IP header */
- sol = SOL_IPV6;
- break;
- default:
- return 0;
- }
- udp_header = ip_len;
- ike_header = ip_len + UDP_LEN;
-
- /* This filter code filters out all non-IKEv2 traffic on
- * a SOCK_RAW IP_PROTP_UDP socket. Handling of other
- * IKE versions is done in pluto.
- */
- struct sock_filter ikev2_filter_code[] =
- {
- /* Destination Port must be either port or natt_port */
- BPF_STMT(BPF_LD+BPF_H+BPF_ABS, udp_header + 2),
- BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IKEV2_UDP_PORT, 1, 0),
- BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IKEV2_NATT_PORT, 6, 14),
- /* port */
- /* IKE version must be 2.x */
- BPF_STMT(BPF_LD+BPF_B+BPF_ABS, ike_header + IKE_VERSION_OFFSET),
- BPF_STMT(BPF_ALU+BPF_RSH+BPF_K, 4),
- BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 2, 0, 11),
- /* packet length is length in IKEv2 header + ip header + udp header */
- BPF_STMT(BPF_LD+BPF_W+BPF_ABS, ike_header + IKE_LENGTH_OFFSET),
- BPF_STMT(BPF_ALU+BPF_ADD+BPF_K, ip_len + UDP_LEN),
- BPF_STMT(BPF_RET+BPF_A, 0),
- /* natt_port */
- /* nat-t: check for marker */
- BPF_STMT(BPF_LD+BPF_W+BPF_ABS, ike_header),
- BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 6),
- /* nat-t: IKE version must be 2.x */
- BPF_STMT(BPF_LD+BPF_B+BPF_ABS, ike_header + MARKER_LEN + IKE_VERSION_OFFSET),
- BPF_STMT(BPF_ALU+BPF_RSH+BPF_K, 4),
- BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 2, 0, 3),
- /* nat-t: packet length is length in IKEv2 header + ip header + udp header + non esp marker */
- BPF_STMT(BPF_LD+BPF_W+BPF_ABS, ike_header + MARKER_LEN + IKE_LENGTH_OFFSET),
- BPF_STMT(BPF_ALU+BPF_ADD+BPF_K, ip_len + UDP_LEN + MARKER_LEN),
- BPF_STMT(BPF_RET+BPF_A, 0),
- /* packet doesn't match, ignore */
- BPF_STMT(BPF_RET+BPF_K, 0),
- };
-
- /* Filter struct to use with setsockopt */
- struct sock_fprog ikev2_filter = {
- sizeof(ikev2_filter_code) / sizeof(struct sock_filter),
- ikev2_filter_code
- };
-
- /* set up a raw socket */
- skt = socket(family, SOCK_RAW, IPPROTO_UDP);
- if (skt < 0)
- {
- DBG1(DBG_NET, "unable to create raw socket: %s", strerror(errno));
- return 0;
- }
-
- if (setsockopt(skt, SOL_SOCKET, SO_ATTACH_FILTER,
- &ikev2_filter, sizeof(ikev2_filter)) < 0)
- {
- DBG1(DBG_NET, "unable to attach IKEv2 filter to raw socket: %s",
- strerror(errno));
- close(skt);
- return 0;
- }
-
- if (family == AF_INET6 &&
- /* we use IPV6_2292PKTINFO, as IPV6_PKTINFO is defined as
- * 2 or 50 depending on kernel header version */
- setsockopt(skt, sol, IPV6_2292PKTINFO, &on, sizeof(on)) < 0)
- {
- DBG1(DBG_NET, "unable to set IPV6_PKTINFO on raw socket: %s",
- strerror(errno));
- close(skt);
- return 0;
- }
-
- if (!hydra->kernel_interface->bypass_socket(hydra->kernel_interface,
- skt, family))
- {
- DBG1(DBG_NET, "installing bypass policy on receive socket failed");
- }
-
- return skt;
-}
-
-METHOD(socket_t, destroy, void,
- private_socket_raw_socket_t *this)
-{
- if (this->recv4)
- {
- close(this->recv4);
- }
- if (this->recv6)
- {
- close(this->recv6);
- }
- if (this->send4)
- {
- close(this->send4);
- }
- if (this->send6)
- {
- close(this->send6);
- }
- if (this->send4_natt)
- {
- close(this->send4_natt);
- }
- if (this->send6_natt)
- {
- close(this->send6_natt);
- }
- free(this);
-}
-
-/*
- * See header for description
- */
-socket_raw_socket_t *socket_raw_socket_create()
-{
- private_socket_raw_socket_t *this;
-
- INIT(this,
- .public = {
- .socket = {
- .send = _sender,
- .receive = _receiver,
- .destroy = _destroy,
- },
- },
- .max_packet = lib->settings->get_int(lib->settings,
- "charon.max_packet", MAX_PACKET),
- );
-
- this->recv4 = open_recv_socket(this, AF_INET);
- if (this->recv4 == 0)
- {
- DBG1(DBG_NET, "could not open IPv4 receive socket, IPv4 disabled");
- }
- else
- {
- this->send4 = open_send_socket(this, AF_INET, IKEV2_UDP_PORT);
- if (this->send4 == 0)
- {
- DBG1(DBG_NET, "could not open IPv4 send socket, IPv4 disabled");
- close(this->recv4);
- }
- else
- {
- this->send4_natt = open_send_socket(this, AF_INET, IKEV2_NATT_PORT);
- if (this->send4_natt == 0)
- {
- DBG1(DBG_NET, "could not open IPv4 NAT-T send socket");
- }
- }
- }
-
- this->recv6 = open_recv_socket(this, AF_INET6);
- if (this->recv6 == 0)
- {
- DBG1(DBG_NET, "could not open IPv6 receive socket, IPv6 disabled");
- }
- else
- {
- this->send6 = open_send_socket(this, AF_INET6, IKEV2_UDP_PORT);
- if (this->send6 == 0)
- {
- DBG1(DBG_NET, "could not open IPv6 send socket, IPv6 disabled");
- close(this->recv6);
- }
- else
- {
- this->send6_natt = open_send_socket(this, AF_INET6, IKEV2_NATT_PORT);
- if (this->send6_natt == 0)
- {
- DBG1(DBG_NET, "could not open IPv6 NAT-T send socket");
- }
- }
- }
-
- if (!(this->send4 || this->send6) || !(this->recv4 || this->recv6))
- {
- DBG1(DBG_NET, "could not create any sockets");
- destroy(this);
- return NULL;
- }
-
- return &this->public;
-}
diff --git a/src/libcharon/plugins/socket_raw/socket_raw_socket.h b/src/libcharon/plugins/socket_raw/socket_raw_socket.h
deleted file mode 100644
index 23ff304a8..000000000
--- a/src/libcharon/plugins/socket_raw/socket_raw_socket.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2010 Martin Willi
- * Copyright (C) 2010 revosec AG
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup socket_raw_socket socket_raw_socket
- * @{ @ingroup socket_raw
- */
-
-#ifndef SOCKET_RAW_SOCKET_H_
-#define SOCKET_RAW_SOCKET_H_
-
-typedef struct socket_raw_socket_t socket_raw_socket_t;
-
-#include <network/socket.h>
-
-/**
- * Raw socket, binds to port 500/4500 using any IPv4/IPv6 address.
- *
- * This imeplementation uses raw sockets to allow binding of other daemons
- * (pluto) to UDP/500/4500. An installed "Linux socket filter" filters out
- * all non-IKEv2 traffic and handles just IKEv2 messages. An other daemon
- * must handle all traffic separately, e.g. ignore IKEv2 traffic, since charon
- * handles that.
- */
-struct socket_raw_socket_t {
-
- /**
- * Implements the socket_t interface.
- */
- socket_t socket;
-
-};
-
-/**
- * Create a socket_raw_socket instance.
- */
-socket_raw_socket_t *socket_raw_socket_create();
-
-#endif /** SOCKET_RAW_SOCKET_H_ @}*/
diff --git a/src/libcharon/plugins/sql/Makefile.in b/src/libcharon/plugins/sql/Makefile.in
index d04c7f6c9..a6c6cbe1e 100644
--- a/src/libcharon/plugins/sql/Makefile.in
+++ b/src/libcharon/plugins/sql/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -83,7 +84,7 @@ libstrongswan_sql_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(libstrongswan_sql_la_LDFLAGS) $(LDFLAGS) -o $@
@MONOLITHIC_FALSE@am_libstrongswan_sql_la_rpath = -rpath $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_sql_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -109,6 +110,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -203,11 +205,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -224,11 +229,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -244,6 +250,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -253,7 +260,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/sql/sql_config.c b/src/libcharon/plugins/sql/sql_config.c
index dc016012c..c614c679e 100644
--- a/src/libcharon/plugins/sql/sql_config.c
+++ b/src/libcharon/plugins/sql/sql_config.c
@@ -259,7 +259,8 @@ static ike_cfg_t *build_ike_cfg(private_sql_config_t *this, enumerator_t *e,
ike_cfg_t *ike_cfg;
ike_cfg = ike_cfg_create(certreq, force_encap,
- local, IKEV2_UDP_PORT, remote, IKEV2_UDP_PORT);
+ local, FALSE, charon->socket->get_port(charon->socket, FALSE),
+ remote, FALSE, IKEV2_UDP_PORT);
add_ike_proposals(this, ike_cfg, id);
return ike_cfg;
}
@@ -332,6 +333,7 @@ static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
mediation, mediated_by, p_type;
chunk_t l_data, r_data, p_data;
char *name, *virtual, *pool;
+ enumerator_t *enumerator;
while (e->enumerate(e,
&id, &name, &ike_cfg, &l_type, &l_data, &r_type, &r_data,
@@ -368,10 +370,25 @@ static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
if (ike)
{
peer_cfg = peer_cfg_create(
- name, 2, ike, cert_policy, uniqueid,
+ name, IKEV2, ike, cert_policy, uniqueid,
keyingtries, rekeytime, reauthtime, jitter, overtime,
- mobike, dpd_delay, vip, pool,
+ mobike, FALSE, dpd_delay, 0,
mediation, mediated_cfg, peer_id);
+ if (vip)
+ {
+ peer_cfg->add_virtual_ip(peer_cfg, vip);
+ }
+ if (pool)
+ {
+ /* attr-sql used comma separated pools, but we now completely
+ * support multiple pools directly. Support old SQL configs: */
+ enumerator = enumerator_create_token(pool, ",", " ");
+ while (enumerator->enumerate(enumerator, &pool))
+ {
+ peer_cfg->add_pool(peer_cfg, pool);
+ }
+ enumerator->destroy(enumerator);
+ }
auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, auth_method);
auth->add(auth, AUTH_RULE_IDENTITY, local_id);
diff --git a/src/libcharon/plugins/sql/sql_logger.c b/src/libcharon/plugins/sql/sql_logger.c
index 10ceacb00..6db3258d2 100644
--- a/src/libcharon/plugins/sql/sql_logger.c
+++ b/src/libcharon/plugins/sql/sql_logger.c
@@ -18,6 +18,7 @@
#include "sql_logger.h"
#include <daemon.h>
+#include <threading/thread_value.h>
typedef struct private_sql_logger_t private_sql_logger_t;
@@ -42,24 +43,23 @@ struct private_sql_logger_t {
int level;
/**
- * avoid recursive logging
+ * avoid recursive calls by the same thread
*/
- bool recursive;
+ thread_value_t *recursive;
};
-METHOD(listener_t, log_, bool,
+METHOD(logger_t, log_, void,
private_sql_logger_t *this, debug_t group, level_t level, int thread,
- ike_sa_t* ike_sa, char *format, va_list args)
+ ike_sa_t* ike_sa, const char *message)
{
- if (this->recursive)
+ if (this->recursive->get(this->recursive))
{
- return TRUE;
+ return;
}
- this->recursive = TRUE;
+ this->recursive->set(this->recursive, this->recursive);
- if (ike_sa && level <= this->level)
+ if (ike_sa)
{
- char buffer[8192];
chunk_t local_spi, remote_spi;
host_t *local_host, *remote_host;
identification_t *local_id, *remote_id;
@@ -85,8 +85,6 @@ METHOD(listener_t, log_, bool,
local_host = ike_sa->get_my_host(ike_sa);
remote_host = ike_sa->get_other_host(ike_sa);
- vsnprintf(buffer, sizeof(buffer), format, args);
-
this->db->execute(this->db, NULL, "REPLACE INTO ike_sas ("
"local_spi, remote_spi, id, initiator, "
"local_id_type, local_id_data, "
@@ -106,11 +104,16 @@ METHOD(listener_t, log_, bool,
this->db->execute(this->db, NULL, "INSERT INTO logs ("
"local_spi, signal, level, msg) VALUES (?, ?, ?, ?)",
DB_BLOB, local_spi, DB_INT, group, DB_INT, level,
- DB_TEXT, buffer);
+ DB_TEXT, message);
}
- this->recursive = FALSE;
- /* always stay registered */
- return TRUE;
+
+ this->recursive->set(this->recursive, NULL);
+}
+
+METHOD(logger_t, get_level, level_t,
+ private_sql_logger_t *this, debug_t group)
+{
+ return this->level;
}
METHOD(sql_logger_t, destroy, void,
@@ -128,14 +131,16 @@ sql_logger_t *sql_logger_create(database_t *db)
INIT(this,
.public = {
- .listener = {
+ .logger = {
.log = _log_,
+ .get_level = _get_level,
},
.destroy = _destroy,
},
.db = db,
+ .recursive = thread_value_create(NULL),
.level = lib->settings->get_int(lib->settings,
- "charon.plugins.sql.loglevel", -1),
+ "%s.plugins.sql.loglevel", -1, charon->name),
);
return &this->public;
diff --git a/src/libcharon/plugins/sql/sql_logger.h b/src/libcharon/plugins/sql/sql_logger.h
index a933705da..62dc3f361 100644
--- a/src/libcharon/plugins/sql/sql_logger.h
+++ b/src/libcharon/plugins/sql/sql_logger.h
@@ -32,9 +32,9 @@ typedef struct sql_logger_t sql_logger_t;
struct sql_logger_t {
/**
- * Implements bus_listener_t interface
+ * Implements logger_t interface
*/
- listener_t listener;
+ logger_t logger;
/**
* Destry the backend.
diff --git a/src/libcharon/plugins/sql/sql_plugin.c b/src/libcharon/plugins/sql/sql_plugin.c
index d915d4696..afbb89c83 100644
--- a/src/libcharon/plugins/sql/sql_plugin.c
+++ b/src/libcharon/plugins/sql/sql_plugin.c
@@ -64,7 +64,7 @@ METHOD(plugin_t, destroy, void,
{
charon->backends->remove_backend(charon->backends, &this->config->backend);
lib->credmgr->remove_set(lib->credmgr, &this->cred->set);
- charon->bus->remove_listener(charon->bus, &this->logger->listener);
+ charon->bus->remove_logger(charon->bus, &this->logger->logger);
this->config->destroy(this->config);
this->cred->destroy(this->cred);
this->logger->destroy(this->logger);
@@ -80,7 +80,8 @@ plugin_t *sql_plugin_create()
char *uri;
private_sql_plugin_t *this;
- uri = lib->settings->get_str(lib->settings, "charon.plugins.sql.database", NULL);
+ uri = lib->settings->get_str(lib->settings, "%s.plugins.sql.database",
+ NULL, charon->name);
if (!uri)
{
DBG1(DBG_CFG, "sql plugin: database URI not set");
@@ -110,7 +111,7 @@ plugin_t *sql_plugin_create()
charon->backends->add_backend(charon->backends, &this->config->backend);
lib->credmgr->add_set(lib->credmgr, &this->cred->set);
- charon->bus->add_listener(charon->bus, &this->logger->listener);
+ charon->bus->add_logger(charon->bus, &this->logger->logger);
return &this->public.plugin;
}
diff --git a/src/libcharon/plugins/stroke/Makefile.am b/src/libcharon/plugins/stroke/Makefile.am
index e561224e9..cebcd984f 100644
--- a/src/libcharon/plugins/stroke/Makefile.am
+++ b/src/libcharon/plugins/stroke/Makefile.am
@@ -21,6 +21,7 @@ libstrongswan_stroke_la_SOURCES = \
stroke_cred.h stroke_cred.c \
stroke_ca.h stroke_ca.c \
stroke_attribute.h stroke_attribute.c \
+ stroke_handler.h stroke_handler.c \
stroke_list.h stroke_list.c
libstrongswan_stroke_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/stroke/Makefile.in b/src/libcharon/plugins/stroke/Makefile.in
index 60f5f535a..f0db20c42 100644
--- a/src/libcharon/plugins/stroke/Makefile.in
+++ b/src/libcharon/plugins/stroke/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -77,7 +78,7 @@ LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_stroke_la_LIBADD =
am_libstrongswan_stroke_la_OBJECTS = stroke_plugin.lo stroke_socket.lo \
stroke_config.lo stroke_control.lo stroke_cred.lo stroke_ca.lo \
- stroke_attribute.lo stroke_list.lo
+ stroke_attribute.lo stroke_handler.lo stroke_list.lo
libstrongswan_stroke_la_OBJECTS = \
$(am_libstrongswan_stroke_la_OBJECTS)
libstrongswan_stroke_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@@ -86,7 +87,7 @@ libstrongswan_stroke_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@MONOLITHIC_FALSE@am_libstrongswan_stroke_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_stroke_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -112,6 +113,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -206,11 +208,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -227,11 +232,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -247,6 +253,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -256,7 +263,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -302,6 +308,7 @@ libstrongswan_stroke_la_SOURCES = \
stroke_cred.h stroke_cred.c \
stroke_ca.h stroke_ca.c \
stroke_attribute.h stroke_attribute.c \
+ stroke_handler.h stroke_handler.c \
stroke_list.h stroke_list.c
libstrongswan_stroke_la_LDFLAGS = -module -avoid-version
@@ -393,6 +400,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_config.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_control.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_cred.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_handler.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_list.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_plugin.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_socket.Plo@am__quote@
diff --git a/src/libcharon/plugins/stroke/stroke_attribute.c b/src/libcharon/plugins/stroke/stroke_attribute.c
index 1e4615e12..85fb94e9e 100644
--- a/src/libcharon/plugins/stroke/stroke_attribute.c
+++ b/src/libcharon/plugins/stroke/stroke_attribute.c
@@ -17,7 +17,6 @@
#include "stroke_attribute.h"
#include <daemon.h>
-#include <attributes/mem_pool.h>
#include <utils/linked_list.h>
#include <threading/rwlock.h>
@@ -39,12 +38,37 @@ struct private_stroke_attribute_t {
linked_list_t *pools;
/**
+ * List of connection specific attributes, as attributes_t
+ */
+ linked_list_t *attrs;
+
+ /**
* rwlock to lock access to pools
*/
rwlock_t *lock;
};
/**
+ * Attributes assigned to a connection
+ */
+typedef struct {
+ /** name of the connection */
+ char *name;
+ /** list of DNS attributes, as host_t */
+ linked_list_t *dns;
+} attributes_t;
+
+/**
+ * Destroy an attributes_t entry
+ */
+static void attributes_destroy(attributes_t *this)
+{
+ this->dns->destroy_offset(this->dns, offsetof(host_t, destroy));
+ free(this->name);
+ free(this);
+}
+
+/**
* find a pool by name
*/
static mem_pool_t *find_pool(private_stroke_attribute_t *this, char *name)
@@ -65,88 +89,246 @@ static mem_pool_t *find_pool(private_stroke_attribute_t *this, char *name)
return found;
}
-METHOD(attribute_provider_t, acquire_address, host_t*,
- private_stroke_attribute_t *this, char *name, identification_t *id,
- host_t *requested)
+/**
+ * Find an existing or not yet existing lease
+ */
+static host_t *find_addr(private_stroke_attribute_t *this, linked_list_t *pools,
+ identification_t *id, host_t *requested,
+ mem_pool_op_t operation)
{
- mem_pool_t *pool;
host_t *addr = NULL;
+ enumerator_t *enumerator;
+ mem_pool_t *pool;
+ char *name;
+
+ enumerator = pools->create_enumerator(pools);
+ while (enumerator->enumerate(enumerator, &name))
+ {
+ pool = find_pool(this, name);
+ if (pool)
+ {
+ addr = pool->acquire_address(pool, id, requested, operation);
+ if (addr)
+ {
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return addr;
+}
+
+METHOD(attribute_provider_t, acquire_address, host_t*,
+ private_stroke_attribute_t *this, linked_list_t *pools, identification_t *id,
+ host_t *requested)
+{
+ host_t *addr;
+
this->lock->read_lock(this->lock);
- pool = find_pool(this, name);
- if (pool)
+
+ addr = find_addr(this, pools, id, requested, MEM_POOL_EXISTING);
+ if (!addr)
{
- addr = pool->acquire_address(pool, id, requested);
+ addr = find_addr(this, pools, id, requested, MEM_POOL_NEW);
+ if (!addr)
+ {
+ addr = find_addr(this, pools, id, requested, MEM_POOL_REASSIGN);
+ }
}
+
this->lock->unlock(this->lock);
+
return addr;
}
METHOD(attribute_provider_t, release_address, bool,
- private_stroke_attribute_t *this, char *name, host_t *address,
- identification_t *id)
+ private_stroke_attribute_t *this, linked_list_t *pools, host_t *address,
+ identification_t *id)
{
+ enumerator_t *enumerator;
mem_pool_t *pool;
bool found = FALSE;
+ char *name;
+
+ enumerator = pools->create_enumerator(pools);
this->lock->read_lock(this->lock);
- pool = find_pool(this, name);
- if (pool)
+ while (enumerator->enumerate(enumerator, &name))
{
- found = pool->release_address(pool, address, id);
+ pool = find_pool(this, name);
+ if (pool)
+ {
+ found = pool->release_address(pool, address, id);
+ if (found)
+ {
+ break;
+ }
+ }
}
this->lock->unlock(this->lock);
+ enumerator->destroy(enumerator);
+
return found;
}
-METHOD(stroke_attribute_t, add_pool, void,
- private_stroke_attribute_t *this, stroke_msg_t *msg)
+/**
+ * Filter function to convert host to DNS configuration attributes
+ */
+static bool attr_filter(void *lock, host_t **in,
+ configuration_attribute_type_t *type,
+ void *dummy, chunk_t *data)
{
- if (msg->add_conn.other.sourceip_mask)
+ host_t *host = *in;
+
+ switch (host->get_family(host))
{
- mem_pool_t *pool;
- host_t *base = NULL;
- u_int32_t bits = 0;
+ case AF_INET:
+ *type = INTERNAL_IP4_DNS;
+ break;
+ case AF_INET6:
+ *type = INTERNAL_IP6_DNS;
+ break;
+ default:
+ return FALSE;
+ }
+ *data = host->get_address(host);
+ return TRUE;
+}
+
+METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
+ private_stroke_attribute_t *this, linked_list_t *pools,
+ identification_t *id, linked_list_t *vips)
+{
+ ike_sa_t *ike_sa;
+ peer_cfg_t *peer_cfg;
+ enumerator_t *enumerator;
+ attributes_t *attr;
- /* if %config, add an empty pool, otherwise */
- if (msg->add_conn.other.sourceip)
+ ike_sa = charon->bus->get_sa(charon->bus);
+ if (ike_sa)
+ {
+ peer_cfg = ike_sa->get_peer_cfg(ike_sa);
+ this->lock->read_lock(this->lock);
+ enumerator = this->attrs->create_enumerator(this->attrs);
+ while (enumerator->enumerate(enumerator, &attr))
{
- DBG1(DBG_CFG, "adding virtual IP address pool '%s': %s/%d",
- msg->add_conn.name, msg->add_conn.other.sourceip,
- msg->add_conn.other.sourceip_mask);
- base = host_create_from_string(msg->add_conn.other.sourceip, 0);
- if (!base)
+ if (streq(attr->name, peer_cfg->get_name(peer_cfg)))
{
- DBG1(DBG_CFG, "virtual IP address invalid, discarded");
- return;
+ enumerator->destroy(enumerator);
+ return enumerator_create_filter(
+ attr->dns->create_enumerator(attr->dns),
+ (void*)attr_filter, this->lock,
+ (void*)this->lock->unlock);
}
- bits = msg->add_conn.other.sourceip_mask;
}
- pool = mem_pool_create(msg->add_conn.name, base, bits);
- DESTROY_IF(base);
-
- this->lock->write_lock(this->lock);
- this->pools->insert_last(this->pools, pool);
+ enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
}
+ return enumerator_create_empty();
}
-METHOD(stroke_attribute_t, del_pool, void,
- private_stroke_attribute_t *this, stroke_msg_t *msg)
+METHOD(stroke_attribute_t, add_pool, void,
+ private_stroke_attribute_t *this, mem_pool_t *pool)
{
enumerator_t *enumerator;
- mem_pool_t *pool;
+ mem_pool_t *current;
+ host_t *base;
+ int size;
+
+ base = pool->get_base(pool);
+ size = pool->get_size(pool);
this->lock->write_lock(this->lock);
+
enumerator = this->pools->create_enumerator(this->pools);
- while (enumerator->enumerate(enumerator, &pool))
+ while (enumerator->enumerate(enumerator, &current))
{
- if (streq(msg->del_conn.name, pool->get_name(pool)))
+ if (base && current->get_base(current) &&
+ base->ip_equals(base, current->get_base(current)) &&
+ size == current->get_size(current))
{
- this->pools->remove_at(this->pools, enumerator);
+ DBG1(DBG_CFG, "reusing virtual IP address pool %s",
+ current->get_name(current));
pool->destroy(pool);
+ pool = NULL;
break;
}
}
enumerator->destroy(enumerator);
+
+ if (pool)
+ {
+ if (base)
+ {
+ DBG1(DBG_CFG, "adding virtual IP address pool %s",
+ pool->get_name(pool));
+ }
+ this->pools->insert_last(this->pools, pool);
+ }
+
+ this->lock->unlock(this->lock);
+}
+
+METHOD(stroke_attribute_t, add_dns, void,
+ private_stroke_attribute_t *this, stroke_msg_t *msg)
+{
+ if (msg->add_conn.other.dns)
+ {
+ enumerator_t *enumerator;
+ attributes_t *attr = NULL;
+ host_t *host;
+ char *token;
+
+ enumerator = enumerator_create_token(msg->add_conn.other.dns, ",", " ");
+ while (enumerator->enumerate(enumerator, &token))
+ {
+ host = host_create_from_string(token, 0);
+ if (host)
+ {
+ if (!attr)
+ {
+ INIT(attr,
+ .name = strdup(msg->add_conn.name),
+ .dns = linked_list_create(),
+ );
+ }
+ attr->dns->insert_last(attr->dns, host);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "ignoring invalid DNS address '%s'", token);
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (attr)
+ {
+ this->lock->write_lock(this->lock);
+ this->attrs->insert_last(this->attrs, attr);
+ this->lock->unlock(this->lock);
+ }
+ }
+}
+
+METHOD(stroke_attribute_t, del_dns, void,
+ private_stroke_attribute_t *this, stroke_msg_t *msg)
+{
+ enumerator_t *enumerator;
+ attributes_t *attr;
+
+ this->lock->write_lock(this->lock);
+
+ enumerator = this->attrs->create_enumerator(this->attrs);
+ while (enumerator->enumerate(enumerator, &attr))
+ {
+ if (streq(msg->del_conn.name, attr->name))
+ {
+ this->attrs->remove_at(this->attrs, enumerator);
+ attributes_destroy(attr);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
this->lock->unlock(this->lock);
}
@@ -158,6 +340,11 @@ static bool pool_filter(void *lock, mem_pool_t **poolp, const char **name,
void *d3, u_int *offline)
{
mem_pool_t *pool = *poolp;
+
+ if (pool->get_size(pool) == 0)
+ {
+ return FALSE;
+ }
*name = pool->get_name(pool);
*size = pool->get_size(pool);
*online = pool->get_online(pool);
@@ -166,7 +353,7 @@ static bool pool_filter(void *lock, mem_pool_t **poolp, const char **name,
}
METHOD(stroke_attribute_t, create_pool_enumerator, enumerator_t*,
- private_stroke_attribute_t *this)
+ private_stroke_attribute_t *this)
{
this->lock->read_lock(this->lock);
return enumerator_create_filter(this->pools->create_enumerator(this->pools),
@@ -175,7 +362,7 @@ METHOD(stroke_attribute_t, create_pool_enumerator, enumerator_t*,
}
METHOD(stroke_attribute_t, create_lease_enumerator, enumerator_t*,
- private_stroke_attribute_t *this, char *name)
+ private_stroke_attribute_t *this, char *name)
{
mem_pool_t *pool;
this->lock->read_lock(this->lock);
@@ -190,10 +377,11 @@ METHOD(stroke_attribute_t, create_lease_enumerator, enumerator_t*,
}
METHOD(stroke_attribute_t, destroy, void,
- private_stroke_attribute_t *this)
+ private_stroke_attribute_t *this)
{
this->lock->destroy(this->lock);
this->pools->destroy_offset(this->pools, offsetof(mem_pool_t, destroy));
+ this->attrs->destroy_function(this->attrs, (void*)attributes_destroy);
free(this);
}
@@ -209,15 +397,17 @@ stroke_attribute_t *stroke_attribute_create()
.provider = {
.acquire_address = _acquire_address,
.release_address = _release_address,
- .create_attribute_enumerator = enumerator_create_empty,
+ .create_attribute_enumerator = _create_attribute_enumerator,
},
.add_pool = _add_pool,
- .del_pool = _del_pool,
+ .add_dns = _add_dns,
+ .del_dns = _del_dns,
.create_pool_enumerator = _create_pool_enumerator,
.create_lease_enumerator = _create_lease_enumerator,
.destroy = _destroy,
},
.pools = linked_list_create(),
+ .attrs = linked_list_create(),
.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
);
diff --git a/src/libcharon/plugins/stroke/stroke_attribute.h b/src/libcharon/plugins/stroke/stroke_attribute.h
index 249a9899b..f1b9d135b 100644
--- a/src/libcharon/plugins/stroke/stroke_attribute.h
+++ b/src/libcharon/plugins/stroke/stroke_attribute.h
@@ -23,6 +23,7 @@
#include <stroke_msg.h>
#include <attributes/attribute_provider.h>
+#include <attributes/mem_pool.h>
typedef struct stroke_attribute_t stroke_attribute_t;
@@ -37,18 +38,28 @@ struct stroke_attribute_t {
attribute_provider_t provider;
/**
- * Add a virtual IP address pool.
+ * Add a memory pool to this virtual IP backend.
*
- * @param msg stroke message
+ * The pool gets owned by the provider, or destroyed if such a pool
+ * is already registered.
+ *
+ * @param pool virtual IP pool to add
+ */
+ void (*add_pool)(stroke_attribute_t *this, mem_pool_t *pool);
+
+ /**
+ * Add connection specific DNS servers.
+ *
+ * @param msg stroke add message
*/
- void (*add_pool)(stroke_attribute_t *this, stroke_msg_t *msg);
+ void (*add_dns)(stroke_attribute_t *this, stroke_msg_t *msg);
/**
- * Remove a virtual IP address pool.
+ * Remove connection specific DNS servers.
*
- * @param msg stroke message
+ * @param msg stroke del message
*/
- void (*del_pool)(stroke_attribute_t *this, stroke_msg_t *msg);
+ void (*del_dns)(stroke_attribute_t *this, stroke_msg_t *msg);
/**
* Create an enumerator over installed pools.
diff --git a/src/libcharon/plugins/stroke/stroke_ca.c b/src/libcharon/plugins/stroke/stroke_ca.c
index bec35a661..763b4cc0f 100644
--- a/src/libcharon/plugins/stroke/stroke_ca.c
+++ b/src/libcharon/plugins/stroke/stroke_ca.c
@@ -348,16 +348,18 @@ METHOD(stroke_ca_t, check_for_hash_and_url, void,
enumerator = this->sections->create_enumerator(this->sections);
while (enumerator->enumerate(enumerator, (void**)&section))
{
- if (section->certuribase && cert->issued_by(cert, section->cert))
+ if (section->certuribase && cert->issued_by(cert, section->cert, NULL))
{
chunk_t hash, encoded;
if (cert->get_encoding(cert, CERT_ASN1_DER, &encoded))
{
- hasher->allocate_hash(hasher, encoded, &hash);
- section->hashes->insert_last(section->hashes,
+ if (hasher->allocate_hash(hasher, encoded, &hash))
+ {
+ section->hashes->insert_last(section->hashes,
identification_create_from_encoding(ID_KEY_ID, hash));
- chunk_free(&hash);
+ chunk_free(&hash);
+ }
chunk_free(&encoded);
}
break;
diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c
index 483e3d253..e43672b18 100644
--- a/src/libcharon/plugins/stroke/stroke_config.c
+++ b/src/libcharon/plugins/stroke/stroke_config.c
@@ -52,6 +52,11 @@ struct private_stroke_config_t {
* credentials
*/
stroke_cred_t *cred;
+
+ /**
+ * Virtual IP pool / DNS backend
+ */
+ stroke_attribute_t *attributes;
};
METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
@@ -186,48 +191,48 @@ static ike_cfg_t *build_ike_cfg(private_stroke_config_t *this, stroke_msg_t *msg
{
stroke_end_t tmp_end;
ike_cfg_t *ike_cfg;
- char *interface;
host_t *host;
+ u_int16_t ikeport;
host = host_create_from_dns(msg->add_conn.other.address, 0, 0);
if (host)
{
- interface = hydra->kernel_interface->get_interface(
- hydra->kernel_interface, host);
- host->destroy(host);
- if (interface)
+ 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;
- free(interface);
+ host->destroy(host);
}
else
{
+ host->destroy(host);
host = host_create_from_dns(msg->add_conn.me.address, 0, 0);
if (host)
{
- interface = hydra->kernel_interface->get_interface(
- hydra->kernel_interface, host);
- host->destroy(host);
- if (!interface)
+ if (!hydra->kernel_interface->get_interface(
+ hydra->kernel_interface, host, NULL))
{
DBG1(DBG_CFG, "left nor right host is our side, "
"assuming left=local");
}
- else
- {
- free(interface);
- }
-
+ host->destroy(host);
}
}
}
+ ikeport = msg->add_conn.me.ikeport;
+ ikeport = (ikeport == IKEV2_UDP_PORT) ?
+ charon->socket->get_port(charon->socket, FALSE) : ikeport;
ike_cfg = ike_cfg_create(msg->add_conn.other.sendcert != CERT_NEVER_SEND,
- msg->add_conn.force_encap,
- msg->add_conn.me.address, msg->add_conn.me.ikeport,
- msg->add_conn.other.address, msg->add_conn.other.ikeport);
+ msg->add_conn.force_encap,
+ msg->add_conn.me.address,
+ msg->add_conn.me.allow_any,
+ ikeport,
+ msg->add_conn.other.address,
+ msg->add_conn.other.allow_any,
+ msg->add_conn.other.ikeport);
add_proposals(this, msg->add_conn.algorithms.ike, ike_cfg, NULL);
return ike_cfg;
}
@@ -257,6 +262,103 @@ static void build_crl_policy(auth_cfg_t *cfg, bool local, int policy)
}
/**
+ * Parse public key / signature strength constraints
+ */
+static void parse_pubkey_constraints(char *auth, auth_cfg_t *cfg)
+{
+ enumerator_t *enumerator;
+ bool rsa = FALSE, ecdsa = FALSE, rsa_len = FALSE, ecdsa_len = FALSE;
+ int strength;
+ char *token;
+
+ enumerator = enumerator_create_token(auth, "-", "");
+ while (enumerator->enumerate(enumerator, &token))
+ {
+ bool found = FALSE;
+ int i;
+ struct {
+ char *name;
+ signature_scheme_t scheme;
+ key_type_t key;
+ } schemes[] = {
+ { "md5", SIGN_RSA_EMSA_PKCS1_MD5, KEY_RSA, },
+ { "sha1", SIGN_RSA_EMSA_PKCS1_SHA1, KEY_RSA, },
+ { "sha224", SIGN_RSA_EMSA_PKCS1_SHA224, KEY_RSA, },
+ { "sha256", SIGN_RSA_EMSA_PKCS1_SHA256, KEY_RSA, },
+ { "sha384", SIGN_RSA_EMSA_PKCS1_SHA384, KEY_RSA, },
+ { "sha512", SIGN_RSA_EMSA_PKCS1_SHA512, KEY_RSA, },
+ { "sha1", SIGN_ECDSA_WITH_SHA1_DER, KEY_ECDSA, },
+ { "sha256", SIGN_ECDSA_WITH_SHA256_DER, KEY_ECDSA, },
+ { "sha384", SIGN_ECDSA_WITH_SHA384_DER, KEY_ECDSA, },
+ { "sha512", SIGN_ECDSA_WITH_SHA512_DER, KEY_ECDSA, },
+ { "sha256", SIGN_ECDSA_256, KEY_ECDSA, },
+ { "sha384", SIGN_ECDSA_384, KEY_ECDSA, },
+ { "sha512", SIGN_ECDSA_521, KEY_ECDSA, },
+ };
+
+ if (rsa_len || ecdsa_len)
+ { /* expecting a key strength token */
+ strength = atoi(token);
+ if (strength)
+ {
+ if (rsa_len)
+ {
+ cfg->add(cfg, AUTH_RULE_RSA_STRENGTH, (uintptr_t)strength);
+ }
+ else if (ecdsa_len)
+ {
+ cfg->add(cfg, AUTH_RULE_ECDSA_STRENGTH, (uintptr_t)strength);
+ }
+ }
+ rsa_len = ecdsa_len = FALSE;
+ if (strength)
+ {
+ continue;
+ }
+ }
+ if (streq(token, "rsa"))
+ {
+ rsa = rsa_len = TRUE;
+ continue;
+ }
+ if (streq(token, "ecdsa"))
+ {
+ ecdsa = ecdsa_len = TRUE;
+ continue;
+ }
+ if (streq(token, "pubkey"))
+ {
+ continue;
+ }
+
+ for (i = 0; i < countof(schemes); i++)
+ {
+ if (streq(schemes[i].name, token))
+ {
+ /* for each matching string, allow the scheme, if:
+ * - it is an RSA scheme, and we enforced RSA
+ * - it is an ECDSA scheme, and we enforced ECDSA
+ * - it is not a key type specific scheme
+ */
+ if ((rsa && schemes[i].key == KEY_RSA) ||
+ (ecdsa && schemes[i].key == KEY_ECDSA) ||
+ (!rsa && !ecdsa))
+ {
+ cfg->add(cfg, AUTH_RULE_SIGNATURE_SCHEME,
+ (uintptr_t)schemes[i].scheme);
+ }
+ found = TRUE;
+ }
+ }
+ if (!found)
+ {
+ DBG1(DBG_CFG, "ignoring invalid auth token: '%s'", token);
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
* build authentication config
*/
static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this,
@@ -264,10 +366,10 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this,
{
identification_t *identity;
certificate_t *certificate;
- char *auth, *id, *pubkey, *cert, *ca;
+ char *auth, *id, *pubkey, *cert, *ca, *groups;
stroke_end_t *end, *other_end;
auth_cfg_t *cfg;
- char eap_buf[32];
+ bool loose = FALSE;
/* select strings */
if (local)
@@ -310,52 +412,17 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this,
ca = other_end->ca2;
}
}
+ if (id && *id == '%' && !streq(id, "%any"))
+ { /* has only an effect on rightid/2 */
+ loose = !local;
+ id++;
+ }
if (!auth)
{
if (primary)
{
- if (local)
- { /* "leftauth" not defined, fall back to deprecated "authby" */
- switch (msg->add_conn.auth_method)
- {
- default:
- case AUTH_CLASS_PUBKEY:
- auth = "pubkey";
- break;
- case AUTH_CLASS_PSK:
- auth = "psk";
- break;
- case AUTH_CLASS_EAP:
- auth = "eap";
- break;
- case AUTH_CLASS_ANY:
- auth = "any";
- break;
- }
- }
- else
- { /* "rightauth" not defined, fall back to deprecated "eap" */
- if (msg->add_conn.eap_type)
- {
- if (msg->add_conn.eap_vendor)
- {
- snprintf(eap_buf, sizeof(eap_buf), "eap-%d-%d",
- msg->add_conn.eap_type,
- msg->add_conn.eap_vendor);
- }
- else
- {
- snprintf(eap_buf, sizeof(eap_buf), "eap-%d",
- msg->add_conn.eap_type);
- }
- auth = eap_buf;
- }
- else
- { /* not EAP => no constraints for this peer */
- auth = "any";
- }
- }
+ auth = "pubkey";
}
else
{ /* no second authentication round, fine. But load certificates
@@ -398,7 +465,18 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this,
}
}
}
- cfg->add(cfg, AUTH_RULE_IDENTITY, identity);
+ if (identity->get_type(identity) != ID_ANY)
+ {
+ cfg->add(cfg, AUTH_RULE_IDENTITY, identity);
+ if (loose)
+ {
+ cfg->add(cfg, AUTH_RULE_IDENTITY_LOOSE, TRUE);
+ }
+ }
+ else
+ {
+ identity->destroy(identity);
+ }
/* add raw RSA public key */
pubkey = end->rsakey;
@@ -431,12 +509,13 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this,
}
/* groups */
- if (end->groups)
+ groups = primary ? end->groups : end->groups2;
+ if (groups)
{
enumerator_t *enumerator;
char *group;
- enumerator = enumerator_create_token(end->groups, ",", " ");
+ enumerator = enumerator_create_token(groups, ",", " ");
while (enumerator->enumerate(enumerator, &group))
{
cfg->add(cfg, AUTH_RULE_GROUP,
@@ -460,75 +539,51 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this,
}
/* authentication metod (class, actually) */
- if (streq(auth, "pubkey") ||
+ if (strneq(auth, "pubkey", strlen("pubkey")) ||
strneq(auth, "rsa", strlen("rsa")) ||
strneq(auth, "ecdsa", strlen("ecdsa")))
{
- u_int strength;
-
cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
build_crl_policy(cfg, local, msg->add_conn.crl_policy);
- if (sscanf(auth, "rsa-%d", &strength) == 1)
- {
- cfg->add(cfg, AUTH_RULE_RSA_STRENGTH, (uintptr_t)strength);
- }
- if (sscanf(auth, "ecdsa-%d", &strength) == 1)
- {
- cfg->add(cfg, AUTH_RULE_ECDSA_STRENGTH, (uintptr_t)strength);
- }
+ parse_pubkey_constraints(auth, cfg);
}
else if (streq(auth, "psk") || streq(auth, "secret"))
{
cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
}
+ else if (strneq(auth, "xauth", 5))
+ {
+ char *pos;
+
+ pos = strchr(auth, '-');
+ if (pos)
+ {
+ cfg->add(cfg, AUTH_RULE_XAUTH_BACKEND, strdup(++pos));
+ }
+ cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_XAUTH);
+ if (msg->add_conn.xauth_identity)
+ {
+ cfg->add(cfg, AUTH_RULE_XAUTH_IDENTITY,
+ identification_create_from_string(msg->add_conn.xauth_identity));
+ }
+ }
else if (strneq(auth, "eap", 3))
{
- enumerator_t *enumerator;
- char *str;
- int i = 0, type = 0, vendor;
+ eap_vendor_type_t *type;
cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
- /* parse EAP string, format: eap[-type[-vendor]] */
- enumerator = enumerator_create_token(auth, "-", " ");
- while (enumerator->enumerate(enumerator, &str))
+ type = eap_vendor_type_from_string(auth);
+ if (type)
{
- switch (i)
+ cfg->add(cfg, AUTH_RULE_EAP_TYPE, type->type);
+ if (type->vendor)
{
- case 1:
- type = eap_type_from_string(str);
- if (!type)
- {
- type = atoi(str);
- if (!type)
- {
- DBG1(DBG_CFG, "unknown EAP method: %s", str);
- break;
- }
- }
- cfg->add(cfg, AUTH_RULE_EAP_TYPE, type);
- break;
- case 2:
- if (type)
- {
- vendor = atoi(str);
- if (vendor)
- {
- cfg->add(cfg, AUTH_RULE_EAP_VENDOR, vendor);
- }
- else
- {
- DBG1(DBG_CFG, "unknown EAP vendor: %s", str);
- }
- }
- break;
- default:
- break;
+ cfg->add(cfg, AUTH_RULE_EAP_VENDOR, type->vendor);
}
- i++;
+ free(type);
}
- enumerator->destroy(enumerator);
if (msg->add_conn.eap_identity)
{
@@ -570,7 +625,6 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
{
identification_t *peer_id = NULL;
peer_cfg_t *mediated_by = NULL;
- host_t *vip = NULL;
unique_policy_t unique;
u_int32_t rekey = 0, reauth = 0, over, jitter;
peer_cfg_t *peer_cfg;
@@ -629,38 +683,6 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
{
rekey = msg->add_conn.rekey.ike_lifetime - over;
}
- if (msg->add_conn.me.sourceip_mask)
- {
- if (msg->add_conn.me.sourceip)
- {
- vip = host_create_from_string(msg->add_conn.me.sourceip, 0);
- }
- if (!vip)
- { /* if it is set to something like %poolname, request an address */
- if (msg->add_conn.me.subnets)
- { /* use the same address as in subnet, if any */
- if (strchr(msg->add_conn.me.subnets, '.'))
- {
- vip = host_create_any(AF_INET);
- }
- else
- {
- vip = host_create_any(AF_INET6);
- }
- }
- else
- {
- if (strchr(ike_cfg->get_my_addr(ike_cfg), ':'))
- {
- vip = host_create_any(AF_INET6);
- }
- else
- {
- vip = host_create_any(AF_INET);
- }
- }
- }
- }
switch (msg->add_conn.unique)
{
case 1: /* yes */
@@ -670,6 +692,9 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
case 3: /* keep */
unique = UNIQUE_KEEP;
break;
+ case 4: /* never */
+ unique = UNIQUE_NEVER;
+ break;
default: /* no */
unique = UNIQUE_NO;
break;
@@ -683,14 +708,131 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
* the pool name as the connection name, which the attribute provider
* uses to serve pool addresses. */
peer_cfg = peer_cfg_create(msg->add_conn.name,
- msg->add_conn.ikev2 ? 2 : 1, ike_cfg,
+ msg->add_conn.version, ike_cfg,
msg->add_conn.me.sendcert, unique,
msg->add_conn.rekey.tries, rekey, reauth, jitter, over,
- msg->add_conn.mobike, msg->add_conn.dpd.delay,
- vip, msg->add_conn.other.sourceip_mask ?
- msg->add_conn.name : msg->add_conn.other.sourceip,
+ msg->add_conn.mobike, msg->add_conn.aggressive,
+ msg->add_conn.dpd.delay, msg->add_conn.dpd.timeout,
msg->add_conn.ikeme.mediation, mediated_by, peer_id);
+ if (msg->add_conn.other.sourceip)
+ {
+ enumerator_t *enumerator;
+ char *token;
+
+ enumerator = enumerator_create_token(msg->add_conn.other.sourceip,
+ ",", " ");
+ while (enumerator->enumerate(enumerator, &token))
+ {
+ if (streq(token, "%modeconfig") || streq(token, "%modecfg") ||
+ streq(token, "%config") || streq(token, "%cfg") ||
+ streq(token, "%config4") || streq(token, "%config6"))
+ {
+ /* empty pool, uses connection name */
+ this->attributes->add_pool(this->attributes,
+ mem_pool_create(msg->add_conn.name, NULL, 0));
+ peer_cfg->add_pool(peer_cfg, msg->add_conn.name);
+ }
+ else if (*token == '%')
+ {
+ /* external named pool */
+ peer_cfg->add_pool(peer_cfg, token + 1);
+ }
+ else
+ {
+ /* in-memory pool, named using CIDR notation */
+ host_t *base;
+ int bits;
+
+ base = host_create_from_subnet(token, &bits);
+ if (base)
+ {
+ this->attributes->add_pool(this->attributes,
+ mem_pool_create(token, base, bits));
+ peer_cfg->add_pool(peer_cfg, token);
+ base->destroy(base);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "IP pool %s invalid, ignored", token);
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ if (msg->add_conn.me.sourceip)
+ {
+ enumerator_t *enumerator;
+ char *token;
+
+ enumerator = enumerator_create_token(msg->add_conn.me.sourceip, ",", " ");
+ while (enumerator->enumerate(enumerator, &token))
+ {
+ host_t *vip = NULL;
+
+ if (streq(token, "%modeconfig") || streq(token, "%modecfg") ||
+ streq(token, "%config") || streq(token, "%cfg"))
+ { /* try to deduce an address family */
+ if (msg->add_conn.me.subnets)
+ { /* use the same family as in local subnet, if any */
+ if (strchr(msg->add_conn.me.subnets, '.'))
+ {
+ vip = host_create_any(AF_INET);
+ }
+ else
+ {
+ vip = host_create_any(AF_INET6);
+ }
+ }
+ else if (msg->add_conn.other.subnets)
+ { /* use the same family as in remote subnet, if any */
+ if (strchr(msg->add_conn.other.subnets, '.'))
+ {
+ vip = host_create_any(AF_INET);
+ }
+ else
+ {
+ vip = host_create_any(AF_INET6);
+ }
+ }
+ else
+ {
+ if (strchr(ike_cfg->get_my_addr(ike_cfg, NULL), ':'))
+ {
+ vip = host_create_any(AF_INET6);
+ }
+ else
+ {
+ vip = host_create_any(AF_INET);
+ }
+ }
+ }
+ else if (streq(token, "%config4"))
+ {
+ vip = host_create_any(AF_INET);
+ }
+ else if (streq(token, "%config6"))
+ {
+ vip = host_create_any(AF_INET6);
+ }
+ else
+ {
+ vip = host_create_from_string(token, 0);
+ if (vip)
+ {
+ DBG1(DBG_CFG, "ignored invalid subnet token: %s", token);
+ }
+ }
+
+ if (vip)
+ {
+ peer_cfg->add_virtual_ip(peer_cfg, vip);
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+
/* build leftauth= */
auth_cfg = build_auth_cfg(this, msg, TRUE, TRUE);
if (auth_cfg)
@@ -1029,8 +1171,8 @@ METHOD(stroke_config_t, set_user_credentials, void,
return;
}
- /* replace/set the username in the first EAP auth_cfg, also look for a
- * suitable remote ID.
+ /* replace/set the username in the first EAP/XAuth auth_cfg, also look for
+ * a suitable remote ID.
* note that adding the identity here is not fully thread-safe as the
* peer_cfg and in turn the auth_cfg could be in use. for the default use
* case (setting user credentials before upping the connection) this will
@@ -1049,16 +1191,25 @@ METHOD(stroke_config_t, set_user_credentials, void,
}
auth_class = (uintptr_t)auth_cfg->get(auth_cfg, AUTH_RULE_AUTH_CLASS);
- if (auth_class == AUTH_CLASS_EAP)
+ if (auth_class == AUTH_CLASS_EAP || auth_class == AUTH_CLASS_XAUTH)
{
- auth_cfg->add(auth_cfg, AUTH_RULE_EAP_IDENTITY, id->clone(id));
- /* if aaa_identity is specified use that as remote ID */
- identity = auth_cfg->get(auth_cfg, AUTH_RULE_AAA_IDENTITY);
- if (identity && identity->get_type(identity) != ID_ANY)
+ if (auth_class == AUTH_CLASS_EAP)
{
- gw = identity;
+ auth_cfg->add(auth_cfg, AUTH_RULE_EAP_IDENTITY, id->clone(id));
+ /* if aaa_identity is specified use that as remote ID */
+ identity = auth_cfg->get(auth_cfg, AUTH_RULE_AAA_IDENTITY);
+ if (identity && identity->get_type(identity) != ID_ANY)
+ {
+ gw = identity;
+ }
+ DBG1(DBG_CFG, " configured EAP-Identity %Y", id);
+ }
+ else
+ {
+ auth_cfg->add(auth_cfg, AUTH_RULE_XAUTH_IDENTITY,
+ id->clone(id));
+ DBG1(DBG_CFG, " configured XAuth username %Y", id);
}
- DBG1(DBG_CFG, " configured EAP-Identity %Y", id);
type = SHARED_EAP;
break;
}
@@ -1149,7 +1300,8 @@ METHOD(stroke_config_t, destroy, void,
/*
* see header file
*/
-stroke_config_t *stroke_config_create(stroke_ca_t *ca, stroke_cred_t *cred)
+stroke_config_t *stroke_config_create(stroke_ca_t *ca, stroke_cred_t *cred,
+ stroke_attribute_t *attributes)
{
private_stroke_config_t *this;
@@ -1169,6 +1321,7 @@ stroke_config_t *stroke_config_create(stroke_ca_t *ca, stroke_cred_t *cred)
.mutex = mutex_create(MUTEX_TYPE_RECURSIVE),
.ca = ca,
.cred = cred,
+ .attributes = attributes,
);
return &this->public;
diff --git a/src/libcharon/plugins/stroke/stroke_config.h b/src/libcharon/plugins/stroke/stroke_config.h
index 450d517f3..894e03ce4 100644
--- a/src/libcharon/plugins/stroke/stroke_config.h
+++ b/src/libcharon/plugins/stroke/stroke_config.h
@@ -26,6 +26,7 @@
#include <stroke_msg.h>
#include "stroke_ca.h"
#include "stroke_cred.h"
+#include "stroke_attribute.h"
typedef struct stroke_config_t stroke_config_t;
@@ -71,6 +72,7 @@ struct stroke_config_t {
/**
* Create a stroke_config instance.
*/
-stroke_config_t *stroke_config_create(stroke_ca_t *ca, stroke_cred_t *cred);
+stroke_config_t *stroke_config_create(stroke_ca_t *ca, stroke_cred_t *cred,
+ stroke_attribute_t *attributes);
#endif /** STROKE_CONFIG_H_ @}*/
diff --git a/src/libcharon/plugins/stroke/stroke_control.c b/src/libcharon/plugins/stroke/stroke_control.c
index 729e9d757..233d4088f 100644
--- a/src/libcharon/plugins/stroke/stroke_control.c
+++ b/src/libcharon/plugins/stroke/stroke_control.c
@@ -58,11 +58,11 @@ struct stroke_log_info_t {
* logging to the stroke interface
*/
static bool stroke_log(stroke_log_info_t *info, debug_t group, level_t level,
- ike_sa_t *ike_sa, char *format, va_list args)
+ ike_sa_t *ike_sa, char *message)
{
if (level <= info->level)
{
- if (vfprintf(info->out, format, args) < 0 ||
+ if (fprintf(info->out, "%s", message) < 0 ||
fprintf(info->out, "\n") < 0 ||
fflush(info->out) != 0)
{
@@ -126,14 +126,6 @@ METHOD(stroke_control_t, initiate, void,
msg->initiate.name);
if (peer_cfg)
{
- if (peer_cfg->get_ike_version(peer_cfg) != 2)
- {
- DBG1(DBG_CFG, "ignoring initiation request for IKEv%d config",
- peer_cfg->get_ike_version(peer_cfg));
- peer_cfg->destroy(peer_cfg);
- return;
- }
-
child_cfg = get_child_from_peer(peer_cfg, msg->initiate.name);
if (child_cfg == NULL)
{
@@ -157,14 +149,10 @@ METHOD(stroke_control_t, initiate, void,
}
else
{
- enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
- NULL, NULL, NULL, NULL);
+ enumerator = charon->backends->create_peer_cfg_enumerator(
+ charon->backends, NULL, NULL, NULL, NULL, IKE_ANY);
while (enumerator->enumerate(enumerator, &peer_cfg))
{
- if (peer_cfg->get_ike_version(peer_cfg) != 2)
- {
- continue;
- }
child_cfg = get_child_from_peer(peer_cfg, msg->initiate.name);
if (child_cfg)
{
@@ -419,10 +407,10 @@ METHOD(stroke_control_t, rekey, void,
METHOD(stroke_control_t, terminate_srcip, void,
private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
{
- enumerator_t *enumerator;
+ enumerator_t *enumerator, *vips;
ike_sa_t *ike_sa;
host_t *start = NULL, *end = NULL, *vip;
- chunk_t chunk_start, chunk_end = chunk_empty, chunk_vip;
+ chunk_t chunk_start, chunk_end = chunk_empty, chunk;
if (msg->terminate_srcip.start)
{
@@ -450,33 +438,40 @@ METHOD(stroke_control_t, terminate_srcip, void,
charon->controller, TRUE);
while (enumerator->enumerate(enumerator, &ike_sa))
{
- vip = ike_sa->get_virtual_ip(ike_sa, FALSE);
- if (!vip)
- {
- continue;
- }
- if (!end)
+ bool match = FALSE;
+
+ vips = ike_sa->create_virtual_ip_enumerator(ike_sa, FALSE);
+ while (vips->enumerate(vips, &vip))
{
- if (!vip->ip_equals(vip, start))
+ if (!end)
{
- continue;
+ if (vip->ip_equals(vip, start))
+ {
+ match = TRUE;
+ break;
+ }
}
- }
- else
- {
- chunk_vip = vip->get_address(vip);
- if (chunk_vip.len != chunk_start.len ||
- chunk_vip.len != chunk_end.len ||
- memcmp(chunk_vip.ptr, chunk_start.ptr, chunk_vip.len) < 0 ||
- memcmp(chunk_vip.ptr, chunk_end.ptr, chunk_vip.len) > 0)
+ else
{
- continue;
+ chunk = vip->get_address(vip);
+ if (chunk.len == chunk_start.len &&
+ chunk.len == chunk_end.len &&
+ memcmp(chunk.ptr, chunk_start.ptr, chunk.len) >= 0 &&
+ memcmp(chunk.ptr, chunk_end.ptr, chunk.len) <= 0)
+ {
+ match = TRUE;
+ break;
+ }
}
}
+ vips->destroy(vips);
- /* schedule delete asynchronously */
- lib->processor->queue_job(lib->processor, (job_t*)
+ if (match)
+ {
+ /* schedule delete asynchronously */
+ lib->processor->queue_job(lib->processor, (job_t*)
delete_ike_sa_job_create(ike_sa->get_id(ike_sa), TRUE));
+ }
}
enumerator->destroy(enumerator);
start->destroy(start);
@@ -568,14 +563,6 @@ METHOD(stroke_control_t, route, void,
msg->route.name);
if (peer_cfg)
{
- if (peer_cfg->get_ike_version(peer_cfg) != 2)
- {
- DBG1(DBG_CFG, "ignoring initiation request for IKEv%d config",
- peer_cfg->get_ike_version(peer_cfg));
- peer_cfg->destroy(peer_cfg);
- return;
- }
-
child_cfg = get_child_from_peer(peer_cfg, msg->route.name);
if (child_cfg == NULL)
{
@@ -599,14 +586,10 @@ METHOD(stroke_control_t, route, void,
}
else
{
- enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
- NULL, NULL, NULL, NULL);
+ enumerator = charon->backends->create_peer_cfg_enumerator(
+ charon->backends, NULL, NULL, NULL, NULL, IKE_ANY);
while (enumerator->enumerate(enumerator, &peer_cfg))
{
- if (peer_cfg->get_ike_version(peer_cfg) != 2)
- {
- continue;
- }
child_cfg = get_child_from_peer(peer_cfg, msg->route.name);
if (child_cfg)
{
diff --git a/src/libcharon/plugins/stroke/stroke_cred.c b/src/libcharon/plugins/stroke/stroke_cred.c
index a2a6d6d9f..ebc09c0d5 100644
--- a/src/libcharon/plugins/stroke/stroke_cred.c
+++ b/src/libcharon/plugins/stroke/stroke_cred.c
@@ -675,7 +675,7 @@ static bool load_pin(private_stroke_cred_t *this, chunk_t line, int line_nr,
pin_data.keyid = chunk;
pin_data.try = 1;
cb = callback_cred_create_shared((void*)pin_cb, &pin_data);
- lib->credmgr->add_local_set(lib->credmgr, &cb->set);
+ lib->credmgr->add_local_set(lib->credmgr, &cb->set, FALSE);
}
else
{
@@ -684,7 +684,7 @@ static bool load_pin(private_stroke_cred_t *this, chunk_t line, int line_nr,
id = identification_create_from_encoding(ID_KEY_ID, chunk);
mem = mem_cred_create();
mem->add_shared(mem, shared, id, NULL);
- lib->credmgr->add_local_set(lib->credmgr, &mem->set);
+ lib->credmgr->add_local_set(lib->credmgr, &mem->set, FALSE);
}
/* unlock: smartcard needs the pin and potentially calls public set */
@@ -722,7 +722,7 @@ static bool load_pin(private_stroke_cred_t *this, chunk_t line, int line_nr,
if (key)
{
- DBG1(DBG_CFG, " loaded private key from %.*s", sc.len, sc.ptr);
+ DBG1(DBG_CFG, " loaded private key from %.*s", (int)sc.len, sc.ptr);
this->creds->add_key(this->creds, key);
}
return TRUE;
@@ -792,7 +792,7 @@ static bool load_private(private_stroke_cred_t *this, chunk_t line, int line_nr,
pp_data.path = path;
pp_data.try = 1;
cb = callback_cred_create_shared((void*)passphrase_cb, &pp_data);
- lib->credmgr->add_local_set(lib->credmgr, &cb->set);
+ lib->credmgr->add_local_set(lib->credmgr, &cb->set, FALSE);
key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, key_type,
BUILD_FROM_FILE, path, BUILD_END);
@@ -809,7 +809,7 @@ static bool load_private(private_stroke_cred_t *this, chunk_t line, int line_nr,
shared = shared_key_create(SHARED_PRIVATE_KEY_PASS, secret);
mem = mem_cred_create();
mem->add_shared(mem, shared, NULL);
- lib->credmgr->add_local_set(lib->credmgr, &mem->set);
+ lib->credmgr->add_local_set(lib->credmgr, &mem->set, FALSE);
key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, key_type,
BUILD_FROM_FILE, path, BUILD_END);
@@ -1181,7 +1181,8 @@ stroke_cred_t *stroke_cred_create()
lib->credmgr->add_set(lib->credmgr, &this->creds->set);
this->force_ca_cert = lib->settings->get_bool(lib->settings,
- "charon.plugins.stroke.ignore_missing_ca_basic_constraint", FALSE);
+ "%s.plugins.stroke.ignore_missing_ca_basic_constraint",
+ FALSE, charon->name);
load_certs(this);
load_secrets(this, SECRETS_FILE, 0, NULL);
diff --git a/src/libcharon/plugins/stroke/stroke_handler.c b/src/libcharon/plugins/stroke/stroke_handler.c
new file mode 100644
index 000000000..523151efb
--- /dev/null
+++ b/src/libcharon/plugins/stroke/stroke_handler.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 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 "stroke_handler.h"
+
+#include <daemon.h>
+#include <utils/linked_list.h>
+#include <threading/rwlock.h>
+
+typedef struct private_stroke_handler_t private_stroke_handler_t;
+
+/**
+ * Private data of an stroke_handler_t object.
+ */
+struct private_stroke_handler_t {
+
+ /**
+ * Public stroke_handler_t interface.
+ */
+ stroke_handler_t public;
+
+ /**
+ * List of connection specific attributes, as attributes_t
+ */
+ linked_list_t *attrs;
+
+ /**
+ * rwlock to lock access to pools
+ */
+ rwlock_t *lock;
+};
+
+/**
+ * Attributes assigned to a connection
+ */
+typedef struct {
+ /** name of the connection */
+ char *name;
+ /** list of DNS attributes, as host_t */
+ linked_list_t *dns;
+} attributes_t;
+
+/**
+ * Destroy an attributes_t entry
+ */
+static void attributes_destroy(attributes_t *this)
+{
+ this->dns->destroy_offset(this->dns, offsetof(host_t, destroy));
+ free(this->name);
+ free(this);
+}
+
+/**
+ * Filter function to convert host to DNS configuration attributes
+ */
+static bool attr_filter(void *lock, host_t **in,
+ configuration_attribute_type_t *type,
+ void *dummy, chunk_t *data)
+{
+ host_t *host = *in;
+
+ switch (host->get_family(host))
+ {
+ case AF_INET:
+ *type = INTERNAL_IP4_DNS;
+ break;
+ case AF_INET6:
+ *type = INTERNAL_IP6_DNS;
+ break;
+ default:
+ return FALSE;
+ }
+ if (host->is_anyaddr(host))
+ {
+ *data = chunk_empty;
+ }
+ else
+ {
+ *data = host->get_address(host);
+ }
+ return TRUE;
+}
+
+METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*,
+ private_stroke_handler_t *this, identification_t *server,
+ linked_list_t *vips)
+{
+ ike_sa_t *ike_sa;
+ peer_cfg_t *peer_cfg;
+ enumerator_t *enumerator;
+ attributes_t *attr;
+
+ ike_sa = charon->bus->get_sa(charon->bus);
+ if (ike_sa)
+ {
+ peer_cfg = ike_sa->get_peer_cfg(ike_sa);
+ this->lock->read_lock(this->lock);
+ enumerator = this->attrs->create_enumerator(this->attrs);
+ while (enumerator->enumerate(enumerator, &attr))
+ {
+ if (streq(attr->name, peer_cfg->get_name(peer_cfg)))
+ {
+ enumerator->destroy(enumerator);
+ return enumerator_create_filter(
+ attr->dns->create_enumerator(attr->dns),
+ (void*)attr_filter, this->lock,
+ (void*)this->lock->unlock);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+ }
+ return enumerator_create_empty();
+}
+
+METHOD(stroke_handler_t, add_attributes, void,
+ private_stroke_handler_t *this, stroke_msg_t *msg)
+{
+ if (msg->add_conn.me.dns)
+ {
+ enumerator_t *enumerator;
+ attributes_t *attr = NULL;
+ host_t *host;
+ char *token;
+
+ enumerator = enumerator_create_token(msg->add_conn.me.dns, ",", " ");
+ while (enumerator->enumerate(enumerator, &token))
+ {
+ if (streq(token, "%config") || streq(token, "%config4"))
+ {
+ host = host_create_any(AF_INET);
+ }
+ else if (streq(token, "%config6"))
+ {
+ host = host_create_any(AF_INET6);
+ }
+ else
+ {
+ host = host_create_from_string(token, 0);
+ }
+ if (host)
+ {
+ if (!attr)
+ {
+ INIT(attr,
+ .name = strdup(msg->add_conn.name),
+ .dns = linked_list_create(),
+ );
+ }
+ attr->dns->insert_last(attr->dns, host);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "ignoring invalid DNS address '%s'", token);
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (attr)
+ {
+ this->lock->write_lock(this->lock);
+ this->attrs->insert_last(this->attrs, attr);
+ this->lock->unlock(this->lock);
+ }
+ }
+}
+
+METHOD(stroke_handler_t, del_attributes, void,
+ private_stroke_handler_t *this, stroke_msg_t *msg)
+{
+ enumerator_t *enumerator;
+ attributes_t *attr;
+
+ this->lock->write_lock(this->lock);
+ enumerator = this->attrs->create_enumerator(this->attrs);
+ while (enumerator->enumerate(enumerator, &attr))
+ {
+ if (streq(msg->del_conn.name, attr->name))
+ {
+ this->attrs->remove_at(this->attrs, enumerator);
+ attributes_destroy(attr);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+}
+
+METHOD(stroke_handler_t, destroy, void,
+ private_stroke_handler_t *this)
+{
+ this->lock->destroy(this->lock);
+ this->attrs->destroy_function(this->attrs, (void*)attributes_destroy);
+ free(this);
+}
+
+/**
+ * See header
+ */
+stroke_handler_t *stroke_handler_create()
+{
+ private_stroke_handler_t *this;
+
+ INIT(this,
+ .public = {
+ .handler = {
+ .handle = (void*)return_false,
+ .release = (void*)return_false,
+ .create_attribute_enumerator = _create_attribute_enumerator,
+ },
+ .add_attributes = _add_attributes,
+ .del_attributes = _del_attributes,
+ .destroy = _destroy,
+ },
+ .attrs = linked_list_create(),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/stroke/stroke_handler.h b/src/libcharon/plugins/stroke/stroke_handler.h
new file mode 100644
index 000000000..ab76f80b0
--- /dev/null
+++ b/src/libcharon/plugins/stroke/stroke_handler.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 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 stroke_handler stroke_handler
+ * @{ @ingroup stroke
+ */
+
+#ifndef STROKE_HANDLER_H_
+#define STROKE_HANDLER_H_
+
+#include <stroke_msg.h>
+#include <attributes/attribute_handler.h>
+
+typedef struct stroke_handler_t stroke_handler_t;
+
+/**
+ * Handler requesting DNS attributes as defined with leftdns option.
+ */
+struct stroke_handler_t {
+
+ /**
+ * Implements the attribute_handler_t interface
+ */
+ attribute_handler_t handler;
+
+ /**
+ * Add connection specific configuration attributes.
+ *
+ * @param msg stroke message
+ */
+ void (*add_attributes)(stroke_handler_t *this, stroke_msg_t *msg);
+
+ /**
+ * Remove connection specific configuration attributes.
+ *
+ * @param msg stroke message
+ */
+ void (*del_attributes)(stroke_handler_t *this, stroke_msg_t *msg);
+
+ /**
+ * Destroy a stroke_handler_t.
+ */
+ void (*destroy)(stroke_handler_t *this);
+};
+
+/**
+ * Create a stroke_handler instance.
+ */
+stroke_handler_t *stroke_handler_create();
+
+#endif /** STROKE_HANDLER_H_ @}*/
diff --git a/src/libcharon/plugins/stroke/stroke_list.c b/src/libcharon/plugins/stroke/stroke_list.c
index 514a91e2b..c012ff25d 100644
--- a/src/libcharon/plugins/stroke/stroke_list.c
+++ b/src/libcharon/plugins/stroke/stroke_list.c
@@ -17,6 +17,7 @@
#include <inttypes.h>
#include <time.h>
+#include <sys/utsname.h>
#ifdef HAVE_MALLINFO
#include <malloc.h>
@@ -51,6 +52,11 @@ struct private_stroke_list_t {
stroke_list_t public;
/**
+ * Kind of *swan we run
+ */
+ char *swan;
+
+ /**
* timestamp of daemon start
*/
time_t uptime;
@@ -115,11 +121,23 @@ static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all)
if (all)
{
proposal_t *ike_proposal;
+ identification_t *eap_id;
+
+ eap_id = ike_sa->get_other_eap_id(ike_sa);
+
+ if (!eap_id->equals(eap_id, ike_sa->get_other_id(ike_sa)))
+ {
+ fprintf(out, "%12s[%d]: Remote %s identity: %Y\n",
+ ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa),
+ ike_sa->get_version(ike_sa) == IKEV1 ? "XAuth" : "EAP",
+ eap_id);
+ }
ike_proposal = ike_sa->get_proposal(ike_sa);
- fprintf(out, "%12s[%d]: IKE SPIs: %.16"PRIx64"_i%s %.16"PRIx64"_r%s",
+ fprintf(out, "%12s[%d]: %N SPIs: %.16"PRIx64"_i%s %.16"PRIx64"_r%s",
ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa),
+ ike_version_names, ike_sa->get_version(ike_sa),
id->get_initiator_spi(id), id->is_initiator(id) ? "*" : "",
id->get_responder_spi(id), id->is_initiator(id) ? "" : "*");
@@ -191,6 +209,7 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all)
proposal_t *proposal;
child_cfg_t *config = child_sa->get_config(child_sa);
+ now = time_monotonic(NULL);
fprintf(out, "%12s{%d}: %N, %N%s",
child_sa->get_name(child_sa), child_sa->get_reqid(child_sa),
@@ -254,7 +273,6 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all)
}
}
- now = time_monotonic(NULL);
child_sa->get_usestats(child_sa, TRUE, &use_in, &bytes_in);
fprintf(out, ", %" PRIu64 " bytes_i", bytes_in);
if (use_in)
@@ -289,6 +307,11 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all)
}
}
+ else if (child_sa->get_state(child_sa) == CHILD_REKEYING)
+ {
+ rekey = child_sa->get_lifetime(child_sa, TRUE);
+ fprintf(out, ", expires in %V", &now, &rekey);
+ }
fprintf(out, "\n%12s{%d}: %#R=== %#R\n",
child_sa->get_name(child_sa), child_sa->get_reqid(child_sa),
@@ -315,15 +338,16 @@ static void log_auth_cfgs(FILE *out, peer_cfg_t *peer_cfg, bool local)
enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, local);
while (enumerator->enumerate(enumerator, &auth))
{
- fprintf(out, "%12s: %s [%Y] uses ", name, local ? "local: " : "remote:",
- auth->get(auth, AUTH_RULE_IDENTITY));
-
- auth_class = (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS);
- if (auth_class != AUTH_CLASS_EAP)
+ fprintf(out, "%12s: %s", name, local ? "local: " : "remote:");
+ id = auth->get(auth, AUTH_RULE_IDENTITY);
+ if (id)
{
- fprintf(out, "%N authentication\n", auth_class_names, auth_class);
+ fprintf(out, " [%Y]", id);
}
- else
+ fprintf(out, " uses ");
+
+ auth_class = (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS);
+ if (auth_class == AUTH_CLASS_EAP)
{
if ((uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE) == EAP_NAK)
{
@@ -350,6 +374,21 @@ static void log_auth_cfgs(FILE *out, peer_cfg_t *peer_cfg, bool local)
}
fprintf(out, "\n");
}
+ else if (auth_class == AUTH_CLASS_XAUTH)
+ {
+ fprintf(out, "%N authentication: %s", auth_class_names, auth_class,
+ auth->get(auth, AUTH_RULE_XAUTH_BACKEND) ?: "any");
+ id = auth->get(auth, AUTH_RULE_XAUTH_IDENTITY);
+ if (id)
+ {
+ fprintf(out, " with XAuth identity '%Y'", id);
+ }
+ fprintf(out, "\n");
+ }
+ else
+ {
+ fprintf(out, "%N authentication\n", auth_class_names, auth_class);
+ }
cert = auth->get(auth, AUTH_RULE_CA_CERT);
if (cert)
@@ -414,16 +453,25 @@ METHOD(stroke_list_t, status, void,
if (all)
{
peer_cfg_t *peer_cfg;
+ ike_version_t ike_version;
char *pool;
host_t *host;
u_int32_t dpd;
time_t since, now;
u_int size, online, offline, i;
+ struct utsname utsname;
+
now = time_monotonic(NULL);
since = time(NULL) - (now - this->uptime);
- fprintf(out, "Status of IKEv2 charon daemon (strongSwan "VERSION"):\n");
- fprintf(out, " uptime: %V, since %T\n", &now, &this->uptime, &since, FALSE);
+ fprintf(out, "Status of IKE charon daemon (%sSwan "VERSION, this->swan);
+ if (uname(&utsname) == 0)
+ {
+ fprintf(out, ", %s %s, %s",
+ utsname.sysname, utsname.release, utsname.machine);
+ }
+ fprintf(out, "):\n uptime: %V, since %T\n", &now, &this->uptime, &since,
+ FALSE);
#ifdef HAVE_MALLINFO
{
struct mallinfo mi = mallinfo();
@@ -469,7 +517,7 @@ METHOD(stroke_list_t, status, void,
enumerator->destroy(enumerator);
enumerator = hydra->kernel_interface->create_address_enumerator(
- hydra->kernel_interface, FALSE, FALSE);
+ hydra->kernel_interface, ADDR_TYPE_REGULAR);
fprintf(out, "Listening IP addresses:\n");
while (enumerator->enumerate(enumerator, (void**)&host))
{
@@ -479,18 +527,30 @@ METHOD(stroke_list_t, status, void,
fprintf(out, "Connections:\n");
enumerator = charon->backends->create_peer_cfg_enumerator(
- charon->backends, NULL, NULL, NULL, NULL);
+ charon->backends, NULL, NULL, NULL, NULL, IKE_ANY);
while (enumerator->enumerate(enumerator, &peer_cfg))
{
- if (peer_cfg->get_ike_version(peer_cfg) != 2 ||
- (name && !streq(name, peer_cfg->get_name(peer_cfg))))
+ char *my_addr, *other_addr;
+ bool my_allow_any, other_allow_any;
+
+ if (name && !streq(name, peer_cfg->get_name(peer_cfg)))
{
continue;
}
ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
- fprintf(out, "%12s: %s...%s", peer_cfg->get_name(peer_cfg),
- ike_cfg->get_my_addr(ike_cfg), ike_cfg->get_other_addr(ike_cfg));
+ ike_version = peer_cfg->get_ike_version(peer_cfg);
+ my_addr = ike_cfg->get_my_addr(ike_cfg, &my_allow_any);
+ other_addr = ike_cfg->get_other_addr(ike_cfg, &other_allow_any);
+ fprintf(out, "%12s: %s%s...%s%s %N", peer_cfg->get_name(peer_cfg),
+ my_allow_any ? "%":"", my_addr,
+ other_allow_any ? "%":"", other_addr,
+ ike_version_names, ike_version);
+
+ if (ike_version == IKEV1 && peer_cfg->use_aggressive(peer_cfg))
+ {
+ fprintf(out, " Aggressive");
+ }
dpd = peer_cfg->get_dpd(peer_cfg);
if (dpd)
@@ -666,15 +726,12 @@ static void list_public_key(public_key_t *public, FILE *out)
private_key_t *private = NULL;
chunk_t keyid;
identification_t *id;
- auth_cfg_t *auth;
if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &keyid))
{
id = identification_create_from_encoding(ID_KEY_ID, keyid);
- auth = auth_cfg_create();
private = lib->credmgr->get_private(lib->credmgr,
- public->get_type(public), id, auth);
- auth->destroy(auth);
+ public->get_type(public), id, NULL);
id->destroy(id);
}
@@ -819,8 +876,8 @@ static void stroke_list_certs(linked_list_t *list, char *label,
x509_flag_t flag_mask;
/* mask all auxiliary flags */
- flag_mask = ~(X509_SERVER_AUTH | X509_CLIENT_AUTH |
- X509_SELF_SIGNED | X509_IP_ADDR_BLOCKS );
+ flag_mask = ~(X509_SERVER_AUTH | X509_CLIENT_AUTH | X509_IKE_INTERMEDIATE |
+ X509_SELF_SIGNED | X509_IP_ADDR_BLOCKS);
enumerator = list->create_enumerator(list);
while (enumerator->enumerate(enumerator, (void**)&cert))
@@ -1059,7 +1116,7 @@ static void stroke_list_crls(linked_list_t *list, bool utc, FILE *out)
}
if (crl->is_delta_crl(crl, &chunk))
{
- chunk = chunk_skip_zero(chunk);
+ chunk = chunk_skip_zero(chunk);
fprintf(out, " delta for: %#B\n", &chunk);
}
@@ -1151,7 +1208,15 @@ static void print_alg(FILE *out, int *len, enum_name_t *alg_names, int alg_type,
char alg_name[BUF_LEN];
int alg_name_len;
- alg_name_len = sprintf(alg_name, " %N[%s]", alg_names, alg_type, plugin_name);
+ if (alg_names)
+ {
+ alg_name_len = sprintf(alg_name, " %N[%s]", alg_names, alg_type,
+ plugin_name);
+ }
+ else
+ {
+ alg_name_len = sprintf(alg_name, " [%s]", plugin_name);
+ }
if (*len + alg_name_len > CRYPTO_MAX_ALG_LINE)
{
fprintf(out, "\n ");
@@ -1234,6 +1299,14 @@ static void list_algs(FILE *out)
print_alg(out, &len, rng_quality_names, quality, plugin_name);
}
enumerator->destroy(enumerator);
+ fprintf(out, "\n nonce-gen: ");
+ len = 13;
+ enumerator = lib->crypto->create_nonce_gen_enumerator(lib->crypto);
+ while (enumerator->enumerate(enumerator, &plugin_name))
+ {
+ print_alg(out, &len, NULL, 0, plugin_name);
+ }
+ enumerator->destroy(enumerator);
fprintf(out, "\n");
}
@@ -1277,7 +1350,7 @@ static void list_plugins(FILE *out)
fprintf(out, " %s\n", str);
break;
case FEATURE_SDEPEND:
- fprintf(out, " %s(soft)\n", str);
+ fprintf(out, " %s (soft)\n", str);
break;
default:
break;
@@ -1450,16 +1523,22 @@ stroke_list_t *stroke_list_create(stroke_attribute_t *attribute)
INIT(this,
.public = {
-
.list = _list,
.status = _status,
.leases = _leases,
.destroy = _destroy,
},
.uptime = time_monotonic(NULL),
+ .swan = "strong",
.attribute = attribute,
);
+ if (lib->settings->get_bool(lib->settings,
+ "charon.i_dont_care_about_security_and_use_aggressive_mode_psk", FALSE))
+ {
+ this->swan = "weak";
+ }
+
return &this->public;
}
diff --git a/src/libcharon/plugins/stroke/stroke_plugin.c b/src/libcharon/plugins/stroke/stroke_plugin.c
index 2884db4bf..4e47a120d 100644
--- a/src/libcharon/plugins/stroke/stroke_plugin.c
+++ b/src/libcharon/plugins/stroke/stroke_plugin.c
@@ -42,10 +42,45 @@ METHOD(plugin_t, get_name, char*,
return "stroke";
}
+/**
+ * Register stroke plugin features
+ */
+static bool register_stroke(private_stroke_plugin_t *this,
+ plugin_feature_t *feature, bool reg, void *data)
+{
+ if (reg)
+ {
+ this->socket = stroke_socket_create();
+ }
+ else
+ {
+ DESTROY_IF(this->socket);
+ }
+ return TRUE;
+}
+
+METHOD(plugin_t, get_features, int,
+ private_stroke_plugin_t *this, plugin_feature_t *features[])
+{
+ static plugin_feature_t f[] = {
+ PLUGIN_CALLBACK((plugin_feature_callback_t)register_stroke, NULL),
+ PLUGIN_PROVIDE(CUSTOM, "stroke"),
+ PLUGIN_SDEPEND(PRIVKEY, KEY_RSA),
+ PLUGIN_SDEPEND(PRIVKEY, KEY_ECDSA),
+ PLUGIN_SDEPEND(PRIVKEY, KEY_DSA),
+ PLUGIN_SDEPEND(CERT_DECODE, CERT_ANY),
+ PLUGIN_SDEPEND(CERT_DECODE, CERT_X509),
+ PLUGIN_SDEPEND(CERT_DECODE, CERT_X509_CRL),
+ PLUGIN_SDEPEND(CERT_DECODE, CERT_X509_AC),
+ PLUGIN_SDEPEND(CERT_DECODE, CERT_TRUSTED_PUBKEY),
+ };
+ *features = f;
+ return countof(f);
+}
+
METHOD(plugin_t, destroy, void,
private_stroke_plugin_t *this)
{
- this->socket->destroy(this->socket);
free(this);
}
@@ -61,17 +96,12 @@ plugin_t *stroke_plugin_create()
.plugin = {
.get_name = _get_name,
.reload = (void*)return_false,
+ .get_features = _get_features,
.destroy = _destroy,
},
},
- .socket = stroke_socket_create(),
);
- if (this->socket == NULL)
- {
- free(this);
- return NULL;
- }
return &this->public.plugin;
}
diff --git a/src/libcharon/plugins/stroke/stroke_socket.c b/src/libcharon/plugins/stroke/stroke_socket.c
index 57648feb8..241f0fbf6 100644
--- a/src/libcharon/plugins/stroke/stroke_socket.c
+++ b/src/libcharon/plugins/stroke/stroke_socket.c
@@ -37,6 +37,7 @@
#include "stroke_cred.h"
#include "stroke_ca.h"
#include "stroke_attribute.h"
+#include "stroke_handler.h"
#include "stroke_list.h"
/**
@@ -64,16 +65,6 @@ struct private_stroke_socket_t {
int socket;
/**
- * job accepting stroke messages
- */
- callback_job_t *receiver;
-
- /**
- * job handling stroke messages
- */
- callback_job_t *handler;
-
- /**
* queued stroke commands
*/
linked_list_t *commands;
@@ -109,6 +100,11 @@ struct private_stroke_socket_t {
stroke_attribute_t *attribute;
/**
+ * attribute handler (requests only)
+ */
+ stroke_handler_t *handler;
+
+ /**
* controller to control daemon
*/
stroke_control_t *control;
@@ -181,6 +177,7 @@ static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end)
pop_string(msg, &end->address);
pop_string(msg, &end->subnets);
pop_string(msg, &end->sourceip);
+ pop_string(msg, &end->dns);
pop_string(msg, &end->auth);
pop_string(msg, &end->auth2);
pop_string(msg, &end->id);
@@ -191,12 +188,14 @@ static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end)
pop_string(msg, &end->ca);
pop_string(msg, &end->ca2);
pop_string(msg, &end->groups);
+ pop_string(msg, &end->groups2);
pop_string(msg, &end->cert_policy);
pop_string(msg, &end->updown);
DBG2(DBG_CFG, " %s=%s", label, end->address);
DBG2(DBG_CFG, " %ssubnet=%s", label, end->subnets);
DBG2(DBG_CFG, " %ssourceip=%s", label, end->sourceip);
+ DBG2(DBG_CFG, " %sdns=%s", label, end->dns);
DBG2(DBG_CFG, " %sauth=%s", label, end->auth);
DBG2(DBG_CFG, " %sauth2=%s", label, end->auth2);
DBG2(DBG_CFG, " %sid=%s", label, end->id);
@@ -207,6 +206,7 @@ static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end)
DBG2(DBG_CFG, " %sca=%s", label, end->ca);
DBG2(DBG_CFG, " %sca2=%s", label, end->ca2);
DBG2(DBG_CFG, " %sgroups=%s", label, end->groups);
+ DBG2(DBG_CFG, " %sgroups2=%s", label, end->groups2);
DBG2(DBG_CFG, " %supdown=%s", label, end->updown);
}
@@ -223,23 +223,28 @@ static void stroke_add_conn(private_stroke_socket_t *this, stroke_msg_t *msg)
pop_end(msg, "right", &msg->add_conn.other);
pop_string(msg, &msg->add_conn.eap_identity);
pop_string(msg, &msg->add_conn.aaa_identity);
+ pop_string(msg, &msg->add_conn.xauth_identity);
pop_string(msg, &msg->add_conn.algorithms.ike);
pop_string(msg, &msg->add_conn.algorithms.esp);
pop_string(msg, &msg->add_conn.ikeme.mediated_by);
pop_string(msg, &msg->add_conn.ikeme.peerid);
DBG2(DBG_CFG, " eap_identity=%s", msg->add_conn.eap_identity);
DBG2(DBG_CFG, " aaa_identity=%s", msg->add_conn.aaa_identity);
+ DBG2(DBG_CFG, " xauth_identity=%s", msg->add_conn.xauth_identity);
DBG2(DBG_CFG, " ike=%s", msg->add_conn.algorithms.ike);
DBG2(DBG_CFG, " esp=%s", msg->add_conn.algorithms.esp);
DBG2(DBG_CFG, " dpddelay=%d", msg->add_conn.dpd.delay);
+ DBG2(DBG_CFG, " dpdtimeout=%d", msg->add_conn.dpd.timeout);
DBG2(DBG_CFG, " dpdaction=%d", msg->add_conn.dpd.action);
DBG2(DBG_CFG, " closeaction=%d", msg->add_conn.close_action);
DBG2(DBG_CFG, " mediation=%s", msg->add_conn.ikeme.mediation ? "yes" : "no");
DBG2(DBG_CFG, " mediated_by=%s", msg->add_conn.ikeme.mediated_by);
DBG2(DBG_CFG, " me_peerid=%s", msg->add_conn.ikeme.peerid);
+ DBG2(DBG_CFG, " keyexchange=ikev%u", msg->add_conn.version);
this->config->add(this->config, msg);
- this->attribute->add_pool(this->attribute, msg);
+ this->attribute->add_dns(this->attribute, msg);
+ this->handler->add_attributes(this->handler, msg);
}
/**
@@ -251,7 +256,8 @@ static void stroke_del_conn(private_stroke_socket_t *this, stroke_msg_t *msg)
DBG1(DBG_CFG, "received stroke: delete connection '%s'", msg->del_conn.name);
this->config->del(this->config, msg);
- this->attribute->del_pool(this->attribute, msg);
+ this->attribute->del_dns(this->attribute, msg);
+ this->handler->del_attributes(this->handler, msg);
}
/**
@@ -514,12 +520,14 @@ static void stroke_loglevel(private_stroke_socket_t *this,
while (enumerator->enumerate(enumerator, &sys_logger))
{
sys_logger->set_level(sys_logger, group, msg->loglevel.level);
+ charon->bus->add_logger(charon->bus, &sys_logger->logger);
}
enumerator->destroy(enumerator);
enumerator = charon->file_loggers->create_enumerator(charon->file_loggers);
while (enumerator->enumerate(enumerator, &file_logger))
{
file_logger->set_level(file_logger, group, msg->loglevel.level);
+ charon->bus->add_logger(charon->bus, &file_logger->logger);
}
enumerator->destroy(enumerator);
}
@@ -696,7 +704,7 @@ static job_requeue_t handle(private_stroke_socket_t *this)
this->handling++;
thread_cleanup_pop(TRUE);
job = callback_job_create_with_prio((callback_job_cb_t)process, ctx,
- (void*)stroke_job_context_destroy, this->handler, JOB_PRIO_HIGH);
+ (void*)stroke_job_context_destroy, NULL, JOB_PRIO_HIGH);
lib->processor->queue_job(lib->processor, (job_t*)job);
return JOB_REQUEUE_DIRECT;
}
@@ -762,7 +770,8 @@ static bool open_socket(private_stroke_socket_t *this)
return FALSE;
}
umask(old);
- if (chown(socket_addr.sun_path, charon->uid, charon->gid) != 0)
+ if (chown(socket_addr.sun_path, charon->caps->get_uid(charon->caps),
+ charon->caps->get_gid(charon->caps)) != 0)
{
DBG1(DBG_CFG, "changing stroke socket permissions failed: %s",
strerror(errno));
@@ -781,8 +790,6 @@ static bool open_socket(private_stroke_socket_t *this)
METHOD(stroke_socket_t, destroy, void,
private_stroke_socket_t *this)
{
- this->handler->cancel(this->handler);
- this->receiver->cancel(this->receiver);
this->commands->destroy_function(this->commands, (void*)stroke_job_context_destroy);
this->condvar->destroy(this->condvar);
this->mutex->destroy(this->mutex);
@@ -790,10 +797,12 @@ METHOD(stroke_socket_t, destroy, void,
lib->credmgr->remove_set(lib->credmgr, &this->cred->set);
charon->backends->remove_backend(charon->backends, &this->config->backend);
hydra->attributes->remove_provider(hydra->attributes, &this->attribute->provider);
+ hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler);
this->cred->destroy(this->cred);
this->ca->destroy(this->ca);
this->config->destroy(this->config);
this->attribute->destroy(this->attribute);
+ this->handler->destroy(this->handler);
this->control->destroy(this->control);
this->list->destroy(this->list);
free(this);
@@ -820,8 +829,9 @@ stroke_socket_t *stroke_socket_create()
this->cred = stroke_cred_create();
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->config = stroke_config_create(this->ca, this->cred, this->attribute);
this->control = stroke_control_create();
this->list = stroke_list_create(this->attribute);
@@ -829,20 +839,22 @@ stroke_socket_t *stroke_socket_create()
this->condvar = condvar_create(CONDVAR_TYPE_DEFAULT);
this->commands = linked_list_create();
this->max_concurrent = lib->settings->get_int(lib->settings,
- "charon.plugins.stroke.max_concurrent", MAX_CONCURRENT_DEFAULT);
+ "%s.plugins.stroke.max_concurrent", MAX_CONCURRENT_DEFAULT,
+ charon->name);
lib->credmgr->add_set(lib->credmgr, &this->ca->set);
lib->credmgr->add_set(lib->credmgr, &this->cred->set);
charon->backends->add_backend(charon->backends, &this->config->backend);
hydra->attributes->add_provider(hydra->attributes, &this->attribute->provider);
+ hydra->attributes->add_handler(hydra->attributes, &this->handler->handler);
- this->receiver = callback_job_create_with_prio((callback_job_cb_t)receive,
- this, NULL, NULL, JOB_PRIO_CRITICAL);
- lib->processor->queue_job(lib->processor, (job_t*)this->receiver);
+ lib->processor->queue_job(lib->processor,
+ (job_t*)callback_job_create_with_prio((callback_job_cb_t)receive, this,
+ NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
- this->handler = callback_job_create_with_prio((callback_job_cb_t)handle,
- this, NULL, NULL, JOB_PRIO_CRITICAL);
- lib->processor->queue_job(lib->processor, (job_t*)this->handler);
+ lib->processor->queue_job(lib->processor,
+ (job_t*)callback_job_create_with_prio((callback_job_cb_t)handle, this,
+ NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
return &this->public;
}
diff --git a/src/libcharon/plugins/tnc_ifmap/Makefile.in b/src/libcharon/plugins/tnc_ifmap/Makefile.in
index 54deb7cd7..5ead4379a 100644
--- a/src/libcharon/plugins/tnc_ifmap/Makefile.in
+++ b/src/libcharon/plugins/tnc_ifmap/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -87,7 +88,7 @@ libstrongswan_tnc_ifmap_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_tnc_ifmap_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_tnc_ifmap_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -113,6 +114,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -207,11 +209,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -228,11 +233,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -248,6 +254,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -257,7 +264,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.c b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.c
index 4fd33696c..eac285ca3 100644
--- a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.c
+++ b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
+ * Copyright (C) 2011 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -49,7 +49,7 @@ static bool publish_device_ip_addresses(private_tnc_ifmap_listener_t *this)
bool success = TRUE;
enumerator = hydra->kernel_interface->create_address_enumerator(
- hydra->kernel_interface, FALSE, FALSE);
+ hydra->kernel_interface, ADDR_TYPE_REGULAR);
while (enumerator->enumerate(enumerator, &host))
{
if (!this->ifmap->publish_device_ip(this->ifmap, host))
@@ -87,7 +87,7 @@ static bool reload_metadata(private_tnc_ifmap_listener_t *this)
}
}
enumerator->destroy(enumerator);
-
+
return success;
}
diff --git a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c
index 913cdab12..b13193612 100644
--- a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c
+++ b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
+ * Copyright (C) 2011 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -16,6 +16,7 @@
#include "tnc_ifmap_soap.h"
#include <debug.h>
+#include <daemon.h>
#include <axis2_util.h>
#include <axis2_client.h>
@@ -27,7 +28,7 @@
#define IFMAP_META_NS "http://www.trustedcomputinggroup.org/2010/IFMAP-METADATA/2"
#define IFMAP_LOGFILE "strongswan_ifmap.log"
#define IFMAP_SERVER "https://localhost:8443/"
-
+
typedef struct private_tnc_ifmap_soap_t private_tnc_ifmap_soap_t;
/**
@@ -41,7 +42,7 @@ struct private_tnc_ifmap_soap_t {
tnc_ifmap_soap_t public;
/**
- * Axis2/C environment
+ * Axis2/C environment
*/
axutil_env_t *env;
@@ -155,8 +156,8 @@ METHOD(tnc_ifmap_soap_t, newSession, bool,
/* set PEP and PDP device name (defaults to IF-MAP Publisher ID) */
this->device_name = lib->settings->get_str(lib->settings,
- "charon.plugins.tnc-ifmap.device_name",
- this->ifmap_publisher_id);
+ "%s.plugins.tnc-ifmap.device_name",
+ this->ifmap_publisher_id, charon->name);
this->device_name = strdup(this->device_name);
/* free result */
@@ -174,13 +175,13 @@ METHOD(tnc_ifmap_soap_t, purgePublisher, bool,
axiom_attribute_t *attr;
/* build purgePublisher request */
- ns = axiom_namespace_create(this->env, IFMAP_NS, "ifmap");
+ ns = axiom_namespace_create(this->env, IFMAP_NS, "ifmap");
el = axiom_element_create(this->env, NULL, "purgePublisher", ns, &request);
attr = axiom_attribute_create(this->env, "session-id",
- this->session_id, NULL);
+ this->session_id, NULL);
axiom_element_add_attribute(el, this->env, attr, request);
attr = axiom_attribute_create(this->env, "ifmap-publisher-id",
- this->ifmap_publisher_id, NULL);
+ this->ifmap_publisher_id, NULL);
axiom_element_add_attribute(el, this->env, attr, request);
/* send purgePublisher request and receive purgePublisherReceived */
@@ -202,7 +203,7 @@ static axiom_node_t* create_access_request(private_tnc_ifmap_soap_t *this,
el = axiom_element_create(this->env, NULL, "access-request", NULL, &node);
snprintf(buf, BUF_LEN, "%s:%d", this->device_name, id);
- attr = axiom_attribute_create(this->env, "name", buf, NULL);
+ attr = axiom_attribute_create(this->env, "name", buf, NULL);
axiom_element_add_attribute(el, this->env, attr, node);
return node;
@@ -222,7 +223,7 @@ static axiom_node_t* create_identity(private_tnc_ifmap_soap_t *this,
el = axiom_element_create(this->env, NULL, "identity", NULL, &node);
snprintf(buf, BUF_LEN, "%Y", id);
- attr = axiom_attribute_create(this->env, "name", buf, NULL);
+ attr = axiom_attribute_create(this->env, "name", buf, NULL);
axiom_element_add_attribute(el, this->env, attr, node);
switch (id->get_type(id))
@@ -260,7 +261,7 @@ static axiom_node_t* create_identity(private_tnc_ifmap_soap_t *this,
"36906:other", NULL);
axiom_element_add_attribute(el, this->env, attr, node);
}
- attr = axiom_attribute_create(this->env, "type", id_type, NULL);
+ attr = axiom_attribute_create(this->env, "type", id_type, NULL);
axiom_element_add_attribute(el, this->env, attr, node);
return node;
@@ -295,7 +296,7 @@ static axiom_node_t* create_ip_address(private_tnc_ifmap_soap_t *this,
{
written = snprintf(pos, len, "%s%x", first ? "" : ":",
256*address.ptr[i] + address.ptr[i+1]);
- if (written < 0 || written > len)
+ if (written < 0 || written >= len)
{
break;
}
@@ -308,11 +309,11 @@ static axiom_node_t* create_ip_address(private_tnc_ifmap_soap_t *this,
{
snprintf(buf, BUF_LEN, "%H", host);
}
- attr = axiom_attribute_create(this->env, "value", buf, NULL);
+ attr = axiom_attribute_create(this->env, "value", buf, NULL);
axiom_element_add_attribute(el, this->env, attr, node);
attr = axiom_attribute_create(this->env, "type",
- host->get_family(host) == AF_INET ? "IPv4" : "IPv6", NULL);
+ host->get_family(host) == AF_INET ? "IPv4" : "IPv6", NULL);
axiom_element_add_attribute(el, this->env, attr, node);
return node;
@@ -352,7 +353,7 @@ static axiom_node_t* create_metadata(private_tnc_ifmap_soap_t *this,
el = axiom_element_create(this->env, NULL, metadata, ns_meta, &node2);
axiom_node_add_child(node, this->env, node2);
attr = axiom_attribute_create(this->env, "ifmap-cardinality", "singleValue",
- NULL);
+ NULL);
axiom_element_add_attribute(el, this->env, attr, node2);
return node;
@@ -374,7 +375,7 @@ static axiom_node_t* create_capability(private_tnc_ifmap_soap_t *this,
ns_meta = axiom_namespace_create(this->env, IFMAP_META_NS, "meta");
el = axiom_element_create(this->env, NULL, "capability", ns_meta, &node);
attr = axiom_attribute_create(this->env, "ifmap-cardinality", "multiValue",
- NULL);
+ NULL);
axiom_element_add_attribute(el, this->env, attr, node);
el = axiom_element_create(this->env, NULL, "name", NULL, &node2);
@@ -385,7 +386,7 @@ static axiom_node_t* create_capability(private_tnc_ifmap_soap_t *this,
el = axiom_element_create(this->env, NULL, "administrative-domain", NULL, &node2);
axiom_node_add_child(node, this->env, node2);
text = axiom_text_create(this->env, node2, "strongswan", &node3);
-
+
return node;
}
@@ -439,7 +440,7 @@ static axiom_node_t* create_delete_filter(private_tnc_ifmap_soap_t *this,
snprintf(buf, BUF_LEN, "meta:%s[@ifmap-publisher-id='%s']",
metadata, this->ifmap_publisher_id);
- attr = axiom_attribute_create(this->env, "filter", buf, NULL);
+ attr = axiom_attribute_create(this->env, "filter", buf, NULL);
axiom_element_add_attribute(el, this->env, attr, node);
return node;
@@ -506,11 +507,11 @@ METHOD(tnc_ifmap_soap_t, publish_ike_sa, bool,
axiom_node_add_child(node, this->env,
create_device(this));
}
-
+
/**
* update or delete authenticated-as metadata
*/
- if (up)
+ if (up)
{
el = axiom_element_create(this->env, NULL, "update", NULL, &node);
}
@@ -534,7 +535,7 @@ METHOD(tnc_ifmap_soap_t, publish_ike_sa, bool,
/**
* update or delete access-request-ip metadata
*/
- if (up)
+ if (up)
{
el = axiom_element_create(this->env, NULL, "update", NULL, &node);
}
@@ -558,7 +559,7 @@ METHOD(tnc_ifmap_soap_t, publish_ike_sa, bool,
/**
* update or delete authenticated-by metadata
*/
- if (up)
+ if (up)
{
el = axiom_element_create(this->env, NULL, "update", NULL, &node);
}
@@ -605,7 +606,7 @@ METHOD(tnc_ifmap_soap_t, publish_ike_sa, bool,
node = create_delete_filter(this, "capability");
}
axiom_node_add_child(request, this->env, node);
-
+
/* add access-request */
axiom_node_add_child(node, this->env,
create_access_request(this, ike_sa_id));
@@ -688,9 +689,9 @@ METHOD(tnc_ifmap_soap_t, endSession, bool,
axiom_attribute_t *attr;
/* build endSession request */
- ns = axiom_namespace_create(this->env, IFMAP_NS, "ifmap");
+ ns = axiom_namespace_create(this->env, IFMAP_NS, "ifmap");
el = axiom_element_create(this->env, NULL, "endSession", ns, &request);
- attr = axiom_attribute_create(this->env, "session-id", this->session_id, NULL);
+ attr = axiom_attribute_create(this->env, "session-id", this->session_id, NULL);
axiom_element_add_attribute(el, this->env, attr, request);
/* send endSession request and receive end SessionResult */
@@ -705,7 +706,7 @@ METHOD(tnc_ifmap_soap_t, destroy, void,
endSession(this);
free(this->session_id);
free(this->ifmap_publisher_id);
- free(this->device_name);
+ free(this->device_name);
}
if (this->svc_client)
{
@@ -731,20 +732,20 @@ static bool axis2c_init(private_tnc_ifmap_soap_t *this)
/* Getting configuration parameters from strongswan.conf */
client_home = lib->settings->get_str(lib->settings,
- "charon.plugins.tnc-ifmap.client_home",
- AXIS2_GETENV("AXIS2C_HOME"));
+ "%s.plugins.tnc-ifmap.client_home",
+ AXIS2_GETENV("AXIS2C_HOME"), charon->name);
server = lib->settings->get_str(lib->settings,
- "charon.plugins.tnc-ifmap.server", IFMAP_SERVER);
+ "%s.plugins.tnc-ifmap.server", IFMAP_SERVER, charon->name);
server_cert = lib->settings->get_str(lib->settings,
- "charon.plugins.tnc-ifmap.server_cert", NULL);
+ "%s.plugins.tnc-ifmap.server_cert", NULL, charon->name);
key_file = lib->settings->get_str(lib->settings,
- "charon.plugins.tnc-ifmap.key_file", NULL);
+ "%s.plugins.tnc-ifmap.key_file", NULL, charon->name);
ssl_passphrase = lib->settings->get_str(lib->settings,
- "charon.plugins.tnc-ifmap.ssl_passphrase", NULL);
+ "%s.plugins.tnc-ifmap.ssl_passphrase", NULL, charon->name);
username = lib->settings->get_str(lib->settings,
- "charon.plugins.tnc-ifmap.username", NULL);
+ "%s.plugins.tnc-ifmap.username", NULL, charon->name);
password = lib->settings->get_str(lib->settings,
- "charon.plugins.tnc-ifmap.password", NULL);
+ "%s.plugins.tnc-ifmap.password", NULL, charon->name);
if (!server_cert)
{
@@ -785,9 +786,9 @@ static bool axis2c_init(private_tnc_ifmap_soap_t *this)
ssl_passphrase);
axis2_options_set_property(options, this->env,
AXIS2_SSL_PASSPHRASE, property);
- }
+ }
}
- else
+ else
{
/* Set up HTTP Basic MAP client authentication */
axis2_options_set_http_auth_info(options, this->env,
@@ -800,14 +801,14 @@ static bool axis2c_init(private_tnc_ifmap_soap_t *this)
/* Set up https transport */
transport_in = axis2_transport_in_desc_create(this->env,
- AXIS2_TRANSPORT_ENUM_HTTPS);
+ AXIS2_TRANSPORT_ENUM_HTTPS);
transport_out = axis2_transport_out_desc_create(this->env,
AXIS2_TRANSPORT_ENUM_HTTPS);
transport_sender = axis2_http_transport_sender_create(this->env);
axis2_transport_out_desc_set_sender(transport_out, this->env,
transport_sender);
axis2_options_set_transport_in(options, this->env, transport_in);
- axis2_options_set_transport_out(options, this->env, transport_out);
+ axis2_options_set_transport_out(options, this->env, transport_out);
/* Create the axis2 service client */
this->svc_client = axis2_svc_client_create(this->env, client_home);
diff --git a/src/libcharon/plugins/tnc_imc/Makefile.am b/src/libcharon/plugins/tnc_imc/Makefile.am
index fc1979525..5e2c30df9 100644
--- a/src/libcharon/plugins/tnc_imc/Makefile.am
+++ b/src/libcharon/plugins/tnc_imc/Makefile.am
@@ -1,6 +1,8 @@
INCLUDES = \
-I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon \
-I$(top_srcdir)/src/libtncif \
-I$(top_srcdir)/src/libtnccs
diff --git a/src/libcharon/plugins/tnc_imc/Makefile.in b/src/libcharon/plugins/tnc_imc/Makefile.in
index 550c0516c..00c0d0d61 100644
--- a/src/libcharon/plugins/tnc_imc/Makefile.in
+++ b/src/libcharon/plugins/tnc_imc/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -87,7 +88,7 @@ libstrongswan_tnc_imc_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@MONOLITHIC_FALSE@am_libstrongswan_tnc_imc_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_tnc_imc_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -113,6 +114,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -207,11 +209,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -228,11 +233,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -248,6 +254,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -257,7 +264,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -287,6 +293,8 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
INCLUDES = \
-I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon \
-I$(top_srcdir)/src/libtncif \
-I$(top_srcdir)/src/libtnccs
diff --git a/src/libcharon/plugins/tnc_imc/tnc_imc_manager.c b/src/libcharon/plugins/tnc_imc/tnc_imc_manager.c
index e101cf974..65ec81dae 100644
--- a/src/libcharon/plugins/tnc_imc/tnc_imc_manager.c
+++ b/src/libcharon/plugins/tnc_imc/tnc_imc_manager.c
@@ -21,6 +21,7 @@
#include <utils/linked_list.h>
#include <debug.h>
+#include <daemon.h>
typedef struct private_tnc_imc_manager_t private_tnc_imc_manager_t;
@@ -171,7 +172,7 @@ METHOD(imc_manager_t, get_preferred_language, char*,
private_tnc_imc_manager_t *this)
{
return lib->settings->get_str(lib->settings,
- "charon.plugins.tnc-imc.preferred_language", "en");
+ "%s.plugins.tnc-imc.preferred_language", "en", charon->name);
}
METHOD(imc_manager_t, notify_connection_change, void,
diff --git a/src/libcharon/plugins/tnc_imc/tnc_imc_plugin.c b/src/libcharon/plugins/tnc_imc/tnc_imc_plugin.c
index a25b1843c..859dded79 100644
--- a/src/libcharon/plugins/tnc_imc/tnc_imc_plugin.c
+++ b/src/libcharon/plugins/tnc_imc/tnc_imc_plugin.c
@@ -44,6 +44,8 @@ METHOD(plugin_t, get_features, int,
PLUGIN_CALLBACK(tnc_manager_register, tnc_imc_manager_create),
PLUGIN_PROVIDE(CUSTOM, "imc-manager"),
PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"),
+ PLUGIN_SDEPEND(CERT_DECODE, CERT_X509),
+ PLUGIN_SDEPEND(CERT_DECODE, CERT_TRUSTED_PUBKEY),
};
*features = f;
return countof(f);
diff --git a/src/libcharon/plugins/tnc_imv/Makefile.in b/src/libcharon/plugins/tnc_imv/Makefile.in
index cf58f0dc3..13b011101 100644
--- a/src/libcharon/plugins/tnc_imv/Makefile.in
+++ b/src/libcharon/plugins/tnc_imv/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -88,7 +89,7 @@ libstrongswan_tnc_imv_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@MONOLITHIC_FALSE@am_libstrongswan_tnc_imv_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_tnc_imv_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -114,6 +115,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -208,11 +210,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -229,11 +234,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -249,6 +255,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -258,7 +265,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv_manager.c b/src/libcharon/plugins/tnc_imv/tnc_imv_manager.c
index b1da73156..0985a47a8 100644
--- a/src/libcharon/plugins/tnc_imv/tnc_imv_manager.c
+++ b/src/libcharon/plugins/tnc_imv/tnc_imv_manager.c
@@ -241,7 +241,7 @@ METHOD(imv_manager_t, enforce_recommendation, bool,
return FALSE;
}
else
- {
+ {
auth = ike_sa->get_auth_cfg(ike_sa, FALSE);
id = identification_create_from_string(group);
auth->add(auth, AUTH_RULE_GROUP, id);
@@ -452,7 +452,8 @@ imv_manager_t* tnc_imv_manager_create(void)
policy = enum_from_name(recommendation_policy_names,
lib->settings->get_str(lib->settings,
- "charon.plugins.tnc-imv.recommendation_policy", "default"));
+ "%s.plugins.tnc-imv.recommendation_policy", "default",
+ charon->name));
this->policy = (policy != -1) ? policy : RECOMMENDATION_POLICY_DEFAULT;
DBG1(DBG_TNC, "TNC recommendation policy is '%N'",
recommendation_policy_names, this->policy);
diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv_plugin.c b/src/libcharon/plugins/tnc_imv/tnc_imv_plugin.c
index c16f6b9e1..612c98add 100644
--- a/src/libcharon/plugins/tnc_imv/tnc_imv_plugin.c
+++ b/src/libcharon/plugins/tnc_imv/tnc_imv_plugin.c
@@ -47,6 +47,8 @@ METHOD(plugin_t, get_features, int,
PLUGIN_CALLBACK(tnc_manager_register, tnc_imv_manager_create),
PLUGIN_PROVIDE(CUSTOM, "imv-manager"),
PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"),
+ PLUGIN_SDEPEND(CERT_DECODE, CERT_X509),
+ PLUGIN_SDEPEND(CERT_DECODE, CERT_TRUSTED_PUBKEY),
};
*features = f;
return countof(f);
diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv_recommendations.c b/src/libcharon/plugins/tnc_imv/tnc_imv_recommendations.c
index 7843293a1..396d5d854 100644
--- a/src/libcharon/plugins/tnc_imv/tnc_imv_recommendations.c
+++ b/src/libcharon/plugins/tnc_imv/tnc_imv_recommendations.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2010-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
@@ -123,8 +124,13 @@ METHOD(recommendations_t, have_recommendation, bool,
TNC_IMV_Evaluation_Result final_eval;
bool first = TRUE, incomplete = FALSE;
- *rec = final_rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION;
- *eval = final_eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
+ final_rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION;
+ final_eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
+ if (rec && eval)
+ {
+ *rec = final_rec;
+ *eval = final_eval;
+ }
if (this->recs->get_count(this->recs) == 0)
{
@@ -267,11 +273,32 @@ METHOD(recommendations_t, have_recommendation, bool,
{
return FALSE;
}
- *rec = final_rec;
- *eval = final_eval;
+ if (rec && eval)
+ {
+ *rec = final_rec;
+ *eval = final_eval;
+ }
return TRUE;
}
+METHOD(recommendations_t, clear_recommendation, void,
+ private_tnc_imv_recommendations_t *this)
+{
+ enumerator_t *enumerator;
+ recommendation_entry_t *entry;
+
+ enumerator = this->recs->create_enumerator(this->recs);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ entry->have_recommendation = FALSE;
+ entry->rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION;
+ entry->eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
+ chunk_clear(&entry->reason);
+ chunk_clear(&entry->reason_language);
+ }
+ enumerator->destroy(enumerator);
+}
+
METHOD(recommendations_t, get_preferred_language, chunk_t,
private_tnc_imv_recommendations_t *this)
{
@@ -293,7 +320,7 @@ METHOD(recommendations_t, set_reason_string, TNC_Result,
bool found = FALSE;
DBG2(DBG_TNC, "IMV %u is setting reason string to '%.*s'",
- id, reason.len, reason.ptr);
+ id, (int)reason.len, reason.ptr);
enumerator = this->recs->create_enumerator(this->recs);
while (enumerator->enumerate(enumerator, &entry))
@@ -318,7 +345,7 @@ METHOD(recommendations_t, set_reason_language, TNC_Result,
bool found = FALSE;
DBG2(DBG_TNC, "IMV %u is setting reason language to '%.*s'",
- id, reason_lang.len, reason_lang.ptr);
+ id, (int)reason_lang.len, reason_lang.ptr);
enumerator = this->recs->create_enumerator(this->recs);
while (enumerator->enumerate(enumerator, &entry))
@@ -362,21 +389,6 @@ METHOD(recommendations_t, create_reason_enumerator, enumerator_t*,
(void*)reason_filter, NULL, NULL);
}
-METHOD(recommendations_t, clear_reasons, void,
- private_tnc_imv_recommendations_t *this)
-{
- enumerator_t *enumerator;
- recommendation_entry_t *entry;
-
- enumerator = this->recs->create_enumerator(this->recs);
- while (enumerator->enumerate(enumerator, &entry))
- {
- chunk_clear(&entry->reason);
- chunk_clear(&entry->reason_language);
- }
- enumerator->destroy(enumerator);
-}
-
METHOD(recommendations_t, destroy, void,
private_tnc_imv_recommendations_t *this)
{
@@ -407,12 +419,12 @@ recommendations_t* tnc_imv_recommendations_create(linked_list_t *imv_list)
.public = {
.provide_recommendation = _provide_recommendation,
.have_recommendation = _have_recommendation,
+ .clear_recommendation = _clear_recommendation,
.get_preferred_language = _get_preferred_language,
.set_preferred_language = _set_preferred_language,
.set_reason_string = _set_reason_string,
.set_reason_language = _set_reason_language,
.create_reason_enumerator = _create_reason_enumerator,
- .clear_reasons = _clear_reasons,
.destroy = _destroy,
},
.recs = linked_list_create(),
diff --git a/src/libcharon/plugins/tnc_pdp/Makefile.in b/src/libcharon/plugins/tnc_pdp/Makefile.in
index 70d3d6249..2b3fbd42b 100644
--- a/src/libcharon/plugins/tnc_pdp/Makefile.in
+++ b/src/libcharon/plugins/tnc_pdp/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -88,7 +89,7 @@ libstrongswan_tnc_pdp_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@MONOLITHIC_FALSE@am_libstrongswan_tnc_pdp_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_tnc_pdp_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -114,6 +115,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -208,11 +210,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -229,11 +234,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -249,6 +255,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -258,7 +265,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/tnc_pdp/tnc_pdp.c b/src/libcharon/plugins/tnc_pdp/tnc_pdp.c
index 0625baa90..77eaa0e05 100644
--- a/src/libcharon/plugins/tnc_pdp/tnc_pdp.c
+++ b/src/libcharon/plugins/tnc_pdp/tnc_pdp.c
@@ -27,7 +27,7 @@
#include <pen/pen.h>
#include <threading/thread.h>
#include <processing/jobs/callback_job.h>
-#include <sa/authenticators/eap/eap_method.h>
+#include <sa/eap/eap_method.h>
typedef struct private_tnc_pdp_t private_tnc_pdp_t;
@@ -67,11 +67,6 @@ struct private_tnc_pdp_t {
int ipv6;
/**
- * Callback job dispatching commands
- */
- callback_job_t *job;
-
- /**
* RADIUS shared secret
*/
chunk_t secret;
@@ -87,9 +82,9 @@ struct private_tnc_pdp_t {
signer_t *signer;
/**
- * Random number generator for MS-MPPE salt values
+ * Nonce generator for MS-MPPE salt values
*/
- rng_t *rng;
+ nonce_gen_t *ng;
/**
* List of registered TNC-PDP connections
@@ -221,7 +216,11 @@ static chunk_t encrypt_mppe_key(private_tnc_pdp_t *this, u_int8_t type,
a = chunk_create((u_char*)&(mppe_key->salt), sizeof(mppe_key->salt));
do
{
- this->rng->get_bytes(this->rng, a.len, a.ptr);
+ if (!this->ng->get_nonce(this->ng, a.len, a.ptr))
+ {
+ free(data.ptr);
+ return chunk_empty;
+ }
*a.ptr |= 0x80;
}
while (mppe_key->salt == *salt);
@@ -236,8 +235,12 @@ static chunk_t encrypt_mppe_key(private_tnc_pdp_t *this, u_int8_t type,
while (c < data.ptr + data.len)
{
/* b(i) = MD5(S + c(i-1)) */
- this->hasher->get_hash(this->hasher, this->secret, NULL);
- this->hasher->get_hash(this->hasher, seed, b);
+ if (!this->hasher->get_hash(this->hasher, this->secret, NULL) ||
+ !this->hasher->get_hash(this->hasher, seed, b))
+ {
+ free(data.ptr);
+ return chunk_empty;
+ }
/* c(i) = b(i) xor p(1) */
memxor(c, b, HASH_SIZE_MD5);
@@ -263,20 +266,18 @@ static void send_response(private_tnc_pdp_t *this, radius_message_t *request,
u_int16_t salt = 0;
response = radius_message_create(code);
- if (eap)
- {
- data = eap->get_data(eap);
- DBG3(DBG_CFG, "%N payload %B", eap_type_names, this->type, &data);
+ data = eap->get_data(eap);
+ DBG3(DBG_CFG, "%N payload %B", eap_type_names, this->type, &data);
- /* fragment data suitable for RADIUS */
- while (data.len > MAX_RADIUS_ATTRIBUTE_SIZE)
- {
- response->add(response, RAT_EAP_MESSAGE,
- chunk_create(data.ptr, MAX_RADIUS_ATTRIBUTE_SIZE));
- data = chunk_skip(data, MAX_RADIUS_ATTRIBUTE_SIZE);
- }
- response->add(response, RAT_EAP_MESSAGE, data);
+ /* fragment data suitable for RADIUS */
+ while (data.len > MAX_RADIUS_ATTRIBUTE_SIZE)
+ {
+ response->add(response, RAT_EAP_MESSAGE,
+ chunk_create(data.ptr, MAX_RADIUS_ATTRIBUTE_SIZE));
+ data = chunk_skip(data, MAX_RADIUS_ATTRIBUTE_SIZE);
}
+ response->add(response, RAT_EAP_MESSAGE, data);
+
if (group)
{
tunnel_type = RADIUS_TUNNEL_TYPE_ESP;
@@ -291,19 +292,20 @@ static void send_response(private_tnc_pdp_t *this, radius_message_t *request,
data = encrypt_mppe_key(this, MS_MPPE_RECV_KEY, recv, &salt, request);
response->add(response, RAT_VENDOR_SPECIFIC, data);
chunk_free(&data);
-
+
send = chunk_create(msk.ptr + recv.len, msk.len - recv.len);
data = encrypt_mppe_key(this, MS_MPPE_SEND_KEY, send, &salt, request);
response->add(response, RAT_VENDOR_SPECIFIC, data);
chunk_free(&data);
}
response->set_identifier(response, request->get_identifier(request));
- response->sign(response, request->get_authenticator(request),
- this->secret, this->hasher, this->signer, NULL, TRUE);
-
- DBG1(DBG_CFG, "sending RADIUS %N to client '%H'", radius_message_code_names,
- code, client);
- send_message(this, response, client);
+ if (response->sign(response, request->get_authenticator(request),
+ this->secret, this->hasher, this->signer, NULL, TRUE))
+ {
+ DBG1(DBG_CFG, "sending RADIUS %N to client '%H'",
+ radius_message_code_names, code, client);
+ send_message(this, response, client);
+ }
response->destroy(response);
}
@@ -368,7 +370,7 @@ static void process_eap(private_tnc_pdp_t *this, radius_message_t *request,
eap_identity = chunk_create(message.ptr + 5, message.len - 5);
peer = identification_create_from_data(eap_identity);
method = charon->eap->create_instance(charon->eap, this->type,
- 0, EAP_SERVER, this->server, peer);
+ 0, EAP_SERVER, this->server, peer);
if (!method)
{
peer->destroy(peer);
@@ -524,7 +526,7 @@ static job_requeue_t receive(private_tnc_pdp_t *this)
if (request)
{
DBG1(DBG_CFG, "received RADIUS %N from client '%H'",
- radius_message_code_names, request->get_code(request), source);
+ radius_message_code_names, request->get_code(request), source);
if (request->verify(request, NULL, this->secret, this->hasher,
this->signer))
@@ -532,7 +534,7 @@ static job_requeue_t receive(private_tnc_pdp_t *this)
process_eap(this, request, source);
}
request->destroy(request);
-
+
}
else
{
@@ -546,10 +548,6 @@ static job_requeue_t receive(private_tnc_pdp_t *this)
METHOD(tnc_pdp_t, destroy, void,
private_tnc_pdp_t *this)
{
- if (this->job)
- {
- this->job->cancel(this->job);
- }
if (this->ipv4)
{
close(this->ipv4);
@@ -561,7 +559,7 @@ METHOD(tnc_pdp_t, destroy, void,
DESTROY_IF(this->server);
DESTROY_IF(this->signer);
DESTROY_IF(this->hasher);
- DESTROY_IF(this->rng);
+ DESTROY_IF(this->ng);
DESTROY_IF(this->connections);
free(this);
}
@@ -582,13 +580,13 @@ tnc_pdp_t *tnc_pdp_create(u_int16_t port)
.ipv6 = open_socket(AF_INET6, port),
.hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5),
.signer = lib->crypto->create_signer(lib->crypto, AUTH_HMAC_MD5_128),
- .rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK),
+ .ng = lib->crypto->create_nonce_gen(lib->crypto),
.connections = tnc_pdp_connections_create(),
);
- if (!this->hasher || !this->signer || !this->rng)
+ if (!this->hasher || !this->signer || !this->ng)
{
- DBG1(DBG_CFG, "RADIUS initialization failed, HMAC/MD5/RNG required");
+ DBG1(DBG_CFG, "RADIUS initialization failed, HMAC/MD5/NG required");
destroy(this);
return NULL;
}
@@ -608,7 +606,7 @@ tnc_pdp_t *tnc_pdp_create(u_int16_t port)
}
server = lib->settings->get_str(lib->settings,
- "charon.plugins.tnc-pdp.server", NULL);
+ "%s.plugins.tnc-pdp.server", NULL, charon->name);
if (!server)
{
DBG1(DBG_CFG, "missing PDP server name, PDP disabled");
@@ -618,7 +616,7 @@ tnc_pdp_t *tnc_pdp_create(u_int16_t port)
this->server = identification_create_from_string(server);
secret = lib->settings->get_str(lib->settings,
- "charon.plugins.tnc-pdp.secret", NULL);
+ "%s.plugins.tnc-pdp.secret", NULL, charon->name);
if (!secret)
{
DBG1(DBG_CFG, "missing RADIUS secret, PDP disabled");
@@ -626,10 +624,15 @@ tnc_pdp_t *tnc_pdp_create(u_int16_t port)
return NULL;
}
this->secret = chunk_create(secret, strlen(secret));
- this->signer->set_key(this->signer, this->secret);
+ if (!this->signer->set_key(this->signer, this->secret))
+ {
+ DBG1(DBG_CFG, "could not set signer key");
+ destroy(this);
+ return NULL;
+ }
eap_type_str = lib->settings->get_str(lib->settings,
- "charon.plugins.tnc-pdp.method", "ttls");
+ "%s.plugins.tnc-pdp.method", "ttls", charon->name);
this->type = eap_type_from_string(eap_type_str);
if (this->type == 0)
{
@@ -639,9 +642,9 @@ tnc_pdp_t *tnc_pdp_create(u_int16_t port)
}
DBG1(DBG_IKE, "eap method %N selected", eap_type_names, this->type);
- this->job = callback_job_create_with_prio((callback_job_cb_t)receive,
- this, NULL, NULL, JOB_PRIO_CRITICAL);
- lib->processor->queue_job(lib->processor, (job_t*)this->job);
+ lib->processor->queue_job(lib->processor,
+ (job_t*)callback_job_create_with_prio((callback_job_cb_t)receive, this,
+ NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
return &this->public;
}
diff --git a/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.c b/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.c
index 175a57aba..bca43985f 100644
--- a/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.c
+++ b/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.c
@@ -33,7 +33,7 @@ struct private_tnc_pdp_connections_t {
/**
* List of TNC PEP RADIUS Connections
- */
+ */
linked_list_t *list;
};
@@ -94,13 +94,14 @@ static void dbg_nas_user(chunk_t nas_id, chunk_t user_name, bool not, char *op)
if (nas_id.len)
{
DBG1(DBG_CFG, "%s RADIUS connection for user '%.*s' NAS '%.*s'",
- not ? "could not find" : op, user_name.len, user_name.ptr,
- nas_id.len, nas_id.ptr);
+ not ? "could not find" : op, (int)user_name.len,
+ user_name.ptr, (int)nas_id.len, nas_id.ptr);
}
else
{
- DBG1(DBG_CFG, "%s RADIUS connection for user '%.*s'",
- not ? "could not find" : op, user_name.len, user_name.ptr);
+ DBG1(DBG_CFG, "%s RADIUS connection for user '%.*s'",
+ not ? "could not find" : op, (int)user_name.len,
+ user_name.ptr);
}
}
@@ -114,8 +115,8 @@ METHOD(tnc_pdp_connections_t, add, void,
ike_sa_t *ike_sa;
bool found = FALSE;
- ike_sa_id = ike_sa_id_create(0, 0, FALSE);
- ike_sa = ike_sa_create(ike_sa_id);
+ ike_sa_id = ike_sa_id_create(IKEV2_MAJOR_VERSION, 0, 0, FALSE);
+ ike_sa = ike_sa_create(ike_sa_id, FALSE, IKEV2);
ike_sa_id->destroy(ike_sa_id);
ike_sa->set_other_id(ike_sa, peer);
@@ -134,7 +135,7 @@ METHOD(tnc_pdp_connections_t, add, void,
}
}
enumerator->destroy(enumerator);
-
+
if (!found)
{
entry = malloc_thing(entry_t);
diff --git a/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.h b/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.h
index b9f5d097b..16492020e 100644
--- a/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.h
+++ b/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.h
@@ -25,7 +25,7 @@ typedef struct tnc_pdp_connections_t tnc_pdp_connections_t;
#include <library.h>
#include <sa/ike_sa.h>
-#include <sa/authenticators/eap/eap_method.h>
+#include <sa/eap/eap_method.h>
/**
* Public interface of a tnc_pdp_connections object
diff --git a/src/libcharon/plugins/tnc_pdp/tnc_pdp_plugin.c b/src/libcharon/plugins/tnc_pdp/tnc_pdp_plugin.c
index 9abe02aec..295c7a5d6 100644
--- a/src/libcharon/plugins/tnc_pdp/tnc_pdp_plugin.c
+++ b/src/libcharon/plugins/tnc_pdp/tnc_pdp_plugin.c
@@ -16,6 +16,8 @@
#include "tnc_pdp_plugin.h"
#include "tnc_pdp.h"
+#include <daemon.h>
+
typedef struct private_tnc_pdp_plugin_t private_tnc_pdp_plugin_t;
/**
@@ -73,7 +75,7 @@ plugin_t *tnc_pdp_plugin_create()
int port;
port = lib->settings->get_int(lib->settings,
- "charon.plugins.tnc_pdp.port", RADIUS_PORT);
+ "%s.plugins.tnc_pdp.port", RADIUS_PORT, charon->name);
INIT(this,
.public = {
diff --git a/src/libcharon/plugins/tnc_tnccs/Makefile.in b/src/libcharon/plugins/tnc_tnccs/Makefile.in
index c12a837d1..3ef913e7b 100644
--- a/src/libcharon/plugins/tnc_tnccs/Makefile.in
+++ b/src/libcharon/plugins/tnc_tnccs/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -88,7 +89,7 @@ libstrongswan_tnc_tnccs_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_tnc_tnccs_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_tnc_tnccs_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -114,6 +115,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -208,11 +210,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -229,11 +234,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -249,6 +255,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -258,7 +265,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.c b/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.c
index 64ed160d9..515e85804 100644
--- a/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.c
+++ b/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Andreas Steffen
+ * Copyright (C) 2010-2012 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -75,6 +75,11 @@ struct tnccs_connection_entry_t {
bool *request_handshake_retry;
/**
+ * Maximum size of a PA-TNC message
+ */
+ u_int32_t max_msg_len;
+
+ /**
* collection of IMV recommendations
*/
recommendations_t *recs;
@@ -181,7 +186,7 @@ METHOD(tnccs_manager_t, create_instance, tnccs_t*,
METHOD(tnccs_manager_t, create_connection, TNC_ConnectionID,
private_tnc_tnccs_manager_t *this, tnccs_type_t type, tnccs_t *tnccs,
tnccs_send_message_t send_message, bool* request_handshake_retry,
- recommendations_t **recs)
+ u_int32_t max_msg_len, recommendations_t **recs)
{
tnccs_connection_entry_t *entry;
@@ -190,6 +195,7 @@ METHOD(tnccs_manager_t, create_connection, TNC_ConnectionID,
entry->tnccs = tnccs;
entry->send_message = send_message;
entry->request_handshake_retry = request_handshake_retry;
+ entry->max_msg_len = max_msg_len;
if (recs)
{
/* we assume a TNC Server needing recommendations from IMVs */
@@ -564,16 +570,18 @@ METHOD(tnccs_manager_t, get_attribute, TNC_Result,
return TNC_RESULT_SUCCESS;
}
case TNC_ATTRIBUTEID_MAX_ROUND_TRIPS:
- return uint_attribute(buffer_len, buffer, value_len, 0xffffffff);
+ return uint_attribute(buffer_len, buffer, value_len,
+ 0xffffffff);
case TNC_ATTRIBUTEID_MAX_MESSAGE_SIZE:
- return uint_attribute(buffer_len, buffer, value_len, 0x00000000);
+ return uint_attribute(buffer_len, buffer, value_len,
+ entry->max_msg_len);
case TNC_ATTRIBUTEID_HAS_LONG_TYPES:
case TNC_ATTRIBUTEID_HAS_EXCLUSIVE:
return bool_attribute(buffer_len, buffer, value_len,
- entry->type == TNCCS_2_0);
+ entry->type == TNCCS_2_0);
case TNC_ATTRIBUTEID_HAS_SOH:
return bool_attribute(buffer_len, buffer, value_len,
- entry->type == TNCCS_SOH);
+ entry->type == TNCCS_SOH);
case TNC_ATTRIBUTEID_IFTNCCS_PROTOCOL:
{
char *protocol;
diff --git a/src/libcharon/plugins/tnccs_11/Makefile.am b/src/libcharon/plugins/tnccs_11/Makefile.am
index c205692d4..1d29460f8 100644
--- a/src/libcharon/plugins/tnccs_11/Makefile.am
+++ b/src/libcharon/plugins/tnccs_11/Makefile.am
@@ -1,6 +1,8 @@
INCLUDES = \
-I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libcharon \
+ -I$(top_srcdir)/src/libhydra \
-I$(top_srcdir)/src/libtls \
-I$(top_srcdir)/src/libtncif \
-I$(top_srcdir)/src/libtnccs \
diff --git a/src/libcharon/plugins/tnccs_11/Makefile.in b/src/libcharon/plugins/tnccs_11/Makefile.in
index 1902d1f93..3a506e672 100644
--- a/src/libcharon/plugins/tnccs_11/Makefile.in
+++ b/src/libcharon/plugins/tnccs_11/Makefile.in
@@ -53,6 +53,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -94,7 +95,7 @@ libstrongswan_tnccs_11_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_tnccs_11_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_tnccs_11_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -120,6 +121,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -214,11 +216,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -235,11 +240,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -255,6 +261,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -264,7 +271,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -294,6 +300,8 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
INCLUDES = \
-I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libcharon \
+ -I$(top_srcdir)/src/libhydra \
-I$(top_srcdir)/src/libtls \
-I$(top_srcdir)/src/libtncif \
-I$(top_srcdir)/src/libtnccs \
diff --git a/src/libcharon/plugins/tnccs_11/tnccs_11.c b/src/libcharon/plugins/tnccs_11/tnccs_11.c
index 3673221e5..56858a8b4 100644
--- a/src/libcharon/plugins/tnccs_11/tnccs_11.c
+++ b/src/libcharon/plugins/tnccs_11/tnccs_11.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Andreas Steffen
+ * Copyright (C) 2010-2012 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -32,6 +32,7 @@
#include <tnc/tnccs/tnccs_manager.h>
#include <debug.h>
+#include <daemon.h>
#include <threading/mutex.h>
typedef struct private_tnccs_11_t private_tnccs_11_t;
@@ -67,6 +68,11 @@ struct private_tnccs_11_t {
tnccs_batch_t *batch;
/**
+ * Maximum PA-TNC message size
+ */
+ size_t max_msg_len;
+
+ /**
* Mutex locking the batch in construction
*/
mutex_t *mutex;
@@ -122,7 +128,7 @@ METHOD(tnccs_t, send_msg, TNC_Result,
return TNC_RESULT_NO_LONG_MESSAGE_TYPES;
}
msg_type = (msg_vid << 8) | msg_subtype;
-
+
pa_subtype_names = get_pa_subtype_names(msg_vid);
if (pa_subtype_names)
{
@@ -266,10 +272,10 @@ static void handle_message(private_tnccs_11_t *this, tnccs_msg_t *msg)
reason_msg = (tnccs_reason_strings_msg_t*)msg;
reason_string = reason_msg->get_reason(reason_msg, &reason_lang);
- DBG2(DBG_TNC, "reason string is '%.*s'", reason_string.len,
- reason_string.ptr);
- DBG2(DBG_TNC, "reason language is '%.*s'", reason_lang.len,
- reason_lang.ptr);
+ DBG2(DBG_TNC, "reason string is '%.*s'", (int)reason_string.len,
+ reason_string.ptr);
+ DBG2(DBG_TNC, "language code is '%.*s'", (int)reason_lang.len,
+ reason_lang.ptr);
break;
}
default:
@@ -289,8 +295,9 @@ METHOD(tls_t, process, status_t,
if (this->is_server && !this->connection_id)
{
this->connection_id = tnc->tnccs->create_connection(tnc->tnccs,
- TNCCS_1_1, (tnccs_t*)this, _send_msg,
- &this->request_handshake_retry, &this->recs);
+ TNCCS_1_1, (tnccs_t*)this, _send_msg,
+ &this->request_handshake_retry,
+ this->max_msg_len, &this->recs);
if (!this->connection_id)
{
return FAILED;
@@ -304,7 +311,7 @@ METHOD(tls_t, process, status_t,
data = chunk_create(buf, buflen);
DBG1(DBG_TNC, "received TNCCS Batch (%u bytes) for Connection ID %u",
data.len, this->connection_id);
- DBG3(DBG_TNC, "%.*s", data.len, data.ptr);
+ DBG3(DBG_TNC, "%.*s", (int)data.len, data.ptr);
batch = tnccs_batch_create_from_data(this->is_server, ++this->batch_id, data);
status = batch->process(batch);
@@ -396,7 +403,6 @@ static void check_and_build_recommendation(private_tnccs_11_t *this)
this->batch->add_msg(this->batch, msg);
}
enumerator->destroy(enumerator);
- this->recs->clear_reasons(this->recs);
/* we have reache the final state */
this->delete_state = TRUE;
@@ -416,7 +422,8 @@ METHOD(tls_t, build, status_t,
this->connection_id = tnc->tnccs->create_connection(tnc->tnccs,
TNCCS_1_1, (tnccs_t*)this, _send_msg,
- &this->request_handshake_retry, NULL);
+ &this->request_handshake_retry,
+ this->max_msg_len, NULL);
if (!this->connection_id)
{
return FAILED;
@@ -456,8 +463,8 @@ METHOD(tls_t, build, status_t,
data = this->batch->get_encoding(this->batch);
DBG1(DBG_TNC, "sending TNCCS Batch (%d bytes) for Connection ID %u",
data.len, this->connection_id);
- DBG3(DBG_TNC, "%.*s", data.len, data.ptr);
- *msglen = data.len;
+ DBG3(DBG_TNC, "%.*s", (int)data.len, data.ptr);
+ *msglen = 0;
if (data.len > *buflen)
{
@@ -545,6 +552,9 @@ tls_t *tnccs_11_create(bool is_server)
},
.is_server = is_server,
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ .max_msg_len = lib->settings->get_int(lib->settings,
+ "%s.plugins.tnccs-11.max_message_size", 45000,
+ charon->name),
);
return &this->public;
diff --git a/src/libcharon/plugins/tnccs_20/Makefile.am b/src/libcharon/plugins/tnccs_20/Makefile.am
index ec17e6412..da924b412 100644
--- a/src/libcharon/plugins/tnccs_20/Makefile.am
+++ b/src/libcharon/plugins/tnccs_20/Makefile.am
@@ -1,6 +1,8 @@
INCLUDES = \
-I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libcharon \
+ -I$(top_srcdir)/src/libhydra \
-I$(top_srcdir)/src/libtls \
-I$(top_srcdir)/src/libtncif \
-I$(top_srcdir)/src/libtnccs
diff --git a/src/libcharon/plugins/tnccs_20/Makefile.in b/src/libcharon/plugins/tnccs_20/Makefile.in
index b0078f338..26d26dbd9 100644
--- a/src/libcharon/plugins/tnccs_20/Makefile.in
+++ b/src/libcharon/plugins/tnccs_20/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -92,7 +93,7 @@ libstrongswan_tnccs_20_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_tnccs_20_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_tnccs_20_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -118,6 +119,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -212,11 +214,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -233,11 +238,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -253,6 +259,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -262,7 +269,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -292,6 +298,8 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
INCLUDES = \
-I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libcharon \
+ -I$(top_srcdir)/src/libhydra \
-I$(top_srcdir)/src/libtls \
-I$(top_srcdir)/src/libtncif \
-I$(top_srcdir)/src/libtnccs
diff --git a/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c b/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c
index c6a4bb599..2f932637a 100644
--- a/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c
+++ b/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Sansar Choinyanbuu
- * Copyright (C) 2010 Andreas Steffen
+ * Copyright (C) 2010-2012 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -96,6 +96,16 @@ struct private_pb_tnc_batch_t {
pb_tnc_batch_type_t type;
/**
+ * Current PB-TNC Batch size
+ */
+ size_t batch_len;
+
+ /**
+ * Maximum PB-TNC Batch size
+ */
+ size_t max_batch_len;
+
+ /**
* linked list of PB-TNC messages
*/
linked_list_t *messages;
@@ -128,42 +138,46 @@ METHOD(pb_tnc_batch_t, get_encoding, chunk_t,
return this->encoding;
}
-METHOD(pb_tnc_batch_t, add_msg, void,
+METHOD(pb_tnc_batch_t, add_msg, bool,
private_pb_tnc_batch_t *this, pb_tnc_msg_t* msg)
{
+ chunk_t msg_value;
+ size_t msg_len;
+
+ msg->build(msg);
+ msg_value = msg->get_encoding(msg);
+ msg_len = PB_TNC_HEADER_SIZE + msg_value.len;
+
+ if (this->batch_len + msg_len > this->max_batch_len)
+ {
+ /* message just does not fit into this batch */
+ return FALSE;
+ }
+ this->batch_len += msg_len;
+
DBG2(DBG_TNC, "adding %N message", pb_tnc_msg_type_names,
msg->get_type(msg));
this->messages->insert_last(this->messages, msg);
+ return TRUE;
}
METHOD(pb_tnc_batch_t, build, void,
private_pb_tnc_batch_t *this)
{
- u_int32_t batch_len, msg_len;
+ u_int32_t msg_len;
chunk_t msg_value;
enumerator_t *enumerator;
pb_tnc_msg_type_t msg_type;
pb_tnc_msg_t *msg;
bio_writer_t *writer;
- /* compute total PB-TNC batch size by summing over all messages */
- batch_len = PB_TNC_BATCH_HEADER_SIZE;
- enumerator = this->messages->create_enumerator(this->messages);
- while (enumerator->enumerate(enumerator, &msg))
- {
- msg->build(msg);
- msg_value = msg->get_encoding(msg);
- batch_len += PB_TNC_HEADER_SIZE + msg_value.len;
- }
- enumerator->destroy(enumerator);
-
/* build PB-TNC batch header */
- writer = bio_writer_create(batch_len);
+ writer = bio_writer_create(this->batch_len);
writer->write_uint8 (writer, PB_TNC_VERSION);
writer->write_uint8 (writer, this->is_server ?
PB_TNC_BATCH_FLAG_D : PB_TNC_BATCH_FLAG_NONE);
writer->write_uint16(writer, this->type);
- writer->write_uint32(writer, batch_len);
+ writer->write_uint32(writer, this->batch_len);
/* build PB-TNC messages */
enumerator = this->messages->create_enumerator(this->messages);
@@ -221,7 +235,7 @@ static status_t process_batch_header(private_pb_tnc_batch_t *this,
/* Version */
if (version != PB_TNC_VERSION)
{
- DBG1(DBG_TNC, "unsupported TNCCS batch version 0x%01x", version);
+ DBG1(DBG_TNC, "unsupported TNCCS batch version 0x%02x", version);
msg = pb_error_msg_create(TRUE, PEN_IETF,
PB_ERROR_VERSION_NOT_SUPPORTED);
err_msg = (pb_error_msg_t*)msg;
@@ -258,6 +272,8 @@ static status_t process_batch_header(private_pb_tnc_batch_t *this,
PB_ERROR_UNEXPECTED_BATCH_TYPE);
goto fatal;
}
+ DBG1(DBG_TNC, "processing PB-TNC %N batch", pb_tnc_batch_type_names,
+ this->type);
/* Batch Length */
if (this->encoding.len != batch_len)
@@ -270,6 +286,13 @@ static status_t process_batch_header(private_pb_tnc_batch_t *this,
}
this->offset = PB_TNC_BATCH_HEADER_SIZE;
+
+ /* Register an empty CDATA batch with the state machine */
+ if (this->type == PB_BATCH_CDATA)
+ {
+ state_machine->set_empty_cdata(state_machine,
+ this->offset == this->encoding.len);
+ }
return SUCCESS;
fatal:
@@ -445,8 +468,7 @@ METHOD(pb_tnc_batch_t, process, status_t,
{
return FAILED;
}
- DBG1(DBG_TNC, "processing PB-TNC %N batch", pb_tnc_batch_type_names,
- this->type);
+
while (this->offset < this->encoding.len)
{
switch (process_tnc_msg(this))
@@ -490,7 +512,8 @@ METHOD(pb_tnc_batch_t, destroy, void,
/**
* See header
*/
-pb_tnc_batch_t* pb_tnc_batch_create(bool is_server, pb_tnc_batch_type_t type)
+pb_tnc_batch_t* pb_tnc_batch_create(bool is_server, pb_tnc_batch_type_t type,
+ size_t max_batch_len)
{
private_pb_tnc_batch_t *this;
@@ -507,6 +530,8 @@ pb_tnc_batch_t* pb_tnc_batch_create(bool is_server, pb_tnc_batch_type_t type)
},
.is_server = is_server,
.type = type,
+ .max_batch_len = max_batch_len,
+ .batch_len = PB_TNC_BATCH_HEADER_SIZE,
.messages = linked_list_create(),
.errors = linked_list_create(),
);
diff --git a/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.h b/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.h
index 17e5fff4c..60cef7735 100644
--- a/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.h
+++ b/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Andreas Steffen
+ * Copyright (C) 2010-2012 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -33,6 +33,7 @@ typedef struct pb_tnc_batch_t pb_tnc_batch_t;
* PB-TNC Batch Types as defined in section 4.1 of RFC 5793
*/
enum pb_tnc_batch_type_t {
+ PB_BATCH_NONE = 0, /* for internal use only */
PB_BATCH_CDATA = 1,
PB_BATCH_SDATA = 2,
PB_BATCH_RESULT = 3,
@@ -70,8 +71,9 @@ struct pb_tnc_batch_t {
* Add a PB-TNC Message
*
* @param msg PB-TNC message to be addedd
+ * @return TRUE if message fit into batch and was added
*/
- void (*add_msg)(pb_tnc_batch_t *this, pb_tnc_msg_t* msg);
+ bool (*add_msg)(pb_tnc_batch_t *this, pb_tnc_msg_t* msg);
/**
* Build the PB-TNC Batch
@@ -112,8 +114,10 @@ struct pb_tnc_batch_t {
*
* @param is_server TRUE if server, FALSE if client
* @param type PB-TNC batch type
+ * @param max_batch_len maximum size the PB-TNC batch
*/
-pb_tnc_batch_t* pb_tnc_batch_create(bool is_server, pb_tnc_batch_type_t type);
+pb_tnc_batch_t* pb_tnc_batch_create(bool is_server, pb_tnc_batch_type_t type,
+ size_t max_batch_len);
/**
* Create an unprocessed PB-TNC Batch from data
diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_access_recommendation_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_access_recommendation_msg.c
index fa3deddf6..974db4d70 100644
--- a/src/libcharon/plugins/tnccs_20/messages/pb_access_recommendation_msg.c
+++ b/src/libcharon/plugins/tnccs_20/messages/pb_access_recommendation_msg.c
@@ -82,11 +82,13 @@ METHOD(pb_tnc_msg_t, build, void,
{
bio_writer_t *writer;
- /* build message */
+ if (this->encoding.ptr)
+ {
+ return;
+ }
writer = bio_writer_create(ACCESS_RECOMMENDATION_MSG_SIZE);
writer->write_uint16(writer, ACCESS_RECOMMENDATION_RESERVED);
writer->write_uint16(writer, this->recommendation);
- free(this->encoding.ptr);
this->encoding = writer->get_buf(writer);
this->encoding = chunk_clone(this->encoding);
writer->destroy(writer);
@@ -98,7 +100,6 @@ METHOD(pb_tnc_msg_t, process, status_t,
bio_reader_t *reader;
u_int16_t reserved;
- /* process message */
reader = bio_reader_create(this->encoding);
reader->read_uint16(reader, &reserved);
reader->read_uint16(reader, &this->recommendation);
diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_assessment_result_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_assessment_result_msg.c
index 0d558c0d4..ee06575b4 100644
--- a/src/libcharon/plugins/tnccs_20/messages/pb_assessment_result_msg.c
+++ b/src/libcharon/plugins/tnccs_20/messages/pb_assessment_result_msg.c
@@ -78,10 +78,12 @@ METHOD(pb_tnc_msg_t, build, void,
{
bio_writer_t *writer;
- /* build message */
+ if (this->encoding.ptr)
+ {
+ return;
+ }
writer = bio_writer_create(ASSESSMENT_RESULT_MSG_SIZE);
writer->write_uint32(writer, this->assessment_result);
- free(this->encoding.ptr);
this->encoding = writer->get_buf(writer);
this->encoding = chunk_clone(this->encoding);
writer->destroy(writer);
@@ -92,7 +94,6 @@ METHOD(pb_tnc_msg_t, process, status_t,
{
bio_reader_t *reader;
- /* process message */
reader = bio_reader_create(this->encoding);
reader->read_uint32(reader, &this->assessment_result);
reader->destroy(reader);
diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_error_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_error_msg.c
index 03e3cec92..457d3da21 100644
--- a/src/libcharon/plugins/tnccs_20/messages/pb_error_msg.c
+++ b/src/libcharon/plugins/tnccs_20/messages/pb_error_msg.c
@@ -120,6 +120,11 @@ METHOD(pb_tnc_msg_t, build, void,
{
bio_writer_t *writer;
+ if (this->encoding.ptr)
+ {
+ return;
+ }
+
/* build message header */
writer = bio_writer_create(ERROR_HEADER_SIZE);
writer->write_uint8 (writer, this->fatal ?
@@ -142,8 +147,6 @@ METHOD(pb_tnc_msg_t, build, void,
/* Error Offset */
writer->write_uint32(writer, this->error_offset);
}
-
- free(this->encoding.ptr);
this->encoding = writer->get_buf(writer);
this->encoding = chunk_clone(this->encoding);
writer->destroy(writer);
diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_language_preference_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_language_preference_msg.c
index 297cc8df7..46df54486 100644
--- a/src/libcharon/plugins/tnccs_20/messages/pb_language_preference_msg.c
+++ b/src/libcharon/plugins/tnccs_20/messages/pb_language_preference_msg.c
@@ -75,6 +75,10 @@ METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
METHOD(pb_tnc_msg_t, build, void,
private_pb_language_preference_msg_t *this)
{
+ if (this->encoding.ptr)
+ {
+ return;
+ }
this->encoding = chunk_cat("cc",
chunk_create(PB_LANG_PREFIX, PB_LANG_PREFIX_LEN),
this->language_preference);
diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.c
index 1c4913e5e..bbad9bf55 100644
--- a/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.c
+++ b/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.c
@@ -68,14 +68,9 @@ struct private_pb_pa_msg_t {
bool excl;
/**
- * PA Message Vendor ID
+ * Vendor-specific PA Subtype
*/
- u_int32_t vendor_id;
-
- /**
- * PA Subtype
- */
- u_int32_t subtype;
+ pen_type_t subtype;
/**
* Posture Validator Identifier
@@ -116,17 +111,21 @@ METHOD(pb_tnc_msg_t, build, void,
chunk_t msg_header;
bio_writer_t *writer;
+ if (this->encoding.ptr)
+ {
+ return;
+ }
+
/* build message header */
writer = bio_writer_create(64);
writer->write_uint8 (writer, this->excl ? PA_FLAG_EXCL : PA_FLAG_NONE);
- writer->write_uint24(writer, this->vendor_id);
- writer->write_uint32(writer, this->subtype);
+ writer->write_uint24(writer, this->subtype.vendor_id);
+ writer->write_uint32(writer, this->subtype.type);
writer->write_uint16(writer, this->collector_id);
writer->write_uint16(writer, this->validator_id);
msg_header = writer->get_buf(writer);
/* create encoding by concatenating message header and message body */
- free(this->encoding.ptr);
this->encoding = chunk_cat("cc", msg_header, this->msg_body);
writer->destroy(writer);
}
@@ -141,8 +140,8 @@ METHOD(pb_tnc_msg_t, process, status_t,
/* process message header */
reader = bio_reader_create(this->encoding);
reader->read_uint8 (reader, &flags);
- reader->read_uint24(reader, &this->vendor_id);
- reader->read_uint32(reader, &this->subtype);
+ reader->read_uint24(reader, &this->subtype.vendor_id);
+ reader->read_uint32(reader, &this->subtype.type);
reader->read_uint16(reader, &this->collector_id);
reader->read_uint16(reader, &this->validator_id);
this->excl = ((flags & PA_FLAG_EXCL) != PA_FLAG_NONE);
@@ -156,14 +155,14 @@ METHOD(pb_tnc_msg_t, process, status_t,
}
reader->destroy(reader);
- if (this->vendor_id == PEN_RESERVED)
+ if (this->subtype.vendor_id == PEN_RESERVED)
{
DBG1(DBG_TNC, "Vendor ID 0x%06x is reserved", PEN_RESERVED);
*offset = 1;
return FAILED;
}
- if (this->subtype == PA_RESERVED_SUBTYPE)
+ if (this->subtype.type == PA_RESERVED_SUBTYPE)
{
DBG1(DBG_TNC, "PA Subtype 0x%08x is reserved", PA_RESERVED_SUBTYPE);
*offset = 4;
@@ -180,11 +179,10 @@ METHOD(pb_tnc_msg_t, destroy, void,
free(this);
}
-METHOD(pb_pa_msg_t, get_vendor_id, u_int32_t,
- private_pb_pa_msg_t *this, u_int32_t *subtype)
+METHOD(pb_pa_msg_t, get_subtype, pen_type_t,
+ private_pb_pa_msg_t *this)
{
- *subtype = this->subtype;
- return this->vendor_id;
+ return this->subtype;
}
METHOD(pb_pa_msg_t, get_collector_id, u_int16_t,
@@ -226,7 +224,7 @@ pb_tnc_msg_t *pb_pa_msg_create_from_data(chunk_t data)
.process = _process,
.destroy = _destroy,
},
- .get_vendor_id = _get_vendor_id,
+ .get_subtype = _get_subtype,
.get_collector_id = _get_collector_id,
.get_validator_id = _get_validator_id,
.get_body = _get_body,
@@ -257,15 +255,14 @@ pb_tnc_msg_t *pb_pa_msg_create(u_int32_t vendor_id, u_int32_t subtype,
.process = _process,
.destroy = _destroy,
},
- .get_vendor_id = _get_vendor_id,
+ .get_subtype= _get_subtype,
.get_collector_id = _get_collector_id,
.get_validator_id = _get_validator_id,
.get_body = _get_body,
.get_exclusive_flag = _get_exclusive_flag,
},
.type = PB_MSG_PA,
- .vendor_id = vendor_id,
- .subtype = subtype,
+ .subtype = { vendor_id, subtype },
.collector_id = collector_id,
.validator_id = validator_id,
.excl = excl,
diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.h b/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.h
index d9db9a1ce..5c9b7c0bf 100644
--- a/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.h
+++ b/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.h
@@ -25,6 +25,8 @@ typedef struct pb_pa_msg_t pb_pa_msg_t;
#include "pb_tnc_msg.h"
+#include <pen/pen.h>
+
/**
* Class representing the PB-PA message type.
*/
@@ -38,10 +40,9 @@ struct pb_pa_msg_t {
/**
* Get PA Message Vendor ID and Subtype
*
- * @param subtype PA Subtype
- * @return PA Message Vendor ID
+ * @return Vendor-specific PA Subtype
*/
- u_int32_t (*get_vendor_id)(pb_pa_msg_t *this, u_int32_t *subtype);
+ pen_type_t (*get_subtype)(pb_pa_msg_t *this);
/**
* Get Posture Collector ID
diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_reason_string_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_reason_string_msg.c
index 181ecf61b..511b45402 100644
--- a/src/libcharon/plugins/tnccs_20/messages/pb_reason_string_msg.c
+++ b/src/libcharon/plugins/tnccs_20/messages/pb_reason_string_msg.c
@@ -83,12 +83,14 @@ METHOD(pb_tnc_msg_t, build, void,
{
bio_writer_t *writer;
- /* build message */
+ if (this->encoding.ptr)
+ {
+ return;
+ }
writer = bio_writer_create(64);
writer->write_data32(writer, this->reason_string);
writer->write_data8 (writer, this->language_code);
- free(this->encoding.ptr);
this->encoding = writer->get_buf(writer);
this->encoding = chunk_clone(this->encoding);
writer->destroy(writer);
@@ -99,7 +101,6 @@ METHOD(pb_tnc_msg_t, process, status_t,
{
bio_reader_t *reader;
- /* process message */
reader = bio_reader_create(this->encoding);
if (!reader->read_data32(reader, &this->reason_string))
{
diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.c
index d213db313..c853f03a3 100644
--- a/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.c
+++ b/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.c
@@ -108,14 +108,16 @@ METHOD(pb_tnc_msg_t, build, void,
{
bio_writer_t *writer;
- /* build message */
+ if (this->encoding.ptr)
+ {
+ return;
+ }
writer = bio_writer_create(64);
writer->write_uint32(writer, this->vendor_id);
writer->write_uint32(writer, this->parameters_type);
writer->write_data32(writer, this->remediation_string);
writer->write_data8 (writer, this->language_code);
- free(this->encoding.ptr);
this->encoding = writer->get_buf(writer);
this->encoding = chunk_clone(this->encoding);
writer->destroy(writer);
diff --git a/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.c b/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.c
index f0cf14ac1..5e95131a8 100644
--- a/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.c
+++ b/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.c
@@ -71,6 +71,11 @@ struct private_pb_tnc_state_machine_t {
bool is_server;
/**
+ * Informs whether last received PB-TNC CDATA Batch was empty
+ */
+ bool empty_cdata;
+
+ /**
* Current PB-TNC state
*/
pb_tnc_state_t state;
@@ -265,6 +270,22 @@ METHOD(pb_tnc_state_machine_t, send_batch, bool,
return TRUE;
}
+METHOD(pb_tnc_state_machine_t, get_empty_cdata, bool,
+ private_pb_tnc_state_machine_t *this)
+{
+ return this->empty_cdata;
+}
+
+METHOD(pb_tnc_state_machine_t, set_empty_cdata, void,
+ private_pb_tnc_state_machine_t *this, bool empty)
+{
+ if (empty)
+ {
+ DBG2(DBG_TNC, "received empty PB-TNC CDATA batch");
+ }
+ this->empty_cdata = empty;
+}
+
METHOD(pb_tnc_state_machine_t, destroy, void,
private_pb_tnc_state_machine_t *this)
{
@@ -283,6 +304,8 @@ pb_tnc_state_machine_t* pb_tnc_state_machine_create(bool is_server)
.get_state = _get_state,
.receive_batch = _receive_batch,
.send_batch = _send_batch,
+ .get_empty_cdata = _get_empty_cdata,
+ .set_empty_cdata = _set_empty_cdata,
.destroy = _destroy,
},
.is_server = is_server,
diff --git a/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.h b/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.h
index 8076b6ded..aa317041e 100644
--- a/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.h
+++ b/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.h
@@ -73,6 +73,20 @@ struct pb_tnc_state_machine_t {
bool (*send_batch)(pb_tnc_state_machine_t *this, pb_tnc_batch_type_t type);
/**
+ * Informs whether the last received PB-TNC CDATA Batch was empty
+ *
+ * @result TRUE if last received PB-TNC CDATA Batch was empty
+ */
+ bool (*get_empty_cdata)(pb_tnc_state_machine_t *this);
+
+ /**
+ * Store information whether the received PB-TNC CDATA Batch was empty
+ *
+ * @param empty set to TRUE if received PB-TNC CDATA Batch was empty
+ */
+ void (*set_empty_cdata)(pb_tnc_state_machine_t *this, bool empty);
+
+ /**
* Destroys a pb_tnc_state_machine_t object.
*/
void (*destroy)(pb_tnc_state_machine_t *this);
diff --git a/src/libcharon/plugins/tnccs_20/tnccs_20.c b/src/libcharon/plugins/tnccs_20/tnccs_20.c
index 606fc529b..44e1d278f 100644
--- a/src/libcharon/plugins/tnccs_20/tnccs_20.c
+++ b/src/libcharon/plugins/tnccs_20/tnccs_20.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Sansar Choinyanbuu
- * Copyright (C) 2010-2011 Andreas Steffen
+ * Copyright (C) 2010-2012 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -35,7 +35,9 @@
#include <tnc/imv/imv_manager.h>
#include <debug.h>
+#include <daemon.h>
#include <threading/mutex.h>
+#include <utils/linked_list.h>
#include <pen/pen.h>
typedef struct private_tnccs_20_t private_tnccs_20_t;
@@ -66,9 +68,24 @@ struct private_tnccs_20_t {
TNC_ConnectionID connection_id;
/**
- * PB-TNC batch being constructed
+ * PB-TNC messages to be sent
*/
- pb_tnc_batch_t *batch;
+ linked_list_t *messages;
+
+ /**
+ * Type of PB-TNC batch being constructed
+ */
+ pb_tnc_batch_type_t batch_type;
+
+ /**
+ * Maximum PB-TNC batch size
+ */
+ size_t max_batch_len;
+
+ /**
+ * Maximum PA-TNC message size
+ */
+ size_t max_msg_len;
/**
* Mutex locking the batch in construction
@@ -97,6 +114,30 @@ struct private_tnccs_20_t {
};
+/**
+ * If the batch type changes then delete all accumulated PB-TNC messages
+ */
+void change_batch_type(private_tnccs_20_t *this, pb_tnc_batch_type_t batch_type)
+{
+ pb_tnc_msg_t *msg;
+
+ if (batch_type != this->batch_type)
+ {
+ if (this->batch_type != PB_BATCH_NONE)
+ {
+ DBG1(DBG_TNC, "cancelling PB-TNC %N batch",
+ pb_tnc_batch_type_names, this->batch_type);
+
+ while (this->messages->remove_last(this->messages,
+ (void**)&msg) == SUCCESS)
+ {
+ msg->destroy(msg);
+ }
+ }
+ this->batch_type = batch_type;
+ }
+}
+
METHOD(tnccs_t, send_msg, TNC_Result,
private_tnccs_20_t* this, TNC_IMCID imc_id, TNC_IMVID imv_id,
TNC_UInt32 msg_flags,
@@ -138,13 +179,13 @@ METHOD(tnccs_t, send_msg, TNC_Result,
/* adding PA message to SDATA or CDATA batch only */
batch_type = this->is_server ? PB_BATCH_SDATA : PB_BATCH_CDATA;
this->mutex->lock(this->mutex);
- if (!this->batch)
+ if (this->batch_type == PB_BATCH_NONE)
{
- this->batch = pb_tnc_batch_create(this->is_server, batch_type);
+ this->batch_type = batch_type;
}
- if (this->batch->get_type(this->batch) == batch_type)
+ if (this->batch_type == batch_type)
{
- this->batch->add_msg(this->batch, pb_tnc_msg);
+ this->messages->insert_last(this->messages, pb_tnc_msg);
}
else
{
@@ -167,30 +208,31 @@ static void handle_message(private_tnccs_20_t *this, pb_tnc_msg_t *msg)
case PB_MSG_PA:
{
pb_pa_msg_t *pa_msg;
- u_int32_t msg_vid, msg_subtype;
+ pen_type_t msg_subtype;
u_int16_t imc_id, imv_id;
chunk_t msg_body;
bool excl;
enum_name_t *pa_subtype_names;
pa_msg = (pb_pa_msg_t*)msg;
- msg_vid = pa_msg->get_vendor_id(pa_msg, &msg_subtype);
+ msg_subtype = pa_msg->get_subtype(pa_msg);
msg_body = pa_msg->get_body(pa_msg);
imc_id = pa_msg->get_collector_id(pa_msg);
imv_id = pa_msg->get_validator_id(pa_msg);
excl = pa_msg->get_exclusive_flag(pa_msg);
- pa_subtype_names = get_pa_subtype_names(msg_vid);
+ pa_subtype_names = get_pa_subtype_names(msg_subtype.vendor_id);
if (pa_subtype_names)
{
DBG2(DBG_TNC, "handling PB-PA message type '%N/%N' 0x%06x/0x%08x",
- pen_names, msg_vid, pa_subtype_names, msg_subtype,
- msg_vid, msg_subtype);
+ pen_names, msg_subtype.vendor_id, pa_subtype_names,
+ msg_subtype.type, msg_subtype.vendor_id, msg_subtype.type);
}
else
{
DBG2(DBG_TNC, "handling PB-PA message type '%N' 0x%06x/0x%08x",
- pen_names, msg_vid, msg_vid, msg_subtype);
+ pen_names, msg_subtype.vendor_id, msg_subtype.vendor_id,
+ msg_subtype.type);
}
this->send_msg = TRUE;
@@ -198,13 +240,15 @@ static void handle_message(private_tnccs_20_t *this, pb_tnc_msg_t *msg)
{
tnc->imvs->receive_message(tnc->imvs, this->connection_id,
excl, msg_body.ptr, msg_body.len,
- msg_vid, msg_subtype, imc_id, imv_id);
+ msg_subtype.vendor_id,
+ msg_subtype.type, imc_id, imv_id);
}
else
{
tnc->imcs->receive_message(tnc->imcs, this->connection_id,
excl, msg_body.ptr, msg_body.len,
- msg_vid, msg_subtype, imv_id, imc_id);
+ msg_subtype.vendor_id,
+ msg_subtype.type, imv_id, imc_id);
}
this->send_msg = FALSE;
break;
@@ -313,7 +357,7 @@ static void handle_message(private_tnccs_20_t *this, pb_tnc_msg_t *msg)
lang = lang_msg->get_language_preference(lang_msg);
DBG2(DBG_TNC, "setting language preference to '%.*s'",
- lang.len, lang.ptr);
+ (int)lang.len, lang.ptr);
this->recs->set_preferred_language(this->recs, lang);
break;
}
@@ -325,9 +369,9 @@ static void handle_message(private_tnccs_20_t *this, pb_tnc_msg_t *msg)
reason_msg = (pb_reason_string_msg_t*)msg;
reason_string = reason_msg->get_reason_string(reason_msg);
language_code = reason_msg->get_language_code(reason_msg);
- DBG2(DBG_TNC, "reason string is '%.*s'", reason_string.len,
+ DBG2(DBG_TNC, "reason string is '%.*s'", (int)reason_string.len,
reason_string.ptr);
- DBG2(DBG_TNC, "language code is '%.*s'", language_code.len,
+ DBG2(DBG_TNC, "language code is '%.*s'", (int)language_code.len,
language_code.ptr);
break;
}
@@ -344,23 +388,20 @@ static void build_retry_batch(private_tnccs_20_t *this)
pb_tnc_batch_type_t batch_retry_type;
batch_retry_type = this->is_server ? PB_BATCH_SRETRY : PB_BATCH_CRETRY;
- if (this->batch)
+ if (this->batch_type == batch_retry_type)
{
- if (this->batch->get_type(this->batch) == batch_retry_type)
- {
- /* retry batch has already been created */
- return;
- }
- DBG1(DBG_TNC, "cancelling PB-TNC %N batch",
- pb_tnc_batch_type_names, this->batch->get_type(this->batch));
- this->batch->destroy(this->batch);
- }
+ /* retry batch has already been selected */
+ return;
+ }
+
+ change_batch_type(this, batch_retry_type);
+
if (this->is_server)
{
+ this->recs->clear_recommendation(this->recs);
tnc->imvs->notify_connection_change(tnc->imvs, this->connection_id,
TNC_CONNECTION_STATE_HANDSHAKE);
}
- this->batch = pb_tnc_batch_create(this->is_server, batch_retry_type);
}
METHOD(tls_t, process, status_t,
@@ -375,8 +416,9 @@ METHOD(tls_t, process, status_t,
if (this->is_server && !this->connection_id)
{
this->connection_id = tnc->tnccs->create_connection(tnc->tnccs,
- TNCCS_2_0, (tnccs_t*)this, _send_msg,
- &this->request_handshake_retry, &this->recs);
+ TNCCS_2_0, (tnccs_t*)this, _send_msg,
+ &this->request_handshake_retry,
+ this->max_msg_len, &this->recs);
if (!this->connection_id)
{
return FAILED;
@@ -461,13 +503,7 @@ METHOD(tls_t, process, status_t,
case FAILED:
this->fatal_error = TRUE;
this->mutex->lock(this->mutex);
- if (this->batch)
- {
- DBG1(DBG_TNC, "cancelling PB-TNC %N batch",
- pb_tnc_batch_type_names, this->batch->get_type(this->batch));
- this->batch->destroy(this->batch);
- }
- this->batch = pb_tnc_batch_create(this->is_server, PB_BATCH_CLOSE);
+ change_batch_type(this, PB_BATCH_CLOSE);
this->mutex->unlock(this->mutex);
/* fall through to add error messages to outbound batch */
case VERIFY_ERROR:
@@ -475,7 +511,7 @@ METHOD(tls_t, process, status_t,
while (enumerator->enumerate(enumerator, &msg))
{
this->mutex->lock(this->mutex);
- this->batch->add_msg(this->batch, msg->get_ref(msg));
+ this->messages->insert_last(this->messages, msg->get_ref(msg));
this->mutex->unlock(this->mutex);
}
enumerator->destroy(enumerator);
@@ -508,10 +544,10 @@ static void check_and_build_recommendation(private_tnccs_20_t *this)
}
if (this->recs->have_recommendation(this->recs, &rec, &eval))
{
- this->batch = pb_tnc_batch_create(this->is_server, PB_BATCH_RESULT);
+ this->batch_type = PB_BATCH_RESULT;
msg = pb_assessment_result_msg_create(eval);
- this->batch->add_msg(this->batch, msg);
+ this->messages->insert_last(this->messages, msg);
/**
* Map IMV Action Recommendation codes to PB Access Recommendation codes
@@ -530,16 +566,15 @@ static void check_and_build_recommendation(private_tnccs_20_t *this)
pb_rec = PB_REC_ACCESS_DENIED;
}
msg = pb_access_recommendation_msg_create(pb_rec);
- this->batch->add_msg(this->batch, msg);
+ this->messages->insert_last(this->messages, msg);
enumerator = this->recs->create_reason_enumerator(this->recs);
while (enumerator->enumerate(enumerator, &id, &reason, &language))
{
msg = pb_reason_string_msg_create(reason, language);
- this->batch->add_msg(this->batch, msg);
+ this->messages->insert_last(this->messages, msg);
}
enumerator->destroy(enumerator);
- this->recs->clear_reasons(this->recs);
}
}
@@ -557,7 +592,8 @@ METHOD(tls_t, build, status_t,
this->connection_id = tnc->tnccs->create_connection(tnc->tnccs,
TNCCS_2_0, (tnccs_t*)this, _send_msg,
- &this->request_handshake_retry, NULL);
+ &this->request_handshake_retry,
+ this->max_msg_len, NULL);
if (!this->connection_id)
{
return FAILED;
@@ -568,8 +604,8 @@ METHOD(tls_t, build, status_t,
msg = pb_language_preference_msg_create(chunk_create(pref_lang,
strlen(pref_lang)));
this->mutex->lock(this->mutex);
- this->batch = pb_tnc_batch_create(this->is_server, PB_BATCH_CDATA);
- this->batch->add_msg(this->batch, msg);
+ this->batch_type = PB_BATCH_CDATA;
+ this->messages->insert_last(this->messages, msg);
this->mutex->unlock(this->mutex);
tnc->imcs->notify_connection_change(tnc->imcs, this->connection_id,
@@ -583,7 +619,7 @@ METHOD(tls_t, build, status_t,
state = this->state_machine->get_state(this->state_machine);
- if (this->is_server && this->fatal_error && state == PB_STATE_END)
+ if (this->fatal_error && state == PB_STATE_END)
{
DBG1(DBG_TNC, "a fatal PB-TNC error occurred, terminating connection");
return FAILED;
@@ -603,66 +639,98 @@ METHOD(tls_t, build, status_t,
this->request_handshake_retry = FALSE;
}
- if (!this->batch)
+ if (this->is_server && state == PB_STATE_SERVER_WORKING &&
+ this->recs->have_recommendation(this->recs, NULL, NULL))
{
- if (this->is_server)
+ check_and_build_recommendation(this);
+ }
+
+ if (this->batch_type == PB_BATCH_NONE)
+ {
+ if (this->is_server && state == PB_STATE_SERVER_WORKING)
{
- if (state == PB_STATE_SERVER_WORKING)
+ if (this->state_machine->get_empty_cdata(this->state_machine))
{
check_and_build_recommendation(this);
}
+ else
+ {
+ DBG2(DBG_TNC, "no recommendation available yet, "
+ "sending empty PB-TNC SDATA batch");
+ this->batch_type = PB_BATCH_SDATA;
+ }
}
else
- {
+ {
/**
- * if the DECIDED state has been reached and no CRETRY is under way
- * or if a CLOSE batch with error messages has been received,
+ * In the DECIDED state and if no CRETRY is under way,
* a PB-TNC client replies with an empty CLOSE batch.
*/
- if (state == PB_STATE_DECIDED || state == PB_STATE_END)
+ if (state == PB_STATE_DECIDED)
{
- this->batch = pb_tnc_batch_create(this->is_server, PB_BATCH_CLOSE);
+ this->batch_type = PB_BATCH_CLOSE;
}
}
}
- if (this->batch)
+ if (this->batch_type != PB_BATCH_NONE)
{
- pb_tnc_batch_type_t batch_type;
+ pb_tnc_batch_t *batch;
+ pb_tnc_msg_t *msg;
chunk_t data;
+ int msg_count;
+ enumerator_t *enumerator;
- batch_type = this->batch->get_type(this->batch);
-
- if (this->state_machine->send_batch(this->state_machine, batch_type))
+ if (this->state_machine->send_batch(this->state_machine, this->batch_type))
{
- this->batch->build(this->batch);
- data = this->batch->get_encoding(this->batch);
+ batch = pb_tnc_batch_create(this->is_server, this->batch_type,
+ min(this->max_batch_len, *buflen));
+
+ enumerator = this->messages->create_enumerator(this->messages);
+ while (enumerator->enumerate(enumerator, &msg))
+ {
+ if (batch->add_msg(batch, msg))
+ {
+ this->messages->remove_at(this->messages, enumerator);
+ }
+ else
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ batch->build(batch);
+ data = batch->get_encoding(batch);
DBG1(DBG_TNC, "sending PB-TNC %N batch (%d bytes) for Connection ID %u",
- pb_tnc_batch_type_names, batch_type, data.len,
+ pb_tnc_batch_type_names, this->batch_type, data.len,
this->connection_id);
DBG3(DBG_TNC, "%B", &data);
- *msglen = data.len;
- if (data.len > *buflen)
+ *buflen = data.len;
+ *msglen = 0;
+ memcpy(buf, data.ptr, *buflen);
+ batch->destroy(batch);
+
+ msg_count = this->messages->get_count(this->messages);
+ if (msg_count)
{
- DBG1(DBG_TNC, "fragmentation of PB-TNC batch not supported yet");
+ DBG2(DBG_TNC, "queued %d PB-TNC message%s for next %N batch",
+ msg_count, (msg_count == 1) ? "" : "s",
+ pb_tnc_batch_type_names, this->batch_type);
}
else
{
- *buflen = data.len;
+ this->batch_type = PB_BATCH_NONE;
}
- memcpy(buf, data.ptr, *buflen);
+
status = ALREADY_DONE;
}
else
{
- DBG1(DBG_TNC, "cancelling unexpected PB-TNC batch type: %N",
- pb_tnc_batch_type_names, batch_type);
+ change_batch_type(this, PB_BATCH_NONE);
status = INVALID_STATE;
}
-
- this->batch->destroy(this->batch);
- this->batch = NULL;
}
else
{
@@ -715,7 +783,8 @@ METHOD(tls_t, destroy, void,
this->is_server);
this->state_machine->destroy(this->state_machine);
this->mutex->destroy(this->mutex);
- DESTROY_IF(this->batch);
+ this->messages->destroy_offset(this->messages,
+ offsetof(pb_tnc_msg_t, destroy));
free(this);
}
@@ -739,6 +808,13 @@ tls_t *tnccs_20_create(bool is_server)
.is_server = is_server,
.state_machine = pb_tnc_state_machine_create(is_server),
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ .messages = linked_list_create(),
+ .max_batch_len = lib->settings->get_int(lib->settings,
+ "%s.plugins.tnccs-20.max_batch_size", 65522,
+ charon->name),
+ .max_msg_len = lib->settings->get_int(lib->settings,
+ "%s.plugins.tnccs-20.max_message_size", 65490,
+ charon->name),
);
return &this->public;
diff --git a/src/libcharon/plugins/tnccs_dynamic/Makefile.in b/src/libcharon/plugins/tnccs_dynamic/Makefile.in
index ab24d32d3..f08d00dab 100644
--- a/src/libcharon/plugins/tnccs_dynamic/Makefile.in
+++ b/src/libcharon/plugins/tnccs_dynamic/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -88,7 +89,7 @@ libstrongswan_tnccs_dynamic_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_tnccs_dynamic_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_tnccs_dynamic_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -114,6 +115,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -208,11 +210,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -229,11 +234,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -249,6 +255,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -258,7 +265,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/uci/Makefile.in b/src/libcharon/plugins/uci/Makefile.in
index dd001e0bd..da9310aa0 100644
--- a/src/libcharon/plugins/uci/Makefile.in
+++ b/src/libcharon/plugins/uci/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -83,7 +84,7 @@ libstrongswan_uci_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(libstrongswan_uci_la_LDFLAGS) $(LDFLAGS) -o $@
@MONOLITHIC_FALSE@am_libstrongswan_uci_la_rpath = -rpath $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_uci_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -109,6 +110,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -203,11 +205,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -224,11 +229,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -244,6 +250,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -253,7 +260,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/uci/uci_config.c b/src/libcharon/plugins/uci/uci_config.c
index 2f5e59b89..1201f568e 100644
--- a/src/libcharon/plugins/uci/uci_config.c
+++ b/src/libcharon/plugins/uci/uci_config.c
@@ -169,14 +169,15 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool,
{
DESTROY_IF(this->peer_cfg);
ike_cfg = ike_cfg_create(FALSE, FALSE,
- local_addr, IKEV2_UDP_PORT, remote_addr, IKEV2_UDP_PORT);
+ local_addr, FALSE, charon->socket->get_port(charon->socket, FALSE),
+ remote_addr, FALSE, IKEV2_UDP_PORT);
ike_cfg->add_proposal(ike_cfg, create_proposal(ike_proposal, PROTO_IKE));
this->peer_cfg = peer_cfg_create(
- name, 2, ike_cfg, CERT_SEND_IF_ASKED, UNIQUE_NO,
+ name, IKEV2, ike_cfg, CERT_SEND_IF_ASKED, UNIQUE_NO,
1, create_rekey(ike_rekey), 0, /* keytries, rekey, reauth */
1800, 900, /* jitter, overtime */
- TRUE, 60, /* mobike, dpddelay */
- NULL, NULL, /* vip, pool */
+ TRUE, FALSE, /* mobike, aggressive */
+ 60, 0, /* DPD delay, timeout */
FALSE, NULL, NULL); /* mediation, med by, peer id */
auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
@@ -264,8 +265,9 @@ METHOD(enumerator_t, ike_enumerator_enumerate, bool,
&local_addr, &remote_addr, &ike_proposal))
{
DESTROY_IF(this->ike_cfg);
- this->ike_cfg = ike_cfg_create(FALSE, FALSE, local_addr, IKEV2_UDP_PORT,
- remote_addr, IKEV2_UDP_PORT);
+ this->ike_cfg = ike_cfg_create(FALSE, FALSE,
+ local_addr, FALSE, charon->socket->get_port(charon->socket, FALSE),
+ remote_addr, FALSE, IKEV2_UDP_PORT);
this->ike_cfg->add_proposal(this->ike_cfg,
create_proposal(ike_proposal, PROTO_IKE));
diff --git a/src/libcharon/plugins/uci/uci_control.c b/src/libcharon/plugins/uci/uci_control.c
index af4a6a711..53221b786 100644
--- a/src/libcharon/plugins/uci/uci_control.c
+++ b/src/libcharon/plugins/uci/uci_control.c
@@ -42,11 +42,6 @@ struct private_uci_control_t {
* Public part
*/
uci_control_t public;
-
- /**
- * Job
- */
- callback_job_t *job;
};
/**
@@ -84,7 +79,7 @@ static void status(private_uci_control_t *this, char *name)
FILE *out = NULL;
configs = charon->backends->create_peer_cfg_enumerator(charon->backends,
- NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL, IKE_ANY);
while (configs->enumerate(configs, &peer_cfg))
{
if (name && !streq(name, peer_cfg->get_name(peer_cfg)))
@@ -269,7 +264,6 @@ static job_requeue_t receive(private_uci_control_t *this)
METHOD(uci_control_t, destroy, void,
private_uci_control_t *this)
{
- this->job->cancel(this->job);
unlink(FIFO_FILE);
free(this);
}
@@ -295,9 +289,10 @@ uci_control_t *uci_control_create()
}
else
{
- this->job = callback_job_create_with_prio((callback_job_cb_t)receive,
- this, NULL, NULL, JOB_PRIO_CRITICAL);
- lib->processor->queue_job(lib->processor, (job_t*)this->job);
+ lib->processor->queue_job(lib->processor,
+ (job_t*)callback_job_create_with_prio((callback_job_cb_t)receive,
+ this, NULL, (callback_job_cancel_t)return_false,
+ JOB_PRIO_CRITICAL));
}
return &this->public;
}
diff --git a/src/libcharon/plugins/unit_tester/Makefile.in b/src/libcharon/plugins/unit_tester/Makefile.in
index 106c9b1fe..9d936a273 100644
--- a/src/libcharon/plugins/unit_tester/Makefile.in
+++ b/src/libcharon/plugins/unit_tester/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -89,7 +90,7 @@ libstrongswan_unit_tester_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_unit_tester_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_unit_tester_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -115,6 +116,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -209,11 +211,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -230,11 +235,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -250,6 +256,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -259,7 +266,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/unit_tester/tests/test_cert.c b/src/libcharon/plugins/unit_tester/tests/test_cert.c
index 342194a4c..f4410a688 100644
--- a/src/libcharon/plugins/unit_tester/tests/test_cert.c
+++ b/src/libcharon/plugins/unit_tester/tests/test_cert.c
@@ -60,7 +60,7 @@ bool test_cert_x509()
{
return FALSE;
}
- if (!parsed->issued_by(parsed, ca_cert))
+ if (!parsed->issued_by(parsed, ca_cert, NULL))
{
return FALSE;
}
@@ -90,7 +90,7 @@ bool test_cert_x509()
{
return FALSE;
}
- if (!parsed->issued_by(parsed, ca_cert))
+ if (!parsed->issued_by(parsed, ca_cert, NULL))
{
return FALSE;
}
diff --git a/src/libcharon/plugins/unit_tester/tests/test_pool.c b/src/libcharon/plugins/unit_tester/tests/test_pool.c
index a68246fff..f36953f3a 100644
--- a/src/libcharon/plugins/unit_tester/tests/test_pool.c
+++ b/src/libcharon/plugins/unit_tester/tests/test_pool.c
@@ -27,6 +27,7 @@ static void* testing(void *thread)
int i;
host_t *addr[ALLOCS];
identification_t *id[ALLOCS];
+ linked_list_t *pools;
/* prepare identities */
for (i = 0; i < ALLOCS; i++)
@@ -37,13 +38,17 @@ static void* testing(void *thread)
id[i] = identification_create_from_string(buf);
}
+ pools = linked_list_create();
+ pools->insert_last(pools, "test");
+
/* allocate addresses */
for (i = 0; i < ALLOCS; i++)
{
addr[i] = hydra->attributes->acquire_address(hydra->attributes,
- "test", id[i], NULL);
+ pools, id[i], NULL);
if (!addr[i])
{
+ pools->destroy(pools);
return (void*)FALSE;
}
}
@@ -52,9 +57,11 @@ static void* testing(void *thread)
for (i = 0; i < ALLOCS; i++)
{
hydra->attributes->release_address(hydra->attributes,
- "test", addr[i], id[i]);
+ pools, addr[i], id[i]);
}
+ pools->destroy(pools);
+
/* cleanup */
for (i = 0; i < ALLOCS; i++)
{
diff --git a/src/libcharon/plugins/unity/Makefile.am b/src/libcharon/plugins/unity/Makefile.am
new file mode 100644
index 000000000..b23143fd6
--- /dev/null
+++ b/src/libcharon/plugins/unity/Makefile.am
@@ -0,0 +1,19 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-unity.la
+else
+plugin_LTLIBRARIES = libstrongswan-unity.la
+endif
+
+libstrongswan_unity_la_SOURCES = \
+ unity_plugin.h unity_plugin.c \
+ unity_handler.h unity_handler.c \
+ unity_narrow.h unity_narrow.c \
+ unity_provider.h unity_provider.c
+
+libstrongswan_unity_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/unity/Makefile.in b/src/libcharon/plugins/unity/Makefile.in
new file mode 100644
index 000000000..3b74530b3
--- /dev/null
+++ b/src/libcharon/plugins/unity/Makefile.in
@@ -0,0 +1,624 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/libcharon/plugins/unity
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
+ $(top_srcdir)/m4/config/ltoptions.m4 \
+ $(top_srcdir)/m4/config/ltsugar.m4 \
+ $(top_srcdir)/m4/config/ltversion.m4 \
+ $(top_srcdir)/m4/config/lt~obsolete.m4 \
+ $(top_srcdir)/m4/macros/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/m4/macros/add-plugin.m4 \
+ $(top_srcdir)/configure.in
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_unity_la_LIBADD =
+am_libstrongswan_unity_la_OBJECTS = unity_plugin.lo unity_handler.lo \
+ unity_narrow.lo unity_provider.lo
+libstrongswan_unity_la_OBJECTS = $(am_libstrongswan_unity_la_OBJECTS)
+libstrongswan_unity_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_unity_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_unity_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_unity_la_rpath =
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_unity_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_unity_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BFDLIB = @BFDLIB@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+attest_plugins = @attest_plugins@
+axis2c_CFLAGS = @axis2c_CFLAGS@
+axis2c_LIBS = @axis2c_LIBS@
+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@
+datadir = @datadir@
+datarootdir = @datarootdir@
+dbusservicedir = @dbusservicedir@
+dev_headers = @dev_headers@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+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@
+libdir = @libdir@
+libexecdir = @libexecdir@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+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@
+openac_plugins = @openac_plugins@
+p_plugins = @p_plugins@
+pcsclite_CFLAGS = @pcsclite_CFLAGS@
+pcsclite_LIBS = @pcsclite_LIBS@
+pdfdir = @pdfdir@
+piddir = @piddir@
+pki_plugins = @pki_plugins@
+plugindir = @plugindir@
+pool_plugins = @pool_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+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@
+sysconfdir = @sysconfdir@
+systemdsystemunitdir = @systemdsystemunitdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-unity.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-unity.la
+libstrongswan_unity_la_SOURCES = \
+ unity_plugin.h unity_plugin.c \
+ unity_handler.h unity_handler.c \
+ unity_narrow.h unity_narrow.c \
+ unity_provider.h unity_provider.c
+
+libstrongswan_unity_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/unity/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/unity/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-unity.la: $(libstrongswan_unity_la_OBJECTS) $(libstrongswan_unity_la_DEPENDENCIES)
+ $(libstrongswan_unity_la_LINK) $(am_libstrongswan_unity_la_rpath) $(libstrongswan_unity_la_OBJECTS) $(libstrongswan_unity_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unity_handler.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unity_narrow.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unity_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unity_provider.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/unity/unity_handler.c b/src/libcharon/plugins/unity/unity_handler.c
new file mode 100644
index 000000000..b2aeba605
--- /dev/null
+++ b/src/libcharon/plugins/unity/unity_handler.c
@@ -0,0 +1,433 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 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 "unity_handler.h"
+
+#include <daemon.h>
+#include <threading/mutex.h>
+#include <utils/linked_list.h>
+#include <processing/jobs/callback_job.h>
+
+typedef struct private_unity_handler_t private_unity_handler_t;
+
+/**
+ * Private data of an unity_handler_t object.
+ */
+struct private_unity_handler_t {
+
+ /**
+ * Public unity_handler_t interface.
+ */
+ unity_handler_t public;
+
+ /**
+ * List of subnets to include, as entry_t
+ */
+ linked_list_t *include;
+
+ /**
+ * Mutex for concurrent access to lists
+ */
+ mutex_t *mutex;
+};
+
+/**
+ * Traffic selector entry for networks to include under a given IKE_SA
+ */
+typedef struct {
+ /** associated IKE_SA, unique ID */
+ u_int32_t sa;
+ /** traffic selector to include/exclude */
+ traffic_selector_t *ts;
+} entry_t;
+
+/**
+ * Clean up an entry
+ */
+static void entry_destroy(entry_t *this)
+{
+ this->ts->destroy(this->ts);
+ free(this);
+}
+
+/**
+ * Create a traffic selector from a unity subnet definition
+ */
+static traffic_selector_t *create_ts(chunk_t subnet)
+{
+ chunk_t net, mask;
+ int i;
+
+ if (subnet.len != 8)
+ {
+ return NULL;
+ }
+ net = chunk_create(subnet.ptr, 4);
+ mask = chunk_clonea(chunk_skip(subnet, 4));
+ for (i = 0; i < net.len; i++)
+ {
+ mask.ptr[i] = (mask.ptr[i] ^ 0xFF) | net.ptr[i];
+ }
+ return traffic_selector_create_from_bytes(0, TS_IPV4_ADDR_RANGE,
+ net, 0, mask, 65535);
+}
+
+/**
+ * Store a subnet to include in tunnels under this IKE_SA
+ */
+static bool add_include(private_unity_handler_t *this, chunk_t subnet)
+{
+ traffic_selector_t *ts;
+ ike_sa_t *ike_sa;
+ entry_t *entry;
+
+ ike_sa = charon->bus->get_sa(charon->bus);
+ if (!ike_sa)
+ {
+ return FALSE;
+ }
+ ts = create_ts(subnet);
+ if (!ts)
+ {
+ return FALSE;
+ }
+ INIT(entry,
+ .sa = ike_sa->get_unique_id(ike_sa),
+ .ts = ts,
+ );
+
+ this->mutex->lock(this->mutex);
+ this->include->insert_last(this->include, entry);
+ this->mutex->unlock(this->mutex);
+ return TRUE;
+}
+
+/**
+ * Rempve a subnet from the inclusion list for this IKE_SA
+ */
+static bool remove_include(private_unity_handler_t *this, chunk_t subnet)
+{
+ enumerator_t *enumerator;
+ traffic_selector_t *ts;
+ ike_sa_t *ike_sa;
+ entry_t *entry;
+
+ ike_sa = charon->bus->get_sa(charon->bus);
+ if (!ike_sa)
+ {
+ return FALSE;
+ }
+ ts = create_ts(subnet);
+ if (!ts)
+ {
+ return FALSE;
+ }
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->include->create_enumerator(this->include);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->sa == ike_sa->get_unique_id(ike_sa) &&
+ ts->equals(ts, entry->ts))
+ {
+ this->include->remove_at(this->include, enumerator);
+ entry_destroy(entry);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+ ts->destroy(ts);
+ return TRUE;
+}
+
+/**
+ * Create a unique shunt name for a bypass policy
+ */
+static void create_shunt_name(ike_sa_t *ike_sa, traffic_selector_t *ts,
+ char *buf, size_t len)
+{
+ snprintf(buf, len, "Unity (%s[%u]: %R)", ike_sa->get_name(ike_sa),
+ ike_sa->get_unique_id(ike_sa), ts);
+}
+
+/**
+ * Install entry as a shunt policy
+ */
+static job_requeue_t add_exclude_async(entry_t *entry)
+{
+ enumerator_t *enumerator;
+ child_cfg_t *child_cfg;
+ lifetime_cfg_t lft = {};
+ ike_sa_t *ike_sa;
+ char name[128];
+ host_t *host;
+ bool has_vip = FALSE;
+
+ ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
+ entry->sa, FALSE);
+ if (ike_sa)
+ {
+ create_shunt_name(ike_sa, entry->ts, name, sizeof(name));
+
+ child_cfg = child_cfg_create(name, &lft, NULL, TRUE, MODE_PASS,
+ ACTION_NONE, ACTION_NONE, ACTION_NONE,
+ FALSE, 0, 0, NULL, NULL, FALSE);
+ child_cfg->add_traffic_selector(child_cfg, FALSE,
+ entry->ts->clone(entry->ts));
+ enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, TRUE);
+ while (enumerator->enumerate(enumerator, &host))
+ {
+ has_vip = TRUE;
+ child_cfg->add_traffic_selector(child_cfg, TRUE,
+ traffic_selector_create_from_subnet(host->clone(host), 32, 0, 0));
+ }
+ enumerator->destroy(enumerator);
+
+ if (!has_vip)
+ {
+ host = ike_sa->get_my_host(ike_sa);
+ child_cfg->add_traffic_selector(child_cfg, TRUE,
+ traffic_selector_create_from_subnet(host->clone(host), 32, 0, 0));
+ }
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+
+ charon->shunts->install(charon->shunts, child_cfg);
+ child_cfg->destroy(child_cfg);
+
+ DBG1(DBG_IKE, "installed %N bypass policy for %R",
+ configuration_attribute_type_names, UNITY_LOCAL_LAN, entry->ts);
+ }
+ return JOB_REQUEUE_NONE;
+}
+
+/**
+ * Add a bypass policy for a given subnet
+ */
+static bool add_exclude(private_unity_handler_t *this, chunk_t subnet)
+{
+ traffic_selector_t *ts;
+ ike_sa_t *ike_sa;
+ entry_t *entry;
+
+ ike_sa = charon->bus->get_sa(charon->bus);
+ if (!ike_sa)
+ {
+ return FALSE;
+ }
+ ts = create_ts(subnet);
+ if (!ts)
+ {
+ return FALSE;
+ }
+ INIT(entry,
+ .sa = ike_sa->get_unique_id(ike_sa),
+ .ts = ts,
+ );
+
+ /* we can't install the shunt policy yet, as we don't know the virtual IP.
+ * Defer installation using an async callback. */
+ lib->processor->queue_job(lib->processor, (job_t*)
+ callback_job_create((void*)add_exclude_async, entry,
+ (void*)entry_destroy, NULL));
+ return TRUE;
+}
+
+/**
+ * Remove a bypass policy for a given subnet
+ */
+static bool remove_exclude(private_unity_handler_t *this, chunk_t subnet)
+{
+ traffic_selector_t *ts;
+ ike_sa_t *ike_sa;
+ char name[128];
+
+ ike_sa = charon->bus->get_sa(charon->bus);
+ if (!ike_sa)
+ {
+ return FALSE;
+ }
+ ts = create_ts(subnet);
+ if (!ts)
+ {
+ return FALSE;
+ }
+ create_shunt_name(ike_sa, ts, name, sizeof(name));
+ DBG1(DBG_IKE, "uninstalling %N bypass policy for %R",
+ configuration_attribute_type_names, UNITY_LOCAL_LAN, ts);
+ ts->destroy(ts);
+ return charon->shunts->uninstall(charon->shunts, name);
+}
+
+METHOD(attribute_handler_t, handle, bool,
+ private_unity_handler_t *this, identification_t *id,
+ configuration_attribute_type_t type, chunk_t data)
+{
+ switch (type)
+ {
+ case UNITY_SPLIT_INCLUDE:
+ return add_include(this, data);
+ case UNITY_LOCAL_LAN:
+ return add_exclude(this, data);
+ default:
+ return FALSE;
+ }
+}
+
+METHOD(attribute_handler_t, release, void,
+ private_unity_handler_t *this, identification_t *server,
+ configuration_attribute_type_t type, chunk_t data)
+{
+ switch (type)
+ {
+ case UNITY_SPLIT_INCLUDE:
+ remove_include(this, data);
+ break;
+ case UNITY_LOCAL_LAN:
+ remove_exclude(this, data);
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * Configuration attributes to request
+ */
+static configuration_attribute_type_t attributes[] = {
+ UNITY_SPLIT_INCLUDE,
+ UNITY_LOCAL_LAN,
+};
+
+/**
+ * Attribute enumerator implementation
+ */
+typedef struct {
+ /** implements enumerator_t */
+ enumerator_t public;
+ /** position in attributes[] */
+ int i;
+} attribute_enumerator_t;
+
+METHOD(enumerator_t, enumerate_attributes, bool,
+ attribute_enumerator_t *this, configuration_attribute_type_t *type,
+ chunk_t *data)
+{
+ if (this->i < countof(attributes))
+ {
+ *type = attributes[this->i++];
+ *data = chunk_empty;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t *,
+ unity_handler_t *this, identification_t *id, linked_list_t *vips)
+{
+ attribute_enumerator_t *enumerator;
+ ike_sa_t *ike_sa;
+
+ ike_sa = charon->bus->get_sa(charon->bus);
+ if (!ike_sa || ike_sa->get_version(ike_sa) != IKEV1 ||
+ !ike_sa->supports_extension(ike_sa, EXT_CISCO_UNITY))
+ {
+ return enumerator_create_empty();
+ }
+ INIT(enumerator,
+ .public = {
+ .enumerate = (void*)_enumerate_attributes,
+ .destroy = (void*)free,
+ },
+ );
+ return &enumerator->public;
+}
+
+typedef struct {
+ /** mutex to unlock */
+ mutex_t *mutex;
+ /** IKE_SA ID to filter for */
+ u_int32_t id;
+} include_filter_t;
+
+/**
+ * Include enumerator filter function
+ */
+static bool include_filter(include_filter_t *data,
+ entry_t **entry, traffic_selector_t **ts)
+{
+ if ((*entry)->sa == data->id)
+ {
+ *ts = (*entry)->ts;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Destroy include filter data, unlock mutex
+ */
+static void destroy_filter(include_filter_t *data)
+{
+ data->mutex->unlock(data->mutex);
+ free(data);
+}
+
+METHOD(unity_handler_t, create_include_enumerator, enumerator_t*,
+ private_unity_handler_t *this, u_int32_t id)
+{
+ include_filter_t *data;
+
+ INIT(data,
+ .mutex = this->mutex,
+ .id = id,
+ );
+ data->mutex->lock(data->mutex);
+ return enumerator_create_filter(
+ this->include->create_enumerator(this->include),
+ (void*)include_filter, data, (void*)destroy_filter);
+}
+
+METHOD(unity_handler_t, destroy, void,
+ private_unity_handler_t *this)
+{
+ this->include->destroy(this->include);
+ this->mutex->destroy(this->mutex);
+ free(this);
+}
+
+/**
+ * See header
+ */
+unity_handler_t *unity_handler_create()
+{
+ private_unity_handler_t *this;
+
+ INIT(this,
+ .public = {
+ .handler = {
+ .handle = _handle,
+ .release = _release,
+ .create_attribute_enumerator = _create_attribute_enumerator,
+ },
+ .create_include_enumerator = _create_include_enumerator,
+ .destroy = _destroy,
+ },
+ .include = linked_list_create(),
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/unity/unity_handler.h b/src/libcharon/plugins/unity/unity_handler.h
new file mode 100644
index 000000000..8656fd372
--- /dev/null
+++ b/src/libcharon/plugins/unity/unity_handler.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 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 unity_handler unity_handler
+ * @{ @ingroup unity
+ */
+
+#ifndef UNITY_HANDLER_H_
+#define UNITY_HANDLER_H_
+
+#include <attributes/attribute_handler.h>
+
+typedef struct unity_handler_t unity_handler_t;
+
+/**
+ * Cisco Unity attribute handling.
+ */
+struct unity_handler_t {
+
+ /**
+ * Implements attribute_handler_t.
+ */
+ attribute_handler_t handler;
+
+ /**
+ * Create an enumerator over Split-Include attributes received for an IKE_SA.
+ *
+ * @param id IKE_SA unique ID to get Split-Includes for
+ * @return enumerator over traffic_selector_t*
+ */
+ enumerator_t* (*create_include_enumerator)(unity_handler_t *this,
+ u_int32_t id);
+
+ /**
+ * Destroy a unity_handler_t.
+ */
+ void (*destroy)(unity_handler_t *this);
+};
+
+/**
+ * Create a unity_handler instance.
+ */
+unity_handler_t *unity_handler_create();
+
+#endif /** UNITY_HANDLER_H_ @}*/
diff --git a/src/libcharon/plugins/unity/unity_narrow.c b/src/libcharon/plugins/unity/unity_narrow.c
new file mode 100644
index 000000000..56de0028f
--- /dev/null
+++ b/src/libcharon/plugins/unity/unity_narrow.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 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 "unity_narrow.h"
+
+#include <daemon.h>
+
+typedef struct private_unity_narrow_t private_unity_narrow_t;
+
+/**
+ * Private data of an unity_narrow_t object.
+ */
+struct private_unity_narrow_t {
+
+ /**
+ * Public unity_narrow_t interface.
+ */
+ unity_narrow_t public;
+
+ /**
+ * Unity attribute handler
+ */
+ unity_handler_t *handler;
+};
+
+/**
+ * Narrow TS as initiator to Unity Split-Include/Local-LAN
+ */
+static void narrow_initiator(private_unity_narrow_t *this, ike_sa_t *ike_sa,
+ child_cfg_t *cfg, linked_list_t *remote)
+{
+ traffic_selector_t *current, *orig = NULL;
+ linked_list_t *received, *selected;
+ enumerator_t *enumerator;
+
+ enumerator = this->handler->create_include_enumerator(this->handler,
+ ike_sa->get_unique_id(ike_sa));
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (orig == NULL)
+ { /* got one, replace original TS */
+ if (remote->remove_first(remote, (void**)&orig) != SUCCESS)
+ {
+ break;
+ }
+ }
+ /* narrow received Unity TS with the child configuration */
+ received = linked_list_create();
+ received->insert_last(received, current);
+ selected = cfg->get_traffic_selectors(cfg, FALSE, received, NULL);
+ while (selected->remove_first(selected, (void**)&current) == SUCCESS)
+ {
+ remote->insert_last(remote, current);
+ }
+ selected->destroy(selected);
+ received->destroy(received);
+ }
+ enumerator->destroy(enumerator);
+ if (orig)
+ {
+ DBG1(DBG_CFG, "narrowed CHILD_SA to %N %#R",
+ configuration_attribute_type_names,
+ UNITY_SPLIT_INCLUDE, remote);
+ orig->destroy(orig);
+ }
+}
+
+/**
+ * As initiator, bump up TS to 0.0.0.0/0 for on-the-wire bits
+ */
+static void narrow_initiator_pre(linked_list_t *list)
+{
+ traffic_selector_t *ts;
+
+ while (list->remove_first(list, (void**)&ts) == SUCCESS)
+ {
+ ts->destroy(ts);
+ }
+ ts = traffic_selector_create_from_string(0, TS_IPV4_ADDR_RANGE,
+ "0.0.0.0", 0,
+ "255.255.255.255", 65535);
+ if (ts)
+ {
+ list->insert_last(list, ts);
+ }
+}
+
+/**
+ * As responder, narrow down TS to configuration for installation
+ */
+static void narrow_responder_post(child_cfg_t *child_cfg, linked_list_t *local)
+{
+ traffic_selector_t *ts;
+ linked_list_t *configured;
+
+ while (local->remove_first(local, (void**)&ts) == SUCCESS)
+ {
+ ts->destroy(ts);
+ }
+ configured = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL);
+
+ while (configured->remove_first(configured, (void**)&ts) == SUCCESS)
+ {
+ local->insert_last(local, ts);
+ }
+ configured->destroy(configured);
+}
+
+METHOD(listener_t, narrow, bool,
+ private_unity_narrow_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
+ narrow_hook_t type, linked_list_t *local, linked_list_t *remote)
+{
+ if (ike_sa->get_version(ike_sa) == IKEV1 &&
+ ike_sa->supports_extension(ike_sa, EXT_CISCO_UNITY))
+ {
+ switch (type)
+ {
+ case NARROW_INITIATOR_PRE_AUTH:
+ narrow_initiator_pre(remote);
+ break;
+ case NARROW_INITIATOR_POST_AUTH:
+ narrow_initiator(this, ike_sa,
+ child_sa->get_config(child_sa), remote);
+ break;
+ case NARROW_RESPONDER_POST:
+ narrow_responder_post(child_sa->get_config(child_sa), local);
+ break;
+ default:
+ break;
+ }
+ }
+ return TRUE;
+}
+
+METHOD(unity_narrow_t, destroy, void,
+ private_unity_narrow_t *this)
+{
+ free(this);
+}
+
+/**
+ * See header
+ */
+unity_narrow_t *unity_narrow_create(unity_handler_t *handler)
+{
+ private_unity_narrow_t *this;
+
+ INIT(this,
+ .public = {
+ .listener = {
+ .narrow = _narrow,
+ },
+ .destroy = _destroy,
+ },
+ .handler = handler,
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/unity/unity_narrow.h b/src/libcharon/plugins/unity/unity_narrow.h
new file mode 100644
index 000000000..5e0968518
--- /dev/null
+++ b/src/libcharon/plugins/unity/unity_narrow.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 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 unity_narrow unity_narrow
+ * @{ @ingroup unity
+ */
+
+#ifndef UNITY_NARROW_H_
+#define UNITY_NARROW_H_
+
+#include <bus/listeners/listener.h>
+
+#include "unity_handler.h"
+
+typedef struct unity_narrow_t unity_narrow_t;
+
+/**
+ * Listener that narrows Quick Modes to the Unity Split-Include subnets.
+ */
+struct unity_narrow_t {
+
+ /**
+ * Implements listener_t.
+ */
+ listener_t listener;
+
+ /**
+ * Destroy a unity_narrow_t.
+ */
+ void (*destroy)(unity_narrow_t *this);
+};
+
+/**
+ * Create a unity_narrow instance.
+ */
+unity_narrow_t *unity_narrow_create(unity_handler_t *handler);
+
+#endif /** UNITY_NARROW_H_ @}*/
diff --git a/src/libcharon/plugins/unity/unity_plugin.c b/src/libcharon/plugins/unity/unity_plugin.c
new file mode 100644
index 000000000..9e21bd9ed
--- /dev/null
+++ b/src/libcharon/plugins/unity/unity_plugin.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 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 "unity_plugin.h"
+#include "unity_handler.h"
+#include "unity_narrow.h"
+#include "unity_provider.h"
+
+#include <daemon.h>
+#include <hydra.h>
+
+typedef struct private_unity_plugin_t private_unity_plugin_t;
+
+/**
+ * private data of unity_plugin
+ */
+struct private_unity_plugin_t {
+
+ /**
+ * public functions
+ */
+ unity_plugin_t public;
+
+ /**
+ * Handler for UNITY configuration attributes
+ */
+ unity_handler_t *handler;
+
+ /**
+ * Responder Unity configuration attribute provider
+ */
+ unity_provider_t *provider;
+
+ /**
+ * Traffic selector narrower, for Unity Split-Includes
+ */
+ unity_narrow_t *narrower;
+};
+
+METHOD(plugin_t, get_name, char*,
+ private_unity_plugin_t *this)
+{
+ return "unity";
+}
+
+METHOD(plugin_t, destroy, void,
+ private_unity_plugin_t *this)
+{
+ charon->bus->remove_listener(charon->bus, &this->narrower->listener);
+ this->narrower->destroy(this->narrower);
+ hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler);
+ hydra->attributes->remove_provider(hydra->attributes,
+ &this->provider->provider);
+ this->handler->destroy(this->handler);
+ this->provider->destroy(this->provider);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *unity_plugin_create()
+{
+ private_unity_plugin_t *this;
+
+ INIT(this,
+ .public = {
+ .plugin = {
+ .get_name = _get_name,
+ .reload = (void*)return_false,
+ .destroy = _destroy,
+ },
+ },
+ .handler = unity_handler_create(),
+ .provider = unity_provider_create(),
+ );
+ hydra->attributes->add_handler(hydra->attributes, &this->handler->handler);
+ hydra->attributes->add_provider(hydra->attributes, &this->provider->provider);
+
+ this->narrower = unity_narrow_create(this->handler),
+ charon->bus->add_listener(charon->bus, &this->narrower->listener);
+
+ return &this->public.plugin;
+}
diff --git a/src/libcharon/plugins/unity/unity_plugin.h b/src/libcharon/plugins/unity/unity_plugin.h
new file mode 100644
index 000000000..0d407b561
--- /dev/null
+++ b/src/libcharon/plugins/unity/unity_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 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 unity unity
+ * @ingroup cplugins
+ *
+ * @defgroup unity_plugin unity_plugin
+ * @{ @ingroup unity
+ */
+
+#ifndef UNITY_PLUGIN_H_
+#define UNITY_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct unity_plugin_t unity_plugin_t;
+
+/**
+ * IKEv1 Cisco Unity extension support.
+ */
+struct unity_plugin_t {
+
+ /**
+ * Implements plugin_t. interface.
+ */
+ plugin_t plugin;
+};
+
+#endif /** UNITY_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/unity/unity_provider.c b/src/libcharon/plugins/unity/unity_provider.c
new file mode 100644
index 000000000..c7feb090c
--- /dev/null
+++ b/src/libcharon/plugins/unity/unity_provider.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 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 "unity_provider.h"
+
+#include <daemon.h>
+
+typedef struct private_unity_provider_t private_unity_provider_t;
+
+/**
+ * Private data of an unity_provider_t object.
+ */
+struct private_unity_provider_t {
+
+ /**
+ * Public unity_provider_t interface.
+ */
+ unity_provider_t public;
+};
+
+/**
+ * Attribute enumerator for traffic selector list
+ */
+typedef struct {
+ /** Implements enumerator_t */
+ enumerator_t public;
+ /** list of traffic selectors to enumerate */
+ linked_list_t *list;
+ /** currently enumerating subnet */
+ u_char subnet[4];
+ /** currently enumerating subnet mask */
+ u_char mask[4];
+} attribute_enumerator_t;
+
+METHOD(enumerator_t, attribute_enumerate, bool,
+ attribute_enumerator_t *this, configuration_attribute_type_t *type,
+ chunk_t *attr)
+{
+ traffic_selector_t *ts;
+ u_int8_t i, mask;
+ host_t *net;
+
+ while (TRUE)
+ {
+ if (this->list->remove_first(this->list, (void**)&ts) != SUCCESS)
+ {
+ return FALSE;
+ }
+ if (ts->get_type(ts) == TS_IPV4_ADDR_RANGE &&
+ ts->to_subnet(ts, &net, &mask))
+ {
+ ts->destroy(ts);
+ break;
+ }
+ ts->destroy(ts);
+ }
+
+ memset(this->mask, 0, sizeof(this->mask));
+ for (i = 0; i < sizeof(this->mask); i++)
+ {
+ if (mask < 8)
+ {
+ this->mask[i] = 0xFF << (8 - mask);
+ break;
+ }
+ this->mask[i] = 0xFF;
+ mask -= 8;
+ }
+ memcpy(this->subnet, net->get_address(net).ptr, sizeof(this->subnet));
+ net->destroy(net);
+
+ *type = UNITY_SPLIT_INCLUDE;
+ *attr = chunk_create(this->subnet, sizeof(this->subnet) + sizeof(this->mask));
+
+ return TRUE;
+}
+
+METHOD(enumerator_t, attribute_destroy, void,
+ attribute_enumerator_t *this)
+{
+ this->list->destroy_offset(this->list, offsetof(traffic_selector_t, destroy));
+ free(this);
+}
+
+METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
+ private_unity_provider_t *this, linked_list_t *pools, identification_t *id,
+ linked_list_t *vips)
+{
+ attribute_enumerator_t *attr_enum;
+ enumerator_t *enumerator;
+ linked_list_t *list, *current;
+ traffic_selector_t *ts;
+ ike_sa_t *ike_sa;
+ peer_cfg_t *peer_cfg;
+ child_cfg_t *child_cfg;
+
+ ike_sa = charon->bus->get_sa(charon->bus);
+ if (!ike_sa || ike_sa->get_version(ike_sa) != IKEV1 ||
+ !ike_sa->supports_extension(ike_sa, EXT_CISCO_UNITY) ||
+ !vips->get_count(vips))
+ {
+ return NULL;
+ }
+
+ list = linked_list_create();
+ peer_cfg = ike_sa->get_peer_cfg(ike_sa);
+ enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
+ while (enumerator->enumerate(enumerator, &child_cfg))
+ {
+ current = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL);
+ while (current->remove_first(current, (void**)&ts) == SUCCESS)
+ {
+ list->insert_last(list, ts);
+ }
+ current->destroy(current);
+ }
+ enumerator->destroy(enumerator);
+
+ if (list->get_count(list) == 0)
+ {
+ list->destroy(list);
+ return NULL;
+ }
+ DBG1(DBG_CFG, "sending %N: %#R",
+ configuration_attribute_type_names, UNITY_SPLIT_INCLUDE, list);
+
+ INIT(attr_enum,
+ .public = {
+ .enumerate = (void*)_attribute_enumerate,
+ .destroy = _attribute_destroy,
+ },
+ .list = list,
+ );
+
+ return &attr_enum->public;
+}
+
+METHOD(unity_provider_t, destroy, void,
+ private_unity_provider_t *this)
+{
+ free(this);
+}
+
+/**
+ * See header
+ */
+unity_provider_t *unity_provider_create()
+{
+ private_unity_provider_t *this;
+
+ INIT(this,
+ .public = {
+ .provider = {
+ .acquire_address = (void*)return_null,
+ .release_address = (void*)return_false,
+ .create_attribute_enumerator = _create_attribute_enumerator,
+ },
+ .destroy = _destroy,
+ },
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/unity/unity_provider.h b/src/libcharon/plugins/unity/unity_provider.h
new file mode 100644
index 000000000..a25df5df0
--- /dev/null
+++ b/src/libcharon/plugins/unity/unity_provider.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 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 unity_provider unity_provider
+ * @{ @ingroup unity
+ */
+
+#ifndef UNITY_PROVIDER_H_
+#define UNITY_PROVIDER_H_
+
+typedef struct unity_provider_t unity_provider_t;
+
+#include <attributes/attribute_provider.h>
+
+/**
+ * Cisco Unity extension attribute provider.
+ */
+struct unity_provider_t {
+
+ /**
+ * Implements attribute_provier_t interface.
+ */
+ attribute_provider_t provider;
+
+ /**
+ * Destroy a unity_provider_t.
+ */
+ void (*destroy)(unity_provider_t *this);
+};
+
+/**
+ * Create a unity_provider instance.
+ */
+unity_provider_t *unity_provider_create();
+
+#endif /** UNITY_PROVIDER_H_ @}*/
diff --git a/src/libcharon/plugins/updown/Makefile.am b/src/libcharon/plugins/updown/Makefile.am
index 312c8d7e8..30683d83e 100644
--- a/src/libcharon/plugins/updown/Makefile.am
+++ b/src/libcharon/plugins/updown/Makefile.am
@@ -12,6 +12,7 @@ endif
libstrongswan_updown_la_SOURCES = \
updown_plugin.h updown_plugin.c \
+ updown_handler.h updown_handler.c \
updown_listener.h updown_listener.c
libstrongswan_updown_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/updown/Makefile.in b/src/libcharon/plugins/updown/Makefile.in
index fb7b38f65..0f3463704 100644
--- a/src/libcharon/plugins/updown/Makefile.in
+++ b/src/libcharon/plugins/updown/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -76,7 +77,7 @@ am__installdirs = "$(DESTDIR)$(plugindir)"
LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_updown_la_LIBADD =
am_libstrongswan_updown_la_OBJECTS = updown_plugin.lo \
- updown_listener.lo
+ updown_handler.lo updown_listener.lo
libstrongswan_updown_la_OBJECTS = \
$(am_libstrongswan_updown_la_OBJECTS)
libstrongswan_updown_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@@ -85,7 +86,7 @@ libstrongswan_updown_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@MONOLITHIC_FALSE@am_libstrongswan_updown_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_updown_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -111,6 +112,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -205,11 +207,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -226,11 +231,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -246,6 +252,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -255,7 +262,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -291,6 +297,7 @@ AM_CFLAGS = -rdynamic
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-updown.la
libstrongswan_updown_la_SOURCES = \
updown_plugin.h updown_plugin.c \
+ updown_handler.h updown_handler.c \
updown_listener.h updown_listener.c
libstrongswan_updown_la_LDFLAGS = -module -avoid-version
@@ -377,6 +384,7 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/updown_handler.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/updown_listener.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/updown_plugin.Plo@am__quote@
diff --git a/src/libcharon/plugins/updown/updown_handler.c b/src/libcharon/plugins/updown/updown_handler.c
new file mode 100644
index 000000000..b2ac02e85
--- /dev/null
+++ b/src/libcharon/plugins/updown/updown_handler.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 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 "updown_handler.h"
+
+#include <daemon.h>
+#include <utils/linked_list.h>
+#include <threading/rwlock.h>
+
+typedef struct private_updown_handler_t private_updown_handler_t;
+
+/**
+ * Private data of an updown_handler_t object.
+ */
+struct private_updown_handler_t {
+
+ /**
+ * Public updown_handler_t interface.
+ */
+ updown_handler_t public;
+
+ /**
+ * List of connection specific attributes, as attributes_t
+ */
+ linked_list_t *attrs;
+
+ /**
+ * rwlock to lock access to pools
+ */
+ rwlock_t *lock;
+};
+
+/**
+ * Attributes assigned to an IKE_SA
+ */
+typedef struct {
+ /** unique IKE_SA identifier */
+ u_int id;
+ /** list of DNS attributes, as host_t */
+ linked_list_t *dns;
+} attributes_t;
+
+/**
+ * Destroy an attributes_t entry
+ */
+static void attributes_destroy(attributes_t *this)
+{
+ this->dns->destroy_offset(this->dns, offsetof(host_t, destroy));
+ free(this);
+}
+
+METHOD(attribute_handler_t, handle, bool,
+ private_updown_handler_t *this, identification_t *server,
+ configuration_attribute_type_t type, chunk_t data)
+{
+ attributes_t *current, *attr = NULL;
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa;
+ host_t *host;
+
+ ike_sa = charon->bus->get_sa(charon->bus);
+ if (!ike_sa)
+ {
+ return FALSE;
+ }
+ switch (type)
+ {
+ case INTERNAL_IP4_DNS:
+ host = host_create_from_chunk(AF_INET, data, 0);
+ break;
+ case INTERNAL_IP6_DNS:
+ host = host_create_from_chunk(AF_INET6, data, 0);
+ break;
+ default:
+ return FALSE;
+ }
+ if (!host)
+ {
+ return FALSE;
+ }
+
+ this->lock->write_lock(this->lock);
+ enumerator = this->attrs->create_enumerator(this->attrs);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (current->id == ike_sa->get_unique_id(ike_sa))
+ {
+ attr = current;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!attr)
+ {
+ INIT(attr,
+ .id = ike_sa->get_unique_id(ike_sa),
+ .dns = linked_list_create(),
+ );
+ this->attrs->insert_last(this->attrs, attr);
+ }
+ attr->dns->insert_last(attr->dns, host);
+ this->lock->unlock(this->lock);
+
+ return TRUE;
+}
+
+METHOD(attribute_handler_t, release, void,
+ private_updown_handler_t *this, identification_t *server,
+ configuration_attribute_type_t type, chunk_t data)
+{
+ attributes_t *attr;
+ enumerator_t *enumerator, *servers;
+ ike_sa_t *ike_sa;
+ host_t *host;
+ bool found = FALSE;
+ int family;
+
+ switch (type)
+ {
+ case INTERNAL_IP4_DNS:
+ family = AF_INET;
+ break;
+ case INTERNAL_IP6_DNS:
+ family = AF_INET6;
+ break;
+ default:
+ return;
+ }
+
+ ike_sa = charon->bus->get_sa(charon->bus);
+ if (ike_sa)
+ {
+ this->lock->write_lock(this->lock);
+ enumerator = this->attrs->create_enumerator(this->attrs);
+ while (enumerator->enumerate(enumerator, &attr))
+ {
+ if (attr->id == ike_sa->get_unique_id(ike_sa))
+ {
+ servers = attr->dns->create_enumerator(attr->dns);
+ while (servers->enumerate(servers, &host))
+ {
+ if (host->get_family(host) == family &&
+ chunk_equals(data, host->get_address(host)))
+ {
+ attr->dns->remove_at(attr->dns, servers);
+ host->destroy(host);
+ found = TRUE;
+ break;
+ }
+ }
+ servers->destroy(servers);
+ if (attr->dns->get_count(attr->dns) == 0)
+ {
+ this->attrs->remove_at(this->attrs, enumerator);
+ attributes_destroy(attr);
+ break;
+ }
+ }
+ if (found)
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+ }
+}
+
+METHOD(updown_handler_t, create_dns_enumerator, enumerator_t*,
+ private_updown_handler_t *this, u_int id)
+{
+ attributes_t *attr;
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa;
+
+ ike_sa = charon->bus->get_sa(charon->bus);
+ if (!ike_sa)
+ {
+ return FALSE;
+ }
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->attrs->create_enumerator(this->attrs);
+ while (enumerator->enumerate(enumerator, &attr))
+ {
+ if (attr->id == ike_sa->get_unique_id(ike_sa))
+ {
+ enumerator->destroy(enumerator);
+ return enumerator_create_cleaner(
+ attr->dns->create_enumerator(attr->dns),
+ (void*)this->lock->unlock, this->lock);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ return enumerator_create_empty();
+}
+
+
+METHOD(updown_handler_t, destroy, void,
+ private_updown_handler_t *this)
+{
+ this->lock->destroy(this->lock);
+ this->attrs->destroy_function(this->attrs, (void*)attributes_destroy);
+ free(this);
+}
+
+/**
+ * See header
+ */
+updown_handler_t *updown_handler_create()
+{
+ private_updown_handler_t *this;
+
+ INIT(this,
+ .public = {
+ .handler = {
+ .handle = _handle,
+ .release = _release,
+ .create_attribute_enumerator = enumerator_create_empty,
+ },
+ .create_dns_enumerator = _create_dns_enumerator,
+ .destroy = _destroy,
+ },
+ .attrs = linked_list_create(),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/updown/updown_handler.h b/src/libcharon/plugins/updown/updown_handler.h
new file mode 100644
index 000000000..d4de880b8
--- /dev/null
+++ b/src/libcharon/plugins/updown/updown_handler.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 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 updown_handler updown_handler
+ * @{ @ingroup updown
+ */
+
+#ifndef UPDOWN_HANDLER_H_
+#define UPDOWN_HANDLER_H_
+
+#include <attributes/attribute_handler.h>
+
+typedef struct updown_handler_t updown_handler_t;
+
+/**
+ * Handler storing configuration attributes to pass to updown script.
+ */
+struct updown_handler_t {
+
+ /**
+ * Implements the attribute_handler_t interface
+ */
+ attribute_handler_t handler;
+
+ /**
+ * Create an enumerator over received DNS servers.
+ *
+ * @param id unique IKE_SA identifier to get attributes for
+ * @return enumerator over host_t*
+ */
+ enumerator_t* (*create_dns_enumerator)(updown_handler_t *this, u_int id);
+
+ /**
+ * Destroy a updown_handler_t.
+ */
+ void (*destroy)(updown_handler_t *this);
+};
+
+/**
+ * Create a updown_handler instance.
+ */
+updown_handler_t *updown_handler_create();
+
+#endif /** UPDOWN_HANDLER_H_ @}*/
diff --git a/src/libcharon/plugins/updown/updown_listener.c b/src/libcharon/plugins/updown/updown_listener.c
index 2bd757ec7..8b2af05b6 100644
--- a/src/libcharon/plugins/updown/updown_listener.c
+++ b/src/libcharon/plugins/updown/updown_listener.c
@@ -38,6 +38,11 @@ struct private_updown_listener_t {
* List of cached interface names
*/
linked_list_t *iface_cache;
+
+ /**
+ * DNS attribute handler
+ */
+ updown_handler_t *handler;
};
typedef struct cache_entry_t cache_entry_t;
@@ -90,6 +95,85 @@ static char* uncache_iface(private_updown_listener_t *this, u_int32_t reqid)
return iface;
}
+/**
+ * Create variables for handled DNS attributes
+ */
+static char *make_dns_vars(private_updown_listener_t *this, ike_sa_t *ike_sa)
+{
+ enumerator_t *enumerator;
+ host_t *host;
+ int v4 = 0, v6 = 0;
+ char total[512] = "", current[64];
+
+ if (!this->handler)
+ {
+ return strdup("");
+ }
+
+ enumerator = this->handler->create_dns_enumerator(this->handler,
+ ike_sa->get_unique_id(ike_sa));
+ while (enumerator->enumerate(enumerator, &host))
+ {
+ switch (host->get_family(host))
+ {
+ case AF_INET:
+ snprintf(current, sizeof(current),
+ "PLUTO_DNS4_%d='%H' ", ++v4, host);
+ break;
+ case AF_INET6:
+ snprintf(current, sizeof(current),
+ "PLUTO_DNS6_%d='%H' ", ++v6, host);
+ break;
+ default:
+ continue;
+ }
+ strncat(total, current, sizeof(total) - strlen(total) - 1);
+ }
+ enumerator->destroy(enumerator);
+
+ return strdup(total);
+}
+
+/**
+ * Create variables for local virtual IPs
+ */
+static char *make_vip_vars(private_updown_listener_t *this, ike_sa_t *ike_sa)
+{
+ enumerator_t *enumerator;
+ host_t *host;
+ int v4 = 0, v6 = 0;
+ char total[512] = "", current[64];
+ bool first = TRUE;
+
+ enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, TRUE);
+ while (enumerator->enumerate(enumerator, &host))
+ {
+ if (first)
+ { /* legacy variable for first VIP */
+ snprintf(current, sizeof(current),
+ "PLUTO_MY_SOURCEIP='%H' ", host);
+ strncat(total, current, sizeof(total) - strlen(total) - 1);
+ }
+ switch (host->get_family(host))
+ {
+ case AF_INET:
+ snprintf(current, sizeof(current),
+ "PLUTO_MY_SOURCEIP4_%d='%H' ", ++v4, host);
+ break;
+ case AF_INET6:
+ snprintf(current, sizeof(current),
+ "PLUTO_MY_SOURCEIP6_%d='%H' ", ++v6, host);
+ break;
+ default:
+ continue;
+ }
+ strncat(total, current, sizeof(total) - strlen(total) - 1);
+ }
+ enumerator->destroy(enumerator);
+
+ return strdup(total);
+}
+
METHOD(listener_t, child_updown, bool,
private_updown_listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
bool up)
@@ -97,11 +181,10 @@ METHOD(listener_t, child_updown, bool,
traffic_selector_t *my_ts, *other_ts;
enumerator_t *enumerator;
child_cfg_t *config;
- host_t *vip, *me, *other;
+ host_t *me, *other;
char *script;
config = child_sa->get_config(child_sa);
- vip = ike_sa->get_virtual_ip(ike_sa, TRUE);
script = config->get_updown(config);
me = ike_sa->get_my_host(ike_sa);
other = ike_sa->get_other_host(ike_sa);
@@ -117,7 +200,7 @@ METHOD(listener_t, child_updown, bool,
char command[1024];
host_t *my_client, *other_client;
u_int8_t my_client_mask, other_client_mask;
- char *virtual_ip, *iface, *mark_in, *mark_out, *udp_enc;
+ char *virtual_ip, *iface, *mark_in, *mark_out, *udp_enc, *dns;
mark_t mark;
bool is_host, is_ipv6;
FILE *shell;
@@ -125,20 +208,7 @@ METHOD(listener_t, child_updown, bool,
my_ts->to_subnet(my_ts, &my_client, &my_client_mask);
other_ts->to_subnet(other_ts, &other_client, &other_client_mask);
- if (vip)
- {
- if (asprintf(&virtual_ip, "PLUTO_MY_SOURCEIP='%H' ", vip) < 0)
- {
- virtual_ip = NULL;
- }
- }
- else
- {
- if (asprintf(&virtual_ip, "") < 0)
- {
- virtual_ip = NULL;
- }
- }
+ virtual_ip = make_vip_vars(this, ike_sa);
/* check for the presence of an inbound mark */
mark = config->get_mark(config, TRUE);
@@ -197,9 +267,8 @@ METHOD(listener_t, child_updown, bool,
if (up)
{
- iface = hydra->kernel_interface->get_interface(
- hydra->kernel_interface, me);
- if (iface)
+ if (hydra->kernel_interface->get_interface(hydra->kernel_interface,
+ me, &iface))
{
cache_iface(this, child_sa->get_reqid(child_sa), iface);
}
@@ -209,6 +278,8 @@ METHOD(listener_t, child_updown, bool,
iface = uncache_iface(this, child_sa->get_reqid(child_sa));
}
+ dns = make_dns_vars(this, ike_sa);
+
/* determine IPv4/IPv6 and client/host situation */
is_host = my_ts->is_host(my_ts, me);
is_ipv6 = is_host ? (me->get_family(me) == AF_INET6) :
@@ -239,6 +310,7 @@ METHOD(listener_t, child_updown, bool,
"%s"
"%s"
"%s"
+ "%s"
"%s",
up ? "up" : "down",
is_host ? "-host" : "-client",
@@ -259,6 +331,7 @@ METHOD(listener_t, child_updown, bool,
mark_out,
udp_enc,
config->get_hostaccess(config) ? "PLUTO_HOST_ACCESS='1' " : "",
+ dns,
script);
my_client->destroy(my_client);
other_client->destroy(other_client);
@@ -266,6 +339,7 @@ METHOD(listener_t, child_updown, bool,
free(mark_in);
free(mark_out);
free(udp_enc);
+ free(dns);
free(iface);
DBG3(DBG_CHD, "running updown script: %s", command);
@@ -315,7 +389,7 @@ METHOD(updown_listener_t, destroy, void,
/**
* See header
*/
-updown_listener_t *updown_listener_create()
+updown_listener_t *updown_listener_create(updown_handler_t *handler)
{
private_updown_listener_t *this;
@@ -327,6 +401,7 @@ updown_listener_t *updown_listener_create()
.destroy = _destroy,
},
.iface_cache = linked_list_create(),
+ .handler = handler,
);
return &this->public;
diff --git a/src/libcharon/plugins/updown/updown_listener.h b/src/libcharon/plugins/updown/updown_listener.h
index 5b866c4e5..2d9b56ade 100644
--- a/src/libcharon/plugins/updown/updown_listener.h
+++ b/src/libcharon/plugins/updown/updown_listener.h
@@ -23,6 +23,8 @@
#include <bus/bus.h>
+#include "updown_handler.h"
+
typedef struct updown_listener_t updown_listener_t;
/**
@@ -44,6 +46,6 @@ struct updown_listener_t {
/**
* Create a updown_listener instance.
*/
-updown_listener_t *updown_listener_create();
+updown_listener_t *updown_listener_create(updown_handler_t *handler);
#endif /** UPDOWN_LISTENER_H_ @}*/
diff --git a/src/libcharon/plugins/updown/updown_plugin.c b/src/libcharon/plugins/updown/updown_plugin.c
index 2ce2d3257..e1f0d1380 100644
--- a/src/libcharon/plugins/updown/updown_plugin.c
+++ b/src/libcharon/plugins/updown/updown_plugin.c
@@ -15,8 +15,10 @@
#include "updown_plugin.h"
#include "updown_listener.h"
+#include "updown_handler.h"
#include <daemon.h>
+#include <hydra.h>
typedef struct private_updown_plugin_t private_updown_plugin_t;
@@ -34,6 +36,11 @@ struct private_updown_plugin_t {
* Listener interface, listens to CHILD_SA state changes
*/
updown_listener_t *listener;
+
+ /**
+ * Attribute handler, to pass DNS servers to updown
+ */
+ updown_handler_t *handler;
};
METHOD(plugin_t, get_name, char*,
@@ -47,6 +54,12 @@ METHOD(plugin_t, destroy, void,
{
charon->bus->remove_listener(charon->bus, &this->listener->listener);
this->listener->destroy(this->listener);
+ if (this->handler)
+ {
+ hydra->attributes->remove_handler(hydra->attributes,
+ &this->handler->handler);
+ this->handler->destroy(this->handler);
+ }
free(this);
}
@@ -65,9 +78,16 @@ plugin_t *updown_plugin_create()
.destroy = _destroy,
},
},
- .listener = updown_listener_create(),
);
+ if (lib->settings->get_bool(lib->settings,
+ "charon.plugins.updown.dns_handler", FALSE))
+ {
+ this->handler = updown_handler_create();
+ hydra->attributes->add_handler(hydra->attributes,
+ &this->handler->handler);
+ }
+ this->listener = updown_listener_create(this->handler);
charon->bus->add_listener(charon->bus, &this->listener->listener);
return &this->public.plugin;
diff --git a/src/libcharon/plugins/whitelist/Makefile.in b/src/libcharon/plugins/whitelist/Makefile.in
index 2534f4bec..80f12df47 100644
--- a/src/libcharon/plugins/whitelist/Makefile.in
+++ b/src/libcharon/plugins/whitelist/Makefile.in
@@ -51,6 +51,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -92,7 +93,7 @@ PROGRAMS = $(ipsec_PROGRAMS)
am_whitelist_OBJECTS = whitelist.$(OBJEXT)
whitelist_OBJECTS = $(am_whitelist_OBJECTS)
whitelist_LDADD = $(LDADD)
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -119,6 +120,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -213,11 +215,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -234,11 +239,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -254,6 +260,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -263,7 +270,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libcharon/plugins/whitelist/whitelist.c b/src/libcharon/plugins/whitelist/whitelist.c
index 5f511f2c5..0a3a34459 100644
--- a/src/libcharon/plugins/whitelist/whitelist.c
+++ b/src/libcharon/plugins/whitelist/whitelist.c
@@ -80,6 +80,7 @@ static int send_msg(int type, char *id)
{
break;
}
+ msg.id[sizeof(msg.id) - 1] = '\0';
printf("%s\n", msg.id);
}
}
diff --git a/src/libcharon/plugins/whitelist/whitelist_control.c b/src/libcharon/plugins/whitelist/whitelist_control.c
index 202c9a418..a75ea9aee 100644
--- a/src/libcharon/plugins/whitelist/whitelist_control.c
+++ b/src/libcharon/plugins/whitelist/whitelist_control.c
@@ -49,11 +49,6 @@ struct private_whitelist_control_t {
* Whitelist unix socket file descriptor
*/
int socket;
-
- /**
- * Callback job dispatching commands
- */
- callback_job_t *job;
};
/**
@@ -82,7 +77,8 @@ static bool open_socket(private_whitelist_control_t *this)
return FALSE;
}
umask(old);
- if (chown(addr.sun_path, charon->uid, charon->gid) != 0)
+ if (chown(addr.sun_path, charon->caps->get_uid(charon->caps),
+ charon->caps->get_gid(charon->caps)) != 0)
{
DBG1(DBG_CFG, "changing whitelist socket permissions failed: %s",
strerror(errno));
@@ -200,7 +196,6 @@ static job_requeue_t receive(private_whitelist_control_t *this)
METHOD(whitelist_control_t, destroy, void,
private_whitelist_control_t *this)
{
- this->job->cancel(this->job);
close(this->socket);
free(this);
}
@@ -225,9 +220,9 @@ whitelist_control_t *whitelist_control_create(whitelist_listener_t *listener)
return NULL;
}
- this->job = callback_job_create_with_prio((callback_job_cb_t)receive,
- this, NULL, NULL, JOB_PRIO_CRITICAL);
- lib->processor->queue_job(lib->processor, (job_t*)this->job);
+ lib->processor->queue_job(lib->processor,
+ (job_t*)callback_job_create_with_prio((callback_job_cb_t)receive, this,
+ NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
return &this->public;
}
diff --git a/src/libcharon/plugins/whitelist/whitelist_listener.c b/src/libcharon/plugins/whitelist/whitelist_listener.c
index 5634e3ef8..64ef04800 100644
--- a/src/libcharon/plugins/whitelist/whitelist_listener.c
+++ b/src/libcharon/plugins/whitelist/whitelist_listener.c
@@ -206,7 +206,7 @@ whitelist_listener_t *whitelist_listener_create()
.ids = hashtable_create((hashtable_hash_t)hash,
(hashtable_equals_t)equals, 32),
.enabled = lib->settings->get_bool(lib->settings,
- "charon.plugins.whitelist.enable", FALSE),
+ "%s.plugins.whitelist.enable", FALSE, charon->name),
);
return &this->public;
diff --git a/src/libcharon/plugins/xauth_eap/Makefile.am b/src/libcharon/plugins/xauth_eap/Makefile.am
new file mode 100644
index 000000000..f2cb0e26c
--- /dev/null
+++ b/src/libcharon/plugins/xauth_eap/Makefile.am
@@ -0,0 +1,17 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-xauth-eap.la
+else
+plugin_LTLIBRARIES = libstrongswan-xauth-eap.la
+endif
+
+libstrongswan_xauth_eap_la_SOURCES = \
+ xauth_eap_plugin.h xauth_eap_plugin.c \
+ xauth_eap.h xauth_eap.c
+
+libstrongswan_xauth_eap_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/socket_raw/Makefile.in b/src/libcharon/plugins/xauth_eap/Makefile.in
index 5abceb6c3..709e2be03 100644
--- a/src/libcharon/plugins/socket_raw/Makefile.in
+++ b/src/libcharon/plugins/xauth_eap/Makefile.in
@@ -34,7 +34,7 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-subdir = src/libcharon/plugins/socket_raw
+subdir = src/libcharon/plugins/xauth_eap
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -74,19 +75,19 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
-libstrongswan_socket_raw_la_LIBADD =
-am_libstrongswan_socket_raw_la_OBJECTS = socket_raw_plugin.lo \
- socket_raw_socket.lo
-libstrongswan_socket_raw_la_OBJECTS = \
- $(am_libstrongswan_socket_raw_la_OBJECTS)
-libstrongswan_socket_raw_la_LINK = $(LIBTOOL) --tag=CC \
+libstrongswan_xauth_eap_la_LIBADD =
+am_libstrongswan_xauth_eap_la_OBJECTS = xauth_eap_plugin.lo \
+ xauth_eap.lo
+libstrongswan_xauth_eap_la_OBJECTS = \
+ $(am_libstrongswan_xauth_eap_la_OBJECTS)
+libstrongswan_xauth_eap_la_LINK = $(LIBTOOL) --tag=CC \
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
- $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_socket_raw_la_LDFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_xauth_eap_la_LDFLAGS) \
$(LDFLAGS) -o $@
-@MONOLITHIC_FALSE@am_libstrongswan_socket_raw_la_rpath = -rpath \
+@MONOLITHIC_FALSE@am_libstrongswan_xauth_eap_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
-@MONOLITHIC_TRUE@am_libstrongswan_socket_raw_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+@MONOLITHIC_TRUE@am_libstrongswan_xauth_eap_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -99,8 +100,8 @@ CCLD = $(CC)
LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
-SOURCES = $(libstrongswan_socket_raw_la_SOURCES)
-DIST_SOURCES = $(libstrongswan_socket_raw_la_SOURCES)
+SOURCES = $(libstrongswan_xauth_eap_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_xauth_eap_la_SOURCES)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -112,6 +113,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -206,11 +208,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -227,11 +232,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -247,6 +253,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -256,7 +263,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -284,17 +290,17 @@ top_srcdir = @top_srcdir@
urandom_device = @urandom_device@
xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
-INCLUDES = -I${linux_headers} -I$(top_srcdir)/src/libstrongswan \
- -I$(top_srcdir)/src/libhydra -I$(top_srcdir)/src/libcharon
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
AM_CFLAGS = -rdynamic
-@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-socket-raw.la
-@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-socket-raw.la
-libstrongswan_socket_raw_la_SOURCES = \
- socket_raw_plugin.h socket_raw_plugin.c \
- socket_raw_socket.h socket_raw_socket.c
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-xauth-eap.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-xauth-eap.la
+libstrongswan_xauth_eap_la_SOURCES = \
+ xauth_eap_plugin.h xauth_eap_plugin.c \
+ xauth_eap.h xauth_eap.c
-libstrongswan_socket_raw_la_LDFLAGS = -module -avoid-version
+libstrongswan_xauth_eap_la_LDFLAGS = -module -avoid-version
all: all-am
.SUFFIXES:
@@ -308,9 +314,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/socket_raw/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/xauth_eap/Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --gnu src/libcharon/plugins/socket_raw/Makefile
+ $(AUTOMAKE) --gnu src/libcharon/plugins/xauth_eap/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
@@ -369,8 +375,8 @@ clean-pluginLTLIBRARIES:
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
-libstrongswan-socket-raw.la: $(libstrongswan_socket_raw_la_OBJECTS) $(libstrongswan_socket_raw_la_DEPENDENCIES)
- $(libstrongswan_socket_raw_la_LINK) $(am_libstrongswan_socket_raw_la_rpath) $(libstrongswan_socket_raw_la_OBJECTS) $(libstrongswan_socket_raw_la_LIBADD) $(LIBS)
+libstrongswan-xauth-eap.la: $(libstrongswan_xauth_eap_la_OBJECTS) $(libstrongswan_xauth_eap_la_DEPENDENCIES)
+ $(libstrongswan_xauth_eap_la_LINK) $(am_libstrongswan_xauth_eap_la_rpath) $(libstrongswan_xauth_eap_la_OBJECTS) $(libstrongswan_xauth_eap_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -378,8 +384,8 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_raw_plugin.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_raw_socket.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xauth_eap.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xauth_eap_plugin.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
diff --git a/src/libcharon/plugins/xauth_eap/xauth_eap.c b/src/libcharon/plugins/xauth_eap/xauth_eap.c
new file mode 100644
index 000000000..1da1d9f85
--- /dev/null
+++ b/src/libcharon/plugins/xauth_eap/xauth_eap.c
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 "xauth_eap.h"
+
+#include <daemon.h>
+
+#include <library.h>
+#include <credentials/sets/callback_cred.h>
+
+typedef struct private_xauth_eap_t private_xauth_eap_t;
+
+/**
+ * Private data of an xauth_eap_t object.
+ */
+struct private_xauth_eap_t {
+
+ /**
+ * Public interface.
+ */
+ xauth_eap_t public;
+
+ /**
+ * ID of the server
+ */
+ identification_t *server;
+
+ /**
+ * ID of the peer
+ */
+ identification_t *peer;
+
+ /**
+ * Callback credential set
+ */
+ callback_cred_t *cred;
+
+ /**
+ * XAuth password
+ */
+ chunk_t pass;
+};
+
+/**
+ * Callback credential set function
+ */
+static shared_key_t* shared_cb(private_xauth_eap_t *this, shared_key_type_t type,
+ identification_t *me, identification_t *other,
+ id_match_t *match_me, id_match_t *match_other)
+{
+ shared_key_t *shared;
+
+ if (!this->pass.len)
+ {
+ return NULL;
+ }
+ if (type != SHARED_EAP && type != SHARED_ANY)
+ {
+ return NULL;
+ }
+ if (me)
+ {
+ if (!this->peer->equals(this->peer, me))
+ {
+ return NULL;
+ }
+ if (match_me)
+ {
+ *match_me = ID_MATCH_PERFECT;
+ }
+ }
+ else if (match_me)
+ {
+ *match_me = ID_MATCH_ANY;
+ }
+ if (other)
+ {
+ if (!this->server->equals(this->server, other))
+ {
+ return NULL;
+ }
+ if (match_other)
+ {
+ *match_other = ID_MATCH_PERFECT;
+ }
+ }
+ else if (match_other)
+ {
+ *match_other = ID_MATCH_ANY;
+ }
+ shared = shared_key_create(SHARED_EAP, chunk_clone(this->pass));
+ this->pass = chunk_empty;
+ return shared;
+}
+
+/**
+ * Do EAP exchanges to verify secret
+ */
+static bool verify_eap(private_xauth_eap_t *this, eap_method_t *backend)
+{
+ eap_payload_t *request, *response;
+ eap_method_t *frontend;
+ eap_type_t type;
+ u_int32_t vendor;
+ status_t status;
+
+ if (backend->initiate(backend, &request) != NEED_MORE)
+ {
+ return FALSE;
+ }
+ type = request->get_type(request, &vendor);
+ frontend = charon->eap->create_instance(charon->eap, type, vendor,
+ EAP_PEER, this->server, this->peer);
+ if (!frontend)
+ {
+ DBG1(DBG_IKE, "XAuth-EAP backend requested %N, but not supported",
+ eap_type_names, type);
+ request->destroy(request);
+ return FALSE;
+ }
+ while (TRUE)
+ {
+ /* credential set is active in frontend only, but not in backend */
+ lib->credmgr->add_local_set(lib->credmgr, &this->cred->set, TRUE);
+ status = frontend->process(frontend, request, &response);
+ lib->credmgr->remove_local_set(lib->credmgr, &this->cred->set);
+ request->destroy(request);
+ if (status != NEED_MORE)
+ { /* clients should never return SUCCESS */
+ frontend->destroy(frontend);
+ return FALSE;
+ }
+ status = backend->process(backend, response, &request);
+ response->destroy(response);
+ switch (status)
+ {
+ case SUCCESS:
+ frontend->destroy(frontend);
+ return TRUE;
+ case NEED_MORE:
+ break;
+ default:
+ frontend->destroy(frontend);
+ return FALSE;
+ }
+ }
+}
+
+METHOD(xauth_method_t, initiate, status_t,
+ private_xauth_eap_t *this, cp_payload_t **out)
+{
+ cp_payload_t *cp;
+
+ cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REQUEST);
+ cp->add_attribute(cp, configuration_attribute_create_chunk(
+ CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_NAME, chunk_empty));
+ cp->add_attribute(cp, configuration_attribute_create_chunk(
+ CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_PASSWORD, chunk_empty));
+ *out = cp;
+ return NEED_MORE;
+}
+
+METHOD(xauth_method_t, process, status_t,
+ private_xauth_eap_t *this, cp_payload_t *in, cp_payload_t **out)
+{
+ configuration_attribute_t *attr;
+ enumerator_t *enumerator;
+ identification_t *id;
+ chunk_t user = chunk_empty;
+ eap_method_t *backend;
+ eap_type_t type;
+ char *name;
+ bool ok;
+
+ enumerator = in->create_attribute_enumerator(in);
+ while (enumerator->enumerate(enumerator, &attr))
+ {
+ switch (attr->get_type(attr))
+ {
+ case XAUTH_USER_NAME:
+ user = attr->get_chunk(attr);
+ break;
+ case XAUTH_USER_PASSWORD:
+ this->pass = attr->get_chunk(attr);
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!user.ptr || !this->pass.ptr)
+ {
+ DBG1(DBG_IKE, "peer did not respond to our XAuth request");
+ return FAILED;
+ }
+ if (user.len)
+ {
+ id = identification_create_from_data(user);
+ if (!id)
+ {
+ DBG1(DBG_IKE, "failed to parse provided XAuth username");
+ return FAILED;
+ }
+ this->peer->destroy(this->peer);
+ this->peer = id;
+ }
+ if (this->pass.len && this->pass.ptr[this->pass.len - 1] == 0)
+ { /* fix null-terminated passwords (Android etc.) */
+ this->pass.len -= 1;
+ }
+
+ name = lib->settings->get_str(lib->settings,
+ "%s.plugins.xauth-eap.backend", "radius",
+ charon->name);
+ type = eap_type_from_string(name);
+ if (!type)
+ {
+ DBG1(DBG_CFG, "Unknown XAuth-EAP method: %s", name);
+ return FAILED;
+ }
+ backend = charon->eap->create_instance(charon->eap, type, 0, EAP_SERVER,
+ this->server, this->peer);
+ if (!backend)
+ {
+ DBG1(DBG_CFG, "XAuth-EAP method backend not supported: %s", name);
+ return FAILED;
+ }
+ ok = verify_eap(this, backend);
+ backend->destroy(backend);
+ if (ok)
+ {
+ return SUCCESS;
+ }
+ return FAILED;
+}
+
+METHOD(xauth_method_t, get_identity, identification_t*,
+ private_xauth_eap_t *this)
+{
+ return this->peer;
+}
+
+METHOD(xauth_method_t, destroy, void,
+ private_xauth_eap_t *this)
+{
+ this->cred->destroy(this->cred);
+ this->server->destroy(this->server);
+ this->peer->destroy(this->peer);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+xauth_eap_t *xauth_eap_create_server(identification_t *server,
+ identification_t *peer)
+{
+ private_xauth_eap_t *this;
+
+ INIT(this,
+ .public = {
+ .xauth_method = {
+ .initiate = _initiate,
+ .process = _process,
+ .get_identity = _get_identity,
+ .destroy = _destroy,
+ },
+ },
+ .server = server->clone(server),
+ .peer = peer->clone(peer),
+ );
+
+ this->cred = callback_cred_create_shared((void*)shared_cb, this);
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/xauth_eap/xauth_eap.h b/src/libcharon/plugins/xauth_eap/xauth_eap.h
new file mode 100644
index 000000000..70927247e
--- /dev/null
+++ b/src/libcharon/plugins/xauth_eap/xauth_eap.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 xauth_eap_i xauth_eap
+ * @{ @ingroup xauth_eap
+ */
+
+#ifndef XAUTH_EAP_H_
+#define XAUTH_EAP_H_
+
+typedef struct xauth_eap_t xauth_eap_t;
+
+#include <sa/xauth/xauth_method.h>
+
+/**
+ * XAuth method that verifies XAuth credentials using EAP methods.
+ *
+ * To reuse existing authentication infrastructure, this XAuth method uses
+ * EAP to verify XAuth Username/Passwords. It is primarily designed to work
+ * with the EAP-RADIUS backend and can use any password-based EAP method
+ * over it. The credentials are fed locally on the IKE responder to a EAP
+ * client which talks to the backend instance, usually a RADIUS server.
+ */
+struct xauth_eap_t {
+
+ /**
+ * Implemented xauth_method_t interface.
+ */
+ xauth_method_t xauth_method;
+};
+
+/**
+ * Creates the XAuth method using EAP, acting as server.
+ *
+ * @param server ID of the XAuth server
+ * @param peer ID of the XAuth client
+ * @return xauth_eap_t object
+ */
+xauth_eap_t *xauth_eap_create_server(identification_t *server,
+ identification_t *peer);
+
+#endif /** XAUTH_EAP_H_ @}*/
diff --git a/src/libcharon/plugins/xauth_eap/xauth_eap_plugin.c b/src/libcharon/plugins/xauth_eap/xauth_eap_plugin.c
new file mode 100644
index 000000000..b776ec8ea
--- /dev/null
+++ b/src/libcharon/plugins/xauth_eap/xauth_eap_plugin.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 "xauth_eap_plugin.h"
+#include "xauth_eap.h"
+
+#include <daemon.h>
+
+METHOD(plugin_t, get_name, char*,
+ xauth_eap_plugin_t *this)
+{
+ return "xauth-eap";
+}
+
+METHOD(plugin_t, get_features, int,
+ xauth_eap_plugin_t *this, plugin_feature_t *features[])
+{
+ static plugin_feature_t f[] = {
+ PLUGIN_CALLBACK(xauth_method_register, xauth_eap_create_server),
+ PLUGIN_PROVIDE(XAUTH_SERVER, "eap"),
+ };
+ *features = f;
+ return countof(f);
+}
+
+METHOD(plugin_t, destroy, void,
+ xauth_eap_plugin_t *this)
+{
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *xauth_eap_plugin_create()
+{
+ xauth_eap_plugin_t *this;
+
+ INIT(this,
+ .plugin = {
+ .get_name = _get_name,
+ .get_features = _get_features,
+ .destroy = _destroy,
+ },
+ );
+
+ return &this->plugin;
+}
diff --git a/src/libcharon/plugins/socket_raw/socket_raw_plugin.h b/src/libcharon/plugins/xauth_eap/xauth_eap_plugin.h
index a692b7594..8ba0628b0 100644
--- a/src/libcharon/plugins/socket_raw/socket_raw_plugin.h
+++ b/src/libcharon/plugins/xauth_eap/xauth_eap_plugin.h
@@ -1,6 +1,6 @@
/*
- * Copyright (C) 2010 Martin Willi
- * Copyright (C) 2010 revosec AG
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 revosec AG
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -14,24 +14,24 @@
*/
/**
- * @defgroup socket_raw socket_raw
+ * @defgroup xauth_eap xauth_eap
* @ingroup cplugins
*
- * @defgroup socket_raw_plugin socket_raw_plugin
- * @{ @ingroup socket_raw
+ * @defgroup xauth_eap_plugin xauth_eap_plugin
+ * @{ @ingroup xauth_eap
*/
-#ifndef SOCKET_RAW_PLUGIN_H_
-#define SOCKET_RAW_PLUGIN_H_
+#ifndef XAUTH_EAP_PLUGIN_H_
+#define XAUTH_EAP_PLUGIN_H_
#include <plugins/plugin.h>
-typedef struct socket_raw_plugin_t socket_raw_plugin_t;
+typedef struct xauth_eap_plugin_t xauth_eap_plugin_t;
/**
- * RAW socket implementation plugin.
+ * XAuth plugin using EAP to verify credentials.
*/
-struct socket_raw_plugin_t {
+struct xauth_eap_plugin_t {
/**
* implements plugin interface
@@ -39,4 +39,4 @@ struct socket_raw_plugin_t {
plugin_t plugin;
};
-#endif /** SOCKET_RAW_PLUGIN_H_ @}*/
+#endif /** XAUTH_EAP_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/xauth_generic/Makefile.am b/src/libcharon/plugins/xauth_generic/Makefile.am
new file mode 100644
index 000000000..0f25e74a2
--- /dev/null
+++ b/src/libcharon/plugins/xauth_generic/Makefile.am
@@ -0,0 +1,17 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-xauth-generic.la
+else
+plugin_LTLIBRARIES = libstrongswan-xauth-generic.la
+endif
+
+libstrongswan_xauth_generic_la_SOURCES = \
+ xauth_generic_plugin.h xauth_generic_plugin.c \
+ xauth_generic.h xauth_generic.c
+
+libstrongswan_xauth_generic_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/xauth_generic/Makefile.in b/src/libcharon/plugins/xauth_generic/Makefile.in
new file mode 100644
index 000000000..9f9743ef1
--- /dev/null
+++ b/src/libcharon/plugins/xauth_generic/Makefile.in
@@ -0,0 +1,622 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/libcharon/plugins/xauth_generic
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
+ $(top_srcdir)/m4/config/ltoptions.m4 \
+ $(top_srcdir)/m4/config/ltsugar.m4 \
+ $(top_srcdir)/m4/config/ltversion.m4 \
+ $(top_srcdir)/m4/config/lt~obsolete.m4 \
+ $(top_srcdir)/m4/macros/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/m4/macros/add-plugin.m4 \
+ $(top_srcdir)/configure.in
+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__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_xauth_generic_la_LIBADD =
+am_libstrongswan_xauth_generic_la_OBJECTS = xauth_generic_plugin.lo \
+ xauth_generic.lo
+libstrongswan_xauth_generic_la_OBJECTS = \
+ $(am_libstrongswan_xauth_generic_la_OBJECTS)
+libstrongswan_xauth_generic_la_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_xauth_generic_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_xauth_generic_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_xauth_generic_la_rpath =
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_xauth_generic_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_xauth_generic_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BFDLIB = @BFDLIB@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+attest_plugins = @attest_plugins@
+axis2c_CFLAGS = @axis2c_CFLAGS@
+axis2c_LIBS = @axis2c_LIBS@
+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@
+datadir = @datadir@
+datarootdir = @datarootdir@
+dbusservicedir = @dbusservicedir@
+dev_headers = @dev_headers@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+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@
+libdir = @libdir@
+libexecdir = @libexecdir@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+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@
+openac_plugins = @openac_plugins@
+p_plugins = @p_plugins@
+pcsclite_CFLAGS = @pcsclite_CFLAGS@
+pcsclite_LIBS = @pcsclite_LIBS@
+pdfdir = @pdfdir@
+piddir = @piddir@
+pki_plugins = @pki_plugins@
+plugindir = @plugindir@
+pool_plugins = @pool_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+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@
+sysconfdir = @sysconfdir@
+systemdsystemunitdir = @systemdsystemunitdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-xauth-generic.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-xauth-generic.la
+libstrongswan_xauth_generic_la_SOURCES = \
+ xauth_generic_plugin.h xauth_generic_plugin.c \
+ xauth_generic.h xauth_generic.c
+
+libstrongswan_xauth_generic_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/xauth_generic/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/xauth_generic/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-xauth-generic.la: $(libstrongswan_xauth_generic_la_OBJECTS) $(libstrongswan_xauth_generic_la_DEPENDENCIES)
+ $(libstrongswan_xauth_generic_la_LINK) $(am_libstrongswan_xauth_generic_la_rpath) $(libstrongswan_xauth_generic_la_OBJECTS) $(libstrongswan_xauth_generic_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xauth_generic.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xauth_generic_plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/xauth_generic/xauth_generic.c b/src/libcharon/plugins/xauth_generic/xauth_generic.c
new file mode 100644
index 000000000..f0e675ac0
--- /dev/null
+++ b/src/libcharon/plugins/xauth_generic/xauth_generic.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2011 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 "xauth_generic.h"
+
+#include <daemon.h>
+#include <library.h>
+
+typedef struct private_xauth_generic_t private_xauth_generic_t;
+
+/**
+ * Private data of an xauth_generic_t object.
+ */
+struct private_xauth_generic_t {
+
+ /**
+ * Public interface.
+ */
+ xauth_generic_t public;
+
+ /**
+ * ID of the server
+ */
+ identification_t *server;
+
+ /**
+ * ID of the peer
+ */
+ identification_t *peer;
+
+};
+
+METHOD(xauth_method_t, initiate_peer, status_t,
+ private_xauth_generic_t *this, cp_payload_t **out)
+{
+ /* peer never initiates */
+ return FAILED;
+}
+
+METHOD(xauth_method_t, process_peer, status_t,
+ private_xauth_generic_t *this, cp_payload_t *in, cp_payload_t **out)
+{
+ shared_key_t *shared;
+ cp_payload_t *cp;
+ chunk_t user, pass;
+
+ shared = lib->credmgr->get_shared(lib->credmgr, SHARED_EAP, this->peer,
+ this->server);
+ if (!shared)
+ {
+ DBG1(DBG_IKE, "no XAuth secret found for '%Y' - '%Y'", this->peer,
+ this->server);
+ return FAILED;
+ }
+
+ user = this->peer->get_encoding(this->peer);
+ pass = shared->get_key(shared);
+
+ cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REPLY);
+ cp->add_attribute(cp, configuration_attribute_create_chunk(
+ CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_NAME, user));
+ cp->add_attribute(cp, configuration_attribute_create_chunk(
+ CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_PASSWORD, pass));
+ shared->destroy(shared);
+ *out = cp;
+ return NEED_MORE;
+}
+
+METHOD(xauth_method_t, initiate_server, status_t,
+ private_xauth_generic_t *this, cp_payload_t **out)
+{
+ cp_payload_t *cp;
+
+ cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REQUEST);
+ cp->add_attribute(cp, configuration_attribute_create_chunk(
+ CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_NAME, chunk_empty));
+ cp->add_attribute(cp, configuration_attribute_create_chunk(
+ CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_PASSWORD, chunk_empty));
+ *out = cp;
+ return NEED_MORE;
+}
+
+METHOD(xauth_method_t, process_server, status_t,
+ private_xauth_generic_t *this, cp_payload_t *in, cp_payload_t **out)
+{
+ configuration_attribute_t *attr;
+ enumerator_t *enumerator;
+ shared_key_t *shared;
+ identification_t *id;
+ chunk_t user = chunk_empty, pass = chunk_empty;
+ status_t status = FAILED;
+ int tried = 0;
+
+ enumerator = in->create_attribute_enumerator(in);
+ while (enumerator->enumerate(enumerator, &attr))
+ {
+ switch (attr->get_type(attr))
+ {
+ case XAUTH_USER_NAME:
+ user = attr->get_chunk(attr);
+ break;
+ case XAUTH_USER_PASSWORD:
+ pass = attr->get_chunk(attr);
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!user.ptr || !pass.ptr)
+ {
+ DBG1(DBG_IKE, "peer did not respond to our XAuth request");
+ return FAILED;
+ }
+ if (user.len)
+ {
+ id = identification_create_from_data(user);
+ if (!id)
+ {
+ DBG1(DBG_IKE, "failed to parse provided XAuth username");
+ return FAILED;
+ }
+ this->peer->destroy(this->peer);
+ this->peer = id;
+ }
+ if (pass.len && pass.ptr[pass.len - 1] == 0)
+ { /* fix null-terminated passwords (Android etc.) */
+ pass.len -= 1;
+ }
+
+ enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr,
+ SHARED_EAP, this->server, this->peer);
+ while (enumerator->enumerate(enumerator, &shared, NULL, NULL))
+ {
+ if (chunk_equals(shared->get_key(shared), pass))
+ {
+ status = SUCCESS;
+ break;
+ }
+ tried++;
+ }
+ enumerator->destroy(enumerator);
+ if (status != SUCCESS)
+ {
+ if (!tried)
+ {
+ DBG1(DBG_IKE, "no XAuth secret found for '%Y' - '%Y'",
+ this->server, this->peer);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "none of %d found XAuth secrets for '%Y' - '%Y' "
+ "matched", tried, this->server, this->peer);
+ }
+ }
+ return status;
+}
+
+METHOD(xauth_method_t, get_identity, identification_t*,
+ private_xauth_generic_t *this)
+{
+ return this->peer;
+}
+
+METHOD(xauth_method_t, destroy, void,
+ private_xauth_generic_t *this)
+{
+ this->server->destroy(this->server);
+ this->peer->destroy(this->peer);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+xauth_generic_t *xauth_generic_create_peer(identification_t *server,
+ identification_t *peer)
+{
+ private_xauth_generic_t *this;
+
+ INIT(this,
+ .public = {
+ .xauth_method = {
+ .initiate = _initiate_peer,
+ .process = _process_peer,
+ .get_identity = _get_identity,
+ .destroy = _destroy,
+ },
+ },
+ .server = server->clone(server),
+ .peer = peer->clone(peer),
+ );
+
+ return &this->public;
+}
+
+/*
+ * Described in header.
+ */
+xauth_generic_t *xauth_generic_create_server(identification_t *server,
+ identification_t *peer)
+{
+ private_xauth_generic_t *this;
+
+ INIT(this,
+ .public = {
+ .xauth_method = {
+ .initiate = _initiate_server,
+ .process = _process_server,
+ .get_identity = _get_identity,
+ .destroy = _destroy,
+ },
+ },
+ .server = server->clone(server),
+ .peer = peer->clone(peer),
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/xauth_generic/xauth_generic.h b/src/libcharon/plugins/xauth_generic/xauth_generic.h
new file mode 100644
index 000000000..5773589cb
--- /dev/null
+++ b/src/libcharon/plugins/xauth_generic/xauth_generic.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2011 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup xauth_generic_i xauth_generic
+ * @{ @ingroup xauth_generic
+ */
+
+#ifndef XAUTH_GENERIC_H_
+#define XAUTH_GENERIC_H_
+
+typedef struct xauth_generic_t xauth_generic_t;
+
+#include <sa/xauth/xauth_method.h>
+
+/**
+ * Implementation of the xauth_method_t interface using cleartext secrets
+ * from any credential set.
+ */
+struct xauth_generic_t {
+
+ /**
+ * Implemented xauth_method_t interface.
+ */
+ xauth_method_t xauth_method;
+};
+
+/**
+ * Creates the generic XAuth method, acting as server.
+ *
+ * @param server ID of the XAuth server
+ * @param peer ID of the XAuth client
+ * @return xauth_generic_t object
+ */
+xauth_generic_t *xauth_generic_create_server(identification_t *server,
+ identification_t *peer);
+
+/**
+ * Creates the generic XAuth method, acting as peer.
+ *
+ * @param server ID of the XAuth server
+ * @param peer ID of the XAuth client
+ * @return xauth_generic_t object
+ */
+xauth_generic_t *xauth_generic_create_peer(identification_t *server,
+ identification_t *peer);
+
+#endif /** XAUTH_GENERIC_H_ @}*/
diff --git a/src/libcharon/plugins/xauth_generic/xauth_generic_plugin.c b/src/libcharon/plugins/xauth_generic/xauth_generic_plugin.c
new file mode 100644
index 000000000..a87084e20
--- /dev/null
+++ b/src/libcharon/plugins/xauth_generic/xauth_generic_plugin.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2011 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 "xauth_generic_plugin.h"
+#include "xauth_generic.h"
+
+#include <daemon.h>
+
+METHOD(plugin_t, get_name, char*,
+ xauth_generic_plugin_t *this)
+{
+ return "xauth-generic";
+}
+
+METHOD(plugin_t, get_features, int,
+ xauth_generic_plugin_t *this, plugin_feature_t *features[])
+{
+ static plugin_feature_t f[] = {
+ PLUGIN_CALLBACK(xauth_method_register, xauth_generic_create_server),
+ PLUGIN_PROVIDE(XAUTH_SERVER, "generic"),
+ PLUGIN_CALLBACK(xauth_method_register, xauth_generic_create_peer),
+ PLUGIN_PROVIDE(XAUTH_PEER, "generic"),
+ };
+ *features = f;
+ return countof(f);
+}
+
+METHOD(plugin_t, destroy, void,
+ xauth_generic_plugin_t *this)
+{
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *xauth_generic_plugin_create()
+{
+ xauth_generic_plugin_t *this;
+
+ INIT(this,
+ .plugin = {
+ .get_name = _get_name,
+ .get_features = _get_features,
+ .destroy = _destroy,
+ },
+ );
+
+ return &this->plugin;
+}
diff --git a/src/libcharon/plugins/xauth_generic/xauth_generic_plugin.h b/src/libcharon/plugins/xauth_generic/xauth_generic_plugin.h
new file mode 100644
index 000000000..426f806a7
--- /dev/null
+++ b/src/libcharon/plugins/xauth_generic/xauth_generic_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2011 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup xauth_generic xauth_generic
+ * @ingroup cplugins
+ *
+ * @defgroup xauth_generic_plugin xauth_generic_plugin
+ * @{ @ingroup xauth_generic
+ */
+
+#ifndef XAUTH_GENERIC_PLUGIN_H_
+#define XAUTH_GENERIC_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct xauth_generic_plugin_t xauth_generic_plugin_t;
+
+/**
+ * XAuth generic plugin using secrets defined in ipsec.secrets.
+ */
+struct xauth_generic_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** XAUTH_GENERIC_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/xauth_pam/Makefile.am b/src/libcharon/plugins/xauth_pam/Makefile.am
new file mode 100644
index 000000000..47521a3ff
--- /dev/null
+++ b/src/libcharon/plugins/xauth_pam/Makefile.am
@@ -0,0 +1,17 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-xauth-pam.la
+else
+plugin_LTLIBRARIES = libstrongswan-xauth-pam.la
+endif
+
+libstrongswan_xauth_pam_la_SOURCES = \
+ xauth_pam_plugin.h xauth_pam_plugin.c \
+ xauth_pam.h xauth_pam.c
+
+libstrongswan_xauth_pam_la_LDFLAGS = -module -avoid-version -lpam
diff --git a/src/libcharon/plugins/nm/Makefile.in b/src/libcharon/plugins/xauth_pam/Makefile.in
index d9ad2388e..c3514473c 100644
--- a/src/libcharon/plugins/nm/Makefile.in
+++ b/src/libcharon/plugins/xauth_pam/Makefile.in
@@ -34,7 +34,7 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-subdir = src/libcharon/plugins/nm
+subdir = src/libcharon/plugins/xauth_pam
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -74,17 +75,19 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
-am__DEPENDENCIES_1 =
-libstrongswan_nm_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
-am_libstrongswan_nm_la_OBJECTS = nm_plugin.lo nm_service.lo \
- nm_creds.lo nm_handler.lo
-libstrongswan_nm_la_OBJECTS = $(am_libstrongswan_nm_la_OBJECTS)
-libstrongswan_nm_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
- $(libstrongswan_nm_la_LDFLAGS) $(LDFLAGS) -o $@
-@MONOLITHIC_FALSE@am_libstrongswan_nm_la_rpath = -rpath $(plugindir)
-@MONOLITHIC_TRUE@am_libstrongswan_nm_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+libstrongswan_xauth_pam_la_LIBADD =
+am_libstrongswan_xauth_pam_la_OBJECTS = xauth_pam_plugin.lo \
+ xauth_pam.lo
+libstrongswan_xauth_pam_la_OBJECTS = \
+ $(am_libstrongswan_xauth_pam_la_OBJECTS)
+libstrongswan_xauth_pam_la_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_xauth_pam_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_xauth_pam_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_xauth_pam_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -97,8 +100,8 @@ CCLD = $(CC)
LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
-SOURCES = $(libstrongswan_nm_la_SOURCES)
-DIST_SOURCES = $(libstrongswan_nm_la_SOURCES)
+SOURCES = $(libstrongswan_xauth_pam_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_xauth_pam_la_SOURCES)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -110,6 +113,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -204,11 +208,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -225,11 +232,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -245,6 +253,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -254,7 +263,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -283,21 +291,16 @@ urandom_device = @urandom_device@
xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
- -I$(top_srcdir)/src/libcharon ${nm_CFLAGS}
-
-AM_CFLAGS = -rdynamic \
- -DNM_CA_DIR=\"${nm_ca_dir}\"
+ -I$(top_srcdir)/src/libcharon
-@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-nm.la
-@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-nm.la
-libstrongswan_nm_la_SOURCES = \
- nm_plugin.h nm_plugin.c \
- nm_service.h nm_service.c \
- nm_creds.h nm_creds.c \
- nm_handler.h nm_handler.c
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-xauth-pam.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-xauth-pam.la
+libstrongswan_xauth_pam_la_SOURCES = \
+ xauth_pam_plugin.h xauth_pam_plugin.c \
+ xauth_pam.h xauth_pam.c
-libstrongswan_nm_la_LDFLAGS = -module -avoid-version
-libstrongswan_nm_la_LIBADD = ${nm_LIBS}
+libstrongswan_xauth_pam_la_LDFLAGS = -module -avoid-version -lpam
all: all-am
.SUFFIXES:
@@ -311,9 +314,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/nm/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/xauth_pam/Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --gnu src/libcharon/plugins/nm/Makefile
+ $(AUTOMAKE) --gnu src/libcharon/plugins/xauth_pam/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
@@ -372,8 +375,8 @@ clean-pluginLTLIBRARIES:
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
-libstrongswan-nm.la: $(libstrongswan_nm_la_OBJECTS) $(libstrongswan_nm_la_DEPENDENCIES)
- $(libstrongswan_nm_la_LINK) $(am_libstrongswan_nm_la_rpath) $(libstrongswan_nm_la_OBJECTS) $(libstrongswan_nm_la_LIBADD) $(LIBS)
+libstrongswan-xauth-pam.la: $(libstrongswan_xauth_pam_la_OBJECTS) $(libstrongswan_xauth_pam_la_DEPENDENCIES)
+ $(libstrongswan_xauth_pam_la_LINK) $(am_libstrongswan_xauth_pam_la_rpath) $(libstrongswan_xauth_pam_la_OBJECTS) $(libstrongswan_xauth_pam_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -381,10 +384,8 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm_creds.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm_handler.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm_plugin.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm_service.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xauth_pam.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xauth_pam_plugin.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
diff --git a/src/libcharon/plugins/xauth_pam/xauth_pam.c b/src/libcharon/plugins/xauth_pam/xauth_pam.c
new file mode 100644
index 000000000..98c1a97a4
--- /dev/null
+++ b/src/libcharon/plugins/xauth_pam/xauth_pam.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 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 "xauth_pam.h"
+
+#include <daemon.h>
+#include <library.h>
+
+#include <security/pam_appl.h>
+
+typedef struct private_xauth_pam_t private_xauth_pam_t;
+
+/**
+ * Private data of an xauth_pam_t object.
+ */
+struct private_xauth_pam_t {
+
+ /**
+ * Public interface.
+ */
+ xauth_pam_t public;
+
+ /**
+ * ID of the peer
+ */
+ identification_t *peer;
+};
+
+METHOD(xauth_method_t, initiate, status_t,
+ private_xauth_pam_t *this, cp_payload_t **out)
+{
+ cp_payload_t *cp;
+
+ cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REQUEST);
+ cp->add_attribute(cp, configuration_attribute_create_chunk(
+ CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_NAME, chunk_empty));
+ cp->add_attribute(cp, configuration_attribute_create_chunk(
+ CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_PASSWORD, chunk_empty));
+ *out = cp;
+ return NEED_MORE;
+}
+
+/**
+ * PAM conv callback function
+ */
+static int auth_conv(int num_msg, const struct pam_message **msg,
+ struct pam_response **resp, char *password)
+{
+ struct pam_response *response;
+
+ if (num_msg != 1)
+ {
+ return PAM_CONV_ERR;
+ }
+ response = malloc(sizeof(struct pam_response));
+ response->resp = strdup(password);
+ response->resp_retcode = 0;
+ *resp = response;
+ return PAM_SUCCESS;
+}
+
+/**
+ * Authenticate a username/password using PAM
+ */
+static bool authenticate(char *service, char *user, char *password)
+{
+ pam_handle_t *pamh = NULL;
+ static struct pam_conv conv;
+ int ret;
+
+ conv.conv = (void*)auth_conv;
+ conv.appdata_ptr = password;
+
+ ret = pam_start(service, user, &conv, &pamh);
+ if (ret != PAM_SUCCESS)
+ {
+ DBG1(DBG_IKE, "XAuth pam_start for '%s' failed: %s",
+ user, pam_strerror(pamh, ret));
+ return FALSE;
+ }
+ ret = pam_authenticate(pamh, 0);
+ if (ret == PAM_SUCCESS)
+ {
+ ret = pam_acct_mgmt(pamh, 0);
+ if (ret != PAM_SUCCESS)
+ {
+ DBG1(DBG_IKE, "XAuth pam_acct_mgmt for '%s' failed: %s",
+ user, pam_strerror(pamh, ret));
+ }
+ }
+ else
+ {
+ DBG1(DBG_IKE, "XAuth pam_authenticate for '%s' failed: %s",
+ user, pam_strerror(pamh, ret));
+ }
+ pam_end(pamh, ret);
+ return ret == PAM_SUCCESS;
+}
+
+/**
+ * Convert configuration attribute content to a null-terminated string
+ */
+static void attr2string(char *buf, size_t len, chunk_t chunk)
+{
+ if (chunk.len && chunk.len < len)
+ {
+ snprintf(buf, len, "%.*s", (int)chunk.len, chunk.ptr);
+ }
+}
+
+METHOD(xauth_method_t, process, status_t,
+ private_xauth_pam_t *this, cp_payload_t *in, cp_payload_t **out)
+{
+ char *service, user[128] = "", pass[128] = "", *pos;
+ configuration_attribute_t *attr;
+ enumerator_t *enumerator;
+ chunk_t chunk;
+
+ enumerator = in->create_attribute_enumerator(in);
+ while (enumerator->enumerate(enumerator, &attr))
+ {
+ switch (attr->get_type(attr))
+ {
+ case XAUTH_USER_NAME:
+ /* trim to username part if email address given */
+ chunk = attr->get_chunk(attr);
+ pos = memchr(chunk.ptr, '@', chunk.len);
+ if (pos)
+ {
+ chunk.len = (u_char*)pos - chunk.ptr;
+ }
+ attr2string(user, sizeof(user), chunk);
+ break;
+ case XAUTH_USER_PASSWORD:
+ attr2string(pass, sizeof(pass), attr->get_chunk(attr));
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!user[0] || !pass[0])
+ {
+ DBG1(DBG_IKE, "peer did not respond to our XAuth request");
+ return FAILED;
+ }
+
+ this->peer->destroy(this->peer);
+ this->peer = identification_create_from_string(user);
+
+ /* Look for PAM service, with a legacy fallback for the eap-gtc plugin.
+ * Default to "login". */
+ service = lib->settings->get_str(lib->settings,
+ "%s.plugins.xauth-pam.pam_service",
+ lib->settings->get_str(lib->settings,
+ "%s.plugins.eap-gtc.pam_service",
+ "login", charon->name),
+ charon->name);
+
+ if (authenticate(service, user, pass))
+ {
+ DBG1(DBG_IKE, "PAM authentication of '%s' successful", user);
+ return SUCCESS;
+ }
+ return FAILED;
+}
+
+METHOD(xauth_method_t, get_identity, identification_t*,
+ private_xauth_pam_t *this)
+{
+ return this->peer;
+}
+
+METHOD(xauth_method_t, destroy, void,
+ private_xauth_pam_t *this)
+{
+ this->peer->destroy(this->peer);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+xauth_pam_t *xauth_pam_create_server(identification_t *server,
+ identification_t *peer)
+{
+ private_xauth_pam_t *this;
+
+ INIT(this,
+ .public = {
+ .xauth_method = {
+ .initiate = _initiate,
+ .process = _process,
+ .get_identity = _get_identity,
+ .destroy = _destroy,
+ },
+ },
+ .peer = peer->clone(peer),
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/xauth_pam/xauth_pam.h b/src/libcharon/plugins/xauth_pam/xauth_pam.h
new file mode 100644
index 000000000..f2d310c0d
--- /dev/null
+++ b/src/libcharon/plugins/xauth_pam/xauth_pam.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 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 xauth_pam_i xauth_pam
+ * @{ @ingroup xauth_pam
+ */
+
+#ifndef XAUTH_PAM_H_
+#define XAUTH_PAM_H_
+
+typedef struct xauth_pam_t xauth_pam_t;
+
+#include <sa/xauth/xauth_method.h>
+
+/**
+ * XAuth plugin using Pluggable Authentication Modules to verify credentials.
+ */
+struct xauth_pam_t {
+
+ /**
+ * Implemented xauth_method_t interface.
+ */
+ xauth_method_t xauth_method;
+};
+
+/**
+ * Creates the XAuth method using PAM, acting as server.
+ *
+ * @param server ID of the XAuth server
+ * @param peer ID of the XAuth client
+ * @return xauth_pam_t object
+ */
+xauth_pam_t *xauth_pam_create_server(identification_t *server,
+ identification_t *peer);
+
+#endif /** XAUTH_PAM_H_ @}*/
diff --git a/src/libcharon/plugins/xauth_pam/xauth_pam_plugin.c b/src/libcharon/plugins/xauth_pam/xauth_pam_plugin.c
new file mode 100644
index 000000000..b9ba0b5ac
--- /dev/null
+++ b/src/libcharon/plugins/xauth_pam/xauth_pam_plugin.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 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 "xauth_pam_plugin.h"
+#include "xauth_pam.h"
+
+#include <daemon.h>
+
+#ifndef CAP_AUDIT_WRITE
+#define CAP_AUDIT_WRITE 29
+#endif
+
+METHOD(plugin_t, get_name, char*,
+ xauth_pam_plugin_t *this)
+{
+ return "xauth-pam";
+}
+
+METHOD(plugin_t, get_features, int,
+ xauth_pam_plugin_t *this, plugin_feature_t *features[])
+{
+ static plugin_feature_t f[] = {
+ PLUGIN_CALLBACK(xauth_method_register, xauth_pam_create_server),
+ PLUGIN_PROVIDE(XAUTH_SERVER, "pam"),
+ };
+ *features = f;
+ return countof(f);
+}
+
+METHOD(plugin_t, destroy, void,
+ xauth_pam_plugin_t *this)
+{
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *xauth_pam_plugin_create()
+{
+ xauth_pam_plugin_t *this;
+
+ INIT(this,
+ .plugin = {
+ .get_name = _get_name,
+ .get_features = _get_features,
+ .destroy = _destroy,
+ },
+ );
+
+ /* required for PAM authentication */
+ charon->caps->keep(charon->caps, CAP_AUDIT_WRITE);
+
+ return &this->plugin;
+}
diff --git a/src/libcharon/plugins/xauth_pam/xauth_pam_plugin.h b/src/libcharon/plugins/xauth_pam/xauth_pam_plugin.h
new file mode 100644
index 000000000..b75268880
--- /dev/null
+++ b/src/libcharon/plugins/xauth_pam/xauth_pam_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 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 xauth_pam xauth_pam
+ * @ingroup cplugins
+ *
+ * @defgroup xauth_pam_plugin xauth_pam_plugin
+ * @{ @ingroup xauth_pam
+ */
+
+#ifndef XAUTH_PAM_PLUGIN_H_
+#define XAUTH_PAM_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct xauth_pam_plugin_t xauth_pam_plugin_t;
+
+/**
+ * XAuth plugin using Pluggable Authentication Modules to verify credentials.
+ */
+struct xauth_pam_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** XAUTH_PAM_PLUGIN_H_ @}*/
diff --git a/src/libcharon/processing/jobs/acquire_job.c b/src/libcharon/processing/jobs/acquire_job.c
index 2d836b002..207f534ba 100644
--- a/src/libcharon/processing/jobs/acquire_job.c
+++ b/src/libcharon/processing/jobs/acquire_job.c
@@ -53,12 +53,12 @@ METHOD(job_t, destroy, void,
free(this);
}
-METHOD(job_t, execute, void,
+METHOD(job_t, execute, job_requeue_t,
private_acquire_job_t *this)
{
charon->traps->acquire(charon->traps, this->reqid,
this->src_ts, this->dst_ts);
- destroy(this);
+ return JOB_REQUEUE_NONE;
}
METHOD(job_t, get_priority, job_priority_t,
diff --git a/src/libcharon/processing/jobs/adopt_children_job.c b/src/libcharon/processing/jobs/adopt_children_job.c
new file mode 100644
index 000000000..df5b70c0f
--- /dev/null
+++ b/src/libcharon/processing/jobs/adopt_children_job.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 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 "adopt_children_job.h"
+
+#include <daemon.h>
+#include <hydra.h>
+
+typedef struct private_adopt_children_job_t private_adopt_children_job_t;
+
+/**
+ * Private data of an adopt_children_job_t object.
+ */
+struct private_adopt_children_job_t {
+
+ /**
+ * Public adopt_children_job_t interface.
+ */
+ adopt_children_job_t public;
+
+ /**
+ * IKE_SA id to adopt children from
+ */
+ ike_sa_id_t *id;
+};
+
+METHOD(job_t, destroy, void,
+ private_adopt_children_job_t *this)
+{
+ this->id->destroy(this->id);
+ free(this);
+}
+
+METHOD(job_t, execute, job_requeue_t,
+ private_adopt_children_job_t *this)
+{
+ identification_t *my_id, *other_id, *xauth;
+ host_t *me, *other;
+ peer_cfg_t *cfg;
+ linked_list_t *children;
+ enumerator_t *enumerator, *childenum;
+ ike_sa_id_t *id;
+ ike_sa_t *ike_sa;
+ child_sa_t *child_sa;
+
+ ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, this->id);
+ if (ike_sa)
+ {
+ /* get what we need from new SA */
+ me = ike_sa->get_my_host(ike_sa);
+ me = me->clone(me);
+ other = ike_sa->get_other_host(ike_sa);
+ other = other->clone(other);
+ my_id = ike_sa->get_my_id(ike_sa);
+ my_id = my_id->clone(my_id);
+ other_id = ike_sa->get_other_id(ike_sa);
+ other_id = other_id->clone(other_id);
+ xauth = ike_sa->get_other_eap_id(ike_sa);
+ xauth = xauth->clone(xauth);
+ cfg = ike_sa->get_peer_cfg(ike_sa);
+ cfg->get_ref(cfg);
+
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+
+ /* find old SA to adopt children from */
+ children = linked_list_create();
+ enumerator = charon->ike_sa_manager->create_id_enumerator(
+ charon->ike_sa_manager, my_id, xauth,
+ other->get_family(other));
+ while (enumerator->enumerate(enumerator, &id))
+ {
+ if (id->equals(id, this->id))
+ { /* not from self */
+ continue;
+ }
+ ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, id);
+ if (ike_sa)
+ {
+ if ((ike_sa->get_state(ike_sa) == IKE_ESTABLISHED ||
+ ike_sa->get_state(ike_sa) == IKE_PASSIVE) &&
+ me->equals(me, ike_sa->get_my_host(ike_sa)) &&
+ other->equals(other, ike_sa->get_other_host(ike_sa)) &&
+ other_id->equals(other_id, ike_sa->get_other_id(ike_sa)) &&
+ cfg->equals(cfg, ike_sa->get_peer_cfg(ike_sa)))
+ {
+ childenum = ike_sa->create_child_sa_enumerator(ike_sa);
+ while (childenum->enumerate(childenum, &child_sa))
+ {
+ ike_sa->remove_child_sa(ike_sa, childenum);
+ children->insert_last(children, child_sa);
+ }
+ childenum->destroy(childenum);
+ DBG1(DBG_IKE, "detected reauth of existing IKE_SA, "
+ "adopting %d children", children->get_count(children));
+ ike_sa->set_state(ike_sa, IKE_DELETING);
+ charon->bus->ike_updown(charon->bus, ike_sa, FALSE);
+ charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager, ike_sa);
+ }
+ else
+ {
+ charon->ike_sa_manager->checkin(
+ charon->ike_sa_manager, ike_sa);
+ }
+ if (children->get_count(children))
+ {
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ me->destroy(me);
+ other->destroy(other);
+ my_id->destroy(my_id);
+ other_id->destroy(other_id);
+ xauth->destroy(xauth);
+ cfg->destroy(cfg);
+
+ if (children->get_count(children))
+ {
+ /* adopt children by new SA */
+ ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
+ this->id);
+ if (ike_sa)
+ {
+ while (children->remove_last(children,
+ (void**)&child_sa) == SUCCESS)
+ {
+ ike_sa->add_child_sa(ike_sa, child_sa);
+ }
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ }
+ }
+ children->destroy_offset(children, offsetof(child_sa_t, destroy));
+ }
+ return JOB_REQUEUE_NONE;
+}
+
+METHOD(job_t, get_priority, job_priority_t,
+ private_adopt_children_job_t *this)
+{
+ return JOB_PRIO_HIGH;
+}
+
+/**
+ * See header
+ */
+adopt_children_job_t *adopt_children_job_create(ike_sa_id_t *id)
+{
+ private_adopt_children_job_t *this;
+
+ INIT(this,
+ .public = {
+ .job_interface = {
+ .execute = _execute,
+ .get_priority = _get_priority,
+ .destroy = _destroy,
+ },
+ },
+ .id = id->clone(id),
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/processing/jobs/adopt_children_job.h b/src/libcharon/processing/jobs/adopt_children_job.h
new file mode 100644
index 000000000..073504abd
--- /dev/null
+++ b/src/libcharon/processing/jobs/adopt_children_job.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 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 adopt_children_job adopt_children_job
+ * @{ @ingroup cjobs
+ */
+
+#ifndef ADOPT_CHILDREN_JOB_H_
+#define ADOPT_CHILDREN_JOB_H_
+
+#include <library.h>
+#include <processing/jobs/job.h>
+#include <sa/ike_sa_id.h>
+
+typedef struct adopt_children_job_t adopt_children_job_t;
+
+/**
+ * Job adopting children after IKEv1 reauthentication from old SA.
+ */
+struct adopt_children_job_t {
+
+ /**
+ * Implements job_t.
+ */
+ job_t job_interface;
+};
+
+/**
+ * Create a adopt_children_job instance.
+ *
+ * @param id ike_sa_id_t of old ISAKMP SA to adopt children from
+ * @return job
+ */
+adopt_children_job_t *adopt_children_job_create(ike_sa_id_t *id);
+
+#endif /** ADOPT_CHILDREN_JOB_H_ @}*/
diff --git a/src/libcharon/processing/jobs/delete_child_sa_job.c b/src/libcharon/processing/jobs/delete_child_sa_job.c
index bd8bb9562..9afbac02b 100644
--- a/src/libcharon/processing/jobs/delete_child_sa_job.c
+++ b/src/libcharon/processing/jobs/delete_child_sa_job.c
@@ -44,6 +44,11 @@ struct private_delete_child_sa_job_t {
* inbound SPI of the CHILD_SA
*/
u_int32_t spi;
+
+ /**
+ * Delete for an expired CHILD_SA
+ */
+ bool expired;
};
METHOD(job_t, destroy, void,
@@ -52,7 +57,7 @@ METHOD(job_t, destroy, void,
free(this);
}
-METHOD(job_t, execute, void,
+METHOD(job_t, execute, job_requeue_t,
private_delete_child_sa_job_t *this)
{
ike_sa_t *ike_sa;
@@ -66,11 +71,11 @@ METHOD(job_t, execute, void,
}
else
{
- ike_sa->delete_child_sa(ike_sa, this->protocol, this->spi);
+ ike_sa->delete_child_sa(ike_sa, this->protocol, this->spi, this->expired);
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
}
- destroy(this);
+ return JOB_REQUEUE_NONE;
}
METHOD(job_t, get_priority, job_priority_t,
@@ -83,8 +88,7 @@ METHOD(job_t, get_priority, job_priority_t,
* Described in header
*/
delete_child_sa_job_t *delete_child_sa_job_create(u_int32_t reqid,
- protocol_id_t protocol,
- u_int32_t spi)
+ protocol_id_t protocol, u_int32_t spi, bool expired)
{
private_delete_child_sa_job_t *this;
@@ -99,6 +103,7 @@ delete_child_sa_job_t *delete_child_sa_job_create(u_int32_t reqid,
.reqid = reqid,
.protocol = protocol,
.spi = spi,
+ .expired = expired,
);
return &this->public;
diff --git a/src/libcharon/processing/jobs/delete_child_sa_job.h b/src/libcharon/processing/jobs/delete_child_sa_job.h
index fc0e2b518..be6d578bc 100644
--- a/src/libcharon/processing/jobs/delete_child_sa_job.h
+++ b/src/libcharon/processing/jobs/delete_child_sa_job.h
@@ -50,10 +50,10 @@ struct delete_child_sa_job_t {
* @param reqid reqid of the CHILD_SA, as used in kernel
* @param protocol protocol of the CHILD_SA
* @param spi security parameter index of the CHILD_SA
+ * @param expired TRUE if CHILD_SA already expired
* @return delete_child_sa_job_t object
*/
delete_child_sa_job_t *delete_child_sa_job_create(u_int32_t reqid,
- protocol_id_t protocol,
- u_int32_t spi);
+ protocol_id_t protocol, u_int32_t spi, bool expired);
#endif /** DELETE_CHILD_SA_JOB_H_ @}*/
diff --git a/src/libcharon/processing/jobs/delete_ike_sa_job.c b/src/libcharon/processing/jobs/delete_ike_sa_job.c
index c29b72230..08b41af8c 100644
--- a/src/libcharon/processing/jobs/delete_ike_sa_job.c
+++ b/src/libcharon/processing/jobs/delete_ike_sa_job.c
@@ -48,7 +48,7 @@ METHOD(job_t, destroy, void,
free(this);
}
-METHOD(job_t, execute, void,
+METHOD(job_t, execute, job_requeue_t,
private_delete_ike_sa_job_t *this)
{
ike_sa_t *ike_sa;
@@ -60,7 +60,7 @@ METHOD(job_t, execute, void,
if (ike_sa->get_state(ike_sa) == IKE_PASSIVE)
{
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
- return destroy(this);
+ return JOB_REQUEUE_NONE;
}
if (this->delete_if_established)
{
@@ -89,7 +89,7 @@ METHOD(job_t, execute, void,
}
}
}
- destroy(this);
+ return JOB_REQUEUE_NONE;
}
METHOD(job_t, get_priority, job_priority_t,
diff --git a/src/libcharon/processing/jobs/dpd_timeout_job.c b/src/libcharon/processing/jobs/dpd_timeout_job.c
new file mode 100644
index 000000000..91a76bbaf
--- /dev/null
+++ b/src/libcharon/processing/jobs/dpd_timeout_job.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stdlib.h>
+
+#include "dpd_timeout_job.h"
+
+#include <sa/ike_sa.h>
+#include <daemon.h>
+
+
+typedef struct private_dpd_timeout_job_t private_dpd_timeout_job_t;
+
+/**
+ * Private data
+ */
+struct private_dpd_timeout_job_t {
+
+ /**
+ * public dpd_timeout_job_t interface
+ */
+ dpd_timeout_job_t public;
+
+ /**
+ * IKE_SA identifier
+ */
+ ike_sa_id_t *ike_sa_id;
+
+ /**
+ * Timestamp of first DPD check
+ */
+ time_t check;
+};
+
+METHOD(job_t, destroy, void,
+ private_dpd_timeout_job_t *this)
+{
+ this->ike_sa_id->destroy(this->ike_sa_id);
+ free(this);
+}
+
+METHOD(job_t, execute, job_requeue_t,
+ private_dpd_timeout_job_t *this)
+{
+ time_t use_time, current;
+ enumerator_t *enumerator;
+ child_sa_t *child_sa;
+ ike_sa_t *ike_sa;
+
+ ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
+ this->ike_sa_id);
+ if (ike_sa)
+ {
+ use_time = ike_sa->get_statistic(ike_sa, STAT_INBOUND);
+
+ enumerator = ike_sa->create_child_sa_enumerator(ike_sa);
+ while (enumerator->enumerate(enumerator, &child_sa))
+ {
+ child_sa->get_usestats(child_sa, TRUE, &current, NULL);
+ use_time = max(use_time, current);
+ }
+ enumerator->destroy(enumerator);
+
+ /* check if no incoming packet during timeout, reestablish SA */
+ if (use_time < this->check)
+ {
+ DBG1(DBG_JOB, "DPD check timed out, enforcing DPD action");
+ ike_sa->reestablish(ike_sa);
+ charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
+ ike_sa);
+ }
+ else
+ {
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ }
+ }
+ return JOB_REQUEUE_NONE;
+}
+
+METHOD(job_t, get_priority, job_priority_t,
+ private_dpd_timeout_job_t *this)
+{
+ return JOB_PRIO_HIGH;
+}
+
+/*
+ * Described in header
+ */
+dpd_timeout_job_t *dpd_timeout_job_create(ike_sa_id_t *ike_sa_id)
+{
+ private_dpd_timeout_job_t *this;
+
+ INIT(this,
+ .public = {
+ .job_interface = {
+ .execute = _execute,
+ .get_priority = _get_priority,
+ .destroy = _destroy,
+ },
+ },
+ .ike_sa_id = ike_sa_id->clone(ike_sa_id),
+ .check = time_monotonic(NULL),
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/processing/jobs/dpd_timeout_job.h b/src/libcharon/processing/jobs/dpd_timeout_job.h
new file mode 100644
index 000000000..573eb192d
--- /dev/null
+++ b/src/libcharon/processing/jobs/dpd_timeout_job.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 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 dpd_timeout_job dpd_timeout_job
+ * @{ @ingroup cjobs
+ */
+
+#ifndef DPD_TIMEOUT_JOB_H_
+#define DPD_TIMEOUT_JOB_H_
+
+typedef struct dpd_timeout_job_t dpd_timeout_job_t;
+
+#include <library.h>
+#include <processing/jobs/job.h>
+#include <sa/ike_sa_id.h>
+
+/**
+ * Job enforcing DPD timeout.
+ *
+ * This job detects if a DPD response has been received during the DPD timeout
+ * interval, and if not, enforced the DPD action.
+ */
+struct dpd_timeout_job_t {
+
+ /**
+ * implements job_t interface
+ */
+ job_t job_interface;
+};
+
+/**
+ * Creates a DPD timeout job.
+ *
+ * @param ike_sa_id ike_sa_id_t, gets cloned
+ * @return initiate_ike_sa_job_t object
+ */
+dpd_timeout_job_t *dpd_timeout_job_create(ike_sa_id_t *ike_sa_id);
+
+#endif /** DPD_TIMEOUT_JOB_H_ @}*/
diff --git a/src/libcharon/processing/jobs/inactivity_job.c b/src/libcharon/processing/jobs/inactivity_job.c
index 251b9ab03..3c56b0cd7 100644
--- a/src/libcharon/processing/jobs/inactivity_job.c
+++ b/src/libcharon/processing/jobs/inactivity_job.c
@@ -51,11 +51,11 @@ METHOD(job_t, destroy, void,
free(this);
}
-METHOD(job_t, execute, void,
+METHOD(job_t, execute, job_requeue_t,
private_inactivity_job_t *this)
{
ike_sa_t *ike_sa;
- bool rescheduled = FALSE;
+ u_int32_t reschedule = 0;
ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
this->reqid, TRUE);
@@ -87,9 +87,7 @@ METHOD(job_t, execute, void,
}
else
{
- lib->scheduler->schedule_job(lib->scheduler,
- &this->public.job_interface, this->timeout - diff);
- rescheduled = TRUE;
+ reschedule = this->timeout - diff;
}
}
children++;
@@ -108,7 +106,7 @@ METHOD(job_t, execute, void,
{
DBG1(DBG_JOB, "deleting CHILD_SA after %d seconds "
"of inactivity", this->timeout);
- status = ike_sa->delete_child_sa(ike_sa, proto, delete);
+ status = ike_sa->delete_child_sa(ike_sa, proto, delete, FALSE);
}
}
if (status == DESTROY_ME)
@@ -121,10 +119,11 @@ METHOD(job_t, execute, void,
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
}
}
- if (!rescheduled)
+ if (reschedule)
{
- destroy(this);
+ return JOB_RESCHEDULE(reschedule);
}
+ return JOB_REQUEUE_NONE;
}
METHOD(job_t, get_priority, job_priority_t,
diff --git a/src/libcharon/processing/jobs/initiate_mediation_job.c b/src/libcharon/processing/jobs/initiate_mediation_job.c
index e52f3c6df..17ab83053 100644
--- a/src/libcharon/processing/jobs/initiate_mediation_job.c
+++ b/src/libcharon/processing/jobs/initiate_mediation_job.c
@@ -54,7 +54,7 @@ METHOD(job_t, destroy, void,
*/
static bool initiate_callback(private_initiate_mediation_job_t *this,
debug_t group, level_t level, ike_sa_t *ike_sa,
- char *format, va_list args)
+ char *message)
{
if (ike_sa && !this->mediation_sa_id)
{
@@ -64,7 +64,7 @@ static bool initiate_callback(private_initiate_mediation_job_t *this,
return TRUE;
}
-METHOD(job_t, initiate, void,
+METHOD(job_t, initiate, job_requeue_t,
private_initiate_mediation_job_t *this)
{
ike_sa_t *mediated_sa, *mediation_sa;
@@ -93,8 +93,7 @@ METHOD(job_t, initiate, void,
mediated_cfg->destroy(mediated_cfg);
mediation_cfg->destroy(mediation_cfg);
enumerator->destroy(enumerator);
- destroy(this);
- return;
+ return JOB_REQUEUE_NONE;
}
enumerator->destroy(enumerator);
@@ -115,8 +114,7 @@ METHOD(job_t, initiate, void,
charon->ike_sa_manager->checkin(
charon->ike_sa_manager, mediated_sa);
}
- destroy(this);
- return;
+ return JOB_REQUEUE_NONE;
}
/* we need an additional reference because initiate consumes one */
mediation_cfg->get_ref(mediation_cfg);
@@ -134,8 +132,7 @@ METHOD(job_t, initiate, void,
charon->ike_sa_manager->checkin_and_destroy(
charon->ike_sa_manager, mediated_sa);
}
- destroy(this);
- return;
+ return JOB_REQUEUE_NONE;
}
mediation_cfg->destroy(mediation_cfg);
@@ -157,18 +154,17 @@ METHOD(job_t, initiate, void,
charon->ike_sa_manager->checkin_and_destroy(
charon->ike_sa_manager, mediated_sa);
}
- destroy(this);
- return;
+ return JOB_REQUEUE_NONE;
}
charon->ike_sa_manager->checkin(charon->ike_sa_manager,
mediation_sa);
}
mediated_cfg->destroy(mediated_cfg);
}
- destroy(this);
+ return JOB_REQUEUE_NONE;
}
-METHOD(job_t, reinitiate, void,
+METHOD(job_t, reinitiate, job_requeue_t,
private_initiate_mediation_job_t *this)
{
ike_sa_t *mediated_sa, *mediation_sa;
@@ -205,8 +201,7 @@ METHOD(job_t, reinitiate, void,
charon->ike_sa_manager,
mediated_sa);
}
- destroy(this);
- return;
+ return JOB_REQUEUE_NONE;
}
charon->ike_sa_manager->checkin(charon->ike_sa_manager,
mediation_sa);
@@ -214,7 +209,7 @@ METHOD(job_t, reinitiate, void,
mediated_cfg->destroy(mediated_cfg);
}
- destroy(this);
+ return JOB_REQUEUE_NONE;
}
METHOD(job_t, get_priority, job_priority_t,
diff --git a/src/libcharon/processing/jobs/mediation_job.c b/src/libcharon/processing/jobs/mediation_job.c
index 6f02f2a0a..759aad003 100644
--- a/src/libcharon/processing/jobs/mediation_job.c
+++ b/src/libcharon/processing/jobs/mediation_job.c
@@ -77,7 +77,7 @@ METHOD(job_t, destroy, void,
free(this);
}
-METHOD(job_t, execute, void,
+METHOD(job_t, execute, job_requeue_t,
private_mediation_job_t *this)
{
ike_sa_id_t *target_sa_id;
@@ -98,8 +98,7 @@ METHOD(job_t, execute, void,
DBG1(DBG_JOB, "callback for '%Y' to '%Y' failed",
this->source, this->target);
charon->ike_sa_manager->checkin(charon->ike_sa_manager, target_sa);
- destroy(this);
- return;
+ return JOB_REQUEUE_NONE;
}
}
else
@@ -112,8 +111,7 @@ METHOD(job_t, execute, void,
this->source, this->target);
charon->ike_sa_manager->checkin(charon->ike_sa_manager, target_sa);
/* FIXME: notify the initiator */
- destroy(this);
- return;
+ return JOB_REQUEUE_NONE;
}
}
@@ -130,7 +128,7 @@ METHOD(job_t, execute, void,
DBG1(DBG_JOB, "mediation between '%Y' and '%Y' failed: "
"peer is not online anymore", this->source, this->target);
}
- destroy(this);
+ return JOB_REQUEUE_NONE;
}
METHOD(job_t, get_priority, job_priority_t,
diff --git a/src/libcharon/processing/jobs/migrate_job.c b/src/libcharon/processing/jobs/migrate_job.c
index eb10e2e46..2ebfc6714 100644
--- a/src/libcharon/processing/jobs/migrate_job.c
+++ b/src/libcharon/processing/jobs/migrate_job.c
@@ -67,7 +67,7 @@ METHOD(job_t, destroy, void,
free(this);
}
-METHOD(job_t, execute, void,
+METHOD(job_t, execute, job_requeue_t,
private_migrate_job_t *this)
{
ike_sa_t *ike_sa = NULL;
@@ -79,9 +79,10 @@ METHOD(job_t, execute, void,
}
if (ike_sa)
{
- enumerator_t *children;
+ enumerator_t *children, *enumerator;
child_sa_t *child_sa;
host_t *host;
+ linked_list_t *vips;
children = ike_sa->create_child_sa_enumerator(ike_sa);
while (children->enumerate(children, (void**)&child_sa))
@@ -97,27 +98,35 @@ METHOD(job_t, execute, void,
ike_sa->set_kmaddress(ike_sa, this->local, this->remote);
host = this->local->clone(this->local);
- host->set_port(host, IKEV2_UDP_PORT);
+ host->set_port(host, charon->socket->get_port(charon->socket, FALSE));
ike_sa->set_my_host(ike_sa, host);
host = this->remote->clone(this->remote);
host->set_port(host, IKEV2_UDP_PORT);
ike_sa->set_other_host(ike_sa, host);
- if (child_sa->update(child_sa, this->local, this->remote,
- ike_sa->get_virtual_ip(ike_sa, TRUE),
+ vips = linked_list_create();
+ enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, TRUE);
+ while (enumerator->enumerate(enumerator, &host))
+ {
+ vips->insert_last(vips, host);
+ }
+ enumerator->destroy(enumerator);
+
+ if (child_sa->update(child_sa, this->local, this->remote, vips,
ike_sa->has_condition(ike_sa, COND_NAT_ANY)) == NOT_SUPPORTED)
{
ike_sa->rekey_child_sa(ike_sa, child_sa->get_protocol(child_sa),
child_sa->get_spi(child_sa, TRUE));
}
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ vips->destroy(vips);
}
else
{
DBG1(DBG_JOB, "no CHILD_SA found with reqid {%d}", this->reqid);
}
- destroy(this);
+ return JOB_REQUEUE_NONE;
}
METHOD(job_t, get_priority, job_priority_t,
diff --git a/src/libcharon/processing/jobs/process_message_job.c b/src/libcharon/processing/jobs/process_message_job.c
index a4924d001..71a2cb45d 100644
--- a/src/libcharon/processing/jobs/process_message_job.c
+++ b/src/libcharon/processing/jobs/process_message_job.c
@@ -42,7 +42,7 @@ METHOD(job_t, destroy, void,
free(this);
}
-METHOD(job_t, execute, void,
+METHOD(job_t, execute, job_requeue_t,
private_process_message_job_t *this)
{
ike_sa_t *ike_sa;
@@ -59,8 +59,7 @@ METHOD(job_t, execute, void,
this->message->get_source(this->message),
this->message->get_destination(this->message));
charon->connect_manager->process_check(charon->connect_manager, this->message);
- destroy(this);
- return;
+ return JOB_REQUEUE_NONE;
}
#endif /* ME */
@@ -81,7 +80,7 @@ METHOD(job_t, execute, void,
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
}
}
- destroy(this);
+ return JOB_REQUEUE_NONE;
}
METHOD(job_t, get_priority, job_priority_t,
diff --git a/src/libcharon/processing/jobs/rekey_child_sa_job.c b/src/libcharon/processing/jobs/rekey_child_sa_job.c
index 5855f1bc9..1bf8dc0cb 100644
--- a/src/libcharon/processing/jobs/rekey_child_sa_job.c
+++ b/src/libcharon/processing/jobs/rekey_child_sa_job.c
@@ -51,7 +51,7 @@ METHOD(job_t, destroy, void,
free(this);
}
-METHOD(job_t, execute, void,
+METHOD(job_t, execute, job_requeue_t,
private_rekey_child_sa_job_t *this)
{
ike_sa_t *ike_sa;
@@ -68,7 +68,7 @@ METHOD(job_t, execute, void,
ike_sa->rekey_child_sa(ike_sa, this->protocol, this->spi);
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
}
- destroy(this);
+ return JOB_REQUEUE_NONE;
}
METHOD(job_t, get_priority, job_priority_t,
diff --git a/src/libcharon/processing/jobs/rekey_ike_sa_job.c b/src/libcharon/processing/jobs/rekey_ike_sa_job.c
index 5366195fd..712c7c2c1 100644
--- a/src/libcharon/processing/jobs/rekey_ike_sa_job.c
+++ b/src/libcharon/processing/jobs/rekey_ike_sa_job.c
@@ -46,7 +46,7 @@ METHOD(job_t, destroy, void,
free(this);
}
-METHOD(job_t, execute, void,
+METHOD(job_t, execute, job_requeue_t,
private_rekey_ike_sa_job_t *this)
{
ike_sa_t *ike_sa;
@@ -78,7 +78,7 @@ METHOD(job_t, execute, void,
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
}
}
- destroy(this);
+ return JOB_REQUEUE_NONE;
}
METHOD(job_t, get_priority, job_priority_t,
diff --git a/src/libcharon/processing/jobs/retransmit_job.c b/src/libcharon/processing/jobs/retransmit_job.c
index 050f7005a..48c326804 100644
--- a/src/libcharon/processing/jobs/retransmit_job.c
+++ b/src/libcharon/processing/jobs/retransmit_job.c
@@ -47,7 +47,7 @@ METHOD(job_t, destroy, void,
free(this);
}
-METHOD(job_t, execute, void,
+METHOD(job_t, execute, job_requeue_t,
private_retransmit_job_t *this)
{
ike_sa_t *ike_sa;
@@ -67,7 +67,7 @@ METHOD(job_t, execute, void,
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
}
}
- destroy(this);
+ return JOB_REQUEUE_NONE;
}
METHOD(job_t, get_priority, job_priority_t,
diff --git a/src/libcharon/processing/jobs/retry_initiate_job.c b/src/libcharon/processing/jobs/retry_initiate_job.c
new file mode 100644
index 000000000..1cdc3058a
--- /dev/null
+++ b/src/libcharon/processing/jobs/retry_initiate_job.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2012 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 "retry_initiate_job.h"
+
+#include <daemon.h>
+
+typedef struct private_retry_initiate_job_t private_retry_initiate_job_t;
+
+/**
+ * Private data of an retry_initiate_job_t object.
+ */
+struct private_retry_initiate_job_t {
+ /**
+ * Public retry_initiate_job_t interface.
+ */
+ retry_initiate_job_t public;
+
+ /**
+ * ID of the IKE_SA to re-initiate
+ */
+ ike_sa_id_t *ike_sa_id;
+};
+
+METHOD(job_t, destroy, void,
+ private_retry_initiate_job_t *this)
+{
+ this->ike_sa_id->destroy(this->ike_sa_id);
+ free(this);
+}
+
+METHOD(job_t, execute, job_requeue_t,
+ private_retry_initiate_job_t *this)
+{
+ ike_sa_t *ike_sa;
+
+ ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
+ this->ike_sa_id);
+ if (ike_sa == NULL)
+ {
+ DBG2(DBG_JOB, "IKE_SA to initiate not found");
+ }
+ else
+ {
+ if (ike_sa->retry_initiate(ike_sa) == DESTROY_ME)
+ {
+ charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
+ ike_sa);
+ }
+ else
+ {
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ }
+ }
+ return JOB_REQUEUE_NONE;
+}
+
+METHOD(job_t, get_priority, job_priority_t,
+ private_retry_initiate_job_t *this)
+{
+ return JOB_PRIO_HIGH;
+}
+
+/*
+ * Described in header
+ */
+retry_initiate_job_t *retry_initiate_job_create(ike_sa_id_t *ike_sa_id)
+{
+ private_retry_initiate_job_t *this;
+
+ INIT(this,
+ .public = {
+ .job_interface = {
+ .execute = _execute,
+ .get_priority = _get_priority,
+ .destroy = _destroy,
+ },
+ },
+ .ike_sa_id = ike_sa_id->clone(ike_sa_id),
+ );
+
+ return &(this->public);
+}
diff --git a/src/libcharon/processing/jobs/retry_initiate_job.h b/src/libcharon/processing/jobs/retry_initiate_job.h
new file mode 100644
index 000000000..29f79f23b
--- /dev/null
+++ b/src/libcharon/processing/jobs/retry_initiate_job.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup retry_initiate_job retry_initiate_job
+ * @{ @ingroup cjobs
+ */
+
+#ifndef RETRY_INITIATE_JOB_H_
+#define RETRY_INITIATE_JOB_H_
+
+typedef struct retry_initiate_job_t retry_initiate_job_t;
+
+#include <library.h>
+#include <sa/ike_sa_id.h>
+#include <processing/jobs/job.h>
+
+/**
+ * This job retries initiating an IKE_SA in case of e.g. a failed DNS lookup.
+ */
+struct retry_initiate_job_t {
+ /**
+ * The job_t interface.
+ */
+ job_t job_interface;
+};
+
+/**
+ * Creates a retry_initiate_job_t object.
+ *
+ * @param ike_sa_id ID of the IKE_SA to initiate
+ * @return retry_initiate_job_t object
+ */
+retry_initiate_job_t *retry_initiate_job_create(ike_sa_id_t *ike_sa_id);
+
+#endif /** RETRY_INITIATE_JOB_H_ @}*/
diff --git a/src/libcharon/processing/jobs/roam_job.c b/src/libcharon/processing/jobs/roam_job.c
index 951ac5ad3..0af4c6c39 100644
--- a/src/libcharon/processing/jobs/roam_job.c
+++ b/src/libcharon/processing/jobs/roam_job.c
@@ -44,7 +44,7 @@ METHOD(job_t, destroy, void,
free(this);
}
-METHOD(job_t, execute, void,
+METHOD(job_t, execute, job_requeue_t,
private_roam_job_t *this)
{
ike_sa_t *ike_sa;
@@ -82,8 +82,7 @@ METHOD(job_t, execute, void,
id->destroy(id);
}
list->destroy(list);
-
- destroy(this);
+ return JOB_REQUEUE_NONE;
}
METHOD(job_t, get_priority, job_priority_t,
diff --git a/src/libcharon/processing/jobs/send_dpd_job.c b/src/libcharon/processing/jobs/send_dpd_job.c
index ab00d013d..d2f38b803 100644
--- a/src/libcharon/processing/jobs/send_dpd_job.c
+++ b/src/libcharon/processing/jobs/send_dpd_job.c
@@ -45,7 +45,7 @@ METHOD(job_t, destroy, void,
free(this);
}
-METHOD(job_t, execute, void,
+METHOD(job_t, execute, job_requeue_t,
private_send_dpd_job_t *this)
{
ike_sa_t *ike_sa;
@@ -63,7 +63,7 @@ METHOD(job_t, execute, void,
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
}
}
- destroy(this);
+ return JOB_REQUEUE_NONE;
}
METHOD(job_t, get_priority, job_priority_t,
diff --git a/src/libcharon/processing/jobs/send_keepalive_job.c b/src/libcharon/processing/jobs/send_keepalive_job.c
index 5e128d478..3e3477679 100644
--- a/src/libcharon/processing/jobs/send_keepalive_job.c
+++ b/src/libcharon/processing/jobs/send_keepalive_job.c
@@ -45,7 +45,7 @@ METHOD(job_t, destroy, void,
free(this);
}
-METHOD(job_t, execute, void,
+METHOD(job_t, execute, job_requeue_t,
private_send_keepalive_job_t *this)
{
ike_sa_t *ike_sa;
@@ -57,7 +57,7 @@ METHOD(job_t, execute, void,
ike_sa->send_keepalive(ike_sa);
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
}
- destroy(this);
+ return JOB_REQUEUE_NONE;
}
METHOD(job_t, get_priority, job_priority_t,
diff --git a/src/libcharon/processing/jobs/start_action_job.c b/src/libcharon/processing/jobs/start_action_job.c
index b65181ef8..bc4aaf6d6 100644
--- a/src/libcharon/processing/jobs/start_action_job.c
+++ b/src/libcharon/processing/jobs/start_action_job.c
@@ -36,7 +36,7 @@ METHOD(job_t, destroy, void,
free(this);
}
-METHOD(job_t, execute, void,
+METHOD(job_t, execute, job_requeue_t,
private_start_action_job_t *this)
{
enumerator_t *enumerator, *children;
@@ -46,14 +46,9 @@ METHOD(job_t, execute, void,
char *name;
enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
- NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL, IKE_ANY);
while (enumerator->enumerate(enumerator, &peer_cfg))
{
- if (peer_cfg->get_ike_version(peer_cfg) != 2)
- {
- continue;
- }
-
children = peer_cfg->create_child_cfg_enumerator(peer_cfg);
while (children->enumerate(children, &child_cfg))
{
@@ -88,7 +83,7 @@ METHOD(job_t, execute, void,
children->destroy(children);
}
enumerator->destroy(enumerator);
- destroy(this);
+ return JOB_REQUEUE_NONE;
}
METHOD(job_t, get_priority, job_priority_t,
diff --git a/src/libcharon/processing/jobs/update_sa_job.c b/src/libcharon/processing/jobs/update_sa_job.c
index c4f6e4782..694318522 100644
--- a/src/libcharon/processing/jobs/update_sa_job.c
+++ b/src/libcharon/processing/jobs/update_sa_job.c
@@ -50,7 +50,7 @@ METHOD(job_t, destroy, void,
free(this);
}
-METHOD(job_t, execute, void,
+METHOD(job_t, execute, job_requeue_t,
private_update_sa_job_t *this)
{
ike_sa_t *ike_sa;
@@ -71,7 +71,7 @@ METHOD(job_t, execute, void,
}
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
}
- destroy(this);
+ return JOB_REQUEUE_NONE;
}
METHOD(job_t, get_priority, job_priority_t,
diff --git a/src/libcharon/sa/authenticators/authenticator.c b/src/libcharon/sa/authenticator.c
index 9ffe661cc..a32b6ab12 100644
--- a/src/libcharon/sa/authenticators/authenticator.c
+++ b/src/libcharon/sa/authenticator.c
@@ -18,9 +18,12 @@
#include "authenticator.h"
-#include <sa/authenticators/pubkey_authenticator.h>
-#include <sa/authenticators/psk_authenticator.h>
-#include <sa/authenticators/eap_authenticator.h>
+#include <sa/ikev2/authenticators/pubkey_authenticator.h>
+#include <sa/ikev2/authenticators/psk_authenticator.h>
+#include <sa/ikev2/authenticators/eap_authenticator.h>
+#include <sa/ikev1/authenticators/psk_v1_authenticator.h>
+#include <sa/ikev1/authenticators/pubkey_v1_authenticator.h>
+#include <sa/ikev1/authenticators/hybrid_authenticator.h>
#include <encoding/payloads/auth_payload.h>
@@ -33,7 +36,17 @@ ENUM_NEXT(auth_method_names, AUTH_ECDSA_256, AUTH_GSPM, AUTH_DSS,
"ECDSA-384 signature",
"ECDSA-521 signature",
"secure password method");
-ENUM_END(auth_method_names, AUTH_GSPM);
+ENUM_NEXT(auth_method_names, AUTH_XAUTH_INIT_PSK, AUTH_HYBRID_RESP_RSA, AUTH_GSPM,
+ "XAuthInitPSK",
+ "XAuthRespPSK",
+ "XAuthInitRSA",
+ "XauthRespRSA",
+ "HybridInitRSA",
+ "HybridRespRSA",
+);
+ENUM_END(auth_method_names, AUTH_HYBRID_RESP_RSA);
+
+#ifdef USE_IKEV2
/**
* Described in header.
@@ -96,3 +109,46 @@ authenticator_t *authenticator_create_verifier(
}
}
+#endif /* USE_IKEV2 */
+
+#ifdef USE_IKEV1
+
+/**
+ * Described in header.
+ */
+authenticator_t *authenticator_create_v1(ike_sa_t *ike_sa, bool initiator,
+ auth_method_t auth_method, diffie_hellman_t *dh,
+ chunk_t dh_value, chunk_t sa_payload,
+ chunk_t id_payload)
+{
+ switch (auth_method)
+ {
+ case AUTH_PSK:
+ case AUTH_XAUTH_INIT_PSK:
+ case AUTH_XAUTH_RESP_PSK:
+ return (authenticator_t*)psk_v1_authenticator_create(ike_sa,
+ initiator, dh, dh_value, sa_payload,
+ id_payload, FALSE);
+ case AUTH_RSA:
+ case AUTH_XAUTH_INIT_RSA:
+ case AUTH_XAUTH_RESP_RSA:
+ return (authenticator_t*)pubkey_v1_authenticator_create(ike_sa,
+ initiator, dh, dh_value, sa_payload,
+ id_payload, KEY_RSA);
+ case AUTH_ECDSA_256:
+ case AUTH_ECDSA_384:
+ case AUTH_ECDSA_521:
+ return (authenticator_t*)pubkey_v1_authenticator_create(ike_sa,
+ initiator, dh, dh_value, sa_payload,
+ id_payload, KEY_ECDSA);
+ case AUTH_HYBRID_INIT_RSA:
+ case AUTH_HYBRID_RESP_RSA:
+ return (authenticator_t*)hybrid_authenticator_create(ike_sa,
+ initiator, dh, dh_value, sa_payload,
+ id_payload);
+ default:
+ return NULL;
+ }
+}
+
+#endif /* USE_IKEV1 */
diff --git a/src/libcharon/sa/authenticators/authenticator.h b/src/libcharon/sa/authenticator.h
index 5042e4a73..914f42d9d 100644
--- a/src/libcharon/sa/authenticators/authenticator.h
+++ b/src/libcharon/sa/authenticator.h
@@ -17,7 +17,7 @@
/**
* @defgroup authenticator authenticator
- * @{ @ingroup authenticators
+ * @{ @ingroup sa
*/
#ifndef AUTHENTICATOR_H_
@@ -34,6 +34,12 @@ typedef struct authenticator_t authenticator_t;
* Method to use for authentication, as defined in IKEv2.
*/
enum auth_method_t {
+
+ /**
+ * No authentication used.
+ */
+ AUTH_NONE = 0,
+
/**
* Computed as specified in section 2.15 of RFC using
* an RSA private key over a PKCS#1 padded hash.
@@ -73,6 +79,35 @@ enum auth_method_t {
*/
AUTH_GSPM = 12,
+ /**
+ * IKEv1 initiator XAUTH with PSK, outside of IANA range
+ */
+ AUTH_XAUTH_INIT_PSK = 256,
+
+ /**
+ * IKEv1 responder XAUTH with PSK, outside of IANA range
+ */
+ AUTH_XAUTH_RESP_PSK,
+
+ /**
+ * IKEv1 initiator XAUTH with RSA, outside of IANA range
+ */
+ AUTH_XAUTH_INIT_RSA,
+
+ /**
+ * IKEv1 responder XAUTH with RSA, outside of IANA range
+ */
+ AUTH_XAUTH_RESP_RSA,
+
+ /**
+ * IKEv1 initiator XAUTH, responder RSA, outside of IANA range
+ */
+ AUTH_HYBRID_INIT_RSA,
+
+ /**
+ * IKEv1 responder XAUTH, initiator RSA, outside of IANA range
+ */
+ AUTH_HYBRID_RESP_RSA,
};
/**
@@ -128,7 +163,7 @@ struct authenticator_t {
};
/**
- * Create an authenticator to build signatures.
+ * Create an IKEv2 authenticator to build signatures.
*
* @param ike_sa associated ike_sa
* @param cfg authentication configuration
@@ -146,7 +181,7 @@ authenticator_t *authenticator_create_builder(
char reserved[3]);
/**
- * Create an authenticator to verify signatures.
+ * Create an IKEv2 authenticator to verify signatures.
*
* @param ike_sa associated ike_sa
* @param message message containing authentication data
@@ -163,4 +198,26 @@ authenticator_t *authenticator_create_verifier(
chunk_t received_init, chunk_t sent_init,
char reserved[3]);
+/**
+ * Create an IKEv1 authenticator to build and verify signatures or hash
+ * payloads.
+ *
+ * @note Due to the fixed ID, these authenticators can only be used in one
+ * direction at a time.
+ *
+ * @param ike_sa associated IKE_SA
+ * @param initiator TRUE if we are the IKE_SA initiator
+ * @param auth_method negotiated authentication method to use
+ * @param dh diffie hellman key exchange
+ * @param dh_value others public diffie hellman value
+ * @param sa_payload generated SA payload data, without payload header
+ * @param id_payload encoded ID payload of peer to authenticate or verify
+ * without payload header (gets owned)
+ * @return authenticator, NULL if not supported
+ */
+authenticator_t *authenticator_create_v1(ike_sa_t *ike_sa, bool initiator,
+ auth_method_t auth_method, diffie_hellman_t *dh,
+ chunk_t dh_value, chunk_t sa_payload,
+ chunk_t id_payload);
+
#endif /** AUTHENTICATOR_H_ @}*/
diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c
index 2130a5998..1245734c9 100644
--- a/src/libcharon/sa/child_sa.c
+++ b/src/libcharon/sa/child_sa.c
@@ -124,6 +124,11 @@ struct private_child_sa_t {
child_sa_state_t state;
/**
+ * TRUE if this CHILD_SA is used to install trap policies
+ */
+ bool trap;
+
+ /**
* Specifies if UDP encapsulation is enabled (NAT traversal)
*/
bool encap;
@@ -526,6 +531,16 @@ METHOD(child_sa_t, get_usestats, void,
}
}
+METHOD(child_sa_t, get_mark, mark_t,
+ private_child_sa_t *this, bool inbound)
+{
+ if (inbound)
+ {
+ return this->mark_in;
+ }
+ return this->mark_out;
+}
+
METHOD(child_sa_t, get_lifetime, time_t,
private_child_sa_t *this, bool hard)
{
@@ -617,7 +632,14 @@ METHOD(child_sa_t, install, status_t,
now = time_monotonic(NULL);
if (lifetime->time.rekey)
{
- this->rekey_time = now + lifetime->time.rekey;
+ if (this->rekey_time)
+ {
+ this->rekey_time = min(this->rekey_time, now + lifetime->time.rekey);
+ }
+ else
+ {
+ this->rekey_time = now + lifetime->time.rekey;
+ }
}
if (lifetime->time.life)
{
@@ -757,8 +779,11 @@ METHOD(child_sa_t, add_policies, status_t,
other_sa.ah.spi = this->other_spi;
}
- priority = this->state == CHILD_CREATED ? POLICY_PRIORITY_ROUTED
- : POLICY_PRIORITY_DEFAULT;
+ /* if we're not in state CHILD_INSTALLING (i.e. if there is no SAD
+ * entry) we install a trap policy */
+ this->trap = this->state == CHILD_CREATED;
+ priority = this->trap ? POLICY_PRIORITY_ROUTED
+ : POLICY_PRIORITY_DEFAULT;
/* enumerate pairs of traffic selectors */
enumerator = create_policy_enumerator(this);
@@ -787,16 +812,25 @@ METHOD(child_sa_t, add_policies, status_t,
enumerator->destroy(enumerator);
}
- if (status == SUCCESS && this->state == CHILD_CREATED)
- { /* switch to routed state if no SAD entry set up */
+ if (status == SUCCESS && this->trap)
+ {
set_state(this, CHILD_ROUTED);
}
return status;
}
+/**
+ * Callback to reinstall a virtual IP
+ */
+static void reinstall_vip(host_t *vip, host_t *me)
+{
+ hydra->kernel_interface->del_ip(hydra->kernel_interface, vip);
+ hydra->kernel_interface->add_ip(hydra->kernel_interface, vip, me);
+}
+
METHOD(child_sa_t, update, status_t,
- private_child_sa_t *this, host_t *me, host_t *other, host_t *vip,
- bool encap)
+ private_child_sa_t *this, host_t *me, host_t *other, linked_list_t *vips,
+ bool encap)
{
child_sa_state_t old;
bool transport_proxy_mode;
@@ -902,13 +936,7 @@ METHOD(child_sa_t, update, status_t,
/* we reinstall the virtual IP to handle interface roaming
* correctly */
- if (vip)
- {
- hydra->kernel_interface->del_ip(hydra->kernel_interface,
- vip);
- hydra->kernel_interface->add_ip(hydra->kernel_interface,
- vip, me);
- }
+ vips->invoke_function(vips, (void*)reinstall_vip, me);
/* reinstall updated policies */
install_policies_internal(this, me, other, my_ts, other_ts,
@@ -960,8 +988,7 @@ METHOD(child_sa_t, destroy, void,
traffic_selector_t *my_ts, *other_ts;
policy_priority_t priority;
- priority = this->state == CHILD_ROUTED ? POLICY_PRIORITY_ROUTED
- : POLICY_PRIORITY_DEFAULT;
+ priority = this->trap ? POLICY_PRIORITY_ROUTED : POLICY_PRIORITY_DEFAULT;
set_state(this, CHILD_DESTROYING);
@@ -1038,6 +1065,7 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
.set_proposal = _set_proposal,
.get_lifetime = _get_lifetime,
.get_usestats = _get_usestats,
+ .get_mark = _get_mark,
.has_encap = _has_encap,
.get_ipcomp = _get_ipcomp,
.set_ipcomp = _set_ipcomp,
@@ -1079,6 +1107,15 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
this->reqid = rekey ? rekey : ++reqid;
}
+ if (this->mark_in.value == MARK_REQID)
+ {
+ this->mark_in.value = this->reqid;
+ }
+ if (this->mark_out.value == MARK_REQID)
+ {
+ this->mark_out.value = this->reqid;
+ }
+
/* MIPv6 proxy transport mode sets SA endpoints to TS hosts */
if (config->get_mode(config) == MODE_TRANSPORT &&
config->use_proxy_mode(config))
@@ -1088,12 +1125,14 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
chunk_t addr;
host_t *host;
enumerator_t *enumerator;
- linked_list_t *my_ts_list, *other_ts_list;
+ linked_list_t *my_ts_list, *other_ts_list, *list;
traffic_selector_t *my_ts, *other_ts;
this->mode = MODE_TRANSPORT;
- my_ts_list = config->get_traffic_selectors(config, TRUE, NULL, me);
+ list = linked_list_create_with_items(me, NULL);
+ my_ts_list = config->get_traffic_selectors(config, TRUE, NULL, list);
+ list->destroy(list);
enumerator = my_ts_list->create_enumerator(my_ts_list);
if (enumerator->enumerate(enumerator, &my_ts))
{
@@ -1114,7 +1153,9 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
enumerator->destroy(enumerator);
my_ts_list->destroy_offset(my_ts_list, offsetof(traffic_selector_t, destroy));
- other_ts_list = config->get_traffic_selectors(config, FALSE, NULL, other);
+ list = linked_list_create_with_items(other, NULL);
+ other_ts_list = config->get_traffic_selectors(config, FALSE, NULL, list);
+ list->destroy(list);
enumerator = other_ts_list->create_enumerator(other_ts_list);
if (enumerator->enumerate(enumerator, &other_ts))
{
diff --git a/src/libcharon/sa/child_sa.h b/src/libcharon/sa/child_sa.h
index f17ef01ac..dae3f2c18 100644
--- a/src/libcharon/sa/child_sa.h
+++ b/src/libcharon/sa/child_sa.h
@@ -275,6 +275,14 @@ struct child_sa_t {
u_int64_t *bytes);
/**
+ * Get the mark used with this CHILD_SA.
+ *
+ * @param inbound TRUE to get inbound mark, FALSE for outbound
+ * @return mark used with this CHILD_SA
+ */
+ mark_t (*get_mark)(child_sa_t *this, bool inbound);
+
+ /**
* Get the traffic selectors list added for one side.
*
* @param local TRUE for own traffic selectors, FALSE for remote
@@ -338,12 +346,12 @@ struct child_sa_t {
*
* @param me the new local host
* @param other the new remote host
- * @param vip virtual IP, if any
+ * @param vips list of local virtual IPs
* @param TRUE to use UDP encapsulation for NAT traversal
* @return SUCCESS or FAILED
*/
status_t (*update)(child_sa_t *this, host_t *me, host_t *other,
- host_t *vip, bool encap);
+ linked_list_t *vips, bool encap);
/**
* Destroys a child_sa.
*/
diff --git a/src/libcharon/sa/authenticators/eap/eap_manager.c b/src/libcharon/sa/eap/eap_manager.c
index bc2c4a617..520c0ce56 100644
--- a/src/libcharon/sa/authenticators/eap/eap_manager.c
+++ b/src/libcharon/sa/eap/eap_manager.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -104,6 +105,44 @@ METHOD(eap_manager_t, remove_method, void,
this->lock->unlock(this->lock);
}
+/**
+ * filter the registered methods
+ */
+static bool filter_methods(uintptr_t role, eap_entry_t **entry,
+ eap_type_t *type, void *in, u_int32_t *vendor)
+{
+ if ((*entry)->role != (eap_role_t)role)
+ {
+ return FALSE;
+ }
+ if ((*entry)->vendor == 0 &&
+ ((*entry)->type < 4 || (*entry)->type == EAP_EXPANDED ||
+ (*entry)->type > EAP_EXPERIMENTAL))
+ { /* filter invalid types */
+ return FALSE;
+ }
+ if (type)
+ {
+ *type = (*entry)->type;
+ }
+ if (vendor)
+ {
+ *vendor = (*entry)->vendor;
+ }
+ return TRUE;
+}
+
+METHOD(eap_manager_t, create_enumerator, enumerator_t*,
+ private_eap_manager_t *this, eap_role_t role)
+{
+ this->lock->read_lock(this->lock);
+ return enumerator_create_cleaner(
+ enumerator_create_filter(
+ this->methods->create_enumerator(this->methods),
+ (void*)filter_methods, (void*)(uintptr_t)role, NULL),
+ (void*)this->lock->unlock, this->lock);
+}
+
METHOD(eap_manager_t, create_instance, eap_method_t*,
private_eap_manager_t *this, eap_type_t type, u_int32_t vendor,
eap_role_t role, identification_t *server, identification_t *peer)
@@ -150,6 +189,7 @@ eap_manager_t *eap_manager_create()
.public = {
.add_method = _add_method,
.remove_method = _remove_method,
+ .create_enumerator = _create_enumerator,
.create_instance = _create_instance,
.destroy = _destroy,
},
@@ -159,4 +199,3 @@ eap_manager_t *eap_manager_create()
return &this->public;
}
-
diff --git a/src/libcharon/sa/authenticators/eap/eap_manager.h b/src/libcharon/sa/eap/eap_manager.h
index 0333fb6da..e318ef57a 100644
--- a/src/libcharon/sa/authenticators/eap/eap_manager.h
+++ b/src/libcharon/sa/eap/eap_manager.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -21,7 +22,7 @@
#ifndef EAP_MANAGER_H_
#define EAP_MANAGER_H_
-#include <sa/authenticators/eap/eap_method.h>
+#include <sa/eap/eap_method.h>
typedef struct eap_manager_t eap_manager_t;
@@ -54,6 +55,17 @@ struct eap_manager_t {
void (*remove_method)(eap_manager_t *this, eap_constructor_t constructor);
/**
+ * Enumerate the registered EAP authentication methods for the given role.
+ *
+ * @note Only authentication types are enumerated (e.g. EAP-Identity is not
+ * even though it is registered as method with this manager).
+ *
+ * @param role EAP role of methods to enumerate
+ * @return enumerator over (eap_type_t type, u_int32_t vendor)
+ */
+ enumerator_t* (*create_enumerator)(eap_manager_t *this, eap_role_t role);
+
+ /**
* Create a new EAP method instance.
*
* @param type type of the EAP method
diff --git a/src/libcharon/sa/authenticators/eap/eap_method.c b/src/libcharon/sa/eap/eap_method.c
index a05e8c59a..a05e8c59a 100644
--- a/src/libcharon/sa/authenticators/eap/eap_method.c
+++ b/src/libcharon/sa/eap/eap_method.c
diff --git a/src/libcharon/sa/authenticators/eap/eap_method.h b/src/libcharon/sa/eap/eap_method.h
index 6242a5a6e..6242a5a6e 100644
--- a/src/libcharon/sa/authenticators/eap/eap_method.h
+++ b/src/libcharon/sa/eap/eap_method.h
diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c
index 07d19381d..1d49acb52 100644
--- a/src/libcharon/sa/ike_sa.c
+++ b/src/libcharon/sa/ike_sa.c
@@ -28,32 +28,16 @@
#include <daemon.h>
#include <utils/linked_list.h>
#include <utils/lexparser.h>
-#include <sa/task_manager.h>
-#include <sa/tasks/ike_init.h>
-#include <sa/tasks/ike_natd.h>
-#include <sa/tasks/ike_mobike.h>
-#include <sa/tasks/ike_auth.h>
-#include <sa/tasks/ike_auth_lifetime.h>
-#include <sa/tasks/ike_config.h>
-#include <sa/tasks/ike_cert_pre.h>
-#include <sa/tasks/ike_cert_post.h>
-#include <sa/tasks/ike_rekey.h>
-#include <sa/tasks/ike_reauth.h>
-#include <sa/tasks/ike_delete.h>
-#include <sa/tasks/ike_dpd.h>
-#include <sa/tasks/ike_vendor.h>
-#include <sa/tasks/child_create.h>
-#include <sa/tasks/child_delete.h>
-#include <sa/tasks/child_rekey.h>
#include <processing/jobs/retransmit_job.h>
#include <processing/jobs/delete_ike_sa_job.h>
#include <processing/jobs/send_dpd_job.h>
#include <processing/jobs/send_keepalive_job.h>
#include <processing/jobs/rekey_ike_sa_job.h>
-#include <encoding/payloads/unknown_payload.h>
+#include <processing/jobs/retry_initiate_job.h>
+#include <sa/ikev2/tasks/ike_auth_lifetime.h>
#ifdef ME
-#include <sa/tasks/ike_me.h>
+#include <sa/ikev2/tasks/ike_me.h>
#include <processing/jobs/initiate_mediation_job.h>
#endif
@@ -86,6 +70,11 @@ struct private_ike_sa_t {
ike_sa_id_t *ike_sa_id;
/**
+ * IKE version of this SA.
+ */
+ ike_version_t version;
+
+ /**
* unique numerical ID for this IKE_SA.
*/
u_int32_t unique_id;
@@ -193,14 +182,14 @@ struct private_ike_sa_t {
keymat_t *keymat;
/**
- * Virtual IP on local host, if any
+ * Virtual IPs on local host
*/
- host_t *my_virtual_ip;
+ linked_list_t *my_vips;
/**
- * Virtual IP on remote host, if any
+ * Virtual IPs on remote host
*/
- host_t *other_virtual_ip;
+ linked_list_t *other_vips;
/**
* List of configuration attributes (attribute_entry_t)
@@ -228,6 +217,17 @@ struct private_ike_sa_t {
u_int32_t keepalive_interval;
/**
+ * interval for retries during initiation (e.g. if DNS resolution failed),
+ * 0 to disable (default)
+ */
+ u_int32_t retry_initiate_interval;
+
+ /**
+ * TRUE if a retry_initiate_job has been queued
+ */
+ bool retry_initiate_queued;
+
+ /**
* Timestamps for this IKE_SA
*/
u_int32_t stats[STAT_MAX];
@@ -248,9 +248,9 @@ struct private_ike_sa_t {
host_t *remote_host;
/**
- * TRUE if we are currently reauthenticating this IKE_SA
+ * Flush auth configs once established?
*/
- bool is_reauthenticating;
+ bool flush_auth_cfg;
};
/**
@@ -319,6 +319,15 @@ METHOD(ike_sa_t, get_statistic, u_int32_t,
return 0;
}
+METHOD(ike_sa_t, set_statistic, void,
+ private_ike_sa_t *this, statistic_t kind, u_int32_t value)
+{
+ if (kind < STAT_MAX)
+ {
+ this->stats[kind] = value;
+ }
+}
+
METHOD(ike_sa_t, get_my_host, host_t*,
private_ike_sa_t *this)
{
@@ -405,6 +414,9 @@ static void flush_auth_cfgs(private_ike_sa_t *this)
{
auth_cfg_t *cfg;
+ this->my_auth->purge(this->my_auth, FALSE);
+ this->other_auth->purge(this->other_auth, FALSE);
+
while (this->my_auths->remove_last(this->my_auths,
(void**)&cfg) == SUCCESS)
{
@@ -471,8 +483,8 @@ METHOD(ike_sa_t, send_keepalive, void,
data.ptr[0] = 0xFF;
data.len = 1;
packet->set_data(packet, data);
- DBG1(DBG_IKE, "sending keep alive");
- charon->sender->send(charon->sender, packet);
+ DBG1(DBG_IKE, "sending keep alive to %#H", this->other_host);
+ charon->sender->send_no_marker(charon->sender, packet);
diff = 0;
}
job = send_keepalive_job_create(this->ike_sa_id);
@@ -563,6 +575,7 @@ METHOD(ike_sa_t, send_dpd, status_t,
{
job_t *job;
time_t diff, delay;
+ bool task_queued = FALSE;
if (this->state == IKE_PASSIVE)
{
@@ -583,27 +596,11 @@ METHOD(ike_sa_t, send_dpd, status_t,
diff = now - last_in;
if (!delay || diff >= delay)
{
- /* to long ago, initiate dead peer detection */
- task_t *task;
- ike_mobike_t *mobike;
-
- if (supports_extension(this, EXT_MOBIKE) &&
- has_condition(this, COND_NAT_HERE))
- {
- /* use mobike enabled DPD to detect NAT mapping changes */
- mobike = ike_mobike_create(&this->public, TRUE);
- mobike->dpd(mobike);
- task = &mobike->task;
- }
- else
- {
- task = (task_t*)ike_dpd_create(TRUE);
- }
- diff = 0;
+ /* too long ago, initiate dead peer detection */
DBG1(DBG_IKE, "sending DPD request");
-
- this->task_manager->queue_task(this->task_manager, task);
- this->task_manager->initiate(this->task_manager);
+ this->task_manager->queue_dpd(this->task_manager);
+ task_queued = TRUE;
+ diff = 0;
}
}
/* recheck in "interval" seconds */
@@ -612,6 +609,10 @@ METHOD(ike_sa_t, send_dpd, status_t,
job = (job_t*)send_dpd_job_create(this->ike_sa_id);
lib->scheduler->schedule_job(lib->scheduler, job, delay - diff);
}
+ if (task_queued)
+ {
+ return this->task_manager->initiate(this->task_manager);
+ }
return SUCCESS;
}
@@ -646,7 +647,7 @@ METHOD(ike_sa_t, set_state, void,
/* schedule rekeying if we have a time which is smaller than
* an already scheduled rekeying */
- t = this->peer_cfg->get_rekey_time(this->peer_cfg);
+ t = this->peer_cfg->get_rekey_time(this->peer_cfg, TRUE);
if (t && (this->stats[STAT_REKEY] == 0 ||
(this->stats[STAT_REKEY] > t + this->stats[STAT_ESTABLISHED])))
{
@@ -655,7 +656,7 @@ METHOD(ike_sa_t, set_state, void,
lib->scheduler->schedule_job(lib->scheduler, job, t);
DBG1(DBG_IKE, "scheduling rekeying in %ds", t);
}
- t = this->peer_cfg->get_reauth_time(this->peer_cfg);
+ t = this->peer_cfg->get_reauth_time(this->peer_cfg, TRUE);
if (t && (this->stats[STAT_REAUTH] == 0 ||
(this->stats[STAT_REAUTH] > t + this->stats[STAT_ESTABLISHED])))
{
@@ -698,7 +699,14 @@ METHOD(ike_sa_t, set_state, void,
if (trigger_dpd)
{
- send_dpd(this);
+ if (supports_extension(this, EXT_DPD))
+ {
+ send_dpd(this);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "DPD not supported by peer, disabled");
+ }
}
}
@@ -716,7 +724,8 @@ METHOD(ike_sa_t, reset, void,
flush_auth_cfgs(this);
this->keymat->destroy(this->keymat);
- this->keymat = keymat_create(this->ike_sa_id->is_initiator(this->ike_sa_id));
+ this->keymat = keymat_create(this->version,
+ this->ike_sa_id->is_initiator(this->ike_sa_id));
this->task_manager->reset(this->task_manager, 0, 0);
}
@@ -727,7 +736,7 @@ METHOD(ike_sa_t, get_keymat, keymat_t*,
return this->keymat;
}
-METHOD(ike_sa_t, set_virtual_ip, void,
+METHOD(ike_sa_t, add_virtual_ip, void,
private_ike_sa_t *this, bool local, host_t *ip)
{
if (local)
@@ -736,39 +745,44 @@ METHOD(ike_sa_t, set_virtual_ip, void,
if (hydra->kernel_interface->add_ip(hydra->kernel_interface, ip,
this->my_host) == SUCCESS)
{
- if (this->my_virtual_ip)
- {
- DBG1(DBG_IKE, "removing old virtual IP %H", this->my_virtual_ip);
- hydra->kernel_interface->del_ip(hydra->kernel_interface,
- this->my_virtual_ip);
- }
- DESTROY_IF(this->my_virtual_ip);
- this->my_virtual_ip = ip->clone(ip);
+ this->my_vips->insert_last(this->my_vips, ip->clone(ip));
}
else
{
DBG1(DBG_IKE, "installing virtual IP %H failed", ip);
- this->my_virtual_ip = NULL;
}
}
else
{
- DESTROY_IF(this->other_virtual_ip);
- this->other_virtual_ip = ip->clone(ip);
+ this->other_vips->insert_last(this->other_vips, ip->clone(ip));
}
}
-METHOD(ike_sa_t, get_virtual_ip, host_t*,
+
+METHOD(ike_sa_t, clear_virtual_ips, void,
private_ike_sa_t *this, bool local)
{
- if (local)
+ linked_list_t *vips = local ? this->my_vips : this->other_vips;
+ host_t *vip;
+
+ while (vips->remove_first(vips, (void**)&vip) == SUCCESS)
{
- return this->my_virtual_ip;
+ if (local)
+ {
+ hydra->kernel_interface->del_ip(hydra->kernel_interface, vip);
+ }
+ vip->destroy(vip);
}
- else
+}
+
+METHOD(ike_sa_t, create_virtual_ip_enumerator, enumerator_t*,
+ private_ike_sa_t *this, bool local)
+{
+ if (local)
{
- return this->other_virtual_ip;
+ return this->my_vips->create_enumerator(this->my_vips);
}
+ return this->other_vips->create_enumerator(this->other_vips);
}
METHOD(ike_sa_t, add_peer_address, void,
@@ -837,9 +851,11 @@ METHOD(ike_sa_t, float_ports, void,
private_ike_sa_t *this)
{
/* do not switch if we have a custom port from MOBIKE/NAT */
- if (this->my_host->get_port(this->my_host) == IKEV2_UDP_PORT)
+ if (this->my_host->get_port(this->my_host) ==
+ charon->socket->get_port(charon->socket, FALSE))
{
- this->my_host->set_port(this->my_host, IKEV2_NATT_PORT);
+ this->my_host->set_port(this->my_host,
+ charon->socket->get_port(charon->socket, TRUE));
}
if (this->other_host->get_port(this->other_host) == IKEV2_UDP_PORT)
{
@@ -899,7 +915,7 @@ METHOD(ike_sa_t, update_hosts, void,
while (enumerator->enumerate(enumerator, (void**)&child_sa))
{
if (child_sa->update(child_sa, this->my_host,
- this->other_host, this->my_virtual_ip,
+ this->other_host, this->my_vips,
has_condition(this, COND_NAT_ANY)) == NOT_SUPPORTED)
{
this->public.rekey_child_sa(&this->public,
@@ -914,6 +930,8 @@ METHOD(ike_sa_t, update_hosts, void,
METHOD(ike_sa_t, generate_message, status_t,
private_ike_sa_t *this, message_t *message, packet_t **packet)
{
+ status_t status;
+
if (message->is_encoded(message))
{ /* already done */
*packet = message->get_packet(message);
@@ -921,44 +939,13 @@ METHOD(ike_sa_t, generate_message, status_t,
}
this->stats[STAT_OUTBOUND] = time_monotonic(NULL);
message->set_ike_sa_id(message, this->ike_sa_id);
- charon->bus->message(charon->bus, message, FALSE);
- return message->generate(message,
- this->keymat->get_aead(this->keymat, FALSE), packet);
-}
-
-/**
- * send a notify back to the sender
- */
-static void send_notify_response(private_ike_sa_t *this, message_t *request,
- notify_type_t type, chunk_t data)
-{
- message_t *response;
- packet_t *packet;
-
- response = message_create();
- response->set_exchange_type(response, request->get_exchange_type(request));
- response->set_request(response, FALSE);
- response->set_message_id(response, request->get_message_id(request));
- response->add_notify(response, FALSE, type, data);
- if (this->my_host->is_anyaddr(this->my_host))
- {
- this->my_host->destroy(this->my_host);
- this->my_host = request->get_destination(request);
- this->my_host = this->my_host->clone(this->my_host);
- }
- if (this->other_host->is_anyaddr(this->other_host))
- {
- this->other_host->destroy(this->other_host);
- this->other_host = request->get_source(request);
- this->other_host = this->other_host->clone(this->other_host);
- }
- response->set_source(response, this->my_host->clone(this->my_host));
- response->set_destination(response, this->other_host->clone(this->other_host));
- if (generate_message(this, response, &packet) == SUCCESS)
+ charon->bus->message(charon->bus, message, FALSE, TRUE);
+ status = message->generate(message, this->keymat, packet);
+ if (status == SUCCESS)
{
- charon->sender->send(charon->sender, packet);
+ charon->bus->message(charon->bus, message, FALSE, FALSE);
}
- response->destroy(response);
+ return status;
}
METHOD(ike_sa_t, set_kmaddress, void,
@@ -1060,8 +1047,12 @@ static void resolve_hosts(private_ike_sa_t *this)
}
else
{
- host = host_create_from_dns(this->ike_cfg->get_other_addr(this->ike_cfg),
- 0, this->ike_cfg->get_other_port(this->ike_cfg));
+ char *other_addr;
+ u_int16_t other_port;
+
+ other_addr = this->ike_cfg->get_other_addr(this->ike_cfg, NULL);
+ other_port = this->ike_cfg->get_other_port(this->ike_cfg);
+ host = host_create_from_dns(other_addr, 0, other_port);
}
if (host)
{
@@ -1071,10 +1062,12 @@ static void resolve_hosts(private_ike_sa_t *this)
if (this->local_host)
{
host = this->local_host->clone(this->local_host);
- host->set_port(host, IKEV2_UDP_PORT);
+ host->set_port(host, charon->socket->get_port(charon->socket, FALSE));
}
else
{
+ char *my_addr;
+ u_int16_t my_port;
int family = 0;
/* use same address family as for other */
@@ -1082,8 +1075,9 @@ static void resolve_hosts(private_ike_sa_t *this)
{
family = this->other_host->get_family(this->other_host);
}
- host = host_create_from_dns(this->ike_cfg->get_my_addr(this->ike_cfg),
- family, this->ike_cfg->get_my_port(this->ike_cfg));
+ my_addr = this->ike_cfg->get_my_addr(this->ike_cfg, NULL);
+ my_port = this->ike_cfg->get_my_port(this->ike_cfg);
+ host = host_create_from_dns(my_addr, family, my_port);
if (host && host->is_anyaddr(host) &&
!this->other_host->is_anyaddr(this->other_host))
@@ -1097,9 +1091,7 @@ static void resolve_hosts(private_ike_sa_t *this)
}
else
{ /* fallback to address family specific %any(6), if configured */
- host = host_create_from_dns(
- this->ike_cfg->get_my_addr(this->ike_cfg),
- 0, this->ike_cfg->get_my_port(this->ike_cfg));
+ host = host_create_from_dns(my_addr, 0, my_port);
}
}
}
@@ -1113,7 +1105,7 @@ METHOD(ike_sa_t, initiate, status_t,
private_ike_sa_t *this, child_cfg_t *child_cfg, u_int32_t reqid,
traffic_selector_t *tsi, traffic_selector_t *tsr)
{
- task_t *task;
+ bool defer_initiate = FALSE;
if (this->state == IKE_CREATED)
{
@@ -1129,39 +1121,31 @@ METHOD(ike_sa_t, initiate, status_t,
#endif /* ME */
)
{
- child_cfg->destroy(child_cfg);
- DBG1(DBG_IKE, "unable to initiate to %%any");
- charon->bus->alert(charon->bus, ALERT_PEER_ADDR_FAILED);
- return DESTROY_ME;
+ char *addr = this->ike_cfg->get_other_addr(this->ike_cfg, NULL);
+ bool is_anyaddr = streq(addr, "%any") || streq(addr, "%any6");
+
+ if (is_anyaddr || !this->retry_initiate_interval)
+ {
+ if (is_anyaddr)
+ {
+ DBG1(DBG_IKE, "unable to initiate to %s", addr);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "unable to resolve %s, initiate aborted",
+ addr);
+ }
+ DESTROY_IF(child_cfg);
+ charon->bus->alert(charon->bus, ALERT_PEER_ADDR_FAILED);
+ return DESTROY_ME;
+ }
+ DBG1(DBG_IKE, "unable to resolve %s, retrying in %ds",
+ addr, this->retry_initiate_interval);
+ defer_initiate = TRUE;
}
set_condition(this, COND_ORIGINAL_INITIATOR, TRUE);
-
- task = (task_t*)ike_vendor_create(&this->public, TRUE);
- this->task_manager->queue_task(this->task_manager, task);
- task = (task_t*)ike_init_create(&this->public, TRUE, NULL);
- this->task_manager->queue_task(this->task_manager, task);
- task = (task_t*)ike_natd_create(&this->public, TRUE);
- this->task_manager->queue_task(this->task_manager, task);
- task = (task_t*)ike_cert_pre_create(&this->public, TRUE);
- this->task_manager->queue_task(this->task_manager, task);
- task = (task_t*)ike_auth_create(&this->public, TRUE);
- this->task_manager->queue_task(this->task_manager, task);
- task = (task_t*)ike_cert_post_create(&this->public, TRUE);
- this->task_manager->queue_task(this->task_manager, task);
- task = (task_t*)ike_config_create(&this->public, TRUE);
- this->task_manager->queue_task(this->task_manager, task);
- task = (task_t*)ike_auth_lifetime_create(&this->public, TRUE);
- this->task_manager->queue_task(this->task_manager, task);
- if (this->peer_cfg->use_mobike(this->peer_cfg))
- {
- task = (task_t*)ike_mobike_create(&this->public, TRUE);
- this->task_manager->queue_task(this->task_manager, task);
- }
-#ifdef ME
- task = (task_t*)ike_me_create(&this->public, TRUE);
- this->task_manager->queue_task(this->task_manager, task);
-#endif /* ME */
+ this->task_manager->queue_ike(this->task_manager);
}
#ifdef ME
@@ -1178,18 +1162,11 @@ METHOD(ike_sa_t, initiate, status_t,
}
else
#endif /* ME */
+ if (child_cfg)
{
/* normal IKE_SA with CHILD_SA */
- task = (task_t*)child_create_create(&this->public, child_cfg, FALSE,
- tsi, tsr);
- child_cfg->destroy(child_cfg);
- if (reqid)
- {
- child_create_t *child_create = (child_create_t*)task;
- child_create->use_reqid(child_create, reqid);
- }
- this->task_manager->queue_task(this->task_manager, task);
-
+ this->task_manager->queue_child(this->task_manager, child_cfg, reqid,
+ tsi, tsr);
#ifdef ME
if (this->peer_cfg->get_mediated_by(this->peer_cfg))
{
@@ -1201,135 +1178,74 @@ METHOD(ike_sa_t, initiate, status_t,
#endif /* ME */
}
+ if (defer_initiate)
+ {
+ if (!this->retry_initiate_queued)
+ {
+ job_t *job = (job_t*)retry_initiate_job_create(this->ike_sa_id);
+ lib->scheduler->schedule_job(lib->scheduler, (job_t*)job,
+ this->retry_initiate_interval);
+ this->retry_initiate_queued = TRUE;
+ }
+ return SUCCESS;
+ }
+ this->retry_initiate_queued = FALSE;
return this->task_manager->initiate(this->task_manager);
}
+METHOD(ike_sa_t, retry_initiate, status_t,
+ private_ike_sa_t *this)
+{
+ if (this->retry_initiate_queued)
+ {
+ this->retry_initiate_queued = FALSE;
+ return initiate(this, NULL, 0, NULL, NULL);
+ }
+ return SUCCESS;
+}
+
METHOD(ike_sa_t, process_message, status_t,
private_ike_sa_t *this, message_t *message)
{
status_t status;
- bool is_request;
- u_int8_t type = 0;
if (this->state == IKE_PASSIVE)
{ /* do not handle messages in passive state */
return FAILED;
}
-
- is_request = message->get_request(message);
-
- status = message->parse_body(message,
- this->keymat->get_aead(this->keymat, TRUE));
- if (status == SUCCESS)
- { /* check for unsupported critical payloads */
- enumerator_t *enumerator;
- unknown_payload_t *unknown;
- payload_t *payload;
-
- enumerator = message->create_payload_enumerator(message);
- while (enumerator->enumerate(enumerator, &payload))
- {
- unknown = (unknown_payload_t*)payload;
- type = payload->get_type(payload);
- if (!payload_is_known(type) &&
- unknown->is_critical(unknown))
+ switch (message->get_exchange_type(message))
+ {
+ case ID_PROT:
+ case AGGRESSIVE:
+ case IKE_SA_INIT:
+ case IKE_AUTH:
+ if (this->state != IKE_CREATED &&
+ this->state != IKE_CONNECTING)
{
- DBG1(DBG_ENC, "payload type %N is not supported, "
- "but its critical!", payload_type_names, type);
- status = NOT_SUPPORTED;
+ DBG1(DBG_IKE, "ignoring %N in established IKE_SA state",
+ exchange_type_names, message->get_exchange_type(message));
+ return FAILED;
}
- }
- enumerator->destroy(enumerator);
+ break;
+ default:
+ break;
}
- if (status != SUCCESS)
+ if (message->get_major_version(message) != this->version)
{
- if (is_request)
- {
- switch (status)
- {
- case NOT_SUPPORTED:
- DBG1(DBG_IKE, "critical unknown payloads found");
- if (is_request)
- {
- send_notify_response(this, message,
- UNSUPPORTED_CRITICAL_PAYLOAD,
- chunk_from_thing(type));
- this->task_manager->incr_mid(this->task_manager, FALSE);
- }
- break;
- case PARSE_ERROR:
- DBG1(DBG_IKE, "message parsing failed");
- if (is_request)
- {
- send_notify_response(this, message,
- INVALID_SYNTAX, chunk_empty);
- this->task_manager->incr_mid(this->task_manager, FALSE);
- }
- break;
- case VERIFY_ERROR:
- DBG1(DBG_IKE, "message verification failed");
- if (is_request)
- {
- send_notify_response(this, message,
- INVALID_SYNTAX, chunk_empty);
- this->task_manager->incr_mid(this->task_manager, FALSE);
- }
- break;
- case FAILED:
- DBG1(DBG_IKE, "integrity check failed");
- /* ignored */
- break;
- case INVALID_STATE:
- DBG1(DBG_IKE, "found encrypted message, but no keys available");
- default:
- break;
- }
- }
- DBG1(DBG_IKE, "%N %s with message ID %d processing failed",
+ DBG1(DBG_IKE, "ignoring %N IKEv%u exchange on %N SA",
exchange_type_names, message->get_exchange_type(message),
- message->get_request(message) ? "request" : "response",
- message->get_message_id(message));
-
- if (this->state == IKE_CREATED)
- { /* invalid initiation attempt, close SA */
- return DESTROY_ME;
- }
+ message->get_major_version(message),
+ ike_version_names, this->version);
+ /* TODO-IKEv1: fall back to IKEv1 if we receive an IKEv1
+ * INVALID_MAJOR_VERSION on an IKEv2 SA. */
+ return FAILED;
}
- else
+ status = this->task_manager->process_message(this->task_manager, message);
+ if (this->flush_auth_cfg && this->state == IKE_ESTABLISHED)
{
- /* if this IKE_SA is virgin, we check for a config */
- if (this->ike_cfg == NULL)
- {
- job_t *job;
- host_t *me = message->get_destination(message),
- *other = message->get_source(message);
- this->ike_cfg = charon->backends->get_ike_cfg(charon->backends,
- me, other);
- if (this->ike_cfg == NULL)
- {
- /* no config found for these hosts, destroy */
- DBG1(DBG_IKE, "no IKE config found for %H...%H, sending %N",
- me, other, notify_type_names, NO_PROPOSAL_CHOSEN);
- send_notify_response(this, message,
- NO_PROPOSAL_CHOSEN, chunk_empty);
- return DESTROY_ME;
- }
- /* add a timeout if peer does not establish it completely */
- job = (job_t*)delete_ike_sa_job_create(this->ike_sa_id, FALSE);
- lib->scheduler->schedule_job(lib->scheduler, job,
- lib->settings->get_int(lib->settings,
- "charon.half_open_timeout", HALF_OPEN_IKE_SA_TIMEOUT));
- }
- this->stats[STAT_INBOUND] = time_monotonic(NULL);
- status = this->task_manager->process_message(this->task_manager,
- message);
- if (message->get_exchange_type(message) == IKE_AUTH &&
- this->state == IKE_ESTABLISHED &&
- lib->settings->get_bool(lib->settings,
- "charon.flush_auth_cfg", FALSE))
- { /* authentication completed */
- flush_auth_cfgs(this);
- }
+ /* authentication completed */
+ this->flush_auth_cfg = FALSE;
+ flush_auth_cfgs(this);
}
return status;
}
@@ -1340,6 +1256,12 @@ METHOD(ike_sa_t, get_id, ike_sa_id_t*,
return this->ike_sa_id;
}
+METHOD(ike_sa_t, get_version, ike_version_t,
+ private_ike_sa_t *this)
+{
+ return this->version;
+}
+
METHOD(ike_sa_t, get_my_id, identification_t*,
private_ike_sa_t *this)
{
@@ -1373,6 +1295,10 @@ METHOD(ike_sa_t, get_other_eap_id, identification_t*,
current = cfg->get(cfg, AUTH_RULE_EAP_IDENTITY);
if (!current || current->get_type(current) == ID_ANY)
{
+ current = cfg->get(cfg, AUTH_RULE_XAUTH_IDENTITY);
+ }
+ if (!current || current->get_type(current) == ID_ANY)
+ {
current = cfg->get(cfg, AUTH_RULE_IDENTITY);
}
if (current && current->get_type(current) != ID_ANY)
@@ -1442,30 +1368,23 @@ METHOD(ike_sa_t, remove_child_sa, void,
METHOD(ike_sa_t, rekey_child_sa, status_t,
private_ike_sa_t *this, protocol_id_t protocol, u_int32_t spi)
{
- child_rekey_t *child_rekey;
-
if (this->state == IKE_PASSIVE)
{
return INVALID_STATE;
}
-
- child_rekey = child_rekey_create(&this->public, protocol, spi);
- this->task_manager->queue_task(this->task_manager, &child_rekey->task);
+ this->task_manager->queue_child_rekey(this->task_manager, protocol, spi);
return this->task_manager->initiate(this->task_manager);
}
METHOD(ike_sa_t, delete_child_sa, status_t,
- private_ike_sa_t *this, protocol_id_t protocol, u_int32_t spi)
+ private_ike_sa_t *this, protocol_id_t protocol, u_int32_t spi, bool expired)
{
- child_delete_t *child_delete;
-
if (this->state == IKE_PASSIVE)
{
return INVALID_STATE;
}
-
- child_delete = child_delete_create(&this->public, protocol, spi);
- this->task_manager->queue_task(this->task_manager, &child_delete->task);
+ this->task_manager->queue_child_delete(this->task_manager,
+ protocol, spi, expired);
return this->task_manager->initiate(this->task_manager);
}
@@ -1495,14 +1414,17 @@ METHOD(ike_sa_t, destroy_child_sa, status_t,
METHOD(ike_sa_t, delete_, status_t,
private_ike_sa_t *this)
{
- ike_delete_t *ike_delete;
-
switch (this->state)
{
- case IKE_ESTABLISHED:
case IKE_REKEYING:
- ike_delete = ike_delete_create(&this->public, TRUE);
- this->task_manager->queue_task(this->task_manager, &ike_delete->task);
+ if (this->version == IKEV1)
+ { /* SA has been reauthenticated, delete */
+ charon->bus->ike_updown(charon->bus, &this->public, FALSE);
+ break;
+ }
+ /* FALL */
+ case IKE_ESTABLISHED:
+ this->task_manager->queue_ike_delete(this->task_manager);
return this->task_manager->initiate(this->task_manager);
case IKE_CREATED:
DBG1(DBG_IKE, "deleting unestablished IKE_SA");
@@ -1521,23 +1443,17 @@ METHOD(ike_sa_t, delete_, status_t,
METHOD(ike_sa_t, rekey, status_t,
private_ike_sa_t *this)
{
- ike_rekey_t *ike_rekey;
-
if (this->state == IKE_PASSIVE)
{
return INVALID_STATE;
}
- ike_rekey = ike_rekey_create(&this->public, TRUE);
-
- this->task_manager->queue_task(this->task_manager, &ike_rekey->task);
+ this->task_manager->queue_ike_rekey(this->task_manager);
return this->task_manager->initiate(this->task_manager);
}
METHOD(ike_sa_t, reauth, status_t,
private_ike_sa_t *this)
{
- task_t *task;
-
if (this->state == IKE_PASSIVE)
{
return INVALID_STATE;
@@ -1548,7 +1464,8 @@ METHOD(ike_sa_t, reauth, status_t,
if (!has_condition(this, COND_ORIGINAL_INITIATOR))
{
DBG1(DBG_IKE, "initiator did not reauthenticate as requested");
- if (this->other_virtual_ip != NULL ||
+ if (this->other_vips->get_count(this->other_vips) != 0 ||
+ has_condition(this, COND_XAUTH_AUTHENTICATED) ||
has_condition(this, COND_EAP_AUTHENTICATED)
#ifdef ME
/* as mediation server we too cannot reauth the IKE_SA */
@@ -1575,10 +1492,8 @@ METHOD(ike_sa_t, reauth, status_t,
DBG0(DBG_IKE, "reauthenticating IKE_SA %s[%d]",
get_name(this), this->unique_id);
}
- this->is_reauthenticating = TRUE;
- task = (task_t*)ike_reauth_create(&this->public);
- this->task_manager->queue_task(this->task_manager, task);
-
+ set_condition(this, COND_REAUTHENTICATING, TRUE);
+ this->task_manager->queue_ike_reauth(this->task_manager);
return this->task_manager->initiate(this->task_manager);
}
@@ -1594,7 +1509,7 @@ METHOD(ike_sa_t, reestablish, status_t,
bool restart = FALSE;
status_t status = FAILED;
- if (this->is_reauthenticating)
+ if (has_condition(this, COND_REAUTHENTICATING))
{ /* only reauthenticate if we have children */
if (this->child_sas->get_count(this->child_sas) == 0
#ifdef ME
@@ -1653,7 +1568,7 @@ METHOD(ike_sa_t, reestablish, status_t,
/* check if we are able to reestablish this IKE_SA */
if (!has_condition(this, COND_ORIGINAL_INITIATOR) &&
- (this->other_virtual_ip != NULL ||
+ (this->other_vips->get_count(this->other_vips) != 0 ||
has_condition(this, COND_EAP_AUTHENTICATED)
#ifdef ME
|| this->is_mediation_server
@@ -1664,18 +1579,24 @@ METHOD(ike_sa_t, reestablish, status_t,
return FAILED;
}
- new = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager, TRUE);
+ new = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager,
+ this->version, TRUE);
+ if (!new)
+ {
+ return FAILED;
+ }
new->set_peer_cfg(new, this->peer_cfg);
host = this->other_host;
new->set_other_host(new, host->clone(host));
host = this->my_host;
new->set_my_host(new, host->clone(host));
/* if we already have a virtual IP, we reuse it */
- host = this->my_virtual_ip;
- if (host)
+ enumerator = this->my_vips->create_enumerator(this->my_vips);
+ while (enumerator->enumerate(enumerator, &host))
{
- new->set_virtual_ip(new, TRUE, host);
+ new->add_virtual_ip(new, TRUE, host);
}
+ enumerator->destroy(enumerator);
#ifdef ME
if (this->peer_cfg->is_mediation(this->peer_cfg))
@@ -1688,7 +1609,7 @@ METHOD(ike_sa_t, reestablish, status_t,
enumerator = this->child_sas->create_enumerator(this->child_sas);
while (enumerator->enumerate(enumerator, (void**)&child_sa))
{
- if (this->is_reauthenticating)
+ if (has_condition(this, COND_REAUTHENTICATING))
{
switch (child_sa->get_state(child_sa))
{
@@ -1744,6 +1665,7 @@ METHOD(ike_sa_t, reestablish, status_t,
}
else
{
+ charon->bus->ike_reestablish(charon->bus, &this->public, new);
charon->ike_sa_manager->checkin(charon->ike_sa_manager, new);
status = SUCCESS;
}
@@ -1751,40 +1673,6 @@ METHOD(ike_sa_t, reestablish, status_t,
return status;
}
-/**
- * Requeue the IKE_SA_INIT tasks for initiation, if required
- */
-static void requeue_init_tasks(private_ike_sa_t *this)
-{
- enumerator_t *enumerator;
- bool has_init = FALSE;
- task_t *task;
-
- /* if we have advanced to IKE_AUTH, the IKE_INIT and related tasks
- * have already completed. Recreate them if necessary. */
- enumerator = this->task_manager->create_task_enumerator(
- this->task_manager, TASK_QUEUE_QUEUED);
- while (enumerator->enumerate(enumerator, &task))
- {
- if (task->get_type(task) == IKE_INIT)
- {
- has_init = TRUE;
- break;
- }
- }
- enumerator->destroy(enumerator);
-
- if (!has_init)
- {
- task = (task_t*)ike_vendor_create(&this->public, TRUE);
- this->task_manager->queue_task(this->task_manager, task);
- task = (task_t*)ike_natd_create(&this->public, TRUE);
- this->task_manager->queue_task(this->task_manager, task);
- task = (task_t*)ike_init_create(&this->public, TRUE, NULL);
- this->task_manager->queue_task(this->task_manager, task);
- }
-}
-
METHOD(ike_sa_t, retransmit, status_t,
private_ike_sa_t *this, u_int32_t message_id)
{
@@ -1800,7 +1688,7 @@ METHOD(ike_sa_t, retransmit, status_t,
{
case IKE_CONNECTING:
{
- /* retry IKE_SA_INIT if we have multiple keyingtries */
+ /* retry IKE_SA_INIT/Main Mode if we have multiple keyingtries */
u_int32_t tries = this->peer_cfg->get_keyingtries(this->peer_cfg);
this->keyingtry++;
if (tries == 0 || tries > this->keyingtry)
@@ -1809,7 +1697,7 @@ METHOD(ike_sa_t, retransmit, status_t,
this->keyingtry + 1, tries);
reset(this);
resolve_hosts(this);
- requeue_init_tasks(this);
+ this->task_manager->queue_ike(this->task_manager);
return this->task_manager->initiate(this->task_manager);
}
DBG1(DBG_IKE, "establishing IKE_SA failed, peer not responding");
@@ -1817,7 +1705,7 @@ METHOD(ike_sa_t, retransmit, status_t,
}
case IKE_DELETING:
DBG1(DBG_IKE, "proper IKE_SA delete failed, peer not responding");
- if (this->is_reauthenticating)
+ if (has_condition(this, COND_REAUTHENTICATING))
{
DBG1(DBG_IKE, "delete during reauthentication failed, "
"trying to reestablish IKE_SA anyway");
@@ -1831,6 +1719,10 @@ METHOD(ike_sa_t, retransmit, status_t,
reestablish(this);
break;
}
+ if (this->state != IKE_CONNECTING)
+ {
+ charon->bus->ike_updown(charon->bus, &this->public, FALSE);
+ }
return DESTROY_ME;
}
return SUCCESS;
@@ -1840,7 +1732,6 @@ METHOD(ike_sa_t, set_auth_lifetime, status_t,
private_ike_sa_t *this, u_int32_t lifetime)
{
u_int32_t diff, hard, soft, now;
- ike_auth_lifetime_t *task;
bool send_update;
diff = this->peer_cfg->get_over_time(this->peer_cfg);
@@ -1850,9 +1741,9 @@ METHOD(ike_sa_t, set_auth_lifetime, status_t,
/* check if we have to send an AUTH_LIFETIME to enforce the new lifetime.
* We send the notify in IKE_AUTH if not yet ESTABLISHED. */
- send_update = this->state == IKE_ESTABLISHED &&
+ send_update = this->state == IKE_ESTABLISHED && this->version == IKEV2 &&
!has_condition(this, COND_ORIGINAL_INITIATOR) &&
- (this->other_virtual_ip != NULL ||
+ (this->other_vips->get_count(this->other_vips) != 0 ||
has_condition(this, COND_EAP_AUTHENTICATED));
if (lifetime < diff)
@@ -1890,12 +1781,16 @@ METHOD(ike_sa_t, set_auth_lifetime, status_t,
/* give at least some seconds to reauthenticate */
this->stats[STAT_DELETE] = max(hard, now + 10);
+#ifdef USE_IKEV2
if (send_update)
{
+ ike_auth_lifetime_t *task;
+
task = ike_auth_lifetime_create(&this->public, TRUE);
this->task_manager->queue_task(this->task_manager, &task->task);
return this->task_manager->initiate(this->task_manager);
}
+#endif
return SUCCESS;
}
@@ -1953,8 +1848,6 @@ static bool is_any_path_valid(private_ike_sa_t *this)
METHOD(ike_sa_t, roam, status_t,
private_ike_sa_t *this, bool address)
{
- ike_mobike_t *mobike;
-
switch (this->state)
{
case IKE_CREATED:
@@ -1976,10 +1869,7 @@ METHOD(ike_sa_t, roam, status_t,
if (supports_extension(this, EXT_MOBIKE) && address)
{ /* if any addresses changed, send an updated list */
DBG1(DBG_IKE, "sending address list update using MOBIKE");
- mobike = ike_mobike_create(&this->public, TRUE);
- mobike->addresses(mobike);
- this->task_manager->queue_task(this->task_manager,
- (task_t*)mobike);
+ this->task_manager->queue_mobike(this->task_manager, FALSE, TRUE);
return this->task_manager->initiate(this->task_manager);
}
return SUCCESS;
@@ -2007,9 +1897,7 @@ METHOD(ike_sa_t, roam, status_t,
{
DBG1(DBG_IKE, "requesting address change using MOBIKE");
}
- mobike = ike_mobike_create(&this->public, TRUE);
- mobike->roam(mobike, address);
- this->task_manager->queue_task(this->task_manager, (task_t*)mobike);
+ this->task_manager->queue_mobike(this->task_manager, TRUE, address);
return this->task_manager->initiate(this->task_manager);
}
@@ -2044,6 +1932,18 @@ METHOD(ike_sa_t, create_task_enumerator, enumerator_t*,
return this->task_manager->create_task_enumerator(this->task_manager, queue);
}
+METHOD(ike_sa_t, flush_queue, void,
+ private_ike_sa_t *this, task_queue_t queue)
+{
+ this->task_manager->flush_queue(this->task_manager, queue);
+}
+
+METHOD(ike_sa_t, queue_task, void,
+ private_ike_sa_t *this, task_t *task)
+{
+ this->task_manager->queue_task(this->task_manager, task);
+}
+
METHOD(ike_sa_t, inherit, void,
private_ike_sa_t *this, ike_sa_t *other_public)
{
@@ -2052,6 +1952,7 @@ METHOD(ike_sa_t, inherit, void,
attribute_entry_t *entry;
enumerator_t *enumerator;
auth_cfg_t *cfg;
+ host_t *vip;
/* apply hosts and ids */
this->my_host->destroy(this->my_host);
@@ -2063,16 +1964,15 @@ METHOD(ike_sa_t, inherit, void,
this->my_id = other->my_id->clone(other->my_id);
this->other_id = other->other_id->clone(other->other_id);
- /* apply virtual assigned IPs... */
- if (other->my_virtual_ip)
+ /* apply assigned virtual IPs... */
+ while (this->my_vips->remove_last(this->my_vips, (void**)&vip) == SUCCESS)
{
- this->my_virtual_ip = other->my_virtual_ip;
- other->my_virtual_ip = NULL;
+ other->my_vips->insert_first(other->my_vips, vip);
}
- if (other->other_virtual_ip)
+ while (this->other_vips->remove_last(this->other_vips,
+ (void**)&vip) == SUCCESS)
{
- this->other_virtual_ip = other->other_virtual_ip;
- other->other_virtual_ip = NULL;
+ other->other_vips->insert_first(other->other_vips, vip);
}
/* authentication information */
@@ -2147,11 +2047,12 @@ METHOD(ike_sa_t, destroy, void,
private_ike_sa_t *this)
{
attribute_entry_t *entry;
+ host_t *vip;
charon->bus->set_sa(charon->bus, &this->public);
set_state(this, IKE_DESTROYING);
- this->task_manager->destroy(this->task_manager);
+ DESTROY_IF(this->task_manager);
/* remove attributes first, as we pass the IKE_SA to the handler */
while (this->attributes->remove_last(this->attributes,
@@ -2169,24 +2070,31 @@ METHOD(ike_sa_t, destroy, void,
/* unset SA after here to avoid usage by the listeners */
charon->bus->set_sa(charon->bus, NULL);
- this->keymat->destroy(this->keymat);
+ DESTROY_IF(this->keymat);
- if (this->my_virtual_ip)
+ while (this->my_vips->remove_last(this->my_vips, (void**)&vip) == SUCCESS)
{
- hydra->kernel_interface->del_ip(hydra->kernel_interface,
- this->my_virtual_ip);
- this->my_virtual_ip->destroy(this->my_virtual_ip);
+ hydra->kernel_interface->del_ip(hydra->kernel_interface, vip);
+ vip->destroy(vip);
}
- if (this->other_virtual_ip)
+ this->my_vips->destroy(this->my_vips);
+ while (this->other_vips->remove_last(this->other_vips,
+ (void**)&vip) == SUCCESS)
{
- if (this->peer_cfg && this->peer_cfg->get_pool(this->peer_cfg))
+ if (this->peer_cfg)
{
- hydra->attributes->release_address(hydra->attributes,
- this->peer_cfg->get_pool(this->peer_cfg),
- this->other_virtual_ip, get_other_eap_id(this));
+ linked_list_t *pools;
+ identification_t *id;
+
+ id = get_other_eap_id(this);
+ pools = linked_list_create_from_enumerator(
+ this->peer_cfg->create_pool_enumerator(this->peer_cfg));
+ hydra->attributes->release_address(hydra->attributes, pools, vip, id);
+ pools->destroy(pools);
}
- this->other_virtual_ip->destroy(this->other_virtual_ip);
+ vip->destroy(vip);
}
+ this->other_vips->destroy(this->other_vips);
this->peer_addresses->destroy_offset(this->peer_addresses,
offsetof(host_t, destroy));
#ifdef ME
@@ -2224,19 +2132,32 @@ METHOD(ike_sa_t, destroy, void,
/*
* Described in header.
*/
-ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
+ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator,
+ ike_version_t version)
{
private_ike_sa_t *this;
static u_int32_t unique_id = 0;
+ if (version == IKE_ANY)
+ { /* prefer IKEv2 if protocol not specified */
+#ifdef USE_IKEV2
+ version = IKEV2;
+#else
+ version = IKEV1;
+#endif
+ }
+
INIT(this,
.public = {
+ .get_version = _get_version,
.get_state = _get_state,
.set_state = _set_state,
.get_name = _get_name,
.get_statistic = _get_statistic,
+ .set_statistic = _set_statistic,
.process_message = _process_message,
.initiate = _initiate,
+ .retry_initiate = _retry_initiate,
.get_ike_cfg = _get_ike_cfg,
.set_ike_cfg = _set_ike_cfg,
.get_peer_cfg = _get_peer_cfg,
@@ -2292,11 +2213,14 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
.generate_message = _generate_message,
.reset = _reset,
.get_unique_id = _get_unique_id,
- .set_virtual_ip = _set_virtual_ip,
- .get_virtual_ip = _get_virtual_ip,
+ .add_virtual_ip = _add_virtual_ip,
+ .clear_virtual_ips = _clear_virtual_ips,
+ .create_virtual_ip_enumerator = _create_virtual_ip_enumerator,
.add_configuration_attribute = _add_configuration_attribute,
.set_kmaddress = _set_kmaddress,
.create_task_enumerator = _create_task_enumerator,
+ .flush_queue = _flush_queue,
+ .queue_task = _queue_task,
#ifdef ME
.act_as_mediation_server = _act_as_mediation_server,
.get_server_reflexive_host = _get_server_reflexive_host,
@@ -2310,12 +2234,13 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
#endif /* ME */
},
.ike_sa_id = ike_sa_id->clone(ike_sa_id),
+ .version = version,
.child_sas = linked_list_create(),
.my_host = host_create_any(AF_INET),
.other_host = host_create_any(AF_INET),
.my_id = identification_create_from_encoding(ID_ANY, chunk_empty),
.other_id = identification_create_from_encoding(ID_ANY, chunk_empty),
- .keymat = keymat_create(ike_sa_id->is_initiator(ike_sa_id)),
+ .keymat = keymat_create(version, initiator),
.state = IKE_CREATED,
.stats[STAT_INBOUND] = time_monotonic(NULL),
.stats[STAT_OUTBOUND] = time_monotonic(NULL),
@@ -2325,12 +2250,31 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
.other_auths = linked_list_create(),
.unique_id = ++unique_id,
.peer_addresses = linked_list_create(),
+ .my_vips = linked_list_create(),
+ .other_vips = linked_list_create(),
.attributes = linked_list_create(),
.keepalive_interval = lib->settings->get_time(lib->settings,
- "charon.keep_alive", KEEPALIVE_INTERVAL),
+ "%s.keep_alive", KEEPALIVE_INTERVAL, charon->name),
+ .retry_initiate_interval = lib->settings->get_time(lib->settings,
+ "%s.retry_initiate_interval", 0, charon->name),
+ .flush_auth_cfg = lib->settings->get_bool(lib->settings,
+ "%s.flush_auth_cfg", FALSE, charon->name),
);
+
+ if (version == IKEV2)
+ { /* always supported with IKEv2 */
+ enable_extension(this, EXT_DPD);
+ }
+
this->task_manager = task_manager_create(&this->public);
- this->my_host->set_port(this->my_host, IKEV2_UDP_PORT);
+ this->my_host->set_port(this->my_host,
+ charon->socket->get_port(charon->socket, FALSE));
+ if (!this->task_manager || !this->keymat)
+ {
+ DBG1(DBG_IKE, "IKE version %d not supported", this->version);
+ destroy(this);
+ return NULL;
+ }
return &this->public;
}
diff --git a/src/libcharon/sa/ike_sa.h b/src/libcharon/sa/ike_sa.h
index 537565e89..af741c799 100644
--- a/src/libcharon/sa/ike_sa.h
+++ b/src/libcharon/sa/ike_sa.h
@@ -37,11 +37,13 @@ typedef struct ike_sa_t ike_sa_t;
#include <encoding/payloads/configuration_attribute.h>
#include <sa/ike_sa_id.h>
#include <sa/child_sa.h>
+#include <sa/task.h>
#include <sa/task_manager.h>
#include <sa/keymat.h>
#include <config/peer_cfg.h>
#include <config/ike_cfg.h>
#include <credentials/auth_cfg.h>
+#include <utils/packet.h>
/**
* Timeout in seconds after that a half open IKE_SA gets deleted.
@@ -69,7 +71,7 @@ typedef struct ike_sa_t ike_sa_t;
enum ike_extension_t {
/**
- * peer supports NAT traversal as specified in RFC4306
+ * peer supports NAT traversal as specified in RFC4306 or RFC3947
*/
EXT_NATT = (1<<0),
@@ -102,6 +104,21 @@ enum ike_extension_t {
* peer is probably a Windows 7 RAS client
*/
EXT_MS_WINDOWS = (1<<6),
+
+ /**
+ * peer supports XAuth authentication, draft-ietf-ipsec-isakmp-xauth-06
+ */
+ EXT_XAUTH = (1<<7),
+
+ /**
+ * peer supports DPD detection, RFC 3706 (or IKEv2)
+ */
+ EXT_DPD = (1<<8),
+
+ /**
+ * peer supports Cisco Unity configuration attributes
+ */
+ EXT_CISCO_UNITY = (1<<9),
};
/**
@@ -148,6 +165,21 @@ enum ike_condition_t {
* IKE_SA is stale, the peer is currently unreachable (MOBIKE)
*/
COND_STALE = (1<<7),
+
+ /**
+ * Initial contact received
+ */
+ COND_INIT_CONTACT_SEEN = (1<<8),
+
+ /**
+ * Peer has been authenticated using XAuth
+ */
+ COND_XAUTH_AUTHENTICATED = (1<<9),
+
+ /**
+ * This IKE_SA is currently being reauthenticated
+ */
+ COND_REAUTHENTICATING = (1<<10),
};
/**
@@ -270,6 +302,11 @@ struct ike_sa_t {
ike_sa_id_t* (*get_id) (ike_sa_t *this);
/**
+ * Gets the IKE version of the SA
+ */
+ ike_version_t (*get_version)(ike_sa_t *this);
+
+ /**
* Get the numerical ID uniquely defining this IKE_SA.
*
* @return unique ID
@@ -288,7 +325,7 @@ struct ike_sa_t {
*
* @param state state to set for the IKE_SA
*/
- void (*set_state) (ike_sa_t *this, ike_sa_state_t ike_sa);
+ void (*set_state) (ike_sa_t *this, ike_sa_state_t state);
/**
* Get the name of the connection this IKE_SA uses.
@@ -306,6 +343,14 @@ struct ike_sa_t {
u_int32_t (*get_statistic)(ike_sa_t *this, statistic_t kind);
/**
+ * Set statistic value of the IKE_SA.
+ *
+ * @param kind kind of value to update
+ * @param value value as integer
+ */
+ void (*set_statistic)(ike_sa_t *this, statistic_t kind, u_int32_t value);
+
+ /**
* Get the own host address.
*
* @return host address
@@ -661,6 +706,15 @@ struct ike_sa_t {
traffic_selector_t *tsr);
/**
+ * Retry initiation of this IKE_SA after it got deferred previously.
+ *
+ * @return
+ * - SUCCESS if initiation deferred or started
+ * - DESTROY_ME if initiation failed
+ */
+ status_t (*retry_initiate) (ike_sa_t *this);
+
+ /**
* Initiates the deletion of an IKE_SA.
*
* Sends a delete message to the remote peer and waits for
@@ -821,11 +875,13 @@ struct ike_sa_t {
*
* @param protocol protocol of the SA
* @param spi inbound SPI of the CHILD_SA
+ * @param expired TRUE if CHILD_SA is expired
* @return
* - NOT_FOUND, if IKE_SA has no such CHILD_SA
* - SUCCESS, if delete message sent
*/
- status_t (*delete_child_sa) (ike_sa_t *this, protocol_id_t protocol, u_int32_t spi);
+ status_t (*delete_child_sa)(ike_sa_t *this, protocol_id_t protocol,
+ u_int32_t spi, bool expired);
/**
* Destroy a CHILD SA with the specified protocol/SPI.
@@ -880,7 +936,7 @@ struct ike_sa_t {
status_t (*set_auth_lifetime)(ike_sa_t *this, u_int32_t lifetime);
/**
- * Set the virtual IP to use for this IKE_SA and its children.
+ * Add a virtual IP to use for this IKE_SA and its children.
*
* The virtual IP is assigned per IKE_SA, not per CHILD_SA. It has the same
* lifetime as the IKE_SA.
@@ -888,15 +944,22 @@ struct ike_sa_t {
* @param local TRUE to set local address, FALSE for remote
* @param ip IP to set as virtual IP
*/
- void (*set_virtual_ip) (ike_sa_t *this, bool local, host_t *ip);
+ void (*add_virtual_ip) (ike_sa_t *this, bool local, host_t *ip);
/**
- * Get the virtual IP configured.
+ * Clear all virtual IPs stored on this IKE_SA.
+ *
+ * @param local TRUE to clear local addresses, FALSE for remote
+ */
+ void (*clear_virtual_ips) (ike_sa_t *this, bool local);
+
+ /**
+ * Create an enumerator over virtual IPs.
*
* @param local TRUE to get local virtual IP, FALSE for remote
- * @return host_t *virtual IP
+ * @return enumerator over host_t*
*/
- host_t* (*get_virtual_ip) (ike_sa_t *this, bool local);
+ enumerator_t* (*create_virtual_ip_enumerator) (ike_sa_t *this, bool local);
/**
* Register a configuration attribute to the IKE_SA.
@@ -933,6 +996,20 @@ struct ike_sa_t {
enumerator_t* (*create_task_enumerator)(ike_sa_t *this, task_queue_t queue);
/**
+ * Flush a task queue, cancelling all tasks in it.
+ *
+ * @param queue queue type to flush
+ */
+ void (*flush_queue)(ike_sa_t *this, task_queue_t queue);
+
+ /**
+ * Queue a task for initiaton to the task manager.
+ *
+ * @param task task to queue
+ */
+ void (*queue_task)(ike_sa_t *this, task_t *task);
+
+ /**
* Inherit all attributes of other to this after rekeying.
*
* When rekeying is completed, all CHILD_SAs, the virtual IP and all
@@ -955,11 +1032,14 @@ struct ike_sa_t {
};
/**
- * Creates an ike_sa_t object with a specific ID.
+ * Creates an ike_sa_t object with a specific ID and IKE version.
*
- * @param ike_sa_id ike_sa_id_t object to associate with new IKE_SA
+ * @param ike_sa_id ike_sa_id_t to associate with new IKE_SA/ISAKMP_SA
+ * @param initiator TRUE to create this IKE_SA as initiator
+ * @param version IKE version of this SA
* @return ike_sa_t object
*/
-ike_sa_t *ike_sa_create(ike_sa_id_t *ike_sa_id);
+ike_sa_t *ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator,
+ ike_version_t version);
#endif /** IKE_SA_H_ @}*/
diff --git a/src/libcharon/sa/ike_sa_id.c b/src/libcharon/sa/ike_sa_id.c
index bea4c2124..0f0f1ab63 100644
--- a/src/libcharon/sa/ike_sa_id.c
+++ b/src/libcharon/sa/ike_sa_id.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -30,13 +31,18 @@ struct private_ike_sa_id_t {
*/
ike_sa_id_t public;
+ /**
+ * Major IKE version of IKE_SA.
+ */
+ u_int8_t ike_version;
+
/**
- * SPI of Initiator.
+ * SPI of initiator.
*/
u_int64_t initiator_spi;
/**
- * SPI of Responder.
+ * SPI of responder.
*/
u_int64_t responder_spi;
@@ -46,6 +52,12 @@ struct private_ike_sa_id_t {
bool is_initiator_flag;
};
+METHOD(ike_sa_id_t, get_ike_version, u_int8_t,
+ private_ike_sa_id_t *this)
+{
+ return this->ike_version;
+}
+
METHOD(ike_sa_id_t, set_responder_spi, void,
private_ike_sa_id_t *this, u_int64_t responder_spi)
{
@@ -77,23 +89,15 @@ METHOD(ike_sa_id_t, equals, bool,
{
return FALSE;
}
- if ((this->is_initiator_flag == other->is_initiator_flag) &&
- (this->initiator_spi == other->initiator_spi) &&
- (this->responder_spi == other->responder_spi))
- {
- /* private_ike_sa_id's are equal */
- return TRUE;
- }
- else
- {
- /* private_ike_sa_id's are not equal */
- return FALSE;
- }
+ return this->ike_version == other->ike_version &&
+ this->initiator_spi == other->initiator_spi &&
+ this->responder_spi == other->responder_spi;
}
METHOD(ike_sa_id_t, replace_values, void,
private_ike_sa_id_t *this, private_ike_sa_id_t *other)
{
+ this->ike_version = other->ike_version;
this->initiator_spi = other->initiator_spi;
this->responder_spi = other->responder_spi;
this->is_initiator_flag = other->is_initiator_flag;
@@ -108,22 +112,15 @@ METHOD(ike_sa_id_t, is_initiator, bool,
METHOD(ike_sa_id_t, switch_initiator, bool,
private_ike_sa_id_t *this)
{
- if (this->is_initiator_flag)
- {
- this->is_initiator_flag = FALSE;
- }
- else
- {
- this->is_initiator_flag = TRUE;
- }
+ this->is_initiator_flag = !this->is_initiator_flag;
return this->is_initiator_flag;
}
METHOD(ike_sa_id_t, clone_, ike_sa_id_t*,
private_ike_sa_id_t *this)
{
- return ike_sa_id_create(this->initiator_spi, this->responder_spi,
- this->is_initiator_flag);
+ return ike_sa_id_create(this->ike_version, this->initiator_spi,
+ this->responder_spi, this->is_initiator_flag);
}
METHOD(ike_sa_id_t, destroy, void,
@@ -135,13 +132,14 @@ METHOD(ike_sa_id_t, destroy, void,
/*
* Described in header.
*/
-ike_sa_id_t * ike_sa_id_create(u_int64_t initiator_spi, u_int64_t responder_spi,
- bool is_initiator_flag)
+ike_sa_id_t * ike_sa_id_create(u_int8_t ike_version, u_int64_t initiator_spi,
+ u_int64_t responder_spi, bool is_initiator_flag)
{
private_ike_sa_id_t *this;
INIT(this,
.public = {
+ .get_ike_version = _get_ike_version,
.set_responder_spi = _set_responder_spi,
.set_initiator_spi = _set_initiator_spi,
.get_responder_spi = _get_responder_spi,
@@ -153,6 +151,7 @@ ike_sa_id_t * ike_sa_id_create(u_int64_t initiator_spi, u_int64_t responder_spi,
.clone = _clone_,
.destroy = _destroy,
},
+ .ike_version = ike_version,
.initiator_spi = initiator_spi,
.responder_spi = responder_spi,
.is_initiator_flag = is_initiator_flag,
diff --git a/src/libcharon/sa/ike_sa_id.h b/src/libcharon/sa/ike_sa_id.h
index fb55359bc..227683d1c 100644
--- a/src/libcharon/sa/ike_sa_id.h
+++ b/src/libcharon/sa/ike_sa_id.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -29,13 +30,20 @@ typedef struct ike_sa_id_t ike_sa_id_t;
/**
* An object of type ike_sa_id_t is used to identify an IKE_SA.
*
- * An IKE_SA is identified by its initiator and responder spi's.
- * Additionally it contains the role of the actual running IKEv2 daemon
- * for the specific IKE_SA (original initiator or responder).
+ * An IKE_SA is identified by its initiator and responder SPIs.
+ * Additionally, it contains the major IKE version of the IKE_SA and, for IKEv2,
+ * the role of the daemon (original initiator or responder).
*/
struct ike_sa_id_t {
/**
+ * Get the major IKE version of this IKE_SA.
+ *
+ * @return IKE version
+ */
+ u_int8_t (*get_ike_version) (ike_sa_id_t *this);
+
+ /**
* Set the SPI of the responder.
*
* This function is called when a request or reply of a IKE_SA_INIT is received.
@@ -68,10 +76,12 @@ struct ike_sa_id_t {
/**
* Check if two ike_sa_id_t objects are equal.
*
- * Two ike_sa_id_t objects are equal if both SPI values and the role matches.
+ * Two ike_sa_id_t objects are equal if version and both SPI values match.
+ * The role is not compared.
*
* @param other ike_sa_id_t object to check if equal
- * @return TRUE if given ike_sa_id_t are equal, FALSE otherwise
+ * @return TRUE if given ike_sa_id_t are equal,
+ * FALSE otherwise
*/
bool (*equals) (ike_sa_id_t *this, ike_sa_id_t *other);
@@ -93,9 +103,9 @@ struct ike_sa_id_t {
bool (*is_initiator) (ike_sa_id_t *this);
/**
- * Switche the original initiator flag.
+ * Switch the original initiator flag.
*
- * @return TRUE if we are the original initiator after switch, FALSE otherwise
+ * @return new value if initiator flag.
*/
bool (*switch_initiator) (ike_sa_id_t *this);
@@ -113,14 +123,15 @@ struct ike_sa_id_t {
};
/**
- * Creates an ike_sa_id_t object with specific SPI's and defined role.
+ * Creates an ike_sa_id_t object.
*
+ * @param ike_version major IKE version
* @param initiator_spi initiators SPI
* @param responder_spi responders SPI
* @param is_initiaor TRUE if we are the original initiator
* @return ike_sa_id_t object
*/
-ike_sa_id_t * ike_sa_id_create(u_int64_t initiator_spi, u_int64_t responder_spi,
- bool is_initiaor);
+ike_sa_id_t * ike_sa_id_create(u_int8_t ike_version, u_int64_t initiator_spi,
+ u_int64_t responder_spi, bool is_initiaor);
#endif /** IKE_SA_ID_H_ @}*/
diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c
index 731ae6007..a396235c2 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 Tobias Brunner
+ * Copyright (C) 2008-2012 Tobias Brunner
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -157,18 +157,6 @@ static entry_t *entry_create()
}
/**
- * Function that matches entry_t objects by initiator SPI and the hash of the
- * IKE_SA_INIT message.
- */
-static bool entry_match_by_hash(entry_t *entry, ike_sa_id_t *id, chunk_t *hash)
-{
- return id->get_responder_spi(id) == 0 &&
- 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) &&
- chunk_equals(*hash, entry->init_hash);
-}
-
-/**
* Function that matches entry_t objects by ike_sa_id_t.
*/
static bool entry_match_by_id(entry_t *entry, ike_sa_id_t *id)
@@ -179,7 +167,6 @@ 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->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 */
@@ -201,8 +188,19 @@ static bool entry_match_by_sa(entry_t *entry, ike_sa_t *ike_sa)
*/
static u_int ike_sa_id_hash(ike_sa_id_t *ike_sa_id)
{
- /* we always use initiator spi as key */
- return ike_sa_id->get_initiator_spi(ike_sa_id);
+ /* IKEv2 does not mandate random SPIs (RFC 5996, 2.6), they just have to be
+ * locally unique, so we use our randomly allocated SPI whether we are
+ * initiator or responder to ensure a good distribution. The latter is not
+ * possible for IKEv1 as we don't know whether we are original initiator or
+ * not (based on the IKE header). But as RFC 2408, section 2.5.3 proposes
+ * SPIs (Cookies) to be allocated near random (we allocate them randomly
+ * anyway) it seems safe to always use the initiator SPI. */
+ if (ike_sa_id->get_ike_version(ike_sa_id) == IKEV1_MAJOR_VERSION ||
+ ike_sa_id->is_initiator(ike_sa_id))
+ {
+ return ike_sa_id->get_initiator_spi(ike_sa_id);
+ }
+ return ike_sa_id->get_responder_spi(ike_sa_id);
}
typedef struct half_open_t half_open_t;
@@ -227,14 +225,6 @@ static void half_open_destroy(half_open_t *this)
free(this);
}
-/**
- * Function that matches half_open_t objects by the given IP address chunk.
- */
-static bool half_open_match(half_open_t *half_open, chunk_t *addr)
-{
- return chunk_equals(*addr, half_open->other);
-}
-
typedef struct connected_peers_t connected_peers_t;
struct connected_peers_t {
@@ -262,15 +252,25 @@ static void connected_peers_destroy(connected_peers_t *this)
/**
* Function that matches connected_peers_t objects by the given ids.
*/
-static bool connected_peers_match(connected_peers_t *connected_peers,
+static inline bool connected_peers_match(connected_peers_t *connected_peers,
identification_t *my_id, identification_t *other_id,
- uintptr_t family)
+ int family)
{
return my_id->equals(my_id, connected_peers->my_id) &&
other_id->equals(other_id, connected_peers->other_id) &&
- family == connected_peers->family;
+ (!family || family == connected_peers->family);
}
+typedef struct init_hash_t init_hash_t;
+
+struct init_hash_t {
+ /** hash of IKE_SA_INIT or initial phase1 message (data is not cloned) */
+ chunk_t hash;
+
+ /** our SPI allocated for the IKE_SA based on this message */
+ u_int64_t our_spi;
+};
+
typedef struct segment_t segment_t;
/**
@@ -298,6 +298,20 @@ struct shareable_segment_t {
u_int count;
};
+typedef struct table_item_t table_item_t;
+
+/**
+ * Instead of using linked_list_t for each bucket we store the data in our own
+ * list to save memory.
+ */
+struct table_item_t {
+ /** data of this item */
+ void *value;
+
+ /** next item in the overflow list */
+ table_item_t *next;
+};
+
typedef struct private_ike_sa_manager_t private_ike_sa_manager_t;
/**
@@ -312,7 +326,7 @@ struct private_ike_sa_manager_t {
/**
* Hash table with entries for the ike_sa_t objects.
*/
- linked_list_t **ike_sa_table;
+ table_item_t **ike_sa_table;
/**
* The size of the hash table.
@@ -342,7 +356,7 @@ struct private_ike_sa_manager_t {
/**
* Hash table with half_open_t objects.
*/
- linked_list_t **half_open_table;
+ table_item_t **half_open_table;
/**
* Segments of the "half-open" hash table.
@@ -352,7 +366,7 @@ struct private_ike_sa_manager_t {
/**
* Hash table with connected_peers_t objects.
*/
- linked_list_t **connected_peers_table;
+ table_item_t **connected_peers_table;
/**
* Segments of the "connected peers" hash table.
@@ -360,6 +374,16 @@ struct private_ike_sa_manager_t {
shareable_segment_t *connected_peers_segments;
/**
+ * Hash table with init_hash_t objects.
+ */
+ table_item_t **init_hashes_table;
+
+ /**
+ * Segments of the "hashes" hash table.
+ */
+ segment_t *init_hashes_segments;
+
+ /**
* RNG to get random SPIs for our side
*/
rng_t *rng;
@@ -379,10 +403,10 @@ struct private_ike_sa_manager_t {
* Acquire a lock to access the segment of the table row with the given index.
* It also works with the segment index directly.
*/
-static void lock_single_segment(private_ike_sa_manager_t *this, u_int index)
+static inline void lock_single_segment(private_ike_sa_manager_t *this,
+ u_int index)
{
mutex_t *lock = this->segments[index & this->segment_mask].mutex;
-
lock->lock(lock);
}
@@ -390,10 +414,10 @@ static void lock_single_segment(private_ike_sa_manager_t *this, u_int index)
* Release the lock required to access the segment of the table row with the given index.
* It also works with the segment index directly.
*/
-static void unlock_single_segment(private_ike_sa_manager_t *this, u_int index)
+static inline void unlock_single_segment(private_ike_sa_manager_t *this,
+ u_int index)
{
mutex_t *lock = this->segments[index & this->segment_mask].mutex;
-
lock->unlock(lock);
}
@@ -456,9 +480,14 @@ struct private_enumerator_t {
u_int row;
/**
- * enumerator for the current table row
+ * current table item
+ */
+ table_item_t *current;
+
+ /**
+ * previous table item
*/
- enumerator_t *current;
+ table_item_t *prev;
};
METHOD(enumerator_t, enumerate, bool,
@@ -473,33 +502,23 @@ METHOD(enumerator_t, enumerate, bool,
{
while (this->row < this->manager->table_size)
{
+ this->prev = this->current;
if (this->current)
{
- entry_t *item;
-
- if (this->current->enumerate(this->current, &item))
- {
- *entry = this->entry = item;
- *segment = this->segment;
- return TRUE;
- }
- this->current->destroy(this->current);
- this->current = NULL;
- unlock_single_segment(this->manager, this->segment);
+ this->current = this->current->next;
}
else
{
- linked_list_t *list;
-
lock_single_segment(this->manager, this->segment);
- if ((list = this->manager->ike_sa_table[this->row]) != NULL &&
- list->get_count(list))
- {
- this->current = list->create_enumerator(list);
- continue;
- }
- unlock_single_segment(this->manager, this->segment);
+ this->current = this->manager->ike_sa_table[this->row];
}
+ if (this->current)
+ {
+ *entry = this->entry = this->current->value;
+ *segment = this->segment;
+ return TRUE;
+ }
+ unlock_single_segment(this->manager, this->segment);
this->row += this->manager->segment_count;
}
this->segment++;
@@ -517,7 +536,6 @@ METHOD(enumerator_t, enumerator_destroy, void,
}
if (this->current)
{
- this->current->destroy(this->current);
unlock_single_segment(this->manager, this->segment);
}
free(this);
@@ -546,19 +564,23 @@ static enumerator_t* create_table_enumerator(private_ike_sa_manager_t *this)
*/
static u_int put_entry(private_ike_sa_manager_t *this, entry_t *entry)
{
- linked_list_t *list;
+ table_item_t *current, *item;
u_int row, segment;
+ INIT(item,
+ .value = entry,
+ );
+
row = ike_sa_id_hash(entry->ike_sa_id) & this->table_mask;
segment = row & this->segment_mask;
lock_single_segment(this, segment);
- list = this->ike_sa_table[row];
- if (!list)
- {
- list = this->ike_sa_table[row] = linked_list_create();
+ current = this->ike_sa_table[row];
+ if (current)
+ { /* insert at the front of current bucket */
+ item->next = current;
}
- list->insert_last(list, entry);
+ this->ike_sa_table[row] = item;
this->segments[segment].count++;
return segment;
}
@@ -569,28 +591,30 @@ static u_int put_entry(private_ike_sa_manager_t *this, entry_t *entry)
*/
static void remove_entry(private_ike_sa_manager_t *this, entry_t *entry)
{
- linked_list_t *list;
+ table_item_t *item, *prev = NULL;
u_int row, segment;
row = ike_sa_id_hash(entry->ike_sa_id) & this->table_mask;
segment = row & this->segment_mask;
- list = this->ike_sa_table[row];
- if (list)
+ item = this->ike_sa_table[row];
+ while (item)
{
- entry_t *current;
- enumerator_t *enumerator;
-
- enumerator = list->create_enumerator(list);
- while (enumerator->enumerate(enumerator, &current))
+ if (item->value == entry)
{
- if (current == entry)
+ if (prev)
{
- list->remove_at(list, enumerator);
- this->segments[segment].count--;
- break;
+ prev->next = item->next;
}
+ else
+ {
+ this->ike_sa_table[row] = item->next;
+ }
+ this->segments[segment].count--;
+ free(item);
+ break;
}
- enumerator->destroy(enumerator);
+ prev = item;
+ item = item->next;
}
}
@@ -602,9 +626,21 @@ static void remove_entry_at(private_enumerator_t *this)
this->entry = NULL;
if (this->current)
{
- linked_list_t *list = this->manager->ike_sa_table[this->row];
- list->remove_at(list, this->current);
+ table_item_t *current = this->current;
+
this->manager->segments[this->segment].count--;
+ this->current = this->prev;
+
+ if (this->prev)
+ {
+ this->prev->next = current->next;
+ }
+ else
+ {
+ this->manager->ike_sa_table[this->row] = current->next;
+ unlock_single_segment(this->manager, this->segment);
+ }
+ free(current);
}
}
@@ -614,26 +650,26 @@ static void remove_entry_at(private_enumerator_t *this)
*/
static status_t get_entry_by_match_function(private_ike_sa_manager_t *this,
ike_sa_id_t *ike_sa_id, entry_t **entry, u_int *segment,
- linked_list_match_t match, void *p1, void *p2)
+ linked_list_match_t match, void *param)
{
- entry_t *current;
- linked_list_t *list;
+ table_item_t *item;
u_int row, seg;
row = ike_sa_id_hash(ike_sa_id) & this->table_mask;
seg = row & this->segment_mask;
lock_single_segment(this, seg);
- list = this->ike_sa_table[row];
- if (list)
+ item = this->ike_sa_table[row];
+ while (item)
{
- if (list->find_first(list, match, (void**)&current, p1, p2) == SUCCESS)
+ if (match(item->value, param))
{
- *entry = current;
+ *entry = item->value;
*segment = seg;
/* the locked segment has to be unlocked by the caller */
return SUCCESS;
}
+ item = item->next;
}
unlock_single_segment(this, seg);
return NOT_FOUND;
@@ -647,18 +683,7 @@ static status_t get_entry_by_id(private_ike_sa_manager_t *this,
ike_sa_id_t *ike_sa_id, entry_t **entry, u_int *segment)
{
return get_entry_by_match_function(this, ike_sa_id, entry, segment,
- (linked_list_match_t)entry_match_by_id, ike_sa_id, NULL);
-}
-
-/**
- * Find an entry by initiator SPI and IKE_SA_INIT hash.
- * Note: On SUCCESS, the caller has to unlock the segment.
- */
-static status_t get_entry_by_hash(private_ike_sa_manager_t *this,
- ike_sa_id_t *ike_sa_id, chunk_t hash, entry_t **entry, u_int *segment)
-{
- return get_entry_by_match_function(this, ike_sa_id, entry, segment,
- (linked_list_match_t)entry_match_by_hash, ike_sa_id, &hash);
+ (linked_list_match_t)entry_match_by_id, ike_sa_id);
}
/**
@@ -669,7 +694,7 @@ static status_t get_entry_by_sa(private_ike_sa_manager_t *this,
ike_sa_id_t *ike_sa_id, ike_sa_t *ike_sa, entry_t **entry, u_int *segment)
{
return get_entry_by_match_function(this, ike_sa_id, entry, segment,
- (linked_list_match_t)entry_match_by_sa, ike_sa, NULL);
+ (linked_list_match_t)entry_match_by_sa, ike_sa);
}
/**
@@ -707,44 +732,43 @@ static bool wait_for_entry(private_ike_sa_manager_t *this, entry_t *entry,
*/
static void put_half_open(private_ike_sa_manager_t *this, entry_t *entry)
{
- half_open_t *half_open = NULL;
- linked_list_t *list;
- chunk_t addr;
+ table_item_t *item;
u_int row, segment;
rwlock_t *lock;
+ half_open_t *half_open;
+ chunk_t addr;
addr = entry->other->get_address(entry->other);
row = chunk_hash(addr) & this->table_mask;
segment = row & this->segment_mask;
lock = this->half_open_segments[segment].lock;
lock->write_lock(lock);
- list = this->half_open_table[row];
- if (list)
+ item = this->half_open_table[row];
+ while (item)
{
- half_open_t *current;
+ half_open = item->value;
- if (list->find_first(list, (linked_list_match_t)half_open_match,
- (void**)&current, &addr) == SUCCESS)
+ if (chunk_equals(addr, half_open->other))
{
- half_open = current;
half_open->count++;
- this->half_open_segments[segment].count++;
+ break;
}
- }
- else
- {
- list = this->half_open_table[row] = linked_list_create();
+ item = item->next;
}
- if (!half_open)
+ if (!item)
{
INIT(half_open,
.other = chunk_clone(addr),
.count = 1,
);
- list->insert_last(list, half_open);
- this->half_open_segments[segment].count++;
+ INIT(item,
+ .value = half_open,
+ .next = this->half_open_table[row],
+ );
+ this->half_open_table[row] = item;
}
+ this->half_open_segments[segment].count++;
lock->unlock(lock);
}
@@ -753,37 +777,41 @@ static void put_half_open(private_ike_sa_manager_t *this, entry_t *entry)
*/
static void remove_half_open(private_ike_sa_manager_t *this, entry_t *entry)
{
- linked_list_t *list;
- chunk_t addr;
+ table_item_t *item, *prev = NULL;
u_int row, segment;
rwlock_t *lock;
+ chunk_t addr;
addr = entry->other->get_address(entry->other);
row = chunk_hash(addr) & this->table_mask;
segment = row & this->segment_mask;
lock = this->half_open_segments[segment].lock;
lock->write_lock(lock);
- list = this->half_open_table[row];
- if (list)
+ item = this->half_open_table[row];
+ while (item)
{
- half_open_t *current;
- enumerator_t *enumerator;
+ half_open_t *half_open = item->value;
- enumerator = list->create_enumerator(list);
- while (enumerator->enumerate(enumerator, &current))
+ if (chunk_equals(addr, half_open->other))
{
- if (half_open_match(current, &addr))
+ if (--half_open->count == 0)
{
- if (--current->count == 0)
+ if (prev)
{
- list->remove_at(list, enumerator);
- half_open_destroy(current);
+ prev->next = item->next;
}
- this->half_open_segments[segment].count--;
- break;
+ else
+ {
+ this->half_open_table[row] = item->next;
+ }
+ half_open_destroy(half_open);
+ free(item);
}
+ this->half_open_segments[segment].count--;
+ break;
}
- enumerator->destroy(enumerator);
+ prev = item;
+ item = item->next;
}
lock->unlock(lock);
}
@@ -793,28 +821,28 @@ static void remove_half_open(private_ike_sa_manager_t *this, entry_t *entry)
*/
static void put_connected_peers(private_ike_sa_manager_t *this, entry_t *entry)
{
- connected_peers_t *connected_peers = NULL;
- chunk_t my_id, other_id;
- linked_list_t *list;
+ table_item_t *item;
u_int row, segment;
rwlock_t *lock;
+ connected_peers_t *connected_peers;
+ chunk_t my_id, other_id;
+ int family;
my_id = entry->my_id->get_encoding(entry->my_id);
other_id = entry->other_id->get_encoding(entry->other_id);
+ family = entry->other->get_family(entry->other);
row = chunk_hash_inc(other_id, chunk_hash(my_id)) & this->table_mask;
segment = row & this->segment_mask;
lock = this->connected_peers_segments[segment].lock;
lock->write_lock(lock);
- list = this->connected_peers_table[row];
- if (list)
+ item = this->connected_peers_table[row];
+ while (item)
{
- connected_peers_t *current;
+ connected_peers = item->value;
- if (list->find_first(list, (linked_list_match_t)connected_peers_match,
- (void**)&current, entry->my_id, entry->other_id,
- (uintptr_t)entry->other->get_family(entry->other)) == SUCCESS)
+ if (connected_peers_match(connected_peers, entry->my_id,
+ entry->other_id, family))
{
- connected_peers = current;
if (connected_peers->sas->find_first(connected_peers->sas,
(linked_list_match_t)entry->ike_sa_id->equals,
NULL, entry->ike_sa_id) == SUCCESS)
@@ -822,22 +850,24 @@ static void put_connected_peers(private_ike_sa_manager_t *this, entry_t *entry)
lock->unlock(lock);
return;
}
+ break;
}
- }
- else
- {
- list = this->connected_peers_table[row] = linked_list_create();
+ item = item->next;
}
- if (!connected_peers)
+ if (!item)
{
INIT(connected_peers,
.my_id = entry->my_id->clone(entry->my_id),
.other_id = entry->other_id->clone(entry->other_id),
- .family = entry->other->get_family(entry->other),
+ .family = family,
.sas = linked_list_create(),
);
- list->insert_last(list, connected_peers);
+ INIT(item,
+ .value = connected_peers,
+ .next = this->connected_peers_table[row],
+ );
+ this->connected_peers_table[row] = item;
}
connected_peers->sas->insert_last(connected_peers->sas,
entry->ike_sa_id->clone(entry->ike_sa_id));
@@ -850,54 +880,61 @@ static void put_connected_peers(private_ike_sa_manager_t *this, entry_t *entry)
*/
static void remove_connected_peers(private_ike_sa_manager_t *this, entry_t *entry)
{
- chunk_t my_id, other_id;
- linked_list_t *list;
+ table_item_t *item, *prev = NULL;
u_int row, segment;
rwlock_t *lock;
+ chunk_t my_id, other_id;
+ int family;
my_id = entry->my_id->get_encoding(entry->my_id);
other_id = entry->other_id->get_encoding(entry->other_id);
+ family = entry->other->get_family(entry->other);
+
row = chunk_hash_inc(other_id, chunk_hash(my_id)) & this->table_mask;
segment = row & this->segment_mask;
lock = this->connected_peers_segments[segment].lock;
lock->write_lock(lock);
- list = this->connected_peers_table[row];
- if (list)
+ item = this->connected_peers_table[row];
+ while (item)
{
- connected_peers_t *current;
- enumerator_t *enumerator;
+ connected_peers_t *current = item->value;
- enumerator = list->create_enumerator(list);
- while (enumerator->enumerate(enumerator, &current))
+ if (connected_peers_match(current, entry->my_id, entry->other_id,
+ family))
{
- if (connected_peers_match(current, entry->my_id, entry->other_id,
- (uintptr_t)entry->other->get_family(entry->other)))
- {
- ike_sa_id_t *ike_sa_id;
- enumerator_t *inner;
+ enumerator_t *enumerator;
+ ike_sa_id_t *ike_sa_id;
- inner = current->sas->create_enumerator(current->sas);
- while (inner->enumerate(inner, &ike_sa_id))
+ enumerator = current->sas->create_enumerator(current->sas);
+ while (enumerator->enumerate(enumerator, &ike_sa_id))
+ {
+ if (ike_sa_id->equals(ike_sa_id, entry->ike_sa_id))
{
- if (ike_sa_id->equals(ike_sa_id, entry->ike_sa_id))
- {
- current->sas->remove_at(current->sas, inner);
- ike_sa_id->destroy(ike_sa_id);
- this->connected_peers_segments[segment].count--;
- break;
- }
+ current->sas->remove_at(current->sas, enumerator);
+ ike_sa_id->destroy(ike_sa_id);
+ this->connected_peers_segments[segment].count--;
+ break;
}
- inner->destroy(inner);
- if (current->sas->get_count(current->sas) == 0)
+ }
+ enumerator->destroy(enumerator);
+ if (current->sas->get_count(current->sas) == 0)
+ {
+ if (prev)
{
- list->remove_at(list, enumerator);
- connected_peers_destroy(current);
+ prev->next = item->next;
}
- break;
+ else
+ {
+ this->connected_peers_table[row] = item->next;
+ }
+ connected_peers_destroy(current);
+ free(item);
}
+ break;
}
- enumerator->destroy(enumerator);
+ prev = item;
+ item = item->next;
}
lock->unlock(lock);
}
@@ -907,13 +944,143 @@ static void remove_connected_peers(private_ike_sa_manager_t *this, entry_t *entr
*/
static u_int64_t get_spi(private_ike_sa_manager_t *this)
{
- u_int64_t spi = 0;
+ u_int64_t spi;
+
+ if (this->rng &&
+ this->rng->get_bytes(this->rng, sizeof(spi), (u_int8_t*)&spi))
+ {
+ return spi;
+ }
+ return 0;
+}
+
+/**
+ * Calculate the hash of the initial IKE message. Memory for the hash is
+ * allocated on success.
+ *
+ * @returns TRUE on success
+ */
+static bool get_init_hash(private_ike_sa_manager_t *this, message_t *message,
+ chunk_t *hash)
+{
+ if (!this->hasher)
+ { /* this might be the case when flush() has been called */
+ return FALSE;
+ }
+ if (message->get_exchange_type(message) == ID_PROT)
+ { /* include the source for Main Mode as the hash will be the same if
+ * SPIs are reused by two initiators that use the same proposal */
+ host_t *src = message->get_source(message);
+
+ if (!this->hasher->allocate_hash(this->hasher,
+ src->get_address(src), NULL))
+ {
+ return FALSE;
+ }
+ }
+ return this->hasher->allocate_hash(this->hasher,
+ message->get_packet_data(message), hash);
+}
+
+/**
+ * Check if we already have created an IKE_SA based on the initial IKE message
+ * with the given hash.
+ * If not the hash is stored, the hash data is not(!) cloned.
+ *
+ * Also, the local SPI is returned. In case of a retransmit this is already
+ * stored together with the hash, otherwise it is newly allocated and should
+ * be used to create the IKE_SA.
+ *
+ * @returns ALREADY_DONE if the message with the given hash has been seen before
+ * NOT_FOUND if the message hash was not found
+ * FAILED if the SPI allocation failed
+ */
+static status_t check_and_put_init_hash(private_ike_sa_manager_t *this,
+ chunk_t init_hash, u_int64_t *our_spi)
+{
+ table_item_t *item;
+ u_int row, segment;
+ mutex_t *mutex;
+ init_hash_t *init;
+ u_int64_t spi;
- if (this->rng)
+ row = chunk_hash(init_hash) & this->table_mask;
+ segment = row & this->segment_mask;
+ mutex = this->init_hashes_segments[segment].mutex;
+ mutex->lock(mutex);
+ item = this->init_hashes_table[row];
+ while (item)
{
- this->rng->get_bytes(this->rng, sizeof(spi), (u_int8_t*)&spi);
+ init_hash_t *current = item->value;
+
+ if (chunk_equals(init_hash, current->hash))
+ {
+ *our_spi = current->our_spi;
+ mutex->unlock(mutex);
+ return ALREADY_DONE;
+ }
+ item = item->next;
+ }
+
+ spi = get_spi(this);
+ if (!spi)
+ {
+ return FAILED;
}
- return spi;
+
+ INIT(init,
+ .hash = {
+ .len = init_hash.len,
+ .ptr = init_hash.ptr,
+ },
+ .our_spi = spi,
+ );
+ INIT(item,
+ .value = init,
+ .next = this->init_hashes_table[row],
+ );
+ this->init_hashes_table[row] = item;
+ *our_spi = init->our_spi;
+ mutex->unlock(mutex);
+ return NOT_FOUND;
+}
+
+/**
+ * Remove the hash of an initial IKE message from the cache.
+ */
+static void remove_init_hash(private_ike_sa_manager_t *this, chunk_t init_hash)
+{
+ table_item_t *item, *prev = NULL;
+ u_int row, segment;
+ mutex_t *mutex;
+
+ row = chunk_hash(init_hash) & this->table_mask;
+ segment = row & this->segment_mask;
+ mutex = this->init_hashes_segments[segment].mutex;
+ mutex->lock(mutex);
+ item = this->init_hashes_table[row];
+ while (item)
+ {
+ init_hash_t *current = item->value;
+
+ if (chunk_equals(init_hash, current->hash))
+ {
+ if (prev)
+ {
+ prev->next = item->next;
+ }
+ else
+ {
+ this->init_hashes_table[row] = item->next;
+ }
+ free(current);
+ free(item);
+ break;
+ }
+ prev = item;
+ item = item->next;
+ }
+ mutex->unlock(mutex);
}
METHOD(ike_sa_manager_t, checkout, ike_sa_t*,
@@ -941,25 +1108,38 @@ METHOD(ike_sa_manager_t, checkout, ike_sa_t*,
}
METHOD(ike_sa_manager_t, checkout_new, ike_sa_t*,
- private_ike_sa_manager_t* this, bool initiator)
+ private_ike_sa_manager_t* this, ike_version_t version, bool initiator)
{
ike_sa_id_t *ike_sa_id;
ike_sa_t *ike_sa;
+ u_int8_t ike_version;
+ u_int64_t spi;
+
+ ike_version = version == IKEV1 ? IKEV1_MAJOR_VERSION : IKEV2_MAJOR_VERSION;
+
+ spi = get_spi(this);
+ if (!spi)
+ {
+ DBG1(DBG_MGR, "failed to allocate SPI for new IKE_SA");
+ return NULL;
+ }
if (initiator)
{
- ike_sa_id = ike_sa_id_create(get_spi(this), 0, TRUE);
+ ike_sa_id = ike_sa_id_create(ike_version, spi, 0, TRUE);
}
else
{
- ike_sa_id = ike_sa_id_create(0, get_spi(this), FALSE);
+ ike_sa_id = ike_sa_id_create(ike_version, 0, spi, FALSE);
}
- ike_sa = ike_sa_create(ike_sa_id);
+ ike_sa = ike_sa_create(ike_sa_id, initiator, version);
ike_sa_id->destroy(ike_sa_id);
- DBG2(DBG_MGR, "created IKE_SA %s[%u]", ike_sa->get_name(ike_sa),
- ike_sa->get_unique_id(ike_sa));
-
+ if (ike_sa)
+ {
+ DBG2(DBG_MGR, "created IKE_SA %s[%u]", ike_sa->get_name(ike_sa),
+ ike_sa->get_unique_id(ike_sa));
+ }
return ike_sa;
}
@@ -970,94 +1150,118 @@ METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*,
entry_t *entry;
ike_sa_t *ike_sa = NULL;
ike_sa_id_t *id;
+ ike_version_t ike_version;
+ bool is_init = FALSE;
id = message->get_ike_sa_id(message);
+ /* clone the IKE_SA ID so we can modify the initiator flag */
id = id->clone(id);
id->switch_initiator(id);
DBG2(DBG_MGR, "checkout IKE_SA by message");
- if (message->get_request(message) &&
- message->get_exchange_type(message) == IKE_SA_INIT &&
- this->hasher)
+ if (id->get_responder_spi(id) == 0)
{
- /* IKE_SA_INIT request. Check for an IKE_SA with such a message hash. */
- chunk_t data, hash;
-
- data = message->get_packet_data(message);
- this->hasher->allocate_hash(this->hasher, data, &hash);
- chunk_free(&data);
-
- if (get_entry_by_hash(this, id, hash, &entry, &segment) == SUCCESS)
+ if (message->get_major_version(message) == IKEV2_MAJOR_VERSION)
{
- if (entry->message_id == 0)
+ if (message->get_exchange_type(message) == IKE_SA_INIT &&
+ message->get_request(message))
{
- unlock_single_segment(this, segment);
- chunk_free(&hash);
- id->destroy(id);
- DBG1(DBG_MGR, "ignoring IKE_SA_INIT, already processing");
- return NULL;
+ ike_version = IKEV2;
+ is_init = TRUE;
}
- else if (wait_for_entry(this, entry, segment))
+ }
+ else
+ {
+ if (message->get_exchange_type(message) == ID_PROT ||
+ message->get_exchange_type(message) == AGGRESSIVE)
{
- entry->checked_out = TRUE;
- entry->message_id = message->get_message_id(message);
- ike_sa = entry->ike_sa;
- DBG2(DBG_MGR, "IKE_SA %s[%u] checked out by hash",
- ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa));
+ ike_version = IKEV1;
+ is_init = TRUE;
+ if (id->is_initiator(id))
+ { /* not set in IKEv1, switch back before applying to new SA */
+ id->switch_initiator(id);
+ }
}
- unlock_single_segment(this, segment);
+ }
+ }
+
+ if (is_init)
+ {
+ u_int64_t our_spi;
+ chunk_t hash;
+
+ if (!get_init_hash(this, message, &hash))
+ {
+ DBG1(DBG_MGR, "ignoring message, failed to hash message");
+ id->destroy(id);
+ return NULL;
}
- if (ike_sa == NULL)
+ /* ensure this is not a retransmit of an already handled init message */
+ switch (check_and_put_init_hash(this, hash, &our_spi))
{
- if (id->get_responder_spi(id) == 0 &&
- message->get_exchange_type(message) == IKE_SA_INIT)
- {
- /* no IKE_SA found, create a new one */
- id->set_responder_spi(id, get_spi(this));
- entry = entry_create();
- entry->ike_sa = ike_sa_create(id);
- entry->ike_sa_id = id->clone(id);
+ case NOT_FOUND:
+ { /* we've not seen this packet yet, create a new IKE_SA */
+ id->set_responder_spi(id, our_spi);
+ ike_sa = ike_sa_create(id, FALSE, ike_version);
+ if (ike_sa)
+ {
+ entry = entry_create();
+ entry->ike_sa = ike_sa;
+ entry->ike_sa_id = id->clone(id);
- segment = put_entry(this, entry);
- entry->checked_out = TRUE;
- unlock_single_segment(this, segment);
+ segment = put_entry(this, entry);
+ entry->checked_out = TRUE;
+ unlock_single_segment(this, segment);
- entry->message_id = message->get_message_id(message);
- entry->init_hash = hash;
- ike_sa = entry->ike_sa;
+ entry->message_id = message->get_message_id(message);
+ entry->init_hash = hash;
- DBG2(DBG_MGR, "created IKE_SA %s[%u]",
- ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa));
+ DBG2(DBG_MGR, "created IKE_SA %s[%u]",
+ ike_sa->get_name(ike_sa),
+ ike_sa->get_unique_id(ike_sa));
+ }
+ else
+ {
+ remove_init_hash(this, hash);
+ chunk_free(&hash);
+ DBG1(DBG_MGR, "ignoring message, no such IKE_SA");
+ }
+ id->destroy(id);
+ charon->bus->set_sa(charon->bus, ike_sa);
+ return ike_sa;
}
- else
- {
+ case FAILED:
+ { /* we failed to allocate an SPI */
chunk_free(&hash);
- DBG1(DBG_MGR, "ignoring message, no such IKE_SA");
+ id->destroy(id);
+ DBG1(DBG_MGR, "ignoring message, failed to allocate SPI");
+ return NULL;
}
+ case ALREADY_DONE:
+ default:
+ break;
}
- else
- {
- chunk_free(&hash);
- }
- id->destroy(id);
- charon->bus->set_sa(charon->bus, ike_sa);
- return ike_sa;
+ /* it looks like we already handled this init message to some degree */
+ id->set_responder_spi(id, our_spi);
+ chunk_free(&hash);
}
if (get_entry_by_id(this, id, &entry, &segment) == SUCCESS)
{
- /* only check out if we are not processing this request */
+ /* only check out in IKEv2 if we are not already processing it */
if (message->get_request(message) &&
message->get_message_id(message) == entry->message_id)
{
- DBG1(DBG_MGR, "ignoring request with ID %d, already processing",
+ DBG1(DBG_MGR, "ignoring request with ID %u, already processing",
entry->message_id);
}
else if (wait_for_entry(this, entry, segment))
{
- ike_sa_id_t *ike_id = entry->ike_sa->get_id(entry->ike_sa);
+ ike_sa_id_t *ike_id;
+
+ ike_id = entry->ike_sa->get_id(entry->ike_sa);
entry->checked_out = TRUE;
entry->message_id = message->get_message_id(message);
if (ike_id->get_responder_spi(ike_id) == 0)
@@ -1089,7 +1293,7 @@ METHOD(ike_sa_manager_t, checkout_by_config, ike_sa_t*,
if (!this->reuse_ikesa)
{ /* IKE_SA reuse disable by config */
- ike_sa = checkout_new(this, TRUE);
+ ike_sa = checkout_new(this, peer_cfg->get_ike_version(peer_cfg), TRUE);
charon->bus->set_sa(charon->bus, ike_sa);
return ike_sa;
}
@@ -1125,7 +1329,7 @@ METHOD(ike_sa_manager_t, checkout_by_config, ike_sa_t*,
if (!ike_sa)
{ /* no IKE_SA using such a config, hand out a new */
- ike_sa = checkout_new(this, TRUE);
+ ike_sa = checkout_new(this, peer_cfg->get_ike_version(peer_cfg), TRUE);
}
charon->bus->set_sa(charon->bus, ike_sa);
return ike_sa;
@@ -1244,6 +1448,7 @@ static bool enumerator_filter_wait(private_ike_sa_manager_t *this,
if (wait_for_entry(this, *in, *segment))
{
*out = (*in)->ike_sa;
+ charon->bus->set_sa(charon->bus, *out);
return TRUE;
}
return FALSE;
@@ -1260,17 +1465,26 @@ static bool enumerator_filter_skip(private_ike_sa_manager_t *this,
!(*in)->checked_out)
{
*out = (*in)->ike_sa;
+ charon->bus->set_sa(charon->bus, *out);
return TRUE;
}
return FALSE;
}
+/**
+ * Reset threads SA after enumeration
+ */
+static void reset_sa(void *data)
+{
+ charon->bus->set_sa(charon->bus, NULL);
+}
+
METHOD(ike_sa_manager_t, create_enumerator, enumerator_t*,
private_ike_sa_manager_t* this, bool wait)
{
return enumerator_create_filter(create_table_enumerator(this),
wait ? (void*)enumerator_filter_wait : (void*)enumerator_filter_skip,
- this, NULL);
+ this, reset_sa);
}
METHOD(ike_sa_manager_t, checkin, void,
@@ -1290,7 +1504,7 @@ METHOD(ike_sa_manager_t, checkin, void,
ike_sa_id = ike_sa->get_id(ike_sa);
my_id = ike_sa->get_my_id(ike_sa);
- other_id = ike_sa->get_other_id(ike_sa);
+ other_id = ike_sa->get_other_eap_id(ike_sa);
other = ike_sa->get_other_host(ike_sa);
DBG2(DBG_MGR, "checkin IKE_SA %s[%u]", ike_sa->get_name(ike_sa),
@@ -1340,9 +1554,21 @@ METHOD(ike_sa_manager_t, checkin, void,
}
/* apply identities for duplicate test */
- if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
+ if ((ike_sa->get_state(ike_sa) == IKE_ESTABLISHED ||
+ ike_sa->get_state(ike_sa) == IKE_PASSIVE) &&
entry->my_id == NULL && entry->other_id == NULL)
{
+ if (ike_sa->get_version(ike_sa) == IKEV1)
+ {
+ /* If authenticated and received INITIAL_CONTACT,
+ * delete any existing IKE_SAs with that peer. */
+ if (ike_sa->has_condition(ike_sa, COND_INIT_CONTACT_SEEN))
+ {
+ this->public.check_uniqueness(&this->public, ike_sa, TRUE);
+ ike_sa->set_condition(ike_sa, COND_INIT_CONTACT_SEEN, FALSE);
+ }
+ }
+
entry->my_id = my_id->clone(my_id);
entry->other_id = other_id->clone(other_id);
if (!entry->other)
@@ -1376,6 +1602,16 @@ METHOD(ike_sa_manager_t, checkin_and_destroy, void,
if (get_entry_by_sa(this, ike_sa_id, ike_sa, &entry, &segment) == SUCCESS)
{
+ if (entry->driveout_waiting_threads && entry->driveout_new_threads)
+ { /* it looks like flush() has been called and the SA is being deleted
+ * anyway, just check it in */
+ DBG2(DBG_MGR, "ignored check-in and destroy of IKE_SA during shutdown");
+ entry->checked_out = FALSE;
+ entry->condvar->broadcast(entry->condvar);
+ unlock_single_segment(this, segment);
+ return;
+ }
+
/* drive out waiting threads, as we are in hurry */
entry->driveout_waiting_threads = TRUE;
/* mark it, so no new threads can get this entry */
@@ -1399,6 +1635,10 @@ METHOD(ike_sa_manager_t, checkin_and_destroy, void,
{
remove_connected_peers(this, entry);
}
+ if (entry->init_hash.ptr)
+ {
+ remove_init_hash(this, entry->init_hash);
+ }
entry_destroy(entry);
@@ -1412,65 +1652,81 @@ METHOD(ike_sa_manager_t, checkin_and_destroy, void,
charon->bus->set_sa(charon->bus, NULL);
}
-METHOD(ike_sa_manager_t, check_uniqueness, bool,
- private_ike_sa_manager_t *this, ike_sa_t *ike_sa, bool force_replace)
+/**
+ * Cleanup function for create_id_enumerator
+ */
+static void id_enumerator_cleanup(linked_list_t *ids)
{
- bool cancel = FALSE;
- peer_cfg_t *peer_cfg;
- unique_policy_t policy;
- linked_list_t *list, *duplicate_ids = NULL;
- enumerator_t *enumerator;
- ike_sa_id_t *duplicate_id = NULL;
- identification_t *me, *other;
+ ids->destroy_offset(ids, offsetof(ike_sa_id_t, destroy));
+}
+
+METHOD(ike_sa_manager_t, create_id_enumerator, enumerator_t*,
+ private_ike_sa_manager_t *this, identification_t *me,
+ identification_t *other, int family)
+{
+ table_item_t *item;
u_int row, segment;
rwlock_t *lock;
-
- peer_cfg = ike_sa->get_peer_cfg(ike_sa);
- policy = peer_cfg->get_unique_policy(peer_cfg);
- if (policy == UNIQUE_NO && !force_replace)
- {
- return FALSE;
- }
-
- me = ike_sa->get_my_id(ike_sa);
- other = ike_sa->get_other_id(ike_sa);
+ linked_list_t *ids = NULL;
row = chunk_hash_inc(other->get_encoding(other),
chunk_hash(me->get_encoding(me))) & this->table_mask;
segment = row & this->segment_mask;
- lock = this->connected_peers_segments[segment & this->segment_mask].lock;
+ lock = this->connected_peers_segments[segment].lock;
lock->read_lock(lock);
- list = this->connected_peers_table[row];
- if (list)
+ item = this->connected_peers_table[row];
+ while (item)
{
- connected_peers_t *current;
- host_t *other_host;
+ connected_peers_t *current = item->value;
- other_host = ike_sa->get_other_host(ike_sa);
- if (list->find_first(list, (linked_list_match_t)connected_peers_match,
- (void**)&current, me, other,
- (uintptr_t)other_host->get_family(other_host)) == SUCCESS)
+ if (connected_peers_match(current, me, other, family))
{
- /* clone the list, so we can release the lock */
- duplicate_ids = current->sas->clone_offset(current->sas,
- offsetof(ike_sa_id_t, clone));
+ ids = current->sas->clone_offset(current->sas,
+ offsetof(ike_sa_id_t, clone));
+ break;
}
+ item = item->next;
}
lock->unlock(lock);
- if (!duplicate_ids)
+ if (!ids)
+ {
+ return enumerator_create_empty();
+ }
+ return enumerator_create_cleaner(ids->create_enumerator(ids),
+ (void*)id_enumerator_cleanup, ids);
+}
+
+METHOD(ike_sa_manager_t, check_uniqueness, bool,
+ private_ike_sa_manager_t *this, ike_sa_t *ike_sa, bool force_replace)
+{
+ bool cancel = FALSE;
+ peer_cfg_t *peer_cfg;
+ unique_policy_t policy;
+ enumerator_t *enumerator;
+ ike_sa_id_t *id = NULL;
+ identification_t *me, *other;
+ host_t *other_host;
+
+ peer_cfg = ike_sa->get_peer_cfg(ike_sa);
+ policy = peer_cfg->get_unique_policy(peer_cfg);
+ if (policy == UNIQUE_NEVER || (policy == UNIQUE_NO && !force_replace))
{
return FALSE;
}
+ me = ike_sa->get_my_id(ike_sa);
+ other = ike_sa->get_other_eap_id(ike_sa);
+ other_host = ike_sa->get_other_host(ike_sa);
- enumerator = duplicate_ids->create_enumerator(duplicate_ids);
- while (enumerator->enumerate(enumerator, &duplicate_id))
+ enumerator = create_id_enumerator(this, me, other,
+ other_host->get_family(other_host));
+ while (enumerator->enumerate(enumerator, &id))
{
status_t status = SUCCESS;
ike_sa_t *duplicate;
- duplicate = checkout(this, duplicate_id);
+ duplicate = checkout(this, id);
if (!duplicate)
{
continue;
@@ -1520,7 +1776,6 @@ METHOD(ike_sa_manager_t, check_uniqueness, bool,
}
}
enumerator->destroy(enumerator);
- duplicate_ids->destroy_offset(duplicate_ids, offsetof(ike_sa_id_t, destroy));
/* reset thread's current IKE_SA after checkin */
charon->bus->set_sa(charon->bus, ike_sa);
return cancel;
@@ -1530,7 +1785,7 @@ METHOD(ike_sa_manager_t, has_contact, bool,
private_ike_sa_manager_t *this, identification_t *me,
identification_t *other, int family)
{
- linked_list_t *list;
+ table_item_t *item;
u_int row, segment;
rwlock_t *lock;
bool found = FALSE;
@@ -1538,16 +1793,17 @@ METHOD(ike_sa_manager_t, has_contact, bool,
row = chunk_hash_inc(other->get_encoding(other),
chunk_hash(me->get_encoding(me))) & this->table_mask;
segment = row & this->segment_mask;
- lock = this->connected_peers_segments[segment & this->segment_mask].lock;
+ lock = this->connected_peers_segments[segment].lock;
lock->read_lock(lock);
- list = this->connected_peers_table[row];
- if (list)
+ item = this->connected_peers_table[row];
+ while (item)
{
- if (list->find_first(list, (linked_list_match_t)connected_peers_match,
- NULL, me, other, family) == SUCCESS)
+ if (connected_peers_match(item->value, me, other, family))
{
found = TRUE;
+ break;
}
+ item = item->next;
}
lock->unlock(lock);
@@ -1573,8 +1829,8 @@ 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)
{
- linked_list_t *list;
- u_int segment, row;
+ table_item_t *item;
+ u_int row, segment;
rwlock_t *lock;
chunk_t addr;
u_int count = 0;
@@ -1584,17 +1840,19 @@ METHOD(ike_sa_manager_t, get_half_open_count, u_int,
addr = ip->get_address(ip);
row = chunk_hash(addr) & this->table_mask;
segment = row & this->segment_mask;
- lock = this->half_open_segments[segment & this->segment_mask].lock;
+ lock = this->half_open_segments[segment].lock;
lock->read_lock(lock);
- if ((list = this->half_open_table[row]) != NULL)
+ item = this->half_open_table[row];
+ while (item)
{
- half_open_t *current;
+ half_open_t *half_open = item->value;
- if (list->find_first(list, (linked_list_match_t)half_open_match,
- (void**)&current, &addr) == SUCCESS)
+ if (chunk_equals(addr, half_open->other))
{
- count = current->count;
+ count = half_open->count;
+ break;
}
+ item = item->next;
}
lock->unlock(lock);
}
@@ -1602,7 +1860,7 @@ METHOD(ike_sa_manager_t, get_half_open_count, u_int,
{
for (segment = 0; segment < this->segment_count; segment++)
{
- lock = this->half_open_segments[segment & this->segment_mask].lock;
+ lock = this->half_open_segments[segment].lock;
lock->read_lock(lock);
count += this->half_open_segments[segment].count;
lock->unlock(lock);
@@ -1651,16 +1909,18 @@ METHOD(ike_sa_manager_t, flush, void,
while (enumerator->enumerate(enumerator, &entry, &segment))
{
charon->bus->set_sa(charon->bus, entry->ike_sa);
- /* as the delete never gets processed, fire down events */
- switch (entry->ike_sa->get_state(entry->ike_sa))
- {
- case IKE_ESTABLISHED:
- case IKE_REKEYING:
- case IKE_DELETING:
- charon->bus->ike_updown(charon->bus, entry->ike_sa, FALSE);
- break;
- default:
- break;
+ if (entry->ike_sa->get_version(entry->ike_sa) == IKEV2)
+ { /* as the delete never gets processed, fire down events */
+ switch (entry->ike_sa->get_state(entry->ike_sa))
+ {
+ case IKE_ESTABLISHED:
+ case IKE_REKEYING:
+ case IKE_DELETING:
+ charon->bus->ike_updown(charon->bus, entry->ike_sa, FALSE);
+ break;
+ default:
+ break;
+ }
}
entry->ike_sa->delete(entry->ike_sa);
}
@@ -1680,6 +1940,10 @@ METHOD(ike_sa_manager_t, flush, void,
{
remove_connected_peers(this, entry);
}
+ if (entry->init_hash.ptr)
+ {
+ remove_init_hash(this, entry->init_hash);
+ }
remove_entry_at((private_enumerator_t*)enumerator);
entry_destroy(entry);
}
@@ -1698,24 +1962,22 @@ METHOD(ike_sa_manager_t, destroy, void,
{
u_int i;
- for (i = 0; i < this->table_size; i++)
- {
- DESTROY_IF(this->ike_sa_table[i]);
- DESTROY_IF(this->half_open_table[i]);
- DESTROY_IF(this->connected_peers_table[i]);
- }
+ /* these are already cleared in flush() above */
free(this->ike_sa_table);
free(this->half_open_table);
free(this->connected_peers_table);
+ free(this->init_hashes_table);
for (i = 0; i < this->segment_count; i++)
{
this->segments[i].mutex->destroy(this->segments[i].mutex);
this->half_open_segments[i].lock->destroy(this->half_open_segments[i].lock);
this->connected_peers_segments[i].lock->destroy(this->connected_peers_segments[i].lock);
+ this->init_hashes_segments[i].mutex->destroy(this->init_hashes_segments[i].mutex);
}
free(this->segments);
free(this->half_open_segments);
free(this->connected_peers_segments);
+ free(this->init_hashes_segments);
free(this);
}
@@ -1757,6 +2019,7 @@ ike_sa_manager_t *ike_sa_manager_create()
.check_uniqueness = _check_uniqueness,
.has_contact = _has_contact,
.create_enumerator = _create_enumerator,
+ .create_id_enumerator = _create_id_enumerator,
.checkin = _checkin,
.checkin_and_destroy = _checkin_and_destroy,
.get_count = _get_count,
@@ -1782,17 +2045,19 @@ ike_sa_manager_t *ike_sa_manager_create()
return NULL;
}
- this->table_size = get_nearest_powerof2(lib->settings->get_int(lib->settings,
- "charon.ikesa_table_size", DEFAULT_HASHTABLE_SIZE));
+ this->table_size = get_nearest_powerof2(lib->settings->get_int(
+ lib->settings, "%s.ikesa_table_size",
+ DEFAULT_HASHTABLE_SIZE, charon->name));
this->table_size = max(1, min(this->table_size, MAX_HASHTABLE_SIZE));
this->table_mask = this->table_size - 1;
- this->segment_count = get_nearest_powerof2(lib->settings->get_int(lib->settings,
- "charon.ikesa_table_segments", DEFAULT_SEGMENT_COUNT));
+ this->segment_count = get_nearest_powerof2(lib->settings->get_int(
+ lib->settings, "%s.ikesa_table_segments",
+ DEFAULT_SEGMENT_COUNT, charon->name));
this->segment_count = max(1, min(this->segment_count, this->table_size));
this->segment_mask = this->segment_count - 1;
- this->ike_sa_table = calloc(this->table_size, sizeof(linked_list_t*));
+ this->ike_sa_table = calloc(this->table_size, sizeof(table_item_t*));
this->segments = (segment_t*)calloc(this->segment_count, sizeof(segment_t));
for (i = 0; i < this->segment_count; i++)
{
@@ -1801,7 +2066,7 @@ ike_sa_manager_t *ike_sa_manager_create()
}
/* we use the same table parameters for the table to track half-open SAs */
- this->half_open_table = calloc(this->table_size, sizeof(linked_list_t*));
+ this->half_open_table = calloc(this->table_size, sizeof(table_item_t*));
this->half_open_segments = calloc(this->segment_count, sizeof(shareable_segment_t));
for (i = 0; i < this->segment_count; i++)
{
@@ -1810,7 +2075,7 @@ ike_sa_manager_t *ike_sa_manager_create()
}
/* also for the hash table used for duplicate tests */
- this->connected_peers_table = calloc(this->table_size, sizeof(linked_list_t*));
+ this->connected_peers_table = calloc(this->table_size, sizeof(table_item_t*));
this->connected_peers_segments = calloc(this->segment_count, sizeof(shareable_segment_t));
for (i = 0; i < this->segment_count; i++)
{
@@ -1818,7 +2083,16 @@ ike_sa_manager_t *ike_sa_manager_create()
this->connected_peers_segments[i].count = 0;
}
+ /* and again for the table of hashes of seen initial IKE messages */
+ this->init_hashes_table = calloc(this->table_size, sizeof(table_item_t*));
+ this->init_hashes_segments = calloc(this->segment_count, sizeof(segment_t));
+ for (i = 0; i < this->segment_count; i++)
+ {
+ this->init_hashes_segments[i].mutex = mutex_create(MUTEX_TYPE_RECURSIVE);
+ this->init_hashes_segments[i].count = 0;
+ }
+
this->reuse_ikesa = lib->settings->get_bool(lib->settings,
- "charon.reuse_ikesa", TRUE);
+ "%s.reuse_ikesa", TRUE, charon->name);
return &this->public;
}
diff --git a/src/libcharon/sa/ike_sa_manager.h b/src/libcharon/sa/ike_sa_manager.h
index 5e542e7df..a68ae7763 100644
--- a/src/libcharon/sa/ike_sa_manager.h
+++ b/src/libcharon/sa/ike_sa_manager.h
@@ -52,10 +52,12 @@ struct ike_sa_manager_t {
/**
* Create and check out a new IKE_SA.
*
+ * @param version IKE version of this SA
* @param initiator TRUE for initiator, FALSE otherwise
* @returns created and checked out IKE_SA
*/
- ike_sa_t* (*checkout_new) (ike_sa_manager_t* this, bool initiator);
+ ike_sa_t* (*checkout_new) (ike_sa_manager_t* this, ike_version_t version,
+ bool initiator);
/**
* Checkout an IKE_SA by a message.
@@ -168,6 +170,20 @@ struct ike_sa_manager_t {
enumerator_t *(*create_enumerator) (ike_sa_manager_t* this, bool wait);
/**
+ * Create an enumerator over ike_sa_id_t*, matching peer identities.
+ *
+ * The remote peer is identified by its XAuth or EAP identity, if available.
+ *
+ * @param me local peer identity to match
+ * @param other remote peer identity to match
+ * @param family address family to match, 0 for any
+ * @return enumerator over ike_sa_id_t*
+ */
+ enumerator_t* (*create_id_enumerator)(ike_sa_manager_t *this,
+ identification_t *me, identification_t *other,
+ int family);
+
+ /**
* Checkin the SA after usage.
*
* If the IKE_SA is not registered in the manager, a new entry is created.
diff --git a/src/libcharon/sa/ikev1/authenticators/hybrid_authenticator.c b/src/libcharon/sa/ikev1/authenticators/hybrid_authenticator.c
new file mode 100644
index 000000000..689f5f376
--- /dev/null
+++ b/src/libcharon/sa/ikev1/authenticators/hybrid_authenticator.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 "hybrid_authenticator.h"
+
+#include <daemon.h>
+#include <sa/ikev1/authenticators/psk_v1_authenticator.h>
+
+typedef struct private_hybrid_authenticator_t private_hybrid_authenticator_t;
+
+/**
+ * Private data of an hybrid_authenticator_t object.
+ */
+struct private_hybrid_authenticator_t {
+
+ /**
+ * Public authenticator_t interface.
+ */
+ hybrid_authenticator_t public;
+
+ /**
+ * Public key authenticator
+ */
+ authenticator_t *sig;
+
+ /**
+ * HASH payload authenticator without credentials
+ */
+ authenticator_t *hash;
+};
+
+METHOD(authenticator_t, build_i, status_t,
+ private_hybrid_authenticator_t *this, message_t *message)
+{
+ return this->hash->build(this->hash, message);
+}
+
+METHOD(authenticator_t, process_r, status_t,
+ private_hybrid_authenticator_t *this, message_t *message)
+{
+ return this->hash->process(this->hash, message);
+}
+
+METHOD(authenticator_t, build_r, status_t,
+ private_hybrid_authenticator_t *this, message_t *message)
+{
+ return this->sig->build(this->sig, message);
+}
+
+METHOD(authenticator_t, process_i, status_t,
+ private_hybrid_authenticator_t *this, message_t *message)
+{
+ return this->sig->process(this->sig, message);
+}
+
+METHOD(authenticator_t, destroy, void,
+ private_hybrid_authenticator_t *this)
+{
+ DESTROY_IF(this->hash);
+ DESTROY_IF(this->sig);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+hybrid_authenticator_t *hybrid_authenticator_create(ike_sa_t *ike_sa,
+ bool initiator, diffie_hellman_t *dh,
+ chunk_t dh_value, chunk_t sa_payload,
+ chunk_t id_payload)
+{
+ private_hybrid_authenticator_t *this;
+
+ INIT(this,
+ .public = {
+ .authenticator = {
+ .is_mutual = (void*)return_false,
+ .destroy = _destroy,
+ },
+ },
+ .hash = (authenticator_t*)psk_v1_authenticator_create(ike_sa, initiator,
+ dh, dh_value, sa_payload, id_payload, TRUE),
+ .sig = authenticator_create_v1(ike_sa, initiator, AUTH_RSA, dh,
+ dh_value, sa_payload, chunk_clone(id_payload)),
+ );
+ if (!this->sig || !this->hash)
+ {
+ destroy(this);
+ return NULL;
+ }
+ if (initiator)
+ {
+ this->public.authenticator.build = _build_i;
+ this->public.authenticator.process = _process_i;
+ }
+ else
+ {
+ this->public.authenticator.build = _build_r;
+ this->public.authenticator.process = _process_r;
+ }
+ return &this->public;
+}
diff --git a/src/libcharon/sa/ikev1/authenticators/hybrid_authenticator.h b/src/libcharon/sa/ikev1/authenticators/hybrid_authenticator.h
new file mode 100644
index 000000000..69e596959
--- /dev/null
+++ b/src/libcharon/sa/ikev1/authenticators/hybrid_authenticator.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 hybrid_authenticator hybrid_authenticator
+ * @{ @ingroup authenticators_v1
+ */
+
+#ifndef HYBRID_AUTHENTICATOR_H_
+#define HYBRID_AUTHENTICATOR_H_
+
+typedef struct hybrid_authenticator_t hybrid_authenticator_t;
+
+#include <sa/authenticator.h>
+
+/**
+ * Implementation of authenticator_t using IKEv1 hybrid authentication.
+ */
+struct hybrid_authenticator_t {
+
+ /**
+ * Implemented authenticator_t interface.
+ */
+ authenticator_t authenticator;
+};
+
+/**
+ * Create an authenticator to build hybrid signatures.
+ *
+ * @param ike_sa associated IKE_SA
+ * @param initiator TRUE if we are the IKE_SA initiator
+ * @param dh diffie hellman key exchange
+ * @param dh_value others public diffie hellman value
+ * @param sa_payload generated SA payload data, without payload header
+ * @param id_payload encoded ID payload of peer to authenticate or verify
+ * without payload header (gets owned)
+ * @return hybrid authenticator
+ */
+hybrid_authenticator_t *hybrid_authenticator_create(ike_sa_t *ike_sa,
+ bool initiator, diffie_hellman_t *dh,
+ chunk_t dh_value, chunk_t sa_payload,
+ chunk_t id_payload);
+
+#endif /** HYBRID_AUTHENTICATOR_H_ @}*/
diff --git a/src/libcharon/sa/ikev1/authenticators/psk_v1_authenticator.c b/src/libcharon/sa/ikev1/authenticators/psk_v1_authenticator.c
new file mode 100644
index 000000000..ee15408c7
--- /dev/null
+++ b/src/libcharon/sa/ikev1/authenticators/psk_v1_authenticator.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 "psk_v1_authenticator.h"
+
+#include <daemon.h>
+#include <sa/ikev1/keymat_v1.h>
+#include <encoding/payloads/hash_payload.h>
+
+typedef struct private_psk_v1_authenticator_t private_psk_v1_authenticator_t;
+
+/**
+ * Private data of an psk_v1_authenticator_t object.
+ */
+struct private_psk_v1_authenticator_t {
+
+ /**
+ * Public authenticator_t interface.
+ */
+ psk_v1_authenticator_t public;
+
+ /**
+ * Assigned IKE_SA
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * TRUE if we are initiator
+ */
+ bool initiator;
+
+ /**
+ * DH key exchange
+ */
+ diffie_hellman_t *dh;
+
+ /**
+ * Others DH public value
+ */
+ chunk_t dh_value;
+
+ /**
+ * Encoded SA payload, without fixed header
+ */
+ chunk_t sa_payload;
+
+ /**
+ * Encoded ID payload, without fixed header
+ */
+ chunk_t id_payload;
+
+ /**
+ * Used for Hybrid authentication to build hash without PSK?
+ */
+ bool hybrid;
+};
+
+METHOD(authenticator_t, build, status_t,
+ private_psk_v1_authenticator_t *this, message_t *message)
+{
+ hash_payload_t *hash_payload;
+ keymat_v1_t *keymat;
+ chunk_t hash, dh;
+
+ this->dh->get_my_public_value(this->dh, &dh);
+ keymat = (keymat_v1_t*)this->ike_sa->get_keymat(this->ike_sa);
+ if (!keymat->get_hash(keymat, this->initiator, dh, this->dh_value,
+ this->ike_sa->get_id(this->ike_sa), this->sa_payload,
+ this->id_payload, &hash))
+ {
+ free(dh.ptr);
+ return FAILED;
+ }
+ free(dh.ptr);
+
+ hash_payload = hash_payload_create(HASH_V1);
+ hash_payload->set_hash(hash_payload, hash);
+ message->add_payload(message, &hash_payload->payload_interface);
+ free(hash.ptr);
+
+ return SUCCESS;
+}
+
+METHOD(authenticator_t, process, status_t,
+ private_psk_v1_authenticator_t *this, message_t *message)
+{
+ hash_payload_t *hash_payload;
+ keymat_v1_t *keymat;
+ chunk_t hash, dh;
+ auth_cfg_t *auth;
+
+ hash_payload = (hash_payload_t*)message->get_payload(message, HASH_V1);
+ if (!hash_payload)
+ {
+ DBG1(DBG_IKE, "HASH payload missing in message");
+ return FAILED;
+ }
+
+ this->dh->get_my_public_value(this->dh, &dh);
+ keymat = (keymat_v1_t*)this->ike_sa->get_keymat(this->ike_sa);
+ if (!keymat->get_hash(keymat, !this->initiator, this->dh_value, dh,
+ this->ike_sa->get_id(this->ike_sa), this->sa_payload,
+ this->id_payload, &hash))
+ {
+ free(dh.ptr);
+ return FAILED;
+ }
+ free(dh.ptr);
+ if (chunk_equals(hash, hash_payload->get_hash(hash_payload)))
+ {
+ free(hash.ptr);
+ if (!this->hybrid)
+ {
+ auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
+ }
+ return SUCCESS;
+ }
+ free(hash.ptr);
+ DBG1(DBG_IKE, "calculated HASH does not match HASH payload");
+ return FAILED;
+}
+
+METHOD(authenticator_t, destroy, void,
+ private_psk_v1_authenticator_t *this)
+{
+ chunk_free(&this->id_payload);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+psk_v1_authenticator_t *psk_v1_authenticator_create(ike_sa_t *ike_sa,
+ bool initiator, diffie_hellman_t *dh,
+ chunk_t dh_value, chunk_t sa_payload,
+ chunk_t id_payload, bool hybrid)
+{
+ private_psk_v1_authenticator_t *this;
+
+ INIT(this,
+ .public = {
+ .authenticator = {
+ .build = _build,
+ .process = _process,
+ .is_mutual = (void*)return_false,
+ .destroy = _destroy,
+ },
+ },
+ .ike_sa = ike_sa,
+ .initiator = initiator,
+ .dh = dh,
+ .dh_value = dh_value,
+ .sa_payload = sa_payload,
+ .id_payload = id_payload,
+ .hybrid = hybrid,
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/sa/ikev1/authenticators/psk_v1_authenticator.h b/src/libcharon/sa/ikev1/authenticators/psk_v1_authenticator.h
new file mode 100644
index 000000000..cc9e18ba1
--- /dev/null
+++ b/src/libcharon/sa/ikev1/authenticators/psk_v1_authenticator.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 psk_v1_authenticator psk_v1_authenticator
+ * @{ @ingroup authenticators_v1
+ */
+
+#ifndef PSK_V1_AUTHENTICATOR_H_
+#define PSK_V1_AUTHENTICATOR_H_
+
+typedef struct psk_v1_authenticator_t psk_v1_authenticator_t;
+
+#include <sa/authenticator.h>
+
+/**
+ * Implementation of authenticator_t using pre-shared keys for IKEv1.
+ */
+struct psk_v1_authenticator_t {
+
+ /**
+ * Implemented authenticator_t interface.
+ */
+ authenticator_t authenticator;
+};
+
+/**
+ * Create an authenticator to build PSK signatures.
+ *
+ * @param ike_sa associated IKE_SA
+ * @param initiator TRUE if we are the IKE_SA initiator
+ * @param dh diffie hellman key exchange
+ * @param dh_value others public diffie hellman value
+ * @param sa_payload generated SA payload data, without payload header
+ * @param id_payload encoded ID payload of peer to authenticate or verify
+ * without payload header (gets owned)
+ * @param hybrid TRUE if used for hybrid authentication without PSK
+ * @return PSK authenticator
+ */
+psk_v1_authenticator_t *psk_v1_authenticator_create(ike_sa_t *ike_sa,
+ bool initiator, diffie_hellman_t *dh,
+ chunk_t dh_value, chunk_t sa_payload,
+ chunk_t id_payload, bool hybrid);
+
+#endif /** PSK_V1_AUTHENTICATOR_H_ @}*/
diff --git a/src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.c b/src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.c
new file mode 100644
index 000000000..d81c77f0d
--- /dev/null
+++ b/src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 "pubkey_v1_authenticator.h"
+
+#include <daemon.h>
+#include <sa/ikev1/keymat_v1.h>
+#include <encoding/payloads/hash_payload.h>
+
+typedef struct private_pubkey_v1_authenticator_t private_pubkey_v1_authenticator_t;
+
+/**
+ * Private data of an pubkey_v1_authenticator_t object.
+ */
+struct private_pubkey_v1_authenticator_t {
+
+ /**
+ * Public authenticator_t interface.
+ */
+ pubkey_v1_authenticator_t public;
+
+ /**
+ * Assigned IKE_SA
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * TRUE if we are initiator
+ */
+ bool initiator;
+
+ /**
+ * DH key exchange
+ */
+ diffie_hellman_t *dh;
+
+ /**
+ * Others DH public value
+ */
+ chunk_t dh_value;
+
+ /**
+ * Encoded SA payload, without fixed header
+ */
+ chunk_t sa_payload;
+
+ /**
+ * Encoded ID payload, without fixed header
+ */
+ chunk_t id_payload;
+
+ /**
+ * Key type to use
+ */
+ key_type_t type;
+};
+
+METHOD(authenticator_t, build, status_t,
+ private_pubkey_v1_authenticator_t *this, message_t *message)
+{
+ hash_payload_t *sig_payload;
+ chunk_t hash, sig, dh;
+ keymat_v1_t *keymat;
+ status_t status;
+ private_key_t *private;
+ identification_t *id;
+ auth_cfg_t *auth;
+ signature_scheme_t scheme = SIGN_RSA_EMSA_PKCS1_NULL;
+
+ if (this->type == KEY_ECDSA)
+ {
+ scheme = SIGN_ECDSA_WITH_NULL;
+ }
+
+ id = this->ike_sa->get_my_id(this->ike_sa);
+ auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
+ private = lib->credmgr->get_private(lib->credmgr, this->type, id, auth);
+ if (!private)
+ {
+ DBG1(DBG_IKE, "no %N private key found for '%Y'",
+ key_type_names, this->type, id);
+ return NOT_FOUND;
+ }
+
+ this->dh->get_my_public_value(this->dh, &dh);
+ keymat = (keymat_v1_t*)this->ike_sa->get_keymat(this->ike_sa);
+ if (!keymat->get_hash(keymat, this->initiator, dh, this->dh_value,
+ this->ike_sa->get_id(this->ike_sa), this->sa_payload,
+ this->id_payload, &hash))
+ {
+ private->destroy(private);
+ free(dh.ptr);
+ return FAILED;
+ }
+ free(dh.ptr);
+
+ if (private->sign(private, scheme, hash, &sig))
+ {
+ sig_payload = hash_payload_create(SIGNATURE_V1);
+ sig_payload->set_hash(sig_payload, sig);
+ free(sig.ptr);
+ message->add_payload(message, &sig_payload->payload_interface);
+ status = SUCCESS;
+ DBG1(DBG_IKE, "authentication of '%Y' (myself) successful", id);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "authentication of '%Y' (myself) failed", id);
+ status = FAILED;
+ }
+ private->destroy(private);
+ free(hash.ptr);
+
+ return status;
+}
+
+METHOD(authenticator_t, process, status_t,
+ private_pubkey_v1_authenticator_t *this, message_t *message)
+{
+ chunk_t hash, sig, dh;
+ keymat_v1_t *keymat;
+ public_key_t *public;
+ hash_payload_t *sig_payload;
+ auth_cfg_t *auth, *current_auth;
+ enumerator_t *enumerator;
+ status_t status = NOT_FOUND;
+ identification_t *id;
+ signature_scheme_t scheme = SIGN_RSA_EMSA_PKCS1_NULL;
+
+ if (this->type == KEY_ECDSA)
+ {
+ scheme = SIGN_ECDSA_WITH_NULL;
+ }
+
+ sig_payload = (hash_payload_t*)message->get_payload(message, SIGNATURE_V1);
+ if (!sig_payload)
+ {
+ DBG1(DBG_IKE, "SIG payload missing in message");
+ return FAILED;
+ }
+
+ id = this->ike_sa->get_other_id(this->ike_sa);
+ this->dh->get_my_public_value(this->dh, &dh);
+ keymat = (keymat_v1_t*)this->ike_sa->get_keymat(this->ike_sa);
+ if (!keymat->get_hash(keymat, !this->initiator, this->dh_value, dh,
+ this->ike_sa->get_id(this->ike_sa), this->sa_payload,
+ this->id_payload, &hash))
+ {
+ free(dh.ptr);
+ return FAILED;
+ }
+ free(dh.ptr);
+
+ sig = sig_payload->get_hash(sig_payload);
+ auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
+ enumerator = lib->credmgr->create_public_enumerator(lib->credmgr, this->type,
+ id, auth);
+ while (enumerator->enumerate(enumerator, &public, &current_auth))
+ {
+ if (public->verify(public, scheme, hash, sig))
+ {
+ DBG1(DBG_IKE, "authentication of '%Y' with %N successful",
+ id, key_type_names, this->type);
+ status = SUCCESS;
+ auth->merge(auth, current_auth, FALSE);
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
+ break;
+ }
+ else
+ {
+ DBG1(DBG_IKE, "signature validation failed, looking for another key");
+ status = FAILED;
+ }
+ }
+ enumerator->destroy(enumerator);
+ free(hash.ptr);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_IKE, "no trusted %N public key found for '%Y'",
+ key_type_names, this->type, id);
+ }
+ return status;
+}
+
+METHOD(authenticator_t, destroy, void,
+ private_pubkey_v1_authenticator_t *this)
+{
+ chunk_free(&this->id_payload);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+pubkey_v1_authenticator_t *pubkey_v1_authenticator_create(ike_sa_t *ike_sa,
+ bool initiator, diffie_hellman_t *dh,
+ chunk_t dh_value, chunk_t sa_payload,
+ chunk_t id_payload, key_type_t type)
+{
+ private_pubkey_v1_authenticator_t *this;
+
+ INIT(this,
+ .public = {
+ .authenticator = {
+ .build = _build,
+ .process = _process,
+ .is_mutual = (void*)return_false,
+ .destroy = _destroy,
+ },
+ },
+ .ike_sa = ike_sa,
+ .initiator = initiator,
+ .dh = dh,
+ .dh_value = dh_value,
+ .sa_payload = sa_payload,
+ .id_payload = id_payload,
+ .type = type,
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.h b/src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.h
new file mode 100644
index 000000000..385664cf3
--- /dev/null
+++ b/src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 pubkey_v1_authenticator pubkey_v1_authenticator
+ * @{ @ingroup authenticators_v1
+ */
+
+#ifndef PUBKEY_V1_AUTHENTICATOR_H_
+#define PUBKEY_V1_AUTHENTICATOR_H_
+
+typedef struct pubkey_v1_authenticator_t pubkey_v1_authenticator_t;
+
+#include <sa/authenticator.h>
+
+/**
+ * Implementation of authenticator_t using public keys for IKEv1.
+ */
+struct pubkey_v1_authenticator_t {
+
+ /**
+ * Implemented authenticator_t interface.
+ */
+ authenticator_t authenticator;
+};
+
+/**
+ * Create an authenticator to build and verify public key signatures.
+ *
+ * @param ike_sa associated IKE_SA
+ * @param initiator TRUE if we are IKE_SA initiator
+ * @param dh diffie hellman key exchange
+ * @param dh_value others public diffie hellman value
+ * @param sa_payload generated SA payload data, without payload header
+ * @param id_payload encoded ID payload of peer to authenticate or verify
+ * without payload header (gets owned)
+ * @param type key type to use, KEY_RSA or KEY_ECDSA
+ * @return pubkey authenticator
+ */
+pubkey_v1_authenticator_t *pubkey_v1_authenticator_create(ike_sa_t *ike_sa,
+ bool initiator, diffie_hellman_t *dh,
+ chunk_t dh_value, chunk_t sa_payload,
+ chunk_t id_payload, key_type_t type);
+
+#endif /** PUBKEY_V1_AUTHENTICATOR_H_ @}*/
diff --git a/src/libcharon/sa/ikev1/keymat_v1.c b/src/libcharon/sa/ikev1/keymat_v1.c
new file mode 100644
index 000000000..cff344a34
--- /dev/null
+++ b/src/libcharon/sa/ikev1/keymat_v1.c
@@ -0,0 +1,1157 @@
+/*
+ * Copyright (C) 2011 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 "keymat_v1.h"
+
+#include <daemon.h>
+#include <encoding/generator.h>
+#include <encoding/payloads/nonce_payload.h>
+#include <utils/linked_list.h>
+
+typedef struct private_keymat_v1_t private_keymat_v1_t;
+
+/**
+ * Max. number of IVs to track.
+ */
+#define MAX_IV 3
+
+/**
+ * Max. number of Quick Modes to track.
+ */
+#define MAX_QM 2
+
+/**
+ * Data stored for IVs
+ */
+typedef struct {
+ /** message ID */
+ u_int32_t mid;
+ /** current IV */
+ chunk_t iv;
+ /** last block of encrypted message */
+ chunk_t last_block;
+} iv_data_t;
+
+/**
+ * Private data of an keymat_t object.
+ */
+struct private_keymat_v1_t {
+
+ /**
+ * Public keymat_v1_t interface.
+ */
+ keymat_v1_t public;
+
+ /**
+ * IKE_SA Role, initiator or responder
+ */
+ bool initiator;
+
+ /**
+ * General purpose PRF
+ */
+ prf_t *prf;
+
+ /**
+ * PRF to create Phase 1 HASH payloads
+ */
+ prf_t *prf_auth;
+
+ /**
+ * Crypter wrapped in an aead_t interface
+ */
+ aead_t *aead;
+
+ /**
+ * Hasher used for IV generation (and other things like e.g. NAT-T)
+ */
+ hasher_t *hasher;
+
+ /**
+ * Key used for authentication during main mode
+ */
+ chunk_t skeyid;
+
+ /**
+ * Key to derive key material from for non-ISAKMP SAs, rekeying
+ */
+ chunk_t skeyid_d;
+
+ /**
+ * Key used for authentication after main mode
+ */
+ chunk_t skeyid_a;
+
+ /**
+ * Phase 1 IV
+ */
+ iv_data_t phase1_iv;
+
+ /**
+ * Keep track of IVs for exchanges after phase 1. We store only a limited
+ * number of IVs in an MRU sort of way. Stores iv_data_t objects.
+ */
+ linked_list_t *ivs;
+
+ /**
+ * Keep track of Nonces during Quick Mode exchanges. Only a limited number
+ * of QMs are tracked at the same time. Stores qm_data_t objects.
+ */
+ linked_list_t *qms;
+};
+
+
+/**
+ * Destroy an iv_data_t object.
+ */
+static void iv_data_destroy(iv_data_t *this)
+{
+ chunk_free(&this->last_block);
+ chunk_free(&this->iv);
+ free(this);
+}
+
+/**
+ * Data stored for Quick Mode exchanges
+ */
+typedef struct {
+ /** message ID */
+ u_int32_t mid;
+ /** Ni_b (Nonce from first message) */
+ chunk_t n_i;
+ /** Nr_b (Nonce from second message) */
+ chunk_t n_r;
+} qm_data_t;
+
+/**
+ * Destroy a qm_data_t object.
+ */
+static void qm_data_destroy(qm_data_t *this)
+{
+ chunk_free(&this->n_i);
+ chunk_free(&this->n_r);
+ free(this);
+}
+
+/**
+ * Constants used in key derivation.
+ */
+static const chunk_t octet_0 = chunk_from_chars(0x00);
+static const chunk_t octet_1 = chunk_from_chars(0x01);
+static const chunk_t octet_2 = chunk_from_chars(0x02);
+
+/**
+ * Simple aead_t implementation without support for authentication.
+ */
+typedef struct {
+ /** implements aead_t interface */
+ aead_t aead;
+ /** crypter to be used */
+ crypter_t *crypter;
+} private_aead_t;
+
+
+METHOD(aead_t, encrypt, bool,
+ private_aead_t *this, chunk_t plain, chunk_t assoc, chunk_t iv,
+ chunk_t *encrypted)
+{
+ return this->crypter->encrypt(this->crypter, plain, iv, encrypted);
+}
+
+METHOD(aead_t, decrypt, bool,
+ private_aead_t *this, chunk_t encrypted, chunk_t assoc, chunk_t iv,
+ chunk_t *plain)
+{
+ return this->crypter->decrypt(this->crypter, encrypted, iv, plain);
+}
+
+METHOD(aead_t, get_block_size, size_t,
+ private_aead_t *this)
+{
+ return this->crypter->get_block_size(this->crypter);
+}
+
+METHOD(aead_t, get_icv_size, size_t,
+ private_aead_t *this)
+{
+ return 0;
+}
+
+METHOD(aead_t, get_iv_size, size_t,
+ private_aead_t *this)
+{
+ /* in order to create the messages properly we return 0 here */
+ return 0;
+}
+
+METHOD(aead_t, get_key_size, size_t,
+ private_aead_t *this)
+{
+ return this->crypter->get_key_size(this->crypter);
+}
+
+METHOD(aead_t, set_key, bool,
+ private_aead_t *this, chunk_t key)
+{
+ return this->crypter->set_key(this->crypter, key);
+}
+
+METHOD(aead_t, aead_destroy, void,
+ private_aead_t *this)
+{
+ this->crypter->destroy(this->crypter);
+ free(this);
+}
+
+/**
+ * Expand SKEYID_e according to Appendix B in RFC 2409.
+ * TODO-IKEv1: verify keys (e.g. for weak keys, see Appendix B)
+ */
+static bool expand_skeyid_e(chunk_t skeyid_e, size_t key_size, prf_t *prf,
+ chunk_t *ka)
+{
+ size_t block_size;
+ chunk_t seed;
+ int i;
+
+ if (skeyid_e.len >= key_size)
+ { /* no expansion required, reduce to key_size */
+ skeyid_e.len = key_size;
+ *ka = skeyid_e;
+ return TRUE;
+ }
+ block_size = prf->get_block_size(prf);
+ *ka = chunk_alloc((key_size / block_size + 1) * block_size);
+ ka->len = key_size;
+
+ /* Ka = K1 | K2 | ..., K1 = prf(SKEYID_e, 0), K2 = prf(SKEYID_e, K1) ... */
+ if (!prf->set_key(prf, skeyid_e))
+ {
+ chunk_clear(ka);
+ chunk_clear(&skeyid_e);
+ return FALSE;
+ }
+ seed = octet_0;
+ for (i = 0; i < key_size; i += block_size)
+ {
+ if (!prf->get_bytes(prf, seed, ka->ptr + i))
+ {
+ chunk_clear(ka);
+ chunk_clear(&skeyid_e);
+ return FALSE;
+ }
+ seed = chunk_create(ka->ptr + i, block_size);
+ }
+ chunk_clear(&skeyid_e);
+ return TRUE;
+}
+
+/**
+ * Create a simple implementation of the aead_t interface which only encrypts
+ * or decrypts data.
+ */
+static aead_t *create_aead(proposal_t *proposal, prf_t *prf, chunk_t skeyid_e)
+{
+ private_aead_t *this;
+ u_int16_t alg, key_size;
+ crypter_t *crypter;
+ chunk_t ka;
+
+ if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg,
+ &key_size))
+ {
+ DBG1(DBG_IKE, "no %N selected",
+ transform_type_names, ENCRYPTION_ALGORITHM);
+ return NULL;
+ }
+ crypter = lib->crypto->create_crypter(lib->crypto, alg, key_size / 8);
+ if (!crypter)
+ {
+ DBG1(DBG_IKE, "%N %N (key size %d) not supported!",
+ transform_type_names, ENCRYPTION_ALGORITHM,
+ encryption_algorithm_names, alg, key_size);
+ return NULL;
+ }
+ key_size = crypter->get_key_size(crypter);
+ if (!expand_skeyid_e(skeyid_e, crypter->get_key_size(crypter), prf, &ka))
+ {
+ return NULL;
+ }
+ DBG4(DBG_IKE, "encryption key Ka %B", &ka);
+ if (!crypter->set_key(crypter, ka))
+ {
+ chunk_clear(&ka);
+ return NULL;
+ }
+ chunk_clear(&ka);
+
+ INIT(this,
+ .aead = {
+ .encrypt = _encrypt,
+ .decrypt = _decrypt,
+ .get_block_size = _get_block_size,
+ .get_icv_size = _get_icv_size,
+ .get_iv_size = _get_iv_size,
+ .get_key_size = _get_key_size,
+ .set_key = _set_key,
+ .destroy = _aead_destroy,
+ },
+ .crypter = crypter,
+ );
+ return &this->aead;
+}
+
+/**
+ * Converts integrity algorithm to PRF algorithm
+ */
+static u_int16_t auth_to_prf(u_int16_t alg)
+{
+ switch (alg)
+ {
+ case AUTH_HMAC_SHA1_96:
+ return PRF_HMAC_SHA1;
+ case AUTH_HMAC_SHA2_256_128:
+ return PRF_HMAC_SHA2_256;
+ case AUTH_HMAC_SHA2_384_192:
+ return PRF_HMAC_SHA2_384;
+ case AUTH_HMAC_SHA2_512_256:
+ return PRF_HMAC_SHA2_512;
+ case AUTH_HMAC_MD5_96:
+ return PRF_HMAC_MD5;
+ case AUTH_AES_XCBC_96:
+ return PRF_AES128_XCBC;
+ default:
+ return PRF_UNDEFINED;
+ }
+}
+
+/**
+ * Converts integrity algorithm to hash algorithm
+ */
+static u_int16_t auth_to_hash(u_int16_t alg)
+{
+ switch (alg)
+ {
+ case AUTH_HMAC_SHA1_96:
+ return HASH_SHA1;
+ case AUTH_HMAC_SHA2_256_128:
+ return HASH_SHA256;
+ case AUTH_HMAC_SHA2_384_192:
+ return HASH_SHA384;
+ case AUTH_HMAC_SHA2_512_256:
+ return HASH_SHA512;
+ case AUTH_HMAC_MD5_96:
+ return HASH_MD5;
+ default:
+ return HASH_UNKNOWN;
+ }
+}
+
+/**
+ * Adjust the key length for PRF algorithms that expect a fixed key length.
+ */
+static void adjust_keylen(u_int16_t alg, chunk_t *key)
+{
+ switch (alg)
+ {
+ case PRF_AES128_XCBC:
+ /* while rfc4434 defines variable keys for AES-XCBC, rfc3664 does
+ * not and therefore fixed key semantics apply to XCBC for key
+ * derivation. */
+ key->len = min(key->len, 16);
+ break;
+ default:
+ /* all other algorithms use variable key length */
+ break;
+ }
+}
+
+METHOD(keymat_v1_t, derive_ike_keys, bool,
+ private_keymat_v1_t *this, proposal_t *proposal, diffie_hellman_t *dh,
+ chunk_t dh_other, chunk_t nonce_i, chunk_t nonce_r, ike_sa_id_t *id,
+ auth_method_t auth, shared_key_t *shared_key)
+{
+ chunk_t g_xy, g_xi, g_xr, dh_me, spi_i, spi_r, nonces, data, skeyid_e;
+ chunk_t skeyid;
+ u_int16_t alg;
+
+ spi_i = chunk_alloca(sizeof(u_int64_t));
+ spi_r = chunk_alloca(sizeof(u_int64_t));
+
+ if (!proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL))
+ { /* no PRF negotiated, use HMAC version of integrity algorithm instead */
+ if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, NULL)
+ || (alg = auth_to_prf(alg)) == PRF_UNDEFINED)
+ {
+ DBG1(DBG_IKE, "no %N selected",
+ transform_type_names, PSEUDO_RANDOM_FUNCTION);
+ return FALSE;
+ }
+ }
+ this->prf = lib->crypto->create_prf(lib->crypto, alg);
+ if (!this->prf)
+ {
+ DBG1(DBG_IKE, "%N %N not supported!",
+ transform_type_names, PSEUDO_RANDOM_FUNCTION,
+ pseudo_random_function_names, alg);
+ return FALSE;
+ }
+ if (this->prf->get_block_size(this->prf) <
+ this->prf->get_key_size(this->prf))
+ { /* TODO-IKEv1: support PRF output expansion (RFC 2409, Appendix B) */
+ DBG1(DBG_IKE, "expansion of %N %N output not supported!",
+ transform_type_names, PSEUDO_RANDOM_FUNCTION,
+ pseudo_random_function_names, alg);
+ return FALSE;
+ }
+
+ if (dh->get_shared_secret(dh, &g_xy) != SUCCESS)
+ {
+ return FALSE;
+ }
+ DBG4(DBG_IKE, "shared Diffie Hellman secret %B", &g_xy);
+
+ *((u_int64_t*)spi_i.ptr) = id->get_initiator_spi(id);
+ *((u_int64_t*)spi_r.ptr) = id->get_responder_spi(id);
+ nonces = chunk_cata("cc", nonce_i, nonce_r);
+
+ switch (auth)
+ {
+ case AUTH_PSK:
+ case AUTH_XAUTH_INIT_PSK:
+ { /* SKEYID = prf(pre-shared-key, Ni_b | Nr_b) */
+ chunk_t psk;
+ if (!shared_key)
+ {
+ chunk_clear(&g_xy);
+ return FALSE;
+ }
+ psk = shared_key->get_key(shared_key);
+ adjust_keylen(alg, &psk);
+ if (!this->prf->set_key(this->prf, psk) ||
+ !this->prf->allocate_bytes(this->prf, nonces, &skeyid))
+ {
+ chunk_clear(&g_xy);
+ return FALSE;
+ }
+ break;
+ }
+ case AUTH_RSA:
+ case AUTH_ECDSA_256:
+ case AUTH_ECDSA_384:
+ case AUTH_ECDSA_521:
+ case AUTH_XAUTH_INIT_RSA:
+ case AUTH_XAUTH_RESP_RSA:
+ case AUTH_HYBRID_INIT_RSA:
+ case AUTH_HYBRID_RESP_RSA:
+ {
+ if (!this->prf->set_key(this->prf, nonces) ||
+ !this->prf->allocate_bytes(this->prf, g_xy, &skeyid))
+ {
+ chunk_clear(&g_xy);
+ return FALSE;
+ }
+ break;
+ }
+ default:
+ /* TODO-IKEv1: implement key derivation for other schemes */
+ /* authentication class not supported */
+ chunk_clear(&g_xy);
+ return FALSE;
+ }
+ adjust_keylen(alg, &skeyid);
+ DBG4(DBG_IKE, "SKEYID %B", &skeyid);
+
+ /* SKEYID_d = prf(SKEYID, g^xy | CKY-I | CKY-R | 0) */
+ data = chunk_cat("cccc", g_xy, spi_i, spi_r, octet_0);
+ if (!this->prf->set_key(this->prf, skeyid) ||
+ !this->prf->allocate_bytes(this->prf, data, &this->skeyid_d))
+ {
+ chunk_clear(&g_xy);
+ chunk_clear(&data);
+ return FALSE;
+ }
+ chunk_clear(&data);
+ DBG4(DBG_IKE, "SKEYID_d %B", &this->skeyid_d);
+
+ /* SKEYID_a = prf(SKEYID, SKEYID_d | g^xy | CKY-I | CKY-R | 1) */
+ data = chunk_cat("ccccc", this->skeyid_d, g_xy, spi_i, spi_r, octet_1);
+ if (!this->prf->allocate_bytes(this->prf, data, &this->skeyid_a))
+ {
+ chunk_clear(&g_xy);
+ chunk_clear(&data);
+ return FALSE;
+ }
+ chunk_clear(&data);
+ DBG4(DBG_IKE, "SKEYID_a %B", &this->skeyid_a);
+
+ /* SKEYID_e = prf(SKEYID, SKEYID_a | g^xy | CKY-I | CKY-R | 2) */
+ data = chunk_cat("ccccc", this->skeyid_a, g_xy, spi_i, spi_r, octet_2);
+ if (!this->prf->allocate_bytes(this->prf, data, &skeyid_e))
+ {
+ chunk_clear(&g_xy);
+ chunk_clear(&data);
+ return FALSE;
+ }
+ chunk_clear(&data);
+ DBG4(DBG_IKE, "SKEYID_e %B", &skeyid_e);
+
+ chunk_clear(&g_xy);
+
+ switch (auth)
+ {
+ case AUTH_ECDSA_256:
+ alg = PRF_HMAC_SHA2_256;
+ break;
+ case AUTH_ECDSA_384:
+ alg = PRF_HMAC_SHA2_384;
+ break;
+ case AUTH_ECDSA_521:
+ alg = PRF_HMAC_SHA2_512;
+ break;
+ default:
+ /* use proposal algorithm */
+ break;
+ }
+ this->prf_auth = lib->crypto->create_prf(lib->crypto, alg);
+ if (!this->prf_auth)
+ {
+ DBG1(DBG_IKE, "%N %N not supported!",
+ transform_type_names, PSEUDO_RANDOM_FUNCTION,
+ pseudo_random_function_names, alg);
+ chunk_clear(&skeyid);
+ return FALSE;
+ }
+ if (!this->prf_auth->set_key(this->prf_auth, skeyid))
+ {
+ chunk_clear(&skeyid);
+ return FALSE;
+ }
+ chunk_clear(&skeyid);
+
+ this->aead = create_aead(proposal, this->prf, skeyid_e);
+ if (!this->aead)
+ {
+ return FALSE;
+ }
+ if (!this->hasher && !this->public.create_hasher(&this->public, proposal))
+ {
+ return FALSE;
+ }
+
+ dh->get_my_public_value(dh, &dh_me);
+ g_xi = this->initiator ? dh_me : dh_other;
+ g_xr = this->initiator ? dh_other : dh_me;
+
+ /* initial IV = hash(g^xi | g^xr) */
+ data = chunk_cata("cc", g_xi, g_xr);
+ chunk_free(&dh_me);
+ if (!this->hasher->allocate_hash(this->hasher, data, &this->phase1_iv.iv))
+ {
+ return FALSE;
+ }
+ if (this->phase1_iv.iv.len > this->aead->get_block_size(this->aead))
+ {
+ this->phase1_iv.iv.len = this->aead->get_block_size(this->aead);
+ }
+ DBG4(DBG_IKE, "initial IV %B", &this->phase1_iv.iv);
+
+ return TRUE;
+}
+
+METHOD(keymat_v1_t, derive_child_keys, bool,
+ private_keymat_v1_t *this, proposal_t *proposal, diffie_hellman_t *dh,
+ u_int32_t spi_i, u_int32_t spi_r, chunk_t nonce_i, chunk_t nonce_r,
+ chunk_t *encr_i, chunk_t *integ_i, chunk_t *encr_r, chunk_t *integ_r)
+{
+ u_int16_t enc_alg, int_alg, enc_size = 0, int_size = 0;
+ u_int8_t protocol;
+ prf_plus_t *prf_plus;
+ chunk_t seed, secret = chunk_empty;
+ bool success = FALSE;
+
+ if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
+ &enc_alg, &enc_size))
+ {
+ DBG2(DBG_CHD, " using %N for encryption",
+ encryption_algorithm_names, enc_alg);
+
+ if (!enc_size)
+ {
+ enc_size = keymat_get_keylen_encr(enc_alg);
+ }
+ if (enc_alg != ENCR_NULL && !enc_size)
+ {
+ DBG1(DBG_CHD, "no keylength defined for %N",
+ encryption_algorithm_names, enc_alg);
+ return FALSE;
+ }
+ /* to bytes */
+ enc_size /= 8;
+
+ /* CCM/GCM/CTR/GMAC needs additional bytes */
+ switch (enc_alg)
+ {
+ case ENCR_AES_CCM_ICV8:
+ case ENCR_AES_CCM_ICV12:
+ case ENCR_AES_CCM_ICV16:
+ case ENCR_CAMELLIA_CCM_ICV8:
+ case ENCR_CAMELLIA_CCM_ICV12:
+ case ENCR_CAMELLIA_CCM_ICV16:
+ enc_size += 3;
+ break;
+ case ENCR_AES_GCM_ICV8:
+ case ENCR_AES_GCM_ICV12:
+ case ENCR_AES_GCM_ICV16:
+ case ENCR_AES_CTR:
+ case ENCR_NULL_AUTH_AES_GMAC:
+ enc_size += 4;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
+ &int_alg, &int_size))
+ {
+ DBG2(DBG_CHD, " using %N for integrity",
+ integrity_algorithm_names, int_alg);
+
+ if (!int_size)
+ {
+ int_size = keymat_get_keylen_integ(int_alg);
+ }
+ if (!int_size)
+ {
+ DBG1(DBG_CHD, "no keylength defined for %N",
+ integrity_algorithm_names, int_alg);
+ return FALSE;
+ }
+ /* to bytes */
+ int_size /= 8;
+ }
+
+ /* KEYMAT = prf+(SKEYID_d, [ g(qm)^xy | ] protocol | SPI | Ni_b | Nr_b) */
+ if (!this->prf->set_key(this->prf, this->skeyid_d))
+ {
+ return FALSE;
+ }
+ protocol = proposal->get_protocol(proposal);
+ if (dh)
+ {
+ if (dh->get_shared_secret(dh, &secret) != SUCCESS)
+ {
+ return FALSE;
+ }
+ DBG4(DBG_CHD, "DH secret %B", &secret);
+ }
+
+ *encr_r = *integ_r = *encr_i = *integ_i = chunk_empty;
+ seed = chunk_cata("ccccc", secret, chunk_from_thing(protocol),
+ chunk_from_thing(spi_r), nonce_i, nonce_r);
+ DBG4(DBG_CHD, "initiator SA seed %B", &seed);
+
+ prf_plus = prf_plus_create(this->prf, FALSE, seed);
+ if (!prf_plus ||
+ !prf_plus->allocate_bytes(prf_plus, enc_size, encr_i) ||
+ !prf_plus->allocate_bytes(prf_plus, int_size, integ_i))
+ {
+ goto failure;
+ }
+
+ seed = chunk_cata("ccccc", secret, chunk_from_thing(protocol),
+ chunk_from_thing(spi_i), nonce_i, nonce_r);
+ DBG4(DBG_CHD, "responder SA seed %B", &seed);
+ prf_plus->destroy(prf_plus);
+ prf_plus = prf_plus_create(this->prf, FALSE, seed);
+ if (!prf_plus ||
+ !prf_plus->allocate_bytes(prf_plus, enc_size, encr_r) ||
+ !prf_plus->allocate_bytes(prf_plus, int_size, integ_r))
+ {
+ goto failure;
+ }
+
+ if (enc_size)
+ {
+ DBG4(DBG_CHD, "encryption initiator key %B", encr_i);
+ DBG4(DBG_CHD, "encryption responder key %B", encr_r);
+ }
+ if (int_size)
+ {
+ DBG4(DBG_CHD, "integrity initiator key %B", integ_i);
+ DBG4(DBG_CHD, "integrity responder key %B", integ_r);
+ }
+ success = TRUE;
+
+failure:
+ if (!success)
+ {
+ chunk_clear(encr_i);
+ chunk_clear(integ_i);
+ chunk_clear(encr_r);
+ chunk_clear(integ_r);
+ }
+ DESTROY_IF(prf_plus);
+ chunk_clear(&secret);
+
+ return success;
+}
+
+METHOD(keymat_v1_t, create_hasher, bool,
+ private_keymat_v1_t *this, proposal_t *proposal)
+{
+ u_int16_t alg;
+ if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, NULL) ||
+ (alg = auth_to_hash(alg)) == HASH_UNKNOWN)
+ {
+ DBG1(DBG_IKE, "no %N selected", transform_type_names, HASH_ALGORITHM);
+ return FALSE;
+ }
+ this->hasher = lib->crypto->create_hasher(lib->crypto, alg);
+ if (!this->hasher)
+ {
+ DBG1(DBG_IKE, "%N %N not supported!",
+ transform_type_names, HASH_ALGORITHM,
+ hash_algorithm_names, alg);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+METHOD(keymat_v1_t, get_hasher, hasher_t*,
+ private_keymat_v1_t *this)
+{
+ return this->hasher;
+}
+
+METHOD(keymat_v1_t, get_hash, bool,
+ private_keymat_v1_t *this, bool initiator, chunk_t dh, chunk_t dh_other,
+ ike_sa_id_t *ike_sa_id, chunk_t sa_i, chunk_t id, chunk_t *hash)
+{
+ chunk_t data;
+ u_int64_t spi, spi_other;
+
+ /* HASH_I = prf(SKEYID, g^xi | g^xr | CKY-I | CKY-R | SAi_b | IDii_b )
+ * HASH_R = prf(SKEYID, g^xr | g^xi | CKY-R | CKY-I | SAi_b | IDir_b )
+ */
+ if (initiator)
+ {
+ spi = ike_sa_id->get_initiator_spi(ike_sa_id);
+ spi_other = ike_sa_id->get_responder_spi(ike_sa_id);
+ }
+ else
+ {
+ spi_other = ike_sa_id->get_initiator_spi(ike_sa_id);
+ spi = ike_sa_id->get_responder_spi(ike_sa_id);
+ }
+ data = chunk_cat("cccccc", dh, dh_other,
+ chunk_from_thing(spi), chunk_from_thing(spi_other),
+ sa_i, id);
+
+ DBG3(DBG_IKE, "HASH_%c data %B", initiator ? 'I' : 'R', &data);
+
+ if (!this->prf_auth->allocate_bytes(this->prf_auth, data, hash))
+ {
+ free(data.ptr);
+ return FALSE;
+ }
+
+ DBG3(DBG_IKE, "HASH_%c %B", initiator ? 'I' : 'R', hash);
+
+ free(data.ptr);
+ return TRUE;
+}
+
+/**
+ * Get the nonce value found in the given message.
+ * Returns FALSE if none is found.
+ */
+static bool get_nonce(message_t *message, chunk_t *n)
+{
+ nonce_payload_t *nonce;
+ nonce = (nonce_payload_t*)message->get_payload(message, NONCE_V1);
+ if (nonce)
+ {
+ *n = nonce->get_nonce(nonce);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Generate the message data in order to generate the hashes.
+ */
+static chunk_t get_message_data(message_t *message, generator_t *generator)
+{
+ payload_t *payload, *next;
+ enumerator_t *enumerator;
+ u_int32_t *lenpos;
+
+ if (message->is_encoded(message))
+ { /* inbound, although the message is generated, we cannot access the
+ * cleartext message data, so generate it anyway */
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ if (payload->get_type(payload) == HASH_V1)
+ {
+ continue;
+ }
+ generator->generate_payload(generator, payload);
+ }
+ enumerator->destroy(enumerator);
+ }
+ else
+ {
+ /* outbound, generate the payloads (there is no HASH payload yet) */
+ enumerator = message->create_payload_enumerator(message);
+ if (enumerator->enumerate(enumerator, &payload))
+ {
+ while (enumerator->enumerate(enumerator, &next))
+ {
+ payload->set_next_type(payload, next->get_type(next));
+ generator->generate_payload(generator, payload);
+ payload = next;
+ }
+ payload->set_next_type(payload, NO_PAYLOAD);
+ generator->generate_payload(generator, payload);
+ }
+ enumerator->destroy(enumerator);
+ }
+ return generator->get_chunk(generator, &lenpos);
+}
+
+/**
+ * Try to find data about a Quick Mode with the given message ID,
+ * if none is found, state is generated.
+ */
+static qm_data_t *lookup_quick_mode(private_keymat_v1_t *this, u_int32_t mid)
+{
+ enumerator_t *enumerator;
+ qm_data_t *qm, *found = NULL;
+
+ enumerator = this->qms->create_enumerator(this->qms);
+ while (enumerator->enumerate(enumerator, &qm))
+ {
+ if (qm->mid == mid)
+ { /* state gets moved to the front of the list */
+ this->qms->remove_at(this->qms, enumerator);
+ found = qm;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (!found)
+ {
+ INIT(found,
+ .mid = mid,
+ );
+ }
+ this->qms->insert_first(this->qms, found);
+ /* remove least recently used state if maximum reached */
+ if (this->qms->get_count(this->qms) > MAX_QM &&
+ this->qms->remove_last(this->qms, (void**)&qm) == SUCCESS)
+ {
+ qm_data_destroy(qm);
+ }
+ return found;
+}
+
+METHOD(keymat_v1_t, get_hash_phase2, bool,
+ private_keymat_v1_t *this, message_t *message, chunk_t *hash)
+{
+ u_int32_t mid, mid_n;
+ chunk_t data = chunk_empty;
+ bool add_message = TRUE;
+ char *name = "Hash";
+
+ if (!this->prf)
+ { /* no keys derived yet */
+ return FALSE;
+ }
+
+ mid = message->get_message_id(message);
+ mid_n = htonl(mid);
+
+ /* Hashes are simple for most exchanges in Phase 2:
+ * Hash = prf(SKEYID_a, M-ID | Complete message after HASH payload)
+ * For Quick Mode there are three hashes:
+ * Hash(1) = same as above
+ * Hash(2) = prf(SKEYID_a, M-ID | Ni_b | Message after HASH payload)
+ * Hash(3) = prf(SKEYID_a, 0 | M-ID | Ni_b | Nr_b)
+ * So, for Quick Mode we keep track of the nonce values.
+ */
+ switch (message->get_exchange_type(message))
+ {
+ case QUICK_MODE:
+ {
+ qm_data_t *qm = lookup_quick_mode(this, mid);
+ if (!qm->n_i.ptr)
+ { /* Hash(1) = prf(SKEYID_a, M-ID | Message after HASH payload) */
+ name = "Hash(1)";
+ if (!get_nonce(message, &qm->n_i))
+ {
+ return FALSE;
+ }
+ data = chunk_from_thing(mid_n);
+ }
+ else if (!qm->n_r.ptr)
+ { /* Hash(2) = prf(SKEYID_a, M-ID | Ni_b | Message after HASH) */
+ name = "Hash(2)";
+ if (!get_nonce(message, &qm->n_r))
+ {
+ return FALSE;
+ }
+ data = chunk_cata("cc", chunk_from_thing(mid_n), qm->n_i);
+ }
+ else
+ { /* Hash(3) = prf(SKEYID_a, 0 | M-ID | Ni_b | Nr_b) */
+ name = "Hash(3)";
+ data = chunk_cata("cccc", octet_0, chunk_from_thing(mid_n),
+ qm->n_i, qm->n_r);
+ add_message = FALSE;
+ /* we don't need the state anymore */
+ this->qms->remove(this->qms, qm, NULL);
+ qm_data_destroy(qm);
+ }
+ break;
+ }
+ case TRANSACTION:
+ case INFORMATIONAL_V1:
+ /* Hash = prf(SKEYID_a, M-ID | Message after HASH payload) */
+ data = chunk_from_thing(mid_n);
+ break;
+ default:
+ return FALSE;
+ }
+ if (!this->prf->set_key(this->prf, this->skeyid_a))
+ {
+ return FALSE;
+ }
+ if (add_message)
+ {
+ generator_t *generator;
+ chunk_t msg;
+
+ generator = generator_create_no_dbg();
+ msg = get_message_data(message, generator);
+ if (!this->prf->allocate_bytes(this->prf, data, NULL) ||
+ !this->prf->allocate_bytes(this->prf, msg, hash))
+ {
+ generator->destroy(generator);
+ return FALSE;
+ }
+ generator->destroy(generator);
+ }
+ else
+ {
+ if (!this->prf->allocate_bytes(this->prf, data, hash))
+ {
+ return FALSE;
+ }
+ }
+ DBG3(DBG_IKE, "%s %B", name, hash);
+ return TRUE;
+}
+
+/**
+ * Generate an IV
+ */
+static bool generate_iv(private_keymat_v1_t *this, iv_data_t *iv)
+{
+ if (iv->mid == 0 || iv->iv.ptr)
+ { /* use last block of previous encrypted message */
+ chunk_free(&iv->iv);
+ iv->iv = iv->last_block;
+ iv->last_block = chunk_empty;
+ }
+ else
+ {
+ /* initial phase 2 IV = hash(last_phase1_block | mid) */
+ u_int32_t net;;
+ chunk_t data;
+
+ net = htonl(iv->mid);
+ data = chunk_cata("cc", this->phase1_iv.iv, chunk_from_thing(net));
+ if (!this->hasher->allocate_hash(this->hasher, data, &iv->iv))
+ {
+ return FALSE;
+ }
+ if (iv->iv.len > this->aead->get_block_size(this->aead))
+ {
+ iv->iv.len = this->aead->get_block_size(this->aead);
+ }
+ }
+ DBG4(DBG_IKE, "next IV for MID %u %B", iv->mid, &iv->iv);
+ return TRUE;
+}
+
+/**
+ * Try to find an IV for the given message ID, if not found, generate it.
+ */
+static iv_data_t *lookup_iv(private_keymat_v1_t *this, u_int32_t mid)
+{
+ enumerator_t *enumerator;
+ iv_data_t *iv, *found = NULL;
+
+ if (mid == 0)
+ {
+ return &this->phase1_iv;
+ }
+
+ enumerator = this->ivs->create_enumerator(this->ivs);
+ while (enumerator->enumerate(enumerator, &iv))
+ {
+ if (iv->mid == mid)
+ { /* IV gets moved to the front of the list */
+ this->ivs->remove_at(this->ivs, enumerator);
+ found = iv;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (!found)
+ {
+ INIT(found,
+ .mid = mid,
+ );
+ if (!generate_iv(this, found))
+ {
+ iv_data_destroy(found);
+ return NULL;
+ }
+ }
+ this->ivs->insert_first(this->ivs, found);
+ /* remove least recently used IV if maximum reached */
+ if (this->ivs->get_count(this->ivs) > MAX_IV &&
+ this->ivs->remove_last(this->ivs, (void**)&iv) == SUCCESS)
+ {
+ iv_data_destroy(iv);
+ }
+ return found;
+}
+
+METHOD(keymat_v1_t, get_iv, bool,
+ private_keymat_v1_t *this, u_int32_t mid, chunk_t *out)
+{
+ iv_data_t *iv;
+
+ iv = lookup_iv(this, mid);
+ if (iv)
+ {
+ *out = iv->iv;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+METHOD(keymat_v1_t, update_iv, bool,
+ private_keymat_v1_t *this, u_int32_t mid, chunk_t last_block)
+{
+ iv_data_t *iv = lookup_iv(this, mid);
+ if (iv)
+ { /* update last block */
+ chunk_free(&iv->last_block);
+ iv->last_block = chunk_clone(last_block);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+METHOD(keymat_v1_t, confirm_iv, bool,
+ private_keymat_v1_t *this, u_int32_t mid)
+{
+ iv_data_t *iv = lookup_iv(this, mid);
+ if (iv)
+ {
+ return generate_iv(this, iv);
+ }
+ return FALSE;
+}
+
+METHOD(keymat_t, get_version, ike_version_t,
+ private_keymat_v1_t *this)
+{
+ return IKEV1;
+}
+
+METHOD(keymat_t, create_dh, diffie_hellman_t*,
+ private_keymat_v1_t *this, diffie_hellman_group_t group)
+{
+ return lib->crypto->create_dh(lib->crypto, group);
+}
+
+METHOD(keymat_t, create_nonce_gen, nonce_gen_t*,
+ private_keymat_v1_t *this)
+{
+ return lib->crypto->create_nonce_gen(lib->crypto);
+}
+
+METHOD(keymat_t, get_aead, aead_t*,
+ private_keymat_v1_t *this, bool in)
+{
+ return this->aead;
+}
+
+METHOD(keymat_t, destroy, void,
+ private_keymat_v1_t *this)
+{
+ DESTROY_IF(this->prf);
+ DESTROY_IF(this->prf_auth);
+ DESTROY_IF(this->aead);
+ DESTROY_IF(this->hasher);
+ chunk_clear(&this->skeyid_d);
+ chunk_clear(&this->skeyid_a);
+ chunk_free(&this->phase1_iv.iv);
+ chunk_free(&this->phase1_iv.last_block);
+ this->ivs->destroy_function(this->ivs, (void*)iv_data_destroy);
+ this->qms->destroy_function(this->qms, (void*)qm_data_destroy);
+ free(this);
+}
+
+/**
+ * See header
+ */
+keymat_v1_t *keymat_v1_create(bool initiator)
+{
+ private_keymat_v1_t *this;
+
+ INIT(this,
+ .public = {
+ .keymat = {
+ .get_version = _get_version,
+ .create_dh = _create_dh,
+ .create_nonce_gen = _create_nonce_gen,
+ .get_aead = _get_aead,
+ .destroy = _destroy,
+ },
+ .derive_ike_keys = _derive_ike_keys,
+ .derive_child_keys = _derive_child_keys,
+ .create_hasher = _create_hasher,
+ .get_hasher = _get_hasher,
+ .get_hash = _get_hash,
+ .get_hash_phase2 = _get_hash_phase2,
+ .get_iv = _get_iv,
+ .update_iv = _update_iv,
+ .confirm_iv = _confirm_iv,
+ },
+ .ivs = linked_list_create(),
+ .qms = linked_list_create(),
+ .initiator = initiator,
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/sa/ikev1/keymat_v1.h b/src/libcharon/sa/ikev1/keymat_v1.h
new file mode 100644
index 000000000..cc9f3b339
--- /dev/null
+++ b/src/libcharon/sa/ikev1/keymat_v1.h
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2011 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup keymat_v1 keymat_v1
+ * @{ @ingroup ikev1
+ */
+
+#ifndef KEYMAT_V1_H_
+#define KEYMAT_V1_H_
+
+#include <sa/keymat.h>
+#include <sa/authenticator.h>
+
+typedef struct keymat_v1_t keymat_v1_t;
+
+/**
+ * Derivation and management of sensitive keying material, IKEv1 variant.
+ */
+struct keymat_v1_t {
+
+ /**
+ * Implements keymat_t.
+ */
+ keymat_t keymat;
+
+ /**
+ * Derive keys for the IKE_SA.
+ *
+ * These keys are not handed out, but are used by the associated signers,
+ * crypters and authentication functions.
+ *
+ * @param proposal selected algorithms
+ * @param dh diffie hellman key allocated by create_dh()
+ * @param dh_other public DH value from other peer
+ * @param nonce_i initiators nonce value
+ * @param nonce_r responders nonce value
+ * @param id IKE_SA identifier
+ * @param auth authentication method
+ * @param shared_key PSK in case of AUTH_CLASS_PSK, NULL otherwise
+ * @return TRUE on success
+ */
+ bool (*derive_ike_keys)(keymat_v1_t *this, proposal_t *proposal,
+ diffie_hellman_t *dh, chunk_t dh_other,
+ chunk_t nonce_i, chunk_t nonce_r, ike_sa_id_t *id,
+ auth_method_t auth, shared_key_t *shared_key);
+
+ /**
+ * Derive keys for the CHILD_SA.
+ *
+ * @param proposal selected algorithms
+ * @param dh diffie hellman key, NULL if none used
+ * @param spi_i SPI chosen by initiatior
+ * @param spi_r SPI chosen by responder
+ * @param nonce_i quick mode initiator nonce
+ * @param nonce_r quick mode responder nonce
+ * @param encr_i allocated initiators encryption key
+ * @param integ_i allocated initiators integrity key
+ * @param encr_r allocated responders encryption key
+ * @param integ_r allocated responders integrity key
+ */
+ bool (*derive_child_keys)(keymat_v1_t *this, proposal_t *proposal,
+ diffie_hellman_t *dh, u_int32_t spi_i, u_int32_t spi_r,
+ chunk_t nonce_i, chunk_t nonce_r,
+ chunk_t *encr_i, chunk_t *integ_i,
+ chunk_t *encr_r, chunk_t *integ_r);
+
+ /**
+ * Create the negotiated hasher.
+ *
+ * @param proposal selected algorithms
+ * @return TRUE, if creation was successful
+ */
+ bool (*create_hasher)(keymat_v1_t *this, proposal_t *proposal);
+
+ /**
+ * Get the negotiated hasher.
+ *
+ * @return allocated hasher or NULL
+ */
+ hasher_t *(*get_hasher)(keymat_v1_t *this);
+
+ /**
+ * Get HASH data for authentication.
+ *
+ * @param initiatior TRUE to create HASH_I, FALSE for HASH_R
+ * @param dh public DH value of peer to create HASH for
+ * @param dh_other others public DH value
+ * @param ike_sa_id IKE_SA identifier
+ * @param sa_i encoded SA payload of initiator
+ * @param id encoded IDii payload for HASH_I (IDir for HASH_R)
+ * @param hash chunk receiving allocated HASH data
+ * @return TRUE if hash allocated successfully
+ */
+ bool (*get_hash)(keymat_v1_t *this, bool initiator,
+ chunk_t dh, chunk_t dh_other, ike_sa_id_t *ike_sa_id,
+ chunk_t sa_i, chunk_t id, chunk_t *hash);
+
+ /**
+ * Get HASH data for integrity/authentication in Phase 2 exchanges.
+ *
+ * @param message message to generate the HASH data for
+ * @param hash chunk receiving allocated hash data
+ * @return TRUE if hash allocated successfully
+ */
+ bool (*get_hash_phase2)(keymat_v1_t *this, message_t *message, chunk_t *hash);
+
+ /**
+ * Returns the IV for a message with the given message ID.
+ *
+ * The return chunk contains internal data and is valid until the next
+ * get_iv/udpate_iv/confirm_iv call.
+ *
+ * @param mid message ID
+ * @param iv chunk receiving IV, internal data
+ * @return TRUE if IV allocated successfully
+ */
+ bool (*get_iv)(keymat_v1_t *this, u_int32_t mid, chunk_t *iv);
+
+ /**
+ * Updates the IV for the next message with the given message ID.
+ *
+ * A call of confirm_iv() is required in order to actually make the IV
+ * available. This is needed for the inbound case where we store the last
+ * block of the encrypted message but want to update the IV only after
+ * verification of the decrypted message.
+ *
+ * @param mid message ID
+ * @param last_block last block of encrypted message (gets cloned)
+ * @return TRUE if IV updated successfully
+ */
+ bool (*update_iv)(keymat_v1_t *this, u_int32_t mid, chunk_t last_block);
+
+ /**
+ * Confirms the updated IV for the given message ID.
+ *
+ * To actually make the new IV available via get_iv this method has to
+ * be called after update_iv.
+ *
+ * @param mid message ID
+ * @return TRUE if IV confirmed successfully
+ */
+ bool (*confirm_iv)(keymat_v1_t *this, u_int32_t mid);
+};
+
+/**
+ * Create a keymat instance.
+ *
+ * @param initiator TRUE if we are the initiator
+ * @return keymat instance
+ */
+keymat_v1_t *keymat_v1_create(bool initiator);
+
+#endif /** KEYMAT_V1_H_ @}*/
diff --git a/src/libcharon/sa/ikev1/phase1.c b/src/libcharon/sa/ikev1/phase1.c
new file mode 100644
index 000000000..4096141ec
--- /dev/null
+++ b/src/libcharon/sa/ikev1/phase1.c
@@ -0,0 +1,795 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 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 "phase1.h"
+
+#include <daemon.h>
+#include <sa/ikev1/keymat_v1.h>
+#include <encoding/payloads/ke_payload.h>
+#include <encoding/payloads/nonce_payload.h>
+#include <utils/linked_list.h>
+
+typedef struct private_phase1_t private_phase1_t;
+
+/**
+ * Private data of an phase1_t object.
+ */
+struct private_phase1_t {
+
+ /**
+ * Public phase1_t interface.
+ */
+ phase1_t public;
+
+ /**
+ * IKE_SA we negotiate
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * Currently selected peer config
+ */
+ peer_cfg_t *peer_cfg;
+
+ /**
+ * Other possible peer config candidates
+ */
+ linked_list_t *candidates;
+
+ /**
+ * Acting as initiator
+ */
+ bool initiator;
+
+ /**
+ * Extracted SA payload bytes
+ */
+ chunk_t sa_payload;
+
+ /**
+ * DH exchange
+ */
+ diffie_hellman_t *dh;
+
+ /**
+ * Keymat derivation (from SA)
+ */
+ keymat_v1_t *keymat;
+
+ /**
+ * Received public DH value from peer
+ */
+ chunk_t dh_value;
+
+ /**
+ * Initiators nonce
+ */
+ chunk_t nonce_i;
+
+ /**
+ * Responder nonce
+ */
+ chunk_t nonce_r;
+};
+
+/**
+ * Get the first authentcation config from peer config
+ */
+static auth_cfg_t *get_auth_cfg(peer_cfg_t *peer_cfg, bool local)
+{
+ enumerator_t *enumerator;
+ auth_cfg_t *cfg = NULL;
+
+ enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, local);
+ enumerator->enumerate(enumerator, &cfg);
+ enumerator->destroy(enumerator);
+ return cfg;
+}
+
+/**
+ * Lookup a shared secret for this IKE_SA
+ */
+static shared_key_t *lookup_shared_key(private_phase1_t *this,
+ peer_cfg_t *peer_cfg)
+{
+ host_t *me, *other;
+ identification_t *my_id, *other_id;
+ shared_key_t *shared_key = NULL;
+ auth_cfg_t *my_auth, *other_auth;
+ enumerator_t *enumerator;
+
+ /* try to get a PSK for IP addresses */
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ other = this->ike_sa->get_other_host(this->ike_sa);
+ my_id = identification_create_from_sockaddr(me->get_sockaddr(me));
+ other_id = identification_create_from_sockaddr(other->get_sockaddr(other));
+ if (my_id && other_id)
+ {
+ shared_key = lib->credmgr->get_shared(lib->credmgr, SHARED_IKE,
+ my_id, other_id);
+ }
+ DESTROY_IF(my_id);
+ DESTROY_IF(other_id);
+ if (shared_key)
+ {
+ return shared_key;
+ }
+
+ if (peer_cfg)
+ { /* as initiator or aggressive responder, use identities */
+ my_auth = get_auth_cfg(peer_cfg, TRUE);
+ other_auth = get_auth_cfg(peer_cfg, FALSE);
+ if (my_auth && other_auth)
+ {
+ my_id = my_auth->get(my_auth, AUTH_RULE_IDENTITY);
+ if (peer_cfg->use_aggressive(peer_cfg))
+ {
+ other_id = this->ike_sa->get_other_id(this->ike_sa);
+ }
+ else
+ {
+ other_id = other_auth->get(other_auth, AUTH_RULE_IDENTITY);
+ }
+ if (my_id && other_id)
+ {
+ shared_key = lib->credmgr->get_shared(lib->credmgr, SHARED_IKE,
+ my_id, other_id);
+ if (!shared_key)
+ {
+ DBG1(DBG_IKE, "no shared key found for '%Y'[%H] - '%Y'[%H]",
+ my_id, me, other_id, other);
+ }
+ }
+ }
+ return shared_key;
+ }
+ /* as responder, we try to find a config by IP */
+ enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
+ me, other, NULL, NULL, IKEV1);
+ while (enumerator->enumerate(enumerator, &peer_cfg))
+ {
+ my_auth = get_auth_cfg(peer_cfg, TRUE);
+ other_auth = get_auth_cfg(peer_cfg, FALSE);
+ if (my_auth && other_auth)
+ {
+ my_id = my_auth->get(my_auth, AUTH_RULE_IDENTITY);
+ other_id = other_auth->get(other_auth, AUTH_RULE_IDENTITY);
+ if (my_id)
+ {
+ shared_key = lib->credmgr->get_shared(lib->credmgr, SHARED_IKE,
+ my_id, other_id);
+ if (shared_key)
+ {
+ break;
+ }
+ else
+ {
+ DBG1(DBG_IKE, "no shared key found for '%Y'[%H] - '%Y'[%H]",
+ my_id, me, other_id, other);
+ }
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (!peer_cfg)
+ {
+ DBG1(DBG_IKE, "no shared key found for %H - %H", me, other);
+ }
+ return shared_key;
+}
+
+METHOD(phase1_t, create_hasher, bool,
+ private_phase1_t *this)
+{
+ return this->keymat->create_hasher(this->keymat,
+ this->ike_sa->get_proposal(this->ike_sa));
+}
+
+METHOD(phase1_t, create_dh, bool,
+ private_phase1_t *this, diffie_hellman_group_t group)
+{
+ this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat, group);
+ return this->dh != NULL;
+}
+
+METHOD(phase1_t, derive_keys, bool,
+ private_phase1_t *this, peer_cfg_t *peer_cfg, auth_method_t method)
+{
+ shared_key_t *shared_key = NULL;
+
+ switch (method)
+ {
+ case AUTH_PSK:
+ case AUTH_XAUTH_INIT_PSK:
+ case AUTH_XAUTH_RESP_PSK:
+ shared_key = lookup_shared_key(this, peer_cfg);
+ if (!shared_key)
+ {
+ return FALSE;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!this->keymat->derive_ike_keys(this->keymat,
+ this->ike_sa->get_proposal(this->ike_sa),
+ this->dh, this->dh_value, this->nonce_i, this->nonce_r,
+ this->ike_sa->get_id(this->ike_sa), method, shared_key))
+ {
+ DESTROY_IF(shared_key);
+ DBG1(DBG_IKE, "key derivation for %N failed", auth_method_names, method);
+ return FALSE;
+ }
+ charon->bus->ike_keys(charon->bus, this->ike_sa, this->dh, this->dh_value,
+ this->nonce_i, this->nonce_r, NULL, shared_key);
+ DESTROY_IF(shared_key);
+ return TRUE;
+}
+
+/**
+ * Check if a peer skipped authentication by using Hybrid authentication
+ */
+static bool skipped_auth(private_phase1_t *this,
+ auth_method_t method, bool local)
+{
+ bool initiator;
+
+ initiator = local == this->initiator;
+ if (initiator && method == AUTH_HYBRID_INIT_RSA)
+ {
+ return TRUE;
+ }
+ if (!initiator && method == AUTH_HYBRID_RESP_RSA)
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Check if remote authentication constraints fulfilled
+ */
+static bool check_constraints(private_phase1_t *this, auth_method_t method)
+{
+ identification_t *id;
+ auth_cfg_t *auth, *cfg;
+ peer_cfg_t *peer_cfg;
+
+ auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
+ /* auth identity to comply */
+ id = this->ike_sa->get_other_id(this->ike_sa);
+ auth->add(auth, AUTH_RULE_IDENTITY, id->clone(id));
+ if (skipped_auth(this, method, FALSE))
+ {
+ return TRUE;
+ }
+ peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
+ cfg = get_auth_cfg(peer_cfg, FALSE);
+ return cfg && auth->complies(auth, cfg, TRUE);
+}
+
+/**
+ * Save authentication information after authentication succeeded
+ */
+static void save_auth_cfg(private_phase1_t *this,
+ auth_method_t method, bool local)
+{
+ auth_cfg_t *auth;
+
+ if (skipped_auth(this, method, local))
+ {
+ return;
+ }
+ auth = auth_cfg_create();
+ /* for local config, we _copy_ entires from the config, as it contains
+ * certificates we must send later. */
+ auth->merge(auth, this->ike_sa->get_auth_cfg(this->ike_sa, local), local);
+ this->ike_sa->add_auth_cfg(this->ike_sa, local, auth);
+}
+
+/**
+ * Create an authenticator instance
+ */
+static authenticator_t* create_authenticator(private_phase1_t *this,
+ auth_method_t method, chunk_t id)
+{
+ authenticator_t *authenticator;
+
+ authenticator = authenticator_create_v1(this->ike_sa, this->initiator,
+ method, this->dh, this->dh_value, this->sa_payload, id);
+ if (!authenticator)
+ {
+ DBG1(DBG_IKE, "negotiated authentication method %N not supported",
+ auth_method_names, method);
+ }
+ return authenticator;
+}
+
+METHOD(phase1_t, verify_auth, bool,
+ private_phase1_t *this, auth_method_t method, message_t *message,
+ chunk_t id_data)
+{
+ authenticator_t *authenticator;
+ status_t status;
+
+ authenticator = create_authenticator(this, method, id_data);
+ if (authenticator)
+ {
+ status = authenticator->process(authenticator, message);
+ authenticator->destroy(authenticator);
+ if (status == SUCCESS && check_constraints(this, method))
+ {
+ save_auth_cfg(this, method, FALSE);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+METHOD(phase1_t, build_auth, bool,
+ private_phase1_t *this, auth_method_t method, message_t *message,
+ chunk_t id_data)
+{
+ authenticator_t *authenticator;
+ status_t status;
+
+ authenticator = create_authenticator(this, method, id_data);
+ if (authenticator)
+ {
+ status = authenticator->build(authenticator, message);
+ authenticator->destroy(authenticator);
+ if (status == SUCCESS)
+ {
+ save_auth_cfg(this, method, TRUE);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * Get the two auth classes from local or remote config
+ */
+static void get_auth_class(peer_cfg_t *peer_cfg, bool local,
+ auth_class_t *c1, auth_class_t *c2)
+{
+ enumerator_t *enumerator;
+ auth_cfg_t *auth;
+
+ *c1 = *c2 = AUTH_CLASS_ANY;
+
+ enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, local);
+ while (enumerator->enumerate(enumerator, &auth))
+ {
+ if (*c1 == AUTH_CLASS_ANY)
+ {
+ *c1 = (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS);
+ }
+ else
+ {
+ *c2 = (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Select an auth method to use by checking what key we have
+ */
+static auth_method_t get_pubkey_method(private_phase1_t *this, auth_cfg_t *auth)
+{
+ auth_method_t method = AUTH_NONE;
+ identification_t *id;
+ private_key_t *private;
+
+ if (auth)
+ {
+ id = (identification_t*)auth->get(auth, AUTH_RULE_IDENTITY);
+ if (id)
+ {
+ private = lib->credmgr->get_private(lib->credmgr, KEY_ANY, id, NULL);
+ if (private)
+ {
+ switch (private->get_type(private))
+ {
+ case KEY_RSA:
+ method = AUTH_RSA;
+ break;
+ case KEY_ECDSA:
+ switch (private->get_keysize(private))
+ {
+ case 256:
+ method = AUTH_ECDSA_256;
+ break;
+ case 384:
+ method = AUTH_ECDSA_384;
+ break;
+ case 521:
+ method = AUTH_ECDSA_521;
+ break;
+ default:
+ DBG1(DBG_IKE, "%d bit ECDSA private key size not "
+ "supported", private->get_keysize(private));
+ break;
+ }
+ break;
+ default:
+ DBG1(DBG_IKE, "private key of type %N not supported",
+ key_type_names, private->get_type(private));
+ break;
+ }
+ private->destroy(private);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "no private key found for '%Y'", id);
+ }
+ }
+ }
+ return method;
+}
+
+/**
+ * Calculate authentication method from a peer config
+ */
+static auth_method_t calc_auth_method(private_phase1_t *this,
+ peer_cfg_t *peer_cfg)
+{
+ auth_class_t i1, i2, r1, r2;
+
+ get_auth_class(peer_cfg, this->initiator, &i1, &i2);
+ get_auth_class(peer_cfg, !this->initiator, &r1, &r2);
+
+ if (i1 == AUTH_CLASS_PUBKEY && r1 == AUTH_CLASS_PUBKEY)
+ {
+ if (i2 == AUTH_CLASS_ANY && r2 == AUTH_CLASS_ANY)
+ {
+ /* for any pubkey method, return RSA */
+ return AUTH_RSA;
+ }
+ if (i2 == AUTH_CLASS_XAUTH)
+ {
+ return AUTH_XAUTH_INIT_RSA;
+ }
+ if (r2 == AUTH_CLASS_XAUTH)
+ {
+ return AUTH_XAUTH_RESP_RSA;
+ }
+ }
+ if (i1 == AUTH_CLASS_PSK && r1 == AUTH_CLASS_PSK)
+ {
+ if (i2 == AUTH_CLASS_ANY && r2 == AUTH_CLASS_ANY)
+ {
+ return AUTH_PSK;
+ }
+ if (i2 == AUTH_CLASS_XAUTH)
+ {
+ return AUTH_XAUTH_INIT_PSK;
+ }
+ if (r2 == AUTH_CLASS_XAUTH)
+ {
+ return AUTH_XAUTH_RESP_PSK;
+ }
+ }
+ if (i1 == AUTH_CLASS_XAUTH && r1 == AUTH_CLASS_PUBKEY &&
+ i2 == AUTH_CLASS_ANY && r2 == AUTH_CLASS_ANY)
+ {
+ return AUTH_HYBRID_INIT_RSA;
+ }
+ return AUTH_NONE;
+}
+
+METHOD(phase1_t, get_auth_method, auth_method_t,
+ private_phase1_t *this, peer_cfg_t *peer_cfg)
+{
+ auth_method_t method;
+
+ method = calc_auth_method(this, peer_cfg);
+ if (method == AUTH_RSA)
+ {
+ return get_pubkey_method(this, get_auth_cfg(peer_cfg, TRUE));
+ }
+ return method;
+}
+
+/**
+ * Check if a peer config can be used with a given auth method
+ */
+static bool check_auth_method(private_phase1_t *this, peer_cfg_t *peer_cfg,
+ auth_method_t given)
+{
+ auth_method_t method;
+
+ method = calc_auth_method(this, peer_cfg);
+ switch (given)
+ {
+ case AUTH_ECDSA_256:
+ case AUTH_ECDSA_384:
+ case AUTH_ECDSA_521:
+ return method == AUTH_RSA;
+ default:
+ return method == given;
+ }
+}
+
+METHOD(phase1_t, select_config, peer_cfg_t*,
+ private_phase1_t *this, auth_method_t method, bool aggressive,
+ identification_t *id)
+{
+ enumerator_t *enumerator;
+ peer_cfg_t *current;
+ host_t *me, *other;
+
+ if (this->peer_cfg)
+ { /* try to find an alternative config */
+ if (this->candidates->remove_first(this->candidates,
+ (void**)&current) != SUCCESS)
+ {
+ DBG1(DBG_CFG, "no alternative config found");
+ return NULL;
+ }
+ DBG1(DBG_CFG, "switching to peer config '%s'",
+ current->get_name(current));
+ return current;
+ }
+
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ other = this->ike_sa->get_other_host(this->ike_sa);
+ DBG1(DBG_CFG, "looking for %N peer configs matching %H...%H[%Y]",
+ auth_method_names, method, me, other, id);
+ enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
+ me, other, NULL, id, IKEV1);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (check_auth_method(this, current, method) &&
+ current->use_aggressive(current) == aggressive)
+ {
+ current->get_ref(current);
+ if (!this->peer_cfg)
+ {
+ this->peer_cfg = current;
+ }
+ else
+ {
+ this->candidates->insert_last(this->candidates, current);
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (this->peer_cfg)
+ {
+ DBG1(DBG_CFG, "selected peer config \"%s\"",
+ this->peer_cfg->get_name(this->peer_cfg));
+ return this->peer_cfg->get_ref(this->peer_cfg);
+ }
+ DBG1(DBG_IKE, "no peer config found");
+ return NULL;
+}
+
+METHOD(phase1_t, get_id, identification_t*,
+ private_phase1_t *this, peer_cfg_t *peer_cfg, bool local)
+{
+ identification_t *id = NULL;
+ auth_cfg_t *auth;
+
+ auth = get_auth_cfg(peer_cfg, local);
+ if (auth)
+ {
+ id = auth->get(auth, AUTH_RULE_IDENTITY);
+ if (local && (!id || id->get_type(id) == ID_ANY))
+ { /* no ID configured, use local IP address */
+ host_t *me;
+
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ if (!me->is_anyaddr(me))
+ {
+ id = identification_create_from_sockaddr(me->get_sockaddr(me));
+ auth->add(auth, AUTH_RULE_IDENTITY, id);
+ }
+ }
+ }
+ return id;
+}
+
+METHOD(phase1_t, has_virtual_ip, bool,
+ private_phase1_t *this, peer_cfg_t *peer_cfg)
+{
+ enumerator_t *enumerator;
+ bool found = FALSE;
+ host_t *host;
+
+ enumerator = peer_cfg->create_virtual_ip_enumerator(peer_cfg);
+ found = enumerator->enumerate(enumerator, &host);
+ enumerator->destroy(enumerator);
+
+ return found;
+}
+
+METHOD(phase1_t, has_pool, bool,
+ private_phase1_t *this, peer_cfg_t *peer_cfg)
+{
+ enumerator_t *enumerator;
+ bool found = FALSE;
+ char *pool;
+
+ enumerator = peer_cfg->create_pool_enumerator(peer_cfg);
+ found = enumerator->enumerate(enumerator, &pool);
+ enumerator->destroy(enumerator);
+
+ return found;
+}
+
+METHOD(phase1_t, save_sa_payload, bool,
+ private_phase1_t *this, message_t *message)
+{
+ enumerator_t *enumerator;
+ payload_t *payload, *sa = NULL;
+ chunk_t data;
+ size_t offset = IKE_HEADER_LENGTH;
+
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ if (payload->get_type(payload) == SECURITY_ASSOCIATION_V1)
+ {
+ sa = payload;
+ break;
+ }
+ else
+ {
+ offset += payload->get_length(payload);
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ data = message->get_packet_data(message);
+ if (sa && data.len >= offset + sa->get_length(sa))
+ {
+ /* Get SA payload without 4 byte fixed header */
+ data = chunk_skip(data, offset);
+ data.len = sa->get_length(sa);
+ data = chunk_skip(data, 4);
+ this->sa_payload = chunk_clone(data);
+ return TRUE;
+ }
+ DBG1(DBG_IKE, "unable to extract SA payload encoding");
+ return FALSE;
+}
+
+METHOD(phase1_t, add_nonce_ke, bool,
+ private_phase1_t *this, message_t *message)
+{
+ nonce_payload_t *nonce_payload;
+ ke_payload_t *ke_payload;
+ nonce_gen_t *nonceg;
+ chunk_t nonce;
+
+ ke_payload = ke_payload_create_from_diffie_hellman(KEY_EXCHANGE_V1, this->dh);
+ message->add_payload(message, &ke_payload->payload_interface);
+
+ nonceg = this->keymat->keymat.create_nonce_gen(&this->keymat->keymat);
+ if (!nonceg)
+ {
+ DBG1(DBG_IKE, "no nonce generator found to create nonce");
+ return FALSE;
+ }
+ if (!nonceg->allocate_nonce(nonceg, NONCE_SIZE, &nonce))
+ {
+ DBG1(DBG_IKE, "nonce allocation failed");
+ nonceg->destroy(nonceg);
+ return FALSE;
+ }
+ nonceg->destroy(nonceg);
+
+ nonce_payload = nonce_payload_create(NONCE_V1);
+ nonce_payload->set_nonce(nonce_payload, nonce);
+ message->add_payload(message, &nonce_payload->payload_interface);
+
+ if (this->initiator)
+ {
+ this->nonce_i = nonce;
+ }
+ else
+ {
+ this->nonce_r = nonce;
+ }
+ return TRUE;
+}
+
+METHOD(phase1_t, get_nonce_ke, bool,
+ private_phase1_t *this, message_t *message)
+{
+ nonce_payload_t *nonce_payload;
+ ke_payload_t *ke_payload;
+
+ ke_payload = (ke_payload_t*)message->get_payload(message, KEY_EXCHANGE_V1);
+ if (!ke_payload)
+ {
+ DBG1(DBG_IKE, "KE payload missing in message");
+ return FALSE;
+ }
+ this->dh_value = chunk_clone(ke_payload->get_key_exchange_data(ke_payload));
+ this->dh->set_other_public_value(this->dh, this->dh_value);
+
+ nonce_payload = (nonce_payload_t*)message->get_payload(message, NONCE_V1);
+ if (!nonce_payload)
+ {
+ DBG1(DBG_IKE, "NONCE payload missing in message");
+ return FALSE;
+ }
+
+ if (this->initiator)
+ {
+ this->nonce_r = nonce_payload->get_nonce(nonce_payload);
+ }
+ else
+ {
+ this->nonce_i = nonce_payload->get_nonce(nonce_payload);
+ }
+ return TRUE;
+}
+
+METHOD(phase1_t, destroy, void,
+ private_phase1_t *this)
+{
+ DESTROY_IF(this->peer_cfg);
+ this->candidates->destroy_offset(this->candidates,
+ offsetof(peer_cfg_t, destroy));
+ chunk_free(&this->sa_payload);
+ DESTROY_IF(this->dh);
+ free(this->dh_value.ptr);
+ free(this->nonce_i.ptr);
+ free(this->nonce_r.ptr);
+ free(this);
+}
+
+/**
+ * See header
+ */
+phase1_t *phase1_create(ike_sa_t *ike_sa, bool initiator)
+{
+ private_phase1_t *this;
+
+ INIT(this,
+ .public = {
+ .create_hasher = _create_hasher,
+ .create_dh = _create_dh,
+ .derive_keys = _derive_keys,
+ .get_auth_method = _get_auth_method,
+ .get_id = _get_id,
+ .select_config = _select_config,
+ .has_virtual_ip = _has_virtual_ip,
+ .has_pool = _has_pool,
+ .verify_auth = _verify_auth,
+ .build_auth = _build_auth,
+ .save_sa_payload = _save_sa_payload,
+ .add_nonce_ke = _add_nonce_ke,
+ .get_nonce_ke = _get_nonce_ke,
+ .destroy = _destroy,
+ },
+ .candidates = linked_list_create(),
+ .ike_sa = ike_sa,
+ .initiator = initiator,
+ .keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa),
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/sa/ikev1/phase1.h b/src/libcharon/sa/ikev1/phase1.h
new file mode 100644
index 000000000..eaf8908e7
--- /dev/null
+++ b/src/libcharon/sa/ikev1/phase1.h
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 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 phase1 phase1
+ * @{ @ingroup ikev1
+ */
+
+#ifndef PHASE1_H_
+#define PHASE1_H_
+
+typedef struct phase1_t phase1_t;
+
+#include <sa/ike_sa.h>
+#include <crypto/diffie_hellman.h>
+
+/**
+ * Common phase 1 helper for main and aggressive mode.
+ */
+struct phase1_t {
+
+ /**
+ * Create keymat hasher.
+ *
+ * @return TRUE if hasher created
+ */
+ bool (*create_hasher)(phase1_t *this);
+
+ /**
+ * Create DH object using SA keymat.
+ *
+ * @param group negotiated DH group
+ * @return TRUE if group supported
+ */
+ bool (*create_dh)(phase1_t *this, diffie_hellman_group_t group);
+
+ /**
+ * Derive key material.
+ *
+ * @param peer_cfg peer config to look up shared key for, or NULL
+ * @param method negotiated authenticated method
+ * @return TRUE if successful
+ */
+ bool (*derive_keys)(phase1_t *this, peer_cfg_t *peer_cfg,
+ auth_method_t method);
+ /**
+ * Verify a HASH or SIG payload in message.
+ *
+ * @param method negotiated auth method
+ * @param message message containing HASH or SIG payload
+ * @param id_data encoded identity, including protocol/port fields
+ * @return TRUE if verified successfully
+ */
+ bool (*verify_auth)(phase1_t *this, auth_method_t method,
+ message_t *message, chunk_t id_data);
+
+ /**
+ * Build a HASH or SIG payload and add it to message.
+ *
+ * @param method negotiated auth method
+ * @param message message to add payload to
+ * @param id_data encoded identity, including protocol/port fields
+ * @return TRUE if built successfully
+ */
+ bool (*build_auth)(phase1_t *this, auth_method_t method,
+ message_t *message, chunk_t id_data);
+
+ /**
+ * Get the IKEv1 authentication method defined by peer config.
+ *
+ * @param peer_cfg peer config to get auth method from
+ * @return auth method, or AUTH_NONE
+ */
+ auth_method_t (*get_auth_method)(phase1_t *this, peer_cfg_t *peer_cfg);
+
+ /**
+ * Select a peer config as responder.
+ *
+ * If called after the first successful call the next alternative config
+ * is returned, if any.
+ *
+ * @param method used authentication method
+ * @param aggressive TRUE to get an aggressive mode config
+ * @param id initiator identity
+ * @return selected peer config, NULL if none found
+ */
+ peer_cfg_t* (*select_config)(phase1_t *this, auth_method_t method,
+ bool aggressive, identification_t *id);
+
+ /**
+ * Get configured identity from peer config.
+ *
+ * @param peer_cfg peer config to get identity from
+ * @param local TRUE to get own identity, FALSE for remote
+ * @return identity, pointing to internal config data
+ */
+ identification_t* (*get_id)(phase1_t *this, peer_cfg_t *peer_cfg, bool local);
+
+ /**
+ * Check if peer config has virtual IPs pool assigned.
+ *
+ * @param peer_cfg peer_config to check
+ * @return TRUE if peer config contains at least one pool
+ */
+ bool (*has_pool)(phase1_t *this, peer_cfg_t *peer_cfg);
+
+ /**
+ * Check if peer config has virtual IPs to request
+ *
+ * @param peer_cfg peer_config to check
+ * @return TRUE if peer config contains at least one virtual IP
+ */
+ bool (*has_virtual_ip)(phase1_t *this, peer_cfg_t *peer_cfg);
+
+ /**
+ * Extract and store SA payload bytes from encoded message.
+ *
+ * @param message message to extract SA payload bytes from
+ * @return TRUE if SA payload found
+ */
+ bool (*save_sa_payload)(phase1_t *this, message_t *message);
+
+ /**
+ * Add Nonce and KE payload to message.
+ *
+ * @param message message to add payloads
+ * @return TRUE if payloads added successfully
+ */
+ bool (*add_nonce_ke)(phase1_t *this, message_t *message);
+
+ /**
+ * Extract Nonce and KE payload from message.
+ *
+ * @param message message to get payloads from
+ * @return TRUE if payloads extracted successfully
+ */
+ bool (*get_nonce_ke)(phase1_t *this, message_t *message);
+
+ /**
+ * Destroy a phase1_t.
+ */
+ void (*destroy)(phase1_t *this);
+};
+
+/**
+ * Create a phase1 instance.
+ *
+ * @param ike_sa IKE_SA to set up
+ * @param initiator TRUE if initiating actively
+ * @return Phase 1 helper
+ */
+phase1_t *phase1_create(ike_sa_t *ike_sa, bool initiator);
+
+#endif /** PHASE1_H_ @}*/
diff --git a/src/libcharon/sa/ikev1/task_manager_v1.c b/src/libcharon/sa/ikev1/task_manager_v1.c
new file mode 100644
index 000000000..fd0ad235a
--- /dev/null
+++ b/src/libcharon/sa/ikev1/task_manager_v1.c
@@ -0,0 +1,1714 @@
+/*
+ * Copyright (C) 2007-2011 Tobias Brunner
+ * Copyright (C) 2007-2011 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "task_manager_v1.h"
+
+#include <math.h>
+
+#include <daemon.h>
+#include <sa/ikev1/tasks/main_mode.h>
+#include <sa/ikev1/tasks/aggressive_mode.h>
+#include <sa/ikev1/tasks/quick_mode.h>
+#include <sa/ikev1/tasks/quick_delete.h>
+#include <sa/ikev1/tasks/xauth.h>
+#include <sa/ikev1/tasks/mode_config.h>
+#include <sa/ikev1/tasks/informational.h>
+#include <sa/ikev1/tasks/isakmp_natd.h>
+#include <sa/ikev1/tasks/isakmp_vendor.h>
+#include <sa/ikev1/tasks/isakmp_cert_pre.h>
+#include <sa/ikev1/tasks/isakmp_cert_post.h>
+#include <sa/ikev1/tasks/isakmp_delete.h>
+#include <sa/ikev1/tasks/isakmp_dpd.h>
+
+#include <processing/jobs/retransmit_job.h>
+#include <processing/jobs/delete_ike_sa_job.h>
+#include <processing/jobs/dpd_timeout_job.h>
+
+/**
+ * Number of old messages hashes we keep for retransmission.
+ *
+ * In Main Mode, we must ignore messages from a previous message pair if
+ * we already continued to the next. Otherwise a late retransmission
+ * could be considered as a reply to the newer request.
+ */
+#define MAX_OLD_HASHES 2
+
+/**
+ * First sequence number of responding packets.
+ *
+ * To distinguish retransmission jobs for initiating and responding packets,
+ * we split up the sequence counter and use the upper half for responding.
+ */
+#define RESPONDING_SEQ INT_MAX
+
+typedef struct exchange_t exchange_t;
+
+/**
+ * An exchange in the air, used do detect and handle retransmission
+ */
+struct exchange_t {
+
+ /**
+ * Message ID used for this transaction
+ */
+ u_int32_t mid;
+
+ /**
+ * generated packet for retransmission
+ */
+ packet_t *packet;
+};
+
+typedef struct private_task_manager_t private_task_manager_t;
+
+/**
+ * private data of the task manager
+ */
+struct private_task_manager_t {
+
+ /**
+ * public functions
+ */
+ task_manager_v1_t public;
+
+ /**
+ * associated IKE_SA we are serving
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * RNG to create message IDs
+ */
+ rng_t *rng;
+
+ /**
+ * Exchange we are currently handling as responder
+ */
+ struct {
+ /**
+ * Message ID of the last response
+ */
+ u_int32_t mid;
+
+ /**
+ * Hash of a previously received message
+ */
+ u_int32_t hash;
+
+ /**
+ * packet for retransmission
+ */
+ packet_t *packet;
+
+ /**
+ * Sequence number of the last sent message
+ */
+ u_int32_t seqnr;
+
+ /**
+ * how many times we have retransmitted so far
+ */
+ u_int retransmitted;
+
+ } responding;
+
+ /**
+ * Exchange we are currently handling as initiator
+ */
+ struct {
+ /**
+ * Message ID of the exchange
+ */
+ u_int32_t mid;
+
+ /**
+ * Hashes of old responses we can ignore
+ */
+ u_int32_t old_hashes[MAX_OLD_HASHES];
+
+ /**
+ * Position in old hash array
+ */
+ int old_hash_pos;
+
+ /**
+ * Sequence number of the last sent message
+ */
+ u_int32_t seqnr;
+
+ /**
+ * how many times we have retransmitted so far
+ */
+ u_int retransmitted;
+
+ /**
+ * packet for retransmission
+ */
+ packet_t *packet;
+
+ /**
+ * type of the initated exchange
+ */
+ exchange_type_t type;
+
+ } initiating;
+
+ /**
+ * List of queued tasks not yet in action
+ */
+ linked_list_t *queued_tasks;
+
+ /**
+ * List of active tasks, initiated by ourselve
+ */
+ linked_list_t *active_tasks;
+
+ /**
+ * List of tasks initiated by peer
+ */
+ linked_list_t *passive_tasks;
+
+ /**
+ * Queued messages not yet ready to process
+ */
+ message_t *queued;
+
+ /**
+ * Number of times we retransmit messages before giving up
+ */
+ u_int retransmit_tries;
+
+ /**
+ * Retransmission timeout
+ */
+ double retransmit_timeout;
+
+ /**
+ * Base to calculate retransmission timeout
+ */
+ double retransmit_base;
+
+ /**
+ * Sequence number for sending DPD requests
+ */
+ u_int32_t dpd_send;
+
+ /**
+ * Sequence number for received DPD requests
+ */
+ u_int32_t dpd_recv;
+};
+
+METHOD(task_manager_t, flush_queue, void,
+ private_task_manager_t *this, task_queue_t queue)
+{
+ linked_list_t *list;
+ task_t *task;
+
+ if (this->queued)
+ {
+ this->queued->destroy(this->queued);
+ this->queued = NULL;
+ }
+ switch (queue)
+ {
+ case TASK_QUEUE_ACTIVE:
+ list = this->active_tasks;
+ /* cancel pending retransmits */
+ this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
+ DESTROY_IF(this->initiating.packet);
+ this->initiating.packet = NULL;
+ break;
+ case TASK_QUEUE_PASSIVE:
+ list = this->passive_tasks;
+ break;
+ case TASK_QUEUE_QUEUED:
+ list = this->queued_tasks;
+ break;
+ default:
+ return;
+ }
+ while (list->remove_last(list, (void**)&task) == SUCCESS)
+ {
+ task->destroy(task);
+ }
+}
+
+/**
+ * flush all tasks in the task manager
+ */
+static void flush(private_task_manager_t *this)
+{
+ flush_queue(this, TASK_QUEUE_QUEUED);
+ flush_queue(this, TASK_QUEUE_PASSIVE);
+ flush_queue(this, TASK_QUEUE_ACTIVE);
+}
+
+/**
+ * move a task of a specific type from the queue to the active list
+ */
+static bool activate_task(private_task_manager_t *this, task_type_t type)
+{
+ enumerator_t *enumerator;
+ task_t *task;
+ bool found = FALSE;
+
+ enumerator = this->queued_tasks->create_enumerator(this->queued_tasks);
+ while (enumerator->enumerate(enumerator, (void**)&task))
+ {
+ if (task->get_type(task) == type)
+ {
+ DBG2(DBG_IKE, " activating %N task", task_type_names, type);
+ this->queued_tasks->remove_at(this->queued_tasks, enumerator);
+ this->active_tasks->insert_last(this->active_tasks, task);
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return found;
+}
+
+/**
+ * Retransmit a packet, either as initiator or as responder
+ */
+static status_t retransmit_packet(private_task_manager_t *this, u_int32_t seqnr,
+ u_int mid, u_int retransmitted, packet_t *packet)
+{
+ u_int32_t t;
+
+ if (retransmitted > this->retransmit_tries)
+ {
+ DBG1(DBG_IKE, "giving up after %u retransmits", retransmitted - 1);
+ return DESTROY_ME;
+ }
+ t = (u_int32_t)(this->retransmit_timeout * 1000.0 *
+ pow(this->retransmit_base, retransmitted));
+ if (retransmitted)
+ {
+ DBG1(DBG_IKE, "sending retransmit %u of %s message ID %u, seq %u",
+ retransmitted, seqnr < RESPONDING_SEQ ? "request" : "response",
+ mid, seqnr < RESPONDING_SEQ ? seqnr : seqnr - RESPONDING_SEQ);
+ }
+ charon->sender->send(charon->sender, packet->clone(packet));
+ lib->scheduler->schedule_job_ms(lib->scheduler, (job_t*)
+ retransmit_job_create(seqnr, this->ike_sa->get_id(this->ike_sa)), t);
+ return NEED_MORE;
+}
+
+METHOD(task_manager_t, retransmit, status_t,
+ private_task_manager_t *this, u_int32_t seqnr)
+{
+ status_t status = SUCCESS;
+
+ if (seqnr == this->initiating.seqnr && this->initiating.packet)
+ {
+ status = retransmit_packet(this, seqnr, this->initiating.mid,
+ this->initiating.retransmitted, this->initiating.packet);
+ if (status == NEED_MORE)
+ {
+ this->initiating.retransmitted++;
+ status = SUCCESS;
+ }
+ }
+ if (seqnr == this->responding.seqnr && this->responding.packet)
+ {
+ status = retransmit_packet(this, seqnr, this->responding.mid,
+ this->responding.retransmitted, this->responding.packet);
+ if (status == NEED_MORE)
+ {
+ this->responding.retransmitted++;
+ status = SUCCESS;
+ }
+ }
+ return status;
+}
+
+/**
+ * Check if we have to wait for a mode config before starting a quick mode
+ */
+static bool mode_config_expected(private_task_manager_t *this)
+{
+ enumerator_t *enumerator;
+ peer_cfg_t *peer_cfg;
+ char *pool;
+ host_t *host;
+
+ peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
+ if (peer_cfg)
+ {
+ enumerator = peer_cfg->create_pool_enumerator(peer_cfg);
+ if (!enumerator->enumerate(enumerator, &pool))
+ { /* no pool configured */
+ enumerator->destroy(enumerator);
+ return FALSE;
+ }
+ enumerator->destroy(enumerator);
+
+ enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa,
+ FALSE);
+ if (!enumerator->enumerate(enumerator, &host))
+ { /* have a pool, but no VIP assigned yet */
+ enumerator->destroy(enumerator);
+ return TRUE;
+ }
+ enumerator->destroy(enumerator);
+ }
+ return FALSE;
+}
+
+METHOD(task_manager_t, initiate, status_t,
+ private_task_manager_t *this)
+{
+ enumerator_t *enumerator;
+ task_t *task;
+ message_t *message;
+ host_t *me, *other;
+ status_t status;
+ exchange_type_t exchange = EXCHANGE_TYPE_UNDEFINED;
+ bool new_mid = FALSE, expect_response = FALSE, cancelled = FALSE, keep = FALSE;
+
+ if (this->initiating.type != EXCHANGE_TYPE_UNDEFINED &&
+ this->initiating.type != INFORMATIONAL_V1)
+ {
+ DBG2(DBG_IKE, "delaying task initiation, %N exchange in progress",
+ exchange_type_names, this->initiating.type);
+ /* do not initiate if we already have a message in the air */
+ return SUCCESS;
+ }
+
+ if (this->active_tasks->get_count(this->active_tasks) == 0)
+ {
+ DBG2(DBG_IKE, "activating new tasks");
+ switch (this->ike_sa->get_state(this->ike_sa))
+ {
+ case IKE_CREATED:
+ activate_task(this, TASK_ISAKMP_VENDOR);
+ activate_task(this, TASK_ISAKMP_CERT_PRE);
+ if (activate_task(this, TASK_MAIN_MODE))
+ {
+ exchange = ID_PROT;
+ }
+ else if (activate_task(this, TASK_AGGRESSIVE_MODE))
+ {
+ exchange = AGGRESSIVE;
+ }
+ activate_task(this, TASK_ISAKMP_CERT_POST);
+ activate_task(this, TASK_ISAKMP_NATD);
+ break;
+ case IKE_CONNECTING:
+ if (activate_task(this, TASK_ISAKMP_DELETE))
+ {
+ exchange = INFORMATIONAL_V1;
+ new_mid = TRUE;
+ break;
+ }
+ if (activate_task(this, TASK_XAUTH))
+ {
+ exchange = TRANSACTION;
+ new_mid = TRUE;
+ break;
+ }
+ if (activate_task(this, TASK_INFORMATIONAL))
+ {
+ exchange = INFORMATIONAL_V1;
+ new_mid = TRUE;
+ break;
+ }
+ break;
+ case IKE_ESTABLISHED:
+ if (activate_task(this, TASK_MODE_CONFIG))
+ {
+ exchange = TRANSACTION;
+ new_mid = TRUE;
+ break;
+ }
+ if (!mode_config_expected(this) &&
+ activate_task(this, TASK_QUICK_MODE))
+ {
+ exchange = QUICK_MODE;
+ new_mid = TRUE;
+ break;
+ }
+ if (activate_task(this, TASK_INFORMATIONAL))
+ {
+ exchange = INFORMATIONAL_V1;
+ new_mid = TRUE;
+ break;
+ }
+ if (activate_task(this, TASK_QUICK_DELETE))
+ {
+ exchange = INFORMATIONAL_V1;
+ new_mid = TRUE;
+ break;
+ }
+ if (activate_task(this, TASK_ISAKMP_DELETE))
+ {
+ exchange = INFORMATIONAL_V1;
+ new_mid = TRUE;
+ break;
+ }
+ if (activate_task(this, TASK_ISAKMP_DPD))
+ {
+ exchange = INFORMATIONAL_V1;
+ new_mid = TRUE;
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ DBG2(DBG_IKE, "reinitiating already active tasks");
+ enumerator = this->active_tasks->create_enumerator(this->active_tasks);
+ while (enumerator->enumerate(enumerator, (void**)&task))
+ {
+ DBG2(DBG_IKE, " %N task", task_type_names, task->get_type(task));
+ switch (task->get_type(task))
+ {
+ case TASK_MAIN_MODE:
+ exchange = ID_PROT;
+ break;
+ case TASK_AGGRESSIVE_MODE:
+ exchange = AGGRESSIVE;
+ break;
+ case TASK_QUICK_MODE:
+ exchange = QUICK_MODE;
+ break;
+ case TASK_XAUTH:
+ exchange = TRANSACTION;
+ new_mid = TRUE;
+ break;
+ default:
+ continue;
+ }
+ break;
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ if (exchange == EXCHANGE_TYPE_UNDEFINED)
+ {
+ DBG2(DBG_IKE, "nothing to initiate");
+ /* nothing to do yet... */
+ return SUCCESS;
+ }
+
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ other = this->ike_sa->get_other_host(this->ike_sa);
+
+ if (new_mid)
+ {
+ if (!this->rng->get_bytes(this->rng, sizeof(this->initiating.mid),
+ (void*)&this->initiating.mid))
+ {
+ DBG1(DBG_IKE, "failed to allocate message ID, destroying IKE_SA");
+ flush(this);
+ return DESTROY_ME;
+ }
+ }
+ message = message_create(IKEV1_MAJOR_VERSION, IKEV1_MINOR_VERSION);
+ message->set_message_id(message, this->initiating.mid);
+ message->set_source(message, me->clone(me));
+ message->set_destination(message, other->clone(other));
+ message->set_exchange_type(message, exchange);
+ this->initiating.type = exchange;
+ this->initiating.retransmitted = 0;
+
+ enumerator = this->active_tasks->create_enumerator(this->active_tasks);
+ while (enumerator->enumerate(enumerator, (void*)&task))
+ {
+ switch (task->build(task, message))
+ {
+ case SUCCESS:
+ /* task completed, remove it */
+ this->active_tasks->remove_at(this->active_tasks, enumerator);
+ if (task->get_type(task) == TASK_AGGRESSIVE_MODE ||
+ task->get_type(task) == TASK_QUICK_MODE)
+ { /* last message of three message exchange */
+ keep = TRUE;
+ }
+ task->destroy(task);
+ continue;
+ case NEED_MORE:
+ expect_response = TRUE;
+ /* processed, but task needs another exchange */
+ continue;
+ case ALREADY_DONE:
+ cancelled = TRUE;
+ break;
+ case FAILED:
+ default:
+ if (this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING)
+ {
+ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ }
+ /* FALL */
+ case DESTROY_ME:
+ /* critical failure, destroy IKE_SA */
+ enumerator->destroy(enumerator);
+ message->destroy(message);
+ flush(this);
+ return DESTROY_ME;
+ }
+ break;
+ }
+ enumerator->destroy(enumerator);
+
+ if (this->active_tasks->get_count(this->active_tasks) == 0 &&
+ (exchange == QUICK_MODE || exchange == AGGRESSIVE))
+ { /* tasks completed, no exchange active anymore */
+ this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
+ }
+ if (cancelled)
+ {
+ message->destroy(message);
+ return initiate(this);
+ }
+
+ DESTROY_IF(this->initiating.packet);
+ status = this->ike_sa->generate_message(this->ike_sa, message,
+ &this->initiating.packet);
+ if (status != SUCCESS)
+ {
+ /* message generation failed. There is nothing more to do than to
+ * close the SA */
+ message->destroy(message);
+ flush(this);
+ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ return DESTROY_ME;
+ }
+
+ this->initiating.seqnr++;
+ if (expect_response)
+ {
+ message->destroy(message);
+ return retransmit(this, this->initiating.seqnr);
+ }
+ if (keep)
+ { /* keep the packet for retransmission, the responder might request it */
+ charon->sender->send(charon->sender,
+ this->initiating.packet->clone(this->initiating.packet));
+ }
+ else
+ {
+ charon->sender->send(charon->sender, this->initiating.packet);
+ this->initiating.packet = NULL;
+ }
+ message->destroy(message);
+
+ if (exchange == INFORMATIONAL_V1)
+ {
+ switch (this->ike_sa->get_state(this->ike_sa))
+ {
+ case IKE_CONNECTING:
+ /* close after sending an INFORMATIONAL when unestablished */
+ return FAILED;
+ case IKE_DELETING:
+ /* close after sending a DELETE */
+ return DESTROY_ME;
+ default:
+ break;
+ }
+ }
+ return initiate(this);
+}
+
+/**
+ * build a response depending on the "passive" task list
+ */
+static status_t build_response(private_task_manager_t *this, message_t *request)
+{
+ enumerator_t *enumerator;
+ task_t *task;
+ message_t *message;
+ host_t *me, *other;
+ bool delete = FALSE, cancelled = FALSE, expect_request = FALSE;
+ status_t status;
+
+ me = request->get_destination(request);
+ other = request->get_source(request);
+
+ message = message_create(IKEV1_MAJOR_VERSION, IKEV1_MINOR_VERSION);
+ message->set_exchange_type(message, request->get_exchange_type(request));
+ /* send response along the path the request came in */
+ message->set_source(message, me->clone(me));
+ message->set_destination(message, other->clone(other));
+ message->set_message_id(message, request->get_message_id(request));
+ message->set_request(message, FALSE);
+
+ this->responding.mid = request->get_message_id(request);
+ this->responding.retransmitted = 0;
+ this->responding.seqnr++;
+
+ enumerator = this->passive_tasks->create_enumerator(this->passive_tasks);
+ while (enumerator->enumerate(enumerator, (void*)&task))
+ {
+ switch (task->build(task, message))
+ {
+ case SUCCESS:
+ /* task completed, remove it */
+ this->passive_tasks->remove_at(this->passive_tasks, enumerator);
+ task->destroy(task);
+ continue;
+ case NEED_MORE:
+ /* processed, but task needs another exchange */
+ if (task->get_type(task) == TASK_QUICK_MODE ||
+ task->get_type(task) == TASK_AGGRESSIVE_MODE)
+ { /* we rely on initiator retransmission, except for
+ * three-message exchanges */
+ expect_request = TRUE;
+ }
+ continue;
+ case ALREADY_DONE:
+ cancelled = TRUE;
+ break;
+ case FAILED:
+ default:
+ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ /* FALL */
+ case DESTROY_ME:
+ /* destroy IKE_SA, but SEND response first */
+ delete = TRUE;
+ break;
+ }
+ break;
+ }
+ enumerator->destroy(enumerator);
+
+ DESTROY_IF(this->responding.packet);
+ this->responding.packet = NULL;
+ if (cancelled)
+ {
+ message->destroy(message);
+ return initiate(this);
+ }
+ status = this->ike_sa->generate_message(this->ike_sa, message,
+ &this->responding.packet);
+ message->destroy(message);
+ if (status != SUCCESS)
+ {
+ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ return DESTROY_ME;
+ }
+
+ if (expect_request && !delete)
+ {
+ return retransmit(this, this->responding.seqnr);
+ }
+ charon->sender->send(charon->sender,
+ this->responding.packet->clone(this->responding.packet));
+ if (delete)
+ {
+ return DESTROY_ME;
+ }
+ return SUCCESS;
+}
+
+/**
+ * Send a notify in a separate INFORMATIONAL exchange back to the sender.
+ * The notify protocol_id is set to ISAKMP
+ */
+static void send_notify(private_task_manager_t *this, message_t *request,
+ notify_type_t type)
+{
+ message_t *response;
+ packet_t *packet;
+ host_t *me, *other;
+ u_int32_t mid;
+
+ if (request->get_exchange_type(request) == INFORMATIONAL_V1)
+ { /* don't respond to INFORMATIONAL requests to avoid a notify war */
+ DBG1(DBG_IKE, "ignore malformed INFORMATIONAL request");
+ return;
+ }
+ if (!this->rng->get_bytes(this->rng, sizeof(mid), (void*)&mid))
+ {
+ DBG1(DBG_IKE, "failed to allocate message ID");
+ return;
+ }
+ response = message_create(IKEV1_MAJOR_VERSION, IKEV1_MINOR_VERSION);
+ response->set_exchange_type(response, INFORMATIONAL_V1);
+ response->set_request(response, TRUE);
+ response->set_message_id(response, mid);
+ response->add_payload(response, (payload_t*)
+ notify_payload_create_from_protocol_and_type(NOTIFY_V1,
+ PROTO_IKE, type));
+
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ if (me->is_anyaddr(me))
+ {
+ me = request->get_destination(request);
+ this->ike_sa->set_my_host(this->ike_sa, me->clone(me));
+ }
+ other = this->ike_sa->get_other_host(this->ike_sa);
+ if (other->is_anyaddr(other))
+ {
+ other = request->get_source(request);
+ this->ike_sa->set_other_host(this->ike_sa, other->clone(other));
+ }
+ response->set_source(response, me->clone(me));
+ response->set_destination(response, other->clone(other));
+ if (this->ike_sa->generate_message(this->ike_sa, response,
+ &packet) == SUCCESS)
+ {
+ charon->sender->send(charon->sender, packet);
+ }
+ response->destroy(response);
+}
+
+/**
+ * Process a DPD request/response
+ */
+static bool process_dpd(private_task_manager_t *this, message_t *message)
+{
+ notify_payload_t *notify;
+ notify_type_t type;
+ u_int32_t seq;
+ chunk_t data;
+
+ type = DPD_R_U_THERE;
+ notify = message->get_notify(message, type);
+ if (!notify)
+ {
+ type = DPD_R_U_THERE_ACK;
+ notify = message->get_notify(message, type);
+ }
+ if (!notify)
+ {
+ return FALSE;
+ }
+ data = notify->get_notification_data(notify);
+ if (data.len != 4)
+ {
+ return FALSE;
+ }
+ seq = untoh32(data.ptr);
+
+ if (type == DPD_R_U_THERE)
+ {
+ if (this->dpd_recv == 0 || seq == this->dpd_recv)
+ { /* check sequence validity */
+ this->dpd_recv = seq + 1;
+ this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
+ time_monotonic(NULL));
+ }
+ /* but respond anyway */
+ this->ike_sa->queue_task(this->ike_sa,
+ &isakmp_dpd_create(this->ike_sa, DPD_R_U_THERE_ACK, seq)->task);
+ }
+ else /* DPD_R_U_THERE_ACK */
+ {
+ if (seq == this->dpd_send - 1)
+ {
+ this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
+ time_monotonic(NULL));
+ }
+ else
+ {
+ DBG1(DBG_IKE, "received invalid DPD sequence number %u "
+ "(expected %u), ignored", seq, this->dpd_send - 1);
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * handle an incoming request message
+ */
+static status_t process_request(private_task_manager_t *this,
+ message_t *message)
+{
+ enumerator_t *enumerator;
+ task_t *task = NULL;
+ bool send_response = FALSE, dpd = FALSE;
+
+ if (message->get_exchange_type(message) == INFORMATIONAL_V1 ||
+ 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))
+ {
+ case ID_PROT:
+ task = (task_t *)isakmp_vendor_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ task = (task_t*)isakmp_cert_pre_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ task = (task_t *)main_mode_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ task = (task_t*)isakmp_cert_post_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ task = (task_t *)isakmp_natd_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ break;
+ case AGGRESSIVE:
+ task = (task_t *)isakmp_vendor_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ task = (task_t*)isakmp_cert_pre_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ task = (task_t *)aggressive_mode_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ task = (task_t*)isakmp_cert_post_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ task = (task_t *)isakmp_natd_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ break;
+ case QUICK_MODE:
+ if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
+ {
+ DBG1(DBG_IKE, "received quick mode request for "
+ "unestablished IKE_SA, ignored");
+ return FAILED;
+ }
+ task = (task_t *)quick_mode_create(this->ike_sa, NULL,
+ NULL, NULL);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ break;
+ case INFORMATIONAL_V1:
+ if (process_dpd(this, message))
+ {
+ dpd = TRUE;
+ }
+ else
+ {
+ task = (task_t *)informational_create(this->ike_sa, NULL);
+ this->passive_tasks->insert_first(this->passive_tasks, task);
+ }
+ break;
+ case TRANSACTION:
+ if (this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING)
+ {
+ task = (task_t *)mode_config_create(this->ike_sa, FALSE);
+ }
+ else
+ {
+ task = (task_t *)xauth_create(this->ike_sa, FALSE);
+ }
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ break;
+ default:
+ return FAILED;
+ }
+ }
+ if (dpd)
+ {
+ return initiate(this);
+ }
+ this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND, time_monotonic(NULL));
+
+ /* let the tasks process the message */
+ enumerator = this->passive_tasks->create_enumerator(this->passive_tasks);
+ while (enumerator->enumerate(enumerator, (void*)&task))
+ {
+ switch (task->process(task, message))
+ {
+ case SUCCESS:
+ /* task completed, remove it */
+ this->passive_tasks->remove_at(this->passive_tasks, enumerator);
+ task->destroy(task);
+ continue;
+ case NEED_MORE:
+ /* processed, but task needs at least another call to build() */
+ send_response = TRUE;
+ continue;
+ case ALREADY_DONE:
+ send_response = FALSE;
+ break;
+ case FAILED:
+ default:
+ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ /* FALL */
+ case DESTROY_ME:
+ /* critical failure, destroy IKE_SA */
+ this->passive_tasks->remove_at(this->passive_tasks, enumerator);
+ enumerator->destroy(enumerator);
+ task->destroy(task);
+ return DESTROY_ME;
+ }
+ break;
+ }
+ enumerator->destroy(enumerator);
+
+ if (send_response)
+ {
+ if (build_response(this, message) != SUCCESS)
+ {
+ return DESTROY_ME;
+ }
+ }
+ else
+ { /* We don't send a response, so don't retransmit one if we get
+ * the same message again. */
+ DESTROY_IF(this->responding.packet);
+ this->responding.packet = NULL;
+ }
+ if (this->passive_tasks->get_count(this->passive_tasks) == 0 &&
+ this->queued_tasks->get_count(this->queued_tasks) > 0)
+ {
+ /* passive tasks completed, check if an active task has been queued,
+ * such as XAUTH or modeconfig push */
+ return initiate(this);
+ }
+ return SUCCESS;
+}
+
+/**
+ * handle an incoming response message
+ */
+static status_t process_response(private_task_manager_t *this,
+ message_t *message)
+{
+ enumerator_t *enumerator;
+ message_t *queued;
+ status_t status;
+ task_t *task;
+
+ if (message->get_exchange_type(message) != this->initiating.type)
+ {
+ DBG1(DBG_IKE, "received %N response, but expected %N",
+ exchange_type_names, message->get_exchange_type(message),
+ exchange_type_names, this->initiating.type);
+ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ return DESTROY_ME;
+ }
+
+ enumerator = this->active_tasks->create_enumerator(this->active_tasks);
+ while (enumerator->enumerate(enumerator, (void*)&task))
+ {
+ switch (task->process(task, message))
+ {
+ case SUCCESS:
+ /* task completed, remove it */
+ this->active_tasks->remove_at(this->active_tasks, enumerator);
+ task->destroy(task);
+ continue;
+ case NEED_MORE:
+ /* processed, but task needs another exchange */
+ continue;
+ case ALREADY_DONE:
+ break;
+ case FAILED:
+ default:
+ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ /* FALL */
+ case DESTROY_ME:
+ /* critical failure, destroy IKE_SA */
+ this->active_tasks->remove_at(this->active_tasks, enumerator);
+ enumerator->destroy(enumerator);
+ task->destroy(task);
+ return DESTROY_ME;
+ }
+ break;
+ }
+ enumerator->destroy(enumerator);
+
+ this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
+ DESTROY_IF(this->initiating.packet);
+ this->initiating.packet = NULL;
+
+ if (this->queued && this->active_tasks->get_count(this->active_tasks) == 0)
+ {
+ queued = this->queued;
+ this->queued = NULL;
+ status = this->public.task_manager.process_message(
+ &this->public.task_manager, queued);
+ queued->destroy(queued);
+ if (status == DESTROY_ME)
+ {
+ return status;
+ }
+ }
+
+ return initiate(this);
+}
+
+/**
+ * Parse the given message and verify that it is valid.
+ */
+static status_t parse_message(private_task_manager_t *this, message_t *msg)
+{
+ status_t status;
+
+ status = msg->parse_body(msg, this->ike_sa->get_keymat(this->ike_sa));
+
+ if (status != SUCCESS)
+ {
+ switch (status)
+ {
+ case NOT_SUPPORTED:
+ DBG1(DBG_IKE, "unsupported exchange type");
+ send_notify(this, msg, INVALID_EXCHANGE_TYPE);
+ break;
+ case PARSE_ERROR:
+ DBG1(DBG_IKE, "message parsing failed");
+ send_notify(this, msg, PAYLOAD_MALFORMED);
+ break;
+ case VERIFY_ERROR:
+ DBG1(DBG_IKE, "message verification failed");
+ send_notify(this, msg, PAYLOAD_MALFORMED);
+ break;
+ case FAILED:
+ DBG1(DBG_IKE, "integrity check failed");
+ send_notify(this, msg, INVALID_HASH_INFORMATION);
+ break;
+ case INVALID_STATE:
+ DBG1(DBG_IKE, "found encrypted message, but no keys available");
+ send_notify(this, msg, PAYLOAD_MALFORMED);
+ default:
+ break;
+ }
+ DBG1(DBG_IKE, "%N %s with message ID %u processing failed",
+ exchange_type_names, msg->get_exchange_type(msg),
+ msg->get_request(msg) ? "request" : "response",
+ msg->get_message_id(msg));
+
+ if (this->ike_sa->get_state(this->ike_sa) == IKE_CREATED)
+ { /* invalid initiation attempt, close SA */
+ return DESTROY_ME;
+ }
+ }
+ return status;
+}
+
+METHOD(task_manager_t, process_message, status_t,
+ private_task_manager_t *this, message_t *msg)
+{
+ u_int32_t hash, mid, i;
+ host_t *me, *other;
+ status_t status;
+
+ /* TODO-IKEv1: update hosts more selectively */
+ me = msg->get_destination(msg);
+ other = msg->get_source(msg);
+ mid = msg->get_message_id(msg);
+ hash = chunk_hash(msg->get_packet_data(msg));
+ for (i = 0; i < MAX_OLD_HASHES; i++)
+ {
+ if (this->initiating.old_hashes[i] == hash)
+ {
+ if (this->initiating.packet &&
+ i == (this->initiating.old_hash_pos % MAX_OLD_HASHES) &&
+ (msg->get_exchange_type(msg) == QUICK_MODE ||
+ msg->get_exchange_type(msg) == AGGRESSIVE))
+ {
+ DBG1(DBG_IKE, "received retransmit of response with ID %u, "
+ "resending last request", mid);
+ charon->sender->send(charon->sender,
+ this->initiating.packet->clone(this->initiating.packet));
+ return SUCCESS;
+ }
+ DBG1(DBG_IKE, "received retransmit of response with ID %u, "
+ "but next request already sent", mid);
+ return SUCCESS;
+ }
+ }
+
+ if ((mid && mid == this->initiating.mid) ||
+ (this->initiating.mid == 0 &&
+ msg->get_exchange_type(msg) == this->initiating.type &&
+ this->active_tasks->get_count(this->active_tasks)))
+ {
+ msg->set_request(msg, FALSE);
+ charon->bus->message(charon->bus, msg, TRUE, FALSE);
+ status = parse_message(this, msg);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
+ time_monotonic(NULL));
+ this->ike_sa->update_hosts(this->ike_sa, me, other, TRUE);
+ charon->bus->message(charon->bus, msg, TRUE, TRUE);
+ if (process_response(this, msg) != SUCCESS)
+ {
+ flush(this);
+ return DESTROY_ME;
+ }
+ this->initiating.old_hashes[(++this->initiating.old_hash_pos) %
+ MAX_OLD_HASHES] = hash;
+ }
+ else
+ {
+ if (hash == this->responding.hash)
+ {
+ if (this->responding.packet)
+ {
+ DBG1(DBG_IKE, "received retransmit of request with ID %u, "
+ "retransmitting response", mid);
+ charon->sender->send(charon->sender,
+ this->responding.packet->clone(this->responding.packet));
+ }
+ else if (this->initiating.packet &&
+ this->initiating.type == INFORMATIONAL_V1)
+ {
+ DBG1(DBG_IKE, "received retransmit of DPD request, "
+ "retransmitting response");
+ charon->sender->send(charon->sender,
+ this->initiating.packet->clone(this->initiating.packet));
+ }
+ else
+ {
+ DBG1(DBG_IKE, "received retransmit of request with ID %u, "
+ "but no response to retransmit", mid);
+ }
+ return SUCCESS;
+ }
+ if (msg->get_exchange_type(msg) == TRANSACTION &&
+ this->active_tasks->get_count(this->active_tasks))
+ { /* main mode not yet complete, queue XAuth/Mode config tasks */
+ if (this->queued)
+ {
+ DBG1(DBG_IKE, "ignoring additional %N request, queue full",
+ exchange_type_names, TRANSACTION);
+ return SUCCESS;
+ }
+ this->queued = message_create_from_packet(msg->get_packet(msg));
+ if (this->queued->parse_header(this->queued) != SUCCESS)
+ {
+ this->queued->destroy(this->queued);
+ this->queued = NULL;
+ return FAILED;
+ }
+ DBG1(DBG_IKE, "queueing %N request as tasks still active",
+ exchange_type_names, TRANSACTION);
+ return SUCCESS;
+ }
+
+ msg->set_request(msg, TRUE);
+ charon->bus->message(charon->bus, msg, TRUE, FALSE);
+ status = parse_message(this, msg);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ /* if this IKE_SA is virgin, we check for a config */
+ if (this->ike_sa->get_ike_cfg(this->ike_sa) == NULL)
+ {
+ ike_sa_id_t *ike_sa_id;
+ ike_cfg_t *ike_cfg;
+ job_t *job;
+
+ ike_cfg = charon->backends->get_ike_cfg(charon->backends, me, other);
+ if (ike_cfg == NULL)
+ {
+ /* no config found for these hosts, destroy */
+ DBG1(DBG_IKE, "no IKE config found for %H...%H, sending %N",
+ me, other, notify_type_names, NO_PROPOSAL_CHOSEN);
+ send_notify(this, msg, NO_PROPOSAL_CHOSEN);
+ return DESTROY_ME;
+ }
+ this->ike_sa->set_ike_cfg(this->ike_sa, ike_cfg);
+ ike_cfg->destroy(ike_cfg);
+ /* add a timeout if peer does not establish it completely */
+ ike_sa_id = this->ike_sa->get_id(this->ike_sa);
+ job = (job_t*)delete_ike_sa_job_create(ike_sa_id, FALSE);
+ lib->scheduler->schedule_job(lib->scheduler, job,
+ lib->settings->get_int(lib->settings,
+ "%s.half_open_timeout", HALF_OPEN_IKE_SA_TIMEOUT,
+ charon->name));
+ }
+ this->ike_sa->update_hosts(this->ike_sa, me, other, TRUE);
+ charon->bus->message(charon->bus, msg, TRUE, TRUE);
+ if (process_request(this, msg) != SUCCESS)
+ {
+ flush(this);
+ return DESTROY_ME;
+ }
+ this->responding.hash = hash;
+ }
+ return SUCCESS;
+}
+
+METHOD(task_manager_t, queue_task, void,
+ private_task_manager_t *this, task_t *task)
+{
+ DBG2(DBG_IKE, "queueing %N task", task_type_names, task->get_type(task));
+ this->queued_tasks->insert_last(this->queued_tasks, task);
+}
+
+/**
+ * Check if a given task has been queued already
+ */
+static bool has_queued(private_task_manager_t *this, task_type_t type)
+{
+ enumerator_t *enumerator;
+ bool found = FALSE;
+ task_t *task;
+
+ enumerator = this->queued_tasks->create_enumerator(this->queued_tasks);
+ while (enumerator->enumerate(enumerator, &task))
+ {
+ if (task->get_type(task) == type)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return found;
+}
+
+METHOD(task_manager_t, queue_ike, void,
+ private_task_manager_t *this)
+{
+ peer_cfg_t *peer_cfg;
+
+ if (!has_queued(this, TASK_ISAKMP_VENDOR))
+ {
+ queue_task(this, (task_t*)isakmp_vendor_create(this->ike_sa, TRUE));
+ }
+ if (!has_queued(this, TASK_ISAKMP_CERT_PRE))
+ {
+ queue_task(this, (task_t*)isakmp_cert_pre_create(this->ike_sa, TRUE));
+ }
+ peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
+ if (peer_cfg->use_aggressive(peer_cfg))
+ {
+ if (!has_queued(this, TASK_AGGRESSIVE_MODE))
+ {
+ queue_task(this, (task_t*)aggressive_mode_create(this->ike_sa, TRUE));
+ }
+ }
+ else
+ {
+ if (!has_queued(this, TASK_MAIN_MODE))
+ {
+ queue_task(this, (task_t*)main_mode_create(this->ike_sa, TRUE));
+ }
+ }
+ if (!has_queued(this, TASK_ISAKMP_CERT_POST))
+ {
+ queue_task(this, (task_t*)isakmp_cert_post_create(this->ike_sa, TRUE));
+ }
+ if (!has_queued(this, TASK_ISAKMP_NATD))
+ {
+ queue_task(this, (task_t*)isakmp_natd_create(this->ike_sa, TRUE));
+ }
+}
+
+METHOD(task_manager_t, queue_ike_reauth, void,
+ private_task_manager_t *this)
+{
+ enumerator_t *enumerator;
+ child_sa_t *child_sa;
+ ike_sa_t *new;
+ host_t *host;
+
+ new = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager,
+ this->ike_sa->get_version(this->ike_sa), TRUE);
+ if (!new)
+ { /* shouldn't happen */
+ return;
+ }
+
+ new->set_peer_cfg(new, this->ike_sa->get_peer_cfg(this->ike_sa));
+ host = this->ike_sa->get_other_host(this->ike_sa);
+ new->set_other_host(new, host->clone(host));
+ host = this->ike_sa->get_my_host(this->ike_sa);
+ new->set_my_host(new, host->clone(host));
+ enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa, TRUE);
+ while (enumerator->enumerate(enumerator, &host))
+ {
+ new->add_virtual_ip(new, TRUE, host);
+ }
+ enumerator->destroy(enumerator);
+
+ enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
+ while (enumerator->enumerate(enumerator, &child_sa))
+ {
+ this->ike_sa->remove_child_sa(this->ike_sa, enumerator);
+ new->add_child_sa(new, child_sa);
+ }
+ enumerator->destroy(enumerator);
+
+ if (!new->get_child_count(new))
+ { /* check if a Quick Mode task is queued (UNITY_LOAD_BALANCE case) */
+ task_t *task;
+
+ enumerator = this->queued_tasks->create_enumerator(this->queued_tasks);
+ while (enumerator->enumerate(enumerator, &task))
+ {
+ if (task->get_type(task) == TASK_QUICK_MODE)
+ {
+ this->queued_tasks->remove_at(this->queued_tasks, enumerator);
+ task->migrate(task, new);
+ new->queue_task(new, task);
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ if (new->initiate(new, NULL, 0, NULL, NULL) != DESTROY_ME)
+ {
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, new);
+ this->ike_sa->set_state(this->ike_sa, IKE_REKEYING);
+ }
+ else
+ {
+ charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, new);
+ DBG1(DBG_IKE, "reauthenticating IKE_SA failed");
+ }
+ charon->bus->set_sa(charon->bus, this->ike_sa);
+}
+
+METHOD(task_manager_t, queue_ike_rekey, void,
+ private_task_manager_t *this)
+{
+ queue_ike_reauth(this);
+}
+
+METHOD(task_manager_t, queue_ike_delete, void,
+ private_task_manager_t *this)
+{
+ enumerator_t *enumerator;
+ child_sa_t *child_sa;
+
+ enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
+ while (enumerator->enumerate(enumerator, &child_sa))
+ {
+ queue_task(this, (task_t*)
+ quick_delete_create(this->ike_sa, child_sa->get_protocol(child_sa),
+ child_sa->get_spi(child_sa, TRUE), FALSE, FALSE));
+ }
+ enumerator->destroy(enumerator);
+
+ queue_task(this, (task_t*)isakmp_delete_create(this->ike_sa, TRUE));
+}
+
+METHOD(task_manager_t, queue_mobike, void,
+ private_task_manager_t *this, bool roam, bool address)
+{
+ /* Not supported in IKEv1 */
+}
+
+METHOD(task_manager_t, queue_child, void,
+ private_task_manager_t *this, child_cfg_t *cfg, u_int32_t reqid,
+ traffic_selector_t *tsi, traffic_selector_t *tsr)
+{
+ quick_mode_t *task;
+
+ task = quick_mode_create(this->ike_sa, cfg, tsi, tsr);
+ task->use_reqid(task, reqid);
+
+ queue_task(this, &task->task);
+}
+
+/**
+ * Check if two CHILD_SAs have the same traffic selector
+ */
+static bool have_equal_ts(child_sa_t *a, child_sa_t *b, bool local)
+{
+ linked_list_t *list;
+ traffic_selector_t *ts_a, *ts_b;
+
+ list = a->get_traffic_selectors(a, local);
+ if (list->get_first(list, (void**)&ts_a) == SUCCESS)
+ {
+ list = b->get_traffic_selectors(b, local);
+ if (list->get_first(list, (void**)&ts_b) == SUCCESS)
+ {
+ return ts_a->equals(ts_a, ts_b);
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * Check if a CHILD_SA is redundant and we should delete instead of rekey
+ */
+static bool is_redundant(private_task_manager_t *this, child_sa_t *child_sa)
+{
+ enumerator_t *enumerator;
+ child_sa_t *current;
+ bool redundant = FALSE;
+
+ enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (current->get_state(current) == CHILD_INSTALLED &&
+ streq(current->get_name(current), child_sa->get_name(child_sa)) &&
+ have_equal_ts(current, child_sa, TRUE) &&
+ have_equal_ts(current, child_sa, FALSE) &&
+ current->get_lifetime(current, FALSE) >
+ child_sa->get_lifetime(child_sa, FALSE))
+ {
+ DBG1(DBG_IKE, "deleting redundant CHILD_SA %s{%d}",
+ child_sa->get_name(child_sa), child_sa->get_reqid(child_sa));
+ redundant = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return redundant;
+}
+
+/**
+ * Get the first traffic selector of a CHILD_SA, local or remote
+ */
+static traffic_selector_t* get_first_ts(child_sa_t *child_sa, bool local)
+{
+ traffic_selector_t *ts = NULL;
+ linked_list_t *list;
+
+ list = child_sa->get_traffic_selectors(child_sa, local);
+ if (list->get_first(list, (void**)&ts) == SUCCESS)
+ {
+ return ts;
+ }
+ return NULL;
+}
+
+METHOD(task_manager_t, queue_child_rekey, void,
+ private_task_manager_t *this, protocol_id_t protocol, u_int32_t spi)
+{
+ child_sa_t *child_sa;
+ child_cfg_t *cfg;
+ quick_mode_t *task;
+
+ child_sa = this->ike_sa->get_child_sa(this->ike_sa, protocol, spi, TRUE);
+ if (!child_sa)
+ {
+ child_sa = this->ike_sa->get_child_sa(this->ike_sa, protocol, spi, FALSE);
+ }
+ if (child_sa && child_sa->get_state(child_sa) == CHILD_INSTALLED)
+ {
+ if (is_redundant(this, child_sa))
+ {
+ queue_task(this, (task_t*)quick_delete_create(this->ike_sa,
+ protocol, spi, FALSE, FALSE));
+ }
+ else
+ {
+ child_sa->set_state(child_sa, CHILD_REKEYING);
+ cfg = child_sa->get_config(child_sa);
+ task = quick_mode_create(this->ike_sa, cfg->get_ref(cfg),
+ get_first_ts(child_sa, TRUE), get_first_ts(child_sa, FALSE));
+ task->use_reqid(task, child_sa->get_reqid(child_sa));
+ task->rekey(task, child_sa->get_spi(child_sa, TRUE));
+
+ queue_task(this, &task->task);
+ }
+ }
+}
+
+METHOD(task_manager_t, queue_child_delete, void,
+ private_task_manager_t *this, protocol_id_t protocol, u_int32_t spi,
+ bool expired)
+{
+ queue_task(this, (task_t*)quick_delete_create(this->ike_sa, protocol,
+ spi, FALSE, expired));
+}
+
+METHOD(task_manager_t, queue_dpd, void,
+ private_task_manager_t *this)
+{
+ peer_cfg_t *peer_cfg;
+ u_int32_t t, retransmit;
+
+ queue_task(this, (task_t*)isakmp_dpd_create(this->ike_sa, DPD_R_U_THERE,
+ this->dpd_send++));
+ peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
+
+ /* compute timeout in milliseconds */
+ t = 1000 * peer_cfg->get_dpd_timeout(peer_cfg);
+ if (t == 0)
+ {
+ /* use the same timeout as a retransmitting IKE message would have */
+ for (retransmit = 0; retransmit <= this->retransmit_tries; retransmit++)
+ {
+ t += (u_int32_t)(this->retransmit_timeout * 1000.0 *
+ pow(this->retransmit_base, retransmit));
+ }
+ }
+
+ /* schedule DPD timeout job */
+ lib->scheduler->schedule_job_ms(lib->scheduler,
+ (job_t*)dpd_timeout_job_create(this->ike_sa->get_id(this->ike_sa)), t);
+}
+
+METHOD(task_manager_t, adopt_tasks, void,
+ private_task_manager_t *this, task_manager_t *other_public)
+{
+ private_task_manager_t *other = (private_task_manager_t*)other_public;
+ task_t *task;
+
+ /* move queued tasks from other to this */
+ while (other->queued_tasks->remove_last(other->queued_tasks,
+ (void**)&task) == SUCCESS)
+ {
+ DBG2(DBG_IKE, "migrating %N task", task_type_names, task->get_type(task));
+ task->migrate(task, this->ike_sa);
+ this->queued_tasks->insert_first(this->queued_tasks, task);
+ }
+}
+
+METHOD(task_manager_t, busy, bool,
+ private_task_manager_t *this)
+{
+ return (this->active_tasks->get_count(this->active_tasks) > 0);
+}
+
+METHOD(task_manager_t, incr_mid, void,
+ private_task_manager_t *this, bool initiate)
+{
+}
+
+METHOD(task_manager_t, reset, void,
+ private_task_manager_t *this, u_int32_t initiate, u_int32_t respond)
+{
+ enumerator_t *enumerator;
+ task_t *task;
+
+ /* reset message counters and retransmit packets */
+ DESTROY_IF(this->responding.packet);
+ DESTROY_IF(this->initiating.packet);
+ this->responding.packet = NULL;
+ this->responding.seqnr = RESPONDING_SEQ;
+ this->responding.retransmitted = 0;
+ this->initiating.packet = NULL;
+ this->initiating.mid = 0;
+ this->initiating.seqnr = 0;
+ this->initiating.retransmitted = 0;
+ this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
+ if (initiate != UINT_MAX)
+ {
+ this->dpd_send = initiate;
+ }
+ if (respond != UINT_MAX)
+ {
+ this->dpd_recv = respond;
+ }
+
+ /* reset queued tasks */
+ enumerator = this->queued_tasks->create_enumerator(this->queued_tasks);
+ while (enumerator->enumerate(enumerator, &task))
+ {
+ task->migrate(task, this->ike_sa);
+ }
+ enumerator->destroy(enumerator);
+
+ /* reset active tasks */
+ while (this->active_tasks->remove_last(this->active_tasks,
+ (void**)&task) == SUCCESS)
+ {
+ task->migrate(task, this->ike_sa);
+ this->queued_tasks->insert_first(this->queued_tasks, task);
+ }
+}
+
+METHOD(task_manager_t, create_task_enumerator, enumerator_t*,
+ private_task_manager_t *this, task_queue_t queue)
+{
+ switch (queue)
+ {
+ case TASK_QUEUE_ACTIVE:
+ return this->active_tasks->create_enumerator(this->active_tasks);
+ case TASK_QUEUE_PASSIVE:
+ return this->passive_tasks->create_enumerator(this->passive_tasks);
+ case TASK_QUEUE_QUEUED:
+ return this->queued_tasks->create_enumerator(this->queued_tasks);
+ default:
+ return enumerator_create_empty();
+ }
+}
+
+METHOD(task_manager_t, destroy, void,
+ private_task_manager_t *this)
+{
+ flush(this);
+
+ this->active_tasks->destroy(this->active_tasks);
+ this->queued_tasks->destroy(this->queued_tasks);
+ this->passive_tasks->destroy(this->passive_tasks);
+
+ DESTROY_IF(this->queued);
+ DESTROY_IF(this->responding.packet);
+ DESTROY_IF(this->initiating.packet);
+ DESTROY_IF(this->rng);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+task_manager_v1_t *task_manager_v1_create(ike_sa_t *ike_sa)
+{
+ private_task_manager_t *this;
+
+ INIT(this,
+ .public = {
+ .task_manager = {
+ .process_message = _process_message,
+ .queue_task = _queue_task,
+ .queue_ike = _queue_ike,
+ .queue_ike_rekey = _queue_ike_rekey,
+ .queue_ike_reauth = _queue_ike_reauth,
+ .queue_ike_delete = _queue_ike_delete,
+ .queue_mobike = _queue_mobike,
+ .queue_child = _queue_child,
+ .queue_child_rekey = _queue_child_rekey,
+ .queue_child_delete = _queue_child_delete,
+ .queue_dpd = _queue_dpd,
+ .initiate = _initiate,
+ .retransmit = _retransmit,
+ .incr_mid = _incr_mid,
+ .reset = _reset,
+ .adopt_tasks = _adopt_tasks,
+ .busy = _busy,
+ .create_task_enumerator = _create_task_enumerator,
+ .flush_queue = _flush_queue,
+ .destroy = _destroy,
+ },
+ },
+ .initiating = {
+ .type = EXCHANGE_TYPE_UNDEFINED,
+ },
+ .responding = {
+ .seqnr = RESPONDING_SEQ,
+ },
+ .ike_sa = ike_sa,
+ .rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK),
+ .queued_tasks = linked_list_create(),
+ .active_tasks = linked_list_create(),
+ .passive_tasks = linked_list_create(),
+ .retransmit_tries = lib->settings->get_int(lib->settings,
+ "%s.retransmit_tries", RETRANSMIT_TRIES, charon->name),
+ .retransmit_timeout = lib->settings->get_double(lib->settings,
+ "%s.retransmit_timeout", RETRANSMIT_TIMEOUT, charon->name),
+ .retransmit_base = lib->settings->get_double(lib->settings,
+ "%s.retransmit_base", RETRANSMIT_BASE, charon->name),
+ );
+
+ if (!this->rng)
+ {
+ DBG1(DBG_IKE, "no RNG found, unable to create IKE_SA");
+ destroy(this);
+ return NULL;
+ }
+ if (!this->rng->get_bytes(this->rng, sizeof(this->dpd_send),
+ (void*)&this->dpd_send))
+ {
+ DBG1(DBG_IKE, "failed to allocate message ID, unable to create IKE_SA");
+ destroy(this);
+ return NULL;
+ }
+ this->dpd_send &= 0x7FFFFFFF;
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/sa/ikev1/task_manager_v1.h b/src/libcharon/sa/ikev1/task_manager_v1.h
new file mode 100644
index 000000000..61e409bbe
--- /dev/null
+++ b/src/libcharon/sa/ikev1/task_manager_v1.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 task_manager_v1 task_manager_v1
+ * @{ @ingroup ikev1
+ */
+
+#ifndef TASK_MANAGER_V1_H_
+#define TASK_MANAGER_V1_H_
+
+typedef struct task_manager_v1_t task_manager_v1_t;
+
+#include <sa/task_manager.h>
+
+/**
+ * Task manager, IKEv1 variant.
+ */
+struct task_manager_v1_t {
+
+ /**
+ * Implements task_manager_t.
+ */
+ task_manager_t task_manager;
+};
+
+/**
+ * Create an instance of the task manager.
+ *
+ * @param ike_sa IKE_SA to manage.
+ */
+task_manager_v1_t *task_manager_v1_create(ike_sa_t *ike_sa);
+
+#endif /** TASK_MANAGER_V1_H_ @}*/
diff --git a/src/libcharon/sa/ikev1/tasks/aggressive_mode.c b/src/libcharon/sa/ikev1/tasks/aggressive_mode.c
new file mode 100644
index 000000000..954dea880
--- /dev/null
+++ b/src/libcharon/sa/ikev1/tasks/aggressive_mode.c
@@ -0,0 +1,714 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 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 "aggressive_mode.h"
+
+#include <string.h>
+
+#include <daemon.h>
+#include <sa/ikev1/phase1.h>
+#include <encoding/payloads/sa_payload.h>
+#include <encoding/payloads/id_payload.h>
+#include <encoding/payloads/hash_payload.h>
+#include <sa/ikev1/tasks/xauth.h>
+#include <sa/ikev1/tasks/mode_config.h>
+#include <sa/ikev1/tasks/informational.h>
+#include <sa/ikev1/tasks/isakmp_delete.h>
+#include <processing/jobs/adopt_children_job.h>
+
+typedef struct private_aggressive_mode_t private_aggressive_mode_t;
+
+/**
+ * Private members of a aggressive_mode_t task.
+ */
+struct private_aggressive_mode_t {
+
+ /**
+ * Public methods and task_t interface.
+ */
+ aggressive_mode_t public;
+
+ /**
+ * Assigned IKE_SA.
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * Are we the initiator?
+ */
+ bool initiator;
+
+ /**
+ * Common phase 1 helper class
+ */
+ phase1_t *ph1;
+
+ /**
+ * IKE config to establish
+ */
+ ike_cfg_t *ike_cfg;
+
+ /**
+ * Peer config to use
+ */
+ peer_cfg_t *peer_cfg;
+
+ /**
+ * selected IKE proposal
+ */
+ proposal_t *proposal;
+
+ /**
+ * Negotiated SA lifetime
+ */
+ u_int32_t lifetime;
+
+ /**
+ * Negotiated authentication method
+ */
+ auth_method_t method;
+
+ /**
+ * Encoded ID payload, without fixed header
+ */
+ chunk_t id_data;
+
+ /** states of aggressive mode */
+ enum {
+ AM_INIT,
+ AM_AUTH,
+ } state;
+};
+
+/**
+ * Set IKE_SA to established state
+ */
+static bool establish(private_aggressive_mode_t *this)
+{
+ if (!charon->bus->authorize(charon->bus, TRUE))
+ {
+ DBG1(DBG_IKE, "final authorization hook forbids IKE_SA, cancelling");
+ return FALSE;
+ }
+
+ DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa),
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_my_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
+
+ this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
+ charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
+
+ return TRUE;
+}
+
+/**
+ * Check for notify errors, return TRUE if error found
+ */
+static bool has_notify_errors(private_aggressive_mode_t *this, message_t *message)
+{
+ enumerator_t *enumerator;
+ payload_t *payload;
+ bool err = FALSE;
+
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ if (payload->get_type(payload) == NOTIFY_V1)
+ {
+ notify_payload_t *notify;
+ notify_type_t type;
+
+ notify = (notify_payload_t*)payload;
+ type = notify->get_notify_type(notify);
+ if (type < 16384)
+ {
+ DBG1(DBG_IKE, "received %N error notify",
+ notify_type_names, type);
+ err = TRUE;
+ }
+ else
+ {
+ DBG1(DBG_IKE, "received %N notify", notify_type_names, type);
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return err;
+}
+
+/**
+ * Queue a task sending a notify in an INFORMATIONAL exchange
+ */
+static status_t send_notify(private_aggressive_mode_t *this, notify_type_t type)
+{
+ notify_payload_t *notify;
+ ike_sa_id_t *ike_sa_id;
+ u_int64_t spi_i, spi_r;
+ chunk_t spi;
+
+ notify = notify_payload_create_from_protocol_and_type(NOTIFY_V1,
+ PROTO_IKE, type);
+ ike_sa_id = this->ike_sa->get_id(this->ike_sa);
+ spi_i = ike_sa_id->get_initiator_spi(ike_sa_id);
+ spi_r = ike_sa_id->get_responder_spi(ike_sa_id);
+ spi = chunk_cata("cc", chunk_from_thing(spi_i), chunk_from_thing(spi_r));
+ notify->set_spi_data(notify, spi);
+
+ this->ike_sa->queue_task(this->ike_sa,
+ (task_t*)informational_create(this->ike_sa, notify));
+ /* cancel all active/passive tasks in favour of informational */
+ this->ike_sa->flush_queue(this->ike_sa,
+ this->initiator ? TASK_QUEUE_ACTIVE : TASK_QUEUE_PASSIVE);
+ return ALREADY_DONE;
+}
+
+/**
+ * Queue a delete task if authentication failed as initiator
+ */
+static status_t send_delete(private_aggressive_mode_t *this)
+{
+ this->ike_sa->queue_task(this->ike_sa,
+ (task_t*)isakmp_delete_create(this->ike_sa, TRUE));
+ /* cancel all active tasks in favour of informational */
+ this->ike_sa->flush_queue(this->ike_sa,
+ this->initiator ? TASK_QUEUE_ACTIVE : TASK_QUEUE_PASSIVE);
+ return ALREADY_DONE;
+}
+
+METHOD(task_t, build_i, status_t,
+ private_aggressive_mode_t *this, message_t *message)
+{
+ switch (this->state)
+ {
+ case AM_INIT:
+ {
+ sa_payload_t *sa_payload;
+ id_payload_t *id_payload;
+ linked_list_t *proposals;
+ identification_t *id;
+ packet_t *packet;
+ u_int16_t group;
+
+ DBG0(DBG_IKE, "initiating Aggressive Mode IKE_SA %s[%d] to %H",
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa));
+ this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
+
+ this->ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
+ this->peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
+ this->peer_cfg->get_ref(this->peer_cfg);
+
+ this->method = this->ph1->get_auth_method(this->ph1, this->peer_cfg);
+ if (this->method == AUTH_NONE)
+ {
+ DBG1(DBG_CFG, "configuration uses unsupported authentication");
+ return FAILED;
+ }
+ this->lifetime = this->peer_cfg->get_reauth_time(this->peer_cfg,
+ FALSE);
+ if (!this->lifetime)
+ { /* fall back to rekey time of no rekey time configured */
+ this->lifetime = this->peer_cfg->get_rekey_time(this->peer_cfg,
+ FALSE);
+ }
+ this->lifetime += this->peer_cfg->get_over_time(this->peer_cfg);
+ proposals = this->ike_cfg->get_proposals(this->ike_cfg);
+ sa_payload = sa_payload_create_from_proposals_v1(proposals,
+ this->lifetime, 0, this->method, MODE_NONE, FALSE, 0);
+ proposals->destroy_offset(proposals, offsetof(proposal_t, destroy));
+
+ message->add_payload(message, &sa_payload->payload_interface);
+
+ group = this->ike_cfg->get_dh_group(this->ike_cfg);
+ if (group == MODP_NONE)
+ {
+ DBG1(DBG_IKE, "DH group selection failed");
+ return FAILED;
+ }
+ if (!this->ph1->create_dh(this->ph1, group))
+ {
+ DBG1(DBG_IKE, "DH group %N not supported",
+ diffie_hellman_group_names, group);
+ return FAILED;
+ }
+ if (!this->ph1->add_nonce_ke(this->ph1, message))
+ {
+ return FAILED;
+ }
+ id = this->ph1->get_id(this->ph1, this->peer_cfg, TRUE);
+ if (!id)
+ {
+ DBG1(DBG_CFG, "own identity not known");
+ return FAILED;
+ }
+ this->ike_sa->set_my_id(this->ike_sa, id->clone(id));
+ id_payload = id_payload_create_from_identification(ID_V1, id);
+ this->id_data = id_payload->get_encoded(id_payload);
+ message->add_payload(message, &id_payload->payload_interface);
+
+ /* pregenerate message to store SA payload */
+ if (this->ike_sa->generate_message(this->ike_sa, message,
+ &packet) != SUCCESS)
+ {
+ DBG1(DBG_IKE, "pregenerating SA payload failed");
+ return FAILED;
+ }
+ packet->destroy(packet);
+ if (!this->ph1->save_sa_payload(this->ph1, message))
+ {
+ DBG1(DBG_IKE, "SA payload invalid");
+ return FAILED;
+ }
+ this->state = AM_AUTH;
+ return NEED_MORE;
+ }
+ case AM_AUTH:
+ {
+ if (!this->ph1->build_auth(this->ph1, this->method, message,
+ this->id_data))
+ {
+ this->id_data = chunk_empty;
+ return send_notify(this, AUTHENTICATION_FAILED);
+ }
+ this->id_data = chunk_empty;
+
+ switch (this->method)
+ {
+ case AUTH_XAUTH_INIT_PSK:
+ case AUTH_XAUTH_INIT_RSA:
+ case AUTH_HYBRID_INIT_RSA:
+ /* wait for XAUTH request */
+ break;
+ case AUTH_XAUTH_RESP_PSK:
+ case AUTH_XAUTH_RESP_RSA:
+ case AUTH_HYBRID_RESP_RSA:
+ this->ike_sa->queue_task(this->ike_sa,
+ (task_t*)xauth_create(this->ike_sa, TRUE));
+ return SUCCESS;
+ default:
+ if (charon->ike_sa_manager->check_uniqueness(
+ charon->ike_sa_manager, this->ike_sa, FALSE))
+ {
+ DBG1(DBG_IKE, "cancelling Aggressive Mode due to "
+ "uniqueness policy");
+ return send_notify(this, AUTHENTICATION_FAILED);
+ }
+ if (!establish(this))
+ {
+ return send_notify(this, AUTHENTICATION_FAILED);
+ }
+ break;
+ }
+ if (this->ph1->has_virtual_ip(this->ph1, this->peer_cfg))
+ {
+ this->ike_sa->queue_task(this->ike_sa,
+ (task_t*)mode_config_create(this->ike_sa, TRUE));
+ }
+ return SUCCESS;
+ }
+ default:
+ return FAILED;
+ }
+}
+
+METHOD(task_t, process_r, status_t,
+ private_aggressive_mode_t *this, message_t *message)
+{
+ switch (this->state)
+ {
+ case AM_INIT:
+ {
+ sa_payload_t *sa_payload;
+ id_payload_t *id_payload;
+ identification_t *id;
+ linked_list_t *list;
+ u_int16_t group;
+
+ this->ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
+ DBG0(DBG_IKE, "%H is initiating a Aggressive Mode IKE_SA",
+ message->get_source(message));
+ this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
+
+ this->ike_sa->update_hosts(this->ike_sa,
+ message->get_destination(message),
+ message->get_source(message), TRUE);
+
+ sa_payload = (sa_payload_t*)message->get_payload(message,
+ SECURITY_ASSOCIATION_V1);
+ if (!sa_payload)
+ {
+ DBG1(DBG_IKE, "SA payload missing");
+ return send_notify(this, INVALID_PAYLOAD_TYPE);
+ }
+ if (!this->ph1->save_sa_payload(this->ph1, message))
+ {
+ return send_notify(this, INVALID_PAYLOAD_TYPE);
+ }
+
+ list = sa_payload->get_proposals(sa_payload);
+ this->proposal = this->ike_cfg->select_proposal(this->ike_cfg,
+ list, FALSE);
+ list->destroy_offset(list, offsetof(proposal_t, destroy));
+ if (!this->proposal)
+ {
+ DBG1(DBG_IKE, "no proposal found");
+ return send_notify(this, NO_PROPOSAL_CHOSEN);
+ }
+ this->ike_sa->set_proposal(this->ike_sa, this->proposal);
+
+ this->method = sa_payload->get_auth_method(sa_payload);
+ this->lifetime = sa_payload->get_lifetime(sa_payload);
+
+ switch (this->method)
+ {
+ case AUTH_XAUTH_INIT_PSK:
+ case AUTH_XAUTH_RESP_PSK:
+ case AUTH_PSK:
+ if (!lib->settings->get_bool(lib->settings, "%s.i_dont_care"
+ "_about_security_and_use_aggressive_mode_psk",
+ FALSE, charon->name))
+ {
+ DBG1(DBG_IKE, "Aggressive Mode PSK disabled for "
+ "security reasons");
+ return send_notify(this, AUTHENTICATION_FAILED);
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!this->proposal->get_algorithm(this->proposal,
+ DIFFIE_HELLMAN_GROUP, &group, NULL))
+ {
+ DBG1(DBG_IKE, "DH group selection failed");
+ return send_notify(this, INVALID_KEY_INFORMATION);
+ }
+ if (!this->ph1->create_dh(this->ph1, group))
+ {
+ DBG1(DBG_IKE, "negotiated DH group not supported");
+ return send_notify(this, INVALID_KEY_INFORMATION);
+ }
+ if (!this->ph1->get_nonce_ke(this->ph1, message))
+ {
+ return send_notify(this, INVALID_PAYLOAD_TYPE);
+ }
+
+ id_payload = (id_payload_t*)message->get_payload(message, ID_V1);
+ if (!id_payload)
+ {
+ DBG1(DBG_IKE, "IDii payload missing");
+ return send_notify(this, INVALID_PAYLOAD_TYPE);
+ }
+
+ id = id_payload->get_identification(id_payload);
+ this->id_data = id_payload->get_encoded(id_payload);
+ this->ike_sa->set_other_id(this->ike_sa, id);
+ this->peer_cfg = this->ph1->select_config(this->ph1,
+ this->method, TRUE, id);
+ if (!this->peer_cfg)
+ {
+ return send_notify(this, AUTHENTICATION_FAILED);
+ }
+ this->ike_sa->set_peer_cfg(this->ike_sa, this->peer_cfg);
+
+ this->state = AM_AUTH;
+ if (has_notify_errors(this, message))
+ {
+ return FAILED;
+ }
+ return NEED_MORE;
+ }
+ case AM_AUTH:
+ {
+ while (TRUE)
+ {
+ if (this->ph1->verify_auth(this->ph1, this->method, message,
+ this->id_data))
+ {
+ break;
+ }
+ this->peer_cfg->destroy(this->peer_cfg);
+ this->peer_cfg = this->ph1->select_config(this->ph1,
+ this->method, TRUE, NULL);
+ if (!this->peer_cfg)
+ {
+ this->id_data = chunk_empty;
+ return send_delete(this);
+ }
+ this->ike_sa->set_peer_cfg(this->ike_sa, this->peer_cfg);
+ }
+ this->id_data = chunk_empty;
+
+ if (!charon->bus->authorize(charon->bus, FALSE))
+ {
+ DBG1(DBG_IKE, "Aggressive Mode authorization hook forbids "
+ "IKE_SA, cancelling");
+ return send_delete(this);
+ }
+
+ switch (this->method)
+ {
+ case AUTH_XAUTH_INIT_PSK:
+ case AUTH_XAUTH_INIT_RSA:
+ case AUTH_HYBRID_INIT_RSA:
+ this->ike_sa->queue_task(this->ike_sa,
+ (task_t*)xauth_create(this->ike_sa, TRUE));
+ return SUCCESS;
+ case AUTH_XAUTH_RESP_PSK:
+ case AUTH_XAUTH_RESP_RSA:
+ case AUTH_HYBRID_RESP_RSA:
+ /* wait for XAUTH request */
+ break;
+ default:
+ if (charon->ike_sa_manager->check_uniqueness(
+ charon->ike_sa_manager, this->ike_sa, FALSE))
+ {
+ DBG1(DBG_IKE, "cancelling Aggressive Mode due to "
+ "uniqueness policy");
+ return send_delete(this);
+ }
+ if (!establish(this))
+ {
+ return send_delete(this);
+ }
+ lib->processor->queue_job(lib->processor, (job_t*)
+ adopt_children_job_create(
+ this->ike_sa->get_id(this->ike_sa)));
+ break;
+ }
+ if (!this->ph1->has_pool(this->ph1, this->peer_cfg) &&
+ this->ph1->has_virtual_ip(this->ph1, this->peer_cfg))
+ {
+ this->ike_sa->queue_task(this->ike_sa,
+ (task_t*)mode_config_create(this->ike_sa, TRUE));
+ }
+ return SUCCESS;
+ }
+ default:
+ return FAILED;
+ }
+}
+
+METHOD(task_t, build_r, status_t,
+ private_aggressive_mode_t *this, message_t *message)
+{
+ if (this->state == AM_AUTH)
+ {
+ sa_payload_t *sa_payload;
+ id_payload_t *id_payload;
+ identification_t *id;
+
+ sa_payload = sa_payload_create_from_proposal_v1(this->proposal,
+ this->lifetime, 0, this->method, MODE_NONE, FALSE, 0);
+ message->add_payload(message, &sa_payload->payload_interface);
+
+ if (!this->ph1->add_nonce_ke(this->ph1, message))
+ {
+ return send_notify(this, INVALID_KEY_INFORMATION);
+ }
+ if (!this->ph1->create_hasher(this->ph1))
+ {
+ return send_notify(this, NO_PROPOSAL_CHOSEN);
+ }
+ if (!this->ph1->derive_keys(this->ph1, this->peer_cfg, this->method))
+ {
+ return send_notify(this, INVALID_KEY_INFORMATION);
+ }
+
+ id = this->ph1->get_id(this->ph1, this->peer_cfg, TRUE);
+ if (!id)
+ {
+ DBG1(DBG_CFG, "own identity not known");
+ return send_notify(this, INVALID_ID_INFORMATION);
+ }
+ this->ike_sa->set_my_id(this->ike_sa, id->clone(id));
+
+ id_payload = id_payload_create_from_identification(ID_V1, id);
+ message->add_payload(message, &id_payload->payload_interface);
+
+ if (!this->ph1->build_auth(this->ph1, this->method, message,
+ id_payload->get_encoded(id_payload)))
+ {
+ return send_notify(this, AUTHENTICATION_FAILED);
+ }
+ return NEED_MORE;
+ }
+ return FAILED;
+}
+
+METHOD(task_t, process_i, status_t,
+ private_aggressive_mode_t *this, message_t *message)
+{
+ if (this->state == AM_AUTH)
+ {
+ auth_method_t method;
+ sa_payload_t *sa_payload;
+ id_payload_t *id_payload;
+ identification_t *id, *cid;
+ linked_list_t *list;
+ u_int32_t lifetime;
+
+ sa_payload = (sa_payload_t*)message->get_payload(message,
+ SECURITY_ASSOCIATION_V1);
+ if (!sa_payload)
+ {
+ DBG1(DBG_IKE, "SA payload missing");
+ return send_notify(this, INVALID_PAYLOAD_TYPE);
+ }
+ list = sa_payload->get_proposals(sa_payload);
+ this->proposal = this->ike_cfg->select_proposal(this->ike_cfg,
+ list, FALSE);
+ list->destroy_offset(list, offsetof(proposal_t, destroy));
+ if (!this->proposal)
+ {
+ DBG1(DBG_IKE, "no proposal found");
+ return send_notify(this, NO_PROPOSAL_CHOSEN);
+ }
+ this->ike_sa->set_proposal(this->ike_sa, this->proposal);
+
+ lifetime = sa_payload->get_lifetime(sa_payload);
+ if (lifetime != this->lifetime)
+ {
+ DBG1(DBG_IKE, "received lifetime %us does not match configured "
+ "lifetime %us", lifetime, this->lifetime);
+ }
+ this->lifetime = lifetime;
+ method = sa_payload->get_auth_method(sa_payload);
+ if (method != this->method)
+ {
+ DBG1(DBG_IKE, "received %N authentication, but configured %N, "
+ "continue with configured", auth_method_names, method,
+ auth_method_names, this->method);
+ }
+ if (!this->ph1->get_nonce_ke(this->ph1, message))
+ {
+ return send_notify(this, INVALID_PAYLOAD_TYPE);
+ }
+ if (!this->ph1->create_hasher(this->ph1))
+ {
+ return send_notify(this, NO_PROPOSAL_CHOSEN);
+ }
+
+ id_payload = (id_payload_t*)message->get_payload(message, ID_V1);
+ if (!id_payload)
+ {
+ DBG1(DBG_IKE, "IDir payload missing");
+ return send_delete(this);
+ }
+ id = id_payload->get_identification(id_payload);
+ cid = this->ph1->get_id(this->ph1, this->peer_cfg, FALSE);
+ if (cid && !id->matches(id, cid))
+ {
+ DBG1(DBG_IKE, "IDir '%Y' does not match to '%Y'", id, cid);
+ id->destroy(id);
+ return send_notify(this, INVALID_ID_INFORMATION);
+ }
+ this->ike_sa->set_other_id(this->ike_sa, id);
+
+ if (!this->ph1->derive_keys(this->ph1, this->peer_cfg, this->method))
+ {
+ return send_notify(this, INVALID_KEY_INFORMATION);
+ }
+ if (!this->ph1->verify_auth(this->ph1, this->method, message,
+ id_payload->get_encoded(id_payload)))
+ {
+ return send_notify(this, AUTHENTICATION_FAILED);
+ }
+ if (!charon->bus->authorize(charon->bus, FALSE))
+ {
+ DBG1(DBG_IKE, "Aggressive Mode authorization hook forbids IKE_SA, "
+ "cancelling");
+ return send_notify(this, AUTHENTICATION_FAILED);
+ }
+
+ return NEED_MORE;
+ }
+ return FAILED;
+}
+
+METHOD(task_t, get_type, task_type_t,
+ private_aggressive_mode_t *this)
+{
+ return TASK_AGGRESSIVE_MODE;
+}
+
+METHOD(task_t, migrate, void,
+ private_aggressive_mode_t *this, ike_sa_t *ike_sa)
+{
+ DESTROY_IF(this->peer_cfg);
+ DESTROY_IF(this->proposal);
+ this->ph1->destroy(this->ph1);
+ chunk_free(&this->id_data);
+
+ this->ike_sa = ike_sa;
+ this->state = AM_INIT;
+ this->peer_cfg = NULL;
+ this->proposal = NULL;
+ this->ph1 = phase1_create(ike_sa, this->initiator);
+}
+
+METHOD(task_t, destroy, void,
+ private_aggressive_mode_t *this)
+{
+ DESTROY_IF(this->peer_cfg);
+ DESTROY_IF(this->proposal);
+ this->ph1->destroy(this->ph1);
+ chunk_free(&this->id_data);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+aggressive_mode_t *aggressive_mode_create(ike_sa_t *ike_sa, bool initiator)
+{
+ private_aggressive_mode_t *this;
+
+ INIT(this,
+ .public = {
+ .task = {
+ .get_type = _get_type,
+ .migrate = _migrate,
+ .destroy = _destroy,
+ },
+ },
+ .ike_sa = ike_sa,
+ .ph1 = phase1_create(ike_sa, initiator),
+ .initiator = initiator,
+ .state = AM_INIT,
+ );
+
+ if (initiator)
+ {
+ this->public.task.build = _build_i;
+ this->public.task.process = _process_i;
+ }
+ else
+ {
+ this->public.task.build = _build_r;
+ this->public.task.process = _process_r;
+ }
+
+ return &this->public;
+}
diff --git a/src/libcharon/sa/ikev1/tasks/aggressive_mode.h b/src/libcharon/sa/ikev1/tasks/aggressive_mode.h
new file mode 100644
index 000000000..d0666f41c
--- /dev/null
+++ b/src/libcharon/sa/ikev1/tasks/aggressive_mode.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 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 aggressive_mode aggressive_mode
+ * @{ @ingroup tasks_v1
+ */
+
+#ifndef AGGRESSIVE_MODE_H_
+#define AGGRESSIVE_MODE_H_
+
+typedef struct aggressive_mode_t aggressive_mode_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/task.h>
+
+/**
+ * IKEv1 aggressive mode, establishes an IKE_SA without identity protection.
+ */
+struct aggressive_mode_t {
+
+ /**
+ * Implements the task_t interface
+ */
+ task_t task;
+};
+
+/**
+ * Create a new AGGRESSIVE_MODE task.
+ *
+ * @param ike_sa IKE_SA this task works for
+ * @param initiator TRUE if task initiated locally
+ * @return task to handle by the task_manager
+ */
+aggressive_mode_t *aggressive_mode_create(ike_sa_t *ike_sa, bool initiator);
+
+#endif /** AGGRESSIVE_MODE_H_ @}*/
diff --git a/src/libcharon/sa/ikev1/tasks/informational.c b/src/libcharon/sa/ikev1/tasks/informational.c
new file mode 100644
index 000000000..bda1d2afb
--- /dev/null
+++ b/src/libcharon/sa/ikev1/tasks/informational.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 "informational.h"
+
+#include <daemon.h>
+#include <sa/ikev1/tasks/isakmp_delete.h>
+#include <sa/ikev1/tasks/quick_delete.h>
+
+#include <encoding/payloads/delete_payload.h>
+
+typedef struct private_informational_t private_informational_t;
+
+/**
+ * Private members of a informational_t task.
+ */
+struct private_informational_t {
+
+ /**
+ * Public methods and task_t interface.
+ */
+ informational_t public;
+
+ /**
+ * Assigned IKE_SA.
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * Notify payload to send
+ */
+ notify_payload_t *notify;
+
+ /**
+ * Delete subtask
+ */
+ task_t *del;
+};
+
+/**
+ * Cancel active quick mode after receiving an error
+ */
+static void cancel_quick_mode(private_informational_t *this)
+{
+ enumerator_t *enumerator;
+ task_t *task;
+
+ enumerator = this->ike_sa->create_task_enumerator(this->ike_sa,
+ TASK_QUEUE_ACTIVE);
+ while (enumerator->enumerate(enumerator, &task))
+ {
+ if (task->get_type(task) == TASK_QUICK_MODE)
+ {
+ this->ike_sa->flush_queue(this->ike_sa, TASK_QUEUE_ACTIVE);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+METHOD(task_t, build_i, status_t,
+ private_informational_t *this, message_t *message)
+{
+ message->add_payload(message, &this->notify->payload_interface);
+ this->notify = NULL;
+ return SUCCESS;
+}
+
+METHOD(task_t, process_r, status_t,
+ private_informational_t *this, message_t *message)
+{
+ enumerator_t *enumerator;
+ delete_payload_t *delete;
+ notify_payload_t *notify;
+ notify_type_t type;
+ payload_t *payload;
+ status_t status = SUCCESS;
+
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ switch (payload->get_type(payload))
+ {
+ case NOTIFY_V1:
+ notify = (notify_payload_t*)payload;
+ type = notify->get_notify_type(notify);
+
+ if (type == INITIAL_CONTACT_IKEV1)
+ {
+ this->ike_sa->set_condition(this->ike_sa,
+ COND_INIT_CONTACT_SEEN, TRUE);
+ }
+ else if (type == UNITY_LOAD_BALANCE)
+ {
+ host_t *redirect, *me;
+ chunk_t data;
+
+ data = notify->get_notification_data(notify);
+ redirect = host_create_from_chunk(AF_INET, data,
+ IKEV2_UDP_PORT);
+ if (redirect)
+ { /* treat the redirect as reauthentication */
+ DBG1(DBG_IKE, "received %N notify. redirected to %H",
+ notify_type_names, type, redirect);
+ /* Cisco boxes reject the first message from 4500 */
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ me->set_port(me, charon->socket->get_port(
+ charon->socket, FALSE));
+ this->ike_sa->set_other_host(this->ike_sa, redirect);
+ this->ike_sa->reauth(this->ike_sa);
+ enumerator->destroy(enumerator);
+ return DESTROY_ME;
+ }
+ else
+ {
+ DBG1(DBG_IKE, "received %N notify, invalid address");
+ }
+ }
+ else if (type < 16384)
+ {
+ DBG1(DBG_IKE, "received %N error notify",
+ notify_type_names, type);
+ if (this->ike_sa->get_state(this->ike_sa) == IKE_CONNECTING)
+ { /* only critical during main mode */
+ status = FAILED;
+ }
+ switch (type)
+ {
+ case INVALID_ID_INFORMATION:
+ case NO_PROPOSAL_CHOSEN:
+ cancel_quick_mode(this);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ else
+ {
+ DBG1(DBG_IKE, "received %N notify",
+ notify_type_names, type);
+ }
+ continue;
+ case DELETE_V1:
+ if (!this->del)
+ {
+ delete = (delete_payload_t*)payload;
+ if (delete->get_protocol_id(delete) == PROTO_IKE)
+ {
+ this->del = (task_t*)isakmp_delete_create(this->ike_sa,
+ FALSE);
+ }
+ else
+ {
+ this->del = (task_t*)quick_delete_create(this->ike_sa,
+ PROTO_NONE, 0, FALSE, FALSE);
+ }
+ }
+ break;
+ default:
+ continue;
+ }
+ break;
+ }
+ enumerator->destroy(enumerator);
+
+ if (this->del && status == SUCCESS)
+ {
+ return this->del->process(this->del, message);
+ }
+ return status;
+}
+
+METHOD(task_t, build_r, status_t,
+ private_informational_t *this, message_t *message)
+{
+ if (this->del)
+ {
+ return this->del->build(this->del, message);
+ }
+ return FAILED;
+}
+
+METHOD(task_t, process_i, status_t,
+ private_informational_t *this, message_t *message)
+{
+ return FAILED;
+}
+
+METHOD(task_t, get_type, task_type_t,
+ private_informational_t *this)
+{
+ return TASK_INFORMATIONAL;
+}
+
+METHOD(task_t, migrate, void,
+ private_informational_t *this, ike_sa_t *ike_sa)
+{
+ this->ike_sa = ike_sa;
+}
+
+METHOD(task_t, destroy, void,
+ private_informational_t *this)
+{
+ DESTROY_IF(this->notify);
+ DESTROY_IF(this->del);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+informational_t *informational_create(ike_sa_t *ike_sa, notify_payload_t *notify)
+{
+ private_informational_t *this;
+
+ INIT(this,
+ .public = {
+ .task = {
+ .get_type = _get_type,
+ .migrate = _migrate,
+ .destroy = _destroy,
+ },
+ },
+ .ike_sa = ike_sa,
+ .notify = notify,
+ );
+
+ if (notify)
+ {
+ this->public.task.build = _build_i;
+ this->public.task.process = _process_i;
+ }
+ else
+ {
+ this->public.task.build = _build_r;
+ this->public.task.process = _process_r;
+ }
+
+ return &this->public;
+}
diff --git a/src/libcharon/sa/ikev1/tasks/informational.h b/src/libcharon/sa/ikev1/tasks/informational.h
new file mode 100644
index 000000000..52938ffbc
--- /dev/null
+++ b/src/libcharon/sa/ikev1/tasks/informational.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 informational informational
+ * @{ @ingroup tasks_v1
+ */
+
+#ifndef INFORMATIONAL_H_
+#define INFORMATIONAL_H_
+
+typedef struct informational_t informational_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/task.h>
+#include <encoding/payloads/notify_payload.h>
+
+/**
+ * IKEv1 informational exchange, negotiates errors.
+ */
+struct informational_t {
+
+ /**
+ * Implements the task_t interface
+ */
+ task_t task;
+};
+
+/**
+ * Create a new informational task.
+ *
+ * @param ike_sa IKE_SA this task works for
+ * @param notify notify to send as initiator, NULL if responder
+ * @return task to handle by the task_manager
+ */
+informational_t *informational_create(ike_sa_t *ike_sa, notify_payload_t *notify);
+
+#endif /** INFORMATIONAL_H_ @}*/
diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_cert_post.c b/src/libcharon/sa/ikev1/tasks/isakmp_cert_post.c
new file mode 100644
index 000000000..edad3b2fa
--- /dev/null
+++ b/src/libcharon/sa/ikev1/tasks/isakmp_cert_post.c
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 "isakmp_cert_post.h"
+
+#include <daemon.h>
+#include <sa/ike_sa.h>
+#include <encoding/payloads/cert_payload.h>
+#include <encoding/payloads/certreq_payload.h>
+#include <encoding/payloads/auth_payload.h>
+#include <encoding/payloads/sa_payload.h>
+#include <credentials/certificates/x509.h>
+
+
+typedef struct private_isakmp_cert_post_t private_isakmp_cert_post_t;
+
+/**
+ * Private members of a isakmp_cert_post_t task.
+ */
+struct private_isakmp_cert_post_t {
+
+ /**
+ * Public methods and task_t interface.
+ */
+ isakmp_cert_post_t public;
+
+ /**
+ * Assigned IKE_SA.
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * Are we the initiator?
+ */
+ bool initiator;
+
+ /**
+ * States of ike cert pre
+ */
+ enum {
+ CR_SA,
+ CR_KE,
+ CR_AUTH,
+ } state;
+};
+
+/**
+ * Check if we actually use certificates for authentication
+ */
+static bool use_certs(private_isakmp_cert_post_t *this, message_t *message)
+{
+ enumerator_t *enumerator;
+ payload_t *payload;
+ bool use = FALSE;
+
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ if (payload->get_type(payload) == SECURITY_ASSOCIATION_V1)
+ {
+ sa_payload_t *sa_payload = (sa_payload_t*)payload;
+
+ switch (sa_payload->get_auth_method(sa_payload))
+ {
+ case AUTH_RSA:
+ case AUTH_ECDSA_256:
+ case AUTH_ECDSA_384:
+ case AUTH_ECDSA_521:
+ case AUTH_XAUTH_INIT_RSA:
+ case AUTH_XAUTH_RESP_RSA:
+ case AUTH_HYBRID_INIT_RSA:
+ case AUTH_HYBRID_RESP_RSA:
+ use = TRUE;
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return use;
+}
+
+/**
+ * Add certificates to message
+ */
+static void build_certs(private_isakmp_cert_post_t *this, message_t *message)
+{
+ peer_cfg_t *peer_cfg;
+
+ peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
+ if (!peer_cfg)
+ {
+ return;
+ }
+
+ switch (peer_cfg->get_cert_policy(peer_cfg))
+ {
+ case CERT_NEVER_SEND:
+ break;
+ case CERT_SEND_IF_ASKED:
+ if (!this->ike_sa->has_condition(this->ike_sa, COND_CERTREQ_SEEN))
+ {
+ break;
+ }
+ /* FALL */
+ case CERT_ALWAYS_SEND:
+ {
+ cert_payload_t *payload;
+ enumerator_t *enumerator;
+ certificate_t *cert;
+ auth_rule_t type;
+ auth_cfg_t *auth;
+
+ auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
+ cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
+ if (!cert)
+ {
+ break;
+ }
+ payload = cert_payload_create_from_cert(CERTIFICATE_V1, cert);
+ if (!payload)
+ {
+ break;
+ }
+ DBG1(DBG_IKE, "sending end entity cert \"%Y\"",
+ cert->get_subject(cert));
+ message->add_payload(message, (payload_t*)payload);
+
+ enumerator = auth->create_enumerator(auth);
+ while (enumerator->enumerate(enumerator, &type, &cert))
+ {
+ if (type == AUTH_RULE_IM_CERT)
+ {
+ payload = cert_payload_create_from_cert(CERTIFICATE_V1, cert);
+ if (payload)
+ {
+ DBG1(DBG_IKE, "sending issuer cert \"%Y\"",
+ cert->get_subject(cert));
+ message->add_payload(message, (payload_t*)payload);
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ }
+}
+
+METHOD(task_t, build_i, status_t,
+ private_isakmp_cert_post_t *this, message_t *message)
+{
+ switch (message->get_exchange_type(message))
+ {
+ case ID_PROT:
+ if (this->state == CR_AUTH)
+ {
+ build_certs(this, message);
+ return SUCCESS;
+ }
+ return NEED_MORE;
+ case AGGRESSIVE:
+ if (this->state == CR_AUTH)
+ {
+ build_certs(this, message);
+ return SUCCESS;
+ }
+ return NEED_MORE;
+ default:
+ return FAILED;
+ }
+}
+
+METHOD(task_t, process_r, status_t,
+ private_isakmp_cert_post_t *this, message_t *message)
+{
+ switch (message->get_exchange_type(message))
+ {
+ case ID_PROT:
+ {
+ switch (this->state)
+ {
+ case CR_SA:
+ if (!use_certs(this, message))
+ {
+ return SUCCESS;
+ }
+ return NEED_MORE;
+ case CR_KE:
+ return NEED_MORE;
+ case CR_AUTH:
+ return NEED_MORE;
+ default:
+ return FAILED;
+ }
+ }
+ case AGGRESSIVE:
+ {
+ switch (this->state)
+ {
+ case CR_SA:
+ if (!use_certs(this, message))
+ {
+ return SUCCESS;
+ }
+ return NEED_MORE;
+ case CR_AUTH:
+ return SUCCESS;
+ default:
+ return FAILED;
+ }
+ }
+ default:
+ return FAILED;
+ }
+}
+
+METHOD(task_t, build_r, status_t,
+ private_isakmp_cert_post_t *this, message_t *message)
+{
+ switch (message->get_exchange_type(message))
+ {
+ case ID_PROT:
+ switch (this->state)
+ {
+ case CR_SA:
+ this->state = CR_KE;
+ return NEED_MORE;
+ case CR_KE:
+ this->state = CR_AUTH;
+ return NEED_MORE;
+ case CR_AUTH:
+ build_certs(this, message);
+ return SUCCESS;
+ }
+ case AGGRESSIVE:
+ switch (this->state)
+ {
+ case CR_SA:
+ build_certs(this, message);
+ this->state = CR_AUTH;
+ return NEED_MORE;
+ case CR_AUTH:
+ return SUCCESS;
+ default:
+ return FAILED;
+ }
+ default:
+ return FAILED;
+ }
+}
+
+METHOD(task_t, process_i, status_t,
+ private_isakmp_cert_post_t *this, message_t *message)
+{
+ switch (message->get_exchange_type(message))
+ {
+ case ID_PROT:
+ {
+ switch (this->state)
+ {
+ case CR_SA:
+ if (!use_certs(this, message))
+ {
+ return SUCCESS;
+ }
+ this->state = CR_KE;
+ return NEED_MORE;
+ case CR_KE:
+ this->state = CR_AUTH;
+ return NEED_MORE;
+ case CR_AUTH:
+ return SUCCESS;
+ default:
+ return FAILED;
+ }
+ break;
+ }
+ case AGGRESSIVE:
+ {
+ if (this->state == CR_SA)
+ {
+ if (!use_certs(this, message))
+ {
+ return SUCCESS;
+ }
+ this->state = CR_AUTH;
+ return NEED_MORE;
+ }
+ return SUCCESS;
+ }
+ default:
+ return FAILED;
+ }
+}
+
+METHOD(task_t, get_type, task_type_t,
+ private_isakmp_cert_post_t *this)
+{
+ return TASK_ISAKMP_CERT_POST;
+}
+
+METHOD(task_t, migrate, void,
+ private_isakmp_cert_post_t *this, ike_sa_t *ike_sa)
+{
+ this->ike_sa = ike_sa;
+ this->state = CR_SA;
+}
+
+METHOD(task_t, destroy, void,
+ private_isakmp_cert_post_t *this)
+{
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+isakmp_cert_post_t *isakmp_cert_post_create(ike_sa_t *ike_sa, bool initiator)
+{
+ private_isakmp_cert_post_t *this;
+
+ INIT(this,
+ .public = {
+ .task = {
+ .get_type = _get_type,
+ .migrate = _migrate,
+ .destroy = _destroy,
+ },
+ },
+ .ike_sa = ike_sa,
+ .initiator = initiator,
+ .state = CR_SA,
+ );
+ if (initiator)
+ {
+ this->public.task.process = _process_i;
+ this->public.task.build = _build_i;
+ }
+ else
+ {
+ this->public.task.process = _process_r;
+ this->public.task.build = _build_r;
+ }
+ return &this->public;
+}
diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_cert_post.h b/src/libcharon/sa/ikev1/tasks/isakmp_cert_post.h
new file mode 100644
index 000000000..3a155cb68
--- /dev/null
+++ b/src/libcharon/sa/ikev1/tasks/isakmp_cert_post.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 isakmp_cert_post isakmp_cert_post
+ * @{ @ingroup tasks_v1
+ */
+
+#ifndef ISAKMP_CERT_POST_H_
+#define ISAKMP_CERT_POST_H_
+
+typedef struct isakmp_cert_post_t isakmp_cert_post_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/task.h>
+
+/**
+ * ISAKMP_CERT_POST, IKEv1 certificate processing after authentication.
+ */
+struct isakmp_cert_post_t {
+
+ /**
+ * Implements the task_t interface
+ */
+ task_t task;
+};
+
+/**
+ * Create a new isakmp_cert_post task.
+ *
+ * The initiator parameter means the original initiator, not the initiator
+ * of the certificate request.
+ *
+ * @param ike_sa IKE_SA this task works for
+ * @param initiator TRUE if task is the original initiator
+ * @return isakmp_cert_post task to handle by the task_manager
+ */
+isakmp_cert_post_t *isakmp_cert_post_create(ike_sa_t *ike_sa, bool initiator);
+
+#endif /** ISAKMP_CERT_POST_H_ @}*/
diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_cert_pre.c b/src/libcharon/sa/ikev1/tasks/isakmp_cert_pre.c
new file mode 100644
index 000000000..d48484f09
--- /dev/null
+++ b/src/libcharon/sa/ikev1/tasks/isakmp_cert_pre.c
@@ -0,0 +1,578 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 "isakmp_cert_pre.h"
+
+#include <daemon.h>
+#include <sa/ike_sa.h>
+#include <encoding/payloads/cert_payload.h>
+#include <encoding/payloads/sa_payload.h>
+#include <encoding/payloads/certreq_payload.h>
+#include <credentials/certificates/x509.h>
+
+
+typedef struct private_isakmp_cert_pre_t private_isakmp_cert_pre_t;
+
+/**
+ * Private members of a isakmp_cert_pre_t task.
+ */
+struct private_isakmp_cert_pre_t {
+
+ /**
+ * Public methods and task_t interface.
+ */
+ isakmp_cert_pre_t public;
+
+ /**
+ * Assigned IKE_SA.
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * Are we the initiator?
+ */
+ bool initiator;
+
+ /**
+ * Send certificate requests?
+ */
+ bool send_req;
+
+ /** next message we expect */
+ enum {
+ CR_SA,
+ CR_KE,
+ CR_AUTH,
+ } state;
+};
+
+/**
+ * Find the CA certificate for a given certreq payload
+ */
+static certificate_t* find_certificate(private_isakmp_cert_pre_t *this,
+ certreq_payload_t *certreq)
+{
+ identification_t *id;
+ certificate_t *cert;
+
+ if (certreq->get_cert_type(certreq) != CERT_X509)
+ {
+ DBG1(DBG_IKE, "%N CERTREQ not supported - ignored",
+ certificate_type_names, certreq->get_cert_type(certreq));
+ return NULL;
+ }
+ id = certreq->get_dn(certreq);
+ if (!id)
+ {
+ DBG1(DBG_IKE, "ignoring certificate request without data",
+ certificate_type_names, certreq->get_cert_type(certreq));
+ return NULL;
+ }
+ cert = lib->credmgr->get_cert(lib->credmgr, CERT_X509, KEY_ANY, id, TRUE);
+ if (cert)
+ {
+ DBG1(DBG_IKE, "received cert request for '%Y'",
+ cert->get_subject(cert));
+ }
+ else
+ {
+ DBG1(DBG_IKE, "received cert request for unknown ca '%Y'", id);
+ }
+ id->destroy(id);
+
+ return cert;
+}
+
+/**
+ * read certificate requests
+ */
+static void process_certreqs(private_isakmp_cert_pre_t *this, message_t *message)
+{
+ enumerator_t *enumerator;
+ payload_t *payload;
+ auth_cfg_t *auth;
+
+ auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
+
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ switch (payload->get_type(payload))
+ {
+ case CERTIFICATE_REQUEST_V1:
+ {
+ certificate_t *cert;
+
+ this->ike_sa->set_condition(this->ike_sa,
+ COND_CERTREQ_SEEN, TRUE);
+ cert = find_certificate(this, (certreq_payload_t*)payload);
+ if (cert)
+ {
+ auth->add(auth, AUTH_RULE_CA_CERT, cert);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Import receuved certificates
+ */
+static void process_certs(private_isakmp_cert_pre_t *this, message_t *message)
+{
+ enumerator_t *enumerator;
+ payload_t *payload;
+ auth_cfg_t *auth;
+ bool first = TRUE;
+
+ auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
+
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ if (payload->get_type(payload) == CERTIFICATE_V1)
+ {
+ cert_payload_t *cert_payload;
+ cert_encoding_t encoding;
+ certificate_t *cert;
+
+ cert_payload = (cert_payload_t*)payload;
+ encoding = cert_payload->get_cert_encoding(cert_payload);
+
+ switch (encoding)
+ {
+ case ENC_X509_SIGNATURE:
+ {
+ cert = cert_payload->get_cert(cert_payload);
+ if (cert)
+ {
+ if (first)
+ { /* the first is an end entity certificate */
+ DBG1(DBG_IKE, "received end entity cert \"%Y\"",
+ cert->get_subject(cert));
+ auth->add(auth, AUTH_HELPER_SUBJECT_CERT, cert);
+ first = FALSE;
+ }
+ else
+ {
+ DBG1(DBG_IKE, "received issuer cert \"%Y\"",
+ cert->get_subject(cert));
+ auth->add(auth, AUTH_HELPER_IM_CERT, cert);
+ }
+ }
+ break;
+ }
+ case ENC_CRL:
+ cert = cert_payload->get_cert(cert_payload);
+ if (cert)
+ {
+ DBG1(DBG_IKE, "received CRL \"%Y\"",
+ cert->get_subject(cert));
+ auth->add(auth, AUTH_HELPER_REVOCATION_CERT, cert);
+ }
+ break;
+ case ENC_PKCS7_WRAPPED_X509:
+ case ENC_PGP:
+ case ENC_DNS_SIGNED_KEY:
+ case ENC_KERBEROS_TOKEN:
+ case ENC_ARL:
+ case ENC_SPKI:
+ case ENC_X509_ATTRIBUTE:
+ case ENC_RAW_RSA_KEY:
+ case ENC_X509_HASH_AND_URL_BUNDLE:
+ case ENC_OCSP_CONTENT:
+ default:
+ DBG1(DBG_ENC, "certificate encoding %N not supported",
+ cert_encoding_names, encoding);
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Add the subject of a CA certificate a message
+ */
+static void add_certreq(private_isakmp_cert_pre_t *this, message_t *message,
+ certificate_t *cert)
+{
+ if (cert->get_type(cert) == CERT_X509)
+ {
+ x509_t *x509 = (x509_t*)cert;
+
+ if (x509->get_flags(x509) & X509_CA)
+ {
+ DBG1(DBG_IKE, "sending cert request for \"%Y\"",
+ cert->get_subject(cert));
+ message->add_payload(message, (payload_t*)
+ certreq_payload_create_dn(cert->get_subject(cert)));
+ }
+ }
+}
+
+/**
+ * Add auth_cfg's CA certificates to the certificate request
+ */
+static void add_certreqs(private_isakmp_cert_pre_t *this,
+ auth_cfg_t *auth, message_t *message)
+{
+ enumerator_t *enumerator;
+ auth_rule_t type;
+ void *value;
+
+ enumerator = auth->create_enumerator(auth);
+ while (enumerator->enumerate(enumerator, &type, &value))
+ {
+ switch (type)
+ {
+ case AUTH_RULE_CA_CERT:
+ add_certreq(this, message, (certificate_t*)value);
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Build certificate requests
+ */
+static void build_certreqs(private_isakmp_cert_pre_t *this, message_t *message)
+{
+ enumerator_t *enumerator;
+ ike_cfg_t *ike_cfg;
+ peer_cfg_t *peer_cfg;
+ certificate_t *cert;
+ auth_cfg_t *auth;
+
+ ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
+ if (!ike_cfg->send_certreq(ike_cfg))
+ {
+ return;
+ }
+ /* check if we require a specific CA for that peer */
+ peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
+ if (peer_cfg)
+ {
+ enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, FALSE);
+ if (enumerator->enumerate(enumerator, &auth))
+ {
+ add_certreqs(this, auth, message);
+ }
+ enumerator->destroy(enumerator);
+ }
+ if (!message->get_payload(message, CERTIFICATE_REQUEST_V1))
+ {
+ /* otherwise add all trusted CA certificates */
+ enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
+ CERT_ANY, KEY_ANY, NULL, TRUE);
+ while (enumerator->enumerate(enumerator, &cert))
+ {
+ add_certreq(this, message, cert);
+ }
+ enumerator->destroy(enumerator);
+ }
+}
+
+/**
+ * Check if we actually use certificates for authentication
+ */
+static bool use_certs(private_isakmp_cert_pre_t *this, message_t *message)
+{
+ enumerator_t *enumerator;
+ payload_t *payload;
+ bool use = FALSE;
+
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ if (payload->get_type(payload) == SECURITY_ASSOCIATION_V1)
+ {
+ sa_payload_t *sa_payload = (sa_payload_t*)payload;
+
+ switch (sa_payload->get_auth_method(sa_payload))
+ {
+ case AUTH_HYBRID_INIT_RSA:
+ case AUTH_HYBRID_RESP_RSA:
+ if (!this->initiator)
+ {
+ this->send_req = FALSE;
+ }
+ /* FALL */
+ case AUTH_RSA:
+ case AUTH_ECDSA_256:
+ case AUTH_ECDSA_384:
+ case AUTH_ECDSA_521:
+ case AUTH_XAUTH_INIT_RSA:
+ case AUTH_XAUTH_RESP_RSA:
+ use = TRUE;
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return use;
+}
+
+/**
+ * Check if we should send a certificate request
+ */
+static bool send_certreq(private_isakmp_cert_pre_t *this)
+{
+ enumerator_t *enumerator;
+ peer_cfg_t *peer_cfg;
+ auth_cfg_t *auth;
+ bool req = FALSE;
+ auth_class_t class;
+
+ peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
+ if (peer_cfg)
+ {
+ enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, FALSE);
+ if (enumerator->enumerate(enumerator, &auth))
+ {
+ class = (intptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS);
+ if (class == AUTH_CLASS_PUBKEY)
+ {
+ req = TRUE;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ return req;
+}
+
+METHOD(task_t, build_i, status_t,
+ private_isakmp_cert_pre_t *this, message_t *message)
+{
+ switch (message->get_exchange_type(message))
+ {
+ case ID_PROT:
+ if (this->state == CR_AUTH)
+ {
+ build_certreqs(this, message);
+ }
+ return NEED_MORE;
+ case AGGRESSIVE:
+ if (this->state == CR_SA)
+ {
+ if (send_certreq(this))
+ {
+ build_certreqs(this, message);
+ }
+ }
+ return NEED_MORE;
+ default:
+ return FAILED;
+ }
+}
+
+METHOD(task_t, process_r, status_t,
+ private_isakmp_cert_pre_t *this, message_t *message)
+{
+ switch (message->get_exchange_type(message))
+ {
+ case ID_PROT:
+ {
+ switch (this->state)
+ {
+ case CR_SA:
+ if (!use_certs(this, message))
+ {
+ return SUCCESS;
+ }
+ return NEED_MORE;
+ case CR_KE:
+ process_certreqs(this, message);
+ return NEED_MORE;
+ case CR_AUTH:
+ process_certreqs(this, message);
+ process_certs(this, message);
+ return SUCCESS;
+ default:
+ return FAILED;
+ }
+ }
+ case AGGRESSIVE:
+ {
+ switch (this->state)
+ {
+ case CR_SA:
+ if (!use_certs(this, message))
+ {
+ return SUCCESS;
+ }
+ process_certreqs(this, message);
+ return NEED_MORE;
+ case CR_AUTH:
+ process_certs(this, message);
+ return SUCCESS;
+ default:
+ return FAILED;
+ }
+ }
+ default:
+ return FAILED;
+ }
+}
+
+METHOD(task_t, build_r, status_t,
+ private_isakmp_cert_pre_t *this, message_t *message)
+{
+ switch (message->get_exchange_type(message))
+ {
+ case ID_PROT:
+ switch (this->state)
+ {
+ case CR_SA:
+ this->state = CR_KE;
+ return NEED_MORE;
+ case CR_KE:
+ if (this->send_req)
+ {
+ build_certreqs(this, message);
+ }
+ this->state = CR_AUTH;
+ return NEED_MORE;
+ case CR_AUTH:
+ return NEED_MORE;
+ default:
+ return FAILED;
+ }
+ case AGGRESSIVE:
+ switch (this->state)
+ {
+ case CR_SA:
+ if (this->send_req)
+ {
+ build_certreqs(this, message);
+ }
+ this->state = CR_AUTH;
+ return NEED_MORE;
+ case CR_AUTH:
+ return SUCCESS;
+ default:
+ return FAILED;
+ }
+ default:
+ return FAILED;
+ }
+}
+
+METHOD(task_t, process_i, status_t,
+ private_isakmp_cert_pre_t *this, message_t *message)
+{
+ switch (message->get_exchange_type(message))
+ {
+ case ID_PROT:
+ {
+ switch (this->state)
+ {
+ case CR_SA:
+ if (!use_certs(this, message))
+ {
+ return SUCCESS;
+ }
+ this->state = CR_KE;
+ return NEED_MORE;
+ case CR_KE:
+ process_certreqs(this, message);
+ this->state = CR_AUTH;
+ return NEED_MORE;
+ case CR_AUTH:
+ process_certs(this, message);
+ return SUCCESS;
+ default:
+ return FAILED;
+ }
+ break;
+ }
+ case AGGRESSIVE:
+ {
+ if (!use_certs(this, message))
+ {
+ return SUCCESS;
+ }
+ process_certreqs(this, message);
+ process_certs(this, message);
+ this->state = CR_AUTH;
+ return SUCCESS;
+ }
+ default:
+ return FAILED;
+ }
+}
+
+METHOD(task_t, get_type, task_type_t,
+ private_isakmp_cert_pre_t *this)
+{
+ return TASK_ISAKMP_CERT_PRE;
+}
+
+METHOD(task_t, migrate, void,
+ private_isakmp_cert_pre_t *this, ike_sa_t *ike_sa)
+{
+ this->ike_sa = ike_sa;
+ this->state = CR_SA;
+ this->send_req = TRUE;
+}
+
+METHOD(task_t, destroy, void,
+ private_isakmp_cert_pre_t *this)
+{
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+isakmp_cert_pre_t *isakmp_cert_pre_create(ike_sa_t *ike_sa, bool initiator)
+{
+ private_isakmp_cert_pre_t *this;
+
+ INIT(this,
+ .public = {
+ .task = {
+ .get_type = _get_type,
+ .migrate = _migrate,
+ .destroy = _destroy,
+ },
+ },
+ .ike_sa = ike_sa,
+ .initiator = initiator,
+ .state = CR_SA,
+ .send_req = TRUE,
+ );
+ if (initiator)
+ {
+ this->public.task.build = _build_i;
+ this->public.task.process = _process_i;
+ }
+ else
+ {
+ this->public.task.build = _build_r;
+ this->public.task.process = _process_r;
+ }
+ return &this->public;
+}
diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_cert_pre.h b/src/libcharon/sa/ikev1/tasks/isakmp_cert_pre.h
new file mode 100644
index 000000000..8e1a94b97
--- /dev/null
+++ b/src/libcharon/sa/ikev1/tasks/isakmp_cert_pre.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 isakmp_cert_pre isakmp_cert_pre
+ * @{ @ingroup tasks_v1
+ */
+
+#ifndef ISAKMP_CERT_PRE_H_
+#define ISAKMP_CERT_PRE_H_
+
+typedef struct isakmp_cert_pre_t isakmp_cert_pre_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/task.h>
+
+/**
+ * ISAKMP_CERT_PRE task, IKEv1 certificate processing before authentication.
+ */
+struct isakmp_cert_pre_t {
+
+ /**
+ * Implements the task_t interface
+ */
+ task_t task;
+};
+
+/**
+ * Create a new ISAKMP_CERT_PRE task.
+ *
+ * The initiator parameter means the original initiator, not the initiator
+ * of the certificate request.
+ *
+ * @param ike_sa IKE_SA this task works for
+ * @param initiator TRUE if task is the original initiator
+ * @return isakmp_cert_pre task to handle by the task_manager
+ */
+isakmp_cert_pre_t *isakmp_cert_pre_create(ike_sa_t *ike_sa, bool initiator);
+
+#endif /** ISAKMP_CERT_PRE_H_ @}*/
diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_delete.c b/src/libcharon/sa/ikev1/tasks/isakmp_delete.c
new file mode 100644
index 000000000..0640d13b1
--- /dev/null
+++ b/src/libcharon/sa/ikev1/tasks/isakmp_delete.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 "isakmp_delete.h"
+
+#include <daemon.h>
+#include <encoding/payloads/delete_payload.h>
+
+typedef struct private_isakmp_delete_t private_isakmp_delete_t;
+
+/**
+ * Private members of a isakmp_delete_t task.
+ */
+struct private_isakmp_delete_t {
+
+ /**
+ * Public methods and task_t interface.
+ */
+ isakmp_delete_t public;
+
+ /**
+ * Assigned IKE_SA.
+ */
+ ike_sa_t *ike_sa;
+};
+
+METHOD(task_t, build_i, status_t,
+ private_isakmp_delete_t *this, message_t *message)
+{
+ delete_payload_t *delete_payload;
+ ike_sa_id_t *id;
+
+ DBG0(DBG_IKE, "deleting IKE_SA %s[%d] between %H[%Y]...%H[%Y]",
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa),
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_my_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
+
+ delete_payload = delete_payload_create(DELETE_V1, PROTO_IKE);
+ id = this->ike_sa->get_id(this->ike_sa);
+ delete_payload->set_ike_spi(delete_payload, id->get_initiator_spi(id),
+ id->get_responder_spi(id));
+ message->add_payload(message, (payload_t*)delete_payload);
+
+ DBG1(DBG_IKE, "sending DELETE for IKE_SA %s[%d]",
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa));
+
+ this->ike_sa->set_state(this->ike_sa, IKE_DELETING);
+ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ return SUCCESS;
+}
+
+METHOD(task_t, process_i, status_t,
+ private_isakmp_delete_t *this, message_t *message)
+{
+ return FAILED;
+}
+
+METHOD(task_t, process_r, status_t,
+ private_isakmp_delete_t *this, message_t *message)
+{
+ DBG1(DBG_IKE, "received DELETE for IKE_SA %s[%d]",
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa));
+ DBG0(DBG_IKE, "deleting IKE_SA %s[%d] between %H[%Y]...%H[%Y]",
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa),
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_my_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
+
+ this->ike_sa->set_state(this->ike_sa, IKE_DELETING);
+ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ return DESTROY_ME;
+}
+
+METHOD(task_t, build_r, status_t,
+ private_isakmp_delete_t *this, message_t *message)
+{
+ return FAILED;
+}
+
+METHOD(task_t, get_type, task_type_t,
+ private_isakmp_delete_t *this)
+{
+ return TASK_ISAKMP_DELETE;
+}
+
+METHOD(task_t, migrate, void,
+ private_isakmp_delete_t *this, ike_sa_t *ike_sa)
+{
+ this->ike_sa = ike_sa;
+}
+
+METHOD(task_t, destroy, void,
+ private_isakmp_delete_t *this)
+{
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+isakmp_delete_t *isakmp_delete_create(ike_sa_t *ike_sa, bool initiator)
+{
+ private_isakmp_delete_t *this;
+
+ INIT(this,
+ .public = {
+ .task = {
+ .get_type = _get_type,
+ .migrate = _migrate,
+ .destroy = _destroy,
+ },
+ },
+ .ike_sa = ike_sa,
+ );
+
+ if (initiator)
+ {
+ this->public.task.build = _build_i;
+ this->public.task.process = _process_i;
+ }
+ else
+ {
+ this->public.task.build = _build_r;
+ this->public.task.process = _process_r;
+ }
+
+ return &this->public;
+}
diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_delete.h b/src/libcharon/sa/ikev1/tasks/isakmp_delete.h
new file mode 100644
index 000000000..1a7a62207
--- /dev/null
+++ b/src/libcharon/sa/ikev1/tasks/isakmp_delete.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 isakmp_delete isakmp_delete
+ * @{ @ingroup tasks_v1
+ */
+
+#ifndef ISAKMP_DELETE_H_
+#define ISAKMP_DELETE_H_
+
+typedef struct isakmp_delete_t isakmp_delete_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/task.h>
+
+/**
+ * Task of type ISAKMP_DELETE, delete an IKEv1 IKE_SA.
+ */
+struct isakmp_delete_t {
+
+ /**
+ * Implements the task_t interface
+ */
+ task_t task;
+};
+
+/**
+ * Create a new isakmp_delete task.
+ *
+ * @param ike_sa IKE_SA this task works for
+ * @param initiator TRUE if we initiate the delete
+ * @return isakmp_delete task to handle by the task_manager
+ */
+isakmp_delete_t *isakmp_delete_create(ike_sa_t *ike_sa, bool initiator);
+
+#endif /** ISAKMP_DELETE_H_ @}*/
diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_dpd.c b/src/libcharon/sa/ikev1/tasks/isakmp_dpd.c
new file mode 100644
index 000000000..a3395a043
--- /dev/null
+++ b/src/libcharon/sa/ikev1/tasks/isakmp_dpd.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 "isakmp_dpd.h"
+
+#include <daemon.h>
+#include <encoding/payloads/notify_payload.h>
+
+typedef struct private_isakmp_dpd_t private_isakmp_dpd_t;
+
+/**
+ * Private members of a isakmp_dpd_t task.
+ */
+struct private_isakmp_dpd_t {
+
+ /**
+ * Public methods and task_t interface.
+ */
+ isakmp_dpd_t public;
+
+ /**
+ * Sequence number.
+ */
+ u_int32_t seqnr;
+
+ /**
+ * DPD notify type
+ */
+ notify_type_t type;
+
+ /**
+ * IKE SA we are serving.
+ */
+ ike_sa_t *ike_sa;
+};
+
+METHOD(task_t, build, status_t,
+ private_isakmp_dpd_t *this, message_t *message)
+{
+ notify_payload_t *notify;
+ ike_sa_id_t *ike_sa_id;
+ u_int64_t spi_i, spi_r;
+ u_int32_t seqnr;
+ chunk_t spi;
+
+ notify = notify_payload_create_from_protocol_and_type(NOTIFY_V1,
+ PROTO_IKE, this->type);
+ seqnr = htonl(this->seqnr);
+ ike_sa_id = this->ike_sa->get_id(this->ike_sa);
+ spi_i = ike_sa_id->get_initiator_spi(ike_sa_id);
+ spi_r = ike_sa_id->get_responder_spi(ike_sa_id);
+ spi = chunk_cata("cc", chunk_from_thing(spi_i), chunk_from_thing(spi_r));
+
+ notify->set_spi_data(notify, spi);
+ notify->set_notification_data(notify, chunk_from_thing(seqnr));
+
+ message->add_payload(message, (payload_t*)notify);
+
+ return SUCCESS;
+}
+
+METHOD(task_t, process, status_t,
+ private_isakmp_dpd_t *this, message_t *message)
+{
+ /* done in task manager */
+ return FAILED;
+}
+
+METHOD(task_t, get_type, task_type_t,
+ private_isakmp_dpd_t *this)
+{
+ return TASK_ISAKMP_DPD;
+}
+
+METHOD(task_t, migrate, void,
+ private_isakmp_dpd_t *this, ike_sa_t *ike_sa)
+{
+ this->ike_sa = ike_sa;
+}
+
+METHOD(task_t, destroy, void,
+ private_isakmp_dpd_t *this)
+{
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+isakmp_dpd_t *isakmp_dpd_create(ike_sa_t *ike_sa, notify_type_t type,
+ u_int32_t seqnr)
+{
+ private_isakmp_dpd_t *this;
+
+ INIT(this,
+ .public = {
+ .task = {
+ .get_type = _get_type,
+ .build = _build,
+ .process = _process,
+ .migrate = _migrate,
+ .destroy = _destroy,
+ },
+ },
+ .ike_sa = ike_sa,
+ .seqnr = seqnr,
+ .type = type,
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_dpd.h b/src/libcharon/sa/ikev1/tasks/isakmp_dpd.h
new file mode 100644
index 000000000..06a0175eb
--- /dev/null
+++ b/src/libcharon/sa/ikev1/tasks/isakmp_dpd.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 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 isakmp_dpd isakmp_dpd
+ * @{ @ingroup tasks_v1
+ */
+
+#ifndef ISAKMP_DPD_H_
+#define ISAKMP_DPD_H_
+
+typedef struct isakmp_dpd_t isakmp_dpd_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/task.h>
+
+/**
+ * IKEv1 dead peer detection task.
+ */
+struct isakmp_dpd_t {
+
+ /**
+ * Implements the task_t interface
+ */
+ task_t task;
+};
+
+/**
+ * Create a new ISAKMP_DPD task.
+ *
+ * @param ike_sa associated IKE_SA
+ * @param type DPD notify to use, DPD_R_U_THERE | DPD_R_U_THERE_ACK
+ * @param seqnr DPD sequence number to use/expect
+ * @return ISAKMP_DPD task to handle by the task_manager
+ */
+isakmp_dpd_t *isakmp_dpd_create(ike_sa_t *ike_sa, notify_type_t type,
+ u_int32_t seqnr);
+
+#endif /** ISAKMP_DPD_H_ @}*/
diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_natd.c b/src/libcharon/sa/ikev1/tasks/isakmp_natd.c
new file mode 100644
index 000000000..50bf1612d
--- /dev/null
+++ b/src/libcharon/sa/ikev1/tasks/isakmp_natd.c
@@ -0,0 +1,456 @@
+/*
+ * Copyright (C) 2006-2011 Tobias Brunner,
+ * Copyright (C) 2006-2007 Martin Willi
+ * Copyright (C) 2006 Daniel Roethlisberger
+ * 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 "isakmp_natd.h"
+
+#include <string.h>
+
+#include <hydra.h>
+#include <daemon.h>
+#include <sa/ikev1/keymat_v1.h>
+#include <config/peer_cfg.h>
+#include <crypto/hashers/hasher.h>
+#include <encoding/payloads/hash_payload.h>
+
+typedef struct private_isakmp_natd_t private_isakmp_natd_t;
+
+/**
+ * Private members of a ike_natt_t task.
+ */
+struct private_isakmp_natd_t {
+
+ /**
+ * Public interface.
+ */
+ isakmp_natd_t public;
+
+ /**
+ * Assigned IKE_SA.
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * Are we the initiator?
+ */
+ bool initiator;
+
+ /**
+ * Keymat derivation (from SA)
+ */
+ keymat_v1_t *keymat;
+
+ /**
+ * Did we process any NAT detection payloads for a source address?
+ */
+ bool src_seen;
+
+ /**
+ * Did we process any NAT detection payloads for a destination address?
+ */
+ bool dst_seen;
+
+ /**
+ * Have we found a matching source address NAT hash?
+ */
+ bool src_matched;
+
+ /**
+ * Have we found a matching destination address NAT hash?
+ */
+ bool dst_matched;
+};
+
+/**
+ * Build NAT detection hash for a host.
+ */
+static chunk_t generate_natd_hash(private_isakmp_natd_t *this,
+ ike_sa_id_t *ike_sa_id, host_t *host)
+{
+ hasher_t *hasher;
+ chunk_t natd_chunk, natd_hash;
+ u_int64_t spi_i, spi_r;
+ u_int16_t port;
+
+ hasher = this->keymat->get_hasher(this->keymat);
+ if (!hasher)
+ {
+ DBG1(DBG_IKE, "no hasher available to build NAT-D payload");
+ return chunk_empty;
+ }
+
+ spi_i = ike_sa_id->get_initiator_spi(ike_sa_id);
+ spi_r = ike_sa_id->get_responder_spi(ike_sa_id);
+ port = htons(host->get_port(host));
+
+ /* natd_hash = HASH(CKY-I | CKY-R | IP | Port) */
+ natd_chunk = chunk_cata("cccc", chunk_from_thing(spi_i),
+ chunk_from_thing(spi_r), host->get_address(host),
+ chunk_from_thing(port));
+ if (!hasher->allocate_hash(hasher, natd_chunk, &natd_hash))
+ {
+ DBG1(DBG_IKE, "creating NAT-D payload hash failed");
+ return chunk_empty;
+ }
+ DBG3(DBG_IKE, "natd_chunk %B", &natd_chunk);
+ DBG3(DBG_IKE, "natd_hash %B", &natd_hash);
+
+ return natd_hash;
+}
+
+/**
+ * Build a faked NAT-D payload to enforce UDP encapsulation.
+ */
+static chunk_t generate_natd_hash_faked(private_isakmp_natd_t *this)
+{
+ hasher_t *hasher;
+ chunk_t chunk;
+ rng_t *rng;
+
+ hasher = this->keymat->get_hasher(this->keymat);
+ if (!hasher)
+ {
+ DBG1(DBG_IKE, "no hasher available to build NAT-D payload");
+ return chunk_empty;
+ }
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ if (!rng ||
+ !rng->allocate_bytes(rng, hasher->get_hash_size(hasher), &chunk))
+ {
+ DBG1(DBG_IKE, "unable to get random bytes for NAT-D fake");
+ DESTROY_IF(rng);
+ return chunk_empty;
+ }
+ rng->destroy(rng);
+ return chunk;
+}
+
+/**
+ * Build a NAT-D payload.
+ */
+static hash_payload_t *build_natd_payload(private_isakmp_natd_t *this, bool src,
+ host_t *host)
+{
+ hash_payload_t *payload;
+ ike_cfg_t *config;
+ chunk_t hash;
+
+ config = this->ike_sa->get_ike_cfg(this->ike_sa);
+ if (src && config->force_encap(config))
+ {
+ hash = generate_natd_hash_faked(this);
+ }
+ else
+ {
+ ike_sa_id_t *ike_sa_id = this->ike_sa->get_id(this->ike_sa);
+ hash = generate_natd_hash(this, ike_sa_id, host);
+ }
+ if (!hash.len)
+ {
+ return NULL;
+ }
+ payload = hash_payload_create(NAT_D_V1);
+ payload->set_hash(payload, hash);
+ chunk_free(&hash);
+ return payload;
+}
+
+/**
+ * Add NAT-D payloads to the message.
+ */
+static void add_natd_payloads(private_isakmp_natd_t *this, message_t *message)
+{
+ hash_payload_t *payload;
+ host_t *host;
+
+ /* destination has to be added first */
+ host = message->get_destination(message);
+ payload = build_natd_payload(this, FALSE, host);
+ if (payload)
+ {
+ message->add_payload(message, (payload_t*)payload);
+ }
+
+ /* source is added second, compared with IKEv2 we always know the source,
+ * as these payloads are added in the second Phase 1 exchange or the
+ * response to the first */
+ host = message->get_source(message);
+ payload = build_natd_payload(this, TRUE, host);
+ if (payload)
+ {
+ message->add_payload(message, (payload_t*)payload);
+ }
+}
+
+/**
+ * Read NAT-D payloads from message and evaluate them.
+ */
+static void process_payloads(private_isakmp_natd_t *this, message_t *message)
+{
+ enumerator_t *enumerator;
+ payload_t *payload;
+ hash_payload_t *hash_payload;
+ chunk_t hash, src_hash, dst_hash;
+ ike_sa_id_t *ike_sa_id;
+ host_t *me, *other;
+ ike_cfg_t *config;
+
+ /* precompute hashes for incoming NAT-D comparison */
+ ike_sa_id = message->get_ike_sa_id(message);
+ me = message->get_destination(message);
+ other = message->get_source(message);
+ dst_hash = generate_natd_hash(this, ike_sa_id, me);
+ src_hash = generate_natd_hash(this, ike_sa_id, other);
+
+ DBG3(DBG_IKE, "precalculated src_hash %B", &src_hash);
+ DBG3(DBG_IKE, "precalculated dst_hash %B", &dst_hash);
+
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ if (payload->get_type(payload) != NAT_D_V1)
+ {
+ continue;
+ }
+ hash_payload = (hash_payload_t*)payload;
+ if (!this->dst_seen)
+ { /* the first NAT-D payload contains the destination hash */
+ this->dst_seen = TRUE;
+ hash = hash_payload->get_hash(hash_payload);
+ DBG3(DBG_IKE, "received dst_hash %B", &hash);
+ if (chunk_equals(hash, dst_hash))
+ {
+ this->dst_matched = TRUE;
+ }
+ continue;
+ }
+ /* the other NAT-D payloads contain source hashes */
+ this->src_seen = TRUE;
+ if (!this->src_matched)
+ {
+ hash = hash_payload->get_hash(hash_payload);
+ DBG3(DBG_IKE, "received src_hash %B", &hash);
+ if (chunk_equals(hash, src_hash))
+ {
+ this->src_matched = TRUE;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ chunk_free(&src_hash);
+ chunk_free(&dst_hash);
+
+ if (this->src_seen && this->dst_seen)
+ {
+ this->ike_sa->set_condition(this->ike_sa, COND_NAT_HERE,
+ !this->dst_matched);
+ this->ike_sa->set_condition(this->ike_sa, COND_NAT_THERE,
+ !this->src_matched);
+ config = this->ike_sa->get_ike_cfg(this->ike_sa);
+ if (this->dst_matched && this->src_matched &&
+ config->force_encap(config))
+ {
+ this->ike_sa->set_condition(this->ike_sa, COND_NAT_FAKE, TRUE);
+ }
+ }
+}
+
+METHOD(task_t, build_i, status_t,
+ private_isakmp_natd_t *this, message_t *message)
+{
+ status_t result = NEED_MORE;
+
+ switch (message->get_exchange_type(message))
+ {
+ case AGGRESSIVE:
+ { /* add NAT-D payloads to the second request, already processed
+ * those by the responder contained in the first response */
+ result = SUCCESS;
+ /* fall */
+ }
+ case ID_PROT:
+ { /* add NAT-D payloads to the second request, need to process
+ * those by the responder contained in the second response */
+ if (message->get_payload(message, SECURITY_ASSOCIATION_V1))
+ { /* wait for the second exchange */
+ return NEED_MORE;
+ }
+ add_natd_payloads(this, message);
+ return result;
+ }
+ default:
+ break;
+ }
+ return SUCCESS;
+}
+
+METHOD(task_t, process_i, status_t,
+ private_isakmp_natd_t *this, message_t *message)
+{
+ status_t result = NEED_MORE;
+
+ if (!this->ike_sa->supports_extension(this->ike_sa, EXT_NATT))
+ { /* we didn't receive VIDs inidcating support for NAT-T */
+ return SUCCESS;
+ }
+
+ switch (message->get_exchange_type(message))
+ {
+ case ID_PROT:
+ { /* process NAT-D payloads in the second response, added them in the
+ * second request already, so we're done afterwards */
+ if (message->get_payload(message, SECURITY_ASSOCIATION_V1))
+ { /* wait for the second exchange */
+ return NEED_MORE;
+ }
+ result = SUCCESS;
+ /* fall */
+ }
+ case AGGRESSIVE:
+ { /* process NAT-D payloads in the first response, add them in the
+ * following second request */
+ process_payloads(this, message);
+
+ if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
+ {
+ this->ike_sa->float_ports(this->ike_sa);
+ }
+ return result;
+ }
+ default:
+ break;
+ }
+ return SUCCESS;
+}
+
+METHOD(task_t, process_r, status_t,
+ private_isakmp_natd_t *this, message_t *message)
+{
+ status_t result = NEED_MORE;
+
+ if (!this->ike_sa->supports_extension(this->ike_sa, EXT_NATT))
+ { /* we didn't receive VIDs indicating NAT-T support */
+ return SUCCESS;
+ }
+
+ switch (message->get_exchange_type(message))
+ {
+ case AGGRESSIVE:
+ { /* proccess NAT-D payloads in the second request, already added ours
+ * in the first response */
+ result = SUCCESS;
+ /* fall */
+ }
+ case ID_PROT:
+ { /* process NAT-D payloads in the second request, need to add ours
+ * to the second response */
+ if (message->get_payload(message, SECURITY_ASSOCIATION_V1))
+ { /* wait for the second exchange */
+ return NEED_MORE;
+ }
+ process_payloads(this, message);
+ return result;
+ }
+ default:
+ break;
+ }
+ return SUCCESS;
+}
+
+METHOD(task_t, build_r, status_t,
+ private_isakmp_natd_t *this, message_t *message)
+{
+ switch (message->get_exchange_type(message))
+ {
+ case ID_PROT:
+ { /* add NAT-D payloads to second response, already processed those
+ * contained in the second request */
+ if (message->get_payload(message, SECURITY_ASSOCIATION_V1))
+ { /* wait for the second exchange */
+ return NEED_MORE;
+ }
+ add_natd_payloads(this, message);
+ return SUCCESS;
+ }
+ case AGGRESSIVE:
+ { /* add NAT-D payloads to the first response, process those contained
+ * in the following second request */
+ add_natd_payloads(this, message);
+ return NEED_MORE;
+ }
+ default:
+ break;
+ }
+ return SUCCESS;
+}
+
+METHOD(task_t, get_type, task_type_t,
+ private_isakmp_natd_t *this)
+{
+ return TASK_ISAKMP_NATD;
+}
+
+METHOD(task_t, migrate, void,
+ private_isakmp_natd_t *this, ike_sa_t *ike_sa)
+{
+ this->ike_sa = ike_sa;
+ this->keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
+ this->src_seen = FALSE;
+ this->dst_seen = FALSE;
+ this->src_matched = FALSE;
+ this->dst_matched = FALSE;
+}
+
+METHOD(task_t, destroy, void,
+ private_isakmp_natd_t *this)
+{
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+isakmp_natd_t *isakmp_natd_create(ike_sa_t *ike_sa, bool initiator)
+{
+ private_isakmp_natd_t *this;
+
+ INIT(this,
+ .public = {
+ .task = {
+ .get_type = _get_type,
+ .migrate = _migrate,
+ .destroy = _destroy,
+ },
+ },
+ .ike_sa = ike_sa,
+ .keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa),
+ .initiator = initiator,
+ );
+
+ if (initiator)
+ {
+ this->public.task.build = _build_i;
+ this->public.task.process = _process_i;
+ }
+ else
+ {
+ this->public.task.build = _build_r;
+ this->public.task.process = _process_r;
+ }
+
+ return &this->public;
+}
diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_natd.h b/src/libcharon/sa/ikev1/tasks/isakmp_natd.h
new file mode 100644
index 000000000..63947fc73
--- /dev/null
+++ b/src/libcharon/sa/ikev1/tasks/isakmp_natd.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2011 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup isakmp_natd isakmp_natd
+ * @{ @ingroup tasks_v1
+ */
+
+#ifndef ISAKMP_NATD_H_
+#define ISAKMP_NATD_H_
+
+typedef struct isakmp_natd_t isakmp_natd_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/task.h>
+
+/**
+ * Task of type ISAKMP_NATD, detects NAT situation in IKEv1 Phase 1.
+ */
+struct isakmp_natd_t {
+
+ /**
+ * Implements the task_t interface
+ */
+ task_t task;
+};
+
+/**
+ * Create a new ISAKMP_NATD task.
+ *
+ * @param ike_sa IKE_SA this task works for
+ * @param initiator TRUE if task is the original initiator
+ * @return isakmp_natd task to handle by the task_manager
+ */
+isakmp_natd_t *isakmp_natd_create(ike_sa_t *ike_sa, bool initiator);
+
+#endif /** ISAKMP_NATD_H_ @}*/
diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c b/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c
new file mode 100644
index 000000000..4fd0ef39b
--- /dev/null
+++ b/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2009 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "isakmp_vendor.h"
+
+#include <daemon.h>
+#include <encoding/payloads/vendor_id_payload.h>
+
+typedef struct private_isakmp_vendor_t private_isakmp_vendor_t;
+
+/**
+ * Private data of an isakmp_vendor_t object.
+ */
+struct private_isakmp_vendor_t {
+
+ /**
+ * Public isakmp_vendor_t interface.
+ */
+ isakmp_vendor_t public;
+
+ /**
+ * Associated IKE_SA
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * Are we the inititator of this task
+ */
+ bool initiator;
+};
+
+/**
+ * IKEv1 Vendor ID database
+ */
+static struct {
+ /* Description */
+ char *desc;
+ /* extension flag negotiated with vendor ID, if any */
+ ike_extension_t extension;
+ /* send yourself? */
+ bool send;
+ /* length of vendor ID string */
+ int len;
+ /* vendor ID string */
+ char *id;
+} vendor_ids[] = {
+
+ /* strongSwan MD5("strongSwan") */
+ { "strongSwan", EXT_STRONGSWAN, FALSE, 16,
+ "\x88\x2f\xe5\x6d\x6f\xd2\x0d\xbc\x22\x51\x61\x3b\x2e\xbe\x5b\xeb"},
+
+ /* XAuth, MD5("draft-ietf-ipsra-isakmp-xauth-06.txt") */
+ { "XAuth", EXT_XAUTH, TRUE, 8,
+ "\x09\x00\x26\x89\xdf\xd6\xb7\x12"},
+
+ /* NAT-Traversal, MD5("RFC 3947") */
+ { "NAT-T (RFC 3947)", EXT_NATT, TRUE, 16,
+ "\x4a\x13\x1c\x81\x07\x03\x58\x45\x5c\x57\x28\xf2\x0e\x95\x45\x2f"},
+
+ /* Dead peer detection, RFC 3706 */
+ { "DPD", EXT_DPD, TRUE, 16,
+ "\xaf\xca\xd7\x13\x68\xa1\xf1\xc9\x6b\x86\x96\xfc\x77\x57\x01\x00"},
+
+ { "draft-stenberg-ipsec-nat-traversal-01", 0, FALSE, 16,
+ "\x27\xba\xb5\xdc\x01\xea\x07\x60\xea\x4e\x31\x90\xac\x27\xc0\xd0"},
+
+ { "draft-stenberg-ipsec-nat-traversal-02", 0, FALSE, 16,
+ "\x61\x05\xc4\x22\xe7\x68\x47\xe4\x3f\x96\x84\x80\x12\x92\xae\xcd"},
+
+ { "draft-ietf-ipsec-nat-t-ike", 0, FALSE, 16,
+ "\x4d\xf3\x79\x28\xe9\xfc\x4f\xd1\xb3\x26\x21\x70\xd5\x15\xc6\x62"},
+
+ { "draft-ietf-ipsec-nat-t-ike-00", 0, FALSE, 16,
+ "\x44\x85\x15\x2d\x18\xb6\xbb\xcd\x0b\xe8\xa8\x46\x95\x79\xdd\xcc"},
+
+ { "draft-ietf-ipsec-nat-t-ike-02", 0, FALSE, 16,
+ "\xcd\x60\x46\x43\x35\xdf\x21\xf8\x7c\xfd\xb2\xfc\x68\xb6\xa4\x48"},
+
+ { "draft-ietf-ipsec-nat-t-ike-02\\n", 0, FALSE, 16,
+ "\x90\xcb\x80\x91\x3e\xbb\x69\x6e\x08\x63\x81\xb5\xec\x42\x7b\x1f"},
+
+ { "draft-ietf-ipsec-nat-t-ike-03", 0, FALSE, 16,
+ "\x7d\x94\x19\xa6\x53\x10\xca\x6f\x2c\x17\x9d\x92\x15\x52\x9d\x56"},
+
+ { "draft-ietf-ipsec-nat-t-ike-04", 0, FALSE, 16,
+ "\x99\x09\xb6\x4e\xed\x93\x7c\x65\x73\xde\x52\xac\xe9\x52\xfa\x6b"},
+
+ { "draft-ietf-ipsec-nat-t-ike-05", 0, FALSE, 16,
+ "\x80\xd0\xbb\x3d\xef\x54\x56\x5e\xe8\x46\x45\xd4\xc8\x5c\xe3\xee"},
+
+ { "draft-ietf-ipsec-nat-t-ike-06", 0, FALSE, 16,
+ "\x4d\x1e\x0e\x13\x6d\xea\xfa\x34\xc4\xf3\xea\x9f\x02\xec\x72\x85"},
+
+ { "draft-ietf-ipsec-nat-t-ike-07", 0, FALSE, 16,
+ "\x43\x9b\x59\xf8\xba\x67\x6c\x4c\x77\x37\xae\x22\xea\xb8\xf5\x82"},
+
+ { "draft-ietf-ipsec-nat-t-ike-08", 0, FALSE, 16,
+ "\x8f\x8d\x83\x82\x6d\x24\x6b\x6f\xc7\xa8\xa6\xa4\x28\xc1\x1d\xe8"},
+
+ { "Cisco Unity", EXT_CISCO_UNITY, FALSE, 16,
+ "\x12\xf5\xf2\x8c\x45\x71\x68\xa9\x70\x2d\x9f\xe2\x74\xcc\x01\x00"},
+};
+
+METHOD(task_t, build, status_t,
+ private_isakmp_vendor_t *this, message_t *message)
+{
+ vendor_id_payload_t *vid_payload;
+ bool strongswan, cisco_unity;
+ int i;
+
+ strongswan = lib->settings->get_bool(lib->settings,
+ "%s.send_vendor_id", FALSE, charon->name);
+ cisco_unity = lib->settings->get_bool(lib->settings,
+ "%s.cisco_unity", FALSE, charon->name);
+ for (i = 0; i < countof(vendor_ids); i++)
+ {
+ if (vendor_ids[i].send ||
+ (vendor_ids[i].extension == EXT_STRONGSWAN && strongswan) ||
+ (vendor_ids[i].extension == EXT_CISCO_UNITY && cisco_unity))
+ {
+ vid_payload = vendor_id_payload_create_data(VENDOR_ID_V1,
+ chunk_clone(chunk_create(vendor_ids[i].id, vendor_ids[i].len)));
+ message->add_payload(message, &vid_payload->payload_interface);
+ }
+ }
+ return this->initiator ? NEED_MORE : SUCCESS;
+}
+
+METHOD(task_t, process, status_t,
+ private_isakmp_vendor_t *this, message_t *message)
+{
+ enumerator_t *enumerator;
+ payload_t *payload;
+ int i;
+
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ if (payload->get_type(payload) == VENDOR_ID_V1)
+ {
+ vendor_id_payload_t *vid;
+ bool found = FALSE;
+ chunk_t data;
+
+ vid = (vendor_id_payload_t*)payload;
+ data = vid->get_data(vid);
+
+ for (i = 0; i < countof(vendor_ids); i++)
+ {
+ if (chunk_equals(data, chunk_create(vendor_ids[i].id,
+ vendor_ids[i].len)))
+ {
+ DBG1(DBG_IKE, "received %s vendor ID", vendor_ids[i].desc);
+ if (vendor_ids[i].extension)
+ {
+ this->ike_sa->enable_extension(this->ike_sa,
+ vendor_ids[i].extension);
+ }
+ found = TRUE;
+ }
+ }
+ if (!found)
+ {
+ DBG1(DBG_ENC, "received unknown vendor ID: %#B", &data);
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return this->initiator ? SUCCESS : NEED_MORE;
+}
+
+METHOD(task_t, migrate, void,
+ private_isakmp_vendor_t *this, ike_sa_t *ike_sa)
+{
+ this->ike_sa = ike_sa;
+}
+
+METHOD(task_t, get_type, task_type_t,
+ private_isakmp_vendor_t *this)
+{
+ return TASK_ISAKMP_VENDOR;
+}
+
+METHOD(task_t, destroy, void,
+ private_isakmp_vendor_t *this)
+{
+ free(this);
+}
+
+/**
+ * See header
+ */
+isakmp_vendor_t *isakmp_vendor_create(ike_sa_t *ike_sa, bool initiator)
+{
+ private_isakmp_vendor_t *this;
+
+ INIT(this,
+ .public = {
+ .task = {
+ .build = _build,
+ .process = _process,
+ .migrate = _migrate,
+ .get_type = _get_type,
+ .destroy = _destroy,
+ },
+ },
+ .initiator = initiator,
+ .ike_sa = ike_sa,
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_vendor.h b/src/libcharon/sa/ikev1/tasks/isakmp_vendor.h
new file mode 100644
index 000000000..91891085b
--- /dev/null
+++ b/src/libcharon/sa/ikev1/tasks/isakmp_vendor.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 isakmp_vendor isakmp_vendor
+ * @{ @ingroup tasks_v1
+ */
+
+#ifndef ISAKMP_VENDOR_H_
+#define ISAKMP_VENDOR_H_
+
+typedef struct isakmp_vendor_t isakmp_vendor_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/task.h>
+
+/**
+ * Vendor ID processing task for IKEv1.
+ */
+struct isakmp_vendor_t {
+
+ /**
+ * Implements task interface.
+ */
+ task_t task;
+};
+
+/**
+ * Create a isakmp_vendor instance.
+ *
+ * @param ike_sa IKE_SA this task works for
+ * @param initiator TRUE if task is the original initiator
+ */
+isakmp_vendor_t *isakmp_vendor_create(ike_sa_t *ike_sa, bool initiator);
+
+#endif /** ISAKMP_VENDOR_H_ @}*/
diff --git a/src/libcharon/sa/ikev1/tasks/main_mode.c b/src/libcharon/sa/ikev1/tasks/main_mode.c
new file mode 100644
index 000000000..9ccf9abf5
--- /dev/null
+++ b/src/libcharon/sa/ikev1/tasks/main_mode.c
@@ -0,0 +1,735 @@
+/*
+ * Copyright (C) 2011-2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 "main_mode.h"
+
+#include <string.h>
+
+#include <daemon.h>
+#include <sa/ikev1/phase1.h>
+#include <encoding/payloads/sa_payload.h>
+#include <encoding/payloads/id_payload.h>
+#include <encoding/payloads/hash_payload.h>
+#include <sa/ikev1/tasks/xauth.h>
+#include <sa/ikev1/tasks/mode_config.h>
+#include <sa/ikev1/tasks/informational.h>
+#include <sa/ikev1/tasks/isakmp_delete.h>
+#include <processing/jobs/adopt_children_job.h>
+
+typedef struct private_main_mode_t private_main_mode_t;
+
+/**
+ * Private members of a main_mode_t task.
+ */
+struct private_main_mode_t {
+
+ /**
+ * Public methods and task_t interface.
+ */
+ main_mode_t public;
+
+ /**
+ * Assigned IKE_SA.
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * Are we the initiator?
+ */
+ bool initiator;
+
+ /**
+ * Common phase 1 helper class
+ */
+ phase1_t *ph1;
+
+ /**
+ * IKE config to establish
+ */
+ ike_cfg_t *ike_cfg;
+
+ /**
+ * Peer config to use
+ */
+ peer_cfg_t *peer_cfg;
+
+ /**
+ * selected IKE proposal
+ */
+ proposal_t *proposal;
+
+ /**
+ * Negotiated SA lifetime
+ */
+ u_int32_t lifetime;
+
+ /**
+ * Negotiated authentication method
+ */
+ auth_method_t method;
+
+ /** states of main mode */
+ enum {
+ MM_INIT,
+ MM_SA,
+ MM_KE,
+ MM_AUTH,
+ } state;
+};
+
+/**
+ * Set IKE_SA to established state
+ */
+static bool establish(private_main_mode_t *this)
+{
+ if (!charon->bus->authorize(charon->bus, TRUE))
+ {
+ DBG1(DBG_IKE, "final authorization hook forbids IKE_SA, cancelling");
+ return FALSE;
+ }
+
+ DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa),
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_my_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
+
+ this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
+ charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
+
+ return TRUE;
+}
+
+/**
+ * Check for notify errors, return TRUE if error found
+ */
+static bool has_notify_errors(private_main_mode_t *this, message_t *message)
+{
+ enumerator_t *enumerator;
+ payload_t *payload;
+ bool err = FALSE;
+
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ if (payload->get_type(payload) == NOTIFY_V1)
+ {
+ notify_payload_t *notify;
+ notify_type_t type;
+
+ notify = (notify_payload_t*)payload;
+ type = notify->get_notify_type(notify);
+ if (type < 16384)
+ {
+ DBG1(DBG_IKE, "received %N error notify",
+ notify_type_names, type);
+ err = TRUE;
+ }
+ else if (type == INITIAL_CONTACT_IKEV1)
+ {
+ if (!this->initiator && this->state == MM_AUTH)
+ {
+ /* If authenticated and received INITIAL_CONTACT,
+ * delete any existing IKE_SAs with that peer.
+ * The delete takes place when the SA is checked in due
+ * to other id not known until the 3rd message.*/
+ this->ike_sa->set_condition(this->ike_sa,
+ COND_INIT_CONTACT_SEEN, TRUE);
+ }
+ }
+ else
+ {
+ DBG1(DBG_IKE, "received %N notify", notify_type_names, type);
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return err;
+}
+
+/**
+ * Queue a task sending a notify in an INFORMATIONAL exchange
+ */
+static status_t send_notify(private_main_mode_t *this, notify_type_t type)
+{
+ notify_payload_t *notify;
+ ike_sa_id_t *ike_sa_id;
+ u_int64_t spi_i, spi_r;
+ chunk_t spi;
+
+ notify = notify_payload_create_from_protocol_and_type(NOTIFY_V1,
+ PROTO_IKE, type);
+ ike_sa_id = this->ike_sa->get_id(this->ike_sa);
+ spi_i = ike_sa_id->get_initiator_spi(ike_sa_id);
+ spi_r = ike_sa_id->get_responder_spi(ike_sa_id);
+ spi = chunk_cata("cc", chunk_from_thing(spi_i), chunk_from_thing(spi_r));
+ notify->set_spi_data(notify, spi);
+
+ this->ike_sa->queue_task(this->ike_sa,
+ (task_t*)informational_create(this->ike_sa, notify));
+ /* cancel all active/passive tasks in favour of informational */
+ this->ike_sa->flush_queue(this->ike_sa,
+ this->initiator ? TASK_QUEUE_ACTIVE : TASK_QUEUE_PASSIVE);
+ return ALREADY_DONE;
+}
+
+/**
+ * Queue a delete task if authentication failed as initiator
+ */
+static status_t send_delete(private_main_mode_t *this)
+{
+ this->ike_sa->queue_task(this->ike_sa,
+ (task_t*)isakmp_delete_create(this->ike_sa, TRUE));
+ /* cancel all active tasks in favour of informational */
+ this->ike_sa->flush_queue(this->ike_sa,
+ this->initiator ? TASK_QUEUE_ACTIVE : TASK_QUEUE_PASSIVE);
+ return ALREADY_DONE;
+}
+
+METHOD(task_t, build_i, status_t,
+ private_main_mode_t *this, message_t *message)
+{
+ switch (this->state)
+ {
+ case MM_INIT:
+ {
+ sa_payload_t *sa_payload;
+ linked_list_t *proposals;
+ packet_t *packet;
+
+ DBG0(DBG_IKE, "initiating Main Mode IKE_SA %s[%d] to %H",
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa));
+ this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
+
+ this->ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
+ this->peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
+ this->peer_cfg->get_ref(this->peer_cfg);
+
+ this->method = this->ph1->get_auth_method(this->ph1, this->peer_cfg);
+ if (this->method == AUTH_NONE)
+ {
+ DBG1(DBG_CFG, "configuration uses unsupported authentication");
+ return FAILED;
+ }
+ this->lifetime = this->peer_cfg->get_reauth_time(this->peer_cfg,
+ FALSE);
+ if (!this->lifetime)
+ { /* fall back to rekey time of no rekey time configured */
+ this->lifetime = this->peer_cfg->get_rekey_time(this->peer_cfg,
+ FALSE);
+ }
+ this->lifetime += this->peer_cfg->get_over_time(this->peer_cfg);
+ proposals = this->ike_cfg->get_proposals(this->ike_cfg);
+ sa_payload = sa_payload_create_from_proposals_v1(proposals,
+ this->lifetime, 0, this->method, MODE_NONE, FALSE, 0);
+ proposals->destroy_offset(proposals, offsetof(proposal_t, destroy));
+
+ message->add_payload(message, &sa_payload->payload_interface);
+
+ /* pregenerate message to store SA payload */
+ if (this->ike_sa->generate_message(this->ike_sa, message,
+ &packet) != SUCCESS)
+ {
+ DBG1(DBG_IKE, "pregenerating SA payload failed");
+ return FAILED;
+ }
+ packet->destroy(packet);
+ if (!this->ph1->save_sa_payload(this->ph1, message))
+ {
+ return FAILED;
+ }
+
+ this->state = MM_SA;
+ return NEED_MORE;
+ }
+ case MM_SA:
+ {
+ u_int16_t group;
+
+ if (!this->ph1->create_hasher(this->ph1))
+ {
+ return send_notify(this, NO_PROPOSAL_CHOSEN);
+ }
+ if (!this->proposal->get_algorithm(this->proposal,
+ DIFFIE_HELLMAN_GROUP, &group, NULL))
+ {
+ DBG1(DBG_IKE, "DH group selection failed");
+ return send_notify(this, NO_PROPOSAL_CHOSEN);
+ }
+ if (!this->ph1->create_dh(this->ph1, group))
+ {
+ DBG1(DBG_IKE, "negotiated DH group not supported");
+ return send_notify(this, INVALID_KEY_INFORMATION);
+ }
+ if (!this->ph1->add_nonce_ke(this->ph1, message))
+ {
+ return send_notify(this, INVALID_KEY_INFORMATION);
+ }
+ this->state = MM_KE;
+ return NEED_MORE;
+ }
+ case MM_KE:
+ {
+ id_payload_t *id_payload;
+ identification_t *id;
+
+ id = this->ph1->get_id(this->ph1, this->peer_cfg, TRUE);
+ if (!id)
+ {
+ DBG1(DBG_CFG, "own identity not known");
+ return send_notify(this, INVALID_ID_INFORMATION);
+ }
+ this->ike_sa->set_my_id(this->ike_sa, id->clone(id));
+ id_payload = id_payload_create_from_identification(ID_V1, id);
+ message->add_payload(message, &id_payload->payload_interface);
+
+ if (!this->ph1->build_auth(this->ph1, this->method, message,
+ id_payload->get_encoded(id_payload)))
+ {
+ return send_notify(this, AUTHENTICATION_FAILED);
+ }
+
+ this->state = MM_AUTH;
+ return NEED_MORE;
+ }
+ default:
+ return FAILED;
+ }
+}
+
+METHOD(task_t, process_r, status_t,
+ private_main_mode_t *this, message_t *message)
+{
+ switch (this->state)
+ {
+ case MM_INIT:
+ {
+ linked_list_t *list;
+ sa_payload_t *sa_payload;
+ bool private;
+
+ this->ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
+ DBG0(DBG_IKE, "%H is initiating a Main Mode IKE_SA",
+ message->get_source(message));
+ this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
+
+ this->ike_sa->update_hosts(this->ike_sa,
+ message->get_destination(message),
+ message->get_source(message), TRUE);
+
+ sa_payload = (sa_payload_t*)message->get_payload(message,
+ SECURITY_ASSOCIATION_V1);
+ if (!sa_payload)
+ {
+ DBG1(DBG_IKE, "SA payload missing");
+ return send_notify(this, INVALID_PAYLOAD_TYPE);
+ }
+ if (!this->ph1->save_sa_payload(this->ph1, message))
+ {
+ return send_notify(this, INVALID_PAYLOAD_TYPE);
+ }
+
+ list = sa_payload->get_proposals(sa_payload);
+ private = this->ike_sa->supports_extension(this->ike_sa,
+ EXT_STRONGSWAN);
+ this->proposal = this->ike_cfg->select_proposal(this->ike_cfg,
+ list, private);
+ list->destroy_offset(list, offsetof(proposal_t, destroy));
+ if (!this->proposal)
+ {
+ DBG1(DBG_IKE, "no proposal found");
+ return send_notify(this, NO_PROPOSAL_CHOSEN);
+ }
+ this->ike_sa->set_proposal(this->ike_sa, this->proposal);
+
+ this->method = sa_payload->get_auth_method(sa_payload);
+ this->lifetime = sa_payload->get_lifetime(sa_payload);
+
+ this->state = MM_SA;
+ return NEED_MORE;
+ }
+ case MM_SA:
+ {
+ u_int16_t group;
+
+ if (!this->ph1->create_hasher(this->ph1))
+ {
+ return send_notify(this, INVALID_KEY_INFORMATION);
+ }
+ if (!this->proposal->get_algorithm(this->proposal,
+ DIFFIE_HELLMAN_GROUP, &group, NULL))
+ {
+ DBG1(DBG_IKE, "DH group selection failed");
+ return send_notify(this, INVALID_KEY_INFORMATION);
+ }
+ if (!this->ph1->create_dh(this->ph1, group))
+ {
+ DBG1(DBG_IKE, "negotiated DH group not supported");
+ return send_notify(this, INVALID_KEY_INFORMATION);
+ }
+ if (!this->ph1->get_nonce_ke(this->ph1, message))
+ {
+ return send_notify(this, INVALID_PAYLOAD_TYPE);
+ }
+ this->state = MM_KE;
+ return NEED_MORE;
+ }
+ case MM_KE:
+ {
+ id_payload_t *id_payload;
+ identification_t *id;
+
+ id_payload = (id_payload_t*)message->get_payload(message, ID_V1);
+ if (!id_payload)
+ {
+ DBG1(DBG_IKE, "IDii payload missing");
+ return send_notify(this, INVALID_PAYLOAD_TYPE);
+ }
+ id = id_payload->get_identification(id_payload);
+ this->ike_sa->set_other_id(this->ike_sa, id);
+
+ while (TRUE)
+ {
+ DESTROY_IF(this->peer_cfg);
+ this->peer_cfg = this->ph1->select_config(this->ph1,
+ this->method, FALSE, id);
+ if (!this->peer_cfg)
+ {
+ return send_notify(this, AUTHENTICATION_FAILED);
+ }
+ this->ike_sa->set_peer_cfg(this->ike_sa, this->peer_cfg);
+
+ if (this->ph1->verify_auth(this->ph1, this->method, message,
+ id_payload->get_encoded(id_payload)))
+ {
+ break;
+ }
+ }
+
+ if (!charon->bus->authorize(charon->bus, FALSE))
+ {
+ DBG1(DBG_IKE, "Main Mode authorization hook forbids IKE_SA, "
+ "cancelling");
+ return send_notify(this, AUTHENTICATION_FAILED);
+ }
+
+ this->state = MM_AUTH;
+ if (has_notify_errors(this, message))
+ {
+ return FAILED;
+ }
+ return NEED_MORE;
+ }
+ default:
+ return FAILED;
+ }
+}
+
+METHOD(task_t, build_r, status_t,
+ private_main_mode_t *this, message_t *message)
+{
+ switch (this->state)
+ {
+ case MM_SA:
+ {
+ sa_payload_t *sa_payload;
+
+ sa_payload = sa_payload_create_from_proposal_v1(this->proposal,
+ this->lifetime, 0, this->method, MODE_NONE, FALSE, 0);
+ message->add_payload(message, &sa_payload->payload_interface);
+
+ return NEED_MORE;
+ }
+ case MM_KE:
+ {
+ if (!this->ph1->add_nonce_ke(this->ph1, message))
+ {
+ return send_notify(this, INVALID_KEY_INFORMATION);
+ }
+ if (!this->ph1->derive_keys(this->ph1, this->peer_cfg, this->method))
+ {
+ return send_notify(this, INVALID_KEY_INFORMATION);
+ }
+ return NEED_MORE;
+ }
+ case MM_AUTH:
+ {
+ id_payload_t *id_payload;
+ identification_t *id;
+
+ id = this->ph1->get_id(this->ph1, this->peer_cfg, TRUE);
+ if (!id)
+ {
+ DBG1(DBG_CFG, "own identity not known");
+ return send_notify(this, INVALID_ID_INFORMATION);
+ }
+ this->ike_sa->set_my_id(this->ike_sa, id->clone(id));
+
+ id_payload = id_payload_create_from_identification(ID_V1, id);
+ message->add_payload(message, &id_payload->payload_interface);
+
+ if (!this->ph1->build_auth(this->ph1, this->method, message,
+ id_payload->get_encoded(id_payload)))
+ {
+ return send_notify(this, AUTHENTICATION_FAILED);
+ }
+
+ switch (this->method)
+ {
+ case AUTH_XAUTH_INIT_PSK:
+ case AUTH_XAUTH_INIT_RSA:
+ case AUTH_HYBRID_INIT_RSA:
+ this->ike_sa->queue_task(this->ike_sa,
+ (task_t*)xauth_create(this->ike_sa, TRUE));
+ return SUCCESS;
+ case AUTH_XAUTH_RESP_PSK:
+ case AUTH_XAUTH_RESP_RSA:
+ case AUTH_HYBRID_RESP_RSA:
+ /* wait for XAUTH request */
+ break;
+ default:
+ if (charon->ike_sa_manager->check_uniqueness(
+ charon->ike_sa_manager, this->ike_sa, FALSE))
+ {
+ DBG1(DBG_IKE, "cancelling Main Mode due to uniqueness "
+ "policy");
+ return send_notify(this, AUTHENTICATION_FAILED);
+ }
+ if (!establish(this))
+ {
+ return send_notify(this, AUTHENTICATION_FAILED);
+ }
+ lib->processor->queue_job(lib->processor, (job_t*)
+ adopt_children_job_create(
+ this->ike_sa->get_id(this->ike_sa)));
+ break;
+ }
+ if (!this->ph1->has_pool(this->ph1, this->peer_cfg) &&
+ this->ph1->has_virtual_ip(this->ph1, this->peer_cfg))
+ {
+ this->ike_sa->queue_task(this->ike_sa,
+ (task_t*)mode_config_create(this->ike_sa, TRUE));
+ }
+ return SUCCESS;
+ }
+ default:
+ return FAILED;
+ }
+}
+
+METHOD(task_t, process_i, status_t,
+ private_main_mode_t *this, message_t *message)
+{
+ switch (this->state)
+ {
+ case MM_SA:
+ {
+ linked_list_t *list;
+ sa_payload_t *sa_payload;
+ auth_method_t method;
+ u_int32_t lifetime;
+ bool private;
+
+ sa_payload = (sa_payload_t*)message->get_payload(message,
+ SECURITY_ASSOCIATION_V1);
+ if (!sa_payload)
+ {
+ DBG1(DBG_IKE, "SA payload missing");
+ return send_notify(this, INVALID_PAYLOAD_TYPE);
+ }
+ list = sa_payload->get_proposals(sa_payload);
+ private = this->ike_sa->supports_extension(this->ike_sa,
+ EXT_STRONGSWAN);
+ this->proposal = this->ike_cfg->select_proposal(this->ike_cfg,
+ list, private);
+ list->destroy_offset(list, offsetof(proposal_t, destroy));
+ if (!this->proposal)
+ {
+ DBG1(DBG_IKE, "no proposal found");
+ return send_notify(this, NO_PROPOSAL_CHOSEN);
+ }
+ this->ike_sa->set_proposal(this->ike_sa, this->proposal);
+
+ lifetime = sa_payload->get_lifetime(sa_payload);
+ if (lifetime != this->lifetime)
+ {
+ DBG1(DBG_IKE, "received lifetime %us does not match configured "
+ "lifetime %us", lifetime, this->lifetime);
+ }
+ this->lifetime = lifetime;
+ method = sa_payload->get_auth_method(sa_payload);
+ if (method != this->method)
+ {
+ DBG1(DBG_IKE, "received %N authentication, but configured %N, "
+ "continue with configured", auth_method_names, method,
+ auth_method_names, this->method);
+ }
+ return NEED_MORE;
+ }
+ case MM_KE:
+ {
+ if (!this->ph1->get_nonce_ke(this->ph1, message))
+ {
+ return send_notify(this, INVALID_PAYLOAD_TYPE);
+ }
+ if (!this->ph1->derive_keys(this->ph1, this->peer_cfg, this->method))
+ {
+ return send_notify(this, INVALID_KEY_INFORMATION);
+ }
+ return NEED_MORE;
+ }
+ case MM_AUTH:
+ {
+ id_payload_t *id_payload;
+ identification_t *id, *cid;
+
+ id_payload = (id_payload_t*)message->get_payload(message, ID_V1);
+ if (!id_payload)
+ {
+ DBG1(DBG_IKE, "IDir payload missing");
+ return send_delete(this);
+ }
+ id = id_payload->get_identification(id_payload);
+ cid = this->ph1->get_id(this->ph1, this->peer_cfg, FALSE);
+ if (cid && !id->matches(id, cid))
+ {
+ DBG1(DBG_IKE, "IDir '%Y' does not match to '%Y'", id, cid);
+ id->destroy(id);
+ return send_delete(this);
+ }
+ this->ike_sa->set_other_id(this->ike_sa, id);
+
+ if (!this->ph1->verify_auth(this->ph1, this->method, message,
+ id_payload->get_encoded(id_payload)))
+ {
+ return send_delete(this);
+ }
+ if (!charon->bus->authorize(charon->bus, FALSE))
+ {
+ DBG1(DBG_IKE, "Main Mode authorization hook forbids IKE_SA, "
+ "cancelling");
+ return send_delete(this);
+ }
+
+ switch (this->method)
+ {
+ case AUTH_XAUTH_INIT_PSK:
+ case AUTH_XAUTH_INIT_RSA:
+ case AUTH_HYBRID_INIT_RSA:
+ /* wait for XAUTH request */
+ break;
+ case AUTH_XAUTH_RESP_PSK:
+ case AUTH_XAUTH_RESP_RSA:
+ case AUTH_HYBRID_RESP_RSA:
+ this->ike_sa->queue_task(this->ike_sa,
+ (task_t*)xauth_create(this->ike_sa, TRUE));
+ return SUCCESS;
+ default:
+ if (charon->ike_sa_manager->check_uniqueness(
+ charon->ike_sa_manager, this->ike_sa, FALSE))
+ {
+ DBG1(DBG_IKE, "cancelling Main Mode due to uniqueness "
+ "policy");
+ return send_delete(this);
+ }
+ if (!establish(this))
+ {
+ return send_delete(this);
+ }
+ break;
+ }
+ if (this->ph1->has_virtual_ip(this->ph1, this->peer_cfg))
+ {
+ this->ike_sa->queue_task(this->ike_sa,
+ (task_t*)mode_config_create(this->ike_sa, TRUE));
+ }
+ return SUCCESS;
+ }
+ default:
+ return FAILED;
+ }
+}
+
+METHOD(task_t, get_type, task_type_t,
+ private_main_mode_t *this)
+{
+ return TASK_MAIN_MODE;
+}
+
+METHOD(task_t, migrate, void,
+ private_main_mode_t *this, ike_sa_t *ike_sa)
+{
+ DESTROY_IF(this->peer_cfg);
+ DESTROY_IF(this->proposal);
+ this->ph1->destroy(this->ph1);
+
+ this->ike_sa = ike_sa;
+ this->state = MM_INIT;
+ this->peer_cfg = NULL;
+ this->proposal = NULL;
+ this->ph1 = phase1_create(ike_sa, this->initiator);
+}
+
+METHOD(task_t, destroy, void,
+ private_main_mode_t *this)
+{
+ DESTROY_IF(this->peer_cfg);
+ DESTROY_IF(this->proposal);
+ this->ph1->destroy(this->ph1);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+main_mode_t *main_mode_create(ike_sa_t *ike_sa, bool initiator)
+{
+ private_main_mode_t *this;
+
+ INIT(this,
+ .public = {
+ .task = {
+ .get_type = _get_type,
+ .migrate = _migrate,
+ .destroy = _destroy,
+ },
+ },
+ .ike_sa = ike_sa,
+ .ph1 = phase1_create(ike_sa, initiator),
+ .initiator = initiator,
+ .state = MM_INIT,
+ );
+
+ if (initiator)
+ {
+ this->public.task.build = _build_i;
+ this->public.task.process = _process_i;
+ }
+ else
+ {
+ this->public.task.build = _build_r;
+ this->public.task.process = _process_r;
+ }
+
+ return &this->public;
+}
diff --git a/src/libcharon/sa/ikev1/tasks/main_mode.h b/src/libcharon/sa/ikev1/tasks/main_mode.h
new file mode 100644
index 000000000..141701f75
--- /dev/null
+++ b/src/libcharon/sa/ikev1/tasks/main_mode.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 main_mode main_mode
+ * @{ @ingroup tasks_v1
+ */
+
+#ifndef MAIN_MODE_H_
+#define MAIN_MODE_H_
+
+typedef struct main_mode_t main_mode_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/task.h>
+
+/**
+ * IKEv1 main mode, establishes a mainmode including authentication.
+ */
+struct main_mode_t {
+
+ /**
+ * Implements the task_t interface
+ */
+ task_t task;
+};
+
+/**
+ * Create a new main_mode task.
+ *
+ * @param ike_sa IKE_SA this task works for
+ * @param initiator TRUE if task initiated locally
+ * @return task to handle by the task_manager
+ */
+main_mode_t *main_mode_create(ike_sa_t *ike_sa, bool initiator);
+
+#endif /** MAIN_MODE_H_ @}*/
diff --git a/src/libcharon/sa/ikev1/tasks/mode_config.c b/src/libcharon/sa/ikev1/tasks/mode_config.c
new file mode 100644
index 000000000..ce897727a
--- /dev/null
+++ b/src/libcharon/sa/ikev1/tasks/mode_config.c
@@ -0,0 +1,459 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 "mode_config.h"
+
+#include <daemon.h>
+#include <hydra.h>
+#include <encoding/payloads/cp_payload.h>
+
+typedef struct private_mode_config_t private_mode_config_t;
+
+/**
+ * Private members of a mode_config_t task.
+ */
+struct private_mode_config_t {
+
+ /**
+ * Public methods and task_t interface.
+ */
+ mode_config_t public;
+
+ /**
+ * Assigned IKE_SA.
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * Are we the initiator?
+ */
+ bool initiator;
+
+ /**
+ * Received list of virtual IPs, host_t*
+ */
+ linked_list_t *vips;
+
+ /**
+ * list of attributes requested and its handler, entry_t
+ */
+ linked_list_t *requested;
+
+ /**
+ * Identifier to include in response
+ */
+ u_int16_t identifier;
+};
+
+/**
+ * Entry for a requested attribute and the requesting handler
+ */
+typedef struct {
+ /** attribute requested */
+ configuration_attribute_type_t type;
+ /** handler requesting this attribute */
+ attribute_handler_t *handler;
+} entry_t;
+
+/**
+ * build INTERNAL_IPV4/6_ADDRESS attribute from virtual ip
+ */
+static configuration_attribute_t *build_vip(host_t *vip)
+{
+ configuration_attribute_type_t type;
+ chunk_t chunk, prefix;
+
+ if (vip->get_family(vip) == AF_INET)
+ {
+ type = INTERNAL_IP4_ADDRESS;
+ if (vip->is_anyaddr(vip))
+ {
+ chunk = chunk_empty;
+ }
+ else
+ {
+ chunk = vip->get_address(vip);
+ }
+ }
+ else
+ {
+ type = INTERNAL_IP6_ADDRESS;
+ if (vip->is_anyaddr(vip))
+ {
+ chunk = chunk_empty;
+ }
+ else
+ {
+ prefix = chunk_alloca(1);
+ *prefix.ptr = 64;
+ chunk = vip->get_address(vip);
+ chunk = chunk_cata("cc", chunk, prefix);
+ }
+ }
+ return configuration_attribute_create_chunk(CONFIGURATION_ATTRIBUTE_V1,
+ type, chunk);
+}
+
+/**
+ * Handle a received attribute as initiator
+ */
+static void handle_attribute(private_mode_config_t *this,
+ configuration_attribute_t *ca)
+{
+ attribute_handler_t *handler = NULL;
+ enumerator_t *enumerator;
+ entry_t *entry;
+
+ /* find the handler which requested this attribute */
+ enumerator = this->requested->create_enumerator(this->requested);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->type == ca->get_type(ca))
+ {
+ handler = entry->handler;
+ this->requested->remove_at(this->requested, enumerator);
+ free(entry);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ /* and pass it to the handle function */
+ handler = hydra->attributes->handle(hydra->attributes,
+ this->ike_sa->get_other_id(this->ike_sa), handler,
+ ca->get_type(ca), ca->get_chunk(ca));
+ if (handler)
+ {
+ this->ike_sa->add_configuration_attribute(this->ike_sa,
+ handler, ca->get_type(ca), ca->get_chunk(ca));
+ }
+}
+
+/**
+ * process a single configuration attribute
+ */
+static void process_attribute(private_mode_config_t *this,
+ configuration_attribute_t *ca)
+{
+ host_t *ip;
+ chunk_t addr;
+ int family = AF_INET6;
+
+ switch (ca->get_type(ca))
+ {
+ case INTERNAL_IP4_ADDRESS:
+ family = AF_INET;
+ /* fall */
+ case INTERNAL_IP6_ADDRESS:
+ {
+ addr = ca->get_chunk(ca);
+ if (addr.len == 0)
+ {
+ ip = host_create_any(family);
+ }
+ else
+ {
+ /* skip prefix byte in IPv6 payload*/
+ if (family == AF_INET6)
+ {
+ addr.len--;
+ }
+ ip = host_create_from_chunk(family, addr, 0);
+ }
+ if (ip)
+ {
+ this->vips->insert_last(this->vips, ip);
+ }
+ break;
+ }
+ default:
+ {
+ if (this->initiator)
+ {
+ handle_attribute(this, ca);
+ }
+ }
+ }
+}
+
+/**
+ * Scan for configuration payloads and attributes
+ */
+static void process_payloads(private_mode_config_t *this, message_t *message)
+{
+ enumerator_t *enumerator, *attributes;
+ payload_t *payload;
+
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ if (payload->get_type(payload) == CONFIGURATION_V1)
+ {
+ cp_payload_t *cp = (cp_payload_t*)payload;
+ configuration_attribute_t *ca;
+
+ switch (cp->get_type(cp))
+ {
+ case CFG_REQUEST:
+ this->identifier = cp->get_identifier(cp);
+ /* FALL */
+ case CFG_REPLY:
+ attributes = cp->create_attribute_enumerator(cp);
+ while (attributes->enumerate(attributes, &ca))
+ {
+ DBG2(DBG_IKE, "processing %N attribute",
+ configuration_attribute_type_names, ca->get_type(ca));
+ process_attribute(this, ca);
+ }
+ attributes->destroy(attributes);
+ break;
+ default:
+ DBG1(DBG_IKE, "ignoring %N config payload",
+ config_type_names, cp->get_type(cp));
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+METHOD(task_t, build_i, status_t,
+ private_mode_config_t *this, message_t *message)
+{
+ cp_payload_t *cp;
+ enumerator_t *enumerator;
+ attribute_handler_t *handler;
+ peer_cfg_t *config;
+ configuration_attribute_type_t type;
+ chunk_t data;
+ linked_list_t *vips;
+ host_t *host;
+
+ cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REQUEST);
+
+ vips = linked_list_create();
+
+ /* reuse virtual IP if we already have one */
+ enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa, TRUE);
+ while (enumerator->enumerate(enumerator, &host))
+ {
+ vips->insert_last(vips, host);
+ }
+ enumerator->destroy(enumerator);
+
+ if (vips->get_count(vips) == 0)
+ {
+ config = this->ike_sa->get_peer_cfg(this->ike_sa);
+ enumerator = config->create_virtual_ip_enumerator(config);
+ while (enumerator->enumerate(enumerator, &host))
+ {
+ vips->insert_last(vips, host);
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ if (vips->get_count(vips))
+ {
+ enumerator = vips->create_enumerator(vips);
+ while (enumerator->enumerate(enumerator, &host))
+ {
+ cp->add_attribute(cp, build_vip(host));
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ enumerator = hydra->attributes->create_initiator_enumerator(
+ hydra->attributes,
+ this->ike_sa->get_other_id(this->ike_sa), vips);
+ while (enumerator->enumerate(enumerator, &handler, &type, &data))
+ {
+ entry_t *entry;
+
+ DBG2(DBG_IKE, "building %N attribute",
+ configuration_attribute_type_names, type);
+ cp->add_attribute(cp,
+ configuration_attribute_create_chunk(CONFIGURATION_ATTRIBUTE_V1,
+ type, data));
+ INIT(entry,
+ .type = type,
+ .handler = handler,
+ );
+ this->requested->insert_last(this->requested, entry);
+ }
+ enumerator->destroy(enumerator);
+
+ vips->destroy(vips);
+
+ message->add_payload(message, (payload_t*)cp);
+
+ return NEED_MORE;
+}
+
+METHOD(task_t, process_r, status_t,
+ private_mode_config_t *this, message_t *message)
+{
+ process_payloads(this, message);
+ return NEED_MORE;
+}
+
+METHOD(task_t, build_r, status_t,
+ private_mode_config_t *this, message_t *message)
+{
+ enumerator_t *enumerator;
+ configuration_attribute_type_t type;
+ chunk_t value;
+ cp_payload_t *cp;
+ peer_cfg_t *config;
+ identification_t *id;
+ linked_list_t *vips, *pools;
+ host_t *requested;
+
+ cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REPLY);
+
+ id = this->ike_sa->get_other_eap_id(this->ike_sa);
+ config = this->ike_sa->get_peer_cfg(this->ike_sa);
+ vips = linked_list_create();
+ pools = linked_list_create_from_enumerator(
+ config->create_pool_enumerator(config));
+
+ this->ike_sa->clear_virtual_ips(this->ike_sa, FALSE);
+
+ enumerator = this->vips->create_enumerator(this->vips);
+ while (enumerator->enumerate(enumerator, &requested))
+ {
+ host_t *found = NULL;
+
+ /* query all pools until we get an address */
+ DBG1(DBG_IKE, "peer requested virtual IP %H", requested);
+
+ found = hydra->attributes->acquire_address(hydra->attributes,
+ pools, id, requested);
+ if (found)
+ {
+ DBG1(DBG_IKE, "assigning virtual IP %H to peer '%Y'", found, id);
+ this->ike_sa->add_virtual_ip(this->ike_sa, FALSE, found);
+ cp->add_attribute(cp, build_vip(found));
+ vips->insert_last(vips, found);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "no virtual IP found for %H requested by '%Y'",
+ requested, id);
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ /* query registered providers for additional attributes to include */
+ enumerator = hydra->attributes->create_responder_enumerator(
+ hydra->attributes, pools, id, vips);
+ while (enumerator->enumerate(enumerator, &type, &value))
+ {
+ DBG2(DBG_IKE, "building %N attribute",
+ configuration_attribute_type_names, type);
+ cp->add_attribute(cp,
+ configuration_attribute_create_chunk(CONFIGURATION_ATTRIBUTE_V1,
+ type, value));
+ }
+ enumerator->destroy(enumerator);
+ vips->destroy_offset(vips, offsetof(host_t, destroy));
+ pools->destroy(pools);
+
+ cp->set_identifier(cp, this->identifier);
+ message->add_payload(message, (payload_t*)cp);
+
+ return SUCCESS;
+}
+
+METHOD(task_t, process_i, status_t,
+ private_mode_config_t *this, message_t *message)
+{
+ enumerator_t *enumerator;
+ host_t *host;
+
+ process_payloads(this, message);
+
+ this->ike_sa->clear_virtual_ips(this->ike_sa, TRUE);
+
+ enumerator = this->vips->create_enumerator(this->vips);
+ while (enumerator->enumerate(enumerator, &host))
+ {
+ if (!host->is_anyaddr(host))
+ {
+ this->ike_sa->add_virtual_ip(this->ike_sa, TRUE, host);
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return SUCCESS;
+}
+
+METHOD(task_t, get_type, task_type_t,
+ private_mode_config_t *this)
+{
+ return TASK_MODE_CONFIG;
+}
+
+METHOD(task_t, migrate, void,
+ private_mode_config_t *this, ike_sa_t *ike_sa)
+{
+ this->ike_sa = ike_sa;
+ this->vips->destroy_offset(this->vips, offsetof(host_t, destroy));
+ this->vips = linked_list_create();
+ this->requested->destroy_function(this->requested, free);
+ this->requested = linked_list_create();
+}
+
+METHOD(task_t, destroy, void,
+ private_mode_config_t *this)
+{
+ this->vips->destroy_offset(this->vips, offsetof(host_t, destroy));
+ this->requested->destroy_function(this->requested, free);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+mode_config_t *mode_config_create(ike_sa_t *ike_sa, bool initiator)
+{
+ private_mode_config_t *this;
+
+ INIT(this,
+ .public = {
+ .task = {
+ .get_type = _get_type,
+ .migrate = _migrate,
+ .destroy = _destroy,
+ },
+ },
+ .initiator = initiator,
+ .ike_sa = ike_sa,
+ .requested = linked_list_create(),
+ .vips = linked_list_create(),
+ );
+
+ if (initiator)
+ {
+ this->public.task.build = _build_i;
+ this->public.task.process = _process_i;
+ }
+ else
+ {
+ this->public.task.build = _build_r;
+ this->public.task.process = _process_r;
+ }
+
+ return &this->public;
+}
diff --git a/src/libcharon/sa/ikev1/tasks/mode_config.h b/src/libcharon/sa/ikev1/tasks/mode_config.h
new file mode 100644
index 000000000..462bee374
--- /dev/null
+++ b/src/libcharon/sa/ikev1/tasks/mode_config.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 mode_config mode_config
+ * @{ @ingroup tasks_v1
+ */
+
+#ifndef MODE_CONFIG_H_
+#define MODE_CONFIG_H_
+
+typedef struct mode_config_t mode_config_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/task.h>
+
+/**
+ * Task of type TASK_MODE_COFNIG, IKEv1 configuration attribute exchange.
+ */
+struct mode_config_t {
+
+ /**
+ * Implements the task_t interface
+ */
+ task_t task;
+};
+
+/**
+ * Create a new mode_config task.
+ *
+ * @param ike_sa IKE_SA this task works for
+ * @param initiator TRUE for initiator
+ * @return mode_config task to handle by the task_manager
+ */
+mode_config_t *mode_config_create(ike_sa_t *ike_sa, bool initiator);
+
+#endif /** MODE_CONFIG_H_ @}*/
diff --git a/src/libcharon/sa/ikev1/tasks/quick_delete.c b/src/libcharon/sa/ikev1/tasks/quick_delete.c
new file mode 100644
index 000000000..db48bc58e
--- /dev/null
+++ b/src/libcharon/sa/ikev1/tasks/quick_delete.c
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 "quick_delete.h"
+
+#include <daemon.h>
+#include <encoding/payloads/delete_payload.h>
+
+typedef struct private_quick_delete_t private_quick_delete_t;
+
+/**
+ * Private members of a quick_delete_t task.
+ */
+struct private_quick_delete_t {
+
+ /**
+ * Public methods and task_t interface.
+ */
+ quick_delete_t public;
+
+ /**
+ * Assigned IKE_SA.
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * Are we the initiator?
+ */
+ bool initiator;
+
+ /**
+ * Protocol of CHILD_SA to delete
+ */
+ protocol_id_t protocol;
+
+ /**
+ * Inbound SPI of CHILD_SA to delete
+ */
+ u_int32_t spi;
+
+ /**
+ * Send delete even if SA does not exist
+ */
+ bool force;
+
+ /**
+ * SA already expired?
+ */
+ bool expired;
+};
+
+/**
+ * Delete the specified CHILD_SA, if found
+ */
+static bool delete_child(private_quick_delete_t *this,
+ protocol_id_t protocol, u_int32_t spi)
+{
+ u_int64_t bytes_in, bytes_out;
+ child_sa_t *child_sa;
+ bool rekeyed;
+
+ child_sa = this->ike_sa->get_child_sa(this->ike_sa, protocol, spi, TRUE);
+ if (!child_sa)
+ { /* fallback and check for outbound SA */
+ child_sa = this->ike_sa->get_child_sa(this->ike_sa, protocol, spi, FALSE);
+ if (!child_sa)
+ {
+ return FALSE;
+ }
+ this->spi = spi = child_sa->get_spi(child_sa, TRUE);
+ }
+
+ rekeyed = child_sa->get_state(child_sa) == CHILD_REKEYING;
+ child_sa->set_state(child_sa, CHILD_DELETING);
+
+ if (this->expired)
+ {
+ DBG0(DBG_IKE, "closing expired CHILD_SA %s{%d} "
+ "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
+ child_sa->get_name(child_sa), child_sa->get_reqid(child_sa),
+ ntohl(child_sa->get_spi(child_sa, TRUE)),
+ ntohl(child_sa->get_spi(child_sa, FALSE)),
+ child_sa->get_traffic_selectors(child_sa, TRUE),
+ child_sa->get_traffic_selectors(child_sa, FALSE));
+ }
+ else
+ {
+ child_sa->get_usestats(child_sa, TRUE, NULL, &bytes_in);
+ child_sa->get_usestats(child_sa, FALSE, NULL, &bytes_out);
+
+ DBG0(DBG_IKE, "closing CHILD_SA %s{%d} with SPIs "
+ "%.8x_i (%llu bytes) %.8x_o (%llu bytes) and TS %#R=== %#R",
+ child_sa->get_name(child_sa), child_sa->get_reqid(child_sa),
+ ntohl(child_sa->get_spi(child_sa, TRUE)), bytes_in,
+ ntohl(child_sa->get_spi(child_sa, FALSE)), bytes_out,
+ child_sa->get_traffic_selectors(child_sa, TRUE),
+ child_sa->get_traffic_selectors(child_sa, FALSE));
+ }
+
+ if (!rekeyed)
+ {
+ charon->bus->child_updown(charon->bus, child_sa, FALSE);
+ }
+
+ this->ike_sa->destroy_child_sa(this->ike_sa, protocol, spi);
+
+ /* TODO-IKEv1: handle close action? */
+
+ return TRUE;
+}
+
+METHOD(task_t, build_i, status_t,
+ private_quick_delete_t *this, message_t *message)
+{
+ if (delete_child(this, this->protocol, this->spi) || this->force)
+ {
+ delete_payload_t *delete_payload;
+
+ DBG1(DBG_IKE, "sending DELETE for %N CHILD_SA with SPI %.8x",
+ protocol_id_names, this->protocol, ntohl(this->spi));
+
+ delete_payload = delete_payload_create(DELETE_V1, PROTO_ESP);
+ delete_payload->add_spi(delete_payload, this->spi);
+ message->add_payload(message, &delete_payload->payload_interface);
+
+ return SUCCESS;
+ }
+ this->ike_sa->flush_queue(this->ike_sa, TASK_QUEUE_ACTIVE);
+ return ALREADY_DONE;
+}
+
+METHOD(task_t, process_i, status_t,
+ private_quick_delete_t *this, message_t *message)
+{
+ return FAILED;
+}
+
+METHOD(task_t, process_r, status_t,
+ private_quick_delete_t *this, message_t *message)
+{
+ enumerator_t *payloads, *spis;
+ payload_t *payload;
+ delete_payload_t *delete_payload;
+ protocol_id_t protocol;
+ u_int32_t spi;
+
+ payloads = message->create_payload_enumerator(message);
+ while (payloads->enumerate(payloads, &payload))
+ {
+ if (payload->get_type(payload) == DELETE_V1)
+ {
+ delete_payload = (delete_payload_t*)payload;
+ protocol = delete_payload->get_protocol_id(delete_payload);
+ if (protocol != PROTO_ESP && protocol != PROTO_AH)
+ {
+ continue;
+ }
+ spis = delete_payload->create_spi_enumerator(delete_payload);
+ while (spis->enumerate(spis, &spi))
+ {
+ DBG1(DBG_IKE, "received DELETE for %N CHILD_SA with SPI %.8x",
+ protocol_id_names, protocol, ntohl(spi));
+ if (!delete_child(this, protocol, spi))
+ {
+ DBG1(DBG_IKE, "CHILD_SA not found, ignored");
+ continue;
+ }
+ }
+ spis->destroy(spis);
+ }
+ }
+ payloads->destroy(payloads);
+
+ return SUCCESS;
+}
+
+METHOD(task_t, build_r, status_t,
+ private_quick_delete_t *this, message_t *message)
+{
+ return FAILED;
+}
+
+METHOD(task_t, get_type, task_type_t,
+ private_quick_delete_t *this)
+{
+ return TASK_QUICK_DELETE;
+}
+
+METHOD(task_t, migrate, void,
+ private_quick_delete_t *this, ike_sa_t *ike_sa)
+{
+ this->ike_sa = ike_sa;
+}
+
+METHOD(task_t, destroy, void,
+ private_quick_delete_t *this)
+{
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+quick_delete_t *quick_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol,
+ u_int32_t spi, bool force, bool expired)
+{
+ private_quick_delete_t *this;
+
+ INIT(this,
+ .public = {
+ .task = {
+ .get_type = _get_type,
+ .migrate = _migrate,
+ .destroy = _destroy,
+ },
+ },
+ .ike_sa = ike_sa,
+ .protocol = protocol,
+ .spi = spi,
+ .force = force,
+ .expired = expired,
+ );
+
+ if (protocol != PROTO_NONE)
+ {
+ this->public.task.build = _build_i;
+ this->public.task.process = _process_i;
+ }
+ else
+ {
+ this->public.task.build = _build_r;
+ this->public.task.process = _process_r;
+ }
+ return &this->public;
+}
diff --git a/src/libcharon/sa/ikev1/tasks/quick_delete.h b/src/libcharon/sa/ikev1/tasks/quick_delete.h
new file mode 100644
index 000000000..4df30c8fe
--- /dev/null
+++ b/src/libcharon/sa/ikev1/tasks/quick_delete.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 quick_delete quick_delete
+ * @{ @ingroup tasks_v1
+ */
+
+#ifndef QUICK_DELETE_H_
+#define QUICK_DELETE_H_
+
+typedef struct quick_delete_t quick_delete_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/task.h>
+#include <sa/child_sa.h>
+
+/**
+ * Task of type QUICK_DELETE, delete an IKEv1 quick mode SA.
+ */
+struct quick_delete_t {
+
+ /**
+ * Implements the task_t interface
+ */
+ task_t task;
+};
+
+/**
+ * Create a new quick_delete task.
+ *
+ * @param ike_sa IKE_SA this task works for
+ * @param protocol protocol of CHILD_SA to delete, PROTO_NONE as responder
+ * @param spi inbound SPI of CHILD_SA to delete
+ * @param force send delete even if SA does not exist
+ * @param expired TRUE if SA already expired
+ * @return quick_delete task to handle by the task_manager
+ */
+quick_delete_t *quick_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol,
+ u_int32_t spi, bool force, bool expired);
+
+#endif /** QUICK_DELETE_H_ @}*/
diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.c b/src/libcharon/sa/ikev1/tasks/quick_mode.c
new file mode 100644
index 000000000..82a7238c3
--- /dev/null
+++ b/src/libcharon/sa/ikev1/tasks/quick_mode.c
@@ -0,0 +1,1273 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 "quick_mode.h"
+
+#include <string.h>
+
+#include <daemon.h>
+#include <sa/ikev1/keymat_v1.h>
+#include <encoding/payloads/sa_payload.h>
+#include <encoding/payloads/nonce_payload.h>
+#include <encoding/payloads/ke_payload.h>
+#include <encoding/payloads/id_payload.h>
+#include <encoding/payloads/payload.h>
+#include <sa/ikev1/tasks/informational.h>
+#include <sa/ikev1/tasks/quick_delete.h>
+#include <processing/jobs/inactivity_job.h>
+
+typedef struct private_quick_mode_t private_quick_mode_t;
+
+/**
+ * Private members of a quick_mode_t task.
+ */
+struct private_quick_mode_t {
+
+ /**
+ * Public methods and task_t interface.
+ */
+ quick_mode_t public;
+
+ /**
+ * Assigned IKE_SA.
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * TRUE if we are initiating quick mode
+ */
+ bool initiator;
+
+ /**
+ * Traffic selector of initiator
+ */
+ traffic_selector_t *tsi;
+
+ /**
+ * Traffic selector of responder
+ */
+ traffic_selector_t *tsr;
+
+ /**
+ * Initiators nonce
+ */
+ chunk_t nonce_i;
+
+ /**
+ * Responder nonce
+ */
+ chunk_t nonce_r;
+
+ /**
+ * Initiators ESP SPI
+ */
+ u_int32_t spi_i;
+
+ /**
+ * Responder ESP SPI
+ */
+ u_int32_t spi_r;
+
+ /**
+ * Initiators IPComp CPI
+ */
+ u_int16_t cpi_i;
+
+ /**
+ * Responders IPComp CPI
+ */
+ u_int16_t cpi_r;
+
+ /**
+ * selected CHILD_SA proposal
+ */
+ proposal_t *proposal;
+
+ /**
+ * Config of CHILD_SA to establish
+ */
+ child_cfg_t *config;
+
+ /**
+ * CHILD_SA we are about to establish
+ */
+ child_sa_t *child_sa;
+
+ /**
+ * IKEv1 keymat
+ */
+ keymat_v1_t *keymat;
+
+ /**
+ * DH exchange, when PFS is in use
+ */
+ diffie_hellman_t *dh;
+
+ /**
+ * Negotiated lifetime of new SA
+ */
+ u_int32_t lifetime;
+
+ /**
+ * Negotaited lifebytes of new SA
+ */
+ u_int64_t lifebytes;
+
+ /**
+ * Reqid to use, 0 for auto-allocate
+ */
+ u_int32_t reqid;
+
+ /**
+ * SPI of SA we rekey
+ */
+ u_int32_t rekey;
+
+ /**
+ * Negotiated mode, tunnel or transport
+ */
+ ipsec_mode_t mode;
+
+ /**
+ * Use UDP encapsulation
+ */
+ bool udp;
+
+ /** states of quick mode */
+ enum {
+ QM_INIT,
+ QM_NEGOTIATED,
+ } state;
+};
+
+/**
+ * Schedule inactivity timeout for CHILD_SA with reqid, if enabled
+ */
+static void schedule_inactivity_timeout(private_quick_mode_t *this)
+{
+ u_int32_t timeout;
+ bool close_ike;
+
+ timeout = this->config->get_inactivity(this->config);
+ if (timeout)
+ {
+ close_ike = lib->settings->get_bool(lib->settings,
+ "%s.inactivity_close_ike", FALSE, charon->name);
+ lib->scheduler->schedule_job(lib->scheduler, (job_t*)
+ inactivity_job_create(this->child_sa->get_reqid(this->child_sa),
+ timeout, close_ike), timeout);
+ }
+}
+
+/**
+ * Check if we have a an address pool configured
+ */
+static bool have_pool(ike_sa_t *ike_sa)
+{
+ enumerator_t *enumerator;
+ peer_cfg_t *peer_cfg;
+ char *pool;
+ bool found = FALSE;
+
+ peer_cfg = ike_sa->get_peer_cfg(ike_sa);
+ if (peer_cfg)
+ {
+ enumerator = peer_cfg->create_pool_enumerator(peer_cfg);
+ if (enumerator->enumerate(enumerator, &pool))
+ {
+ found = TRUE;
+ }
+ enumerator->destroy(enumerator);
+ }
+ return found;
+}
+
+/**
+ * Get hosts to use for dynamic traffic selectors
+ */
+static linked_list_t *get_dynamic_hosts(ike_sa_t *ike_sa, bool local)
+{
+ enumerator_t *enumerator;
+ linked_list_t *list;
+ host_t *host;
+
+ list = linked_list_create();
+ enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, local);
+ while (enumerator->enumerate(enumerator, &host))
+ {
+ list->insert_last(list, host);
+ }
+ enumerator->destroy(enumerator);
+
+ if (list->get_count(list) == 0)
+ { /* no virtual IPs assigned */
+ if (local)
+ {
+ host = ike_sa->get_my_host(ike_sa);
+ list->insert_last(list, host);
+ }
+ else if (!have_pool(ike_sa))
+ { /* use host only if we don't have a pool configured */
+ host = ike_sa->get_other_host(ike_sa);
+ list->insert_last(list, host);
+ }
+ }
+ return list;
+}
+
+/**
+ * Install negotiated CHILD_SA
+ */
+static bool install(private_quick_mode_t *this)
+{
+ status_t status, status_i, status_o;
+ chunk_t encr_i, encr_r, integ_i, integ_r;
+ linked_list_t *tsi, *tsr;
+ child_sa_t *old = NULL;
+
+ this->child_sa->set_proposal(this->child_sa, this->proposal);
+ this->child_sa->set_state(this->child_sa, CHILD_INSTALLING);
+ this->child_sa->set_mode(this->child_sa, this->mode);
+
+ if (this->cpi_i && this->cpi_r)
+ { /* DEFLATE is the only transform we currently support */
+ this->child_sa->set_ipcomp(this->child_sa, IPCOMP_DEFLATE);
+ }
+ else
+ {
+ this->cpi_i = this->cpi_r = 0;
+ }
+
+ this->child_sa->set_protocol(this->child_sa,
+ this->proposal->get_protocol(this->proposal));
+
+ status_i = status_o = FAILED;
+ encr_i = encr_r = integ_i = integ_r = chunk_empty;
+ tsi = linked_list_create_with_items(this->tsi->clone(this->tsi), NULL);
+ tsr = linked_list_create_with_items(this->tsr->clone(this->tsr), NULL);
+ if (this->initiator)
+ {
+ charon->bus->narrow(charon->bus, this->child_sa,
+ NARROW_INITIATOR_POST_AUTH, tsi, tsr);
+ }
+ else
+ {
+ charon->bus->narrow(charon->bus, this->child_sa,
+ NARROW_RESPONDER_POST, tsr, tsi);
+ }
+ if (tsi->get_count(tsi) == 0 || tsr->get_count(tsr) == 0)
+ {
+ tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
+ tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
+ DBG1(DBG_IKE, "no acceptable traffic selectors found");
+ return FALSE;
+ }
+
+ if (this->keymat->derive_child_keys(this->keymat, this->proposal, this->dh,
+ this->spi_i, this->spi_r, this->nonce_i, this->nonce_r,
+ &encr_i, &integ_i, &encr_r, &integ_r))
+ {
+ if (this->initiator)
+ {
+ status_i = this->child_sa->install(this->child_sa, encr_r, integ_r,
+ this->spi_i, this->cpi_i, TRUE, FALSE, tsi, tsr);
+ status_o = this->child_sa->install(this->child_sa, encr_i, integ_i,
+ this->spi_r, this->cpi_r, FALSE, FALSE, tsi, tsr);
+ }
+ else
+ {
+ status_i = this->child_sa->install(this->child_sa, encr_i, integ_i,
+ this->spi_r, this->cpi_r, TRUE, FALSE, tsr, tsi);
+ status_o = this->child_sa->install(this->child_sa, encr_r, integ_r,
+ this->spi_i, this->cpi_i, FALSE, FALSE, tsr, tsi);
+ }
+ }
+ chunk_clear(&integ_i);
+ chunk_clear(&integ_r);
+ chunk_clear(&encr_i);
+ chunk_clear(&encr_r);
+
+ if (status_i != SUCCESS || status_o != SUCCESS)
+ {
+ DBG1(DBG_IKE, "unable to install %s%s%sIPsec SA (SAD) in kernel",
+ (status_i != SUCCESS) ? "inbound " : "",
+ (status_i != SUCCESS && status_o != SUCCESS) ? "and ": "",
+ (status_o != SUCCESS) ? "outbound " : "");
+ tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
+ tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
+ return FALSE;
+ }
+
+ if (this->initiator)
+ {
+ status = this->child_sa->add_policies(this->child_sa, tsi, tsr);
+ }
+ else
+ {
+ status = this->child_sa->add_policies(this->child_sa, tsr, tsi);
+ }
+ tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
+ tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel");
+ return FALSE;
+ }
+
+ charon->bus->child_keys(charon->bus, this->child_sa, this->initiator,
+ this->dh, this->nonce_i, this->nonce_r);
+
+ /* add to IKE_SA, and remove from task */
+ this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
+ this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
+
+ DBG0(DBG_IKE, "CHILD_SA %s{%d} established "
+ "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
+ this->child_sa->get_name(this->child_sa),
+ this->child_sa->get_reqid(this->child_sa),
+ ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
+ ntohl(this->child_sa->get_spi(this->child_sa, FALSE)),
+ this->child_sa->get_traffic_selectors(this->child_sa, TRUE),
+ this->child_sa->get_traffic_selectors(this->child_sa, FALSE));
+
+ if (this->rekey)
+ {
+ old = this->ike_sa->get_child_sa(this->ike_sa,
+ this->proposal->get_protocol(this->proposal),
+ this->rekey, TRUE);
+ }
+ if (old)
+ {
+ charon->bus->child_rekey(charon->bus, old, this->child_sa);
+ }
+ else
+ {
+ charon->bus->child_updown(charon->bus, this->child_sa, TRUE);
+ }
+ if (!this->rekey)
+ {
+ schedule_inactivity_timeout(this);
+ }
+ this->child_sa = NULL;
+ return TRUE;
+}
+
+/**
+ * Generate and add NONCE
+ */
+static bool add_nonce(private_quick_mode_t *this, chunk_t *nonce,
+ message_t *message)
+{
+ nonce_payload_t *nonce_payload;
+ nonce_gen_t *nonceg;
+
+ nonceg = this->keymat->keymat.create_nonce_gen(&this->keymat->keymat);
+ if (!nonceg)
+ {
+ DBG1(DBG_IKE, "no nonce generator found to create nonce");
+ return FALSE;
+ }
+ if (!nonceg->allocate_nonce(nonceg, NONCE_SIZE, nonce))
+ {
+ DBG1(DBG_IKE, "nonce allocation failed");
+ nonceg->destroy(nonceg);
+ return FALSE;
+ }
+ nonceg->destroy(nonceg);
+
+ nonce_payload = nonce_payload_create(NONCE_V1);
+ nonce_payload->set_nonce(nonce_payload, *nonce);
+ message->add_payload(message, &nonce_payload->payload_interface);
+
+ return TRUE;
+}
+
+/**
+ * Extract nonce from NONCE payload
+ */
+static bool get_nonce(private_quick_mode_t *this, chunk_t *nonce,
+ message_t *message)
+{
+ nonce_payload_t *nonce_payload;
+
+ nonce_payload = (nonce_payload_t*)message->get_payload(message, NONCE_V1);
+ if (!nonce_payload)
+ {
+ DBG1(DBG_IKE, "NONCE payload missing in message");
+ return FALSE;
+ }
+ *nonce = nonce_payload->get_nonce(nonce_payload);
+
+ return TRUE;
+}
+
+/**
+ * Add KE payload to message
+ */
+static void add_ke(private_quick_mode_t *this, message_t *message)
+{
+ ke_payload_t *ke_payload;
+
+ ke_payload = ke_payload_create_from_diffie_hellman(KEY_EXCHANGE_V1, this->dh);
+ message->add_payload(message, &ke_payload->payload_interface);
+}
+
+/**
+ * Get DH value from a KE payload
+ */
+static bool get_ke(private_quick_mode_t *this, message_t *message)
+{
+ ke_payload_t *ke_payload;
+
+ ke_payload = (ke_payload_t*)message->get_payload(message, KEY_EXCHANGE_V1);
+ if (!ke_payload)
+ {
+ DBG1(DBG_IKE, "KE payload missing");
+ return FALSE;
+ }
+ this->dh->set_other_public_value(this->dh,
+ ke_payload->get_key_exchange_data(ke_payload));
+ return TRUE;
+}
+
+/**
+ * Select a traffic selector from configuration
+ */
+static traffic_selector_t* select_ts(private_quick_mode_t *this, bool local,
+ linked_list_t *supplied)
+{
+ traffic_selector_t *ts;
+ linked_list_t *list, *hosts;
+
+ hosts = get_dynamic_hosts(this->ike_sa, local);
+ list = this->config->get_traffic_selectors(this->config,
+ local, supplied, hosts);
+ hosts->destroy(hosts);
+ if (list->get_first(list, (void**)&ts) == SUCCESS)
+ {
+ ts = ts->clone(ts);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "%s traffic selector missing in configuration",
+ local ? "local" : "local");
+ ts = NULL;
+ }
+ list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
+ return ts;
+}
+
+/**
+ * Add selected traffic selectors to message
+ */
+static void add_ts(private_quick_mode_t *this, message_t *message)
+{
+ id_payload_t *id_payload;
+ host_t *hsi, *hsr;
+
+ if (this->initiator)
+ {
+ hsi = this->ike_sa->get_my_host(this->ike_sa);
+ hsr = this->ike_sa->get_other_host(this->ike_sa);
+ }
+ else
+ {
+ hsr = this->ike_sa->get_my_host(this->ike_sa);
+ hsi = this->ike_sa->get_other_host(this->ike_sa);
+ }
+ /* add ID payload only if negotiating non host2host tunnels */
+ if (!this->tsi->is_host(this->tsi, hsi) ||
+ !this->tsr->is_host(this->tsr, hsr) ||
+ this->tsi->get_protocol(this->tsi) ||
+ this->tsr->get_protocol(this->tsr) ||
+ this->tsi->get_from_port(this->tsi) ||
+ this->tsr->get_from_port(this->tsr) ||
+ this->tsi->get_to_port(this->tsi) != 65535 ||
+ this->tsr->get_to_port(this->tsr) != 65535)
+ {
+ id_payload = id_payload_create_from_ts(this->tsi);
+ message->add_payload(message, &id_payload->payload_interface);
+ id_payload = id_payload_create_from_ts(this->tsr);
+ message->add_payload(message, &id_payload->payload_interface);
+ }
+}
+
+/**
+ * Get traffic selectors from received message
+ */
+static bool get_ts(private_quick_mode_t *this, message_t *message)
+{
+ traffic_selector_t *tsi = NULL, *tsr = NULL;
+ enumerator_t *enumerator;
+ id_payload_t *id_payload;
+ payload_t *payload;
+ host_t *hsi, *hsr;
+ bool first = TRUE;
+
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ if (payload->get_type(payload) == ID_V1)
+ {
+ id_payload = (id_payload_t*)payload;
+
+ if (first)
+ {
+ tsi = id_payload->get_ts(id_payload);
+ first = FALSE;
+ }
+ else
+ {
+ tsr = id_payload->get_ts(id_payload);
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ /* create host2host selectors if ID payloads missing */
+ if (this->initiator)
+ {
+ hsi = this->ike_sa->get_my_host(this->ike_sa);
+ hsr = this->ike_sa->get_other_host(this->ike_sa);
+ }
+ else
+ {
+ hsr = this->ike_sa->get_my_host(this->ike_sa);
+ hsi = this->ike_sa->get_other_host(this->ike_sa);
+ }
+ if (!tsi)
+ {
+ tsi = traffic_selector_create_from_subnet(hsi->clone(hsi),
+ hsi->get_family(hsi) == AF_INET ? 32 : 128, 0, 0);
+ }
+ if (!tsr)
+ {
+ tsr = traffic_selector_create_from_subnet(hsr->clone(hsr),
+ hsr->get_family(hsr) == AF_INET ? 32 : 128, 0, 0);
+ }
+ if (!this->initiator && this->mode == MODE_TRANSPORT && this->udp &&
+ (!tsi->is_host(tsi, hsi) || !tsr->is_host(tsr, hsr)))
+ { /* change TS in case of a NAT in transport mode */
+ DBG2(DBG_IKE, "changing received traffic selectors %R=== %R due to NAT",
+ tsi, tsr);
+ tsi->set_address(tsi, hsi);
+ tsr->set_address(tsr, hsr);
+ }
+
+ if (this->initiator)
+ {
+ /* check if peer selection valid */
+ if (!tsr->is_contained_in(tsr, this->tsr) ||
+ !tsi->is_contained_in(tsi, this->tsi))
+ {
+ DBG1(DBG_IKE, "peer selected invalid traffic selectors: ",
+ "%R for %R, %R for %R", tsi, this->tsi, tsr, this->tsr);
+ tsi->destroy(tsi);
+ tsr->destroy(tsr);
+ return FALSE;
+ }
+ this->tsi->destroy(this->tsi);
+ this->tsr->destroy(this->tsr);
+ this->tsi = tsi;
+ this->tsr = tsr;
+ }
+ else
+ {
+ this->tsi = tsi;
+ this->tsr = tsr;
+ }
+ return TRUE;
+}
+
+/**
+ * Add NAT-OA payloads
+ */
+static void add_nat_oa_payloads(private_quick_mode_t *this, message_t *message)
+{
+ identification_t *id;
+ id_payload_t *nat_oa;
+ host_t *src, *dst;
+
+ src = message->get_source(message);
+ dst = message->get_destination(message);
+
+ src = this->initiator ? src : dst;
+ dst = this->initiator ? dst : src;
+
+ /* first NAT-OA is the initiator's address */
+ id = identification_create_from_sockaddr(src->get_sockaddr(src));
+ nat_oa = id_payload_create_from_identification(NAT_OA_V1, id);
+ message->add_payload(message, (payload_t*)nat_oa);
+ id->destroy(id);
+
+ /* second NAT-OA is that of the responder */
+ id = identification_create_from_sockaddr(dst->get_sockaddr(dst));
+ nat_oa = id_payload_create_from_identification(NAT_OA_V1, id);
+ message->add_payload(message, (payload_t*)nat_oa);
+ id->destroy(id);
+}
+
+/**
+ * Look up lifetimes
+ */
+static void get_lifetimes(private_quick_mode_t *this)
+{
+ lifetime_cfg_t *lft;
+
+ lft = this->config->get_lifetime(this->config);
+ if (lft->time.life)
+ {
+ this->lifetime = lft->time.life;
+ }
+ else if (lft->bytes.life)
+ {
+ this->lifebytes = lft->bytes.life;
+ }
+ free(lft);
+}
+
+/**
+ * Check and apply lifetimes
+ */
+static void apply_lifetimes(private_quick_mode_t *this, sa_payload_t *sa_payload)
+{
+ u_int32_t lifetime;
+ u_int64_t lifebytes;
+
+ lifetime = sa_payload->get_lifetime(sa_payload);
+ lifebytes = sa_payload->get_lifebytes(sa_payload);
+ if (this->lifetime != lifetime)
+ {
+ DBG1(DBG_IKE, "received %us lifetime, configured %us",
+ lifetime, this->lifetime);
+ this->lifetime = lifetime;
+ }
+ if (this->lifebytes != lifebytes)
+ {
+ DBG1(DBG_IKE, "received %llu lifebytes, configured %llu",
+ lifebytes, this->lifebytes);
+ this->lifebytes = lifebytes;
+ }
+}
+
+/**
+ * Set the task ready to build notify error message
+ */
+static status_t send_notify(private_quick_mode_t *this, notify_type_t type)
+{
+ notify_payload_t *notify;
+
+ notify = notify_payload_create_from_protocol_and_type(NOTIFY_V1,
+ PROTO_ESP, type);
+ notify->set_spi(notify, this->spi_i);
+
+ this->ike_sa->queue_task(this->ike_sa,
+ (task_t*)informational_create(this->ike_sa, notify));
+ /* cancel all active/passive tasks in favour of informational */
+ this->ike_sa->flush_queue(this->ike_sa,
+ this->initiator ? TASK_QUEUE_ACTIVE : TASK_QUEUE_PASSIVE);
+ return ALREADY_DONE;
+}
+
+METHOD(task_t, build_i, status_t,
+ private_quick_mode_t *this, message_t *message)
+{
+ switch (this->state)
+ {
+ case QM_INIT:
+ {
+ enumerator_t *enumerator;
+ sa_payload_t *sa_payload;
+ linked_list_t *list, *tsi, *tsr;
+ proposal_t *proposal;
+ diffie_hellman_group_t group;
+
+ this->udp = this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY);
+ this->mode = this->config->get_mode(this->config);
+ this->child_sa = child_sa_create(
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->config, this->reqid, this->udp);
+
+ if (this->udp && this->mode == MODE_TRANSPORT)
+ {
+ /* TODO-IKEv1: disable NAT-T for TRANSPORT mode by default? */
+ add_nat_oa_payloads(this, message);
+ }
+
+ if (this->config->use_ipcomp(this->config))
+ {
+ if (this->udp)
+ {
+ DBG1(DBG_IKE, "IPComp is not supported if either peer is "
+ "natted, IPComp disabled");
+ }
+ else
+ {
+ this->cpi_i = this->child_sa->alloc_cpi(this->child_sa);
+ if (!this->cpi_i)
+ {
+ DBG1(DBG_IKE, "unable to allocate a CPI from kernel, "
+ "IPComp disabled");
+ }
+ }
+ }
+
+ this->spi_i = this->child_sa->alloc_spi(this->child_sa, PROTO_ESP);
+ if (!this->spi_i)
+ {
+ DBG1(DBG_IKE, "allocating SPI from kernel failed");
+ return FAILED;
+ }
+
+ list = this->config->get_proposals(this->config, FALSE);
+ enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, &proposal))
+ {
+ proposal->set_spi(proposal, this->spi_i);
+ }
+ enumerator->destroy(enumerator);
+
+ get_lifetimes(this);
+ sa_payload = sa_payload_create_from_proposals_v1(list,
+ this->lifetime, this->lifebytes, AUTH_NONE,
+ this->mode, this->udp, this->cpi_i);
+ list->destroy_offset(list, offsetof(proposal_t, destroy));
+ message->add_payload(message, &sa_payload->payload_interface);
+
+ if (!add_nonce(this, &this->nonce_i, message))
+ {
+ return FAILED;
+ }
+
+ group = this->config->get_dh_group(this->config);
+ if (group != MODP_NONE)
+ {
+ this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
+ group);
+ if (!this->dh)
+ {
+ DBG1(DBG_IKE, "configured DH group %N not supported",
+ diffie_hellman_group_names, group);
+ return FAILED;
+ }
+ add_ke(this, message);
+ }
+ if (!this->tsi)
+ {
+ this->tsi = select_ts(this, TRUE, NULL);
+ }
+ if (!this->tsr)
+ {
+ this->tsr = select_ts(this, FALSE, NULL);
+ }
+ tsi = linked_list_create_with_items(this->tsi, NULL);
+ tsr = linked_list_create_with_items(this->tsr, NULL);
+ this->tsi = this->tsr = NULL;
+ charon->bus->narrow(charon->bus, this->child_sa,
+ NARROW_INITIATOR_PRE_AUTH, tsi, tsr);
+ tsi->remove_first(tsi, (void**)&this->tsi);
+ tsr->remove_first(tsr, (void**)&this->tsr);
+ tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
+ tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
+ if (!this->tsi || !this->tsr)
+ {
+ return FAILED;
+ }
+ add_ts(this, message);
+ return NEED_MORE;
+ }
+ case QM_NEGOTIATED:
+ {
+ return SUCCESS;
+ }
+ default:
+ return FAILED;
+ }
+}
+
+/**
+ * Check for notify errors, return TRUE if error found
+ */
+static bool has_notify_errors(private_quick_mode_t *this, message_t *message)
+{
+ enumerator_t *enumerator;
+ payload_t *payload;
+ bool err = FALSE;
+
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ if (payload->get_type(payload) == NOTIFY_V1)
+ {
+ notify_payload_t *notify;
+ notify_type_t type;
+
+ notify = (notify_payload_t*)payload;
+ type = notify->get_notify_type(notify);
+ if (type < 16384)
+ {
+
+ DBG1(DBG_IKE, "received %N error notify",
+ notify_type_names, type);
+ err = TRUE;
+ }
+ else
+ {
+ DBG1(DBG_IKE, "received %N notify", notify_type_names, type);
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return err;
+}
+
+/**
+ * Check if this is a rekey for an existing CHILD_SA, reuse reqid if so
+ */
+static void check_for_rekeyed_child(private_quick_mode_t *this)
+{
+ enumerator_t *enumerator, *policies;
+ traffic_selector_t *local, *remote;
+ child_sa_t *child_sa;
+
+ enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
+ while (this->reqid == 0 && enumerator->enumerate(enumerator, &child_sa))
+ {
+ if (child_sa->get_state(child_sa) == CHILD_INSTALLED &&
+ streq(child_sa->get_name(child_sa),
+ this->config->get_name(this->config)))
+ {
+ policies = child_sa->create_policy_enumerator(child_sa);
+ if (policies->enumerate(policies, &local, &remote))
+ {
+ if (local->equals(local, this->tsr) &&
+ remote->equals(remote, this->tsi) &&
+ this->proposal->equals(this->proposal,
+ child_sa->get_proposal(child_sa)))
+ {
+ this->reqid = child_sa->get_reqid(child_sa);
+ this->rekey = child_sa->get_spi(child_sa, TRUE);
+ child_sa->set_state(child_sa, CHILD_REKEYING);
+ DBG1(DBG_IKE, "detected rekeying of CHILD_SA %s{%u}",
+ child_sa->get_name(child_sa), this->reqid);
+ }
+ }
+ policies->destroy(policies);
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+METHOD(task_t, process_r, status_t,
+ private_quick_mode_t *this, message_t *message)
+{
+ switch (this->state)
+ {
+ case QM_INIT:
+ {
+ sa_payload_t *sa_payload;
+ linked_list_t *tsi, *tsr, *hostsi, *hostsr, *list = NULL;
+ peer_cfg_t *peer_cfg;
+ u_int16_t group;
+ bool private;
+
+ sa_payload = (sa_payload_t*)message->get_payload(message,
+ SECURITY_ASSOCIATION_V1);
+ if (!sa_payload)
+ {
+ DBG1(DBG_IKE, "sa payload missing");
+ return send_notify(this, INVALID_PAYLOAD_TYPE);
+ }
+
+ this->mode = sa_payload->get_encap_mode(sa_payload, &this->udp);
+
+ if (!get_ts(this, message))
+ {
+ return FAILED;
+ }
+ peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
+ tsi = linked_list_create_with_items(this->tsi, NULL);
+ tsr = linked_list_create_with_items(this->tsr, NULL);
+ this->tsi = this->tsr = NULL;
+ hostsi = get_dynamic_hosts(this->ike_sa, FALSE);
+ hostsr = get_dynamic_hosts(this->ike_sa, TRUE);
+ this->config = peer_cfg->select_child_cfg(peer_cfg, tsr, tsi,
+ hostsr, hostsi);
+ hostsi->destroy(hostsi);
+ hostsr->destroy(hostsr);
+ if (this->config)
+ {
+ this->tsi = select_ts(this, FALSE, tsi);
+ this->tsr = select_ts(this, TRUE, tsr);
+ }
+ tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
+ tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
+ if (!this->config || !this->tsi || !this->tsr)
+ {
+ DBG1(DBG_IKE, "no matching CHILD_SA config found");
+ return send_notify(this, INVALID_ID_INFORMATION);
+ }
+
+ if (this->config->use_ipcomp(this->config))
+ {
+ if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
+ {
+ DBG1(DBG_IKE, "IPComp is not supported if either peer is "
+ "natted, IPComp disabled");
+ }
+ else
+ {
+ list = sa_payload->get_ipcomp_proposals(sa_payload,
+ &this->cpi_i);
+ if (!list->get_count(list))
+ {
+ DBG1(DBG_IKE, "expected IPComp proposal but peer did "
+ "not send one, IPComp disabled");
+ this->cpi_i = 0;
+ }
+ }
+ }
+ if (!list || !list->get_count(list))
+ {
+ DESTROY_IF(list);
+ list = sa_payload->get_proposals(sa_payload);
+ }
+ private = this->ike_sa->supports_extension(this->ike_sa,
+ EXT_STRONGSWAN);
+ this->proposal = this->config->select_proposal(this->config,
+ list, FALSE, private);
+ list->destroy_offset(list, offsetof(proposal_t, destroy));
+
+ get_lifetimes(this);
+ apply_lifetimes(this, sa_payload);
+
+ if (!this->proposal)
+ {
+ DBG1(DBG_IKE, "no matching proposal found, sending %N",
+ notify_type_names, NO_PROPOSAL_CHOSEN);
+ return send_notify(this, NO_PROPOSAL_CHOSEN);
+ }
+ this->spi_i = this->proposal->get_spi(this->proposal);
+
+ if (!get_nonce(this, &this->nonce_i, message))
+ {
+ return send_notify(this, INVALID_PAYLOAD_TYPE);
+ }
+
+ if (this->proposal->get_algorithm(this->proposal,
+ DIFFIE_HELLMAN_GROUP, &group, NULL))
+ {
+ this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
+ group);
+ if (!this->dh)
+ {
+ DBG1(DBG_IKE, "negotiated DH group %N not supported",
+ diffie_hellman_group_names, group);
+ return send_notify(this, INVALID_KEY_INFORMATION);
+ }
+ if (!get_ke(this, message))
+ {
+ return send_notify(this, INVALID_PAYLOAD_TYPE);
+ }
+ }
+
+ check_for_rekeyed_child(this);
+
+ this->child_sa = child_sa_create(
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->config, this->reqid, this->udp);
+
+ tsi = linked_list_create_with_items(this->tsi, NULL);
+ tsr = linked_list_create_with_items(this->tsr, NULL);
+ this->tsi = this->tsr = NULL;
+ charon->bus->narrow(charon->bus, this->child_sa,
+ NARROW_RESPONDER, tsr, tsi);
+ if (tsi->remove_first(tsi, (void**)&this->tsi) != SUCCESS ||
+ tsr->remove_first(tsr, (void**)&this->tsr) != SUCCESS)
+ {
+ tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
+ tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
+ return send_notify(this, INVALID_ID_INFORMATION);
+ }
+ tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
+ tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
+
+ return NEED_MORE;
+ }
+ case QM_NEGOTIATED:
+ {
+ if (message->get_exchange_type(message) == INFORMATIONAL_V1 ||
+ has_notify_errors(this, message))
+ {
+ return SUCCESS;
+ }
+ if (!install(this))
+ {
+ ike_sa_t *ike_sa = this->ike_sa;
+ task_t *task;
+
+ task = (task_t*)quick_delete_create(this->ike_sa,
+ this->proposal->get_protocol(this->proposal),
+ this->spi_i, TRUE, TRUE);
+ /* flush_queue() destroys the current task */
+ ike_sa->flush_queue(ike_sa, TASK_QUEUE_PASSIVE);
+ ike_sa->queue_task(ike_sa, task);
+ return ALREADY_DONE;
+ }
+ return SUCCESS;
+ }
+ default:
+ return FAILED;
+ }
+}
+
+METHOD(task_t, build_r, status_t,
+ private_quick_mode_t *this, message_t *message)
+{
+ switch (this->state)
+ {
+ case QM_INIT:
+ {
+ sa_payload_t *sa_payload;
+
+ this->spi_r = this->child_sa->alloc_spi(this->child_sa, PROTO_ESP);
+ if (!this->spi_r)
+ {
+ DBG1(DBG_IKE, "allocating SPI from kernel failed");
+ return send_notify(this, NO_PROPOSAL_CHOSEN);
+ }
+ this->proposal->set_spi(this->proposal, this->spi_r);
+
+ if (this->cpi_i)
+ {
+ this->cpi_r = this->child_sa->alloc_cpi(this->child_sa);
+ if (!this->cpi_r)
+ {
+ DBG1(DBG_IKE, "unable to allocate a CPI from "
+ "kernel, IPComp disabled");
+ return send_notify(this, NO_PROPOSAL_CHOSEN);
+ }
+ }
+
+ if (this->udp && this->mode == MODE_TRANSPORT)
+ {
+ /* TODO-IKEv1: disable NAT-T for TRANSPORT mode by default? */
+ add_nat_oa_payloads(this, message);
+ }
+
+ sa_payload = sa_payload_create_from_proposal_v1(this->proposal,
+ this->lifetime, this->lifebytes, AUTH_NONE,
+ this->mode, this->udp, this->cpi_r);
+ message->add_payload(message, &sa_payload->payload_interface);
+
+ if (!add_nonce(this, &this->nonce_r, message))
+ {
+ return FAILED;
+ }
+ if (this->dh)
+ {
+ add_ke(this, message);
+ }
+
+ add_ts(this, message);
+
+ this->state = QM_NEGOTIATED;
+ return NEED_MORE;
+ }
+ default:
+ return FAILED;
+ }
+}
+
+METHOD(task_t, process_i, status_t,
+ private_quick_mode_t *this, message_t *message)
+{
+ switch (this->state)
+ {
+ case QM_INIT:
+ {
+ sa_payload_t *sa_payload;
+ linked_list_t *list = NULL;
+ bool private;
+
+ sa_payload = (sa_payload_t*)message->get_payload(message,
+ SECURITY_ASSOCIATION_V1);
+ if (!sa_payload)
+ {
+ DBG1(DBG_IKE, "sa payload missing");
+ return send_notify(this, NO_PROPOSAL_CHOSEN);
+ }
+ if (this->cpi_i)
+ {
+ list = sa_payload->get_ipcomp_proposals(sa_payload,
+ &this->cpi_r);
+ if (!list->get_count(list))
+ {
+ DBG1(DBG_IKE, "peer did not acccept our IPComp proposal, "
+ "IPComp disabled");
+ this->cpi_i = 0;
+ }
+ }
+ if (!list || !list->get_count(list))
+ {
+ DESTROY_IF(list);
+ list = sa_payload->get_proposals(sa_payload);
+ }
+ private = this->ike_sa->supports_extension(this->ike_sa,
+ EXT_STRONGSWAN);
+ this->proposal = this->config->select_proposal(this->config,
+ list, FALSE, private);
+ list->destroy_offset(list, offsetof(proposal_t, destroy));
+ if (!this->proposal)
+ {
+ DBG1(DBG_IKE, "no matching proposal found");
+ return send_notify(this, NO_PROPOSAL_CHOSEN);
+ }
+ this->spi_r = this->proposal->get_spi(this->proposal);
+
+ apply_lifetimes(this, sa_payload);
+
+ if (!get_nonce(this, &this->nonce_r, message))
+ {
+ return send_notify(this, INVALID_PAYLOAD_TYPE);
+ }
+ if (this->dh && !get_ke(this, message))
+ {
+ return send_notify(this, INVALID_KEY_INFORMATION);
+ }
+ if (!get_ts(this, message))
+ {
+ return send_notify(this, INVALID_PAYLOAD_TYPE);
+ }
+ if (!install(this))
+ {
+ return send_notify(this, NO_PROPOSAL_CHOSEN);
+ }
+ this->state = QM_NEGOTIATED;
+ return NEED_MORE;
+ }
+ default:
+ return FAILED;
+ }
+}
+
+METHOD(task_t, get_type, task_type_t,
+ private_quick_mode_t *this)
+{
+ return TASK_QUICK_MODE;
+}
+
+METHOD(quick_mode_t, use_reqid, void,
+ private_quick_mode_t *this, u_int32_t reqid)
+{
+ this->reqid = reqid;
+}
+
+METHOD(quick_mode_t, rekey, void,
+ private_quick_mode_t *this, u_int32_t spi)
+{
+ this->rekey = spi;
+}
+
+METHOD(task_t, migrate, void,
+ private_quick_mode_t *this, ike_sa_t *ike_sa)
+{
+ chunk_free(&this->nonce_i);
+ chunk_free(&this->nonce_r);
+ DESTROY_IF(this->tsi);
+ DESTROY_IF(this->tsr);
+ DESTROY_IF(this->proposal);
+ DESTROY_IF(this->child_sa);
+ DESTROY_IF(this->dh);
+
+ this->ike_sa = ike_sa;
+ this->keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
+ this->state = QM_INIT;
+ this->tsi = NULL;
+ this->tsr = NULL;
+ this->proposal = NULL;
+ this->child_sa = NULL;
+ this->dh = NULL;
+ this->spi_i = 0;
+ this->spi_r = 0;
+
+ if (!this->initiator)
+ {
+ DESTROY_IF(this->config);
+ this->config = NULL;
+ }
+}
+
+METHOD(task_t, destroy, void,
+ private_quick_mode_t *this)
+{
+ chunk_free(&this->nonce_i);
+ chunk_free(&this->nonce_r);
+ DESTROY_IF(this->tsi);
+ DESTROY_IF(this->tsr);
+ DESTROY_IF(this->proposal);
+ DESTROY_IF(this->child_sa);
+ DESTROY_IF(this->config);
+ DESTROY_IF(this->dh);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+quick_mode_t *quick_mode_create(ike_sa_t *ike_sa, child_cfg_t *config,
+ traffic_selector_t *tsi, traffic_selector_t *tsr)
+{
+ private_quick_mode_t *this;
+
+ INIT(this,
+ .public = {
+ .task = {
+ .get_type = _get_type,
+ .migrate = _migrate,
+ .destroy = _destroy,
+ },
+ .use_reqid = _use_reqid,
+ .rekey = _rekey,
+ },
+ .ike_sa = ike_sa,
+ .initiator = config != NULL,
+ .config = config,
+ .keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa),
+ .state = QM_INIT,
+ .tsi = tsi ? tsi->clone(tsi) : NULL,
+ .tsr = tsr ? tsr->clone(tsr) : NULL,
+ );
+
+ if (config)
+ {
+ this->public.task.build = _build_i;
+ this->public.task.process = _process_i;
+ }
+ else
+ {
+ this->public.task.build = _build_r;
+ this->public.task.process = _process_r;
+ }
+
+ return &this->public;
+}
diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.h b/src/libcharon/sa/ikev1/tasks/quick_mode.h
new file mode 100644
index 000000000..0b80cb836
--- /dev/null
+++ b/src/libcharon/sa/ikev1/tasks/quick_mode.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 quick_mode quick_mode
+ * @{ @ingroup tasks_v1
+ */
+
+#ifndef QUICK_MODE_H_
+#define QUICK_MODE_H_
+
+typedef struct quick_mode_t quick_mode_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/task.h>
+
+/**
+ * IKEv1 quick mode, establishes a CHILD_SA in IKEv1.
+ */
+struct quick_mode_t {
+
+ /**
+ * Implements the task_t interface
+ */
+ task_t task;
+
+ /**
+ * Use a specific reqid to install this CHILD_SA.
+ *
+ * @param reqid reqid to use
+ */
+ void (*use_reqid)(quick_mode_t *this, u_int32_t reqid);
+
+ /**
+ * Set the SPI of the old SA, if rekeying.
+ *
+ * @param spi spi of SA to rekey
+ */
+ void (*rekey)(quick_mode_t *this, u_int32_t spi);
+};
+
+/**
+ * Create a new quick_mode task.
+ *
+ * @param ike_sa IKE_SA this task works for
+ * @param config child_cfg if task initiator, NULL if responder
+ * @param tsi source of triggering packet, or NULL
+ * @param tsr destination of triggering packet, or NULL
+ * @return task to handle by the task_manager
+ */
+quick_mode_t *quick_mode_create(ike_sa_t *ike_sa, child_cfg_t *config,
+ traffic_selector_t *tsi, traffic_selector_t *tsr);
+
+#endif /** QUICK_MODE_H_ @}*/
diff --git a/src/libcharon/sa/ikev1/tasks/xauth.c b/src/libcharon/sa/ikev1/tasks/xauth.c
new file mode 100644
index 000000000..10bea5636
--- /dev/null
+++ b/src/libcharon/sa/ikev1/tasks/xauth.c
@@ -0,0 +1,551 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 "xauth.h"
+
+#include <daemon.h>
+#include <hydra.h>
+#include <encoding/payloads/cp_payload.h>
+#include <processing/jobs/adopt_children_job.h>
+
+typedef struct private_xauth_t private_xauth_t;
+
+/**
+ * Status types exchanged
+ */
+typedef enum {
+ XAUTH_FAILED = 0,
+ XAUTH_OK = 1,
+} xauth_status_t;
+
+/**
+ * Private members of a xauth_t task.
+ */
+struct private_xauth_t {
+
+ /**
+ * Public methods and task_t interface.
+ */
+ xauth_t public;
+
+ /**
+ * Assigned IKE_SA.
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * Are we the XAUTH initiator?
+ */
+ bool initiator;
+
+ /**
+ * XAuth backend to use
+ */
+ xauth_method_t *xauth;
+
+ /**
+ * XAuth username
+ */
+ identification_t *user;
+
+ /**
+ * Generated configuration payload
+ */
+ cp_payload_t *cp;
+
+ /**
+ * received identifier
+ */
+ u_int16_t identifier;
+
+ /**
+ * status of Xauth exchange
+ */
+ xauth_status_t status;
+};
+
+/**
+ * Load XAuth backend
+ */
+static xauth_method_t *load_method(private_xauth_t* this)
+{
+ identification_t *server, *peer;
+ enumerator_t *enumerator;
+ xauth_method_t *xauth;
+ xauth_role_t role;
+ peer_cfg_t *peer_cfg;
+ auth_cfg_t *auth;
+ char *name;
+
+ if (this->initiator)
+ {
+ server = this->ike_sa->get_my_id(this->ike_sa);
+ peer = this->ike_sa->get_other_id(this->ike_sa);
+ role = XAUTH_SERVER;
+ }
+ else
+ {
+ peer = this->ike_sa->get_my_id(this->ike_sa);
+ server = this->ike_sa->get_other_id(this->ike_sa);
+ role = XAUTH_PEER;
+ }
+ peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
+ enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, !this->initiator);
+ if (!enumerator->enumerate(enumerator, &auth) ||
+ (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS) != AUTH_CLASS_XAUTH)
+ {
+ if (!enumerator->enumerate(enumerator, &auth) ||
+ (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS) != AUTH_CLASS_XAUTH)
+ {
+ DBG1(DBG_CFG, "no XAuth authentication round found");
+ enumerator->destroy(enumerator);
+ return NULL;
+ }
+ }
+ name = auth->get(auth, AUTH_RULE_XAUTH_BACKEND);
+ this->user = auth->get(auth, AUTH_RULE_XAUTH_IDENTITY);
+ enumerator->destroy(enumerator);
+ if (!this->initiator && this->user)
+ { /* use XAUTH username, if configured */
+ peer = this->user;
+ }
+ xauth = charon->xauth->create_instance(charon->xauth, name, role,
+ server, peer);
+ if (!xauth)
+ {
+ if (name)
+ {
+ DBG1(DBG_CFG, "no XAuth method found named '%s'", name);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "no XAuth method found");
+ }
+ }
+ return xauth;
+}
+
+/**
+ * Check if XAuth connection is allowed to succeed
+ */
+static bool allowed(private_xauth_t *this)
+{
+ if (charon->ike_sa_manager->check_uniqueness(charon->ike_sa_manager,
+ this->ike_sa, FALSE))
+ {
+ DBG1(DBG_IKE, "cancelling XAuth due to uniqueness policy");
+ return FALSE;
+ }
+ if (!charon->bus->authorize(charon->bus, FALSE))
+ {
+ DBG1(DBG_IKE, "XAuth authorization hook forbids IKE_SA, cancelling");
+ return FALSE;
+ }
+ if (!charon->bus->authorize(charon->bus, TRUE))
+ {
+ DBG1(DBG_IKE, "final authorization hook forbids IKE_SA, cancelling");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * Set IKE_SA to established state
+ */
+static bool establish(private_xauth_t *this)
+{
+ DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa),
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_my_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
+
+ this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
+ charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
+
+ return TRUE;
+}
+
+/**
+ * Check if we are compliant to a given peer config
+ */
+static bool is_compliant(private_xauth_t *this, peer_cfg_t *peer_cfg, bool log)
+{
+ bool complies = TRUE;
+ enumerator_t *e1, *e2;
+ auth_cfg_t *c1, *c2;
+
+ e1 = peer_cfg->create_auth_cfg_enumerator(peer_cfg, FALSE);
+ e2 = this->ike_sa->create_auth_cfg_enumerator(this->ike_sa, FALSE);
+ while (e1->enumerate(e1, &c1))
+ {
+ if (!e2->enumerate(e2, &c2) || !c2->complies(c2, c1, log))
+ {
+ complies = FALSE;
+ break;
+ }
+ }
+ e1->destroy(e1);
+ e2->destroy(e2);
+
+ return complies;
+}
+
+/**
+ * Check if we are compliant to current config, switch to another if not
+ */
+static bool select_compliant_config(private_xauth_t *this)
+{
+ peer_cfg_t *peer_cfg = NULL, *old, *current;
+ identification_t *my_id, *other_id;
+ host_t *my_host, *other_host;
+ enumerator_t *enumerator;
+ bool aggressive;
+
+ old = this->ike_sa->get_peer_cfg(this->ike_sa);
+ if (is_compliant(this, old, TRUE))
+ { /* current config is fine */
+ return TRUE;
+ }
+ DBG1(DBG_CFG, "selected peer config '%s' inacceptable",
+ old->get_name(old));
+ aggressive = old->use_aggressive(old);
+
+ my_host = this->ike_sa->get_my_host(this->ike_sa);
+ other_host = this->ike_sa->get_other_host(this->ike_sa);
+ my_id = this->ike_sa->get_my_id(this->ike_sa);
+ other_id = this->ike_sa->get_other_id(this->ike_sa);
+ enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
+ my_host, other_host, my_id, other_id, IKEV1);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (!current->equals(current, old) &&
+ current->use_aggressive(current) == aggressive &&
+ is_compliant(this, current, FALSE))
+ {
+ peer_cfg = current;
+ break;
+ }
+ }
+ if (peer_cfg)
+ {
+ DBG1(DBG_CFG, "switching to peer config '%s'",
+ peer_cfg->get_name(peer_cfg));
+ this->ike_sa->set_peer_cfg(this->ike_sa, peer_cfg);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "no alternative config found");
+ }
+ enumerator->destroy(enumerator);
+
+ return peer_cfg != NULL;
+}
+
+/**
+ * Create auth config after successful authentication
+ */
+static bool add_auth_cfg(private_xauth_t *this, identification_t *id, bool local)
+{
+ auth_cfg_t *auth;
+
+ auth = auth_cfg_create();
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_XAUTH);
+ auth->add(auth, AUTH_RULE_XAUTH_IDENTITY, id->clone(id));
+ auth->merge(auth, this->ike_sa->get_auth_cfg(this->ike_sa, local), FALSE);
+ this->ike_sa->add_auth_cfg(this->ike_sa, local, auth);
+
+ return select_compliant_config(this);
+}
+
+METHOD(task_t, build_i_status, status_t,
+ private_xauth_t *this, message_t *message)
+{
+ cp_payload_t *cp;
+
+ cp = cp_payload_create_type(CONFIGURATION_V1, CFG_SET);
+ cp->add_attribute(cp,
+ configuration_attribute_create_value(XAUTH_STATUS, this->status));
+
+ message->add_payload(message, (payload_t *)cp);
+
+ return NEED_MORE;
+}
+
+METHOD(task_t, build_i, status_t,
+ private_xauth_t *this, message_t *message)
+{
+ if (!this->xauth)
+ {
+ cp_payload_t *cp;
+
+ this->xauth = load_method(this);
+ if (!this->xauth)
+ {
+ return FAILED;
+ }
+ if (this->xauth->initiate(this->xauth, &cp) != NEED_MORE)
+ {
+ return FAILED;
+ }
+ message->add_payload(message, (payload_t *)cp);
+ return NEED_MORE;
+ }
+
+ if (this->cp)
+ { /* send previously generated payload */
+ message->add_payload(message, (payload_t *)this->cp);
+ this->cp = NULL;
+ return NEED_MORE;
+ }
+ return FAILED;
+}
+
+METHOD(task_t, build_r_ack, status_t,
+ private_xauth_t *this, message_t *message)
+{
+ cp_payload_t *cp;
+
+ cp = cp_payload_create_type(CONFIGURATION_V1, CFG_ACK);
+ cp->set_identifier(cp, this->identifier);
+ cp->add_attribute(cp,
+ configuration_attribute_create_chunk(
+ CONFIGURATION_ATTRIBUTE_V1, XAUTH_STATUS, chunk_empty));
+
+ message->add_payload(message, (payload_t *)cp);
+
+ if (this->status == XAUTH_OK && allowed(this) && establish(this))
+ {
+ return SUCCESS;
+ }
+ return FAILED;
+}
+
+METHOD(task_t, process_r, status_t,
+ private_xauth_t *this, message_t *message)
+{
+ cp_payload_t *cp;
+
+ if (!this->xauth)
+ {
+ this->xauth = load_method(this);
+ if (!this->xauth)
+ { /* send empty reply */
+ return NEED_MORE;
+ }
+ }
+ cp = (cp_payload_t*)message->get_payload(message, CONFIGURATION_V1);
+ if (!cp)
+ {
+ DBG1(DBG_IKE, "configuration payload missing in XAuth request");
+ return FAILED;
+ }
+ if (cp->get_type(cp) == CFG_REQUEST)
+ {
+ switch (this->xauth->process(this->xauth, cp, &this->cp))
+ {
+ case NEED_MORE:
+ return NEED_MORE;
+ case SUCCESS:
+ case FAILED:
+ default:
+ break;
+ }
+ this->cp = NULL;
+ return NEED_MORE;
+ }
+ if (cp->get_type(cp) == CFG_SET)
+ {
+ configuration_attribute_t *attribute;
+ enumerator_t *enumerator;
+
+ enumerator = cp->create_attribute_enumerator(cp);
+ while (enumerator->enumerate(enumerator, &attribute))
+ {
+ if (attribute->get_type(attribute) == XAUTH_STATUS)
+ {
+ this->status = attribute->get_value(attribute);
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (this->status == XAUTH_OK &&
+ add_auth_cfg(this, this->xauth->get_identity(this->xauth), TRUE))
+ {
+ DBG1(DBG_IKE, "XAuth authentication of '%Y' (myself) successful",
+ this->xauth->get_identity(this->xauth));
+ }
+ else
+ {
+ DBG1(DBG_IKE, "XAuth authentication of '%Y' (myself) failed",
+ this->xauth->get_identity(this->xauth));
+ }
+ }
+ this->identifier = cp->get_identifier(cp);
+ this->public.task.build = _build_r_ack;
+ return NEED_MORE;
+}
+
+METHOD(task_t, build_r, status_t,
+ private_xauth_t *this, message_t *message)
+{
+ if (!this->cp)
+ { /* send empty reply if building data failed */
+ this->cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REPLY);
+ }
+ message->add_payload(message, (payload_t *)this->cp);
+ this->cp = NULL;
+ return NEED_MORE;
+}
+
+METHOD(task_t, process_i_status, status_t,
+ private_xauth_t *this, message_t *message)
+{
+ cp_payload_t *cp;
+
+ cp = (cp_payload_t*)message->get_payload(message, CONFIGURATION_V1);
+ if (!cp || cp->get_type(cp) != CFG_ACK)
+ {
+ DBG1(DBG_IKE, "received invalid XAUTH status response");
+ return FAILED;
+ }
+ if (this->status != XAUTH_OK)
+ {
+ DBG1(DBG_IKE, "destroying IKE_SA after failed XAuth authentication");
+ return FAILED;
+ }
+ if (!establish(this))
+ {
+ return FAILED;
+ }
+ this->ike_sa->set_condition(this->ike_sa, COND_XAUTH_AUTHENTICATED, TRUE);
+ lib->processor->queue_job(lib->processor, (job_t*)
+ adopt_children_job_create(this->ike_sa->get_id(this->ike_sa)));
+ return SUCCESS;
+}
+
+METHOD(task_t, process_i, status_t,
+ private_xauth_t *this, message_t *message)
+{
+ identification_t *id;
+ cp_payload_t *cp;
+
+ cp = (cp_payload_t*)message->get_payload(message, CONFIGURATION_V1);
+ if (!cp)
+ {
+ DBG1(DBG_IKE, "configuration payload missing in XAuth response");
+ return FAILED;
+ }
+ switch (this->xauth->process(this->xauth, cp, &this->cp))
+ {
+ case NEED_MORE:
+ return NEED_MORE;
+ case SUCCESS:
+ id = this->xauth->get_identity(this->xauth);
+ if (this->user && !id->matches(id, this->user))
+ {
+ DBG1(DBG_IKE, "XAuth username '%Y' does not match to "
+ "configured username '%Y'", id, this->user);
+ break;
+ }
+ DBG1(DBG_IKE, "XAuth authentication of '%Y' successful", id);
+ if (add_auth_cfg(this, id, FALSE) && allowed(this))
+ {
+ this->status = XAUTH_OK;
+ }
+ break;
+ case FAILED:
+ DBG1(DBG_IKE, "XAuth authentication of '%Y' failed",
+ this->xauth->get_identity(this->xauth));
+ break;
+ default:
+ return FAILED;
+ }
+ this->public.task.build = _build_i_status;
+ this->public.task.process = _process_i_status;
+ return NEED_MORE;
+}
+
+METHOD(task_t, get_type, task_type_t,
+ private_xauth_t *this)
+{
+ return TASK_XAUTH;
+}
+
+METHOD(task_t, migrate, void,
+ private_xauth_t *this, ike_sa_t *ike_sa)
+{
+ DESTROY_IF(this->xauth);
+ DESTROY_IF(this->cp);
+
+ this->ike_sa = ike_sa;
+ this->xauth = NULL;
+ this->cp = NULL;
+ this->user = NULL;
+ this->status = XAUTH_FAILED;
+
+ if (this->initiator)
+ {
+ this->public.task.build = _build_i;
+ this->public.task.process = _process_i;
+ }
+ else
+ {
+ this->public.task.build = _build_r;
+ this->public.task.process = _process_r;
+ }
+}
+
+METHOD(task_t, destroy, void,
+ private_xauth_t *this)
+{
+ DESTROY_IF(this->xauth);
+ DESTROY_IF(this->cp);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+xauth_t *xauth_create(ike_sa_t *ike_sa, bool initiator)
+{
+ private_xauth_t *this;
+
+ INIT(this,
+ .public = {
+ .task = {
+ .get_type = _get_type,
+ .migrate = _migrate,
+ .destroy = _destroy,
+ },
+ },
+ .initiator = initiator,
+ .ike_sa = ike_sa,
+ .status = XAUTH_FAILED,
+ );
+
+ if (initiator)
+ {
+ this->public.task.build = _build_i;
+ this->public.task.process = _process_i;
+ }
+ else
+ {
+ this->public.task.build = _build_r;
+ this->public.task.process = _process_r;
+ }
+ return &this->public;
+}
diff --git a/src/libcharon/sa/ikev1/tasks/xauth.h b/src/libcharon/sa/ikev1/tasks/xauth.h
new file mode 100644
index 000000000..303eb31ce
--- /dev/null
+++ b/src/libcharon/sa/ikev1/tasks/xauth.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 xauth_t xauth
+ * @{ @ingroup tasks_v1
+ */
+
+#ifndef XAUTH_H_
+#define XAUTH_H_
+
+typedef struct xauth_t xauth_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/task.h>
+
+/**
+ * Task of type TASK_XAUTH, additional authentication after main/aggressive mode.
+ */
+struct xauth_t {
+
+ /**
+ * Implements the task_t interface
+ */
+ task_t task;
+};
+
+/**
+ * Create a new xauth task.
+ *
+ * @param ike_sa IKE_SA this task works for
+ * @param initiator TRUE for initiator
+ * @return xauth task to handle by the task_manager
+ */
+xauth_t *xauth_create(ike_sa_t *ike_sa, bool initiator);
+
+#endif /** XAUTH_H_ @}*/
diff --git a/src/libcharon/sa/authenticators/eap_authenticator.c b/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c
index 5c8f0b6ce..aa0644033 100644
--- a/src/libcharon/sa/authenticators/eap_authenticator.c
+++ b/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2006-2009 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -16,7 +17,8 @@
#include "eap_authenticator.h"
#include <daemon.h>
-#include <sa/authenticators/eap/eap_method.h>
+#include <sa/ikev2/keymat_v2.h>
+#include <sa/eap/eap_method.h>
#include <encoding/payloads/auth_payload.h>
#include <encoding/payloads/eap_payload.h>
@@ -185,9 +187,9 @@ static eap_payload_t* server_initiate_eap(private_eap_authenticator_t *this,
if (this->method)
{
action = "initiating";
- type = this->method->get_type(this->method, &vendor);
if (this->method->initiate(this->method, &out) == NEED_MORE)
{
+ type = this->method->get_type(this->method, &vendor);
if (vendor)
{
DBG1(DBG_IKE, "initiating EAP vendor type %d-%d method (id 0x%02X)",
@@ -200,6 +202,8 @@ static eap_payload_t* server_initiate_eap(private_eap_authenticator_t *this,
}
return out;
}
+ /* type might have changed for virtual methods */
+ type = this->method->get_type(this->method, &vendor);
}
if (vendor)
{
@@ -232,9 +236,10 @@ static void replace_eap_identity(private_eap_authenticator_t *this)
static eap_payload_t* server_process_eap(private_eap_authenticator_t *this,
eap_payload_t *in)
{
- eap_type_t type, received_type;
- u_int32_t vendor, received_vendor;
+ eap_type_t type, received_type, conf_type;
+ u_int32_t vendor, received_vendor, conf_vendor;
eap_payload_t *out;
+ auth_cfg_t *auth;
if (in->get_code(in) != EAP_RESPONSE)
{
@@ -249,15 +254,25 @@ static eap_payload_t* server_process_eap(private_eap_authenticator_t *this,
{
if (received_vendor == 0 && received_type == EAP_NAK)
{
- DBG1(DBG_IKE, "received %N, sending %N",
- eap_type_names, EAP_NAK, eap_code_names, EAP_FAILURE);
+ auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
+ conf_type = (uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE);
+ conf_vendor = (uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR);
+ if ((type == EAP_IDENTITY && !vendor) ||
+ (type == conf_type && vendor == conf_vendor))
+ {
+ DBG1(DBG_IKE, "received %N, sending %N",
+ eap_type_names, EAP_NAK, eap_code_names, EAP_FAILURE);
+ return eap_payload_create_code(EAP_FAILURE,
+ in->get_identifier(in));
+ }
+ /* virtual methods handle NAKs in process() */
}
else
{
DBG1(DBG_IKE, "received invalid EAP response, sending %N",
eap_code_names, EAP_FAILURE);
+ return eap_payload_create_code(EAP_FAILURE, in->get_identifier(in));
}
- return eap_payload_create_code(EAP_FAILURE, in->get_identifier(in));
}
switch (this->method->process(this->method, in, &out))
@@ -301,6 +316,8 @@ static eap_payload_t* server_process_eap(private_eap_authenticator_t *this,
return eap_payload_create_code(EAP_SUCCESS, in->get_identifier(in));
case FAILED:
default:
+ /* type might have changed for virtual methods */
+ type = this->method->get_type(this->method, &vendor);
if (vendor)
{
DBG1(DBG_IKE, "EAP vendor specific method %d-%d failed for "
@@ -323,8 +340,8 @@ static eap_payload_t* server_process_eap(private_eap_authenticator_t *this,
static eap_payload_t* client_process_eap(private_eap_authenticator_t *this,
eap_payload_t *in)
{
- eap_type_t type;
- u_int32_t vendor;
+ eap_type_t type, conf_type;
+ u_int32_t vendor, conf_vendor;
auth_cfg_t *auth;
eap_payload_t *out;
identification_t *id;
@@ -356,27 +373,49 @@ static eap_payload_t* client_process_eap(private_eap_authenticator_t *this,
this->method->destroy(this->method);
this->method = NULL;
}
+ /* FIXME: sending a Nak is not correct here as EAP_IDENTITY (1) is no
+ * EAP method (types 3-253, 255) */
DBG1(DBG_IKE, "%N not supported, sending EAP_NAK",
eap_type_names, type);
- return eap_payload_create_nak(in->get_identifier(in));
+ return eap_payload_create_nak(in->get_identifier(in), 0, 0, FALSE);
}
if (this->method == NULL)
{
if (vendor)
{
DBG1(DBG_IKE, "server requested vendor specific EAP method %d-%d ",
- "(id 0x%02X)", type, vendor, in->get_identifier(in));
+ "(id 0x%02X)", type, vendor, in->get_identifier(in));
}
else
{
DBG1(DBG_IKE, "server requested %N authentication (id 0x%02X)",
eap_type_names, type, in->get_identifier(in));
}
+ auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
+ conf_type = (uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE);
+ conf_vendor = (uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR);
+ if (conf_type != EAP_NAK &&
+ (conf_type != type || conf_vendor != vendor))
+ {
+ if (conf_vendor)
+ {
+ DBG1(DBG_IKE, "requesting EAP method %d-%d, sending EAP_NAK",
+ conf_type, conf_vendor);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "requesting %N authentication, sending EAP_NAK",
+ eap_type_names, conf_type);
+ }
+ return eap_payload_create_nak(in->get_identifier(in), conf_type,
+ conf_vendor, in->is_expanded(in));
+ }
this->method = load_method(this, type, vendor, EAP_PEER);
if (!this->method)
{
DBG1(DBG_IKE, "EAP method not supported, sending EAP_NAK");
- return eap_payload_create_nak(in->get_identifier(in));
+ return eap_payload_create_nak(in->get_identifier(in), 0, 0,
+ in->is_expanded(in));
}
}
@@ -408,7 +447,7 @@ static bool verify_auth(private_eap_authenticator_t *this, message_t *message,
chunk_t auth_data, recv_auth_data;
identification_t *other_id;
auth_cfg_t *auth;
- keymat_t *keymat;
+ keymat_v2_t *keymat;
auth_payload = (auth_payload_t*)message->get_payload(message,
AUTHENTICATION);
@@ -418,9 +457,12 @@ static bool verify_auth(private_eap_authenticator_t *this, message_t *message,
return FALSE;
}
other_id = this->ike_sa->get_other_id(this->ike_sa);
- keymat = this->ike_sa->get_keymat(this->ike_sa);
- auth_data = keymat->get_psk_sig(keymat, TRUE, init, nonce,
- this->msk, other_id, this->reserved);
+ keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa);
+ if (!keymat->get_psk_sig(keymat, TRUE, init, nonce,
+ this->msk, other_id, this->reserved, &auth_data))
+ {
+ return FALSE;
+ }
recv_auth_data = auth_payload->get_data(auth_payload);
if (!auth_data.len || !chunk_equals(auth_data, recv_auth_data))
{
@@ -442,27 +484,31 @@ static bool verify_auth(private_eap_authenticator_t *this, message_t *message,
/**
* Build AUTH payload
*/
-static void build_auth(private_eap_authenticator_t *this, message_t *message,
+static bool build_auth(private_eap_authenticator_t *this, message_t *message,
chunk_t nonce, chunk_t init)
{
auth_payload_t *auth_payload;
identification_t *my_id;
chunk_t auth_data;
- keymat_t *keymat;
+ keymat_v2_t *keymat;
my_id = this->ike_sa->get_my_id(this->ike_sa);
- keymat = this->ike_sa->get_keymat(this->ike_sa);
+ keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa);
DBG1(DBG_IKE, "authentication of '%Y' (myself) with %N",
my_id, auth_class_names, AUTH_CLASS_EAP);
- auth_data = keymat->get_psk_sig(keymat, FALSE, init, nonce,
- this->msk, my_id, this->reserved);
+ if (!keymat->get_psk_sig(keymat, FALSE, init, nonce,
+ this->msk, my_id, this->reserved, &auth_data))
+ {
+ return FALSE;
+ }
auth_payload = auth_payload_create();
auth_payload->set_auth_method(auth_payload, AUTH_PSK);
auth_payload->set_data(auth_payload, auth_data);
message->add_payload(message, (payload_t*)auth_payload);
chunk_free(&auth_data);
+ return TRUE;
}
METHOD(authenticator_t, process_server, status_t,
@@ -512,9 +558,9 @@ METHOD(authenticator_t, build_server, status_t,
}
return NEED_MORE;
}
- if (this->eap_complete && this->auth_complete)
+ if (this->eap_complete && this->auth_complete &&
+ build_auth(this, message, this->received_nonce, this->sent_init))
{
- build_auth(this, message, this->received_nonce, this->sent_init);
return SUCCESS;
}
return FAILED;
@@ -610,9 +656,9 @@ METHOD(authenticator_t, build_client, status_t,
this->eap_payload = NULL;
return NEED_MORE;
}
- if (this->eap_complete)
+ if (this->eap_complete &&
+ build_auth(this, message, this->received_nonce, this->sent_init))
{
- build_auth(this, message, this->received_nonce, this->sent_init);
return NEED_MORE;
}
return NEED_MORE;
@@ -695,4 +741,3 @@ eap_authenticator_t *eap_authenticator_create_verifier(ike_sa_t *ike_sa,
return &this->public;
}
-
diff --git a/src/libcharon/sa/authenticators/eap_authenticator.h b/src/libcharon/sa/ikev2/authenticators/eap_authenticator.h
index 726411a18..d81ebd562 100644
--- a/src/libcharon/sa/authenticators/eap_authenticator.h
+++ b/src/libcharon/sa/ikev2/authenticators/eap_authenticator.h
@@ -15,7 +15,7 @@
/**
* @defgroup eap_authenticator eap_authenticator
- * @{ @ingroup authenticators
+ * @{ @ingroup authenticators_v2
*/
#ifndef EAP_AUTHENTICATOR_H_
@@ -23,7 +23,7 @@
typedef struct eap_authenticator_t eap_authenticator_t;
-#include <sa/authenticators/authenticator.h>
+#include <sa/authenticator.h>
/**
* Implementation of authenticator_t using EAP authentication.
diff --git a/src/libcharon/sa/authenticators/psk_authenticator.c b/src/libcharon/sa/ikev2/authenticators/psk_authenticator.c
index 21fc0f9b8..997efe359 100644
--- a/src/libcharon/sa/authenticators/psk_authenticator.c
+++ b/src/libcharon/sa/ikev2/authenticators/psk_authenticator.c
@@ -18,6 +18,7 @@
#include <daemon.h>
#include <encoding/payloads/auth_payload.h>
+#include <sa/ikev2/keymat_v2.h>
typedef struct private_psk_authenticator_t private_psk_authenticator_t;
@@ -59,9 +60,9 @@ METHOD(authenticator_t, build, status_t,
auth_payload_t *auth_payload;
shared_key_t *key;
chunk_t auth_data;
- keymat_t *keymat;
+ keymat_v2_t *keymat;
- keymat = this->ike_sa->get_keymat(this->ike_sa);
+ keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa);
my_id = this->ike_sa->get_my_id(this->ike_sa);
other_id = this->ike_sa->get_other_id(this->ike_sa);
DBG1(DBG_IKE, "authentication of '%Y' (myself) with %N",
@@ -72,8 +73,12 @@ METHOD(authenticator_t, build, status_t,
DBG1(DBG_IKE, "no shared key found for '%Y' - '%Y'", my_id, other_id);
return NOT_FOUND;
}
- auth_data = keymat->get_psk_sig(keymat, FALSE, this->ike_sa_init,
- this->nonce, key->get_key(key), my_id, this->reserved);
+ if (!keymat->get_psk_sig(keymat, FALSE, this->ike_sa_init, this->nonce,
+ key->get_key(key), my_id, this->reserved, &auth_data))
+ {
+ key->destroy(key);
+ return FAILED;
+ }
key->destroy(key);
DBG2(DBG_IKE, "successfully created shared key MAC");
auth_payload = auth_payload_create();
@@ -96,14 +101,14 @@ METHOD(authenticator_t, process, status_t,
enumerator_t *enumerator;
bool authenticated = FALSE;
int keys_found = 0;
- keymat_t *keymat;
+ keymat_v2_t *keymat;
auth_payload = (auth_payload_t*)message->get_payload(message, AUTHENTICATION);
if (!auth_payload)
{
return FAILED;
}
- keymat = this->ike_sa->get_keymat(this->ike_sa);
+ keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa);
recv_auth_data = auth_payload->get_data(auth_payload);
my_id = this->ike_sa->get_my_id(this->ike_sa);
other_id = this->ike_sa->get_other_id(this->ike_sa);
@@ -113,8 +118,11 @@ METHOD(authenticator_t, process, status_t,
{
keys_found++;
- auth_data = keymat->get_psk_sig(keymat, TRUE, this->ike_sa_init,
- this->nonce, key->get_key(key), other_id, this->reserved);
+ if (!keymat->get_psk_sig(keymat, TRUE, this->ike_sa_init, this->nonce,
+ key->get_key(key), other_id, this->reserved, &auth_data))
+ {
+ continue;
+ }
if (auth_data.len && chunk_equals(auth_data, recv_auth_data))
{
DBG1(DBG_IKE, "authentication of '%Y' with %N successful",
@@ -201,4 +209,3 @@ psk_authenticator_t *psk_authenticator_create_verifier(ike_sa_t *ike_sa,
return &this->public;
}
-
diff --git a/src/libcharon/sa/authenticators/psk_authenticator.h b/src/libcharon/sa/ikev2/authenticators/psk_authenticator.h
index 8cf1a0f98..91c534145 100644
--- a/src/libcharon/sa/authenticators/psk_authenticator.h
+++ b/src/libcharon/sa/ikev2/authenticators/psk_authenticator.h
@@ -15,7 +15,7 @@
/**
* @defgroup psk_authenticator psk_authenticator
- * @{ @ingroup authenticators
+ * @{ @ingroup authenticators_v2
*/
#ifndef PSK_AUTHENTICATOR_H_
@@ -23,7 +23,7 @@
typedef struct psk_authenticator_t psk_authenticator_t;
-#include <sa/authenticators/authenticator.h>
+#include <sa/authenticator.h>
/**
* Implementation of authenticator_t using pre-shared keys.
diff --git a/src/libcharon/sa/authenticators/pubkey_authenticator.c b/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c
index 247891670..5ceff40ba 100644
--- a/src/libcharon/sa/authenticators/pubkey_authenticator.c
+++ b/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c
@@ -19,6 +19,7 @@
#include <daemon.h>
#include <encoding/payloads/auth_payload.h>
+#include <sa/ikev2/keymat_v2.h>
typedef struct private_pubkey_authenticator_t private_pubkey_authenticator_t;
@@ -56,7 +57,7 @@ struct private_pubkey_authenticator_t {
METHOD(authenticator_t, build, status_t,
private_pubkey_authenticator_t *this, message_t *message)
{
- chunk_t octets, auth_data;
+ chunk_t octets = chunk_empty, auth_data;
status_t status = FAILED;
private_key_t *private;
identification_t *id;
@@ -64,7 +65,7 @@ METHOD(authenticator_t, build, status_t,
auth_payload_t *auth_payload;
auth_method_t auth_method;
signature_scheme_t scheme;
- keymat_t *keymat;
+ keymat_v2_t *keymat;
id = this->ike_sa->get_my_id(this->ike_sa);
auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
@@ -110,10 +111,10 @@ METHOD(authenticator_t, build, status_t,
key_type_names, private->get_type(private));
return status;
}
- keymat = this->ike_sa->get_keymat(this->ike_sa);
- octets = keymat->get_auth_octets(keymat, FALSE, this->ike_sa_init,
- this->nonce, id, this->reserved);
- if (private->sign(private, scheme, octets, &auth_data))
+ keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa);
+ if (keymat->get_auth_octets(keymat, FALSE, this->ike_sa_init,
+ this->nonce, id, this->reserved, &octets) &&
+ private->sign(private, scheme, octets, &auth_data))
{
auth_payload = auth_payload_create();
auth_payload->set_auth_method(auth_payload, auth_method);
@@ -144,7 +145,7 @@ METHOD(authenticator_t, process, status_t,
key_type_t key_type = KEY_ECDSA;
signature_scheme_t scheme;
status_t status = NOT_FOUND;
- keymat_t *keymat;
+ keymat_v2_t *keymat;
auth_payload = (auth_payload_t*)message->get_payload(message, AUTHENTICATION);
if (!auth_payload)
@@ -174,9 +175,12 @@ METHOD(authenticator_t, process, status_t,
}
auth_data = auth_payload->get_data(auth_payload);
id = this->ike_sa->get_other_id(this->ike_sa);
- keymat = this->ike_sa->get_keymat(this->ike_sa);
- octets = keymat->get_auth_octets(keymat, TRUE, this->ike_sa_init,
- this->nonce, id, this->reserved);
+ keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa);
+ if (!keymat->get_auth_octets(keymat, TRUE, this->ike_sa_init,
+ this->nonce, id, this->reserved, &octets))
+ {
+ return FAILED;
+ }
auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
enumerator = lib->credmgr->create_public_enumerator(lib->credmgr,
key_type, id, auth);
diff --git a/src/libcharon/sa/authenticators/pubkey_authenticator.h b/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.h
index 4c3937ecc..82bfea23b 100644
--- a/src/libcharon/sa/authenticators/pubkey_authenticator.h
+++ b/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.h
@@ -16,7 +16,7 @@
/**
* @defgroup pubkey_authenticator pubkey_authenticator
- * @{ @ingroup authenticators
+ * @{ @ingroup authenticators_v2
*/
#ifndef PUBKEY_AUTHENTICATOR_H_
@@ -24,7 +24,7 @@
typedef struct pubkey_authenticator_t pubkey_authenticator_t;
-#include <sa/authenticators/authenticator.h>
+#include <sa/authenticator.h>
/**
* Implementation of authenticator_t using public key authenitcation.
diff --git a/src/libcharon/sa/connect_manager.c b/src/libcharon/sa/ikev2/connect_manager.c
index 7b6ca430f..5fdcea1ab 100644
--- a/src/libcharon/sa/connect_manager.c
+++ b/src/libcharon/sa/ikev2/connect_manager.c
@@ -839,7 +839,10 @@ static chunk_t build_signature(private_connect_manager_t *this,
/* signature = SHA1( MID | ME_CONNECTID | ME_ENDPOINT | ME_CONNECTKEY ) */
sig_chunk = chunk_cat("cccc", mid_chunk, check->connect_id,
check->endpoint_raw, key_chunk);
- this->hasher->allocate_hash(this->hasher, sig_chunk, &sig_hash);
+ if (!this->hasher->allocate_hash(this->hasher, sig_chunk, &sig_hash))
+ {
+ sig_hash = chunk_empty;
+ }
DBG3(DBG_IKE, "sig_chunk %#B", &sig_chunk);
DBG3(DBG_IKE, "sig_hash %#B", &sig_hash);
@@ -919,8 +922,10 @@ static void update_checklist_state(private_connect_manager_t *this,
&checklist->connect_id);
callback_data_t *data = callback_data_create(this, checklist->connect_id);
- job_t *job = (job_t*)callback_job_create((callback_job_cb_t)initiator_finish, data, (callback_job_cleanup_t)callback_data_destroy, NULL);
- lib->scheduler->schedule_job_ms(lib->scheduler, job, ME_WAIT_TO_FINISH);
+ lib->scheduler->schedule_job_ms(lib->scheduler,
+ (job_t*)callback_job_create((callback_job_cb_t)initiator_finish,
+ data, (callback_job_cleanup_t)callback_data_destroy, NULL),
+ ME_WAIT_TO_FINISH);
checklist->is_finishing = TRUE;
}
@@ -1007,8 +1012,12 @@ retransmit_end:
*/
static void queue_retransmission(private_connect_manager_t *this, check_list_t *checklist, endpoint_pair_t *pair)
{
- callback_data_t *data = retransmit_data_create(this, checklist->connect_id, pair->id);
- job_t *job = (job_t*)callback_job_create((callback_job_cb_t)retransmit, data, (callback_job_cleanup_t)callback_data_destroy, NULL);
+ callback_data_t *data;
+ job_t *job;
+
+ data = retransmit_data_create(this, checklist->connect_id, pair->id);
+ job = (job_t*)callback_job_create((callback_job_cb_t)retransmit, data,
+ (callback_job_cleanup_t)callback_data_destroy, NULL);
u_int32_t retransmission = pair->retransmitted + 1;
u_int32_t rto = ME_INTERVAL;
@@ -1028,14 +1037,15 @@ static void queue_retransmission(private_connect_manager_t *this, check_list_t *
static void send_check(private_connect_manager_t *this, check_list_t *checklist,
check_t *check, endpoint_pair_t *pair, bool request)
{
- message_t *message = message_create();
+ message_t *message = message_create(IKEV2_MAJOR_VERSION, IKEV2_MINOR_VERSION);
message->set_message_id(message, check->mid);
message->set_exchange_type(message, INFORMATIONAL);
message->set_request(message, request);
message->set_destination(message, check->dst->clone(check->dst));
message->set_source(message, check->src->clone(check->src));
- ike_sa_id_t *ike_sa_id = ike_sa_id_create(0, 0, request);
+ ike_sa_id_t *ike_sa_id = ike_sa_id_create(IKEV2_MAJOR_VERSION, 0, 0,
+ request);
message->set_ike_sa_id(message, ike_sa_id);
ike_sa_id->destroy(ike_sa_id);
@@ -1154,10 +1164,12 @@ static job_requeue_t sender(callback_data_t *data)
/**
* Schedules checks for a checklist (time in ms)
*/
-static void schedule_checks(private_connect_manager_t *this, check_list_t *checklist, u_int32_t time)
+static void schedule_checks(private_connect_manager_t *this,
+ check_list_t *checklist, u_int32_t time)
{
callback_data_t *data = callback_data_create(this, checklist->connect_id);
- checklist->sender = (job_t*)callback_job_create((callback_job_cb_t)sender, data, (callback_job_cleanup_t)callback_data_destroy, NULL);
+ checklist->sender = (job_t*)callback_job_create((callback_job_cb_t)sender,
+ data, (callback_job_cleanup_t)callback_data_destroy, NULL);
lib->scheduler->schedule_job_ms(lib->scheduler, checklist->sender, time);
}
@@ -1209,12 +1221,15 @@ static void finish_checks(private_connect_manager_t *this, check_list_t *checkli
if (get_initiated_by_ids(this, checklist->initiator.id,
checklist->responder.id, &initiated) == SUCCESS)
{
+ callback_job_t *job;
+
remove_checklist(this, checklist);
remove_initiated(this, initiated);
initiate_data_t *data = initiate_data_create(checklist, initiated);
- job_t *job = (job_t*)callback_job_create((callback_job_cb_t)initiate_mediated, data, (callback_job_cleanup_t)initiate_data_destroy, NULL);
- lib->processor->queue_job(lib->processor, job);
+ job = callback_job_create((callback_job_cb_t)initiate_mediated,
+ data, (callback_job_cleanup_t)initiate_data_destroy, NULL);
+ lib->processor->queue_job(lib->processor, (job_t*)job);
return;
}
else
diff --git a/src/libcharon/sa/connect_manager.h b/src/libcharon/sa/ikev2/connect_manager.h
index 8fa8ff697..e667e1f70 100644
--- a/src/libcharon/sa/connect_manager.h
+++ b/src/libcharon/sa/ikev2/connect_manager.h
@@ -15,7 +15,7 @@
/**
* @defgroup connect_manager connect_manager
- * @{ @ingroup sa
+ * @{ @ingroup ikev2
*/
#ifndef CONNECT_MANAGER_H_
diff --git a/src/libcharon/sa/ikev2/keymat_v2.c b/src/libcharon/sa/ikev2/keymat_v2.c
new file mode 100644
index 000000000..4d0683f0a
--- /dev/null
+++ b/src/libcharon/sa/ikev2/keymat_v2.c
@@ -0,0 +1,687 @@
+/*
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "keymat_v2.h"
+
+#include <daemon.h>
+#include <crypto/prf_plus.h>
+
+typedef struct private_keymat_v2_t private_keymat_v2_t;
+
+/**
+ * Private data of an keymat_t object.
+ */
+struct private_keymat_v2_t {
+
+ /**
+ * Public keymat_v2_t interface.
+ */
+ keymat_v2_t public;
+
+ /**
+ * IKE_SA Role, initiator or responder
+ */
+ bool initiator;
+
+ /**
+ * inbound AEAD
+ */
+ aead_t *aead_in;
+
+ /**
+ * outbound AEAD
+ */
+ aead_t *aead_out;
+
+ /**
+ * General purpose PRF
+ */
+ prf_t *prf;
+
+ /**
+ * Negotiated PRF algorithm
+ */
+ pseudo_random_function_t prf_alg;
+
+ /**
+ * Key to derive key material from for CHILD_SAs, rekeying
+ */
+ chunk_t skd;
+
+ /**
+ * Key to build outging authentication data (SKp)
+ */
+ chunk_t skp_build;
+
+ /**
+ * Key to verify incoming authentication data (SKp)
+ */
+ chunk_t skp_verify;
+};
+
+METHOD(keymat_t, get_version, ike_version_t,
+ private_keymat_v2_t *this)
+{
+ return IKEV2;
+}
+
+METHOD(keymat_t, create_dh, diffie_hellman_t*,
+ private_keymat_v2_t *this, diffie_hellman_group_t group)
+{
+ return lib->crypto->create_dh(lib->crypto, group);
+}
+
+METHOD(keymat_t, create_nonce_gen, nonce_gen_t*,
+ private_keymat_v2_t *this)
+{
+ return lib->crypto->create_nonce_gen(lib->crypto);
+}
+
+/**
+ * Derive IKE keys for a combined AEAD algorithm
+ */
+static bool derive_ike_aead(private_keymat_v2_t *this, u_int16_t alg,
+ u_int16_t key_size, prf_plus_t *prf_plus)
+{
+ aead_t *aead_i, *aead_r;
+ chunk_t key = chunk_empty;
+
+ /* SK_ei/SK_er used for encryption */
+ aead_i = lib->crypto->create_aead(lib->crypto, alg, key_size / 8);
+ aead_r = lib->crypto->create_aead(lib->crypto, alg, key_size / 8);
+ if (aead_i == NULL || aead_r == NULL)
+ {
+ DBG1(DBG_IKE, "%N %N (key size %d) not supported!",
+ transform_type_names, ENCRYPTION_ALGORITHM,
+ encryption_algorithm_names, alg, key_size);
+ goto failure;
+ }
+ key_size = aead_i->get_key_size(aead_i);
+ if (key_size != aead_r->get_key_size(aead_r))
+ {
+ goto failure;
+ }
+ if (!prf_plus->allocate_bytes(prf_plus, key_size, &key))
+ {
+ goto failure;
+ }
+ DBG4(DBG_IKE, "Sk_ei secret %B", &key);
+ if (!aead_i->set_key(aead_i, key))
+ {
+ goto failure;
+ }
+ chunk_clear(&key);
+
+ if (!prf_plus->allocate_bytes(prf_plus, key_size, &key))
+ {
+ goto failure;
+ }
+ DBG4(DBG_IKE, "Sk_er secret %B", &key);
+ if (!aead_r->set_key(aead_r, key))
+ {
+ goto failure;
+ }
+
+ if (this->initiator)
+ {
+ this->aead_in = aead_r;
+ this->aead_out = aead_i;
+ }
+ else
+ {
+ this->aead_in = aead_i;
+ this->aead_out = aead_r;
+ }
+ aead_i = aead_r = NULL;
+
+failure:
+ DESTROY_IF(aead_i);
+ DESTROY_IF(aead_r);
+ chunk_clear(&key);
+ return this->aead_in && this->aead_out;
+}
+
+/**
+ * Derive IKE keys for traditional encryption and MAC algorithms
+ */
+static bool derive_ike_traditional(private_keymat_v2_t *this, u_int16_t enc_alg,
+ u_int16_t enc_size, u_int16_t int_alg, prf_plus_t *prf_plus)
+{
+ crypter_t *crypter_i = NULL, *crypter_r = NULL;
+ signer_t *signer_i, *signer_r;
+ size_t key_size;
+ chunk_t key = chunk_empty;
+
+ signer_i = lib->crypto->create_signer(lib->crypto, int_alg);
+ signer_r = lib->crypto->create_signer(lib->crypto, int_alg);
+ crypter_i = lib->crypto->create_crypter(lib->crypto, enc_alg, enc_size / 8);
+ crypter_r = lib->crypto->create_crypter(lib->crypto, enc_alg, enc_size / 8);
+ if (signer_i == NULL || signer_r == NULL)
+ {
+ DBG1(DBG_IKE, "%N %N not supported!",
+ transform_type_names, INTEGRITY_ALGORITHM,
+ integrity_algorithm_names, int_alg);
+ goto failure;
+ }
+ if (crypter_i == NULL || crypter_r == NULL)
+ {
+ DBG1(DBG_IKE, "%N %N (key size %d) not supported!",
+ transform_type_names, ENCRYPTION_ALGORITHM,
+ encryption_algorithm_names, enc_alg, enc_size);
+ goto failure;
+ }
+
+ /* SK_ai/SK_ar used for integrity protection */
+ key_size = signer_i->get_key_size(signer_i);
+
+ if (!prf_plus->allocate_bytes(prf_plus, key_size, &key))
+ {
+ goto failure;
+ }
+ DBG4(DBG_IKE, "Sk_ai secret %B", &key);
+ if (!signer_i->set_key(signer_i, key))
+ {
+ goto failure;
+ }
+ chunk_clear(&key);
+
+ if (!prf_plus->allocate_bytes(prf_plus, key_size, &key))
+ {
+ goto failure;
+ }
+ DBG4(DBG_IKE, "Sk_ar secret %B", &key);
+ if (!signer_r->set_key(signer_r, key))
+ {
+ goto failure;
+ }
+ chunk_clear(&key);
+
+ /* SK_ei/SK_er used for encryption */
+ key_size = crypter_i->get_key_size(crypter_i);
+
+ if (!prf_plus->allocate_bytes(prf_plus, key_size, &key))
+ {
+ goto failure;
+ }
+ DBG4(DBG_IKE, "Sk_ei secret %B", &key);
+ if (!crypter_i->set_key(crypter_i, key))
+ {
+ goto failure;
+ }
+ chunk_clear(&key);
+
+ if (!prf_plus->allocate_bytes(prf_plus, key_size, &key))
+ {
+ goto failure;
+ }
+ DBG4(DBG_IKE, "Sk_er secret %B", &key);
+ if (!crypter_r->set_key(crypter_r, key))
+ {
+ goto failure;
+ }
+
+ if (this->initiator)
+ {
+ this->aead_in = aead_create(crypter_r, signer_r);
+ this->aead_out = aead_create(crypter_i, signer_i);
+ }
+ else
+ {
+ this->aead_in = aead_create(crypter_i, signer_i);
+ this->aead_out = aead_create(crypter_r, signer_r);
+ }
+ signer_i = signer_r = NULL;
+ crypter_i = crypter_r = NULL;
+
+failure:
+ chunk_clear(&key);
+ DESTROY_IF(signer_i);
+ DESTROY_IF(signer_r);
+ DESTROY_IF(crypter_i);
+ DESTROY_IF(crypter_r);
+ return this->aead_in && this->aead_out;
+}
+
+METHOD(keymat_v2_t, derive_ike_keys, bool,
+ private_keymat_v2_t *this, proposal_t *proposal, diffie_hellman_t *dh,
+ chunk_t nonce_i, chunk_t nonce_r, ike_sa_id_t *id,
+ pseudo_random_function_t rekey_function, chunk_t rekey_skd)
+{
+ chunk_t skeyseed, key, secret, full_nonce, fixed_nonce, prf_plus_seed;
+ chunk_t spi_i, spi_r;
+ prf_plus_t *prf_plus = NULL;
+ u_int16_t alg, key_size, int_alg;
+ prf_t *rekey_prf = NULL;
+
+ spi_i = chunk_alloca(sizeof(u_int64_t));
+ spi_r = chunk_alloca(sizeof(u_int64_t));
+
+ if (dh->get_shared_secret(dh, &secret) != SUCCESS)
+ {
+ return FALSE;
+ }
+
+ /* Create SAs general purpose PRF first, we may use it here */
+ if (!proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL))
+ {
+ DBG1(DBG_IKE, "no %N selected",
+ transform_type_names, PSEUDO_RANDOM_FUNCTION);
+ return FALSE;
+ }
+ this->prf_alg = alg;
+ this->prf = lib->crypto->create_prf(lib->crypto, alg);
+ if (this->prf == NULL)
+ {
+ DBG1(DBG_IKE, "%N %N not supported!",
+ transform_type_names, PSEUDO_RANDOM_FUNCTION,
+ pseudo_random_function_names, alg);
+ return FALSE;
+ }
+ DBG4(DBG_IKE, "shared Diffie Hellman secret %B", &secret);
+ /* full nonce is used as seed for PRF+ ... */
+ full_nonce = chunk_cat("cc", nonce_i, nonce_r);
+ /* but the PRF may need a fixed key which only uses the first bytes of
+ * the nonces. */
+ switch (alg)
+ {
+ case PRF_AES128_XCBC:
+ /* while rfc4434 defines variable keys for AES-XCBC, rfc3664 does
+ * not and therefore fixed key semantics apply to XCBC for key
+ * derivation. */
+ case PRF_CAMELLIA128_XCBC:
+ /* draft-kanno-ipsecme-camellia-xcbc refers to rfc 4434, we
+ * assume fixed key length. */
+ key_size = this->prf->get_key_size(this->prf)/2;
+ nonce_i.len = min(nonce_i.len, key_size);
+ nonce_r.len = min(nonce_r.len, key_size);
+ break;
+ default:
+ /* all other algorithms use variable key length, full nonce */
+ break;
+ }
+ fixed_nonce = chunk_cat("cc", nonce_i, nonce_r);
+ *((u_int64_t*)spi_i.ptr) = id->get_initiator_spi(id);
+ *((u_int64_t*)spi_r.ptr) = id->get_responder_spi(id);
+ prf_plus_seed = chunk_cat("ccc", full_nonce, spi_i, spi_r);
+
+ /* KEYMAT = prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr)
+ *
+ * if we are rekeying, SKEYSEED is built on another way
+ */
+ if (rekey_function == PRF_UNDEFINED) /* not rekeying */
+ {
+ /* SKEYSEED = prf(Ni | Nr, g^ir) */
+ if (this->prf->set_key(this->prf, fixed_nonce) &&
+ this->prf->allocate_bytes(this->prf, secret, &skeyseed) &&
+ this->prf->set_key(this->prf, skeyseed))
+ {
+ prf_plus = prf_plus_create(this->prf, TRUE, prf_plus_seed);
+ }
+ }
+ else
+ {
+ /* SKEYSEED = prf(SK_d (old), [g^ir (new)] | Ni | Nr)
+ * use OLD SAs PRF functions for both prf_plus and prf */
+ rekey_prf = lib->crypto->create_prf(lib->crypto, rekey_function);
+ if (!rekey_prf)
+ {
+ DBG1(DBG_IKE, "PRF of old SA %N not supported!",
+ pseudo_random_function_names, rekey_function);
+ chunk_free(&full_nonce);
+ chunk_free(&fixed_nonce);
+ chunk_clear(&prf_plus_seed);
+ return FALSE;
+ }
+ secret = chunk_cat("mc", secret, full_nonce);
+ if (rekey_prf->set_key(rekey_prf, rekey_skd) &&
+ rekey_prf->allocate_bytes(rekey_prf, secret, &skeyseed) &&
+ rekey_prf->set_key(rekey_prf, skeyseed))
+ {
+ prf_plus = prf_plus_create(rekey_prf, TRUE, prf_plus_seed);
+ }
+ }
+ DBG4(DBG_IKE, "SKEYSEED %B", &skeyseed);
+
+ chunk_clear(&skeyseed);
+ chunk_clear(&secret);
+ chunk_free(&full_nonce);
+ chunk_free(&fixed_nonce);
+ chunk_clear(&prf_plus_seed);
+
+ if (!prf_plus)
+ {
+ goto failure;
+ }
+
+ /* KEYMAT = SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr */
+
+ /* SK_d is used for generating CHILD_SA key mat => store for later use */
+ key_size = this->prf->get_key_size(this->prf);
+ if (!prf_plus->allocate_bytes(prf_plus, key_size, &this->skd))
+ {
+ goto failure;
+ }
+ DBG4(DBG_IKE, "Sk_d secret %B", &this->skd);
+
+ if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg, &key_size))
+ {
+ DBG1(DBG_IKE, "no %N selected",
+ transform_type_names, ENCRYPTION_ALGORITHM);
+ goto failure;
+ }
+
+ if (encryption_algorithm_is_aead(alg))
+ {
+ if (!derive_ike_aead(this, alg, key_size, prf_plus))
+ {
+ goto failure;
+ }
+ }
+ else
+ {
+ if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
+ &int_alg, NULL))
+ {
+ DBG1(DBG_IKE, "no %N selected",
+ transform_type_names, INTEGRITY_ALGORITHM);
+ goto failure;
+ }
+ if (!derive_ike_traditional(this, alg, key_size, int_alg, prf_plus))
+ {
+ goto failure;
+ }
+ }
+
+ /* SK_pi/SK_pr used for authentication => stored for later */
+ key_size = this->prf->get_key_size(this->prf);
+ if (!prf_plus->allocate_bytes(prf_plus, key_size, &key))
+ {
+ goto failure;
+ }
+ DBG4(DBG_IKE, "Sk_pi secret %B", &key);
+ if (this->initiator)
+ {
+ this->skp_build = key;
+ }
+ else
+ {
+ this->skp_verify = key;
+ }
+ if (!prf_plus->allocate_bytes(prf_plus, key_size, &key))
+ {
+ goto failure;
+ }
+ DBG4(DBG_IKE, "Sk_pr secret %B", &key);
+ if (this->initiator)
+ {
+ this->skp_verify = key;
+ }
+ else
+ {
+ this->skp_build = key;
+ }
+
+ /* all done, prf_plus not needed anymore */
+failure:
+ DESTROY_IF(prf_plus);
+ DESTROY_IF(rekey_prf);
+
+ return this->skp_build.len && this->skp_verify.len;
+}
+
+METHOD(keymat_v2_t, derive_child_keys, bool,
+ private_keymat_v2_t *this, proposal_t *proposal, diffie_hellman_t *dh,
+ chunk_t nonce_i, chunk_t nonce_r, chunk_t *encr_i, chunk_t *integ_i,
+ chunk_t *encr_r, chunk_t *integ_r)
+{
+ u_int16_t enc_alg, int_alg, enc_size = 0, int_size = 0;
+ chunk_t seed, secret = chunk_empty;
+ prf_plus_t *prf_plus;
+
+ if (dh)
+ {
+ if (dh->get_shared_secret(dh, &secret) != SUCCESS)
+ {
+ return FALSE;
+ }
+ DBG4(DBG_CHD, "DH secret %B", &secret);
+ }
+ seed = chunk_cata("mcc", secret, nonce_i, nonce_r);
+ DBG4(DBG_CHD, "seed %B", &seed);
+
+ if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
+ &enc_alg, &enc_size))
+ {
+ DBG2(DBG_CHD, " using %N for encryption",
+ encryption_algorithm_names, enc_alg);
+
+ if (!enc_size)
+ {
+ enc_size = keymat_get_keylen_encr(enc_alg);
+ }
+ if (enc_alg != ENCR_NULL && !enc_size)
+ {
+ DBG1(DBG_CHD, "no keylength defined for %N",
+ encryption_algorithm_names, enc_alg);
+ return FALSE;
+ }
+ /* to bytes */
+ enc_size /= 8;
+
+ /* CCM/GCM/CTR/GMAC needs additional bytes */
+ switch (enc_alg)
+ {
+ case ENCR_AES_CCM_ICV8:
+ case ENCR_AES_CCM_ICV12:
+ case ENCR_AES_CCM_ICV16:
+ case ENCR_CAMELLIA_CCM_ICV8:
+ case ENCR_CAMELLIA_CCM_ICV12:
+ case ENCR_CAMELLIA_CCM_ICV16:
+ enc_size += 3;
+ break;
+ case ENCR_AES_GCM_ICV8:
+ case ENCR_AES_GCM_ICV12:
+ case ENCR_AES_GCM_ICV16:
+ case ENCR_AES_CTR:
+ case ENCR_NULL_AUTH_AES_GMAC:
+ enc_size += 4;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
+ &int_alg, &int_size))
+ {
+ DBG2(DBG_CHD, " using %N for integrity",
+ integrity_algorithm_names, int_alg);
+
+ if (!int_size)
+ {
+ int_size = keymat_get_keylen_integ(int_alg);
+ }
+ if (!int_size)
+ {
+ DBG1(DBG_CHD, "no keylength defined for %N",
+ integrity_algorithm_names, int_alg);
+ return FALSE;
+ }
+ /* to bytes */
+ int_size /= 8;
+ }
+
+ if (!this->prf->set_key(this->prf, this->skd))
+ {
+ return FALSE;
+ }
+ prf_plus = prf_plus_create(this->prf, TRUE, seed);
+ if (!prf_plus)
+ {
+ return FALSE;
+ }
+
+ *encr_i = *integ_i = *encr_r = *integ_r = chunk_empty;
+ if (!prf_plus->allocate_bytes(prf_plus, enc_size, encr_i) ||
+ !prf_plus->allocate_bytes(prf_plus, int_size, integ_i) ||
+ !prf_plus->allocate_bytes(prf_plus, enc_size, encr_r) ||
+ !prf_plus->allocate_bytes(prf_plus, int_size, integ_r))
+ {
+ chunk_free(encr_i);
+ chunk_free(integ_i);
+ chunk_free(encr_r);
+ chunk_free(integ_r);
+ prf_plus->destroy(prf_plus);
+ return FALSE;
+ }
+
+ prf_plus->destroy(prf_plus);
+
+ if (enc_size)
+ {
+ DBG4(DBG_CHD, "encryption initiator key %B", encr_i);
+ DBG4(DBG_CHD, "encryption responder key %B", encr_r);
+ }
+ if (int_size)
+ {
+ DBG4(DBG_CHD, "integrity initiator key %B", integ_i);
+ DBG4(DBG_CHD, "integrity responder key %B", integ_r);
+ }
+ return TRUE;
+}
+
+METHOD(keymat_v2_t, get_skd, pseudo_random_function_t,
+ private_keymat_v2_t *this, chunk_t *skd)
+{
+ *skd = this->skd;
+ return this->prf_alg;
+}
+
+METHOD(keymat_t, get_aead, aead_t*,
+ private_keymat_v2_t *this, bool in)
+{
+ return in ? this->aead_in : this->aead_out;
+}
+
+METHOD(keymat_v2_t, get_auth_octets, bool,
+ private_keymat_v2_t *this, bool verify, chunk_t ike_sa_init,
+ chunk_t nonce, identification_t *id, char reserved[3], chunk_t *octets)
+{
+ chunk_t chunk, idx;
+ chunk_t skp;
+
+ skp = verify ? this->skp_verify : this->skp_build;
+
+ chunk = chunk_alloca(4);
+ chunk.ptr[0] = id->get_type(id);
+ memcpy(chunk.ptr + 1, reserved, 3);
+ idx = chunk_cata("cc", chunk, id->get_encoding(id));
+
+ DBG3(DBG_IKE, "IDx' %B", &idx);
+ DBG3(DBG_IKE, "SK_p %B", &skp);
+ if (!this->prf->set_key(this->prf, skp) ||
+ !this->prf->allocate_bytes(this->prf, idx, &chunk))
+ {
+ return FALSE;
+ }
+ *octets = chunk_cat("ccm", ike_sa_init, nonce, chunk);
+ DBG3(DBG_IKE, "octets = message + nonce + prf(Sk_px, IDx') %B", octets);
+ return TRUE;
+}
+
+/**
+ * Key pad for the AUTH method SHARED_KEY_MESSAGE_INTEGRITY_CODE.
+ */
+#define IKEV2_KEY_PAD "Key Pad for IKEv2"
+#define IKEV2_KEY_PAD_LENGTH 17
+
+METHOD(keymat_v2_t, get_psk_sig, bool,
+ private_keymat_v2_t *this, bool verify, chunk_t ike_sa_init, chunk_t nonce,
+ chunk_t secret, identification_t *id, char reserved[3], chunk_t *sig)
+{
+ chunk_t key_pad, key, octets;
+
+ if (!secret.len)
+ { /* EAP uses SK_p if no MSK has been established */
+ secret = verify ? this->skp_verify : this->skp_build;
+ }
+ if (!get_auth_octets(this, verify, ike_sa_init, nonce, id, reserved, &octets))
+ {
+ return FALSE;
+ }
+ /* AUTH = prf(prf(Shared Secret,"Key Pad for IKEv2"), <msg octets>) */
+ key_pad = chunk_create(IKEV2_KEY_PAD, IKEV2_KEY_PAD_LENGTH);
+ if (!this->prf->set_key(this->prf, secret) ||
+ !this->prf->allocate_bytes(this->prf, key_pad, &key))
+ {
+ chunk_free(&octets);
+ return FALSE;
+ }
+ if (!this->prf->set_key(this->prf, key) ||
+ !this->prf->allocate_bytes(this->prf, octets, sig))
+ {
+ chunk_free(&key);
+ chunk_free(&octets);
+ return FALSE;
+ }
+ DBG4(DBG_IKE, "secret %B", &secret);
+ DBG4(DBG_IKE, "prf(secret, keypad) %B", &key);
+ DBG3(DBG_IKE, "AUTH = prf(prf(secret, keypad), octets) %B", sig);
+ chunk_free(&octets);
+ chunk_free(&key);
+
+ return TRUE;
+}
+
+METHOD(keymat_t, destroy, void,
+ private_keymat_v2_t *this)
+{
+ DESTROY_IF(this->aead_in);
+ DESTROY_IF(this->aead_out);
+ DESTROY_IF(this->prf);
+ chunk_clear(&this->skd);
+ chunk_clear(&this->skp_verify);
+ chunk_clear(&this->skp_build);
+ free(this);
+}
+
+/**
+ * See header
+ */
+keymat_v2_t *keymat_v2_create(bool initiator)
+{
+ private_keymat_v2_t *this;
+
+ INIT(this,
+ .public = {
+ .keymat = {
+ .get_version = _get_version,
+ .create_dh = _create_dh,
+ .create_nonce_gen = _create_nonce_gen,
+ .get_aead = _get_aead,
+ .destroy = _destroy,
+ },
+ .derive_ike_keys = _derive_ike_keys,
+ .derive_child_keys = _derive_child_keys,
+ .get_skd = _get_skd,
+ .get_auth_octets = _get_auth_octets,
+ .get_psk_sig = _get_psk_sig,
+ },
+ .initiator = initiator,
+ .prf_alg = PRF_UNDEFINED,
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/sa/ikev2/keymat_v2.h b/src/libcharon/sa/ikev2/keymat_v2.h
new file mode 100644
index 000000000..04432f05b
--- /dev/null
+++ b/src/libcharon/sa/ikev2/keymat_v2.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2011 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup keymat_v2 keymat_v2
+ * @{ @ingroup ikev2
+ */
+
+#ifndef KEYMAT_V2_H_
+#define KEYMAT_V2_H_
+
+#include <sa/keymat.h>
+
+typedef struct keymat_v2_t keymat_v2_t;
+
+/**
+ * Derivation and management of sensitive keying material, IKEv2 variant.
+ */
+struct keymat_v2_t {
+
+ /**
+ * Implements keymat_t.
+ */
+ keymat_t keymat;
+
+ /**
+ * Derive keys for the IKE_SA.
+ *
+ * These keys are not handed out, but are used by the associated signers,
+ * crypters and authentication functions.
+ *
+ * @param proposal selected algorithms
+ * @param dh diffie hellman key allocated by create_dh()
+ * @param nonce_i initiators nonce value
+ * @param nonce_r responders nonce value
+ * @param id IKE_SA identifier
+ * @param rekey_prf PRF of old SA if rekeying, PRF_UNDEFINED otherwise
+ * @param rekey_sdk SKd of old SA if rekeying
+ * @return TRUE on success
+ */
+ bool (*derive_ike_keys)(keymat_v2_t *this, proposal_t *proposal,
+ diffie_hellman_t *dh, chunk_t nonce_i,
+ chunk_t nonce_r, ike_sa_id_t *id,
+ pseudo_random_function_t rekey_function,
+ chunk_t rekey_skd);
+
+ /**
+ * Derive keys for a CHILD_SA.
+ *
+ * The keys for the CHILD_SA are allocated in the integ and encr chunks.
+ * An implementation might hand out encrypted keys only, which are
+ * decrypted in the kernel before use.
+ * If no PFS is used for the CHILD_SA, dh can be NULL.
+ *
+ * @param proposal selected algorithms
+ * @param dh diffie hellman key allocated by create_dh(), or NULL
+ * @param nonce_i initiators nonce value
+ * @param nonce_r responders nonce value
+ * @param encr_i chunk to write initiators encryption key to
+ * @param integ_i chunk to write initiators integrity key to
+ * @param encr_r chunk to write responders encryption key to
+ * @param integ_r chunk to write responders integrity key to
+ * @return TRUE on success
+ */
+ bool (*derive_child_keys)(keymat_v2_t *this,
+ proposal_t *proposal, diffie_hellman_t *dh,
+ chunk_t nonce_i, chunk_t nonce_r,
+ chunk_t *encr_i, chunk_t *integ_i,
+ chunk_t *encr_r, chunk_t *integ_r);
+ /**
+ * Get SKd to pass to derive_ikey_keys() during rekeying.
+ *
+ * @param skd chunk to write SKd to (internal data)
+ * @return PRF function to derive keymat
+ */
+ pseudo_random_function_t (*get_skd)(keymat_v2_t *this, chunk_t *skd);
+
+ /**
+ * Generate octets to use for authentication procedure (RFC4306 2.15).
+ *
+ * This method creates the plain octets and is usually signed by a private
+ * key. PSK and EAP authentication include a secret into the data, use
+ * the get_psk_sig() method instead.
+ *
+ * @param verify TRUE to create for verfification, FALSE to sign
+ * @param ike_sa_init encoded ike_sa_init message
+ * @param nonce nonce value
+ * @param id identity
+ * @param reserved reserved bytes of id_payload
+ * @param octests chunk receiving allocated auth octets
+ * @return TRUE if octets created successfully
+ */
+ bool (*get_auth_octets)(keymat_v2_t *this, bool verify, chunk_t ike_sa_init,
+ chunk_t nonce, identification_t *id,
+ char reserved[3], chunk_t *octets);
+ /**
+ * Build the shared secret signature used for PSK and EAP authentication.
+ *
+ * This method wraps the get_auth_octets() method and additionally
+ * includes the secret into the signature. If no secret is given, SK_p is
+ * used as secret (used for EAP methods without MSK).
+ *
+ * @param verify TRUE to create for verfification, FALSE to sign
+ * @param ike_sa_init encoded ike_sa_init message
+ * @param nonce nonce value
+ * @param secret optional secret to include into signature
+ * @param id identity
+ * @param reserved reserved bytes of id_payload
+ * @param sign chunk receiving allocated signature octets
+ * @return TRUE if signature created successfully
+ */
+ bool (*get_psk_sig)(keymat_v2_t *this, bool verify, chunk_t ike_sa_init,
+ chunk_t nonce, chunk_t secret,
+ identification_t *id, char reserved[3], chunk_t *sig);
+};
+
+/**
+ * Create a keymat instance.
+ *
+ * @param initiator TRUE if we are the initiator
+ * @return keymat instance
+ */
+keymat_v2_t *keymat_v2_create(bool initiator);
+
+#endif /** KEYMAT_V2_H_ @}*/
diff --git a/src/libcharon/sa/mediation_manager.c b/src/libcharon/sa/ikev2/mediation_manager.c
index 60eeb5d4b..60eeb5d4b 100644
--- a/src/libcharon/sa/mediation_manager.c
+++ b/src/libcharon/sa/ikev2/mediation_manager.c
diff --git a/src/libcharon/sa/mediation_manager.h b/src/libcharon/sa/ikev2/mediation_manager.h
index 31a16f69c..5212bdb86 100644
--- a/src/libcharon/sa/mediation_manager.h
+++ b/src/libcharon/sa/ikev2/mediation_manager.h
@@ -15,7 +15,7 @@
/**
* @defgroup mediation_manager mediation_manager
- * @{ @ingroup sa
+ * @{ @ingroup ikev2
*/
#ifndef MEDIATION_MANAGER_H_
diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c
new file mode 100644
index 000000000..53051fab4
--- /dev/null
+++ b/src/libcharon/sa/ikev2/task_manager_v2.c
@@ -0,0 +1,1502 @@
+/*
+ * Copyright (C) 2007-2011 Tobias Brunner
+ * Copyright (C) 2007-2010 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "task_manager_v2.h"
+
+#include <math.h>
+
+#include <daemon.h>
+#include <sa/ikev2/tasks/ike_init.h>
+#include <sa/ikev2/tasks/ike_natd.h>
+#include <sa/ikev2/tasks/ike_mobike.h>
+#include <sa/ikev2/tasks/ike_auth.h>
+#include <sa/ikev2/tasks/ike_auth_lifetime.h>
+#include <sa/ikev2/tasks/ike_cert_pre.h>
+#include <sa/ikev2/tasks/ike_cert_post.h>
+#include <sa/ikev2/tasks/ike_rekey.h>
+#include <sa/ikev2/tasks/ike_reauth.h>
+#include <sa/ikev2/tasks/ike_delete.h>
+#include <sa/ikev2/tasks/ike_config.h>
+#include <sa/ikev2/tasks/ike_dpd.h>
+#include <sa/ikev2/tasks/ike_vendor.h>
+#include <sa/ikev2/tasks/child_create.h>
+#include <sa/ikev2/tasks/child_rekey.h>
+#include <sa/ikev2/tasks/child_delete.h>
+#include <encoding/payloads/delete_payload.h>
+#include <encoding/payloads/unknown_payload.h>
+#include <processing/jobs/retransmit_job.h>
+#include <processing/jobs/delete_ike_sa_job.h>
+
+#ifdef ME
+#include <sa/ikev2/tasks/ike_me.h>
+#endif
+
+typedef struct exchange_t exchange_t;
+
+/**
+ * An exchange in the air, used do detect and handle retransmission
+ */
+struct exchange_t {
+
+ /**
+ * Message ID used for this transaction
+ */
+ u_int32_t mid;
+
+ /**
+ * generated packet for retransmission
+ */
+ packet_t *packet;
+};
+
+typedef struct private_task_manager_t private_task_manager_t;
+
+/**
+ * private data of the task manager
+ */
+struct private_task_manager_t {
+
+ /**
+ * public functions
+ */
+ task_manager_v2_t public;
+
+ /**
+ * associated IKE_SA we are serving
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * Exchange we are currently handling as responder
+ */
+ struct {
+ /**
+ * Message ID of the exchange
+ */
+ u_int32_t mid;
+
+ /**
+ * packet for retransmission
+ */
+ packet_t *packet;
+
+ } responding;
+
+ /**
+ * Exchange we are currently handling as initiator
+ */
+ struct {
+ /**
+ * Message ID of the exchange
+ */
+ u_int32_t mid;
+
+ /**
+ * how many times we have retransmitted so far
+ */
+ u_int retransmitted;
+
+ /**
+ * packet for retransmission
+ */
+ packet_t *packet;
+
+ /**
+ * type of the initated exchange
+ */
+ exchange_type_t type;
+
+ } initiating;
+
+ /**
+ * List of queued tasks not yet in action
+ */
+ linked_list_t *queued_tasks;
+
+ /**
+ * List of active tasks, initiated by ourselve
+ */
+ linked_list_t *active_tasks;
+
+ /**
+ * List of tasks initiated by peer
+ */
+ linked_list_t *passive_tasks;
+
+ /**
+ * the task manager has been reset
+ */
+ bool reset;
+
+ /**
+ * Number of times we retransmit messages before giving up
+ */
+ u_int retransmit_tries;
+
+ /**
+ * Retransmission timeout
+ */
+ double retransmit_timeout;
+
+ /**
+ * Base to calculate retransmission timeout
+ */
+ double retransmit_base;
+};
+
+METHOD(task_manager_t, flush_queue, void,
+ private_task_manager_t *this, task_queue_t queue)
+{
+ linked_list_t *list;
+ task_t *task;
+
+ switch (queue)
+ {
+ case TASK_QUEUE_ACTIVE:
+ list = this->active_tasks;
+ break;
+ case TASK_QUEUE_PASSIVE:
+ list = this->passive_tasks;
+ break;
+ case TASK_QUEUE_QUEUED:
+ list = this->queued_tasks;
+ break;
+ default:
+ return;
+ }
+ while (list->remove_last(list, (void**)&task) == SUCCESS)
+ {
+ task->destroy(task);
+ }
+}
+
+/**
+ * flush all tasks in the task manager
+ */
+static void flush(private_task_manager_t *this)
+{
+ flush_queue(this, TASK_QUEUE_QUEUED);
+ flush_queue(this, TASK_QUEUE_PASSIVE);
+ flush_queue(this, TASK_QUEUE_ACTIVE);
+}
+
+/**
+ * move a task of a specific type from the queue to the active list
+ */
+static bool activate_task(private_task_manager_t *this, task_type_t type)
+{
+ enumerator_t *enumerator;
+ task_t *task;
+ bool found = FALSE;
+
+ enumerator = this->queued_tasks->create_enumerator(this->queued_tasks);
+ while (enumerator->enumerate(enumerator, (void**)&task))
+ {
+ if (task->get_type(task) == type)
+ {
+ DBG2(DBG_IKE, " activating %N task", task_type_names, type);
+ this->queued_tasks->remove_at(this->queued_tasks, enumerator);
+ this->active_tasks->insert_last(this->active_tasks, task);
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return found;
+}
+
+METHOD(task_manager_t, retransmit, status_t,
+ private_task_manager_t *this, u_int32_t message_id)
+{
+ if (this->initiating.packet && message_id == this->initiating.mid)
+ {
+ u_int32_t timeout;
+ job_t *job;
+ enumerator_t *enumerator;
+ packet_t *packet;
+ task_t *task;
+ ike_mobike_t *mobike = NULL;
+
+ /* check if we are retransmitting a MOBIKE routability check */
+ enumerator = this->active_tasks->create_enumerator(this->active_tasks);
+ while (enumerator->enumerate(enumerator, (void*)&task))
+ {
+ if (task->get_type(task) == TASK_IKE_MOBIKE)
+ {
+ mobike = (ike_mobike_t*)task;
+ if (!mobike->is_probing(mobike))
+ {
+ mobike = NULL;
+ }
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (mobike == NULL)
+ {
+ if (this->initiating.retransmitted <= this->retransmit_tries)
+ {
+ timeout = (u_int32_t)(this->retransmit_timeout * 1000.0 *
+ pow(this->retransmit_base, this->initiating.retransmitted));
+ }
+ else
+ {
+ DBG1(DBG_IKE, "giving up after %d retransmits",
+ this->initiating.retransmitted - 1);
+ return DESTROY_ME;
+ }
+
+ if (this->initiating.retransmitted)
+ {
+ DBG1(DBG_IKE, "retransmit %d of request with message ID %d",
+ this->initiating.retransmitted, message_id);
+ }
+ packet = this->initiating.packet->clone(this->initiating.packet);
+ charon->sender->send(charon->sender, packet);
+ }
+ else
+ { /* for routeability checks, we use a more aggressive behavior */
+ if (this->initiating.retransmitted <= ROUTEABILITY_CHECK_TRIES)
+ {
+ timeout = ROUTEABILITY_CHECK_INTERVAL;
+ }
+ else
+ {
+ DBG1(DBG_IKE, "giving up after %d path probings",
+ this->initiating.retransmitted - 1);
+ return DESTROY_ME;
+ }
+
+ if (this->initiating.retransmitted)
+ {
+ DBG1(DBG_IKE, "path probing attempt %d",
+ this->initiating.retransmitted);
+ }
+ mobike->transmit(mobike, this->initiating.packet);
+ }
+
+ this->initiating.retransmitted++;
+ job = (job_t*)retransmit_job_create(this->initiating.mid,
+ this->ike_sa->get_id(this->ike_sa));
+ lib->scheduler->schedule_job_ms(lib->scheduler, job, timeout);
+ }
+ return SUCCESS;
+}
+
+METHOD(task_manager_t, initiate, status_t,
+ private_task_manager_t *this)
+{
+ enumerator_t *enumerator;
+ task_t *task;
+ message_t *message;
+ host_t *me, *other;
+ status_t status;
+ exchange_type_t exchange = 0;
+
+ if (this->initiating.type != EXCHANGE_TYPE_UNDEFINED)
+ {
+ DBG2(DBG_IKE, "delaying task initiation, %N exchange in progress",
+ exchange_type_names, this->initiating.type);
+ /* do not initiate if we already have a message in the air */
+ return SUCCESS;
+ }
+
+ if (this->active_tasks->get_count(this->active_tasks) == 0)
+ {
+ DBG2(DBG_IKE, "activating new tasks");
+ switch (this->ike_sa->get_state(this->ike_sa))
+ {
+ case IKE_CREATED:
+ activate_task(this, TASK_IKE_VENDOR);
+ if (activate_task(this, TASK_IKE_INIT))
+ {
+ this->initiating.mid = 0;
+ exchange = IKE_SA_INIT;
+ activate_task(this, TASK_IKE_NATD);
+ activate_task(this, TASK_IKE_CERT_PRE);
+#ifdef ME
+ /* this task has to be activated before the TASK_IKE_AUTH
+ * task, because that task pregenerates the packet after
+ * which no payloads can be added to the message anymore.
+ */
+ activate_task(this, TASK_IKE_ME);
+#endif /* ME */
+ activate_task(this, TASK_IKE_AUTH);
+ activate_task(this, TASK_IKE_CERT_POST);
+ activate_task(this, TASK_IKE_CONFIG);
+ activate_task(this, TASK_CHILD_CREATE);
+ activate_task(this, TASK_IKE_AUTH_LIFETIME);
+ activate_task(this, TASK_IKE_MOBIKE);
+ }
+ break;
+ case IKE_ESTABLISHED:
+ if (activate_task(this, TASK_CHILD_CREATE))
+ {
+ exchange = CREATE_CHILD_SA;
+ break;
+ }
+ if (activate_task(this, TASK_CHILD_DELETE))
+ {
+ exchange = INFORMATIONAL;
+ break;
+ }
+ if (activate_task(this, TASK_CHILD_REKEY))
+ {
+ exchange = CREATE_CHILD_SA;
+ break;
+ }
+ if (activate_task(this, TASK_IKE_DELETE))
+ {
+ exchange = INFORMATIONAL;
+ break;
+ }
+ if (activate_task(this, TASK_IKE_REKEY))
+ {
+ exchange = CREATE_CHILD_SA;
+ break;
+ }
+ if (activate_task(this, TASK_IKE_REAUTH))
+ {
+ exchange = INFORMATIONAL;
+ break;
+ }
+ if (activate_task(this, TASK_IKE_MOBIKE))
+ {
+ exchange = INFORMATIONAL;
+ break;
+ }
+ if (activate_task(this, TASK_IKE_DPD))
+ {
+ exchange = INFORMATIONAL;
+ break;
+ }
+ if (activate_task(this, TASK_IKE_AUTH_LIFETIME))
+ {
+ exchange = INFORMATIONAL;
+ break;
+ }
+#ifdef ME
+ if (activate_task(this, TASK_IKE_ME))
+ {
+ exchange = ME_CONNECT;
+ break;
+ }
+#endif /* ME */
+ case IKE_REKEYING:
+ if (activate_task(this, TASK_IKE_DELETE))
+ {
+ exchange = INFORMATIONAL;
+ break;
+ }
+ case IKE_DELETING:
+ default:
+ break;
+ }
+ }
+ else
+ {
+ DBG2(DBG_IKE, "reinitiating already active tasks");
+ enumerator = this->active_tasks->create_enumerator(this->active_tasks);
+ while (enumerator->enumerate(enumerator, (void**)&task))
+ {
+ DBG2(DBG_IKE, " %N task", task_type_names, task->get_type(task));
+ switch (task->get_type(task))
+ {
+ case TASK_IKE_INIT:
+ exchange = IKE_SA_INIT;
+ break;
+ case TASK_IKE_AUTH:
+ exchange = IKE_AUTH;
+ break;
+ case TASK_CHILD_CREATE:
+ case TASK_CHILD_REKEY:
+ case TASK_IKE_REKEY:
+ exchange = CREATE_CHILD_SA;
+ break;
+ case TASK_IKE_MOBIKE:
+ exchange = INFORMATIONAL;
+ break;
+ default:
+ continue;
+ }
+ break;
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ if (exchange == 0)
+ {
+ DBG2(DBG_IKE, "nothing to initiate");
+ /* nothing to do yet... */
+ return SUCCESS;
+ }
+
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ other = this->ike_sa->get_other_host(this->ike_sa);
+
+ message = message_create(IKEV2_MAJOR_VERSION, IKEV2_MINOR_VERSION);
+ message->set_message_id(message, this->initiating.mid);
+ message->set_source(message, me->clone(me));
+ message->set_destination(message, other->clone(other));
+ message->set_exchange_type(message, exchange);
+ this->initiating.type = exchange;
+ this->initiating.retransmitted = 0;
+
+ enumerator = this->active_tasks->create_enumerator(this->active_tasks);
+ while (enumerator->enumerate(enumerator, (void*)&task))
+ {
+ switch (task->build(task, message))
+ {
+ case SUCCESS:
+ /* task completed, remove it */
+ this->active_tasks->remove_at(this->active_tasks, enumerator);
+ task->destroy(task);
+ break;
+ case NEED_MORE:
+ /* processed, but task needs another exchange */
+ break;
+ case FAILED:
+ default:
+ if (this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING)
+ {
+ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ }
+ /* FALL */
+ case DESTROY_ME:
+ /* critical failure, destroy IKE_SA */
+ enumerator->destroy(enumerator);
+ message->destroy(message);
+ flush(this);
+ return DESTROY_ME;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ /* update exchange type if a task changed it */
+ this->initiating.type = message->get_exchange_type(message);
+
+ status = this->ike_sa->generate_message(this->ike_sa, message,
+ &this->initiating.packet);
+ if (status != SUCCESS)
+ {
+ /* message generation failed. There is nothing more to do than to
+ * close the SA */
+ message->destroy(message);
+ flush(this);
+ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ return DESTROY_ME;
+ }
+ message->destroy(message);
+
+ return retransmit(this, this->initiating.mid);
+}
+
+/**
+ * handle an incoming response message
+ */
+static status_t process_response(private_task_manager_t *this,
+ message_t *message)
+{
+ enumerator_t *enumerator;
+ task_t *task;
+
+ if (message->get_exchange_type(message) != this->initiating.type)
+ {
+ DBG1(DBG_IKE, "received %N response, but expected %N",
+ exchange_type_names, message->get_exchange_type(message),
+ exchange_type_names, this->initiating.type);
+ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ return DESTROY_ME;
+ }
+
+ /* catch if we get resetted while processing */
+ this->reset = FALSE;
+ enumerator = this->active_tasks->create_enumerator(this->active_tasks);
+ while (enumerator->enumerate(enumerator, (void*)&task))
+ {
+ switch (task->process(task, message))
+ {
+ case SUCCESS:
+ /* task completed, remove it */
+ this->active_tasks->remove_at(this->active_tasks, enumerator);
+ task->destroy(task);
+ break;
+ case NEED_MORE:
+ /* processed, but task needs another exchange */
+ break;
+ case FAILED:
+ default:
+ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ /* FALL */
+ case DESTROY_ME:
+ /* critical failure, destroy IKE_SA */
+ this->active_tasks->remove_at(this->active_tasks, enumerator);
+ enumerator->destroy(enumerator);
+ task->destroy(task);
+ return DESTROY_ME;
+ }
+ if (this->reset)
+ { /* start all over again if we were reset */
+ this->reset = FALSE;
+ enumerator->destroy(enumerator);
+ return initiate(this);
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ this->initiating.mid++;
+ this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
+ this->initiating.packet->destroy(this->initiating.packet);
+ this->initiating.packet = NULL;
+
+ return initiate(this);
+}
+
+/**
+ * handle exchange collisions
+ */
+static bool handle_collisions(private_task_manager_t *this, task_t *task)
+{
+ enumerator_t *enumerator;
+ task_t *active;
+ task_type_t type;
+
+ type = task->get_type(task);
+
+ /* do we have to check */
+ if (type == TASK_IKE_REKEY || type == TASK_CHILD_REKEY ||
+ type == TASK_CHILD_DELETE || type == TASK_IKE_DELETE ||
+ type == TASK_IKE_REAUTH)
+ {
+ /* find an exchange collision, and notify these tasks */
+ enumerator = this->active_tasks->create_enumerator(this->active_tasks);
+ while (enumerator->enumerate(enumerator, (void**)&active))
+ {
+ switch (active->get_type(active))
+ {
+ case TASK_IKE_REKEY:
+ if (type == TASK_IKE_REKEY || type == TASK_IKE_DELETE ||
+ type == TASK_IKE_REAUTH)
+ {
+ ike_rekey_t *rekey = (ike_rekey_t*)active;
+ rekey->collide(rekey, task);
+ break;
+ }
+ continue;
+ case TASK_CHILD_REKEY:
+ if (type == TASK_CHILD_REKEY || type == TASK_CHILD_DELETE)
+ {
+ child_rekey_t *rekey = (child_rekey_t*)active;
+ rekey->collide(rekey, task);
+ break;
+ }
+ continue;
+ default:
+ continue;
+ }
+ enumerator->destroy(enumerator);
+ return TRUE;
+ }
+ enumerator->destroy(enumerator);
+ }
+ return FALSE;
+}
+
+/**
+ * build a response depending on the "passive" task list
+ */
+static status_t build_response(private_task_manager_t *this, message_t *request)
+{
+ enumerator_t *enumerator;
+ task_t *task;
+ message_t *message;
+ host_t *me, *other;
+ bool delete = FALSE, hook = FALSE;
+ status_t status;
+
+ me = request->get_destination(request);
+ other = request->get_source(request);
+
+ message = message_create(IKEV2_MAJOR_VERSION, IKEV2_MINOR_VERSION);
+ message->set_exchange_type(message, request->get_exchange_type(request));
+ /* send response along the path the request came in */
+ message->set_source(message, me->clone(me));
+ message->set_destination(message, other->clone(other));
+ message->set_message_id(message, this->responding.mid);
+ message->set_request(message, FALSE);
+
+ enumerator = this->passive_tasks->create_enumerator(this->passive_tasks);
+ while (enumerator->enumerate(enumerator, (void*)&task))
+ {
+ switch (task->build(task, message))
+ {
+ case SUCCESS:
+ /* task completed, remove it */
+ this->passive_tasks->remove_at(this->passive_tasks, enumerator);
+ if (!handle_collisions(this, task))
+ {
+ task->destroy(task);
+ }
+ break;
+ case NEED_MORE:
+ /* processed, but task needs another exchange */
+ if (handle_collisions(this, task))
+ {
+ this->passive_tasks->remove_at(this->passive_tasks,
+ enumerator);
+ }
+ break;
+ case FAILED:
+ default:
+ hook = TRUE;
+ /* FALL */
+ case DESTROY_ME:
+ /* destroy IKE_SA, but SEND response first */
+ delete = TRUE;
+ break;
+ }
+ if (delete)
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ /* remove resonder SPI if IKE_SA_INIT failed */
+ if (delete && request->get_exchange_type(request) == IKE_SA_INIT)
+ {
+ ike_sa_id_t *id = this->ike_sa->get_id(this->ike_sa);
+ id->set_responder_spi(id, 0);
+ }
+
+ /* message complete, send it */
+ DESTROY_IF(this->responding.packet);
+ this->responding.packet = NULL;
+ status = this->ike_sa->generate_message(this->ike_sa, message,
+ &this->responding.packet);
+ message->destroy(message);
+ if (status != SUCCESS)
+ {
+ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ return DESTROY_ME;
+ }
+
+ charon->sender->send(charon->sender,
+ this->responding.packet->clone(this->responding.packet));
+ if (delete)
+ {
+ if (hook)
+ {
+ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ }
+ return DESTROY_ME;
+ }
+ return SUCCESS;
+}
+
+/**
+ * handle an incoming request message
+ */
+static status_t process_request(private_task_manager_t *this,
+ message_t *message)
+{
+ enumerator_t *enumerator;
+ task_t *task = NULL;
+ payload_t *payload;
+ notify_payload_t *notify;
+ delete_payload_t *delete;
+
+ if (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))
+ {
+ case IKE_SA_INIT:
+ {
+ task = (task_t*)ike_vendor_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ task = (task_t*)ike_init_create(this->ike_sa, FALSE, NULL);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ task = (task_t*)ike_natd_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ task = (task_t*)ike_cert_pre_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+#ifdef ME
+ task = (task_t*)ike_me_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+#endif /* ME */
+ task = (task_t*)ike_auth_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ task = (task_t*)ike_cert_post_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ task = (task_t*)ike_config_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ task = (task_t*)child_create_create(this->ike_sa, NULL, FALSE,
+ NULL, NULL);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ task = (task_t*)ike_auth_lifetime_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ task = (task_t*)ike_mobike_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ break;
+ }
+ case CREATE_CHILD_SA:
+ { /* FIXME: we should prevent this on mediation connections */
+ bool notify_found = FALSE, ts_found = FALSE;
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ switch (payload->get_type(payload))
+ {
+ case NOTIFY:
+ { /* if we find a rekey notify, its CHILD_SA rekeying */
+ notify = (notify_payload_t*)payload;
+ if (notify->get_notify_type(notify) == REKEY_SA &&
+ (notify->get_protocol_id(notify) == PROTO_AH ||
+ notify->get_protocol_id(notify) == PROTO_ESP))
+ {
+ notify_found = TRUE;
+ }
+ break;
+ }
+ case TRAFFIC_SELECTOR_INITIATOR:
+ case TRAFFIC_SELECTOR_RESPONDER:
+ { /* if we don't find a TS, its IKE rekeying */
+ ts_found = TRUE;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (ts_found)
+ {
+ if (notify_found)
+ {
+ task = (task_t*)child_rekey_create(this->ike_sa,
+ PROTO_NONE, 0);
+ }
+ else
+ {
+ task = (task_t*)child_create_create(this->ike_sa, NULL,
+ FALSE, NULL, NULL);
+ }
+ }
+ else
+ {
+ task = (task_t*)ike_rekey_create(this->ike_sa, FALSE);
+ }
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ break;
+ }
+ case INFORMATIONAL:
+ {
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ switch (payload->get_type(payload))
+ {
+ case NOTIFY:
+ {
+ notify = (notify_payload_t*)payload;
+ switch (notify->get_notify_type(notify))
+ {
+ case ADDITIONAL_IP4_ADDRESS:
+ case ADDITIONAL_IP6_ADDRESS:
+ case NO_ADDITIONAL_ADDRESSES:
+ case UPDATE_SA_ADDRESSES:
+ case NO_NATS_ALLOWED:
+ case UNACCEPTABLE_ADDRESSES:
+ case UNEXPECTED_NAT_DETECTED:
+ case COOKIE2:
+ case NAT_DETECTION_SOURCE_IP:
+ case NAT_DETECTION_DESTINATION_IP:
+ task = (task_t*)ike_mobike_create(
+ this->ike_sa, FALSE);
+ break;
+ case AUTH_LIFETIME:
+ task = (task_t*)ike_auth_lifetime_create(
+ this->ike_sa, FALSE);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case DELETE:
+ {
+ delete = (delete_payload_t*)payload;
+ if (delete->get_protocol_id(delete) == PROTO_IKE)
+ {
+ task = (task_t*)ike_delete_create(this->ike_sa,
+ FALSE);
+ }
+ else
+ {
+ task = (task_t*)child_delete_create(this->ike_sa,
+ PROTO_NONE, 0, FALSE);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ if (task)
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (task == NULL)
+ {
+ task = (task_t*)ike_dpd_create(FALSE);
+ }
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ break;
+ }
+#ifdef ME
+ case ME_CONNECT:
+ {
+ task = (task_t*)ike_me_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ }
+#endif /* ME */
+ default:
+ break;
+ }
+ }
+
+ /* let the tasks process the message */
+ enumerator = this->passive_tasks->create_enumerator(this->passive_tasks);
+ while (enumerator->enumerate(enumerator, (void*)&task))
+ {
+ switch (task->process(task, message))
+ {
+ case SUCCESS:
+ /* task completed, remove it */
+ this->passive_tasks->remove_at(this->passive_tasks, enumerator);
+ task->destroy(task);
+ break;
+ case NEED_MORE:
+ /* processed, but task needs at least another call to build() */
+ break;
+ case FAILED:
+ default:
+ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ /* FALL */
+ case DESTROY_ME:
+ /* critical failure, destroy IKE_SA */
+ this->passive_tasks->remove_at(this->passive_tasks, enumerator);
+ enumerator->destroy(enumerator);
+ task->destroy(task);
+ return DESTROY_ME;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return build_response(this, message);
+}
+
+METHOD(task_manager_t, incr_mid, void,
+ private_task_manager_t *this, bool initiate)
+{
+ if (initiate)
+ {
+ this->initiating.mid++;
+ }
+ else
+ {
+ this->responding.mid++;
+ }
+}
+
+/**
+ * Send a notify back to the sender
+ */
+static void send_notify_response(private_task_manager_t *this,
+ message_t *request, notify_type_t type,
+ chunk_t data)
+{
+ message_t *response;
+ packet_t *packet;
+ host_t *me, *other;
+
+ response = message_create(IKEV2_MAJOR_VERSION, IKEV2_MINOR_VERSION);
+ response->set_exchange_type(response, request->get_exchange_type(request));
+ response->set_request(response, FALSE);
+ response->set_message_id(response, request->get_message_id(request));
+ response->add_notify(response, FALSE, type, data);
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ if (me->is_anyaddr(me))
+ {
+ me = request->get_destination(request);
+ this->ike_sa->set_my_host(this->ike_sa, me->clone(me));
+ }
+ other = this->ike_sa->get_other_host(this->ike_sa);
+ if (other->is_anyaddr(other))
+ {
+ other = request->get_source(request);
+ this->ike_sa->set_other_host(this->ike_sa, other->clone(other));
+ }
+ response->set_source(response, me->clone(me));
+ response->set_destination(response, other->clone(other));
+ if (this->ike_sa->generate_message(this->ike_sa, response,
+ &packet) == SUCCESS)
+ {
+ charon->sender->send(charon->sender, packet);
+ }
+ response->destroy(response);
+}
+
+/**
+ * Parse the given message and verify that it is valid.
+ */
+static status_t parse_message(private_task_manager_t *this, message_t *msg)
+{
+ status_t status;
+ u_int8_t type = 0;
+
+ status = msg->parse_body(msg, this->ike_sa->get_keymat(this->ike_sa));
+
+ if (status == SUCCESS)
+ { /* check for unsupported critical payloads */
+ enumerator_t *enumerator;
+ unknown_payload_t *unknown;
+ payload_t *payload;
+
+ enumerator = msg->create_payload_enumerator(msg);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ unknown = (unknown_payload_t*)payload;
+ type = payload->get_type(payload);
+ if (!payload_is_known(type) &&
+ unknown->is_critical(unknown))
+ {
+ DBG1(DBG_ENC, "payload type %N is not supported, "
+ "but its critical!", payload_type_names, type);
+ status = NOT_SUPPORTED;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ if (status != SUCCESS)
+ {
+ bool is_request = msg->get_request(msg);
+
+ switch (status)
+ {
+ case NOT_SUPPORTED:
+ DBG1(DBG_IKE, "critical unknown payloads found");
+ if (is_request)
+ {
+ send_notify_response(this, msg,
+ UNSUPPORTED_CRITICAL_PAYLOAD,
+ chunk_from_thing(type));
+ incr_mid(this, FALSE);
+ }
+ break;
+ case PARSE_ERROR:
+ DBG1(DBG_IKE, "message parsing failed");
+ if (is_request)
+ {
+ send_notify_response(this, msg,
+ INVALID_SYNTAX, chunk_empty);
+ incr_mid(this, FALSE);
+ }
+ break;
+ case VERIFY_ERROR:
+ DBG1(DBG_IKE, "message verification failed");
+ if (is_request)
+ {
+ send_notify_response(this, msg,
+ INVALID_SYNTAX, chunk_empty);
+ incr_mid(this, FALSE);
+ }
+ break;
+ case FAILED:
+ DBG1(DBG_IKE, "integrity check failed");
+ /* ignored */
+ break;
+ case INVALID_STATE:
+ DBG1(DBG_IKE, "found encrypted message, but no keys available");
+ default:
+ break;
+ }
+ DBG1(DBG_IKE, "%N %s with message ID %d processing failed",
+ exchange_type_names, msg->get_exchange_type(msg),
+ is_request ? "request" : "response",
+ msg->get_message_id(msg));
+
+ if (this->ike_sa->get_state(this->ike_sa) == IKE_CREATED)
+ { /* invalid initiation attempt, close SA */
+ return DESTROY_ME;
+ }
+ }
+ return status;
+}
+
+
+METHOD(task_manager_t, process_message, status_t,
+ private_task_manager_t *this, message_t *msg)
+{
+ host_t *me, *other;
+ status_t status;
+ u_int32_t mid;
+
+ charon->bus->message(charon->bus, msg, TRUE, FALSE);
+ status = parse_message(this, msg);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+
+ me = msg->get_destination(msg);
+ other = msg->get_source(msg);
+
+ /* if this IKE_SA is virgin, we check for a config */
+ if (this->ike_sa->get_ike_cfg(this->ike_sa) == NULL)
+ {
+ ike_sa_id_t *ike_sa_id;
+ ike_cfg_t *ike_cfg;
+ job_t *job;
+ ike_cfg = charon->backends->get_ike_cfg(charon->backends, me, other);
+ if (ike_cfg == NULL)
+ {
+ /* no config found for these hosts, destroy */
+ DBG1(DBG_IKE, "no IKE config found for %H...%H, sending %N",
+ me, other, notify_type_names, NO_PROPOSAL_CHOSEN);
+ send_notify_response(this, msg,
+ NO_PROPOSAL_CHOSEN, chunk_empty);
+ return DESTROY_ME;
+ }
+ this->ike_sa->set_ike_cfg(this->ike_sa, ike_cfg);
+ ike_cfg->destroy(ike_cfg);
+ /* add a timeout if peer does not establish it completely */
+ ike_sa_id = this->ike_sa->get_id(this->ike_sa);
+ job = (job_t*)delete_ike_sa_job_create(ike_sa_id, FALSE);
+ lib->scheduler->schedule_job(lib->scheduler, job,
+ lib->settings->get_int(lib->settings,
+ "%s.half_open_timeout", HALF_OPEN_IKE_SA_TIMEOUT,
+ charon->name));
+ }
+ this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
+ time_monotonic(NULL));
+
+ mid = msg->get_message_id(msg);
+ if (msg->get_request(msg))
+ {
+ if (mid == this->responding.mid)
+ {
+ if (this->ike_sa->get_state(this->ike_sa) == IKE_CREATED ||
+ this->ike_sa->get_state(this->ike_sa) == IKE_CONNECTING ||
+ msg->get_exchange_type(msg) != IKE_SA_INIT)
+ { /* only do host updates based on verified messages */
+ if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE))
+ { /* with MOBIKE, we do no implicit updates */
+ this->ike_sa->update_hosts(this->ike_sa, me, other, mid == 1);
+ }
+ }
+ charon->bus->message(charon->bus, msg, TRUE, TRUE);
+ if (msg->get_exchange_type(msg) == EXCHANGE_TYPE_UNDEFINED)
+ { /* ignore messages altered to EXCHANGE_TYPE_UNDEFINED */
+ return SUCCESS;
+ }
+ if (process_request(this, msg) != SUCCESS)
+ {
+ flush(this);
+ return DESTROY_ME;
+ }
+ this->responding.mid++;
+ }
+ else if ((mid == this->responding.mid - 1) && this->responding.packet)
+ {
+ packet_t *clone;
+ host_t *host;
+
+ DBG1(DBG_IKE, "received retransmit of request with ID %d, "
+ "retransmitting response", mid);
+ clone = this->responding.packet->clone(this->responding.packet);
+ host = msg->get_destination(msg);
+ clone->set_source(clone, host->clone(host));
+ host = msg->get_source(msg);
+ clone->set_destination(clone, host->clone(host));
+ charon->sender->send(charon->sender, clone);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "received message ID %d, expected %d. Ignored",
+ mid, this->responding.mid);
+ }
+ }
+ else
+ {
+ if (mid == this->initiating.mid)
+ {
+ if (this->ike_sa->get_state(this->ike_sa) == IKE_CREATED ||
+ this->ike_sa->get_state(this->ike_sa) == IKE_CONNECTING ||
+ msg->get_exchange_type(msg) != IKE_SA_INIT)
+ { /* only do host updates based on verified messages */
+ if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE))
+ { /* with MOBIKE, we do no implicit updates */
+ this->ike_sa->update_hosts(this->ike_sa, me, other, FALSE);
+ }
+ }
+ charon->bus->message(charon->bus, msg, TRUE, TRUE);
+ if (msg->get_exchange_type(msg) == EXCHANGE_TYPE_UNDEFINED)
+ { /* ignore messages altered to EXCHANGE_TYPE_UNDEFINED */
+ return SUCCESS;
+ }
+ if (process_response(this, msg) != SUCCESS)
+ {
+ flush(this);
+ return DESTROY_ME;
+ }
+ }
+ else
+ {
+ DBG1(DBG_IKE, "received message ID %d, expected %d. Ignored",
+ mid, this->initiating.mid);
+ return SUCCESS;
+ }
+ }
+ return SUCCESS;
+}
+
+METHOD(task_manager_t, queue_task, void,
+ private_task_manager_t *this, task_t *task)
+{
+ if (task->get_type(task) == TASK_IKE_MOBIKE)
+ { /* there is no need to queue more than one mobike task */
+ enumerator_t *enumerator;
+ task_t *current;
+
+ enumerator = this->queued_tasks->create_enumerator(this->queued_tasks);
+ while (enumerator->enumerate(enumerator, (void**)&current))
+ {
+ if (current->get_type(current) == TASK_IKE_MOBIKE)
+ {
+ enumerator->destroy(enumerator);
+ task->destroy(task);
+ return;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ DBG2(DBG_IKE, "queueing %N task", task_type_names, task->get_type(task));
+ this->queued_tasks->insert_last(this->queued_tasks, task);
+}
+
+/**
+ * Check if a given task has been queued already
+ */
+static bool has_queued(private_task_manager_t *this, task_type_t type)
+{
+ enumerator_t *enumerator;
+ bool found = FALSE;
+ task_t *task;
+
+ enumerator = this->queued_tasks->create_enumerator(this->queued_tasks);
+ while (enumerator->enumerate(enumerator, &task))
+ {
+ if (task->get_type(task) == type)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return found;
+}
+
+METHOD(task_manager_t, queue_ike, void,
+ private_task_manager_t *this)
+{
+ if (!has_queued(this, TASK_IKE_VENDOR))
+ {
+ queue_task(this, (task_t*)ike_vendor_create(this->ike_sa, TRUE));
+ }
+ if (!has_queued(this, TASK_IKE_INIT))
+ {
+ queue_task(this, (task_t*)ike_init_create(this->ike_sa, TRUE, NULL));
+ }
+ if (!has_queued(this, TASK_IKE_NATD))
+ {
+ queue_task(this, (task_t*)ike_natd_create(this->ike_sa, TRUE));
+ }
+ if (!has_queued(this, TASK_IKE_CERT_PRE))
+ {
+ queue_task(this, (task_t*)ike_cert_pre_create(this->ike_sa, TRUE));
+ }
+ if (!has_queued(this, TASK_IKE_AUTH))
+ {
+ queue_task(this, (task_t*)ike_auth_create(this->ike_sa, TRUE));
+ }
+ if (!has_queued(this, TASK_IKE_CERT_POST))
+ {
+ queue_task(this, (task_t*)ike_cert_post_create(this->ike_sa, TRUE));
+ }
+ if (!has_queued(this, TASK_IKE_CONFIG))
+ {
+ queue_task(this, (task_t*)ike_config_create(this->ike_sa, TRUE));
+ }
+ if (!has_queued(this, TASK_IKE_AUTH_LIFETIME))
+ {
+ queue_task(this, (task_t*)ike_auth_lifetime_create(this->ike_sa, TRUE));
+ }
+ if (!has_queued(this, TASK_IKE_MOBIKE))
+ {
+ peer_cfg_t *peer_cfg;
+
+ peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
+ if (peer_cfg->use_mobike(peer_cfg))
+ {
+ queue_task(this, (task_t*)ike_mobike_create(this->ike_sa, TRUE));
+ }
+ }
+#ifdef ME
+ if (!has_queued(this, TASK_IKE_ME))
+ {
+ queue_task(this, (task_t*)ike_me_create(this->ike_sa, TRUE));
+ }
+#endif /* ME */
+}
+
+METHOD(task_manager_t, queue_ike_rekey, void,
+ private_task_manager_t *this)
+{
+ queue_task(this, (task_t*)ike_rekey_create(this->ike_sa, TRUE));
+}
+
+METHOD(task_manager_t, queue_ike_reauth, void,
+ private_task_manager_t *this)
+{
+ queue_task(this, (task_t*)ike_reauth_create(this->ike_sa));
+}
+
+METHOD(task_manager_t, queue_ike_delete, void,
+ private_task_manager_t *this)
+{
+ queue_task(this, (task_t*)ike_delete_create(this->ike_sa, TRUE));
+}
+
+METHOD(task_manager_t, queue_mobike, void,
+ private_task_manager_t *this, bool roam, bool address)
+{
+ ike_mobike_t *mobike;
+
+ mobike = ike_mobike_create(this->ike_sa, TRUE);
+ if (roam)
+ {
+ mobike->roam(mobike, address);
+ }
+ else
+ {
+ mobike->addresses(mobike);
+ }
+ queue_task(this, &mobike->task);
+}
+
+METHOD(task_manager_t, queue_child, void,
+ private_task_manager_t *this, child_cfg_t *cfg, u_int32_t reqid,
+ traffic_selector_t *tsi, traffic_selector_t *tsr)
+{
+ child_create_t *task;
+
+ task = child_create_create(this->ike_sa, cfg, FALSE, tsi, tsr);
+ if (reqid)
+ {
+ task->use_reqid(task, reqid);
+ }
+ queue_task(this, &task->task);
+}
+
+METHOD(task_manager_t, queue_child_rekey, void,
+ private_task_manager_t *this, protocol_id_t protocol, u_int32_t spi)
+{
+ queue_task(this, (task_t*)child_rekey_create(this->ike_sa, protocol, spi));
+}
+
+METHOD(task_manager_t, queue_child_delete, void,
+ private_task_manager_t *this, protocol_id_t protocol, u_int32_t spi,
+ bool expired)
+{
+ queue_task(this, (task_t*)child_delete_create(this->ike_sa,
+ protocol, spi, expired));
+}
+
+METHOD(task_manager_t, queue_dpd, void,
+ private_task_manager_t *this)
+{
+ ike_mobike_t *mobike;
+
+ if (this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE) &&
+ this->ike_sa->has_condition(this->ike_sa, COND_NAT_HERE))
+ {
+ /* use mobike enabled DPD to detect NAT mapping changes */
+ mobike = ike_mobike_create(this->ike_sa, TRUE);
+ mobike->dpd(mobike);
+ queue_task(this, &mobike->task);
+ }
+ else
+ {
+ queue_task(this, (task_t*)ike_dpd_create(TRUE));
+ }
+}
+
+METHOD(task_manager_t, adopt_tasks, void,
+ private_task_manager_t *this, task_manager_t *other_public)
+{
+ private_task_manager_t *other = (private_task_manager_t*)other_public;
+ task_t *task;
+
+ /* move queued tasks from other to this */
+ while (other->queued_tasks->remove_last(other->queued_tasks,
+ (void**)&task) == SUCCESS)
+ {
+ DBG2(DBG_IKE, "migrating %N task", task_type_names, task->get_type(task));
+ task->migrate(task, this->ike_sa);
+ this->queued_tasks->insert_first(this->queued_tasks, task);
+ }
+}
+
+METHOD(task_manager_t, busy, bool,
+ private_task_manager_t *this)
+{
+ return (this->active_tasks->get_count(this->active_tasks) > 0);
+}
+
+METHOD(task_manager_t, reset, void,
+ private_task_manager_t *this, u_int32_t initiate, u_int32_t respond)
+{
+ enumerator_t *enumerator;
+ task_t *task;
+
+ /* reset message counters and retransmit packets */
+ DESTROY_IF(this->responding.packet);
+ DESTROY_IF(this->initiating.packet);
+ this->responding.packet = NULL;
+ this->initiating.packet = NULL;
+ if (initiate != UINT_MAX)
+ {
+ this->initiating.mid = initiate;
+ }
+ if (respond != UINT_MAX)
+ {
+ this->responding.mid = respond;
+ }
+ this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
+
+ /* reset queued tasks */
+ enumerator = this->queued_tasks->create_enumerator(this->queued_tasks);
+ while (enumerator->enumerate(enumerator, &task))
+ {
+ task->migrate(task, this->ike_sa);
+ }
+ enumerator->destroy(enumerator);
+
+ /* reset active tasks */
+ while (this->active_tasks->remove_last(this->active_tasks,
+ (void**)&task) == SUCCESS)
+ {
+ task->migrate(task, this->ike_sa);
+ this->queued_tasks->insert_first(this->queued_tasks, task);
+ }
+
+ this->reset = TRUE;
+}
+
+METHOD(task_manager_t, create_task_enumerator, enumerator_t*,
+ private_task_manager_t *this, task_queue_t queue)
+{
+ switch (queue)
+ {
+ case TASK_QUEUE_ACTIVE:
+ return this->active_tasks->create_enumerator(this->active_tasks);
+ case TASK_QUEUE_PASSIVE:
+ return this->passive_tasks->create_enumerator(this->passive_tasks);
+ case TASK_QUEUE_QUEUED:
+ return this->queued_tasks->create_enumerator(this->queued_tasks);
+ default:
+ return enumerator_create_empty();
+ }
+}
+
+METHOD(task_manager_t, destroy, void,
+ private_task_manager_t *this)
+{
+ flush(this);
+
+ this->active_tasks->destroy(this->active_tasks);
+ this->queued_tasks->destroy(this->queued_tasks);
+ this->passive_tasks->destroy(this->passive_tasks);
+
+ DESTROY_IF(this->responding.packet);
+ DESTROY_IF(this->initiating.packet);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+task_manager_v2_t *task_manager_v2_create(ike_sa_t *ike_sa)
+{
+ private_task_manager_t *this;
+
+ INIT(this,
+ .public = {
+ .task_manager = {
+ .process_message = _process_message,
+ .queue_task = _queue_task,
+ .queue_ike = _queue_ike,
+ .queue_ike_rekey = _queue_ike_rekey,
+ .queue_ike_reauth = _queue_ike_reauth,
+ .queue_ike_delete = _queue_ike_delete,
+ .queue_mobike = _queue_mobike,
+ .queue_child = _queue_child,
+ .queue_child_rekey = _queue_child_rekey,
+ .queue_child_delete = _queue_child_delete,
+ .queue_dpd = _queue_dpd,
+ .initiate = _initiate,
+ .retransmit = _retransmit,
+ .incr_mid = _incr_mid,
+ .reset = _reset,
+ .adopt_tasks = _adopt_tasks,
+ .busy = _busy,
+ .create_task_enumerator = _create_task_enumerator,
+ .flush_queue = _flush_queue,
+ .destroy = _destroy,
+ },
+ },
+ .ike_sa = ike_sa,
+ .initiating.type = EXCHANGE_TYPE_UNDEFINED,
+ .queued_tasks = linked_list_create(),
+ .active_tasks = linked_list_create(),
+ .passive_tasks = linked_list_create(),
+ .retransmit_tries = lib->settings->get_int(lib->settings,
+ "%s.retransmit_tries", RETRANSMIT_TRIES, charon->name),
+ .retransmit_timeout = lib->settings->get_double(lib->settings,
+ "%s.retransmit_timeout", RETRANSMIT_TIMEOUT, charon->name),
+ .retransmit_base = lib->settings->get_double(lib->settings,
+ "%s.retransmit_base", RETRANSMIT_BASE, charon->name),
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/sa/ikev2/task_manager_v2.h b/src/libcharon/sa/ikev2/task_manager_v2.h
new file mode 100644
index 000000000..70444ae27
--- /dev/null
+++ b/src/libcharon/sa/ikev2/task_manager_v2.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 task_manager_v2 task_manager_v2
+ * @{ @ingroup ikev2
+ */
+
+#ifndef TASK_MANAGER_V2_H_
+#define TASK_MANAGER_V2_H_
+
+typedef struct task_manager_v2_t task_manager_v2_t;
+
+#include <sa/task_manager.h>
+
+/**
+ * Task manager, IKEv2 variant.
+ */
+struct task_manager_v2_t {
+
+ /**
+ * Implements task_manager_t.
+ */
+ task_manager_t task_manager;
+};
+
+/**
+ * Create an instance of the task manager.
+ *
+ * @param ike_sa IKE_SA to manage.
+ */
+task_manager_v2_t *task_manager_v2_create(ike_sa_t *ike_sa);
+
+#endif /** TASK_MANAGER_V2_H_ @}*/
diff --git a/src/libcharon/sa/tasks/child_create.c b/src/libcharon/sa/ikev2/tasks/child_create.c
index 67c29d31f..46a165546 100644
--- a/src/libcharon/sa/tasks/child_create.c
+++ b/src/libcharon/sa/ikev2/tasks/child_create.c
@@ -18,6 +18,7 @@
#include "child_create.h"
#include <daemon.h>
+#include <sa/ikev2/keymat_v2.h>
#include <crypto/diffie_hellman.h>
#include <credentials/certificates/x509.h>
#include <encoding/payloads/sa_payload.h>
@@ -109,7 +110,7 @@ struct private_child_create_t {
/**
* IKE_SAs keymat
*/
- keymat_t *keymat;
+ keymat_v2_t *keymat;
/**
* mode the new CHILD_SA uses (transport/tunnel/beet)
@@ -170,6 +171,11 @@ struct private_child_create_t {
* whether the CHILD_SA rekeys an existing one
*/
bool rekey;
+
+ /**
+ * whether we are retrying with another DH group
+ */
+ bool retry;
};
/**
@@ -191,18 +197,24 @@ static status_t get_nonce(message_t *message, chunk_t *nonce)
/**
* generate a new nonce to include in a CREATE_CHILD_SA message
*/
-static status_t generate_nonce(chunk_t *nonce)
+static status_t generate_nonce(private_child_create_t *this)
{
- rng_t *rng;
+ nonce_gen_t *nonceg;
- rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
- if (!rng)
+ nonceg = this->keymat->keymat.create_nonce_gen(&this->keymat->keymat);
+ if (!nonceg)
{
- DBG1(DBG_IKE, "error generating nonce value, no RNG found");
+ DBG1(DBG_IKE, "no nonce generator found to create nonce");
return FAILED;
}
- rng->allocate_bytes(rng, NONCE_SIZE, nonce);
- rng->destroy(rng);
+ if (!nonceg->allocate_nonce(nonceg, NONCE_SIZE, &this->my_nonce))
+ {
+ DBG1(DBG_IKE, "nonce allocation failed");
+ nonceg->destroy(nonceg);
+ return FAILED;
+ }
+ nonceg->destroy(nonceg);
+
return SUCCESS;
}
@@ -265,7 +277,7 @@ static void schedule_inactivity_timeout(private_child_create_t *this)
if (timeout)
{
close_ike = lib->settings->get_bool(lib->settings,
- "charon.inactivity_close_ike", FALSE);
+ "%s.inactivity_close_ike", FALSE, charon->name);
lib->scheduler->schedule_job(lib->scheduler, (job_t*)
inactivity_job_create(this->child_sa->get_reqid(this->child_sa),
timeout, close_ike), timeout);
@@ -273,6 +285,62 @@ static void schedule_inactivity_timeout(private_child_create_t *this)
}
/**
+ * Check if we have a an address pool configured
+ */
+static bool have_pool(ike_sa_t *ike_sa)
+{
+ enumerator_t *enumerator;
+ peer_cfg_t *peer_cfg;
+ char *pool;
+ bool found = FALSE;
+
+ peer_cfg = ike_sa->get_peer_cfg(ike_sa);
+ if (peer_cfg)
+ {
+ enumerator = peer_cfg->create_pool_enumerator(peer_cfg);
+ if (enumerator->enumerate(enumerator, &pool))
+ {
+ found = TRUE;
+ }
+ enumerator->destroy(enumerator);
+ }
+ return found;
+}
+
+/**
+ * Get hosts to use for dynamic traffic selectors
+ */
+static linked_list_t *get_dynamic_hosts(ike_sa_t *ike_sa, bool local)
+{
+ enumerator_t *enumerator;
+ linked_list_t *list;
+ host_t *host;
+
+ list = linked_list_create();
+ enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, local);
+ while (enumerator->enumerate(enumerator, &host))
+ {
+ list->insert_last(list, host);
+ }
+ enumerator->destroy(enumerator);
+
+ if (list->get_count(list) == 0)
+ { /* no virtual IPs assigned */
+ if (local)
+ {
+ host = ike_sa->get_my_host(ike_sa);
+ list->insert_last(list, host);
+ }
+ else if (!have_pool(ike_sa))
+ { /* use host only if we don't have a pool configured */
+ host = ike_sa->get_other_host(ike_sa);
+ list->insert_last(list, host);
+ }
+ }
+ return list;
+}
+
+/**
* Install a CHILD_SA for usage, return value:
* - FAILED: no acceptable proposal
* - INVALID_ARG: diffie hellman group inacceptable
@@ -285,8 +353,8 @@ static status_t select_and_install(private_child_create_t *this,
chunk_t nonce_i, nonce_r;
chunk_t encr_i = chunk_empty, encr_r = chunk_empty;
chunk_t integ_i = chunk_empty, integ_r = chunk_empty;
- linked_list_t *my_ts, *other_ts;
- host_t *me, *other, *other_vip, *my_vip;
+ linked_list_t *my_ts, *other_ts, *list;
+ host_t *me, *other;
bool private;
if (this->proposals == NULL)
@@ -302,8 +370,6 @@ static status_t select_and_install(private_child_create_t *this,
me = this->ike_sa->get_my_host(this->ike_sa);
other = this->ike_sa->get_other_host(this->ike_sa);
- my_vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
- other_vip = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
private = this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN);
this->proposal = this->config->select_proposal(this->config,
@@ -342,15 +408,6 @@ static status_t select_and_install(private_child_create_t *this,
this->dh_group = MODP_NONE;
}
- if (my_vip == NULL)
- {
- my_vip = me;
- }
- if (other_vip == NULL)
- {
- other_vip = other;
- }
-
if (this->initiator)
{
nonce_i = this->my_nonce;
@@ -365,10 +422,14 @@ static status_t select_and_install(private_child_create_t *this,
my_ts = this->tsr;
other_ts = this->tsi;
}
- my_ts = this->config->get_traffic_selectors(this->config, TRUE, my_ts,
- my_vip);
- other_ts = this->config->get_traffic_selectors(this->config, FALSE, other_ts,
- other_vip);
+ list = get_dynamic_hosts(this->ike_sa, TRUE);
+ my_ts = this->config->get_traffic_selectors(this->config,
+ TRUE, my_ts, list);
+ list->destroy(list);
+ list = get_dynamic_hosts(this->ike_sa, FALSE);
+ other_ts = this->config->get_traffic_selectors(this->config,
+ FALSE, other_ts, list);
+ list->destroy(list);
if (this->initiator)
{
@@ -491,7 +552,32 @@ static status_t select_and_install(private_child_create_t *this,
return FAILED;
}
- status = this->child_sa->add_policies(this->child_sa, my_ts, other_ts);
+ if (this->initiator)
+ {
+ status = this->child_sa->add_policies(this->child_sa, my_ts, other_ts);
+ }
+ else
+ {
+ /* use a copy of the traffic selectors, as the POST hook should not
+ * change payloads */
+ my_ts = this->tsr->clone_offset(this->tsr,
+ offsetof(traffic_selector_t, clone));
+ other_ts = this->tsi->clone_offset(this->tsi,
+ offsetof(traffic_selector_t, clone));
+ charon->bus->narrow(charon->bus, this->child_sa,
+ NARROW_RESPONDER_POST, my_ts, other_ts);
+ if (my_ts->get_count(my_ts) == 0 || other_ts->get_count(other_ts) == 0)
+ {
+ status = FAILED;
+ }
+ else
+ {
+ status = this->child_sa->add_policies(this->child_sa,
+ my_ts, other_ts);
+ }
+ my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
+ other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
+ }
if (status != SUCCESS)
{
DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel");
@@ -526,18 +612,18 @@ static void build_payloads(private_child_create_t *this, message_t *message)
/* add SA payload */
if (this->initiator)
{
- sa_payload = sa_payload_create_from_proposal_list(this->proposals);
+ sa_payload = sa_payload_create_from_proposals_v2(this->proposals);
}
else
{
- sa_payload = sa_payload_create_from_proposal(this->proposal);
+ sa_payload = sa_payload_create_from_proposal_v2(this->proposal);
}
message->add_payload(message, (payload_t*)sa_payload);
/* add nonce payload if not in IKE_AUTH */
if (message->get_exchange_type(message) == CREATE_CHILD_SA)
{
- nonce_payload = nonce_payload_create();
+ nonce_payload = nonce_payload_create(NONCE);
nonce_payload->set_nonce(nonce_payload, this->my_nonce);
message->add_payload(message, (payload_t*)nonce_payload);
}
@@ -545,7 +631,8 @@ static void build_payloads(private_child_create_t *this, message_t *message)
/* diffie hellman exchange, if PFS enabled */
if (this->dh)
{
- ke_payload = ke_payload_create_from_diffie_hellman(this->dh);
+ ke_payload = ke_payload_create_from_diffie_hellman(KEY_EXCHANGE,
+ this->dh);
message->add_payload(message, (payload_t*)ke_payload);
}
@@ -680,7 +767,8 @@ static void process_payloads(private_child_create_t *this, message_t *message)
if (!this->initiator)
{
this->dh_group = ke_payload->get_dh_group_number(ke_payload);
- this->dh = this->keymat->create_dh(this->keymat, this->dh_group);
+ this->dh = this->keymat->keymat.create_dh(
+ &this->keymat->keymat, this->dh_group);
}
if (this->dh)
{
@@ -709,20 +797,22 @@ static void process_payloads(private_child_create_t *this, message_t *message)
METHOD(task_t, build_i, status_t,
private_child_create_t *this, message_t *message)
{
- host_t *me, *other, *vip;
+ enumerator_t *enumerator;
+ host_t *vip;
peer_cfg_t *peer_cfg;
+ linked_list_t *list;
switch (message->get_exchange_type(message))
{
case IKE_SA_INIT:
return get_nonce(message, &this->my_nonce);
case CREATE_CHILD_SA:
- if (generate_nonce(&this->my_nonce) != SUCCESS)
+ if (generate_nonce(this) != SUCCESS)
{
message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
return SUCCESS;
}
- if (this->dh_group == MODP_NONE)
+ if (!this->retry)
{
this->dh_group = this->config->get_dh_group(this->config);
}
@@ -749,36 +839,38 @@ METHOD(task_t, build_i, status_t,
this->config->get_name(this->config));
}
- /* reuse virtual IP if we already have one */
- me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
- if (me == NULL)
- {
- me = this->ike_sa->get_my_host(this->ike_sa);
- }
- other = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
- if (other == NULL)
- {
- other = this->ike_sa->get_other_host(this->ike_sa);
- }
-
/* check if we want a virtual IP, but don't have one */
+ list = linked_list_create();
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
- vip = peer_cfg->get_virtual_ip(peer_cfg);
- if (!this->reqid && vip)
+ if (!this->reqid)
{
- /* propose a 0.0.0.0/0 or ::/0 subnet when we use virtual ip */
- vip = host_create_any(vip->get_family(vip));
- this->tsi = this->config->get_traffic_selectors(this->config, TRUE,
- NULL, vip);
- vip->destroy(vip);
+ enumerator = peer_cfg->create_virtual_ip_enumerator(peer_cfg);
+ while (enumerator->enumerate(enumerator, &vip))
+ {
+ /* propose a 0.0.0.0/0 or ::/0 subnet when we use virtual ip */
+ vip = host_create_any(vip->get_family(vip));
+ list->insert_last(list, vip);
+ }
+ enumerator->destroy(enumerator);
}
- else
- { /* but narrow it for host2host / if we already have a vip */
- this->tsi = this->config->get_traffic_selectors(this->config, TRUE,
- NULL, me);
+ if (list->get_count(list))
+ {
+ this->tsi = this->config->get_traffic_selectors(this->config,
+ TRUE, NULL, list);
+ list->destroy_offset(list, offsetof(host_t, destroy));
}
- this->tsr = this->config->get_traffic_selectors(this->config, FALSE,
- NULL, other);
+ else
+ { /* no virtual IPs configured */
+ list->destroy(list);
+ list = get_dynamic_hosts(this->ike_sa, TRUE);
+ this->tsi = this->config->get_traffic_selectors(this->config,
+ TRUE, NULL, list);
+ list->destroy(list);
+ }
+ list = get_dynamic_hosts(this->ike_sa, FALSE);
+ this->tsr = this->config->get_traffic_selectors(this->config,
+ FALSE, NULL, list);
+ list->destroy(list);
if (this->packet_tsi)
{
@@ -812,7 +904,8 @@ METHOD(task_t, build_i, status_t,
if (this->dh_group != MODP_NONE)
{
- this->dh = this->keymat->create_dh(this->keymat, this->dh_group);
+ this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
+ this->dh_group);
}
if (this->config->use_ipcomp(this->config))
@@ -877,7 +970,7 @@ static void handle_child_sa_failure(private_child_create_t *this,
{
if (message->get_exchange_type(message) == IKE_AUTH &&
lib->settings->get_bool(lib->settings,
- "charon.close_ike_on_child_failure", FALSE))
+ "%s.close_ike_on_child_failure", FALSE, charon->name))
{
/* we delay the delete for 100ms, as the IKE_AUTH response must arrive
* first */
@@ -905,7 +998,7 @@ METHOD(task_t, build_r, status_t,
case IKE_SA_INIT:
return get_nonce(message, &this->my_nonce);
case CREATE_CHILD_SA:
- if (generate_nonce(&this->my_nonce) != SUCCESS)
+ if (generate_nonce(this) != SUCCESS)
{
message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN,
chunk_empty);
@@ -931,22 +1024,16 @@ METHOD(task_t, build_r, status_t,
}
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
- if (peer_cfg && this->tsi && this->tsr)
+ if (!this->config && peer_cfg && this->tsi && this->tsr)
{
- host_t *me, *other;
+ linked_list_t *listr, *listi;
- me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
- if (me == NULL)
- {
- me = this->ike_sa->get_my_host(this->ike_sa);
- }
- other = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
- if (other == NULL)
- {
- other = this->ike_sa->get_other_host(this->ike_sa);
- }
- this->config = peer_cfg->select_child_cfg(peer_cfg, this->tsr,
- this->tsi, me, other);
+ listr = get_dynamic_hosts(this->ike_sa, TRUE);
+ listi = get_dynamic_hosts(this->ike_sa, FALSE);
+ this->config = peer_cfg->select_child_cfg(peer_cfg,
+ this->tsr, this->tsi, listr, listi);
+ listr->destroy(listr);
+ listi->destroy(listi);
}
if (this->config == NULL)
@@ -1108,6 +1195,7 @@ METHOD(task_t, process_i, status_t,
DBG1(DBG_IKE, "peer didn't accept DH group %N, "
"it requested %N", diffie_hellman_group_names,
this->dh_group, diffie_hellman_group_names, group);
+ this->retry = TRUE;
this->dh_group = group;
this->public.task.migrate(&this->public.task, this->ike_sa);
enumerator->destroy(enumerator);
@@ -1192,6 +1280,13 @@ METHOD(child_create_t, get_child, child_sa_t*,
return this->child_sa;
}
+METHOD(child_create_t, set_config, void,
+ private_child_create_t *this, child_cfg_t *cfg)
+{
+ DESTROY_IF(this->config);
+ this->config = cfg;
+}
+
METHOD(child_create_t, get_lower_nonce, chunk_t,
private_child_create_t *this)
{
@@ -1209,7 +1304,7 @@ METHOD(child_create_t, get_lower_nonce, chunk_t,
METHOD(task_t, get_type, task_type_t,
private_child_create_t *this)
{
- return CHILD_CREATE;
+ return TASK_CHILD_CREATE;
}
METHOD(task_t, migrate, void,
@@ -1234,7 +1329,7 @@ METHOD(task_t, migrate, void,
}
this->ike_sa = ike_sa;
- this->keymat = ike_sa->get_keymat(ike_sa);
+ this->keymat = (keymat_v2_t*)ike_sa->get_keymat(ike_sa);
this->proposal = NULL;
this->proposals = NULL;
this->tsi = NULL;
@@ -1291,6 +1386,7 @@ child_create_t *child_create_create(ike_sa_t *ike_sa,
INIT(this,
.public = {
.get_child = _get_child,
+ .set_config = _set_config,
.get_lower_nonce = _get_lower_nonce,
.use_reqid = _use_reqid,
.task = {
@@ -1304,12 +1400,13 @@ child_create_t *child_create_create(ike_sa_t *ike_sa,
.packet_tsi = tsi ? tsi->clone(tsi) : NULL,
.packet_tsr = tsr ? tsr->clone(tsr) : NULL,
.dh_group = MODP_NONE,
- .keymat = ike_sa->get_keymat(ike_sa),
+ .keymat = (keymat_v2_t*)ike_sa->get_keymat(ike_sa),
.mode = MODE_TUNNEL,
.tfcv3 = TRUE,
.ipcomp = IPCOMP_NONE,
.ipcomp_received = IPCOMP_NONE,
.rekey = rekey,
+ .retry = FALSE,
);
if (config)
@@ -1317,7 +1414,6 @@ child_create_t *child_create_create(ike_sa_t *ike_sa,
this->public.task.build = _build_i;
this->public.task.process = _process_i;
this->initiator = TRUE;
- config->get_ref(config);
}
else
{
diff --git a/src/libcharon/sa/tasks/child_create.h b/src/libcharon/sa/ikev2/tasks/child_create.h
index 5dedeb8b1..d29ba3d98 100644
--- a/src/libcharon/sa/tasks/child_create.h
+++ b/src/libcharon/sa/ikev2/tasks/child_create.h
@@ -15,7 +15,7 @@
/**
* @defgroup child_create child_create
- * @{ @ingroup tasks
+ * @{ @ingroup tasks_v2
*/
#ifndef CHILD_CREATE_H_
@@ -25,11 +25,11 @@ typedef struct child_create_t child_create_t;
#include <library.h>
#include <sa/ike_sa.h>
-#include <sa/tasks/task.h>
+#include <sa/task.h>
#include <config/child_cfg.h>
/**
- * Task of type CHILD_CREATE, established a new CHILD_SA.
+ * Task of type TASK_CHILD_CREATE, established a new CHILD_SA.
*
* This task may be included in the IKE_AUTH message or in a separate
* CREATE_CHILD_SA exchange.
@@ -64,6 +64,13 @@ struct child_create_t {
* @return child_sa
*/
child_sa_t* (*get_child) (child_create_t *this);
+
+ /**
+ * Enforce a specific CHILD_SA config as responder.
+ *
+ * @param cfg configuration to enforce, reference gets owned
+ */
+ void (*set_config)(child_create_t *this, child_cfg_t *cfg);
};
/**
diff --git a/src/libcharon/sa/tasks/child_delete.c b/src/libcharon/sa/ikev2/tasks/child_delete.c
index dc4b30dd3..644af782c 100644
--- a/src/libcharon/sa/tasks/child_delete.c
+++ b/src/libcharon/sa/ikev2/tasks/child_delete.c
@@ -62,6 +62,11 @@ struct private_child_delete_t {
bool rekeyed;
/**
+ * CHILD_SA already expired?
+ */
+ bool expired;
+
+ /**
* CHILD_SAs which get deleted
*/
linked_list_t *child_sas;
@@ -87,7 +92,7 @@ static void build_payloads(private_child_delete_t *this, message_t *message)
case PROTO_ESP:
if (esp == NULL)
{
- esp = delete_payload_create(PROTO_ESP);
+ esp = delete_payload_create(DELETE, PROTO_ESP);
message->add_payload(message, (payload_t*)esp);
}
esp->add_spi(esp, spi);
@@ -97,7 +102,7 @@ static void build_payloads(private_child_delete_t *this, message_t *message)
case PROTO_AH:
if (ah == NULL)
{
- ah = delete_payload_create(PROTO_AH);
+ ah = delete_payload_create(DELETE, PROTO_AH);
message->add_payload(message, (payload_t*)ah);
}
ah->add_spi(ah, spi);
@@ -247,16 +252,29 @@ static void log_children(private_child_delete_t *this)
enumerator = this->child_sas->create_enumerator(this->child_sas);
while (enumerator->enumerate(enumerator, (void**)&child_sa))
{
- child_sa->get_usestats(child_sa, TRUE, NULL, &bytes_in);
- child_sa->get_usestats(child_sa, FALSE, NULL, &bytes_out);
-
- DBG0(DBG_IKE, "closing CHILD_SA %s{%d} "
- "with SPIs %.8x_i (%llu bytes) %.8x_o (%llu bytes) and TS %#R=== %#R",
- child_sa->get_name(child_sa), child_sa->get_reqid(child_sa),
- ntohl(child_sa->get_spi(child_sa, TRUE)), bytes_in,
- ntohl(child_sa->get_spi(child_sa, FALSE)), bytes_out,
- child_sa->get_traffic_selectors(child_sa, TRUE),
- child_sa->get_traffic_selectors(child_sa, FALSE));
+ if (this->expired)
+ {
+ DBG0(DBG_IKE, "closing expired CHILD_SA %s{%d} "
+ "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
+ child_sa->get_name(child_sa), child_sa->get_reqid(child_sa),
+ ntohl(child_sa->get_spi(child_sa, TRUE)),
+ ntohl(child_sa->get_spi(child_sa, FALSE)),
+ child_sa->get_traffic_selectors(child_sa, TRUE),
+ child_sa->get_traffic_selectors(child_sa, FALSE));
+ }
+ else
+ {
+ child_sa->get_usestats(child_sa, TRUE, NULL, &bytes_in);
+ child_sa->get_usestats(child_sa, FALSE, NULL, &bytes_out);
+
+ DBG0(DBG_IKE, "closing CHILD_SA %s{%d} with SPIs %.8x_i "
+ "(%llu bytes) %.8x_o (%llu bytes) and TS %#R=== %#R",
+ child_sa->get_name(child_sa), child_sa->get_reqid(child_sa),
+ ntohl(child_sa->get_spi(child_sa, TRUE)), bytes_in,
+ ntohl(child_sa->get_spi(child_sa, FALSE)), bytes_out,
+ child_sa->get_traffic_selectors(child_sa, TRUE),
+ child_sa->get_traffic_selectors(child_sa, FALSE));
+ }
}
enumerator->destroy(enumerator);
}
@@ -324,7 +342,7 @@ METHOD(task_t, build_r, status_t,
METHOD(task_t, get_type, task_type_t,
private_child_delete_t *this)
{
- return CHILD_DELETE;
+ return TASK_CHILD_DELETE;
}
METHOD(child_delete_t , get_child, child_sa_t*,
@@ -356,7 +374,7 @@ METHOD(task_t, destroy, void,
* Described in header.
*/
child_delete_t *child_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol,
- u_int32_t spi)
+ u_int32_t spi, bool expired)
{
private_child_delete_t *this;
@@ -373,6 +391,7 @@ child_delete_t *child_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol,
.child_sas = linked_list_create(),
.protocol = protocol,
.spi = spi,
+ .expired = expired,
);
if (protocol != PROTO_NONE)
diff --git a/src/libcharon/sa/tasks/child_delete.h b/src/libcharon/sa/ikev2/tasks/child_delete.h
index 365807c68..1ada0699e 100644
--- a/src/libcharon/sa/tasks/child_delete.h
+++ b/src/libcharon/sa/ikev2/tasks/child_delete.h
@@ -15,7 +15,7 @@
/**
* @defgroup child_delete child_delete
- * @{ @ingroup tasks
+ * @{ @ingroup tasks_v2
*/
#ifndef CHILD_DELETE_H_
@@ -25,7 +25,7 @@ typedef struct child_delete_t child_delete_t;
#include <library.h>
#include <sa/ike_sa.h>
-#include <sa/tasks/task.h>
+#include <sa/task.h>
#include <sa/child_sa.h>
/**
@@ -52,9 +52,10 @@ struct child_delete_t {
* @param ike_sa IKE_SA this task works for
* @param protocol protocol of CHILD_SA to delete, PROTO_NONE as responder
* @param spi inbound SPI of CHILD_SA to delete
+ * @param expired TRUE if CHILD_SA already expired
* @return child_delete task to handle by the task_manager
*/
child_delete_t *child_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol,
- u_int32_t spi);
+ u_int32_t spi, bool expired);
#endif /** CHILD_DELETE_H_ @}*/
diff --git a/src/libcharon/sa/tasks/child_rekey.c b/src/libcharon/sa/ikev2/tasks/child_rekey.c
index 76d185590..f8c2ed141 100644
--- a/src/libcharon/sa/tasks/child_rekey.c
+++ b/src/libcharon/sa/ikev2/tasks/child_rekey.c
@@ -18,8 +18,8 @@
#include <daemon.h>
#include <encoding/payloads/notify_payload.h>
-#include <sa/tasks/child_create.h>
-#include <sa/tasks/child_delete.h>
+#include <sa/ikev2/tasks/child_create.h>
+#include <sa/ikev2/tasks/child_delete.h>
#include <processing/jobs/rekey_child_sa_job.h>
#include <processing/jobs/rekey_ike_sa_job.h>
@@ -153,16 +153,16 @@ 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(this->protocol,
- REKEY_SA);
+ notify = notify_payload_create_from_protocol_and_type(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. */
if (!this->child_create)
{
- this->child_create = child_create_create(this->ike_sa, config, TRUE,
- NULL, NULL);
+ this->child_create = child_create_create(this->ike_sa,
+ config->get_ref(config), TRUE, NULL, NULL);
}
reqid = this->child_sa->get_reqid(this->child_sa);
this->child_create->use_reqid(this->child_create, reqid);
@@ -187,6 +187,7 @@ METHOD(task_t, process_r, status_t,
METHOD(task_t, build_r, status_t,
private_child_rekey_t *this, message_t *message)
{
+ child_cfg_t *config;
u_int32_t reqid;
if (this->child_sa == NULL ||
@@ -200,6 +201,8 @@ METHOD(task_t, build_r, status_t,
/* let the CHILD_CREATE task build the response */
reqid = this->child_sa->get_reqid(this->child_sa);
this->child_create->use_reqid(this->child_create, reqid);
+ config = this->child_sa->get_config(this->child_sa);
+ this->child_create->set_config(this->child_create, config->get_ref(config));
this->child_create->task.build(&this->child_create->task, message);
if (message->get_payload(message, SECURITY_ASSOCIATION) == NULL)
@@ -224,7 +227,7 @@ static child_sa_t *handle_collision(private_child_rekey_t *this)
{
child_sa_t *to_delete;
- if (this->collision->get_type(this->collision) == CHILD_REKEY)
+ if (this->collision->get_type(this->collision) == TASK_CHILD_REKEY)
{
chunk_t this_nonce, other_nonce;
private_child_rekey_t *other = (private_child_rekey_t*)this->collision;
@@ -311,7 +314,7 @@ METHOD(task_t, process_i, status_t,
/* establishing new child failed, reuse old. but not when we
* received a delete in the meantime */
if (!(this->collision &&
- this->collision->get_type(this->collision) == CHILD_DELETE))
+ this->collision->get_type(this->collision) == TASK_CHILD_DELETE))
{
job_t *job;
u_int32_t retry = RETRY_INTERVAL - (random() % RETRY_JITTER);
@@ -352,7 +355,7 @@ METHOD(task_t, process_i, status_t,
protocol = to_delete->get_protocol(to_delete);
/* rekeying done, delete the obsolete CHILD_SA using a subtask */
- this->child_delete = child_delete_create(this->ike_sa, protocol, spi);
+ this->child_delete = child_delete_create(this->ike_sa, protocol, spi, FALSE);
this->public.task.build = (status_t(*)(task_t*,message_t*))build_i_delete;
this->public.task.process = (status_t(*)(task_t*,message_t*))process_i_delete;
@@ -362,7 +365,7 @@ METHOD(task_t, process_i, status_t,
METHOD(task_t, get_type, task_type_t,
private_child_rekey_t *this)
{
- return CHILD_REKEY;
+ return TASK_CHILD_REKEY;
}
METHOD(child_rekey_t, collide, void,
@@ -370,7 +373,7 @@ METHOD(child_rekey_t, collide, void,
{
/* the task manager only detects exchange collision, but not if
* the collision is for the same child. we check it here. */
- if (other->get_type(other) == CHILD_REKEY)
+ if (other->get_type(other) == TASK_CHILD_REKEY)
{
private_child_rekey_t *rekey = (private_child_rekey_t*)other;
if (rekey->child_sa != this->child_sa)
@@ -380,7 +383,7 @@ METHOD(child_rekey_t, collide, void,
return;
}
}
- else if (other->get_type(other) == CHILD_DELETE)
+ else if (other->get_type(other) == TASK_CHILD_DELETE)
{
child_delete_t *del = (child_delete_t*)other;
if (del->get_child(del) == this->child_create->get_child(this->child_create))
@@ -403,8 +406,8 @@ METHOD(child_rekey_t, collide, void,
other->destroy(other);
return;
}
- DBG1(DBG_IKE, "detected %N collision with %N", task_type_names, CHILD_REKEY,
- task_type_names, other->get_type(other));
+ DBG1(DBG_IKE, "detected %N collision with %N", task_type_names,
+ TASK_CHILD_REKEY, task_type_names, other->get_type(other));
DESTROY_IF(this->collision);
this->collision = other;
}
@@ -462,7 +465,7 @@ child_rekey_t *child_rekey_create(ike_sa_t *ike_sa, protocol_id_t protocol,
.protocol = protocol,
.spi = spi,
);
-
+
if (protocol != PROTO_NONE)
{
this->public.task.build = _build_i;
diff --git a/src/libcharon/sa/tasks/child_rekey.h b/src/libcharon/sa/ikev2/tasks/child_rekey.h
index 9b1aea5fa..23384653d 100644
--- a/src/libcharon/sa/tasks/child_rekey.h
+++ b/src/libcharon/sa/ikev2/tasks/child_rekey.h
@@ -15,7 +15,7 @@
/**
* @defgroup child_rekey child_rekey
- * @{ @ingroup tasks
+ * @{ @ingroup tasks_v2
*/
#ifndef CHILD_REKEY_H_
@@ -26,10 +26,10 @@ typedef struct child_rekey_t child_rekey_t;
#include <library.h>
#include <sa/ike_sa.h>
#include <sa/child_sa.h>
-#include <sa/tasks/task.h>
+#include <sa/task.h>
/**
- * Task of type CHILD_REKEY, rekey an established CHILD_SA.
+ * Task of type TASK_CHILD_REKEY, rekey an established CHILD_SA.
*/
struct child_rekey_t {
@@ -51,7 +51,7 @@ struct child_rekey_t {
};
/**
- * Create a new CHILD_REKEY task.
+ * Create a new TASK_CHILD_REKEY task.
*
* @param ike_sa IKE_SA this task works for
* @param protocol protocol of CHILD_SA to rekey, PROTO_NONE as responder
diff --git a/src/libcharon/sa/tasks/ike_auth.c b/src/libcharon/sa/ikev2/tasks/ike_auth.c
index 665468fe8..cd94ccd9e 100644
--- a/src/libcharon/sa/tasks/ike_auth.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_auth.c
@@ -24,7 +24,7 @@
#include <encoding/payloads/auth_payload.h>
#include <encoding/payloads/eap_payload.h>
#include <encoding/payloads/nonce_payload.h>
-#include <sa/authenticators/eap_authenticator.h>
+#include <sa/ikev2/authenticators/eap_authenticator.h>
typedef struct private_ike_auth_t private_ike_auth_t;
@@ -120,7 +120,7 @@ struct private_ike_auth_t {
static bool multiple_auth_enabled()
{
return lib->settings->get_bool(lib->settings,
- "charon.multiple_authentication", TRUE);
+ "%s.multiple_authentication", TRUE, charon->name);
}
/**
@@ -270,8 +270,10 @@ static bool load_cfg_candidates(private_ike_auth_t *this)
my_id = this->ike_sa->get_my_id(this->ike_sa);
other_id = this->ike_sa->get_other_id(this->ike_sa);
+ DBG1(DBG_CFG, "looking for peer configs matching %H[%Y]...%H[%Y]",
+ me, my_id, other, other_id);
enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
- me, other, my_id, other_id);
+ me, other, my_id, other_id, IKEV2);
while (enumerator->enumerate(enumerator, &peer_cfg))
{
peer_cfg->get_ref(peer_cfg);
@@ -406,7 +408,8 @@ METHOD(task_t, build_i, status_t,
if (cfg)
{
idr = cfg->get(cfg, AUTH_RULE_IDENTITY);
- if (idr && !idr->contains_wildcards(idr))
+ if (!cfg->get(cfg, AUTH_RULE_IDENTITY_LOOSE) && idr &&
+ !idr->contains_wildcards(idr))
{
this->ike_sa->set_other_id(this->ike_sa, idr->clone(idr));
id_payload = id_payload_create_from_identification(
@@ -433,7 +436,8 @@ METHOD(task_t, build_i, status_t,
message->add_payload(message, (payload_t*)id_payload);
if (idr && message->get_message_id(message) == 1 &&
- this->peer_cfg->get_unique_policy(this->peer_cfg) != UNIQUE_NO)
+ this->peer_cfg->get_unique_policy(this->peer_cfg) != UNIQUE_NO &&
+ this->peer_cfg->get_unique_policy(this->peer_cfg) != UNIQUE_NEVER)
{
host_t *host;
@@ -1033,7 +1037,7 @@ peer_auth_failed:
METHOD(task_t, get_type, task_type_t,
private_ike_auth_t *this)
{
- return IKE_AUTHENTICATE;
+ return TASK_IKE_AUTH;
}
METHOD(task_t, migrate, void,
@@ -1104,4 +1108,3 @@ ike_auth_t *ike_auth_create(ike_sa_t *ike_sa, bool initiator)
}
return &this->public;
}
-
diff --git a/src/libcharon/sa/tasks/ike_auth.h b/src/libcharon/sa/ikev2/tasks/ike_auth.h
index 132907941..ca864a710 100644
--- a/src/libcharon/sa/tasks/ike_auth.h
+++ b/src/libcharon/sa/ikev2/tasks/ike_auth.h
@@ -15,7 +15,7 @@
/**
* @defgroup ike_auth ike_auth
- * @{ @ingroup tasks
+ * @{ @ingroup tasks_v2
*/
#ifndef IKE_AUTH_H_
@@ -25,7 +25,7 @@ typedef struct ike_auth_t ike_auth_t;
#include <library.h>
#include <sa/ike_sa.h>
-#include <sa/tasks/task.h>
+#include <sa/task.h>
/**
* Task of type ike_auth, authenticates an IKE_SA using authenticators.
@@ -46,7 +46,7 @@ struct ike_auth_t {
};
/**
- * Create a new task of type IKE_AUTHENTICATE.
+ * Create a new task of type TASK_IKE_AUTH.
*
* @param ike_sa IKE_SA this task works for
* @param initiator TRUE if task is the initiator of an exchange
diff --git a/src/libcharon/sa/tasks/ike_auth_lifetime.c b/src/libcharon/sa/ikev2/tasks/ike_auth_lifetime.c
index a57cfd075..a7d162e68 100644
--- a/src/libcharon/sa/tasks/ike_auth_lifetime.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_auth_lifetime.c
@@ -124,7 +124,7 @@ METHOD(task_t, process_i, status_t,
METHOD(task_t, get_type, task_type_t,
private_ike_auth_lifetime_t *this)
{
- return IKE_AUTH_LIFETIME;
+ return TASK_IKE_AUTH_LIFETIME;
}
METHOD(task_t, migrate, void,
@@ -170,4 +170,3 @@ ike_auth_lifetime_t *ike_auth_lifetime_create(ike_sa_t *ike_sa, bool initiator)
return &this->public;
}
-
diff --git a/src/libcharon/sa/tasks/ike_auth_lifetime.h b/src/libcharon/sa/ikev2/tasks/ike_auth_lifetime.h
index 3b129b9e3..4d5087ff5 100644
--- a/src/libcharon/sa/tasks/ike_auth_lifetime.h
+++ b/src/libcharon/sa/ikev2/tasks/ike_auth_lifetime.h
@@ -15,7 +15,7 @@
/**
* @defgroup ike_auth_lifetime ike_auth_lifetime
- * @{ @ingroup tasks
+ * @{ @ingroup tasks_v2
*/
#ifndef IKE_AUTH_LIFETIME_H_
@@ -25,10 +25,10 @@ typedef struct ike_auth_lifetime_t ike_auth_lifetime_t;
#include <library.h>
#include <sa/ike_sa.h>
-#include <sa/tasks/task.h>
+#include <sa/task.h>
/**
- * Task of type IKE_AUTH_LIFETIME, implements RFC4478.
+ * Task of type TASK_IKE_AUTH_LIFETIME, implements RFC4478.
*
* This task exchanges lifetimes for IKE_AUTH to force a client to
* reauthenticate before the responders lifetime reaches the limit.
@@ -42,7 +42,7 @@ struct ike_auth_lifetime_t {
};
/**
- * Create a new IKE_AUTH_LIFETIME task.
+ * Create a new TASK_IKE_AUTH_LIFETIME task.
*
* @param ike_sa IKE_SA this task works for
* @param initiator TRUE if taks is initiated by us
@@ -50,4 +50,4 @@ struct ike_auth_lifetime_t {
*/
ike_auth_lifetime_t *ike_auth_lifetime_create(ike_sa_t *ike_sa, bool initiator);
-#endif /** IKE_MOBIKE_H_ @}*/
+#endif /** IKE_AUTH_LIFETIME_H_ @}*/
diff --git a/src/libcharon/sa/tasks/ike_cert_post.c b/src/libcharon/sa/ikev2/tasks/ike_cert_post.c
index 94af50eae..a93e5137e 100644
--- a/src/libcharon/sa/tasks/ike_cert_post.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_cert_post.c
@@ -62,14 +62,14 @@ static cert_payload_t *build_cert_payload(private_ike_cert_post_t *this,
if (!this->ike_sa->supports_extension(this->ike_sa, EXT_HASH_AND_URL))
{
- return cert_payload_create_from_cert(cert);
+ return cert_payload_create_from_cert(CERTIFICATE, cert);
}
hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
if (!hasher)
{
DBG1(DBG_IKE, "unable to use hash-and-url: sha1 not supported");
- return cert_payload_create_from_cert(cert);
+ return cert_payload_create_from_cert(CERTIFICATE, cert);
}
if (!cert->get_encoding(cert, CERT_ASN1_DER, &encoded))
@@ -78,7 +78,12 @@ static cert_payload_t *build_cert_payload(private_ike_cert_post_t *this,
hasher->destroy(hasher);
return NULL;
}
- hasher->allocate_hash(hasher, encoded, &hash);
+ if (!hasher->allocate_hash(hasher, encoded, &hash))
+ {
+ hasher->destroy(hasher);
+ chunk_free(&encoded);
+ return cert_payload_create_from_cert(CERTIFICATE, cert);
+ }
chunk_free(&encoded);
hasher->destroy(hasher);
id = identification_create_from_encoding(ID_KEY_ID, hash);
@@ -91,7 +96,7 @@ static cert_payload_t *build_cert_payload(private_ike_cert_post_t *this,
}
else
{
- payload = cert_payload_create_from_cert(cert);
+ payload = cert_payload_create_from_cert(CERTIFICATE, cert);
}
enumerator->destroy(enumerator);
chunk_free(&hash);
@@ -154,7 +159,7 @@ static void build_certs(private_ike_cert_post_t *this, message_t *message)
{
if (type == AUTH_RULE_IM_CERT)
{
- payload = cert_payload_create_from_cert(cert);
+ payload = cert_payload_create_from_cert(CERTIFICATE, cert);
if (payload)
{
DBG1(DBG_IKE, "sending issuer cert \"%Y\"",
@@ -207,7 +212,7 @@ METHOD(task_t, process_i, status_t,
METHOD(task_t, get_type, task_type_t,
private_ike_cert_post_t *this)
{
- return IKE_CERT_POST;
+ return TASK_IKE_CERT_POST;
}
METHOD(task_t, migrate, void,
@@ -254,4 +259,3 @@ ike_cert_post_t *ike_cert_post_create(ike_sa_t *ike_sa, bool initiator)
return &this->public;
}
-
diff --git a/src/libcharon/sa/tasks/ike_cert_post.h b/src/libcharon/sa/ikev2/tasks/ike_cert_post.h
index b3881a01a..34606b1e8 100644
--- a/src/libcharon/sa/tasks/ike_cert_post.h
+++ b/src/libcharon/sa/ikev2/tasks/ike_cert_post.h
@@ -15,7 +15,7 @@
/**
* @defgroup ike_cert_post ike_cert_post
- * @{ @ingroup tasks
+ * @{ @ingroup tasks_v2
*/
#ifndef IKE_CERT_POST_H_
@@ -25,7 +25,7 @@ typedef struct ike_cert_post_t ike_cert_post_t;
#include <library.h>
#include <sa/ike_sa.h>
-#include <sa/tasks/task.h>
+#include <sa/task.h>
/**
* Task of type ike_cert_post, certificate processing after authentication.
diff --git a/src/libcharon/sa/tasks/ike_cert_pre.c b/src/libcharon/sa/ikev2/tasks/ike_cert_pre.c
index b33aebe46..60e878777 100644
--- a/src/libcharon/sa/tasks/ike_cert_pre.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_cert_pre.c
@@ -398,7 +398,8 @@ static void build_certreqs(private_ike_cert_pre_t *this, message_t *message)
{
message->add_payload(message, (payload_t*)req);
- if (lib->settings->get_bool(lib->settings, "charon.hash_and_url", FALSE))
+ if (lib->settings->get_bool(lib->settings,
+ "%s.hash_and_url", FALSE, charon->name))
{
message->add_notify(message, FALSE, HTTP_CERT_LOOKUP_SUPPORTED,
chunk_empty);
@@ -479,7 +480,7 @@ METHOD(task_t, process_i, status_t,
METHOD(task_t, get_type, task_type_t,
private_ike_cert_pre_t *this)
{
- return IKE_CERT_PRE;
+ return TASK_IKE_CERT_PRE;
}
METHOD(task_t, migrate, void,
diff --git a/src/libcharon/sa/tasks/ike_cert_pre.h b/src/libcharon/sa/ikev2/tasks/ike_cert_pre.h
index 4b2d0d470..ac1a85c29 100644
--- a/src/libcharon/sa/tasks/ike_cert_pre.h
+++ b/src/libcharon/sa/ikev2/tasks/ike_cert_pre.h
@@ -15,7 +15,7 @@
/**
* @defgroup ike_cert_pre ike_cert_pre
- * @{ @ingroup tasks
+ * @{ @ingroup tasks_v2
*/
#ifndef IKE_CERT_PRE_H_
@@ -25,7 +25,7 @@ typedef struct ike_cert_pre_t ike_cert_pre_t;
#include <library.h>
#include <sa/ike_sa.h>
-#include <sa/tasks/task.h>
+#include <sa/task.h>
/**
* Task of type ike_cert_post, certificate processing before authentication.
diff --git a/src/libcharon/sa/tasks/ike_config.c b/src/libcharon/sa/ikev2/tasks/ike_config.c
index 4ef9c56a5..c44f0452c 100644
--- a/src/libcharon/sa/tasks/ike_config.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_config.c
@@ -43,9 +43,9 @@ struct private_ike_config_t {
bool initiator;
/**
- * virtual ip
+ * Received list of virtual IPs, host_t*
*/
- host_t *virtual_ip;
+ linked_list_t *vips;
/**
* list of attributes requested and its handler, entry_t
@@ -98,7 +98,8 @@ static configuration_attribute_t *build_vip(host_t *vip)
chunk = chunk_cata("cc", chunk, prefix);
}
}
- return configuration_attribute_create_value(type, chunk);
+ return configuration_attribute_create_chunk(CONFIGURATION_ATTRIBUTE,
+ type, chunk);
}
/**
@@ -128,11 +129,11 @@ static void handle_attribute(private_ike_config_t *this,
/* and pass it to the handle function */
handler = hydra->attributes->handle(hydra->attributes,
this->ike_sa->get_other_id(this->ike_sa), handler,
- ca->get_type(ca), ca->get_value(ca));
+ ca->get_type(ca), ca->get_chunk(ca));
if (handler)
{
this->ike_sa->add_configuration_attribute(this->ike_sa,
- handler, ca->get_type(ca), ca->get_value(ca));
+ handler, ca->get_type(ca), ca->get_chunk(ca));
}
}
@@ -153,7 +154,7 @@ static void process_attribute(private_ike_config_t *this,
/* fall */
case INTERNAL_IP6_ADDRESS:
{
- addr = ca->get_value(ca);
+ addr = ca->get_chunk(ca);
if (addr.len == 0)
{
ip = host_create_any(family);
@@ -169,8 +170,7 @@ static void process_attribute(private_ike_config_t *this,
}
if (ip)
{
- DESTROY_IF(this->virtual_ip);
- this->virtual_ip = ip;
+ this->vips->insert_last(this->vips, ip);
}
break;
}
@@ -241,23 +241,45 @@ METHOD(task_t, build_i, status_t,
peer_cfg_t *config;
configuration_attribute_type_t type;
chunk_t data;
- host_t *vip;
+ linked_list_t *vips;
+ host_t *host;
+
+ vips = linked_list_create();
/* reuse virtual IP if we already have one */
- vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
- if (!vip)
+ enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa,
+ TRUE);
+ while (enumerator->enumerate(enumerator, &host))
+ {
+ vips->insert_last(vips, host);
+ }
+ enumerator->destroy(enumerator);
+
+ if (vips->get_count(vips) == 0)
{
config = this->ike_sa->get_peer_cfg(this->ike_sa);
- vip = config->get_virtual_ip(config);
+ enumerator = config->create_virtual_ip_enumerator(config);
+ while (enumerator->enumerate(enumerator, &host))
+ {
+ vips->insert_last(vips, host);
+ }
+ enumerator->destroy(enumerator);
}
- if (vip)
+
+ if (vips->get_count(vips))
{
- cp = cp_payload_create_type(CFG_REQUEST);
- cp->add_attribute(cp, build_vip(vip));
+ cp = cp_payload_create_type(CONFIGURATION, CFG_REQUEST);
+ enumerator = vips->create_enumerator(vips);
+ while (enumerator->enumerate(enumerator, &host))
+ {
+ cp->add_attribute(cp, build_vip(host));
+ }
+ enumerator->destroy(enumerator);
}
- enumerator = hydra->attributes->create_initiator_enumerator(hydra->attributes,
- this->ike_sa->get_other_id(this->ike_sa), vip);
+ enumerator = hydra->attributes->create_initiator_enumerator(
+ hydra->attributes,
+ this->ike_sa->get_other_id(this->ike_sa), vips);
while (enumerator->enumerate(enumerator, &handler, &type, &data))
{
configuration_attribute_t *ca;
@@ -266,10 +288,11 @@ METHOD(task_t, build_i, status_t,
/* create configuration attribute */
DBG2(DBG_IKE, "building %N attribute",
configuration_attribute_type_names, type);
- ca = configuration_attribute_create_value(type, data);
+ ca = configuration_attribute_create_chunk(CONFIGURATION_ATTRIBUTE,
+ type, data);
if (!cp)
{
- cp = cp_payload_create_type(CFG_REQUEST);
+ cp = cp_payload_create_type(CONFIGURATION, CFG_REQUEST);
}
cp->add_attribute(cp, ca);
@@ -282,6 +305,8 @@ METHOD(task_t, build_i, status_t,
}
enumerator->destroy(enumerator);
+ vips->destroy(vips);
+
if (cp)
{
message->add_payload(message, (payload_t*)cp);
@@ -308,58 +333,92 @@ METHOD(task_t, build_r, status_t,
enumerator_t *enumerator;
configuration_attribute_type_t type;
chunk_t value;
- host_t *vip = NULL;
cp_payload_t *cp = NULL;
peer_cfg_t *config;
identification_t *id;
+ linked_list_t *vips, *pools;
+ host_t *requested;
id = this->ike_sa->get_other_eap_id(this->ike_sa);
-
config = this->ike_sa->get_peer_cfg(this->ike_sa);
- if (this->virtual_ip)
+ vips = linked_list_create();
+ pools = linked_list_create_from_enumerator(
+ config->create_pool_enumerator(config));
+
+ this->ike_sa->clear_virtual_ips(this->ike_sa, FALSE);
+
+ enumerator = this->vips->create_enumerator(this->vips);
+ while (enumerator->enumerate(enumerator, &requested))
{
- DBG1(DBG_IKE, "peer requested virtual IP %H", this->virtual_ip);
- if (config->get_pool(config))
+ host_t *found = NULL;
+
+ /* query all pools until we get an address */
+ DBG1(DBG_IKE, "peer requested virtual IP %H", requested);
+
+ found = hydra->attributes->acquire_address(hydra->attributes,
+ pools, id, requested);
+ if (found)
{
- vip = hydra->attributes->acquire_address(hydra->attributes,
- config->get_pool(config), id, this->virtual_ip);
+ DBG1(DBG_IKE, "assigning virtual IP %H to peer '%Y'", found, id);
+ this->ike_sa->add_virtual_ip(this->ike_sa, FALSE, found);
+ if (!cp)
+ {
+ cp = cp_payload_create_type(CONFIGURATION, CFG_REPLY);
+ }
+ cp->add_attribute(cp, build_vip(found));
+ vips->insert_last(vips, found);
}
- if (vip == NULL)
+ else
{
- DBG1(DBG_IKE, "no virtual IP found, sending %N",
- notify_type_names, INTERNAL_ADDRESS_FAILURE);
- message->add_notify(message, FALSE, INTERNAL_ADDRESS_FAILURE,
- chunk_empty);
- return SUCCESS;
+ DBG1(DBG_IKE, "no virtual IP found for %H requested by '%Y'",
+ requested, id);
}
- DBG1(DBG_IKE, "assigning virtual IP %H to peer '%Y'", vip, id);
- this->ike_sa->set_virtual_ip(this->ike_sa, FALSE, vip);
+ }
+ enumerator->destroy(enumerator);
- cp = cp_payload_create_type(CFG_REPLY);
- cp->add_attribute(cp, build_vip(vip));
+ if (this->vips->get_count(this->vips) && !vips->get_count(vips))
+ {
+ DBG1(DBG_IKE, "no virtual IP found, sending %N",
+ notify_type_names, INTERNAL_ADDRESS_FAILURE);
+ message->add_notify(message, FALSE, INTERNAL_ADDRESS_FAILURE,
+ chunk_empty);
+ vips->destroy_offset(vips, offsetof(host_t, destroy));
+ pools->destroy(pools);
+ return SUCCESS;
+ }
+ if (pools->get_count(pools) && !this->vips->get_count(this->vips))
+ {
+ DBG1(DBG_IKE, "expected a virtual IP request, sending %N",
+ notify_type_names, FAILED_CP_REQUIRED);
+ message->add_notify(message, FALSE, FAILED_CP_REQUIRED, chunk_empty);
+ vips->destroy_offset(vips, offsetof(host_t, destroy));
+ pools->destroy(pools);
+ return SUCCESS;
}
/* query registered providers for additional attributes to include */
enumerator = hydra->attributes->create_responder_enumerator(
- hydra->attributes, config->get_pool(config), id, vip);
+ hydra->attributes, pools, id, vips);
while (enumerator->enumerate(enumerator, &type, &value))
{
if (!cp)
{
- cp = cp_payload_create_type(CFG_REPLY);
+ cp = cp_payload_create_type(CONFIGURATION, CFG_REPLY);
}
DBG2(DBG_IKE, "building %N attribute",
configuration_attribute_type_names, type);
cp->add_attribute(cp,
- configuration_attribute_create_value(type, value));
+ configuration_attribute_create_chunk(CONFIGURATION_ATTRIBUTE,
+ type, value));
}
enumerator->destroy(enumerator);
+ vips->destroy_offset(vips, offsetof(host_t, destroy));
+ pools->destroy(pools);
if (cp)
{
message->add_payload(message, (payload_t*)cp);
}
- DESTROY_IF(vip);
return SUCCESS;
}
return NEED_MORE;
@@ -370,13 +429,22 @@ METHOD(task_t, process_i, status_t,
{
if (this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
{ /* in last IKE_AUTH exchange */
+ enumerator_t *enumerator;
+ host_t *host;
process_payloads(this, message);
- if (this->virtual_ip)
+ this->ike_sa->clear_virtual_ips(this->ike_sa, TRUE);
+
+ enumerator = this->vips->create_enumerator(this->vips);
+ while (enumerator->enumerate(enumerator, &host))
{
- this->ike_sa->set_virtual_ip(this->ike_sa, TRUE, this->virtual_ip);
+ if (!host->is_anyaddr(host))
+ {
+ this->ike_sa->add_virtual_ip(this->ike_sa, TRUE, host);
+ }
}
+ enumerator->destroy(enumerator);
return SUCCESS;
}
return NEED_MORE;
@@ -385,16 +453,15 @@ METHOD(task_t, process_i, status_t,
METHOD(task_t, get_type, task_type_t,
private_ike_config_t *this)
{
- return IKE_CONFIG;
+ return TASK_IKE_CONFIG;
}
METHOD(task_t, migrate, void,
private_ike_config_t *this, ike_sa_t *ike_sa)
{
- DESTROY_IF(this->virtual_ip);
-
this->ike_sa = ike_sa;
- this->virtual_ip = NULL;
+ this->vips->destroy_offset(this->vips, offsetof(host_t, destroy));
+ this->vips = linked_list_create();
this->requested->destroy_function(this->requested, free);
this->requested = linked_list_create();
}
@@ -402,7 +469,7 @@ METHOD(task_t, migrate, void,
METHOD(task_t, destroy, void,
private_ike_config_t *this)
{
- DESTROY_IF(this->virtual_ip);
+ this->vips->destroy_offset(this->vips, offsetof(host_t, destroy));
this->requested->destroy_function(this->requested, free);
free(this);
}
@@ -424,6 +491,7 @@ ike_config_t *ike_config_create(ike_sa_t *ike_sa, bool initiator)
},
.initiator = initiator,
.ike_sa = ike_sa,
+ .vips = linked_list_create(),
.requested = linked_list_create(),
);
@@ -440,4 +508,3 @@ ike_config_t *ike_config_create(ike_sa_t *ike_sa, bool initiator)
return &this->public;
}
-
diff --git a/src/libcharon/sa/tasks/ike_config.h b/src/libcharon/sa/ikev2/tasks/ike_config.h
index 8cef08697..e35457645 100644
--- a/src/libcharon/sa/tasks/ike_config.h
+++ b/src/libcharon/sa/ikev2/tasks/ike_config.h
@@ -15,7 +15,7 @@
/**
* @defgroup ike_config ike_config
- * @{ @ingroup tasks
+ * @{ @ingroup tasks_v2
*/
#ifndef IKE_CONFIG_H_
@@ -25,10 +25,10 @@ typedef struct ike_config_t ike_config_t;
#include <library.h>
#include <sa/ike_sa.h>
-#include <sa/tasks/task.h>
+#include <sa/task.h>
/**
- * Task of type IKE_CONFIG, sets up a virtual IP and other
+ * Task of type TASK_IKE_CONFIG, sets up a virtual IP and other
* configurations for an IKE_SA.
*/
struct ike_config_t {
diff --git a/src/libcharon/sa/tasks/ike_delete.c b/src/libcharon/sa/ikev2/tasks/ike_delete.c
index d79674fe4..f127b0c15 100644
--- a/src/libcharon/sa/tasks/ike_delete.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_delete.c
@@ -65,7 +65,7 @@ METHOD(task_t, build_i, status_t,
this->ike_sa->get_other_host(this->ike_sa),
this->ike_sa->get_other_id(this->ike_sa));
- delete_payload = delete_payload_create(PROTO_IKE);
+ delete_payload = delete_payload_create(DELETE, PROTO_IKE);
message->add_payload(message, (payload_t*)delete_payload);
if (this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING)
@@ -149,7 +149,7 @@ METHOD(task_t, build_r, status_t,
METHOD(task_t, get_type, task_type_t,
private_ike_delete_t *this)
{
- return IKE_DELETE;
+ return TASK_IKE_DELETE;
}
METHOD(task_t, migrate, void,
diff --git a/src/libcharon/sa/tasks/ike_delete.h b/src/libcharon/sa/ikev2/tasks/ike_delete.h
index 82782f393..2d5d7cb3a 100644
--- a/src/libcharon/sa/tasks/ike_delete.h
+++ b/src/libcharon/sa/ikev2/tasks/ike_delete.h
@@ -15,7 +15,7 @@
/**
* @defgroup ike_delete ike_delete
- * @{ @ingroup tasks
+ * @{ @ingroup tasks_v2
*/
#ifndef IKE_DELETE_H_
@@ -25,7 +25,7 @@ typedef struct ike_delete_t ike_delete_t;
#include <library.h>
#include <sa/ike_sa.h>
-#include <sa/tasks/task.h>
+#include <sa/task.h>
/**
* Task of type ike_delete, delete an IKE_SA.
diff --git a/src/libcharon/sa/tasks/ike_dpd.c b/src/libcharon/sa/ikev2/tasks/ike_dpd.c
index 106eff87c..28ccc2efe 100644
--- a/src/libcharon/sa/tasks/ike_dpd.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_dpd.c
@@ -46,7 +46,7 @@ METHOD(task_t, return_success, status_t,
METHOD(task_t, get_type, task_type_t,
private_ike_dpd_t *this)
{
- return IKE_DPD;
+ return TASK_IKE_DPD;
}
diff --git a/src/libcharon/sa/tasks/ike_dpd.h b/src/libcharon/sa/ikev2/tasks/ike_dpd.h
index a9f68c31c..026871610 100644
--- a/src/libcharon/sa/tasks/ike_dpd.h
+++ b/src/libcharon/sa/ikev2/tasks/ike_dpd.h
@@ -15,7 +15,7 @@
/**
* @defgroup ike_dpd ike_dpd
- * @{ @ingroup tasks
+ * @{ @ingroup tasks_v2
*/
#ifndef IKE_DPD_H_
@@ -25,7 +25,7 @@ typedef struct ike_dpd_t ike_dpd_t;
#include <library.h>
#include <sa/ike_sa.h>
-#include <sa/tasks/task.h>
+#include <sa/task.h>
/**
* Task of type ike_dpd, detects dead peers.
diff --git a/src/libcharon/sa/tasks/ike_init.c b/src/libcharon/sa/ikev2/tasks/ike_init.c
index dd8a4b086..f2a06735e 100644
--- a/src/libcharon/sa/tasks/ike_init.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_init.c
@@ -20,6 +20,7 @@
#include <string.h>
#include <daemon.h>
+#include <sa/ikev2/keymat_v2.h>
#include <crypto/diffie_hellman.h>
#include <encoding/payloads/sa_payload.h>
#include <encoding/payloads/ke_payload.h>
@@ -68,7 +69,7 @@ struct private_ike_init_t {
/**
* Keymat derivation (from IKE_SA)
*/
- keymat_t *keymat;
+ keymat_v2_t *keymat;
/**
* nonce chosen by us
@@ -132,7 +133,7 @@ static void build_payloads(private_ike_init_t *this, message_t *message)
enumerator->destroy(enumerator);
}
- sa_payload = sa_payload_create_from_proposal_list(proposal_list);
+ sa_payload = sa_payload_create_from_proposals_v2(proposal_list);
proposal_list->destroy_offset(proposal_list, offsetof(proposal_t, destroy));
}
else
@@ -142,13 +143,13 @@ static void build_payloads(private_ike_init_t *this, message_t *message)
/* include SPI of new IKE_SA when we are rekeying */
this->proposal->set_spi(this->proposal, id->get_responder_spi(id));
}
- sa_payload = sa_payload_create_from_proposal(this->proposal);
+ sa_payload = sa_payload_create_from_proposal_v2(this->proposal);
}
message->add_payload(message, (payload_t*)sa_payload);
- nonce_payload = nonce_payload_create();
+ nonce_payload = nonce_payload_create(NONCE);
nonce_payload->set_nonce(nonce_payload, this->my_nonce);
- ke_payload = ke_payload_create_from_diffie_hellman(this->dh);
+ ke_payload = ke_payload_create_from_diffie_hellman(KEY_EXCHANGE, this->dh);
if (this->old_sa)
{ /* payload order differs if we are rekeying */
@@ -197,8 +198,8 @@ static void process_payloads(private_ike_init_t *this, message_t *message)
this->dh_group = ke_payload->get_dh_group_number(ke_payload);
if (!this->initiator)
{
- this->dh = this->keymat->create_dh(this->keymat,
- this->dh_group);
+ this->dh = this->keymat->keymat.create_dh(
+ &this->keymat->keymat, this->dh_group);
}
if (this->dh)
{
@@ -224,8 +225,6 @@ static void process_payloads(private_ike_init_t *this, message_t *message)
METHOD(task_t, build_i, status_t,
private_ike_init_t *this, message_t *message)
{
- rng_t *rng;
-
this->config = this->ike_sa->get_ike_cfg(this->ike_sa);
DBG0(DBG_IKE, "initiating IKE_SA %s[%d] to %H",
this->ike_sa->get_name(this->ike_sa),
@@ -243,7 +242,8 @@ METHOD(task_t, build_i, status_t,
if (!this->dh)
{
this->dh_group = this->config->get_dh_group(this->config);
- this->dh = this->keymat->create_dh(this->keymat, this->dh_group);
+ this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
+ this->dh_group);
if (!this->dh)
{
DBG1(DBG_IKE, "configured DH group %N not supported",
@@ -255,14 +255,21 @@ METHOD(task_t, build_i, status_t,
/* generate nonce only when we are trying the first time */
if (this->my_nonce.ptr == NULL)
{
- rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
- if (!rng)
+ nonce_gen_t *nonceg;
+
+ nonceg = this->keymat->keymat.create_nonce_gen(&this->keymat->keymat);
+ if (!nonceg)
+ {
+ DBG1(DBG_IKE, "no nonce generator found to create nonce");
+ return FAILED;
+ }
+ if (!nonceg->allocate_nonce(nonceg, NONCE_SIZE, &this->my_nonce))
{
- DBG1(DBG_IKE, "error generating nonce");
+ DBG1(DBG_IKE, "nonce allocation failed");
+ nonceg->destroy(nonceg);
return FAILED;
}
- rng->allocate_bytes(rng, NONCE_SIZE, &this->my_nonce);
- rng->destroy(rng);
+ nonceg->destroy(nonceg);
}
if (this->cookie.ptr)
@@ -288,20 +295,25 @@ METHOD(task_t, build_i, status_t,
METHOD(task_t, process_r, status_t,
private_ike_init_t *this, message_t *message)
{
- rng_t *rng;
+ nonce_gen_t *nonceg;
this->config = this->ike_sa->get_ike_cfg(this->ike_sa);
DBG0(DBG_IKE, "%H is initiating an IKE_SA", message->get_source(message));
this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
- rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
- if (!rng)
+ nonceg = this->keymat->keymat.create_nonce_gen(&this->keymat->keymat);
+ if (!nonceg)
+ {
+ DBG1(DBG_IKE, "no nonce generator found to create nonce");
+ return FAILED;
+ }
+ if (!nonceg->allocate_nonce(nonceg, NONCE_SIZE, &this->my_nonce))
{
- DBG1(DBG_IKE, "error generating nonce");
+ DBG1(DBG_IKE, "nonce allocation failed");
+ nonceg->destroy(nonceg);
return FAILED;
}
- rng->allocate_bytes(rng, NONCE_SIZE, &this->my_nonce);
- rng->destroy(rng);
+ nonceg->destroy(nonceg);
#ifdef ME
{
@@ -327,7 +339,7 @@ METHOD(task_t, process_r, status_t,
static bool derive_keys(private_ike_init_t *this,
chunk_t nonce_i, chunk_t nonce_r)
{
- keymat_t *old_keymat;
+ keymat_v2_t *old_keymat;
pseudo_random_function_t prf_alg = PRF_UNDEFINED;
chunk_t skd = chunk_empty;
ike_sa_id_t *id;
@@ -336,7 +348,7 @@ static bool derive_keys(private_ike_init_t *this,
if (this->old_sa)
{
/* rekeying: Include old SKd, use old PRF, apply SPI */
- old_keymat = this->old_sa->get_keymat(this->old_sa);
+ old_keymat = (keymat_v2_t*)this->old_sa->get_keymat(this->old_sa);
prf_alg = old_keymat->get_skd(old_keymat, &skd);
if (this->initiator)
{
@@ -352,8 +364,8 @@ static bool derive_keys(private_ike_init_t *this,
{
return FALSE;
}
- charon->bus->ike_keys(charon->bus, this->ike_sa, this->dh,
- nonce_i, nonce_r, this->old_sa);
+ charon->bus->ike_keys(charon->bus, this->ike_sa, this->dh, chunk_empty,
+ nonce_i, nonce_r, this->old_sa, NULL);
return TRUE;
}
@@ -505,7 +517,7 @@ METHOD(task_t, process_i, status_t,
METHOD(task_t, get_type, task_type_t,
private_ike_init_t *this)
{
- return IKE_INIT;
+ return TASK_IKE_INIT;
}
METHOD(task_t, migrate, void,
@@ -515,12 +527,13 @@ METHOD(task_t, migrate, void,
chunk_free(&this->other_nonce);
this->ike_sa = ike_sa;
- this->keymat = ike_sa->get_keymat(ike_sa);
+ this->keymat = (keymat_v2_t*)ike_sa->get_keymat(ike_sa);
this->proposal = NULL;
if (this->dh && this->dh->get_dh_group(this->dh) != this->dh_group)
{ /* reset DH value only if group changed (INVALID_KE_PAYLOAD) */
this->dh->destroy(this->dh);
- this->dh = this->keymat->create_dh(this->keymat, this->dh_group);
+ this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
+ this->dh_group);
}
}
@@ -568,7 +581,7 @@ ike_init_t *ike_init_create(ike_sa_t *ike_sa, bool initiator, ike_sa_t *old_sa)
.ike_sa = ike_sa,
.initiator = initiator,
.dh_group = MODP_NONE,
- .keymat = ike_sa->get_keymat(ike_sa),
+ .keymat = (keymat_v2_t*)ike_sa->get_keymat(ike_sa),
.old_sa = old_sa,
);
diff --git a/src/libcharon/sa/tasks/ike_init.h b/src/libcharon/sa/ikev2/tasks/ike_init.h
index 4b7f60416..ab169954d 100644
--- a/src/libcharon/sa/tasks/ike_init.h
+++ b/src/libcharon/sa/ikev2/tasks/ike_init.h
@@ -15,7 +15,7 @@
/**
* @defgroup ike_init ike_init
- * @{ @ingroup tasks
+ * @{ @ingroup tasks_v2
*/
#ifndef IKE_INIT_H_
@@ -25,10 +25,10 @@ typedef struct ike_init_t ike_init_t;
#include <library.h>
#include <sa/ike_sa.h>
-#include <sa/tasks/task.h>
+#include <sa/task.h>
/**
- * Task of type IKE_INIT, creates an IKE_SA without authentication.
+ * Task of type TASK_IKE_INIT, creates an IKE_SA without authentication.
*
* The authentication of is handle in the ike_auth task.
*/
@@ -48,7 +48,7 @@ struct ike_init_t {
};
/**
- * Create a new IKE_INIT task.
+ * Create a new TASK_IKE_INIT task.
*
* @param ike_sa IKE_SA this task works for (new one when rekeying)
* @param initiator TRUE if task is the original initiator
diff --git a/src/libcharon/sa/tasks/ike_me.c b/src/libcharon/sa/ikev2/tasks/ike_me.c
index 8f90efcc3..135c06d19 100644
--- a/src/libcharon/sa/tasks/ike_me.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_me.c
@@ -136,7 +136,7 @@ static void gather_and_add_endpoints(private_ike_me_t *this, message_t *message)
port = host->get_port(host);
enumerator = hydra->kernel_interface->create_address_enumerator(
- hydra->kernel_interface, FALSE, FALSE);
+ hydra->kernel_interface, ADDR_TYPE_REGULAR);
while (enumerator->enumerate(enumerator, (void**)&addr))
{
host = addr->clone(addr);
@@ -291,9 +291,21 @@ METHOD(task_t, build_i, status_t,
{
/* only the initiator creates a connect ID. the responder
* returns the connect ID that it received from the initiator */
- rng->allocate_bytes(rng, ME_CONNECTID_LEN, &this->connect_id);
+ if (!rng->allocate_bytes(rng, ME_CONNECTID_LEN,
+ &this->connect_id))
+ {
+ DBG1(DBG_IKE, "unable to generate ID for ME_CONNECT");
+ rng->destroy(rng);
+ return FAILED;
+ }
+ }
+ if (!rng->allocate_bytes(rng, ME_CONNECTKEY_LEN,
+ &this->connect_key))
+ {
+ DBG1(DBG_IKE, "unable to generate connect key for ME_CONNECT");
+ rng->destroy(rng);
+ return FAILED;
}
- rng->allocate_bytes(rng, ME_CONNECTKEY_LEN, &this->connect_key);
rng->destroy(rng);
message->add_notify(message, FALSE, ME_CONNECTID, this->connect_id);
@@ -750,7 +762,7 @@ METHOD(ike_me_t, relay, void,
METHOD(task_t, get_type, task_type_t,
private_ike_me_t *this)
{
- return IKE_ME;
+ return TASK_IKE_ME;
}
METHOD(task_t, migrate, void,
diff --git a/src/libcharon/sa/tasks/ike_me.h b/src/libcharon/sa/ikev2/tasks/ike_me.h
index 31285a426..44a4ce69c 100644
--- a/src/libcharon/sa/tasks/ike_me.h
+++ b/src/libcharon/sa/ikev2/tasks/ike_me.h
@@ -15,7 +15,7 @@
/**
* @defgroup ike_me ike_me
- * @{ @ingroup tasks
+ * @{ @ingroup tasks_v2
*/
#ifndef IKE_ME_H_
@@ -25,10 +25,10 @@ typedef struct ike_me_t ike_me_t;
#include <library.h>
#include <sa/ike_sa.h>
-#include <sa/tasks/task.h>
+#include <sa/task.h>
/**
- * Task of type IKE_ME, detects and handles IKE-ME extensions.
+ * Task of type TASK_IKE_ME, detects and handles IKE-ME extensions.
*
* This tasks handles the ME_MEDIATION Notify exchange to setup a mediation
* connection, allows to initiate mediated connections using ME_CONNECT
diff --git a/src/libcharon/sa/tasks/ike_mobike.c b/src/libcharon/sa/ikev2/tasks/ike_mobike.c
index fb1100028..ae3526f42 100644
--- a/src/libcharon/sa/tasks/ike_mobike.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_mobike.c
@@ -20,7 +20,7 @@
#include <hydra.h>
#include <daemon.h>
-#include <sa/tasks/ike_natd.h>
+#include <sa/ikev2/tasks/ike_natd.h>
#include <encoding/payloads/notify_payload.h>
#define COOKIE2_SIZE 16
@@ -54,7 +54,7 @@ struct private_ike_mobike_t {
chunk_t cookie2;
/**
- * NAT discovery reusing the IKE_NATD task
+ * NAT discovery reusing the TASK_IKE_NATD task
*/
ike_natd_t *natd;
@@ -192,7 +192,7 @@ static void build_address_list(private_ike_mobike_t *this, message_t *message)
me = this->ike_sa->get_my_host(this->ike_sa);
enumerator = hydra->kernel_interface->create_address_enumerator(
- hydra->kernel_interface, FALSE, FALSE);
+ hydra->kernel_interface, ADDR_TYPE_REGULAR);
while (enumerator->enumerate(enumerator, (void**)&host))
{
if (me->ip_equals(me, host))
@@ -227,18 +227,20 @@ static void build_address_list(private_ike_mobike_t *this, message_t *message)
/**
* build a cookie and add it to the message
*/
-static void build_cookie(private_ike_mobike_t *this, message_t *message)
+static bool build_cookie(private_ike_mobike_t *this, message_t *message)
{
rng_t *rng;
chunk_free(&this->cookie2);
rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
- if (rng)
+ if (!rng || !rng->allocate_bytes(rng, COOKIE2_SIZE, &this->cookie2))
{
- rng->allocate_bytes(rng, COOKIE2_SIZE, &this->cookie2);
- rng->destroy(rng);
- message->add_notify(message, FALSE, COOKIE2, this->cookie2);
+ DESTROY_IF(rng);
+ return FALSE;
}
+ message->add_notify(message, FALSE, COOKIE2, this->cookie2);
+ rng->destroy(rng);
+ return TRUE;
}
/**
@@ -248,15 +250,26 @@ static void update_children(private_ike_mobike_t *this)
{
enumerator_t *enumerator;
child_sa_t *child_sa;
+ linked_list_t *vips;
+ host_t *host;
+
+ vips = linked_list_create();
+
+ enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa, TRUE);
+ while (enumerator->enumerate(enumerator, &host))
+ {
+ vips->insert_last(vips, host);
+ }
+ enumerator->destroy(enumerator);
enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
while (enumerator->enumerate(enumerator, (void**)&child_sa))
{
if (child_sa->update(child_sa,
this->ike_sa->get_my_host(this->ike_sa),
- this->ike_sa->get_other_host(this->ike_sa),
- this->ike_sa->get_virtual_ip(this->ike_sa, TRUE),
- this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY)) == NOT_SUPPORTED)
+ this->ike_sa->get_other_host(this->ike_sa), vips,
+ this->ike_sa->has_condition(this->ike_sa,
+ COND_NAT_ANY)) == NOT_SUPPORTED)
{
this->ike_sa->rekey_child_sa(this->ike_sa,
child_sa->get_protocol(child_sa),
@@ -264,18 +277,24 @@ static void update_children(private_ike_mobike_t *this)
}
}
enumerator->destroy(enumerator);
+
+ vips->destroy(vips);
}
/**
* Apply the port of the old host, if its ip equals the new, use port otherwise.
*/
-static void apply_port(host_t *host, host_t *old, u_int16_t port)
+static void apply_port(host_t *host, host_t *old, u_int16_t port, bool local)
{
if (host->ip_equals(host, old))
{
port = old->get_port(old);
}
- else if (port == IKEV2_UDP_PORT)
+ else if (local && port == charon->socket->get_port(charon->socket, FALSE))
+ {
+ port = charon->socket->get_port(charon->socket, TRUE);
+ }
+ else if (!local && port == IKEV2_UDP_PORT)
{
port = IKEV2_NATT_PORT;
}
@@ -312,9 +331,9 @@ METHOD(ike_mobike_t, transmit, void,
continue;
}
/* reuse port for an active address, 4500 otherwise */
- apply_port(me, me_old, ike_cfg->get_my_port(ike_cfg));
+ apply_port(me, me_old, ike_cfg->get_my_port(ike_cfg), TRUE);
other = other->clone(other);
- apply_port(other, other_old, ike_cfg->get_other_port(ike_cfg));
+ apply_port(other, other_old, ike_cfg->get_other_port(ike_cfg), FALSE);
DBG1(DBG_IKE, "checking path %#H - %#H", me, other);
copy = packet->clone(packet);
copy->set_source(copy, me);
@@ -358,7 +377,10 @@ METHOD(task_t, build_i, status_t,
{
message->add_notify(message, FALSE, UPDATE_SA_ADDRESSES,
chunk_empty);
- build_cookie(this, message);
+ if (!build_cookie(this, message))
+ {
+ return FAILED;
+ }
update_children(this);
}
if (this->address && !this->check)
@@ -584,7 +606,7 @@ METHOD(ike_mobike_t, is_probing, bool,
METHOD(task_t, get_type, task_type_t,
private_ike_mobike_t *this)
{
- return IKE_MOBIKE;
+ return TASK_IKE_MOBIKE;
}
METHOD(task_t, migrate, void,
@@ -646,4 +668,3 @@ ike_mobike_t *ike_mobike_create(ike_sa_t *ike_sa, bool initiator)
return &this->public;
}
-
diff --git a/src/libcharon/sa/tasks/ike_mobike.h b/src/libcharon/sa/ikev2/tasks/ike_mobike.h
index 16611939e..3b447af51 100644
--- a/src/libcharon/sa/tasks/ike_mobike.h
+++ b/src/libcharon/sa/ikev2/tasks/ike_mobike.h
@@ -15,7 +15,7 @@
/**
* @defgroup ike_mobike ike_mobike
- * @{ @ingroup tasks
+ * @{ @ingroup tasks_v2
*/
#ifndef IKE_MOBIKE_H_
@@ -25,8 +25,8 @@ typedef struct ike_mobike_t ike_mobike_t;
#include <library.h>
#include <sa/ike_sa.h>
-#include <sa/tasks/task.h>
-#include <network/packet.h>
+#include <sa/task.h>
+#include <utils/packet.h>
/**
* Task of type ike_mobike, detects and handles MOBIKE extension.
diff --git a/src/libcharon/sa/tasks/ike_natd.c b/src/libcharon/sa/ikev2/tasks/ike_natd.c
index f06a518fa..0a93db9ed 100644
--- a/src/libcharon/sa/tasks/ike_natd.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_natd.c
@@ -104,7 +104,10 @@ static chunk_t generate_natd_hash(private_ike_natd_t *this,
/* natd_hash = SHA1( spi_i | spi_r | address | port ) */
natd_chunk = chunk_cat("cccc", spi_i_chunk, spi_r_chunk, addr_chunk, port_chunk);
- this->hasher->allocate_hash(this->hasher, natd_chunk, &natd_hash);
+ if (!this->hasher->allocate_hash(this->hasher, natd_chunk, &natd_hash))
+ {
+ natd_hash = chunk_empty;
+ }
DBG3(DBG_IKE, "natd_chunk %B", &natd_chunk);
DBG3(DBG_IKE, "natd_hash %B", &natd_hash);
@@ -121,12 +124,12 @@ static chunk_t generate_natd_hash_faked(private_ike_natd_t *this)
chunk_t chunk;
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
- if (!rng)
+ if (!rng || !rng->allocate_bytes(rng, HASH_SIZE_SHA1, &chunk))
{
DBG1(DBG_IKE, "unable to get random bytes for NATD fake");
+ DESTROY_IF(rng);
return chunk_empty;
}
- rng->allocate_bytes(rng, HASH_SIZE_SHA1, &chunk);
rng->destroy(rng);
return chunk;
}
@@ -152,7 +155,11 @@ static notify_payload_t *build_natd_payload(private_ike_natd_t *this,
{
hash = generate_natd_hash(this, ike_sa_id, host);
}
- notify = notify_payload_create();
+ if (!hash.len)
+ {
+ return NULL;
+ }
+ notify = notify_payload_create(NOTIFY);
notify->set_notify_type(notify, type);
notify->set_notification_data(notify, hash);
chunk_free(&hash);
@@ -298,7 +305,10 @@ METHOD(task_t, build_i, status_t,
/* destination is always set */
host = message->get_destination(message);
notify = build_natd_payload(this, NAT_DETECTION_DESTINATION_IP, host);
- message->add_payload(message, (payload_t*)notify);
+ if (notify)
+ {
+ message->add_payload(message, (payload_t*)notify);
+ }
/* source may be any, we have 3 possibilities to get our source address:
* 1. It is defined in the config => use the one of the IKE_SA
@@ -306,10 +316,13 @@ METHOD(task_t, build_i, status_t,
* 3. Include all possbile addresses
*/
host = message->get_source(message);
- if (!host->is_anyaddr(host))
- { /* 1. */
+ if (!host->is_anyaddr(host) || ike_cfg->force_encap(ike_cfg))
+ { /* 1. or if we force UDP encap, as it doesn't matter if it's %any */
notify = build_natd_payload(this, NAT_DETECTION_SOURCE_IP, host);
- message->add_payload(message, (payload_t*)notify);
+ if (notify)
+ {
+ message->add_payload(message, (payload_t*)notify);
+ }
}
else
{
@@ -319,13 +332,16 @@ METHOD(task_t, build_i, status_t,
{ /* 2. */
host->set_port(host, ike_cfg->get_my_port(ike_cfg));
notify = build_natd_payload(this, NAT_DETECTION_SOURCE_IP, host);
- message->add_payload(message, (payload_t*)notify);
+ if (notify)
+ {
+ message->add_payload(message, (payload_t*)notify);
+ }
host->destroy(host);
}
else
{ /* 3. */
enumerator = hydra->kernel_interface->create_address_enumerator(
- hydra->kernel_interface, FALSE, FALSE);
+ hydra->kernel_interface, ADDR_TYPE_REGULAR);
while (enumerator->enumerate(enumerator, (void**)&host))
{
/* apply port 500 to host, but work on a copy */
@@ -333,7 +349,10 @@ METHOD(task_t, build_i, status_t,
host->set_port(host, ike_cfg->get_my_port(ike_cfg));
notify = build_natd_payload(this, NAT_DETECTION_SOURCE_IP, host);
host->destroy(host);
- message->add_payload(message, (payload_t*)notify);
+ if (notify)
+ {
+ message->add_payload(message, (payload_t*)notify);
+ }
}
enumerator->destroy(enumerator);
}
@@ -365,11 +384,16 @@ METHOD(task_t, build_r, status_t,
/* initiator seems to support NAT detection, add response */
me = message->get_source(message);
notify = build_natd_payload(this, NAT_DETECTION_SOURCE_IP, me);
- message->add_payload(message, (payload_t*)notify);
-
+ if (notify)
+ {
+ message->add_payload(message, (payload_t*)notify);
+ }
other = message->get_destination(message);
notify = build_natd_payload(this, NAT_DETECTION_DESTINATION_IP, other);
- message->add_payload(message, (payload_t*)notify);
+ if (notify)
+ {
+ message->add_payload(message, (payload_t*)notify);
+ }
}
return SUCCESS;
}
@@ -385,7 +409,7 @@ METHOD(task_t, process_r, status_t,
METHOD(task_t, get_type, task_type_t,
private_ike_natd_t *this)
{
- return IKE_NATD;
+ return TASK_IKE_NATD;
}
METHOD(task_t, migrate, void,
diff --git a/src/libcharon/sa/tasks/ike_natd.h b/src/libcharon/sa/ikev2/tasks/ike_natd.h
index 68114af42..9c571b8e6 100644
--- a/src/libcharon/sa/tasks/ike_natd.h
+++ b/src/libcharon/sa/ikev2/tasks/ike_natd.h
@@ -15,7 +15,7 @@
/**
* @defgroup ike_natd ike_natd
- * @{ @ingroup tasks
+ * @{ @ingroup tasks_v2
*/
#ifndef IKE_NATD_H_
@@ -25,7 +25,7 @@ typedef struct ike_natd_t ike_natd_t;
#include <library.h>
#include <sa/ike_sa.h>
-#include <sa/tasks/task.h>
+#include <sa/task.h>
/**
* Task of type ike_natd, detects NAT situation in IKE_SA_INIT exchange.
@@ -42,7 +42,7 @@ struct ike_natd_t {
*
* MOBIKE uses NAT payloads in DPD to detect changes in the NAT mappings.
*
- * @return TRUE if mappings have changed
+ * @return TRUE if mappings have changed
*/
bool (*has_mapping_changed)(ike_natd_t *this);
};
diff --git a/src/libcharon/sa/tasks/ike_reauth.c b/src/libcharon/sa/ikev2/tasks/ike_reauth.c
index 48002d81c..6f90339ea 100644
--- a/src/libcharon/sa/tasks/ike_reauth.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_reauth.c
@@ -16,7 +16,7 @@
#include "ike_reauth.h"
#include <daemon.h>
-#include <sa/tasks/ike_delete.h>
+#include <sa/ikev2/tasks/ike_delete.h>
typedef struct private_ike_reauth_t private_ike_reauth_t;
@@ -68,7 +68,7 @@ METHOD(task_t, process_i, status_t,
METHOD(task_t, get_type, task_type_t,
private_ike_reauth_t *this)
{
- return IKE_REAUTH;
+ return TASK_IKE_REAUTH;
}
METHOD(task_t, migrate, void,
@@ -108,4 +108,3 @@ ike_reauth_t *ike_reauth_create(ike_sa_t *ike_sa)
return &this->public;
}
-
diff --git a/src/libcharon/sa/tasks/ike_reauth.h b/src/libcharon/sa/ikev2/tasks/ike_reauth.h
index 5e97b719c..781b463a7 100644
--- a/src/libcharon/sa/tasks/ike_reauth.h
+++ b/src/libcharon/sa/ikev2/tasks/ike_reauth.h
@@ -15,7 +15,7 @@
/**
* @defgroup ike_reauth ike_reauth
- * @{ @ingroup tasks
+ * @{ @ingroup tasks_v2
*/
#ifndef IKE_REAUTH_H_
@@ -25,7 +25,7 @@ typedef struct ike_reauth_t ike_reauth_t;
#include <library.h>
#include <sa/ike_sa.h>
-#include <sa/tasks/task.h>
+#include <sa/task.h>
/**
* Task of type ike_reauth, reestablishes an IKE_SA.
diff --git a/src/libcharon/sa/tasks/ike_rekey.c b/src/libcharon/sa/ikev2/tasks/ike_rekey.c
index 826d6e192..c3c6cf00e 100644
--- a/src/libcharon/sa/tasks/ike_rekey.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_rekey.c
@@ -18,8 +18,8 @@
#include <daemon.h>
#include <encoding/payloads/notify_payload.h>
-#include <sa/tasks/ike_init.h>
-#include <sa/tasks/ike_delete.h>
+#include <sa/ikev2/tasks/ike_init.h>
+#include <sa/ikev2/tasks/ike_delete.h>
#include <processing/jobs/delete_ike_sa_job.h>
#include <processing/jobs/rekey_ike_sa_job.h>
@@ -52,7 +52,7 @@ struct private_ike_rekey_t {
bool initiator;
/**
- * the IKE_INIT task which is reused to simplify rekeying
+ * the TASK_IKE_INIT task which is reused to simplify rekeying
*/
ike_init_t *ike_init;
@@ -123,15 +123,20 @@ METHOD(task_t, process_i_delete, status_t,
METHOD(task_t, build_i, status_t,
private_ike_rekey_t *this, message_t *message)
{
+ ike_version_t version;
peer_cfg_t *peer_cfg;
host_t *other_host;
/* create new SA only on first try */
if (this->new_sa == NULL)
{
- this->new_sa = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager,
- TRUE);
-
+ version = this->ike_sa->get_version(this->ike_sa);
+ this->new_sa = charon->ike_sa_manager->checkout_new(
+ charon->ike_sa_manager, version, TRUE);
+ if (!this->new_sa)
+ { /* shouldn't happen */
+ return FAILED;
+ }
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
other_host = this->ike_sa->get_other_host(this->ike_sa);
this->new_sa->set_peer_cfg(this->new_sa, peer_cfg);
@@ -176,7 +181,11 @@ METHOD(task_t, process_r, status_t,
enumerator->destroy(enumerator);
this->new_sa = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager,
- FALSE);
+ this->ike_sa->get_version(this->ike_sa), FALSE);
+ if (!this->new_sa)
+ { /* shouldn't happen */
+ return FAILED;
+ }
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
this->new_sa->set_peer_cfg(this->new_sa, peer_cfg);
@@ -230,8 +239,8 @@ METHOD(task_t, process_i, status_t,
case FAILED:
/* rekeying failed, fallback to old SA */
if (!(this->collision && (
- this->collision->get_type(this->collision) == IKE_DELETE ||
- this->collision->get_type(this->collision) == IKE_REAUTH)))
+ this->collision->get_type(this->collision) == TASK_IKE_DELETE ||
+ this->collision->get_type(this->collision) == TASK_IKE_REAUTH)))
{
job_t *job;
u_int32_t retry = RETRY_INTERVAL - (random() % RETRY_JITTER);
@@ -253,7 +262,7 @@ METHOD(task_t, process_i, status_t,
/* check for collisions */
if (this->collision &&
- this->collision->get_type(this->collision) == IKE_REKEY)
+ this->collision->get_type(this->collision) == TASK_IKE_REKEY)
{
private_ike_rekey_t *other = (private_ike_rekey_t*)this->collision;
@@ -323,14 +332,14 @@ METHOD(task_t, process_i, status_t,
METHOD(task_t, get_type, task_type_t,
private_ike_rekey_t *this)
{
- return IKE_REKEY;
+ return TASK_IKE_REKEY;
}
METHOD(ike_rekey_t, collide, void,
private_ike_rekey_t* this, task_t *other)
{
- DBG1(DBG_IKE, "detected %N collision with %N", task_type_names, IKE_REKEY,
- task_type_names, other->get_type(other));
+ DBG1(DBG_IKE, "detected %N collision with %N", task_type_names,
+ TASK_IKE_REKEY, task_type_names, other->get_type(other));
DESTROY_IF(this->collision);
this->collision = other;
}
diff --git a/src/libcharon/sa/tasks/ike_rekey.h b/src/libcharon/sa/ikev2/tasks/ike_rekey.h
index 1c9550768..6a12e9034 100644
--- a/src/libcharon/sa/tasks/ike_rekey.h
+++ b/src/libcharon/sa/ikev2/tasks/ike_rekey.h
@@ -15,7 +15,7 @@
/**
* @defgroup ike_rekey ike_rekey
- * @{ @ingroup tasks
+ * @{ @ingroup tasks_v2
*/
#ifndef IKE_REKEY_H_
@@ -25,10 +25,10 @@ typedef struct ike_rekey_t ike_rekey_t;
#include <library.h>
#include <sa/ike_sa.h>
-#include <sa/tasks/task.h>
+#include <sa/task.h>
/**
- * Task of type IKE_REKEY, rekey an established IKE_SA.
+ * Task of type TASK_IKE_REKEY, rekey an established IKE_SA.
*/
struct ike_rekey_t {
@@ -50,11 +50,11 @@ struct ike_rekey_t {
};
/**
- * Create a new IKE_REKEY task.
+ * Create a new TASK_IKE_REKEY task.
*
* @param ike_sa IKE_SA this task works for
* @param initiator TRUE for initiator, FALSE for responder
- * @return IKE_REKEY task to handle by the task_manager
+ * @return TASK_IKE_REKEY task to handle by the task_manager
*/
ike_rekey_t *ike_rekey_create(ike_sa_t *ike_sa, bool initiator);
diff --git a/src/libcharon/sa/tasks/ike_vendor.c b/src/libcharon/sa/ikev2/tasks/ike_vendor.c
index 1c14ee06b..2730f5876 100644
--- a/src/libcharon/sa/tasks/ike_vendor.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_vendor.c
@@ -53,11 +53,12 @@ METHOD(task_t, build, status_t,
private_ike_vendor_t *this, message_t *message)
{
if (lib->settings->get_bool(lib->settings,
- "charon.send_vendor_id", FALSE))
+ "%s.send_vendor_id", FALSE, charon->name))
{
vendor_id_payload_t *vid;
- vid = vendor_id_payload_create_data(chunk_clone(strongswan_vid));
+ vid = vendor_id_payload_create_data(VENDOR_ID,
+ chunk_clone(strongswan_vid));
message->add_payload(message, &vid->payload_interface);
}
@@ -83,12 +84,12 @@ METHOD(task_t, process, status_t,
if (chunk_equals(data, strongswan_vid))
{
- DBG1(DBG_IKE, "received strongSwan vendor id");
+ DBG1(DBG_IKE, "received strongSwan vendor ID");
this->ike_sa->enable_extension(this->ike_sa, EXT_STRONGSWAN);
}
else
{
- DBG1(DBG_ENC, "received unknown vendor id: %#B", &data);
+ DBG1(DBG_ENC, "received unknown vendor ID: %#B", &data);
}
}
}
@@ -106,7 +107,7 @@ METHOD(task_t, migrate, void,
METHOD(task_t, get_type, task_type_t,
private_ike_vendor_t *this)
{
- return IKE_VENDOR;
+ return TASK_IKE_VENDOR;
}
METHOD(task_t, destroy, void,
@@ -138,4 +139,3 @@ ike_vendor_t *ike_vendor_create(ike_sa_t *ike_sa, bool initiator)
return &this->public;
}
-
diff --git a/src/libcharon/sa/tasks/ike_vendor.h b/src/libcharon/sa/ikev2/tasks/ike_vendor.h
index 6c353c447..86c711636 100644
--- a/src/libcharon/sa/tasks/ike_vendor.h
+++ b/src/libcharon/sa/ikev2/tasks/ike_vendor.h
@@ -15,7 +15,7 @@
/**
* @defgroup ike_vendor ike_vendor
- * @{ @ingroup tasks
+ * @{ @ingroup tasks_v2
*/
#ifndef IKE_VENDOR_H_
@@ -25,7 +25,7 @@ typedef struct ike_vendor_t ike_vendor_t;
#include <library.h>
#include <sa/ike_sa.h>
-#include <sa/tasks/task.h>
+#include <sa/task.h>
/**
* Vendor ID processing task.
diff --git a/src/libcharon/sa/keymat.c b/src/libcharon/sa/keymat.c
index d762fa34e..26c305f77 100644
--- a/src/libcharon/sa/keymat.c
+++ b/src/libcharon/sa/keymat.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Martin Willi
+ * Copyright (C) 2011 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -15,621 +15,112 @@
#include "keymat.h"
-#include <daemon.h>
-#include <crypto/prf_plus.h>
+#include <sa/ikev1/keymat_v1.h>
+#include <sa/ikev2/keymat_v2.h>
-typedef struct private_keymat_t private_keymat_t;
+static keymat_constructor_t keymat_v1_ctor = NULL, keymat_v2_ctor = NULL;
/**
- * Private data of an keymat_t object.
+ * See header
*/
-struct private_keymat_t {
-
- /**
- * Public keymat_t interface.
- */
- keymat_t public;
-
- /**
- * IKE_SA Role, initiator or responder
- */
- bool initiator;
-
- /**
- * inbound AEAD
- */
- aead_t *aead_in;
-
- /**
- * outbound AEAD
- */
- aead_t *aead_out;
-
- /**
- * General purpose PRF
- */
- prf_t *prf;
-
- /**
- * Negotiated PRF algorithm
- */
- pseudo_random_function_t prf_alg;
-
- /**
- * Key to derive key material from for CHILD_SAs, rekeying
- */
- chunk_t skd;
-
- /**
- * Key to build outging authentication data (SKp)
- */
- chunk_t skp_build;
-
- /**
- * Key to verify incoming authentication data (SKp)
- */
- chunk_t skp_verify;
-};
+keymat_t *keymat_create(ike_version_t version, bool initiator)
+{
+ keymat_t *keymat = NULL;
-typedef struct keylen_entry_t keylen_entry_t;
+ switch (version)
+ {
+ case IKEV1:
+#ifdef USE_IKEV1
+ keymat = keymat_v1_ctor ? keymat_v1_ctor(initiator)
+ : &keymat_v1_create(initiator)->keymat;
+#endif
+ break;
+ case IKEV2:
+#ifdef USE_IKEV2
+ keymat = keymat_v2_ctor ? keymat_v2_ctor(initiator)
+ : &keymat_v2_create(initiator)->keymat;
+#endif
+ break;
+ default:
+ break;
+ }
+ return keymat;
+}
/**
* Implicit key length for an algorithm
*/
-struct keylen_entry_t {
+typedef struct {
/** IKEv2 algorithm identifier */
- int algo;
+ int alg;
/** key length in bits */
int len;
-};
-
-#define END_OF_LIST -1
-
-/**
- * Keylen for encryption algos
- */
-keylen_entry_t keylen_enc[] = {
- {ENCR_DES, 64},
- {ENCR_3DES, 192},
- {END_OF_LIST, 0}
-};
+} keylen_entry_t;
/**
- * Keylen for integrity algos
+ * See header.
*/
-keylen_entry_t keylen_int[] = {
- {AUTH_HMAC_MD5_96, 128},
- {AUTH_HMAC_MD5_128, 128},
- {AUTH_HMAC_SHA1_96, 160},
- {AUTH_HMAC_SHA1_160, 160},
- {AUTH_HMAC_SHA2_256_96, 256},
- {AUTH_HMAC_SHA2_256_128, 256},
- {AUTH_HMAC_SHA2_384_192, 384},
- {AUTH_HMAC_SHA2_512_256, 512},
- {AUTH_AES_XCBC_96, 128},
- {END_OF_LIST, 0}
-};
-
-/**
- * Lookup key length of an algorithm
- */
-static int lookup_keylen(keylen_entry_t *list, int algo)
+int keymat_get_keylen_encr(encryption_algorithm_t alg)
{
- while (list->algo != END_OF_LIST)
+ keylen_entry_t map[] = {
+ {ENCR_DES, 64},
+ {ENCR_3DES, 192},
+ };
+ int i;
+
+ for (i = 0; i < countof(map); i++)
{
- if (algo == list->algo)
+ if (map[i].alg == alg)
{
- return list->len;
+ return map[i].len;
}
- list++;
}
return 0;
}
-METHOD(keymat_t, create_dh, diffie_hellman_t*,
- private_keymat_t *this, diffie_hellman_group_t group)
-{
- return lib->crypto->create_dh(lib->crypto, group);;
-}
-
/**
- * Derive IKE keys for a combined AEAD algorithm
+ * See header.
*/
-static bool derive_ike_aead(private_keymat_t *this, u_int16_t alg,
- u_int16_t key_size, prf_plus_t *prf_plus)
+int keymat_get_keylen_integ(integrity_algorithm_t alg)
{
- aead_t *aead_i, *aead_r;
- chunk_t key;
-
- /* SK_ei/SK_er used for encryption */
- aead_i = lib->crypto->create_aead(lib->crypto, alg, key_size / 8);
- aead_r = lib->crypto->create_aead(lib->crypto, alg, key_size / 8);
- if (aead_i == NULL || aead_r == NULL)
- {
- DBG1(DBG_IKE, "%N %N (key size %d) not supported!",
- transform_type_names, ENCRYPTION_ALGORITHM,
- encryption_algorithm_names, alg, key_size);
- return FALSE;
- }
- key_size = aead_i->get_key_size(aead_i);
-
- prf_plus->allocate_bytes(prf_plus, key_size, &key);
- DBG4(DBG_IKE, "Sk_ei secret %B", &key);
- aead_i->set_key(aead_i, key);
- chunk_clear(&key);
-
- prf_plus->allocate_bytes(prf_plus, key_size, &key);
- DBG4(DBG_IKE, "Sk_er secret %B", &key);
- aead_r->set_key(aead_r, key);
- chunk_clear(&key);
-
- if (this->initiator)
- {
- this->aead_in = aead_r;
- this->aead_out = aead_i;
- }
- else
- {
- this->aead_in = aead_i;
- this->aead_out = aead_r;
+ keylen_entry_t map[] = {
+ {AUTH_HMAC_MD5_96, 128},
+ {AUTH_HMAC_MD5_128, 128},
+ {AUTH_HMAC_SHA1_96, 160},
+ {AUTH_HMAC_SHA1_160, 160},
+ {AUTH_HMAC_SHA2_256_96, 256},
+ {AUTH_HMAC_SHA2_256_128, 256},
+ {AUTH_HMAC_SHA2_384_192, 384},
+ {AUTH_HMAC_SHA2_512_256, 512},
+ {AUTH_AES_XCBC_96, 128},
+ };
+ int i;
+
+ for (i = 0; i < countof(map); i++)
+ {
+ if (map[i].alg == alg)
+ {
+ return map[i].len;
+ }
}
- return TRUE;
+ return 0;
}
/**
- * Derive IKE keys for traditional encryption and MAC algorithms
+ * See header.
*/
-static bool derive_ike_traditional(private_keymat_t *this, u_int16_t enc_alg,
- u_int16_t enc_size, u_int16_t int_alg, prf_plus_t *prf_plus)
+void keymat_register_constructor(ike_version_t version,
+ keymat_constructor_t create)
{
- crypter_t *crypter_i, *crypter_r;
- signer_t *signer_i, *signer_r;
- size_t key_size;
- chunk_t key;
-
- /* SK_ai/SK_ar used for integrity protection */
- signer_i = lib->crypto->create_signer(lib->crypto, int_alg);
- signer_r = lib->crypto->create_signer(lib->crypto, int_alg);
- if (signer_i == NULL || signer_r == NULL)
+ switch (version)
{
- DBG1(DBG_IKE, "%N %N not supported!",
- transform_type_names, INTEGRITY_ALGORITHM,
- integrity_algorithm_names, int_alg);
- return FALSE;
- }
- key_size = signer_i->get_key_size(signer_i);
-
- prf_plus->allocate_bytes(prf_plus, key_size, &key);
- DBG4(DBG_IKE, "Sk_ai secret %B", &key);
- signer_i->set_key(signer_i, key);
- chunk_clear(&key);
-
- prf_plus->allocate_bytes(prf_plus, key_size, &key);
- DBG4(DBG_IKE, "Sk_ar secret %B", &key);
- signer_r->set_key(signer_r, key);
- chunk_clear(&key);
-
- /* SK_ei/SK_er used for encryption */
- crypter_i = lib->crypto->create_crypter(lib->crypto, enc_alg, enc_size / 8);
- crypter_r = lib->crypto->create_crypter(lib->crypto, enc_alg, enc_size / 8);
- if (crypter_i == NULL || crypter_r == NULL)
- {
- DBG1(DBG_IKE, "%N %N (key size %d) not supported!",
- transform_type_names, ENCRYPTION_ALGORITHM,
- encryption_algorithm_names, enc_alg, enc_size);
- signer_i->destroy(signer_i);
- signer_r->destroy(signer_r);
- return FALSE;
- }
- key_size = crypter_i->get_key_size(crypter_i);
-
- prf_plus->allocate_bytes(prf_plus, key_size, &key);
- DBG4(DBG_IKE, "Sk_ei secret %B", &key);
- crypter_i->set_key(crypter_i, key);
- chunk_clear(&key);
-
- prf_plus->allocate_bytes(prf_plus, key_size, &key);
- DBG4(DBG_IKE, "Sk_er secret %B", &key);
- crypter_r->set_key(crypter_r, key);
- chunk_clear(&key);
-
- if (this->initiator)
- {
- this->aead_in = aead_create(crypter_r, signer_r);
- this->aead_out = aead_create(crypter_i, signer_i);
- }
- else
- {
- this->aead_in = aead_create(crypter_i, signer_i);
- this->aead_out = aead_create(crypter_r, signer_r);
- }
- return TRUE;
-}
-
-METHOD(keymat_t, derive_ike_keys, bool,
- private_keymat_t *this, proposal_t *proposal, diffie_hellman_t *dh,
- chunk_t nonce_i, chunk_t nonce_r, ike_sa_id_t *id,
- pseudo_random_function_t rekey_function, chunk_t rekey_skd)
-{
- chunk_t skeyseed, key, secret, full_nonce, fixed_nonce, prf_plus_seed;
- chunk_t spi_i, spi_r;
- prf_plus_t *prf_plus;
- u_int16_t alg, key_size, int_alg;
- prf_t *rekey_prf = NULL;
-
- spi_i = chunk_alloca(sizeof(u_int64_t));
- spi_r = chunk_alloca(sizeof(u_int64_t));
-
- if (dh->get_shared_secret(dh, &secret) != SUCCESS)
- {
- return FALSE;
- }
-
- /* Create SAs general purpose PRF first, we may use it here */
- if (!proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL))
- {
- DBG1(DBG_IKE, "no %N selected",
- transform_type_names, PSEUDO_RANDOM_FUNCTION);
- return FALSE;
- }
- this->prf_alg = alg;
- this->prf = lib->crypto->create_prf(lib->crypto, alg);
- if (this->prf == NULL)
- {
- DBG1(DBG_IKE, "%N %N not supported!",
- transform_type_names, PSEUDO_RANDOM_FUNCTION,
- pseudo_random_function_names, alg);
- return FALSE;
- }
- DBG4(DBG_IKE, "shared Diffie Hellman secret %B", &secret);
- /* full nonce is used as seed for PRF+ ... */
- full_nonce = chunk_cat("cc", nonce_i, nonce_r);
- /* but the PRF may need a fixed key which only uses the first bytes of
- * the nonces. */
- switch (alg)
- {
- case PRF_AES128_XCBC:
- /* while rfc4434 defines variable keys for AES-XCBC, rfc3664 does
- * not and therefore fixed key semantics apply to XCBC for key
- * derivation. */
- case PRF_CAMELLIA128_XCBC:
- /* draft-kanno-ipsecme-camellia-xcbc refers to rfc 4434, we
- * assume fixed key length. */
- key_size = this->prf->get_key_size(this->prf)/2;
- nonce_i.len = min(nonce_i.len, key_size);
- nonce_r.len = min(nonce_r.len, key_size);
+ case IKEV1:
+ keymat_v1_ctor = create;
+ break;
+ case IKEV2:
+ keymat_v2_ctor = create;
break;
default:
- /* all other algorithms use variable key length, full nonce */
break;
}
- fixed_nonce = chunk_cat("cc", nonce_i, nonce_r);
- *((u_int64_t*)spi_i.ptr) = id->get_initiator_spi(id);
- *((u_int64_t*)spi_r.ptr) = id->get_responder_spi(id);
- prf_plus_seed = chunk_cat("ccc", full_nonce, spi_i, spi_r);
-
- /* KEYMAT = prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr)
- *
- * if we are rekeying, SKEYSEED is built on another way
- */
- if (rekey_function == PRF_UNDEFINED) /* not rekeying */
- {
- /* SKEYSEED = prf(Ni | Nr, g^ir) */
- this->prf->set_key(this->prf, fixed_nonce);
- this->prf->allocate_bytes(this->prf, secret, &skeyseed);
- this->prf->set_key(this->prf, skeyseed);
- prf_plus = prf_plus_create(this->prf, prf_plus_seed);
- }
- else
- {
- /* SKEYSEED = prf(SK_d (old), [g^ir (new)] | Ni | Nr)
- * use OLD SAs PRF functions for both prf_plus and prf */
- rekey_prf = lib->crypto->create_prf(lib->crypto, rekey_function);
- if (!rekey_prf)
- {
- DBG1(DBG_IKE, "PRF of old SA %N not supported!",
- pseudo_random_function_names, rekey_function);
- chunk_free(&full_nonce);
- chunk_free(&fixed_nonce);
- chunk_clear(&prf_plus_seed);
- return FALSE;
- }
- secret = chunk_cat("mc", secret, full_nonce);
- rekey_prf->set_key(rekey_prf, rekey_skd);
- rekey_prf->allocate_bytes(rekey_prf, secret, &skeyseed);
- rekey_prf->set_key(rekey_prf, skeyseed);
- prf_plus = prf_plus_create(rekey_prf, prf_plus_seed);
- }
- DBG4(DBG_IKE, "SKEYSEED %B", &skeyseed);
-
- chunk_clear(&skeyseed);
- chunk_clear(&secret);
- chunk_free(&full_nonce);
- chunk_free(&fixed_nonce);
- chunk_clear(&prf_plus_seed);
-
- /* KEYMAT = SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr */
-
- /* SK_d is used for generating CHILD_SA key mat => store for later use */
- key_size = this->prf->get_key_size(this->prf);
- prf_plus->allocate_bytes(prf_plus, key_size, &this->skd);
- DBG4(DBG_IKE, "Sk_d secret %B", &this->skd);
-
- if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg, &key_size))
- {
- DBG1(DBG_IKE, "no %N selected",
- transform_type_names, ENCRYPTION_ALGORITHM);
- prf_plus->destroy(prf_plus);
- DESTROY_IF(rekey_prf);
- return FALSE;
- }
-
- if (encryption_algorithm_is_aead(alg))
- {
- if (!derive_ike_aead(this, alg, key_size, prf_plus))
- {
- prf_plus->destroy(prf_plus);
- DESTROY_IF(rekey_prf);
- return FALSE;
- }
- }
- else
- {
- if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
- &int_alg, NULL))
- {
- DBG1(DBG_IKE, "no %N selected",
- transform_type_names, INTEGRITY_ALGORITHM);
- prf_plus->destroy(prf_plus);
- DESTROY_IF(rekey_prf);
- return FALSE;
- }
- if (!derive_ike_traditional(this, alg, key_size, int_alg, prf_plus))
- {
- prf_plus->destroy(prf_plus);
- DESTROY_IF(rekey_prf);
- return FALSE;
- }
- }
-
- /* SK_pi/SK_pr used for authentication => stored for later */
- key_size = this->prf->get_key_size(this->prf);
- prf_plus->allocate_bytes(prf_plus, key_size, &key);
- DBG4(DBG_IKE, "Sk_pi secret %B", &key);
- if (this->initiator)
- {
- this->skp_build = key;
- }
- else
- {
- this->skp_verify = key;
- }
- prf_plus->allocate_bytes(prf_plus, key_size, &key);
- DBG4(DBG_IKE, "Sk_pr secret %B", &key);
- if (this->initiator)
- {
- this->skp_verify = key;
- }
- else
- {
- this->skp_build = key;
- }
-
- /* all done, prf_plus not needed anymore */
- prf_plus->destroy(prf_plus);
- DESTROY_IF(rekey_prf);
-
- return TRUE;
-}
-
-METHOD(keymat_t, derive_child_keys, bool,
- private_keymat_t *this, proposal_t *proposal, diffie_hellman_t *dh,
- chunk_t nonce_i, chunk_t nonce_r, chunk_t *encr_i, chunk_t *integ_i,
- chunk_t *encr_r, chunk_t *integ_r)
-{
- u_int16_t enc_alg, int_alg, enc_size = 0, int_size = 0;
- chunk_t seed, secret = chunk_empty;
- prf_plus_t *prf_plus;
-
- if (dh)
- {
- if (dh->get_shared_secret(dh, &secret) != SUCCESS)
- {
- return FALSE;
- }
- DBG4(DBG_CHD, "DH secret %B", &secret);
- }
- seed = chunk_cata("mcc", secret, nonce_i, nonce_r);
- DBG4(DBG_CHD, "seed %B", &seed);
-
- if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
- &enc_alg, &enc_size))
- {
- DBG2(DBG_CHD, " using %N for encryption",
- encryption_algorithm_names, enc_alg);
-
- if (!enc_size)
- {
- enc_size = lookup_keylen(keylen_enc, enc_alg);
- }
- if (enc_alg != ENCR_NULL && !enc_size)
- {
- DBG1(DBG_CHD, "no keylength defined for %N",
- encryption_algorithm_names, enc_alg);
- return FALSE;
- }
- /* to bytes */
- enc_size /= 8;
-
- /* CCM/GCM/CTR/GMAC needs additional bytes */
- switch (enc_alg)
- {
- case ENCR_AES_CCM_ICV8:
- case ENCR_AES_CCM_ICV12:
- case ENCR_AES_CCM_ICV16:
- case ENCR_CAMELLIA_CCM_ICV8:
- case ENCR_CAMELLIA_CCM_ICV12:
- case ENCR_CAMELLIA_CCM_ICV16:
- enc_size += 3;
- break;
- case ENCR_AES_GCM_ICV8:
- case ENCR_AES_GCM_ICV12:
- case ENCR_AES_GCM_ICV16:
- case ENCR_AES_CTR:
- case ENCR_NULL_AUTH_AES_GMAC:
- enc_size += 4;
- break;
- default:
- break;
- }
- }
-
- if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
- &int_alg, &int_size))
- {
- DBG2(DBG_CHD, " using %N for integrity",
- integrity_algorithm_names, int_alg);
-
- if (!int_size)
- {
- int_size = lookup_keylen(keylen_int, int_alg);
- }
- if (!int_size)
- {
- DBG1(DBG_CHD, "no keylength defined for %N",
- integrity_algorithm_names, int_alg);
- return FALSE;
- }
- /* to bytes */
- int_size /= 8;
- }
-
- this->prf->set_key(this->prf, this->skd);
- prf_plus = prf_plus_create(this->prf, seed);
-
- prf_plus->allocate_bytes(prf_plus, enc_size, encr_i);
- prf_plus->allocate_bytes(prf_plus, int_size, integ_i);
- prf_plus->allocate_bytes(prf_plus, enc_size, encr_r);
- prf_plus->allocate_bytes(prf_plus, int_size, integ_r);
-
- prf_plus->destroy(prf_plus);
-
- if (enc_size)
- {
- DBG4(DBG_CHD, "encryption initiator key %B", encr_i);
- DBG4(DBG_CHD, "encryption responder key %B", encr_r);
- }
- if (int_size)
- {
- DBG4(DBG_CHD, "integrity initiator key %B", integ_i);
- DBG4(DBG_CHD, "integrity responder key %B", integ_r);
- }
- return TRUE;
-}
-
-METHOD(keymat_t, get_skd, pseudo_random_function_t,
- private_keymat_t *this, chunk_t *skd)
-{
- *skd = this->skd;
- return this->prf_alg;
-}
-
-METHOD(keymat_t, get_aead, aead_t*,
- private_keymat_t *this, bool in)
-{
- return in ? this->aead_in : this->aead_out;
-}
-
-METHOD(keymat_t, get_auth_octets, chunk_t,
- private_keymat_t *this, bool verify, chunk_t ike_sa_init,
- chunk_t nonce, identification_t *id, char reserved[3])
-{
- chunk_t chunk, idx, octets;
- chunk_t skp;
-
- skp = verify ? this->skp_verify : this->skp_build;
-
- chunk = chunk_alloca(4);
- chunk.ptr[0] = id->get_type(id);
- memcpy(chunk.ptr + 1, reserved, 3);
- idx = chunk_cata("cc", chunk, id->get_encoding(id));
-
- DBG3(DBG_IKE, "IDx' %B", &idx);
- DBG3(DBG_IKE, "SK_p %B", &skp);
- this->prf->set_key(this->prf, skp);
- this->prf->allocate_bytes(this->prf, idx, &chunk);
-
- octets = chunk_cat("ccm", ike_sa_init, nonce, chunk);
- DBG3(DBG_IKE, "octets = message + nonce + prf(Sk_px, IDx') %B", &octets);
- return octets;
}
-
-/**
- * Key pad for the AUTH method SHARED_KEY_MESSAGE_INTEGRITY_CODE.
- */
-#define IKEV2_KEY_PAD "Key Pad for IKEv2"
-#define IKEV2_KEY_PAD_LENGTH 17
-
-METHOD(keymat_t, get_psk_sig, chunk_t,
- private_keymat_t *this, bool verify, chunk_t ike_sa_init,
- chunk_t nonce, chunk_t secret, identification_t *id, char reserved[3])
-{
- chunk_t key_pad, key, sig, octets;
-
- if (!secret.len)
- { /* EAP uses SK_p if no MSK has been established */
- secret = verify ? this->skp_verify : this->skp_build;
- }
- octets = get_auth_octets(this, verify, ike_sa_init, nonce, id, reserved);
- /* AUTH = prf(prf(Shared Secret,"Key Pad for IKEv2"), <msg octets>) */
- key_pad = chunk_create(IKEV2_KEY_PAD, IKEV2_KEY_PAD_LENGTH);
- this->prf->set_key(this->prf, secret);
- this->prf->allocate_bytes(this->prf, key_pad, &key);
- this->prf->set_key(this->prf, key);
- this->prf->allocate_bytes(this->prf, octets, &sig);
- DBG4(DBG_IKE, "secret %B", &secret);
- DBG4(DBG_IKE, "prf(secret, keypad) %B", &key);
- DBG3(DBG_IKE, "AUTH = prf(prf(secret, keypad), octets) %B", &sig);
- chunk_free(&octets);
- chunk_free(&key);
-
- return sig;
-}
-
-METHOD(keymat_t, destroy, void,
- private_keymat_t *this)
-{
- DESTROY_IF(this->aead_in);
- DESTROY_IF(this->aead_out);
- DESTROY_IF(this->prf);
- chunk_clear(&this->skd);
- chunk_clear(&this->skp_verify);
- chunk_clear(&this->skp_build);
- free(this);
-}
-
-/**
- * See header
- */
-keymat_t *keymat_create(bool initiator)
-{
- private_keymat_t *this;
-
- INIT(this,
- .public = {
- .create_dh = _create_dh,
- .derive_ike_keys = _derive_ike_keys,
- .derive_child_keys = _derive_child_keys,
- .get_skd = _get_skd,
- .get_aead = _get_aead,
- .get_auth_octets = _get_auth_octets,
- .get_psk_sig = _get_psk_sig,
- .destroy = _destroy,
- },
- .initiator = initiator,
- .prf_alg = PRF_UNDEFINED,
- );
-
- return &this->public;
-}
-
diff --git a/src/libcharon/sa/keymat.h b/src/libcharon/sa/keymat.h
index 6c2b5d4b5..02db5ca58 100644
--- a/src/libcharon/sa/keymat.h
+++ b/src/libcharon/sa/keymat.h
@@ -21,14 +21,23 @@
#ifndef KEYMAT_H_
#define KEYMAT_H_
+typedef struct keymat_t keymat_t;
+
#include <library.h>
#include <utils/identification.h>
#include <crypto/prfs/prf.h>
#include <crypto/aead.h>
#include <config/proposal.h>
+#include <config/peer_cfg.h>
#include <sa/ike_sa_id.h>
-typedef struct keymat_t keymat_t;
+/**
+ * Constructor function for custom keymat implementations
+ *
+ * @param initiator TRUE if the keymat is used as initiator
+ * @return keymat_t implementation
+ */
+typedef keymat_t* (*keymat_constructor_t)(bool initiator);
/**
* Derivation an management of sensitive keying material.
@@ -36,6 +45,13 @@ typedef struct keymat_t keymat_t;
struct keymat_t {
/**
+ * Get IKE version of this keymat.
+ *
+ * @return IKEV1 for keymat_v1_t, IKEV2 for keymat_v2_t
+ */
+ ike_version_t (*get_version)(keymat_t *this);
+
+ /**
* Create a diffie hellman object for key agreement.
*
* The diffie hellman is either for IKE negotiation/rekeying or
@@ -50,58 +66,18 @@ struct keymat_t {
* @param group diffie hellman group
* @return DH object, NULL if group not supported
*/
- diffie_hellman_t* (*create_dh)(keymat_t *this, diffie_hellman_group_t group);
+ diffie_hellman_t* (*create_dh)(keymat_t *this,
+ diffie_hellman_group_t group);
/**
- * Derive keys for the IKE_SA.
+ * Create a nonce generator object.
*
- * These keys are not handed out, but are used by the associated signers,
- * crypters and authentication functions.
+ * The nonce generator can be used to create nonces needed during IKE/CHILD
+ * SA establishment or rekeying.
*
- * @param proposal selected algorithms
- * @param dh diffie hellman key allocated by create_dh()
- * @param nonce_i initiators nonce value
- * @param nonce_r responders nonce value
- * @param id IKE_SA identifier
- * @param rekey_prf PRF of old SA if rekeying, PRF_UNDEFINED otherwise
- * @param rekey_sdk SKd of old SA if rekeying
- * @return TRUE on success
+ * @return nonce generator object
*/
- bool (*derive_ike_keys)(keymat_t *this, proposal_t *proposal,
- diffie_hellman_t *dh, chunk_t nonce_i,
- chunk_t nonce_r, ike_sa_id_t *id,
- pseudo_random_function_t rekey_function,
- chunk_t rekey_skd);
- /**
- * Derive keys for a CHILD_SA.
- *
- * The keys for the CHILD_SA are allocated in the integ and encr chunks.
- * An implementation might hand out encrypted keys only, which are
- * decrypted in the kernel before use.
- * If no PFS is used for the CHILD_SA, dh can be NULL.
- *
- * @param proposal selected algorithms
- * @param dh diffie hellman key allocated by create_dh(), or NULL
- * @param nonce_i initiators nonce value
- * @param nonce_r responders nonce value
- * @param encr_i chunk to write initiators encryption key to
- * @param integ_i chunk to write initiators integrity key to
- * @param encr_r chunk to write responders encryption key to
- * @param integ_r chunk to write responders integrity key to
- * @return TRUE on success
- */
- bool (*derive_child_keys)(keymat_t *this,
- proposal_t *proposal, diffie_hellman_t *dh,
- chunk_t nonce_i, chunk_t nonce_r,
- chunk_t *encr_i, chunk_t *integ_i,
- chunk_t *encr_r, chunk_t *integ_r);
- /**
- * Get SKd to pass to derive_ikey_keys() during rekeying.
- *
- * @param skd chunk to write SKd to (internal data)
- * @return PRF function to derive keymat
- */
- pseudo_random_function_t (*get_skd)(keymat_t *this, chunk_t *skd);
+ nonce_gen_t* (*create_nonce_gen)(keymat_t *this);
/*
* Get a AEAD transform to en-/decrypt and sign/verify IKE messages.
@@ -112,52 +88,43 @@ struct keymat_t {
aead_t* (*get_aead)(keymat_t *this, bool in);
/**
- * Generate octets to use for authentication procedure (RFC4306 2.15).
- *
- * This method creates the plain octets and is usually signed by a private
- * key. PSK and EAP authentication include a secret into the data, use
- * the get_psk_sig() method instead.
- *
- * @param verify TRUE to create for verfification, FALSE to sign
- * @param ike_sa_init encoded ike_sa_init message
- * @param nonce nonce value
- * @param id identity
- * @param reserved reserved bytes of id_payload
- * @return authentication octets
- */
- chunk_t (*get_auth_octets)(keymat_t *this, bool verify, chunk_t ike_sa_init,
- chunk_t nonce, identification_t *id,
- char reserved[3]);
- /**
- * Build the shared secret signature used for PSK and EAP authentication.
- *
- * This method wraps the get_auth_octets() method and additionally
- * includes the secret into the signature. If no secret is given, SK_p is
- * used as secret (used for EAP methods without MSK).
- *
- * @param verify TRUE to create for verfification, FALSE to sign
- * @param ike_sa_init encoded ike_sa_init message
- * @param nonce nonce value
- * @param secret optional secret to include into signature
- * @param id identity
- * @param reserved reserved bytes of id_payload
- * @return signature octets
- */
- chunk_t (*get_psk_sig)(keymat_t *this, bool verify, chunk_t ike_sa_init,
- chunk_t nonce, chunk_t secret,
- identification_t *id, char reserved[3]);
- /**
* Destroy a keymat_t.
*/
void (*destroy)(keymat_t *this);
};
/**
- * Create a keymat instance.
+ * Create the appropriate keymat_t implementation based on the IKE version.
+ *
+ * @param version requested IKE version
+ * @param initiator TRUE if we are initiator
+ * @return keymat_t implmenetation
+ */
+keymat_t *keymat_create(ike_version_t version, bool initiator);
+
+/**
+ * Look up the key length of an encryption algorithm.
+ *
+ * @param alg algorithm to get key length for
+ * @return key length in bits
+ */
+int keymat_get_keylen_encr(encryption_algorithm_t alg);
+
+/**
+ * Look up the key length of an integrity algorithm.
+ *
+ * @param alg algorithm to get key length for
+ * @return key length in bits
+ */
+int keymat_get_keylen_integ(integrity_algorithm_t alg);
+
+/**
+ * Register keymat_t constructor for given IKE version.
*
- * @param initiator TRUE if we are the initiator
- * @return keymat instance
+ * @param version IKE version of given keymat constructor
+ * @param create keymat constructor function, NULL to unregister
*/
-keymat_t *keymat_create(bool initiator);
+void keymat_register_constructor(ike_version_t version,
+ keymat_constructor_t create);
#endif /** KEYMAT_H_ @}*/
diff --git a/src/libcharon/sa/shunt_manager.c b/src/libcharon/sa/shunt_manager.c
index 52b2ecd62..5af43fb91 100644
--- a/src/libcharon/sa/shunt_manager.c
+++ b/src/libcharon/sa/shunt_manager.c
@@ -206,6 +206,7 @@ METHOD(shunt_manager_t, uninstall, bool,
return FALSE;
}
uninstall_shunt_policy(child);
+ child->destroy(child);
return TRUE;
}
diff --git a/src/libcharon/sa/tasks/task.c b/src/libcharon/sa/task.c
index 0d7383141..4336b23ff 100644
--- a/src/libcharon/sa/tasks/task.c
+++ b/src/libcharon/sa/task.c
@@ -16,12 +16,11 @@
#include "task.h"
-#ifdef ME
-ENUM(task_type_names, IKE_INIT, CHILD_REKEY,
+ENUM(task_type_names, TASK_IKE_INIT, TASK_ISAKMP_CERT_POST,
"IKE_INIT",
"IKE_NATD",
"IKE_MOBIKE",
- "IKE_AUTHENTICATE",
+ "IKE_AUTH",
"IKE_AUTH_LIFETIME",
"IKE_CERT_PRE",
"IKE_CERT_POST",
@@ -31,28 +30,23 @@ ENUM(task_type_names, IKE_INIT, CHILD_REKEY,
"IKE_DELETE",
"IKE_DPD",
"IKE_VENDOR",
+#ifdef ME
"IKE_ME",
+#endif /* ME */
"CHILD_CREATE",
"CHILD_DELETE",
"CHILD_REKEY",
+ "MAIN_MODE",
+ "AGGRESSIVE_MODE",
+ "INFORMATIONAL",
+ "ISAKMP_DELETE",
+ "XAUTH",
+ "MODE_CONFIG",
+ "QUICK_MODE",
+ "QUICK_DELETE",
+ "ISAKMP_VENDOR",
+ "ISAKMP_NATD",
+ "ISAKMP_DPD",
+ "ISAKMP_CERT_PRE",
+ "ISAKMP_CERT_POST",
);
-#else
-ENUM(task_type_names, IKE_INIT, CHILD_REKEY,
- "IKE_INIT",
- "IKE_NATD",
- "IKE_MOBIKE",
- "IKE_AUTHENTICATE",
- "IKE_AUTH_LIFETIME",
- "IKE_CERT_PRE",
- "IKE_CERT_POST",
- "IKE_CONFIG",
- "IKE_REKEY",
- "IKE_REAUTH",
- "IKE_DELETE",
- "IKE_DPD",
- "IKE_VENDOR",
- "CHILD_CREATE",
- "CHILD_DELETE",
- "CHILD_REKEY",
-);
-#endif /* ME */
diff --git a/src/libcharon/sa/tasks/task.h b/src/libcharon/sa/task.h
index d57085954..c37221a77 100644
--- a/src/libcharon/sa/tasks/task.h
+++ b/src/libcharon/sa/task.h
@@ -16,7 +16,7 @@
/**
* @defgroup task task
- * @{ @ingroup tasks
+ * @{ @ingroup sa
*/
#ifndef TASK_H_
@@ -34,41 +34,67 @@ typedef struct task_t task_t;
*/
enum task_type_t {
/** establish an unauthenticated IKE_SA */
- IKE_INIT,
+ TASK_IKE_INIT,
/** detect NAT situation */
- IKE_NATD,
+ TASK_IKE_NATD,
/** handle MOBIKE stuff */
- IKE_MOBIKE,
+ TASK_IKE_MOBIKE,
/** authenticate the initiated IKE_SA */
- IKE_AUTHENTICATE,
+ TASK_IKE_AUTH,
/** AUTH_LIFETIME negotiation, RFC4478 */
- IKE_AUTH_LIFETIME,
+ TASK_IKE_AUTH_LIFETIME,
/** certificate processing before authentication (certreqs, cert parsing) */
- IKE_CERT_PRE,
+ TASK_IKE_CERT_PRE,
/** certificate processing after authentication (certs payload generation) */
- IKE_CERT_POST,
+ TASK_IKE_CERT_POST,
/** Configuration payloads, virtual IP and such */
- IKE_CONFIG,
+ TASK_IKE_CONFIG,
/** rekey an IKE_SA */
- IKE_REKEY,
+ TASK_IKE_REKEY,
/** reestablish a complete IKE_SA */
- IKE_REAUTH,
+ TASK_IKE_REAUTH,
/** delete an IKE_SA */
- IKE_DELETE,
+ TASK_IKE_DELETE,
/** liveness check */
- IKE_DPD,
+ TASK_IKE_DPD,
/** Vendor ID processing */
- IKE_VENDOR,
+ TASK_IKE_VENDOR,
#ifdef ME
/** handle ME stuff */
- IKE_ME,
+ TASK_IKE_ME,
#endif /* ME */
/** establish a CHILD_SA within an IKE_SA */
- CHILD_CREATE,
+ TASK_CHILD_CREATE,
/** delete an established CHILD_SA */
- CHILD_DELETE,
+ TASK_CHILD_DELETE,
/** rekey an CHILD_SA */
- CHILD_REKEY,
+ TASK_CHILD_REKEY,
+ /** IKEv1 main mode */
+ TASK_MAIN_MODE,
+ /** IKEv1 aggressive mode */
+ TASK_AGGRESSIVE_MODE,
+ /** IKEv1 informational exchange */
+ TASK_INFORMATIONAL,
+ /** IKEv1 delete using an informational */
+ TASK_ISAKMP_DELETE,
+ /** IKEv1 XAUTH authentication */
+ TASK_XAUTH,
+ /** IKEv1 Mode Config */
+ TASK_MODE_CONFIG,
+ /** IKEv1 quick mode */
+ TASK_QUICK_MODE,
+ /** IKEv1 delete of a quick mode SA */
+ TASK_QUICK_DELETE,
+ /** IKEv1 vendor ID payload handling */
+ TASK_ISAKMP_VENDOR,
+ /** IKEv1 NAT detection */
+ TASK_ISAKMP_NATD,
+ /** IKEv1 DPD */
+ TASK_ISAKMP_DPD,
+ /** IKEv1 pre-authentication certificate handling */
+ TASK_ISAKMP_CERT_PRE,
+ /** IKEv1 post-authentication certificate handling */
+ TASK_ISAKMP_CERT_POST,
};
/**
@@ -105,6 +131,7 @@ struct task_t {
* - FAILED if a critical error occurred
* - DESTROY_ME if IKE_SA has been properly deleted
* - NEED_MORE if another call to build/process needed
+ * - ALREADY_DONE to cancel task processing
* - SUCCESS if task completed
*/
status_t (*build) (task_t *this, message_t *message);
@@ -114,9 +141,10 @@ struct task_t {
*
* @param message message to read payloads from
* @return
- * - FAILED if a critical error occurred
+ * - FAILED if a critical error occurred
* - DESTROY_ME if IKE_SA has been properly deleted
* - NEED_MORE if another call to build/process needed
+ * - ALREADY_DONE to cancel task processing
* - SUCCESS if task completed
*/
status_t (*process) (task_t *this, message_t *message);
diff --git a/src/libcharon/sa/task_manager.c b/src/libcharon/sa/task_manager.c
index 022a5e3d6..c42008ba9 100644
--- a/src/libcharon/sa/task_manager.c
+++ b/src/libcharon/sa/task_manager.c
@@ -1,6 +1,5 @@
/*
- * Copyright (C) 2007 Tobias Brunner
- * Copyright (C) 2007-2010 Martin Willi
+ * Copyright (C) 2011 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -16,1135 +15,29 @@
#include "task_manager.h"
-#include <math.h>
-
-#include <daemon.h>
-#include <sa/tasks/ike_init.h>
-#include <sa/tasks/ike_natd.h>
-#include <sa/tasks/ike_mobike.h>
-#include <sa/tasks/ike_auth.h>
-#include <sa/tasks/ike_auth_lifetime.h>
-#include <sa/tasks/ike_cert_pre.h>
-#include <sa/tasks/ike_cert_post.h>
-#include <sa/tasks/ike_rekey.h>
-#include <sa/tasks/ike_delete.h>
-#include <sa/tasks/ike_config.h>
-#include <sa/tasks/ike_dpd.h>
-#include <sa/tasks/ike_vendor.h>
-#include <sa/tasks/child_create.h>
-#include <sa/tasks/child_rekey.h>
-#include <sa/tasks/child_delete.h>
-#include <encoding/payloads/delete_payload.h>
-#include <processing/jobs/retransmit_job.h>
-
-#ifdef ME
-#include <sa/tasks/ike_me.h>
-#endif
-
-typedef struct exchange_t exchange_t;
+#include <sa/ikev1/task_manager_v1.h>
+#include <sa/ikev2/task_manager_v2.h>
/**
- * An exchange in the air, used do detect and handle retransmission
+ * See header
*/
-struct exchange_t {
-
- /**
- * Message ID used for this transaction
- */
- u_int32_t mid;
-
- /**
- * generated packet for retransmission
- */
- packet_t *packet;
-};
-
-typedef struct private_task_manager_t private_task_manager_t;
-
-/**
- * private data of the task manager
- */
-struct private_task_manager_t {
-
- /**
- * public functions
- */
- task_manager_t public;
-
- /**
- * associated IKE_SA we are serving
- */
- ike_sa_t *ike_sa;
-
- /**
- * Exchange we are currently handling as responder
- */
- struct {
- /**
- * Message ID of the exchange
- */
- u_int32_t mid;
-
- /**
- * packet for retransmission
- */
- packet_t *packet;
-
- } responding;
-
- /**
- * Exchange we are currently handling as initiator
- */
- struct {
- /**
- * Message ID of the exchange
- */
- u_int32_t mid;
-
- /**
- * how many times we have retransmitted so far
- */
- u_int retransmitted;
-
- /**
- * packet for retransmission
- */
- packet_t *packet;
-
- /**
- * type of the initated exchange
- */
- exchange_type_t type;
-
- } initiating;
-
- /**
- * List of queued tasks not yet in action
- */
- linked_list_t *queued_tasks;
-
- /**
- * List of active tasks, initiated by ourselve
- */
- linked_list_t *active_tasks;
-
- /**
- * List of tasks initiated by peer
- */
- linked_list_t *passive_tasks;
-
- /**
- * the task manager has been reset
- */
- bool reset;
-
- /**
- * Number of times we retransmit messages before giving up
- */
- u_int retransmit_tries;
-
- /**
- * Retransmission timeout
- */
- double retransmit_timeout;
-
- /**
- * Base to calculate retransmission timeout
- */
- double retransmit_base;
-};
-
-/**
- * flush all tasks in the task manager
- */
-static void flush(private_task_manager_t *this)
-{
- this->passive_tasks->destroy_offset(this->passive_tasks,
- offsetof(task_t, destroy));
- this->passive_tasks = linked_list_create();
- this->active_tasks->destroy_offset(this->active_tasks,
- offsetof(task_t, destroy));
- this->active_tasks = linked_list_create();
- this->queued_tasks->destroy_offset(this->queued_tasks,
- offsetof(task_t, destroy));
- this->queued_tasks = linked_list_create();
-}
-
-/**
- * move a task of a specific type from the queue to the active list
- */
-static bool activate_task(private_task_manager_t *this, task_type_t type)
-{
- enumerator_t *enumerator;
- task_t *task;
- bool found = FALSE;
-
- enumerator = this->queued_tasks->create_enumerator(this->queued_tasks);
- while (enumerator->enumerate(enumerator, (void**)&task))
- {
- if (task->get_type(task) == type)
- {
- DBG2(DBG_IKE, " activating %N task", task_type_names, type);
- this->queued_tasks->remove_at(this->queued_tasks, enumerator);
- this->active_tasks->insert_last(this->active_tasks, task);
- found = TRUE;
- break;
- }
- }
- enumerator->destroy(enumerator);
- return found;
-}
-
-METHOD(task_manager_t, retransmit, status_t,
- private_task_manager_t *this, u_int32_t message_id)
-{
- if (message_id == this->initiating.mid)
- {
- u_int32_t timeout;
- job_t *job;
- enumerator_t *enumerator;
- packet_t *packet;
- task_t *task;
- ike_mobike_t *mobike = NULL;
-
- /* check if we are retransmitting a MOBIKE routability check */
- enumerator = this->active_tasks->create_enumerator(this->active_tasks);
- while (enumerator->enumerate(enumerator, (void*)&task))
- {
- if (task->get_type(task) == IKE_MOBIKE)
- {
- mobike = (ike_mobike_t*)task;
- if (!mobike->is_probing(mobike))
- {
- mobike = NULL;
- }
- break;
- }
- }
- enumerator->destroy(enumerator);
-
- if (mobike == NULL)
- {
- if (this->initiating.retransmitted <= this->retransmit_tries)
- {
- timeout = (u_int32_t)(this->retransmit_timeout * 1000.0 *
- pow(this->retransmit_base, this->initiating.retransmitted));
- }
- else
- {
- DBG1(DBG_IKE, "giving up after %d retransmits",
- this->initiating.retransmitted - 1);
- if (this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING)
- {
- charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
- }
- return DESTROY_ME;
- }
-
- if (this->initiating.retransmitted)
- {
- DBG1(DBG_IKE, "retransmit %d of request with message ID %d",
- this->initiating.retransmitted, message_id);
- }
- packet = this->initiating.packet->clone(this->initiating.packet);
- charon->sender->send(charon->sender, packet);
- }
- else
- { /* for routeability checks, we use a more aggressive behavior */
- if (this->initiating.retransmitted <= ROUTEABILITY_CHECK_TRIES)
- {
- timeout = ROUTEABILITY_CHECK_INTERVAL;
- }
- else
- {
- DBG1(DBG_IKE, "giving up after %d path probings",
- this->initiating.retransmitted - 1);
- charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
- return DESTROY_ME;
- }
-
- if (this->initiating.retransmitted)
- {
- DBG1(DBG_IKE, "path probing attempt %d",
- this->initiating.retransmitted);
- }
- mobike->transmit(mobike, this->initiating.packet);
- }
-
- this->initiating.retransmitted++;
- job = (job_t*)retransmit_job_create(this->initiating.mid,
- this->ike_sa->get_id(this->ike_sa));
- lib->scheduler->schedule_job_ms(lib->scheduler, job, timeout);
- }
- return SUCCESS;
-}
-
-METHOD(task_manager_t, initiate, status_t,
- private_task_manager_t *this)
+task_manager_t *task_manager_create(ike_sa_t *ike_sa)
{
- enumerator_t *enumerator;
- task_t *task;
- message_t *message;
- host_t *me, *other;
- status_t status;
- exchange_type_t exchange = 0;
-
- if (this->initiating.type != EXCHANGE_TYPE_UNDEFINED)
- {
- DBG2(DBG_IKE, "delaying task initiation, %N exchange in progress",
- exchange_type_names, this->initiating.type);
- /* do not initiate if we already have a message in the air */
- return SUCCESS;
- }
-
- if (this->active_tasks->get_count(this->active_tasks) == 0)
- {
- DBG2(DBG_IKE, "activating new tasks");
- switch (this->ike_sa->get_state(this->ike_sa))
- {
- case IKE_CREATED:
- activate_task(this, IKE_VENDOR);
- if (activate_task(this, IKE_INIT))
- {
- this->initiating.mid = 0;
- exchange = IKE_SA_INIT;
- activate_task(this, IKE_NATD);
- activate_task(this, IKE_CERT_PRE);
-#ifdef ME
- /* this task has to be activated before the IKE_AUTHENTICATE
- * task, because that task pregenerates the packet after
- * which no payloads can be added to the message anymore.
- */
- activate_task(this, IKE_ME);
-#endif /* ME */
- activate_task(this, IKE_AUTHENTICATE);
- activate_task(this, IKE_CERT_POST);
- activate_task(this, IKE_CONFIG);
- activate_task(this, CHILD_CREATE);
- activate_task(this, IKE_AUTH_LIFETIME);
- activate_task(this, IKE_MOBIKE);
- }
- break;
- case IKE_ESTABLISHED:
- if (activate_task(this, CHILD_CREATE))
- {
- exchange = CREATE_CHILD_SA;
- break;
- }
- if (activate_task(this, CHILD_DELETE))
- {
- exchange = INFORMATIONAL;
- break;
- }
- if (activate_task(this, CHILD_REKEY))
- {
- exchange = CREATE_CHILD_SA;
- break;
- }
- if (activate_task(this, IKE_DELETE))
- {
- exchange = INFORMATIONAL;
- break;
- }
- if (activate_task(this, IKE_REKEY))
- {
- exchange = CREATE_CHILD_SA;
- break;
- }
- if (activate_task(this, IKE_REAUTH))
- {
- exchange = INFORMATIONAL;
- break;
- }
- if (activate_task(this, IKE_MOBIKE))
- {
- exchange = INFORMATIONAL;
- break;
- }
- if (activate_task(this, IKE_DPD))
- {
- exchange = INFORMATIONAL;
- break;
- }
- if (activate_task(this, IKE_AUTH_LIFETIME))
- {
- exchange = INFORMATIONAL;
- break;
- }
-#ifdef ME
- if (activate_task(this, IKE_ME))
- {
- exchange = ME_CONNECT;
- break;
- }
-#endif /* ME */
- case IKE_REKEYING:
- if (activate_task(this, IKE_DELETE))
- {
- exchange = INFORMATIONAL;
- break;
- }
- case IKE_DELETING:
- default:
- break;
- }
- }
- else
+ switch (ike_sa->get_version(ike_sa))
{
- DBG2(DBG_IKE, "reinitiating already active tasks");
- enumerator = this->active_tasks->create_enumerator(this->active_tasks);
- while (enumerator->enumerate(enumerator, (void**)&task))
- {
- DBG2(DBG_IKE, " %N task", task_type_names, task->get_type(task));
- switch (task->get_type(task))
- {
- case IKE_INIT:
- exchange = IKE_SA_INIT;
- break;
- case IKE_AUTHENTICATE:
- exchange = IKE_AUTH;
- break;
- case CHILD_CREATE:
- case CHILD_REKEY:
- case IKE_REKEY:
- exchange = CREATE_CHILD_SA;
- break;
- case IKE_MOBIKE:
- exchange = INFORMATIONAL;
- break;
- default:
- continue;
- }
+ case IKEV1:
+#ifdef USE_IKEV1
+ return &task_manager_v1_create(ike_sa)->task_manager;
+#endif
break;
- }
- enumerator->destroy(enumerator);
- }
-
- if (exchange == 0)
- {
- DBG2(DBG_IKE, "nothing to initiate");
- /* nothing to do yet... */
- return SUCCESS;
- }
-
- me = this->ike_sa->get_my_host(this->ike_sa);
- other = this->ike_sa->get_other_host(this->ike_sa);
-
- message = message_create();
- message->set_message_id(message, this->initiating.mid);
- message->set_source(message, me->clone(me));
- message->set_destination(message, other->clone(other));
- message->set_exchange_type(message, exchange);
- this->initiating.type = exchange;
- this->initiating.retransmitted = 0;
-
- enumerator = this->active_tasks->create_enumerator(this->active_tasks);
- while (enumerator->enumerate(enumerator, (void*)&task))
- {
- switch (task->build(task, message))
- {
- case SUCCESS:
- /* task completed, remove it */
- this->active_tasks->remove_at(this->active_tasks, enumerator);
- task->destroy(task);
- break;
- case NEED_MORE:
- /* processed, but task needs another exchange */
- break;
- case FAILED:
- default:
- if (this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING)
- {
- charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
- }
- /* FALL */
- case DESTROY_ME:
- /* critical failure, destroy IKE_SA */
- enumerator->destroy(enumerator);
- message->destroy(message);
- flush(this);
- return DESTROY_ME;
- }
- }
- enumerator->destroy(enumerator);
-
- /* update exchange type if a task changed it */
- this->initiating.type = message->get_exchange_type(message);
-
- status = this->ike_sa->generate_message(this->ike_sa, message,
- &this->initiating.packet);
- if (status != SUCCESS)
- {
- /* message generation failed. There is nothing more to do than to
- * close the SA */
- message->destroy(message);
- flush(this);
- charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
- return DESTROY_ME;
- }
- message->destroy(message);
-
- return retransmit(this, this->initiating.mid);
-}
-
-/**
- * handle an incoming response message
- */
-static status_t process_response(private_task_manager_t *this,
- message_t *message)
-{
- enumerator_t *enumerator;
- task_t *task;
-
- if (message->get_exchange_type(message) != this->initiating.type)
- {
- DBG1(DBG_IKE, "received %N response, but expected %N",
- exchange_type_names, message->get_exchange_type(message),
- exchange_type_names, this->initiating.type);
- charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
- return DESTROY_ME;
- }
-
- /* catch if we get resetted while processing */
- this->reset = FALSE;
- enumerator = this->active_tasks->create_enumerator(this->active_tasks);
- while (enumerator->enumerate(enumerator, (void*)&task))
- {
- switch (task->process(task, message))
- {
- case SUCCESS:
- /* task completed, remove it */
- this->active_tasks->remove_at(this->active_tasks, enumerator);
- task->destroy(task);
- break;
- case NEED_MORE:
- /* processed, but task needs another exchange */
- break;
- case FAILED:
- default:
- charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
- /* FALL */
- case DESTROY_ME:
- /* critical failure, destroy IKE_SA */
- this->active_tasks->remove_at(this->active_tasks, enumerator);
- enumerator->destroy(enumerator);
- task->destroy(task);
- return DESTROY_ME;
- }
- if (this->reset)
- { /* start all over again if we were reset */
- this->reset = FALSE;
- enumerator->destroy(enumerator);
- return initiate(this);
- }
- }
- enumerator->destroy(enumerator);
-
- this->initiating.mid++;
- this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
- this->initiating.packet->destroy(this->initiating.packet);
- this->initiating.packet = NULL;
-
- return initiate(this);
-}
-
-/**
- * handle exchange collisions
- */
-static bool handle_collisions(private_task_manager_t *this, task_t *task)
-{
- enumerator_t *enumerator;
- task_t *active;
- task_type_t type;
-
- type = task->get_type(task);
-
- /* do we have to check */
- if (type == IKE_REKEY || type == CHILD_REKEY ||
- type == CHILD_DELETE || type == IKE_DELETE || type == IKE_REAUTH)
- {
- /* find an exchange collision, and notify these tasks */
- enumerator = this->active_tasks->create_enumerator(this->active_tasks);
- while (enumerator->enumerate(enumerator, (void**)&active))
- {
- switch (active->get_type(active))
- {
- case IKE_REKEY:
- if (type == IKE_REKEY || type == IKE_DELETE ||
- type == IKE_REAUTH)
- {
- ike_rekey_t *rekey = (ike_rekey_t*)active;
- rekey->collide(rekey, task);
- break;
- }
- continue;
- case CHILD_REKEY:
- if (type == CHILD_REKEY || type == CHILD_DELETE)
- {
- child_rekey_t *rekey = (child_rekey_t*)active;
- rekey->collide(rekey, task);
- break;
- }
- continue;
- default:
- continue;
- }
- enumerator->destroy(enumerator);
- return TRUE;
- }
- enumerator->destroy(enumerator);
- }
- return FALSE;
-}
-
-/**
- * build a response depending on the "passive" task list
- */
-static status_t build_response(private_task_manager_t *this, message_t *request)
-{
- enumerator_t *enumerator;
- task_t *task;
- message_t *message;
- host_t *me, *other;
- bool delete = FALSE, hook = FALSE;
- status_t status;
-
- me = request->get_destination(request);
- other = request->get_source(request);
-
- message = message_create();
- message->set_exchange_type(message, request->get_exchange_type(request));
- /* send response along the path the request came in */
- message->set_source(message, me->clone(me));
- message->set_destination(message, other->clone(other));
- message->set_message_id(message, this->responding.mid);
- message->set_request(message, FALSE);
-
- enumerator = this->passive_tasks->create_enumerator(this->passive_tasks);
- while (enumerator->enumerate(enumerator, (void*)&task))
- {
- switch (task->build(task, message))
- {
- case SUCCESS:
- /* task completed, remove it */
- this->passive_tasks->remove_at(this->passive_tasks, enumerator);
- if (!handle_collisions(this, task))
- {
- task->destroy(task);
- }
- break;
- case NEED_MORE:
- /* processed, but task needs another exchange */
- if (handle_collisions(this, task))
- {
- this->passive_tasks->remove_at(this->passive_tasks,
- enumerator);
- }
- break;
- case FAILED:
- default:
- hook = TRUE;
- /* FALL */
- case DESTROY_ME:
- /* destroy IKE_SA, but SEND response first */
- delete = TRUE;
- break;
- }
- if (delete)
- {
+ case IKEV2:
+#ifdef USE_IKEV2
+ return &task_manager_v2_create(ike_sa)->task_manager;
+#endif
break;
- }
- }
- enumerator->destroy(enumerator);
-
- /* remove resonder SPI if IKE_SA_INIT failed */
- if (delete && request->get_exchange_type(request) == IKE_SA_INIT)
- {
- ike_sa_id_t *id = this->ike_sa->get_id(this->ike_sa);
- id->set_responder_spi(id, 0);
- }
-
- /* message complete, send it */
- DESTROY_IF(this->responding.packet);
- this->responding.packet = NULL;
- status = this->ike_sa->generate_message(this->ike_sa, message,
- &this->responding.packet);
- message->destroy(message);
- if (status != SUCCESS)
- {
- charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
- return DESTROY_ME;
- }
-
- charon->sender->send(charon->sender,
- this->responding.packet->clone(this->responding.packet));
- if (delete)
- {
- if (hook)
- {
- charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
- }
- return DESTROY_ME;
- }
- return SUCCESS;
-}
-
-/**
- * handle an incoming request message
- */
-static status_t process_request(private_task_manager_t *this,
- message_t *message)
-{
- enumerator_t *enumerator;
- task_t *task = NULL;
- payload_t *payload;
- notify_payload_t *notify;
- delete_payload_t *delete;
-
- if (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))
- {
- case IKE_SA_INIT:
- {
- task = (task_t*)ike_vendor_create(this->ike_sa, FALSE);
- this->passive_tasks->insert_last(this->passive_tasks, task);
- task = (task_t*)ike_init_create(this->ike_sa, FALSE, NULL);
- this->passive_tasks->insert_last(this->passive_tasks, task);
- task = (task_t*)ike_natd_create(this->ike_sa, FALSE);
- this->passive_tasks->insert_last(this->passive_tasks, task);
- task = (task_t*)ike_cert_pre_create(this->ike_sa, FALSE);
- this->passive_tasks->insert_last(this->passive_tasks, task);
-#ifdef ME
- task = (task_t*)ike_me_create(this->ike_sa, FALSE);
- this->passive_tasks->insert_last(this->passive_tasks, task);
-#endif /* ME */
- task = (task_t*)ike_auth_create(this->ike_sa, FALSE);
- this->passive_tasks->insert_last(this->passive_tasks, task);
- task = (task_t*)ike_cert_post_create(this->ike_sa, FALSE);
- this->passive_tasks->insert_last(this->passive_tasks, task);
- task = (task_t*)ike_config_create(this->ike_sa, FALSE);
- this->passive_tasks->insert_last(this->passive_tasks, task);
- task = (task_t*)child_create_create(this->ike_sa, NULL, FALSE,
- NULL, NULL);
- this->passive_tasks->insert_last(this->passive_tasks, task);
- task = (task_t*)ike_auth_lifetime_create(this->ike_sa, FALSE);
- this->passive_tasks->insert_last(this->passive_tasks, task);
- task = (task_t*)ike_mobike_create(this->ike_sa, FALSE);
- this->passive_tasks->insert_last(this->passive_tasks, task);
- break;
- }
- case CREATE_CHILD_SA:
- { /* FIXME: we should prevent this on mediation connections */
- bool notify_found = FALSE, ts_found = FALSE;
- enumerator = message->create_payload_enumerator(message);
- while (enumerator->enumerate(enumerator, &payload))
- {
- switch (payload->get_type(payload))
- {
- case NOTIFY:
- { /* if we find a rekey notify, its CHILD_SA rekeying */
- notify = (notify_payload_t*)payload;
- if (notify->get_notify_type(notify) == REKEY_SA &&
- (notify->get_protocol_id(notify) == PROTO_AH ||
- notify->get_protocol_id(notify) == PROTO_ESP))
- {
- notify_found = TRUE;
- }
- break;
- }
- case TRAFFIC_SELECTOR_INITIATOR:
- case TRAFFIC_SELECTOR_RESPONDER:
- { /* if we don't find a TS, its IKE rekeying */
- ts_found = TRUE;
- break;
- }
- default:
- break;
- }
- }
- enumerator->destroy(enumerator);
-
- if (ts_found)
- {
- if (notify_found)
- {
- task = (task_t*)child_rekey_create(this->ike_sa,
- PROTO_NONE, 0);
- }
- else
- {
- task = (task_t*)child_create_create(this->ike_sa, NULL,
- FALSE, NULL, NULL);
- }
- }
- else
- {
- task = (task_t*)ike_rekey_create(this->ike_sa, FALSE);
- }
- this->passive_tasks->insert_last(this->passive_tasks, task);
- break;
- }
- case INFORMATIONAL:
- {
- enumerator = message->create_payload_enumerator(message);
- while (enumerator->enumerate(enumerator, &payload))
- {
- switch (payload->get_type(payload))
- {
- case NOTIFY:
- {
- notify = (notify_payload_t*)payload;
- switch (notify->get_notify_type(notify))
- {
- case ADDITIONAL_IP4_ADDRESS:
- case ADDITIONAL_IP6_ADDRESS:
- case NO_ADDITIONAL_ADDRESSES:
- case UPDATE_SA_ADDRESSES:
- case NO_NATS_ALLOWED:
- case UNACCEPTABLE_ADDRESSES:
- case UNEXPECTED_NAT_DETECTED:
- case COOKIE2:
- case NAT_DETECTION_SOURCE_IP:
- case NAT_DETECTION_DESTINATION_IP:
- task = (task_t*)ike_mobike_create(
- this->ike_sa, FALSE);
- break;
- case AUTH_LIFETIME:
- task = (task_t*)ike_auth_lifetime_create(
- this->ike_sa, FALSE);
- break;
- default:
- break;
- }
- break;
- }
- case DELETE:
- {
- delete = (delete_payload_t*)payload;
- if (delete->get_protocol_id(delete) == PROTO_IKE)
- {
- task = (task_t*)ike_delete_create(this->ike_sa,
- FALSE);
- }
- else
- {
- task = (task_t*)child_delete_create(this->ike_sa,
- PROTO_NONE, 0);
- }
- break;
- }
- default:
- break;
- }
- if (task)
- {
- break;
- }
- }
- enumerator->destroy(enumerator);
-
- if (task == NULL)
- {
- task = (task_t*)ike_dpd_create(FALSE);
- }
- this->passive_tasks->insert_last(this->passive_tasks, task);
- break;
- }
-#ifdef ME
- case ME_CONNECT:
- {
- task = (task_t*)ike_me_create(this->ike_sa, FALSE);
- this->passive_tasks->insert_last(this->passive_tasks, task);
- }
-#endif /* ME */
- default:
- break;
- }
- }
-
- /* let the tasks process the message */
- enumerator = this->passive_tasks->create_enumerator(this->passive_tasks);
- while (enumerator->enumerate(enumerator, (void*)&task))
- {
- switch (task->process(task, message))
- {
- case SUCCESS:
- /* task completed, remove it */
- this->passive_tasks->remove_at(this->passive_tasks, enumerator);
- task->destroy(task);
- break;
- case NEED_MORE:
- /* processed, but task needs at least another call to build() */
- break;
- case FAILED:
- default:
- charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
- /* FALL */
- case DESTROY_ME:
- /* critical failure, destroy IKE_SA */
- this->passive_tasks->remove_at(this->passive_tasks, enumerator);
- enumerator->destroy(enumerator);
- task->destroy(task);
- return DESTROY_ME;
- }
- }
- enumerator->destroy(enumerator);
-
- return build_response(this, message);
-}
-
-METHOD(task_manager_t, process_message, status_t,
- private_task_manager_t *this, message_t *msg)
-{
- host_t *me, *other;
- u_int32_t mid;
-
- mid = msg->get_message_id(msg);
- me = msg->get_destination(msg);
- other = msg->get_source(msg);
-
- if (msg->get_request(msg))
- {
- if (mid == this->responding.mid)
- {
- if (this->ike_sa->get_state(this->ike_sa) == IKE_CREATED ||
- this->ike_sa->get_state(this->ike_sa) == IKE_CONNECTING ||
- msg->get_exchange_type(msg) != IKE_SA_INIT)
- { /* only do host updates based on verified messages */
- if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE))
- { /* with MOBIKE, we do no implicit updates */
- this->ike_sa->update_hosts(this->ike_sa, me, other, mid == 1);
- }
- }
- charon->bus->message(charon->bus, msg, TRUE);
- if (msg->get_exchange_type(msg) == EXCHANGE_TYPE_UNDEFINED)
- { /* ignore messages altered to EXCHANGE_TYPE_UNDEFINED */
- return SUCCESS;
- }
- if (process_request(this, msg) != SUCCESS)
- {
- flush(this);
- return DESTROY_ME;
- }
- this->responding.mid++;
- }
- else if ((mid == this->responding.mid - 1) && this->responding.packet)
- {
- packet_t *clone;
- host_t *host;
-
- DBG1(DBG_IKE, "received retransmit of request with ID %d, "
- "retransmitting response", mid);
- clone = this->responding.packet->clone(this->responding.packet);
- host = msg->get_destination(msg);
- clone->set_source(clone, host->clone(host));
- host = msg->get_source(msg);
- clone->set_destination(clone, host->clone(host));
- charon->sender->send(charon->sender, clone);
- }
- else
- {
- DBG1(DBG_IKE, "received message ID %d, expected %d. Ignored",
- mid, this->responding.mid);
- }
- }
- else
- {
- if (mid == this->initiating.mid)
- {
- if (this->ike_sa->get_state(this->ike_sa) == IKE_CREATED ||
- this->ike_sa->get_state(this->ike_sa) == IKE_CONNECTING ||
- msg->get_exchange_type(msg) != IKE_SA_INIT)
- { /* only do host updates based on verified messages */
- if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE))
- { /* with MOBIKE, we do no implicit updates */
- this->ike_sa->update_hosts(this->ike_sa, me, other, FALSE);
- }
- }
- charon->bus->message(charon->bus, msg, TRUE);
- if (msg->get_exchange_type(msg) == EXCHANGE_TYPE_UNDEFINED)
- { /* ignore messages altered to EXCHANGE_TYPE_UNDEFINED */
- return SUCCESS;
- }
- if (process_response(this, msg) != SUCCESS)
- {
- flush(this);
- return DESTROY_ME;
- }
- }
- else
- {
- DBG1(DBG_IKE, "received message ID %d, expected %d. Ignored",
- mid, this->initiating.mid);
- return SUCCESS;
- }
- }
- return SUCCESS;
-}
-
-METHOD(task_manager_t, queue_task, void,
- private_task_manager_t *this, task_t *task)
-{
- if (task->get_type(task) == IKE_MOBIKE)
- { /* there is no need to queue more than one mobike task */
- enumerator_t *enumerator;
- task_t *current;
-
- enumerator = this->queued_tasks->create_enumerator(this->queued_tasks);
- while (enumerator->enumerate(enumerator, (void**)&current))
- {
- if (current->get_type(current) == IKE_MOBIKE)
- {
- enumerator->destroy(enumerator);
- task->destroy(task);
- return;
- }
- }
- enumerator->destroy(enumerator);
- }
- DBG2(DBG_IKE, "queueing %N task", task_type_names, task->get_type(task));
- this->queued_tasks->insert_last(this->queued_tasks, task);
-}
-
-METHOD(task_manager_t, adopt_tasks, void,
- private_task_manager_t *this, task_manager_t *other_public)
-{
- private_task_manager_t *other = (private_task_manager_t*)other_public;
- task_t *task;
-
- /* move queued tasks from other to this */
- while (other->queued_tasks->remove_last(other->queued_tasks,
- (void**)&task) == SUCCESS)
- {
- DBG2(DBG_IKE, "migrating %N task", task_type_names, task->get_type(task));
- task->migrate(task, this->ike_sa);
- this->queued_tasks->insert_first(this->queued_tasks, task);
- }
-}
-
-METHOD(task_manager_t, busy, bool,
- private_task_manager_t *this)
-{
- return (this->active_tasks->get_count(this->active_tasks) > 0);
-}
-
-METHOD(task_manager_t, incr_mid, void,
- private_task_manager_t *this, bool initiate)
-{
- if (initiate)
- {
- this->initiating.mid++;
- }
- else
- {
- this->responding.mid++;
- }
-}
-
-METHOD(task_manager_t, reset, void,
- private_task_manager_t *this, u_int32_t initiate, u_int32_t respond)
-{
- enumerator_t *enumerator;
- task_t *task;
-
- /* reset message counters and retransmit packets */
- DESTROY_IF(this->responding.packet);
- DESTROY_IF(this->initiating.packet);
- this->responding.packet = NULL;
- this->initiating.packet = NULL;
- if (initiate != UINT_MAX)
- {
- this->initiating.mid = initiate;
- }
- if (respond != UINT_MAX)
- {
- this->responding.mid = respond;
- }
- this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
-
- /* reset queued tasks */
- enumerator = this->queued_tasks->create_enumerator(this->queued_tasks);
- while (enumerator->enumerate(enumerator, &task))
- {
- task->migrate(task, this->ike_sa);
- }
- enumerator->destroy(enumerator);
-
- /* reset active tasks */
- while (this->active_tasks->remove_last(this->active_tasks,
- (void**)&task) == SUCCESS)
- {
- task->migrate(task, this->ike_sa);
- this->queued_tasks->insert_first(this->queued_tasks, task);
- }
-
- this->reset = TRUE;
-}
-
-METHOD(task_manager_t, create_task_enumerator, enumerator_t*,
- private_task_manager_t *this, task_queue_t queue)
-{
- switch (queue)
- {
- case TASK_QUEUE_ACTIVE:
- return this->active_tasks->create_enumerator(this->active_tasks);
- case TASK_QUEUE_PASSIVE:
- return this->passive_tasks->create_enumerator(this->passive_tasks);
- case TASK_QUEUE_QUEUED:
- return this->queued_tasks->create_enumerator(this->queued_tasks);
default:
- return enumerator_create_empty();
+ break;
}
-}
-
-METHOD(task_manager_t, destroy, void,
- private_task_manager_t *this)
-{
- flush(this);
-
- this->active_tasks->destroy(this->active_tasks);
- this->queued_tasks->destroy(this->queued_tasks);
- this->passive_tasks->destroy(this->passive_tasks);
-
- DESTROY_IF(this->responding.packet);
- DESTROY_IF(this->initiating.packet);
- free(this);
-}
-
-/*
- * see header file
- */
-task_manager_t *task_manager_create(ike_sa_t *ike_sa)
-{
- private_task_manager_t *this;
-
- INIT(this,
- .public = {
- .process_message = _process_message,
- .queue_task = _queue_task,
- .initiate = _initiate,
- .retransmit = _retransmit,
- .incr_mid = _incr_mid,
- .reset = _reset,
- .adopt_tasks = _adopt_tasks,
- .busy = _busy,
- .create_task_enumerator = _create_task_enumerator,
- .destroy = _destroy,
- },
- .ike_sa = ike_sa,
- .initiating.type = EXCHANGE_TYPE_UNDEFINED,
- .queued_tasks = linked_list_create(),
- .active_tasks = linked_list_create(),
- .passive_tasks = linked_list_create(),
- .retransmit_tries = lib->settings->get_int(lib->settings,
- "charon.retransmit_tries", RETRANSMIT_TRIES),
- .retransmit_timeout = lib->settings->get_double(lib->settings,
- "charon.retransmit_timeout", RETRANSMIT_TIMEOUT),
- .retransmit_base = lib->settings->get_double(lib->settings,
- "charon.retransmit_base", RETRANSMIT_BASE),
- );
-
- return &this->public;
+ return NULL;
}
diff --git a/src/libcharon/sa/task_manager.h b/src/libcharon/sa/task_manager.h
index 5bc6c80c4..c649cf78e 100644
--- a/src/libcharon/sa/task_manager.h
+++ b/src/libcharon/sa/task_manager.h
@@ -29,7 +29,7 @@ typedef enum task_queue_t task_queue_t;
#include <library.h>
#include <encoding/message.h>
#include <sa/ike_sa.h>
-#include <sa/tasks/task.h>
+#include <sa/task.h>
/**
* First retransmit timeout in seconds.
@@ -125,6 +125,69 @@ struct task_manager_t {
void (*queue_task) (task_manager_t *this, task_t *task);
/**
+ * Queue IKE_SA establishing tasks.
+ */
+ void (*queue_ike)(task_manager_t *this);
+
+ /**
+ * Queue IKE_SA rekey tasks.
+ */
+ void (*queue_ike_rekey)(task_manager_t *this);
+
+ /**
+ * Queue IKE_SA reauth tasks.
+ */
+ void (*queue_ike_reauth)(task_manager_t *this);
+
+ /**
+ * Queue MOBIKE task
+ *
+ * @param roam TRUE to switch to new address
+ * @param address TRUE to include address list update
+ */
+ void (*queue_mobike)(task_manager_t *this, bool roam, bool address);
+
+ /**
+ * Queue IKE_SA delete tasks.
+ */
+ void (*queue_ike_delete)(task_manager_t *this);
+
+ /**
+ * Queue CHILD_SA establishing tasks.
+ *
+ * @param cfg CHILD_SA config to establish
+ * @param reqid reqid to use for CHILD_SA
+ * @param tsi initiator traffic selector, if packet-triggered
+ * @param tsr responder traffic selector, if packet-triggered
+ */
+ void (*queue_child)(task_manager_t *this, child_cfg_t *cfg, u_int32_t reqid,
+ traffic_selector_t *tsi, traffic_selector_t *tsr);
+
+ /**
+ * Queue CHILD_SA rekeying tasks.
+ *
+ * @param protocol CHILD_SA protocol, AH|ESP
+ * @param spi CHILD_SA SPI to rekey
+ */
+ void (*queue_child_rekey)(task_manager_t *this, protocol_id_t protocol,
+ u_int32_t spi);
+
+ /**
+ * Queue CHILD_SA delete tasks.
+ *
+ * @param protocol CHILD_SA protocol, AH|ESP
+ * @param spi CHILD_SA SPI to rekey
+ * @param expired TRUE if SA already expired
+ */
+ void (*queue_child_delete)(task_manager_t *this, protocol_id_t protocol,
+ u_int32_t spi, bool expired);
+
+ /**
+ * Queue liveness checking tasks.
+ */
+ void (*queue_dpd)(task_manager_t *this);
+
+ /**
* Retransmit a request if it hasn't been acknowledged yet.
*
* A return value of INVALID_STATE means that the message was already
@@ -166,9 +229,11 @@ struct task_manager_t {
* resets the message IDs and resets all active tasks using the migrate()
* method.
* Use a value of UINT_MAX to keep the current message ID.
+ * For IKEv1, the arguments do not set the message ID, but the DPD sequence
+ * number counters.
*
- * @param initiate message ID to initiate exchanges (send)
- * @param respond message ID to respond to exchanges (expect)
+ * @param initiate message ID / DPD seq to initiate exchanges (send)
+ * @param respond message ID / DPD seq to respond to exchanges (expect)
*/
void (*reset) (task_manager_t *this, u_int32_t initiate, u_int32_t respond);
@@ -189,15 +254,23 @@ struct task_manager_t {
task_queue_t queue);
/**
+ * Flush a queue, cancelling all tasks.
+ *
+ * @param queue queue to flush
+ */
+ void (*flush_queue)(task_manager_t *this, task_queue_t queue);
+
+ /**
* Destroy the task_manager_t.
*/
void (*destroy) (task_manager_t *this);
};
/**
- * Create an instance of the task manager.
+ * Create a task manager instance for the correct IKE version.
*
- * @param ike_sa IKE_SA to manage.
+ * @param ike_sa IKE_SA to create a task manager for
+ * @return task manager implementation for IKE version
*/
task_manager_t *task_manager_create(ike_sa_t *ike_sa);
diff --git a/src/libcharon/sa/trap_manager.c b/src/libcharon/sa/trap_manager.c
index 86d9f4c22..fdcfa0a20 100644
--- a/src/libcharon/sa/trap_manager.c
+++ b/src/libcharon/sa/trap_manager.c
@@ -98,7 +98,7 @@ METHOD(trap_manager_t, install, u_int32_t,
ike_cfg_t *ike_cfg;
child_sa_t *child_sa;
host_t *me, *other;
- linked_list_t *my_ts, *other_ts;
+ linked_list_t *my_ts, *other_ts, *list;
enumerator_t *enumerator;
bool found = FALSE;
status_t status;
@@ -127,14 +127,14 @@ METHOD(trap_manager_t, install, u_int32_t,
/* try to resolve addresses */
ike_cfg = peer->get_ike_cfg(peer);
- other = host_create_from_dns(ike_cfg->get_other_addr(ike_cfg),
+ other = host_create_from_dns(ike_cfg->get_other_addr(ike_cfg, NULL),
0, ike_cfg->get_other_port(ike_cfg));
if (!other || other->is_anyaddr(other))
{
DBG1(DBG_CFG, "installing trap failed, remote address unknown");
return 0;
}
- me = host_create_from_dns(ike_cfg->get_my_addr(ike_cfg),
+ me = host_create_from_dns(ike_cfg->get_my_addr(ike_cfg, NULL),
other->get_family(other), ike_cfg->get_my_port(ike_cfg));
if (!me || me->is_anyaddr(me))
{
@@ -152,10 +152,14 @@ METHOD(trap_manager_t, install, u_int32_t,
/* create and route CHILD_SA */
child_sa = child_sa_create(me, other, child, 0, FALSE);
- my_ts = child->get_traffic_selectors(child, TRUE, NULL, me);
- other_ts = child->get_traffic_selectors(child, FALSE, NULL, other);
- me->destroy(me);
- other->destroy(other);
+
+ list = linked_list_create_with_items(me, NULL);
+ my_ts = child->get_traffic_selectors(child, TRUE, NULL, list);
+ list->destroy_offset(list, offsetof(host_t, destroy));
+
+ list = linked_list_create_with_items(other, NULL);
+ other_ts = child->get_traffic_selectors(child, FALSE, NULL, list);
+ list->destroy_offset(list, offsetof(host_t, destroy));
/* while we don't know the finally negotiated protocol (ESP|AH), we
* could iterate all proposals for a best guess (TODO). But as we
@@ -284,26 +288,34 @@ METHOD(trap_manager_t, acquire, void,
ike_sa = charon->ike_sa_manager->checkout_by_config(
charon->ike_sa_manager, peer);
- if (ike_sa->get_peer_cfg(ike_sa) == NULL)
- {
- ike_sa->set_peer_cfg(ike_sa, peer);
- }
- if (ike_sa->initiate(ike_sa, child, reqid, src, dst) != DESTROY_ME)
+ if (ike_sa)
{
- /* make sure the entry is still there */
- this->lock->read_lock(this->lock);
- if (this->traps->find_first(this->traps, NULL,
- (void**)&found) == SUCCESS)
+ if (ike_sa->get_peer_cfg(ike_sa) == NULL)
{
- found->ike_sa = ike_sa;
+ ike_sa->set_peer_cfg(ike_sa, peer);
+ }
+ if (ike_sa->get_version(ike_sa) == IKEV1)
+ { /* in IKEv1, don't prepend the acquiring packet TS, as we only
+ * have a single TS that we can establish in a Quick Mode. */
+ src = dst = NULL;
+ }
+ 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
+ {
+ charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager, ike_sa);
}
- this->lock->unlock(this->lock);
- charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
- }
- else
- {
- charon->ike_sa_manager->checkin_and_destroy(
- charon->ike_sa_manager, ike_sa);
}
peer->destroy(peer);
}
diff --git a/src/libcharon/sa/xauth/xauth_manager.c b/src/libcharon/sa/xauth/xauth_manager.c
new file mode 100644
index 000000000..432c9c0ab
--- /dev/null
+++ b/src/libcharon/sa/xauth/xauth_manager.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 "xauth_manager.h"
+
+#include <utils/linked_list.h>
+#include <threading/rwlock.h>
+
+typedef struct private_xauth_manager_t private_xauth_manager_t;
+typedef struct xauth_entry_t xauth_entry_t;
+
+/**
+ * XAuth constructor entry
+ */
+struct xauth_entry_t {
+
+ /**
+ * Xauth backend name
+ */
+ char *name;
+
+ /**
+ * Role of the method, XAUTH_SERVER or XAUTH_PEER
+ */
+ xauth_role_t role;
+
+ /**
+ * constructor function to create instance
+ */
+ xauth_constructor_t constructor;
+};
+
+/**
+ * private data of xauth_manager
+ */
+struct private_xauth_manager_t {
+
+ /**
+ * public functions
+ */
+ xauth_manager_t public;
+
+ /**
+ * list of eap_entry_t's
+ */
+ linked_list_t *methods;
+
+ /**
+ * rwlock to lock methods
+ */
+ rwlock_t *lock;
+};
+
+METHOD(xauth_manager_t, add_method, void,
+ private_xauth_manager_t *this, char *name, xauth_role_t role,
+ xauth_constructor_t constructor)
+{
+ xauth_entry_t *entry;
+
+ INIT(entry,
+ .name = name,
+ .role = role,
+ .constructor = constructor,
+ );
+
+ this->lock->write_lock(this->lock);
+ this->methods->insert_last(this->methods, entry);
+ this->lock->unlock(this->lock);
+}
+
+METHOD(xauth_manager_t, remove_method, void,
+ private_xauth_manager_t *this, xauth_constructor_t constructor)
+{
+ enumerator_t *enumerator;
+ xauth_entry_t *entry;
+
+ this->lock->write_lock(this->lock);
+ enumerator = this->methods->create_enumerator(this->methods);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (constructor == entry->constructor)
+ {
+ this->methods->remove_at(this->methods, enumerator);
+ free(entry);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+}
+
+METHOD(xauth_manager_t, create_instance, xauth_method_t*,
+ private_xauth_manager_t *this, char *name, xauth_role_t role,
+ identification_t *server, identification_t *peer)
+{
+ enumerator_t *enumerator;
+ xauth_entry_t *entry;
+ xauth_method_t *method = NULL;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->methods->create_enumerator(this->methods);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (role == entry->role &&
+ (!name || streq(name, entry->name)))
+ {
+ method = entry->constructor(server, peer);
+ if (method)
+ {
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+ return method;
+}
+
+METHOD(xauth_manager_t, destroy, void,
+ private_xauth_manager_t *this)
+{
+ this->methods->destroy_function(this->methods, free);
+ this->lock->destroy(this->lock);
+ free(this);
+}
+
+/*
+ * See header
+ */
+xauth_manager_t *xauth_manager_create()
+{
+ private_xauth_manager_t *this;
+
+ INIT(this,
+ .public = {
+ .add_method = _add_method,
+ .remove_method = _remove_method,
+ .create_instance = _create_instance,
+ .destroy = _destroy,
+ },
+ .methods = linked_list_create(),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/sa/xauth/xauth_manager.h b/src/libcharon/sa/xauth/xauth_manager.h
new file mode 100644
index 000000000..929d5de8f
--- /dev/null
+++ b/src/libcharon/sa/xauth/xauth_manager.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 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 xauth_manager xauth_manager
+ * @{ @ingroup xauth
+ */
+
+#ifndef XAUTH_MANAGER_H_
+#define XAUTH_MANAGER_H_
+
+#include <sa/xauth/xauth_method.h>
+
+typedef struct xauth_manager_t xauth_manager_t;
+
+/**
+ * The XAuth manager manages all XAuth implementations and creates instances.
+ *
+ * A plugin registers it's implemented XAuth method at the manager by
+ * providing type and a contructor function. The manager then instanciates
+ * xauth_method_t instances through the provided constructor to handle
+ * XAuth authentication.
+ */
+struct xauth_manager_t {
+
+ /**
+ * Register a XAuth method implementation.
+ *
+ * @param name backend name to register
+ * @param role XAUTH_SERVER or XAUTH_PEER
+ * @param constructor constructor function, returns an xauth_method_t
+ */
+ void (*add_method)(xauth_manager_t *this, char *name,
+ xauth_role_t role, xauth_constructor_t constructor);
+
+ /**
+ * Unregister a XAuth method implementation using it's constructor.
+ *
+ * @param constructor constructor function, as added in add_method
+ */
+ void (*remove_method)(xauth_manager_t *this, xauth_constructor_t constructor);
+
+ /**
+ * Create a new XAuth method instance.
+ *
+ * @param name backend name, as it was registered with
+ * @param role XAUTH_SERVER or XAUTH_PEER
+ * @param server identity of the server
+ * @param peer identity of the peer (client)
+ * @return XAUTH method instance, NULL if no constructor found
+ */
+ xauth_method_t* (*create_instance)(xauth_manager_t *this,
+ char *name, xauth_role_t role,
+ identification_t *server, identification_t *peer);
+
+ /**
+ * Destroy a eap_manager instance.
+ */
+ void (*destroy)(xauth_manager_t *this);
+};
+
+/**
+ * Create a eap_manager instance.
+ */
+xauth_manager_t *xauth_manager_create();
+
+#endif /** XAUTH_MANAGER_H_ @}*/
diff --git a/src/libcharon/sa/xauth/xauth_method.c b/src/libcharon/sa/xauth/xauth_method.c
new file mode 100644
index 000000000..838822d1e
--- /dev/null
+++ b/src/libcharon/sa/xauth/xauth_method.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2006 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "xauth_method.h"
+
+#include <daemon.h>
+
+ENUM(xauth_role_names, XAUTH_SERVER, XAUTH_PEER,
+ "XAUTH_SERVER",
+ "XAUTH_PEER",
+);
+
+/**
+ * See header
+ */
+bool xauth_method_register(plugin_t *plugin, plugin_feature_t *feature,
+ bool reg, void *data)
+{
+ if (reg)
+ {
+ charon->xauth->add_method(charon->xauth, feature->arg.xauth,
+ feature->type == FEATURE_XAUTH_SERVER ? XAUTH_SERVER : XAUTH_PEER,
+ (xauth_constructor_t)data);
+ }
+ else
+ {
+ charon->xauth->remove_method(charon->xauth, (xauth_constructor_t)data);
+ }
+ return TRUE;
+}
diff --git a/src/libcharon/sa/xauth/xauth_method.h b/src/libcharon/sa/xauth/xauth_method.h
new file mode 100644
index 000000000..9f6067dbf
--- /dev/null
+++ b/src/libcharon/sa/xauth/xauth_method.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2006 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup xauth_method xauth_method
+ * @{ @ingroup xauth
+ */
+
+#ifndef XAUTH_METHOD_H_
+#define XAUTH_METHOD_H_
+
+typedef struct xauth_method_t xauth_method_t;
+typedef enum xauth_role_t xauth_role_t;
+
+#include <library.h>
+#include <plugins/plugin.h>
+#include <utils/identification.h>
+#include <encoding/payloads/cp_payload.h>
+
+/**
+ * Role of an xauth_method, SERVER or PEER (client)
+ */
+enum xauth_role_t {
+ XAUTH_SERVER,
+ XAUTH_PEER,
+};
+
+/**
+ * enum names for xauth_role_t.
+ */
+extern enum_name_t *xauth_role_names;
+
+/**
+ * Interface of an XAuth method for server and client side.
+ *
+ * An XAuth method initiates an XAuth exchange and processes requests and
+ * responses. An XAuth method may need multiple exchanges before succeeding.
+ * Sending of XAUTH(STATUS) message is done by the framework, not a method.
+ */
+struct xauth_method_t {
+
+ /**
+ * Initiate the XAuth exchange.
+ *
+ * initiate() is only useable for server implementations, as clients only
+ * reply to server requests.
+ * A cp_payload is created in "out" if result is NEED_MORE.
+ *
+ * @param out cp_payload to send to the client
+ * @return
+ * - NEED_MORE, if an other exchange is required
+ * - FAILED, if unable to create XAuth request payload
+ */
+ status_t (*initiate) (xauth_method_t *this, cp_payload_t **out);
+
+ /**
+ * Process a received XAuth message.
+ *
+ * A cp_payload is created in "out" if result is NEED_MORE.
+ *
+ * @param in cp_payload response received
+ * @param out created cp_payload to send
+ * @return
+ * - NEED_MORE, if an other exchange is required
+ * - FAILED, if XAuth method failed
+ * - SUCCESS, if XAuth method succeeded
+ */
+ status_t (*process) (xauth_method_t *this, cp_payload_t *in,
+ cp_payload_t **out);
+
+ /**
+ * Get the XAuth username received as XAuth initiator.
+ *
+ * @return used XAuth username, pointer to internal data
+ */
+ identification_t* (*get_identity)(xauth_method_t *this);
+
+ /**
+ * Destroys a eap_method_t object.
+ */
+ void (*destroy) (xauth_method_t *this);
+};
+
+/**
+ * Constructor definition for a pluggable XAuth method.
+ *
+ * Each XAuth module must define a constructor function which will return
+ * an initialized object with the methods defined in xauth_method_t.
+ * Constructors for server and peers are identical, to support both roles
+ * of a XAuth method, a plugin needs register two constructors in the
+ * xauth_manager_t.
+ *
+ * @param server ID of the server to use for credential lookup
+ * @param peer ID of the peer to use for credential lookup
+ * @return implementation of the eap_method_t interface
+ */
+typedef xauth_method_t *(*xauth_constructor_t)(identification_t *server,
+ identification_t *peer);
+
+/**
+ * Helper function to (un-)register XAuth methods from plugin features.
+ *
+ * This function is a plugin_feature_callback_t and can be used with the
+ * PLUGIN_CALLBACK macro to register a XAuth method constructor.
+ *
+ * @param plugin plugin registering the XAuth method constructor
+ * @param feature associated plugin feature
+ * @param reg TRUE to register, FALSE to unregister.
+ * @param data data passed to callback, an xauth_constructor_t
+ */
+bool xauth_method_register(plugin_t *plugin, plugin_feature_t *feature,
+ bool reg, void *data);
+
+#endif /** XAUTH_METHOD_H_ @}*/
diff --git a/src/libfast/Makefile.am b/src/libfast/Makefile.am
index 35d102109..df5b650ce 100644
--- a/src/libfast/Makefile.am
+++ b/src/libfast/Makefile.am
@@ -1,7 +1,14 @@
ipseclib_LTLIBRARIES = libfast.la
-libfast_la_SOURCES = context.h dispatcher.c request.h session.h \
- controller.h dispatcher.h request.c session.c filter.h smtp.c smtp.h
+libfast_la_SOURCES = \
+ dispatcher.c request.c session.c smtp.c
+
+if USE_DEV_HEADERS
+fast_includedir = ${dev_headers}/fast
+nobase_fast_include_HEADERS = \
+ context.h controller.h dispatcher.h filter.h request.h session.h smtp.h
+endif
+
libfast_la_LIBADD = $(top_builddir)/src/libstrongswan/libstrongswan.la \
-lfcgi $(clearsilver_LIBS) $(PTHREADLIB)
INCLUDES = -I$(top_srcdir)/src/libstrongswan -I/usr/include/ClearSilver
diff --git a/src/libfast/Makefile.in b/src/libfast/Makefile.in
index abb721758..78341c7e7 100644
--- a/src/libfast/Makefile.in
+++ b/src/libfast/Makefile.in
@@ -15,6 +15,7 @@
@SET_MAKE@
+
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
@@ -35,7 +36,8 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = src/libfast
-DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+DIST_COMMON = $(am__nobase_fast_include_HEADERS_DIST) \
+ $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
$(top_srcdir)/m4/config/ltoptions.m4 \
@@ -49,6 +51,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -72,7 +75,8 @@ am__nobase_list = $(am__nobase_strip_setup); \
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
-am__installdirs = "$(DESTDIR)$(ipseclibdir)"
+am__installdirs = "$(DESTDIR)$(ipseclibdir)" \
+ "$(DESTDIR)$(fast_includedir)"
LTLIBRARIES = $(ipseclib_LTLIBRARIES)
am__DEPENDENCIES_1 =
libfast_la_DEPENDENCIES = \
@@ -80,7 +84,7 @@ libfast_la_DEPENDENCIES = \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
am_libfast_la_OBJECTS = dispatcher.lo request.lo session.lo smtp.lo
libfast_la_OBJECTS = $(am_libfast_la_OBJECTS)
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -95,6 +99,9 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(libfast_la_SOURCES)
DIST_SOURCES = $(libfast_la_SOURCES)
+am__nobase_fast_include_HEADERS_DIST = context.h controller.h \
+ dispatcher.h filter.h request.h session.h smtp.h
+HEADERS = $(nobase_fast_include_HEADERS)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -106,6 +113,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -200,11 +208,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -221,11 +232,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -241,6 +253,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -250,7 +263,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -279,8 +291,12 @@ urandom_device = @urandom_device@
xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
ipseclib_LTLIBRARIES = libfast.la
-libfast_la_SOURCES = context.h dispatcher.c request.h session.h \
- controller.h dispatcher.h request.c session.c filter.h smtp.c smtp.h
+libfast_la_SOURCES = \
+ dispatcher.c request.c session.c smtp.c
+
+@USE_DEV_HEADERS_TRUE@fast_includedir = ${dev_headers}/fast
+@USE_DEV_HEADERS_TRUE@nobase_fast_include_HEADERS = \
+@USE_DEV_HEADERS_TRUE@ context.h controller.h dispatcher.h filter.h request.h session.h smtp.h
libfast_la_LIBADD = $(top_builddir)/src/libstrongswan/libstrongswan.la \
-lfcgi $(clearsilver_LIBS) $(PTHREADLIB)
@@ -392,6 +408,29 @@ mostlyclean-libtool:
clean-libtool:
-rm -rf .libs _libs
+install-nobase_fast_includeHEADERS: $(nobase_fast_include_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(fast_includedir)" || $(MKDIR_P) "$(DESTDIR)$(fast_includedir)"
+ @list='$(nobase_fast_include_HEADERS)'; test -n "$(fast_includedir)" || list=; \
+ $(am__nobase_list) | while read dir files; do \
+ xfiles=; for file in $$files; do \
+ if test -f "$$file"; then xfiles="$$xfiles $$file"; \
+ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \
+ test -z "$$xfiles" || { \
+ test "x$$dir" = x. || { \
+ echo "$(MKDIR_P) '$(DESTDIR)$(fast_includedir)/$$dir'"; \
+ $(MKDIR_P) "$(DESTDIR)$(fast_includedir)/$$dir"; }; \
+ echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(fast_includedir)/$$dir'"; \
+ $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(fast_includedir)/$$dir" || exit $$?; }; \
+ done
+
+uninstall-nobase_fast_includeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(nobase_fast_include_HEADERS)'; test -n "$(fast_includedir)" || list=; \
+ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(fast_includedir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(fast_includedir)" && rm -f $$files
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
@@ -477,9 +516,9 @@ distdir: $(DISTFILES)
done
check-am: all-am
check: check-am
-all-am: Makefile $(LTLIBRARIES)
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
installdirs:
- for dir in "$(DESTDIR)$(ipseclibdir)"; do \
+ for dir in "$(DESTDIR)$(ipseclibdir)" "$(DESTDIR)$(fast_includedir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
@@ -530,7 +569,8 @@ info: info-am
info-am:
-install-data-am: install-ipseclibLTLIBRARIES
+install-data-am: install-ipseclibLTLIBRARIES \
+ install-nobase_fast_includeHEADERS
install-dvi: install-dvi-am
@@ -576,7 +616,8 @@ ps: ps-am
ps-am:
-uninstall-am: uninstall-ipseclibLTLIBRARIES
+uninstall-am: uninstall-ipseclibLTLIBRARIES \
+ uninstall-nobase_fast_includeHEADERS
.MAKE: install-am install-strip
@@ -587,12 +628,14 @@ uninstall-am: uninstall-ipseclibLTLIBRARIES
install install-am install-data install-data-am install-dvi \
install-dvi-am install-exec install-exec-am install-html \
install-html-am install-info install-info-am \
- install-ipseclibLTLIBRARIES install-man install-pdf \
- install-pdf-am install-ps install-ps-am install-strip \
- installcheck installcheck-am installdirs maintainer-clean \
+ install-ipseclibLTLIBRARIES install-man \
+ install-nobase_fast_includeHEADERS 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 uninstall uninstall-am uninstall-ipseclibLTLIBRARIES
+ tags uninstall uninstall-am uninstall-ipseclibLTLIBRARIES \
+ uninstall-nobase_fast_includeHEADERS
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libfast/dispatcher.c b/src/libfast/dispatcher.c
index e5fca7074..63c872e35 100644
--- a/src/libfast/dispatcher.c
+++ b/src/libfast/dispatcher.c
@@ -179,10 +179,16 @@ static session_entry_t *session_entry_create(private_dispatcher_t *this,
char *host)
{
session_entry_t *entry;
+ session_t *session;
+ session = load_session(this);
+ if (!session)
+ {
+ return NULL;
+ }
INIT(entry,
.cond = condvar_create(CONDVAR_TYPE_DEFAULT),
- .session = load_session(this),
+ .session = session,
.host = strdup(host),
.used = time_monotonic(NULL),
);
@@ -324,6 +330,12 @@ static void dispatch(private_dispatcher_t *this)
else
{ /* create a new session if not found */
found = session_entry_create(this, request->get_host(request));
+ if (!found)
+ {
+ request->destroy(request);
+ this->mutex->unlock(this->mutex);
+ continue;
+ }
sid = found->session->get_sid(found->session);
this->sessions->put(this->sessions, sid, found);
}
diff --git a/src/libfast/request.c b/src/libfast/request.c
index 3acd831b2..6ca474037 100644
--- a/src/libfast/request.c
+++ b/src/libfast/request.c
@@ -22,6 +22,11 @@
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
#include <ClearSilver/ClearSilver.h>
#include <threading/thread.h>
@@ -275,6 +280,60 @@ METHOD(request_t, serve, void,
FCGX_PutStr(chunk.ptr, chunk.len, this->req.out);
}
+METHOD(request_t, sendfile, bool,
+ private_request_t *this, char *path, char *mime)
+{
+ struct stat sb;
+ chunk_t data;
+ void *addr;
+ int fd, written;
+ char buf[24];
+
+ fd = open(path, O_RDONLY);
+ if (fd == -1)
+ {
+ return FALSE;
+ }
+ if (fstat(fd, &sb) == -1)
+ {
+ close(fd);
+ return FALSE;
+ }
+ addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (addr == MAP_FAILED)
+ {
+ close(fd);
+ return FALSE;
+ }
+
+ /* FCGX does not like large integers, print to a buffer using libc */
+ snprintf(buf, sizeof(buf), "%lld", (int64_t)sb.st_size);
+ FCGX_FPrintF(this->req.out, "Content-Length: %s\n", buf);
+ if (mime)
+ {
+ FCGX_FPrintF(this->req.out, "Content-Type: %s\n", mime);
+ }
+ FCGX_FPrintF(this->req.out, "\n");
+
+ data = chunk_create(addr, sb.st_size);
+
+ while (data.len)
+ {
+ written = FCGX_PutStr(data.ptr, data.len, this->req.out);
+ if (written == -1)
+ {
+ munmap(addr, sb.st_size);
+ close(fd);
+ return FALSE;
+ }
+ data = chunk_skip(data, written);
+ }
+
+ munmap(addr, sb.st_size);
+ close(fd);
+ return TRUE;
+}
+
METHOD(request_t, render, void,
private_request_t *this, char *template)
{
@@ -380,6 +439,7 @@ request_t *request_create(int fd, bool debug)
.render = _render,
.streamf = _streamf,
.serve = _serve,
+ .sendfile = _sendfile,
.set = _set,
.setf = _setf,
.get_ref = _get_ref,
diff --git a/src/libfast/request.h b/src/libfast/request.h
index c9c1f13e2..63a465bb8 100644
--- a/src/libfast/request.h
+++ b/src/libfast/request.h
@@ -185,6 +185,15 @@ struct request_t {
void (*serve)(request_t *this, char *headers, chunk_t chunk);
/**
+ * Send a file from the file system.
+ *
+ * @param path path to file to serve
+ * @param mime mime type of file to send, or NULL
+ * @return TRUE if file served successfully
+ */
+ bool (*sendfile)(request_t *this, char *path, char *mime);
+
+ /**
* Increase the reference count to the stream.
*
* @return this with increased refcount
diff --git a/src/libfast/session.c b/src/libfast/session.c
index 1d9ed0107..cf14dbeb6 100644
--- a/src/libfast/session.c
+++ b/src/libfast/session.c
@@ -78,20 +78,24 @@ METHOD(session_t, add_filter, void,
/**
* Create a session ID and a cookie
*/
-static void create_sid(private_session_t *this)
+static bool create_sid(private_session_t *this)
{
char buf[COOKIE_LEN];
rng_t *rng;
- memset(buf, 0, sizeof(buf));
- memset(this->sid, 0, sizeof(this->sid));
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
- if (rng)
+ if (!rng)
+ {
+ return FALSE;
+ }
+ if (!rng->get_bytes(rng, sizeof(buf), buf))
{
- rng->get_bytes(rng, sizeof(buf), buf);
rng->destroy(rng);
+ return FALSE;
}
+ rng->destroy(rng);
chunk_to_hex(chunk_create(buf, sizeof(buf)), this->sid, FALSE);
+ return TRUE;
}
/**
@@ -212,7 +216,11 @@ session_t *session_create(context_t *context)
.filters = linked_list_create(),
.context = context,
);
- create_sid(this);
+ if (!create_sid(this))
+ {
+ destroy(this);
+ return NULL;
+ }
return &this->public;
}
diff --git a/src/libfast/session.h b/src/libfast/session.h
index f60fa9ef2..acbab8964 100644
--- a/src/libfast/session.h
+++ b/src/libfast/session.h
@@ -70,6 +70,7 @@ struct session_t {
* Create a session new session.
*
* @param context user defined session context instance
+ * @return client session, NULL on error
*/
session_t *session_create(context_t *context);
diff --git a/src/libfast/smtp.c b/src/libfast/smtp.c
index 4118c74a6..1375c2944 100644
--- a/src/libfast/smtp.c
+++ b/src/libfast/smtp.c
@@ -136,7 +136,13 @@ METHOD(smtp_t, destroy, void,
smtp_t *smtp_create()
{
private_smtp_t *this;
- struct sockaddr_in addr;
+ struct sockaddr_in addr = {
+ .sin_family = AF_INET,
+ .sin_port = htons(25),
+ .sin_addr = {
+ .s_addr = htonl(INADDR_LOOPBACK),
+ },
+ };
int s;
INIT(this,
@@ -153,9 +159,6 @@ smtp_t *smtp_create()
free(this);
return NULL;
}
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- addr.sin_port = htons(25);
if (connect(s, (struct sockaddr*)&addr, sizeof(addr)) < 0)
{
DBG1(DBG_LIB, "connecting to SMTP server failed: %s", strerror(errno));
diff --git a/src/libfreeswan/Android.mk b/src/libfreeswan/Android.mk
deleted file mode 100644
index a834d4846..000000000
--- a/src/libfreeswan/Android.mk
+++ /dev/null
@@ -1,38 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-# copy-n-paste from Makefile.am
-LOCAL_SRC_FILES := \
-addrtoa.c addrtot.c addrtypeof.c anyaddr.c atoaddr.c atoasr.c \
-atosubnet.c atoul.c copyright.c datatot.c freeswan.h \
-goodmask.c initaddr.c initsaid.c initsubnet.c internal.h ipsec_param.h \
-pfkey_v2_build.c pfkey_v2_debug.c \
-pfkey_v2_ext_bits.c pfkey_v2_parse.c portof.c rangetoa.c \
-pfkey.h pfkeyv2.h rangetosubnet.c sameaddr.c \
-satot.c subnetof.c subnettoa.c subnettot.c \
-subnettypeof.c ttoaddr.c ttodata.c ttoprotoport.c ttosa.c ttosubnet.c ttoul.c \
-ultoa.c ultot.c
-
-# build libfreeswan ------------------------------------------------------------
-
-LOCAL_C_INCLUDES += \
- $(libvstr_PATH) \
- $(strongswan_PATH)/src/include \
- $(strongswan_PATH)/src/libstrongswan \
- $(strongswan_PATH)/src/libhydra \
- $(strongswan_PATH)/src/pluto
-
-LOCAL_CFLAGS := $(strongswan_CFLAGS)
-
-LOCAL_MODULE := libfreeswan
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_ARM_MODE := arm
-
-LOCAL_PRELINK_MODULE := false
-
-LOCAL_SHARED_LIBRARIES += libstrongswan
-
-include $(BUILD_SHARED_LIBRARY)
-
diff --git a/src/libfreeswan/Makefile.am b/src/libfreeswan/Makefile.am
deleted file mode 100644
index b38343d34..000000000
--- a/src/libfreeswan/Makefile.am
+++ /dev/null
@@ -1,22 +0,0 @@
-noinst_LIBRARIES = libfreeswan.a
-libfreeswan_a_SOURCES = \
-addrtoa.c addrtot.c addrtypeof.c anyaddr.c atoaddr.c atoasr.c \
-atosubnet.c atoul.c copyright.c datatot.c freeswan.h \
-goodmask.c initaddr.c initsaid.c initsubnet.c internal.h ipsec_param.h \
-pfkey_v2_build.c pfkey_v2_debug.c \
-pfkey_v2_ext_bits.c pfkey_v2_parse.c portof.c rangetoa.c \
-pfkey.h pfkeyv2.h rangetosubnet.c sameaddr.c \
-satot.c subnetof.c subnettoa.c subnettot.c \
-subnettypeof.c ttoaddr.c ttodata.c ttoprotoport.c ttosa.c ttosubnet.c ttoul.c \
-ultoa.c ultot.c
-
-INCLUDES = \
--I$(top_srcdir)/src/libstrongswan \
--I$(top_srcdir)/src/libhydra \
--I$(top_srcdir)/src/pluto
-
-dist_man3_MANS = anyaddr.3 atoaddr.3 atoasr.3 atoul.3 goodmask.3 initaddr.3 initsubnet.3 \
- portof.3 rangetosubnet.3 sameaddr.3 subnetof.3 \
- ttoaddr.3 ttodata.3 ttosa.3 ttoul.3
-
-EXTRA_DIST = Android.mk
diff --git a/src/libfreeswan/addrtoa.c b/src/libfreeswan/addrtoa.c
deleted file mode 100644
index e1c71da3c..000000000
--- a/src/libfreeswan/addrtoa.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * addresses to ASCII
- * Copyright (C) 1998, 1999 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-#include "internal.h"
-#include "freeswan.h"
-
-#define NBYTES 4 /* bytes in an address */
-#define PERBYTE 4 /* three digits plus a dot or NUL */
-#define BUFLEN (NBYTES*PERBYTE)
-
-#if BUFLEN != ADDRTOA_BUF
-#error "ADDRTOA_BUF in freeswan.h inconsistent with addrtoa() code"
-#endif
-
-/*
- - addrtoa - convert binary address to ASCII dotted decimal
- */
-size_t /* space needed for full conversion */
-addrtoa(addr, format, dst, dstlen)
-struct in_addr addr;
-int format; /* character */
-char *dst; /* need not be valid if dstlen is 0 */
-size_t dstlen;
-{
- unsigned long a = ntohl(addr.s_addr);
- int i;
- size_t n;
- unsigned long byte;
- char buf[BUFLEN];
- char *p;
-
- switch (format) {
- case 0:
- break;
- default:
- return 0;
- break;
- }
-
- p = buf;
- for (i = NBYTES-1; i >= 0; i--) {
- byte = (a >> (i*8)) & 0xff;
- p += ultoa(byte, 10, p, PERBYTE);
- if (i != 0)
- *(p-1) = '.';
- }
- n = p - buf;
-
- if (dstlen > 0) {
- if (n > dstlen)
- buf[dstlen - 1] = '\0';
- strcpy(dst, buf);
- }
- return n;
-}
diff --git a/src/libfreeswan/addrtot.c b/src/libfreeswan/addrtot.c
deleted file mode 100644
index d1a338730..000000000
--- a/src/libfreeswan/addrtot.c
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * addresses to text
- * Copyright (C) 2000 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-#include <sys/socket.h>
-
-#include "internal.h"
-#include "freeswan.h"
-
-#define IP4BYTES 4 /* bytes in an IPv4 address */
-#define PERBYTE 4 /* three digits plus a dot or NUL */
-#define IP6BYTES 16 /* bytes in an IPv6 address */
-
-/* forwards */
-static size_t normal4(const unsigned char *s, size_t len, char *b, char **dp);
-static size_t normal6(const unsigned char *s, size_t len, char *b, char **dp, int squish);
-static size_t reverse4(const unsigned char *s, size_t len, char *b, char **dp);
-static size_t reverse6(const unsigned char *s, size_t len, char *b, char **dp);
-
-/*
- - addrtot - convert binary address to text (dotted decimal or IPv6 string)
- */
-size_t /* space needed for full conversion */
-addrtot(src, format, dst, dstlen)
-const ip_address *src;
-int format; /* character */
-char *dst; /* need not be valid if dstlen is 0 */
-size_t dstlen;
-{
- const unsigned char *b;
- size_t n;
- char buf[1+ADDRTOT_BUF+1]; /* :address: */
- char *p;
- int t = addrtypeof(src);
-# define TF(t, f) (((t)<<8) | (f))
-
- n = addrbytesptr(src, &b);
- if (n == 0)
- return 0;
-
- switch (TF(t, format)) {
- case TF(AF_INET, 0):
- n = normal4(b, n, buf, &p);
- break;
- case TF(AF_INET6, 0):
- n = normal6(b, n, buf, &p, 1);
- break;
- case TF(AF_INET, 'Q'):
- n = normal4(b, n, buf, &p);
- break;
- case TF(AF_INET6, 'Q'):
- n = normal6(b, n, buf, &p, 0);
- break;
- case TF(AF_INET, 'r'):
- n = reverse4(b, n, buf, &p);
- break;
- case TF(AF_INET6, 'r'):
- n = reverse6(b, n, buf, &p);
- break;
- default: /* including (AF_INET, 'R') */
- return 0;
- break;
- }
-
- if (dstlen > 0) {
- if (dstlen < n)
- p[dstlen - 1] = '\0';
- strcpy(dst, p);
- }
- return n;
-}
-
-/*
- - normal4 - normal IPv4 address-text conversion
- */
-static size_t /* size of text, including NUL */
-normal4(srcp, srclen, buf, dstp)
-const unsigned char *srcp;
-size_t srclen;
-char *buf; /* guaranteed large enough */
-char **dstp; /* where to put result pointer */
-{
- int i;
- char *p;
-
- if (srclen != IP4BYTES) /* "can't happen" */
- return 0;
- p = buf;
- for (i = 0; i < IP4BYTES; i++) {
- p += ultot(srcp[i], 10, p, PERBYTE);
- if (i != IP4BYTES - 1)
- *(p-1) = '.'; /* overwrites the NUL */
- }
- *dstp = buf;
- return p - buf;
-}
-
-/*
- - normal6 - normal IPv6 address-text conversion
- */
-static size_t /* size of text, including NUL */
-normal6(srcp, srclen, buf, dstp, squish)
-const unsigned char *srcp;
-size_t srclen;
-char *buf; /* guaranteed large enough, plus 2 */
-char **dstp; /* where to put result pointer */
-int squish; /* whether to squish out 0:0 */
-{
- int i;
- unsigned long piece;
- char *p;
- char *q;
-
- if (srclen != IP6BYTES) /* "can't happen" */
- return 0;
- p = buf;
- *p++ = ':';
- for (i = 0; i < IP6BYTES/2; i++) {
- piece = (srcp[2*i] << 8) + srcp[2*i + 1];
- p += ultot(piece, 16, p, 5); /* 5 = abcd + NUL */
- *(p-1) = ':'; /* overwrites the NUL */
- }
- *p = '\0';
- q = strstr(buf, ":0:0:");
- if (squish && q != NULL) { /* zero squishing is possible */
- p = q + 1;
- while (*p == '0' && *(p+1) == ':')
- p += 2;
- q++;
- *q++ = ':'; /* overwrite first 0 */
- while (*p != '\0')
- *q++ = *p++;
- *q = '\0';
- if (!(*(q-1) == ':' && *(q-2) == ':'))
- *--q = '\0'; /* strip final : unless :: */
- p = buf;
- if (!(*p == ':' && *(p+1) == ':'))
- p++; /* skip initial : unless :: */
- } else {
- q = p;
- *--q = '\0'; /* strip final : */
- p = buf + 1; /* skip initial : */
- }
- *dstp = p;
- return q - p + 1;
-}
-
-/*
- - reverse4 - IPv4 reverse-lookup conversion
- */
-static size_t /* size of text, including NUL */
-reverse4(srcp, srclen, buf, dstp)
-const unsigned char *srcp;
-size_t srclen;
-char *buf; /* guaranteed large enough */
-char **dstp; /* where to put result pointer */
-{
- int i;
- char *p;
-
- if (srclen != IP4BYTES) /* "can't happen" */
- return 0;
- p = buf;
- for (i = IP4BYTES-1; i >= 0; i--) {
- p += ultot(srcp[i], 10, p, PERBYTE);
- *(p-1) = '.'; /* overwrites the NUL */
- }
- strcpy(p, "IN-ADDR.ARPA.");
- *dstp = buf;
- return strlen(buf) + 1;
-}
-
-/*
- - reverse6 - IPv6 reverse-lookup conversion (RFC 1886)
- * A trifle inefficient, really shouldn't use ultot...
- */
-static size_t /* size of text, including NUL */
-reverse6(srcp, srclen, buf, dstp)
-const unsigned char *srcp;
-size_t srclen;
-char *buf; /* guaranteed large enough */
-char **dstp; /* where to put result pointer */
-{
- int i;
- unsigned long piece;
- char *p;
-
- if (srclen != IP6BYTES) /* "can't happen" */
- return 0;
- p = buf;
- for (i = IP6BYTES-1; i >= 0; i--) {
- piece = srcp[i];
- p += ultot(piece&0xf, 16, p, 2);
- *(p-1) = '.';
- p += ultot(piece>>4, 16, p, 2);
- *(p-1) = '.';
- }
- strcpy(p, "IP6.ARPA.");
- *dstp = buf;
- return strlen(buf) + 1;
-}
-
-/*
- - reverse6 - modern IPv6 reverse-lookup conversion (RFC 2874)
- * this version removed as it was obsoleted in the end.
- */
-
-#ifdef ADDRTOT_MAIN
-
-#include <stdio.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-void regress(void);
-
-int
-main(int argc, char *argv[])
-{
- if (argc < 2) {
- fprintf(stderr, "Usage: %s {addr|net/mask|begin...end|-r}\n",
- argv[0]);
- exit(2);
- }
-
- if (strcmp(argv[1], "-r") == 0) {
- regress();
- fprintf(stderr, "regress() returned?!?\n");
- exit(1);
- }
- exit(0);
-}
-
-struct rtab {
- char *input;
- char format;
- char *output; /* NULL means error expected */
-} rtab[] = {
- {"1.2.3.0", 0, "1.2.3.0"},
- {"1:2::3:4", 0, "1:2::3:4"},
- {"1:2::3:4", 'Q', "1:2:0:0:0:0:3:4"},
- {"1:2:0:0:3:4:0:0", 0, "1:2::3:4:0:0"},
- {"1.2.3.4", 'r' , "4.3.2.1.IN-ADDR.ARPA."},
- /* 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9 a b c d e f */
- {"1:2::3:4", 'r', "4.0.0.0.3.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.1.0.0.0.IP6.ARPA."},
- {NULL, 0, NULL}
-};
-
-void
-regress()
-{
- struct rtab *r;
- int status = 0;
- ip_address a;
- char in[100];
- char buf[100];
- const char *oops;
- size_t n;
-
- for (r = rtab; r->input != NULL; r++) {
- strcpy(in, r->input);
-
- /* convert it *to* internal format */
- oops = ttoaddr(in, strlen(in), 0, &a);
-
- /* now convert it back */
-
- n = addrtot(&a, r->format, buf, sizeof(buf));
-
- if (n == 0 && r->output == NULL)
- {} /* okay, error expected */
-
- else if (n == 0) {
- printf("`%s' atoasr failed\n", r->input);
- status = 1;
-
- } else if (r->output == NULL) {
- printf("`%s' atoasr succeeded unexpectedly '%c'\n",
- r->input, r->format);
- status = 1;
- } else {
- if (strcasecmp(r->output, buf) != 0) {
- printf("`%s' '%c' gave `%s', expected `%s'\n",
- r->input, r->format, buf, r->output);
- status = 1;
- }
- }
- }
- exit(status);
-}
-
-#endif /* ADDRTOT_MAIN */
diff --git a/src/libfreeswan/addrtypeof.c b/src/libfreeswan/addrtypeof.c
deleted file mode 100644
index ee3cc998f..000000000
--- a/src/libfreeswan/addrtypeof.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * extract parts of an ip_address
- * Copyright (C) 2000 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-#include <sys/socket.h>
-
-#include "internal.h"
-#include "freeswan.h"
-
-/*
- - addrtypeof - get the type of an ip_address
- */
-int
-addrtypeof(src)
-const ip_address *src;
-{
- return src->u.v4.sin_family;
-}
-
-/*
- - addrbytesptr - get pointer to the address bytes of an ip_address
- */
-size_t /* 0 for error */
-addrbytesptr(src, dstp)
-const ip_address *src;
-const unsigned char **dstp; /* NULL means just a size query */
-{
- const unsigned char *p;
- size_t n;
-
- switch (src->u.v4.sin_family) {
- case AF_INET:
- p = (const unsigned char *)&src->u.v4.sin_addr.s_addr;
- n = 4;
- break;
- case AF_INET6:
- p = (const unsigned char *)&src->u.v6.sin6_addr;
- n = 16;
- break;
- default:
- return 0;
- break;
- }
-
- if (dstp != NULL)
- *dstp = p;
- return n;
-}
-
-/*
- - addrlenof - get length of the address bytes of an ip_address
- */
-size_t /* 0 for error */
-addrlenof(src)
-const ip_address *src;
-{
- return addrbytesptr(src, NULL);
-}
-
-/*
- - addrbytesof - get the address bytes of an ip_address
- */
-size_t /* 0 for error */
-addrbytesof(src, dst, dstlen)
-const ip_address *src;
-unsigned char *dst;
-size_t dstlen;
-{
- const unsigned char *p;
- size_t n;
- size_t ncopy;
-
- n = addrbytesptr(src, &p);
- if (n == 0)
- return 0;
-
- if (dstlen > 0) {
- ncopy = n;
- if (ncopy > dstlen)
- ncopy = dstlen;
- memcpy(dst, p, ncopy);
- }
- return n;
-}
diff --git a/src/libfreeswan/anyaddr.3 b/src/libfreeswan/anyaddr.3
deleted file mode 100644
index 58789cf6c..000000000
--- a/src/libfreeswan/anyaddr.3
+++ /dev/null
@@ -1,86 +0,0 @@
-.TH IPSEC_ANYADDR 3 "8 Sept 2000"
-.SH NAME
-ipsec anyaddr \- get "any" address
-.br
-ipsec isanyaddr \- test address for equality to "any" address
-.br
-ipsec unspecaddr \- get "unspecified" address
-.br
-ipsec isunspecaddr \- test address for equality to "unspecified" address
-.br
-ipsec loopbackaddr \- get loopback address
-.br
-ipsec isloopbackaddr \- test address for equality to loopback address
-.SH SYNOPSIS
-.B "#include <freeswan.h>
-.sp
-.B "const char *anyaddr(int af, ip_address *dst);"
-.br
-.B "int isanyaddr(const ip_address *src);"
-.br
-.B "const char *unspecaddr(int af, ip_address *dst);"
-.br
-.B "int isunspecaddr(const ip_address *src);"
-.br
-.B "const char *loopbackaddr(int af, ip_address *dst);"
-.br
-.B "int isloopbackaddr(const ip_address *src);"
-.SH DESCRIPTION
-These functions fill in, and test for, special values of the
-.I ip_address
-type.
-.PP
-.I Anyaddr
-fills in the destination
-.I *dst
-with the ``any'' address of address family
-.IR af
-(normally
-.B AF_INET
-or
-.BR AF_INET6 ).
-The IPv4 ``any'' address is the one embodied in the old
-.B INADDR_ANY
-macro.
-.PP
-.I Isanyaddr
-returns
-.B 1
-if the
-.I src
-address equals the ``any'' address,
-and
-.B 0
-otherwise.
-.PP
-Similarly,
-.I unspecaddr
-supplies, and
-.I isunspecaddr
-tests for,
-the ``unspecified'' address,
-which may be the same as the ``any'' address.
-.PP
-Similarly,
-.I loopbackaddr
-supplies, and
-.I islookbackaddr
-tests for,
-the loopback address.
-.PP
-.IR Anyaddr ,
-.IR unspecaddr ,
-and
-.I loopbackaddr
-return
-.B NULL
-for success and
-a pointer to a string-literal error message for failure;
-see DIAGNOSTICS.
-.SH SEE ALSO
-inet(3), ipsec_addrtot(3), ipsec_sameaddr(3)
-.SH DIAGNOSTICS
-Fatal errors in the address-supplying functions are:
-unknown address family.
-.SH HISTORY
-Written for the FreeS/WAN project by Henry Spencer.
diff --git a/src/libfreeswan/anyaddr.c b/src/libfreeswan/anyaddr.c
deleted file mode 100644
index 5b7691b7b..000000000
--- a/src/libfreeswan/anyaddr.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * special addresses
- * Copyright (C) 2000 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-#include <sys/socket.h>
-
-#include "internal.h"
-#include "freeswan.h"
-
-/* OpenSolaris defines strange versions of these macros */
-#ifdef __sun
-#undef IN6ADDR_ANY_INIT
-#define IN6ADDR_ANY_INIT {{{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }}}
-
-#undef IN6ADDR_LOOPBACK_INIT
-#define IN6ADDR_LOOPBACK_INIT {{{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }}}
-#endif
-
-static struct in6_addr v6any = IN6ADDR_ANY_INIT;
-static struct in6_addr v6loop = IN6ADDR_LOOPBACK_INIT;
-
-/*
- - anyaddr - initialize to the any-address value
- */
-err_t /* NULL for success, else string literal */
-anyaddr(af, dst)
-int af; /* address family */
-ip_address *dst;
-{
- uint32_t v4any = htonl(INADDR_ANY);
-
- switch (af) {
- case AF_INET:
- return initaddr((unsigned char *)&v4any, sizeof(v4any), af, dst);
- break;
- case AF_INET6:
- return initaddr((unsigned char *)&v6any, sizeof(v6any), af, dst);
- break;
- default:
- return "unknown address family in anyaddr/unspecaddr";
- break;
- }
-}
-
-/*
- - unspecaddr - initialize to the unspecified-address value
- */
-err_t /* NULL for success, else string literal */
-unspecaddr(af, dst)
-int af; /* address family */
-ip_address *dst;
-{
- return anyaddr(af, dst);
-}
-
-/*
- - loopbackaddr - initialize to the loopback-address value
- */
-err_t /* NULL for success, else string literal */
-loopbackaddr(af, dst)
-int af; /* address family */
-ip_address *dst;
-{
- uint32_t v4loop = htonl(INADDR_LOOPBACK);
-
- switch (af) {
- case AF_INET:
- return initaddr((unsigned char *)&v4loop, sizeof(v4loop), af, dst);
- break;
- case AF_INET6:
- return initaddr((unsigned char *)&v6loop, sizeof(v6loop), af, dst);
- break;
- default:
- return "unknown address family in loopbackaddr";
- break;
- }
-}
-
-/*
- - isanyaddr - test for the any-address value
- */
-int
-isanyaddr(src)
-const ip_address *src;
-{
- uint32_t v4any = htonl(INADDR_ANY);
- int cmp;
-
- switch (src->u.v4.sin_family) {
- case AF_INET:
- cmp = memcmp(&src->u.v4.sin_addr.s_addr, &v4any, sizeof(v4any));
- break;
- case AF_INET6:
- cmp = memcmp(&src->u.v6.sin6_addr, &v6any, sizeof(v6any));
- break;
- default:
- return 0;
- break;
- }
-
- return (cmp == 0) ? 1 : 0;
-}
-
-/*
- - isunspecaddr - test for the unspecified-address value
- */
-int
-isunspecaddr(src)
-const ip_address *src;
-{
- return isanyaddr(src);
-}
-
-/*
- - isloopbackaddr - test for the loopback-address value
- */
-int
-isloopbackaddr(src)
-const ip_address *src;
-{
- uint32_t v4loop = htonl(INADDR_LOOPBACK);
- int cmp;
-
- switch (src->u.v4.sin_family) {
- case AF_INET:
- cmp = memcmp(&src->u.v4.sin_addr.s_addr, &v4loop, sizeof(v4loop));
- break;
- case AF_INET6:
- cmp = memcmp(&src->u.v6.sin6_addr, &v6loop, sizeof(v6loop));
- break;
- default:
- return 0;
- break;
- }
-
- return (cmp == 0) ? 1 : 0;
-}
diff --git a/src/libfreeswan/atoaddr.3 b/src/libfreeswan/atoaddr.3
deleted file mode 100644
index 10da2691c..000000000
--- a/src/libfreeswan/atoaddr.3
+++ /dev/null
@@ -1,291 +0,0 @@
-.TH IPSEC_ATOADDR 3 "11 June 2001"
-.SH NAME
-ipsec atoaddr, addrtoa \- convert Internet addresses to and from ASCII
-.br
-ipsec atosubnet, subnettoa \- convert subnet/mask ASCII form to and from addresses
-.SH SYNOPSIS
-.B "#include <freeswan.h>
-.sp
-.B "const char *atoaddr(const char *src, size_t srclen,"
-.ti +1c
-.B "struct in_addr *addr);"
-.br
-.B "size_t addrtoa(struct in_addr addr, int format,"
-.ti +1c
-.B "char *dst, size_t dstlen);"
-.sp
-.B "const char *atosubnet(const char *src, size_t srclen,"
-.ti +1c
-.B "struct in_addr *addr, struct in_addr *mask);"
-.br
-.B "size_t subnettoa(struct in_addr addr, struct in_addr mask,"
-.ti +1c
-.B "int format, char *dst, size_t dstlen);"
-.SH DESCRIPTION
-These functions are obsolete; see
-.IR ipsec_ttoaddr (3)
-for their replacements.
-.PP
-.I Atoaddr
-converts an ASCII name or dotted-decimal address into a binary address
-(in network byte order).
-.I Addrtoa
-does the reverse conversion, back to an ASCII dotted-decimal address.
-.I Atosubnet
-and
-.I subnettoa
-do likewise for the ``address/mask'' ASCII form used to write a
-specification of a subnet.
-.PP
-An address is specified in ASCII as a
-dotted-decimal address (e.g.
-.BR 1.2.3.4 ),
-an eight-digit network-order hexadecimal number with the usual C prefix (e.g.
-.BR 0x01020304 ,
-which is synonymous with
-.BR 1.2.3.4 ),
-an eight-digit host-order hexadecimal number with a
-.B 0h
-prefix (e.g.
-.BR 0h01020304 ,
-which is synonymous with
-.B 1.2.3.4
-on a big-endian host and
-.B 4.3.2.1
-on a little-endian host),
-a DNS name to be looked up via
-.IR getaddrinfo (3),
-or an old-style network name to be looked up via
-.IR getnetbyname (3).
-.PP
-A dotted-decimal address may be incomplete, in which case
-ASCII-to-binary conversion implicitly appends
-as many instances of
-.B .0
-as necessary to bring it up to four components.
-The components of a dotted-decimal address are always taken as
-decimal, and leading zeros are ignored.
-For example,
-.B 10
-is synonymous with
-.BR 10.0.0.0 ,
-and
-.B 128.009.000.032
-is synonymous with
-.BR 128.9.0.32
-(the latter example is verbatim from RFC 1166).
-The result of
-.I addrtoa
-is always complete and does not contain leading zeros.
-.PP
-The letters in
-a hexadecimal address may be uppercase or lowercase or any mixture thereof.
-Use of hexadecimal addresses is
-.B strongly
-.BR discouraged ;
-they are included only to save hassles when dealing with
-the handful of perverted programs which already print
-network addresses in hexadecimal.
-.PP
-DNS names may be complete (optionally terminated with a ``.'')
-or incomplete, and are looked up as specified by local system configuration
-(see
-.IR resolver (5)).
-The first value returned by
-.IR getaddrinfo (3)
-is used,
-so with current DNS implementations,
-the result when the name corresponds to more than one address is
-difficult to predict.
-Name lookup resorts to
-.IR getnetbyname (3)
-only if
-.IR getaddrinfo (3)
-fails.
-.PP
-A subnet specification is of the form \fInetwork\fB/\fImask\fR.
-The
-.I network
-and
-.I mask
-can be any form acceptable to
-.IR atoaddr .
-In addition, the
-.I mask
-can be a decimal integer (leading zeros ignored) giving a bit count,
-in which case
-it stands for a mask with that number of high bits on and all others off
-(e.g.,
-.B 24
-means
-.BR 255.255.255.0 ).
-In any case, the mask must be contiguous
-(a sequence of high bits on and all remaining low bits off).
-As a special case, the subnet specification
-.B %default
-is a synonym for
-.BR 0.0.0.0/0 .
-.PP
-.I Atosubnet
-ANDs the mask with the address before returning,
-so that any non-network bits in the address are turned off
-(e.g.,
-.B 10.1.2.3/24
-is synonymous with
-.BR 10.1.2.0/24 ).
-.I Subnettoa
-generates the decimal-integer-bit-count
-form of the mask,
-with no leading zeros,
-unless the mask is non-contiguous.
-.PP
-The
-.I srclen
-parameter of
-.I atoaddr
-and
-.I atosubnet
-specifies the length of the ASCII string pointed to by
-.IR src ;
-it is an error for there to be anything else
-(e.g., a terminating NUL) within that length.
-As a convenience for cases where an entire NUL-terminated string is
-to be converted,
-a
-.I srclen
-value of
-.B 0
-is taken to mean
-.BR strlen(src) .
-.PP
-The
-.I dstlen
-parameter of
-.I addrtoa
-and
-.I subnettoa
-specifies the size of the
-.I dst
-parameter;
-under no circumstances are more than
-.I dstlen
-bytes written to
-.IR dst .
-A result which will not fit is truncated.
-.I Dstlen
-can be zero, in which case
-.I dst
-need not be valid and no result is written,
-but the return value is unaffected;
-in all other cases, the (possibly truncated) result is NUL-terminated.
-The
-.I freeswan.h
-header file defines constants,
-.B ADDRTOA_BUF
-and
-.BR SUBNETTOA_BUF ,
-which are the sizes of buffers just large enough for worst-case results.
-.PP
-The
-.I format
-parameter of
-.I addrtoa
-and
-.I subnettoa
-specifies what format is to be used for the conversion.
-The value
-.B 0
-(not the ASCII character
-.BR '0' ,
-but a zero value)
-specifies a reasonable default,
-and is in fact the only format currently available.
-This parameter is a hedge against future needs.
-.PP
-The ASCII-to-binary functions return NULL for success and
-a pointer to a string-literal error message for failure;
-see DIAGNOSTICS.
-The binary-to-ASCII functions return
-.B 0
-for a failure, and otherwise
-always return the size of buffer which would
-be needed to
-accommodate the full conversion result, including terminating NUL;
-it is the caller's responsibility to check this against the size of
-the provided buffer to determine whether truncation has occurred.
-.SH SEE ALSO
-inet(3)
-.SH DIAGNOSTICS
-Fatal errors in
-.I atoaddr
-are:
-empty input;
-attempt to allocate temporary storage for a very long name failed;
-name lookup failed;
-syntax error in dotted-decimal form;
-dotted-decimal component too large to fit in 8 bits.
-.PP
-Fatal errors in
-.I atosubnet
-are:
-no
-.B /
-in
-.IR src ;
-.I atoaddr
-error in conversion of
-.I network
-or
-.IR mask ;
-bit-count mask too big;
-mask non-contiguous.
-.PP
-Fatal errors in
-.I addrtoa
-and
-.I subnettoa
-are:
-unknown format.
-.SH HISTORY
-Written for the FreeS/WAN project by Henry Spencer.
-.SH BUGS
-The interpretation of incomplete dotted-decimal addresses
-(e.g.
-.B 10/24
-means
-.BR 10.0.0.0/24 )
-differs from that of some older conversion
-functions, e.g. those of
-.IR inet (3).
-The behavior of the older functions has never been
-particularly consistent or particularly useful.
-.PP
-Ignoring leading zeros in dotted-decimal components and bit counts
-is arguably the most useful behavior in this application,
-but it might occasionally cause confusion with the historical use of leading
-zeros to denote octal numbers.
-.PP
-It is barely possible that somebody, somewhere,
-might have a legitimate use for non-contiguous subnet masks.
-.PP
-.IR Getnetbyname (3)
-is a historical dreg.
-.PP
-The restriction of ASCII-to-binary error reports to literal strings
-(so that callers don't need to worry about freeing them or copying them)
-does limit the precision of error reporting.
-.PP
-The ASCII-to-binary error-reporting convention lends itself
-to slightly obscure code,
-because many readers will not think of NULL as signifying success.
-A good way to make it clearer is to write something like:
-.PP
-.RS
-.nf
-.B "const char *error;"
-.sp
-.B "error = atoaddr( /* ... */ );"
-.B "if (error != NULL) {"
-.B " /* something went wrong */"
-.fi
-.RE
diff --git a/src/libfreeswan/atoaddr.c b/src/libfreeswan/atoaddr.c
deleted file mode 100644
index a3643801e..000000000
--- a/src/libfreeswan/atoaddr.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * conversion from ASCII forms of addresses to internal ones
- * Copyright (C) 1998, 1999 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-#include <sys/socket.h>
-
-#include "internal.h"
-#include "freeswan.h"
-
-/*
- * Define NOLEADINGZEROS to interpret 032 as an error, not as 32. There
- * is deliberately no way to interpret it as 26 (i.e., as octal).
- */
-
-/*
- * Legal characters in a domain name. Underscore technically is not,
- * but is a common misunderstanding.
- */
-static const char namechars[] = "abcdefghijklmnopqrstuvwxyz0123456789"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ-_.";
-
-static const char *try8hex(const char *, size_t, struct in_addr *);
-static const char *try8hosthex(const char *, size_t, struct in_addr *);
-static const char *trydotted(const char *, size_t, struct in_addr *);
-static const char *getbyte(const char **, const char *, int *);
-
-/*
- - atoaddr - convert ASCII name or dotted-decimal address to binary address
- */
-const char * /* NULL for success, else string literal */
-atoaddr(src, srclen, addrp)
-const char *src;
-size_t srclen; /* 0 means "apply strlen" */
-struct in_addr *addrp;
-{
- struct addrinfo hints, *res;
- struct netent *ne = NULL;
- const char *oops, *msg = NULL;
-# define HEXLEN 10 /* strlen("0x11223344") */
-# ifndef ATOADDRBUF
-# define ATOADDRBUF 100
-# endif
- char namebuf[ATOADDRBUF];
- char *p = namebuf;
- char *q;
- int error;
-
- if (srclen == 0)
- srclen = strlen(src);
- if (srclen == 0)
- return "empty string";
-
- /* might it be hex? */
- if (srclen == HEXLEN && *src == '0' && CIEQ(*(src+1), 'x'))
- return try8hex(src+2, srclen-2, addrp);
- if (srclen == HEXLEN && *src == '0' && CIEQ(*(src+1), 'h'))
- return try8hosthex(src+2, srclen-2, addrp);
-
- /* try it as dotted decimal */
- oops = trydotted(src, srclen, addrp);
- if (oops == NULL)
- return NULL; /* it worked */
- if (*oops != '?')
- return oops; /* it *was* probably meant as a d.q. */
-
- /* try it as a name -- first, NUL-terminate it */
- if (srclen > sizeof(namebuf)-1) {
- p = (char *) MALLOC(srclen+1);
- if (p == NULL)
- return "unable to allocate temporary space for name";
- }
- p[0] = '\0';
- strncat(p, src, srclen);
-
- /* next, check that it's a vaguely legal name */
- for (q = p; *q != '\0'; q++)
- {
- if (!isprint(*q))
- {
- msg = "unprintable character in name";
- goto error;
- }
- }
- if (strspn(p, namechars) != srclen)
- {
- msg = "illegal (non-DNS-name) character in name";
- goto error;
- }
-
- /* try as host name, failing that as /etc/networks network name */
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_INET;
- error = getaddrinfo(p, NULL, &hints, &res);
- if (error != 0)
- {
- ne = getnetbyname(p);
- if (ne == NULL)
- {
- msg = "name lookup failed";
- goto error;
- }
- addrp->s_addr = htonl(ne->n_net);
- }
- else
- {
- struct sockaddr_in *in = (struct sockaddr_in*)res->ai_addr;
- memcpy(&addrp->s_addr, &in->sin_addr.s_addr, sizeof(addrp->s_addr));
- freeaddrinfo(res);
- }
-
-error:
- if (p != namebuf)
- {
- FREE(p);
- }
-
- return msg;
-}
-
-/*
- - try8hosthex - try conversion as an eight-digit host-order hex number
- */
-const char * /* NULL for success, else string literal */
-try8hosthex(src, srclen, addrp)
-const char *src;
-size_t srclen; /* should be 8 */
-struct in_addr *addrp;
-{
- const char *oops;
- unsigned long addr;
-
- if (srclen != 8)
- return "internal error, try8hex called with bad length";
-
- oops = atoul(src, srclen, 16, &addr);
- if (oops != NULL)
- return oops;
-
- addrp->s_addr = addr;
- return NULL;
-}
-
-/*
- - try8hex - try conversion as an eight-digit network-order hex number
- */
-const char * /* NULL for success, else string literal */
-try8hex(src, srclen, addrp)
-const char *src;
-size_t srclen; /* should be 8 */
-struct in_addr *addrp;
-{
- const char *oops;
-
- oops = try8hosthex(src, srclen, addrp);
- if (oops != NULL)
- return oops;
-
- addrp->s_addr = htonl(addrp->s_addr);
- return NULL;
-}
-
-/*
- - trydotted - try conversion as dotted decimal
- *
- * If the first char of a complaint is '?', that means "didn't look like
- * dotted decimal at all".
- */
-const char * /* NULL for success, else string literal */
-trydotted(src, srclen, addrp)
-const char *src;
-size_t srclen;
-struct in_addr *addrp;
-{
- const char *stop = src + srclen; /* just past end */
- int byte;
- const char *oops;
- unsigned long addr;
- int i;
-# define NBYTES 4
-# define BYTE 8
-
- addr = 0;
- for (i = 0; i < NBYTES && src < stop; i++) {
- oops = getbyte(&src, stop, &byte);
- if (oops != NULL) {
- if (*oops != '?')
- return oops; /* bad number */
- if (i > 1)
- return oops+1; /* failed number */
- return oops; /* with leading '?' */
- }
- addr = (addr << BYTE) | byte;
- if (i < 3 && src < stop && *src++ != '.') {
- if (i == 0)
- return "?syntax error in dotted-decimal address";
- else
- return "syntax error in dotted-decimal address";
- }
- }
- addr <<= (NBYTES - i) * BYTE;
- if (src != stop)
- return "extra garbage on end of dotted-decimal address";
-
- addrp->s_addr = htonl(addr);
- return NULL;
-}
-
-/*
- - getbyte - try to scan a byte in dotted decimal
- * A subtlety here is that all this arithmetic on ASCII digits really is
- * highly portable -- ANSI C guarantees that digits 0-9 are contiguous.
- * It's easier to just do it ourselves than set up for a call to atoul().
- *
- * If the first char of a complaint is '?', that means "didn't look like a
- * number at all".
- */
-const char * /* NULL for success, else string literal */
-getbyte(srcp, stop, retp)
-const char **srcp; /* *srcp is updated */
-const char *stop; /* first untouchable char */
-int *retp; /* return-value pointer */
-{
- char c;
- const char *p;
- int no;
-
- if (*srcp >= stop)
- return "?empty number in dotted-decimal address";
-
- if (stop - *srcp >= 3 && **srcp == '0' && CIEQ(*(*srcp+1), 'x'))
- return "hex numbers not supported in dotted-decimal addresses";
-#ifdef NOLEADINGZEROS
- if (stop - *srcp >= 2 && **srcp == '0' && isdigit(*(*srcp+1)))
- return "octal numbers not supported in dotted-decimal addresses";
-#endif /* NOLEADINGZEROS */
-
- /* must be decimal, if it's numeric at all */
- no = 0;
- p = *srcp;
- while (p < stop && no <= 255 && (c = *p) >= '0' && c <= '9') {
- no = no*10 + (c - '0');
- p++;
- }
- if (p == *srcp)
- return "?non-numeric component in dotted-decimal address";
- *srcp = p;
- if (no > 255)
- return "byte overflow in dotted-decimal address";
- *retp = no;
- return NULL;
-}
diff --git a/src/libfreeswan/atoasr.3 b/src/libfreeswan/atoasr.3
deleted file mode 100644
index 0b9a5fea3..000000000
--- a/src/libfreeswan/atoasr.3
+++ /dev/null
@@ -1,185 +0,0 @@
-.TH IPSEC_ATOASR 3 "11 June 2001"
-.SH NAME
-ipsec atoasr \- convert ASCII to Internet address, subnet, or range
-.br
-ipsec rangetoa \- convert Internet address range to ASCII
-.SH SYNOPSIS
-.B "#include <freeswan.h>
-.sp
-.B "const char *atoasr(const char *src, size_t srclen,"
-.ti +1c
-.B "char *type, struct in_addr *addrs);"
-.br
-.B "size_t rangetoa(struct in_addr *addrs, int format,
-.ti +1c
-.B "char *dst, size_t dstlen);"
-.SH DESCRIPTION
-These functions are obsolete;
-there is no current equivalent,
-because so far they have not proved useful.
-.PP
-.I Atoasr
-converts an ASCII address, subnet, or address range
-into a suitable combination of binary addresses
-(in network byte order).
-.I Rangetoa
-converts an address range back into ASCII,
-using dotted-decimal form for the addresses
-(the other reverse conversions are handled by
-.IR ipsec_addrtoa (3)
-and
-.IR ipsec_subnettoa (3)).
-.PP
-A single address can be any form acceptable to
-.IR ipsec_atoaddr (3):
-dotted decimal, DNS name, or hexadecimal number.
-A subnet
-specification uses the form \fInetwork\fB/\fImask\fR
-interpreted by
-.IR ipsec_atosubnet (3).
-.PP
-An address range is two
-.IR ipsec_atoaddr (3)
-addresses separated by a
-.B ...
-delimiter.
-If there are four dots rather than three, the first is taken as
-part of the begin address,
-e.g. for a complete DNS name which ends with
-.B .
-to suppress completion attempts.
-The begin address of a range must be
-less than or equal to the end address.
-.PP
-The
-.I srclen
-parameter of
-.I atoasr
-specifies the length of the ASCII string pointed to by
-.IR src ;
-it is an error for there to be anything else
-(e.g., a terminating NUL) within that length.
-As a convenience for cases where an entire NUL-terminated string is
-to be converted,
-a
-.I srclen
-value of
-.B 0
-is taken to mean
-.BR strlen(src) .
-.PP
-The
-.I type
-parameter of
-.I atoasr
-must point to a
-.B char
-variable used to record which form was found.
-The
-.I addrs
-parameter must point to a two-element array of
-.B "struct in_addr"
-which receives the results.
-The values stored into
-.BR *type ,
-and the corresponding values in the array, are:
-.PP
-.ta 3c +2c +3c
- *type addrs[0] addrs[1]
-.sp 0.8
-address \&\fB'a'\fR address -
-.br
-subnet \&\fB's'\fR network mask
-.br
-range \&\fB'r'\fR begin end
-.PP
-The
-.I dstlen
-parameter of
-.I rangetoa
-specifies the size of the
-.I dst
-parameter;
-under no circumstances are more than
-.I dstlen
-bytes written to
-.IR dst .
-A result which will not fit is truncated.
-.I Dstlen
-can be zero, in which case
-.I dst
-need not be valid and no result is written,
-but the return value is unaffected;
-in all other cases, the (possibly truncated) result is NUL-terminated.
-The
-.I freeswan.h
-header file defines a constant,
-.BR RANGETOA_BUF ,
-which is the size of a buffer just large enough for worst-case results.
-.PP
-The
-.I format
-parameter of
-.I rangetoa
-specifies what format is to be used for the conversion.
-The value
-.B 0
-(not the ASCII character
-.BR '0' ,
-but a zero value)
-specifies a reasonable default,
-and is in fact the only format currently available.
-This parameter is a hedge against future needs.
-.PP
-.I Atoasr
-returns NULL for success and
-a pointer to a string-literal error message for failure;
-see DIAGNOSTICS.
-.I Rangetoa
-returns
-.B 0
-for a failure, and otherwise
-always returns the size of buffer which would
-be needed to
-accommodate the full conversion result, including terminating NUL;
-it is the caller's responsibility to check this against the size of
-the provided buffer to determine whether truncation has occurred.
-.SH SEE ALSO
-ipsec_atoaddr(3), ipsec_atosubnet(3)
-.SH DIAGNOSTICS
-Fatal errors in
-.I atoasr
-are:
-empty input;
-error in
-.IR ipsec_atoaddr (3)
-or
-.IR ipsec_atosubnet (3)
-during conversion;
-begin address of range exceeds end address.
-.PP
-Fatal errors in
-.I rangetoa
-are:
-unknown format.
-.SH HISTORY
-Written for the FreeS/WAN project by Henry Spencer.
-.SH BUGS
-The restriction of error reports to literal strings
-(so that callers don't need to worry about freeing them or copying them)
-does limit the precision of error reporting.
-.PP
-The error-reporting convention lends itself
-to slightly obscure code,
-because many readers will not think of NULL as signifying success.
-A good way to make it clearer is to write something like:
-.PP
-.RS
-.nf
-.B "const char *error;"
-.sp
-.B "error = atoasr( /* ... */ );"
-.B "if (error != NULL) {"
-.B " /* something went wrong */"
-.fi
-.RE
diff --git a/src/libfreeswan/atoasr.c b/src/libfreeswan/atoasr.c
deleted file mode 100644
index ad62ef46b..000000000
--- a/src/libfreeswan/atoasr.c
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * convert from ASCII form of address/subnet/range to binary
- * Copyright (C) 1998, 1999 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-#include "internal.h"
-#include "freeswan.h"
-
-/*
- - atoasr - convert ASCII to address, subnet, or range
- */
-const char * /* NULL for success, else string literal */
-atoasr(src, srclen, typep, addrsp)
-const char *src;
-size_t srclen; /* 0 means "apply strlen" */
-char *typep; /* return type code: 'a', 's', 'r' */
-struct in_addr addrsp[2];
-{
- const char *punct;
- const char *stop;
- const char *oops;
-
- if (srclen == 0)
- srclen = strlen(src);
- if (srclen == 0)
- return "empty string";
-
- /* subnet is easy to spot */
- punct = memchr(src, '/', srclen);
- if (punct != NULL) {
- *typep = 's';
- return atosubnet(src, srclen, &addrsp[0], &addrsp[1]);
- }
-
- /* try for a range */
- stop = src + srclen;
- for (punct = src; (punct = memchr(punct, '.', stop - punct)) != NULL;
- punct++)
- if (stop - punct > 3 && *(punct+1) == '.' && *(punct+2) == '.')
- break; /* NOTE BREAK OUT */
- if (punct == NULL) {
- /* didn't find the range delimiter, must be plain address */
- *typep = 'a';
- return atoaddr(src, srclen, &addrsp[0]);
- }
-
- /* looks like a range */
- *typep = 'r';
- if (stop - punct > 4 && *(punct+3) == '.')
- punct++; /* first dot is trailing dot of name */
- oops = atoaddr(src, punct - src, &addrsp[0]);
- if (oops != NULL)
- return oops;
- oops = atoaddr(punct+3, stop - (punct+3), &addrsp[1]);
- if (oops != NULL)
- return oops;
- if (ntohl(addrsp[0].s_addr) > ntohl(addrsp[1].s_addr))
- return "invalid range, begin > end";
- return NULL;
-}
-
-
-
-#ifdef ATOASR_MAIN
-
-#include <stdio.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-void regress(void);
-
-int
-main(int argc, char *argv[])
-{
- struct in_addr a[2];
- char buf[100];
- const char *oops;
- size_t n;
- char type;
-
- if (argc < 2) {
- fprintf(stderr, "Usage: %s {addr|net/mask|begin...end|-r}\n",
- argv[0]);
- exit(2);
- }
-
- if (strcmp(argv[1], "-r") == 0) {
- regress();
- fprintf(stderr, "regress() returned?!?\n");
- exit(1);
- }
-
- oops = atoasr(argv[1], 0, &type, a);
- if (oops != NULL) {
- fprintf(stderr, "%s: conversion failed: %s\n", argv[0], oops);
- exit(1);
- }
- switch (type) {
- case 'a':
- n = addrtoa(a[0], 0, buf, sizeof(buf));
- break;
- case 's':
- n = subnettoa(a[0], a[1], 0, buf, sizeof(buf));
- break;
- case 'r':
- n = rangetoa(a, 0, buf, sizeof(buf));
- break;
- default:
- fprintf(stderr, "%s: unknown type '%c'\n", argv[0], type);
- exit(1);
- break;
- }
- if (n > sizeof(buf)) {
- fprintf(stderr, "%s: reverse conversion of ", argv[0]);
- fprintf(stderr, "%s ", inet_ntoa(a[0]));
- fprintf(stderr, "%s", inet_ntoa(a[1]));
- fprintf(stderr, " failed: need %ld bytes, have only %ld\n",
- (long)n, (long)sizeof(buf));
- exit(1);
- }
- printf("%s\n", buf);
-
- exit(0);
-}
-
-struct rtab {
- char *input;
- char *output; /* NULL means error expected */
-} rtab[] = {
- {"1.2.3.0", "1.2.3.0"},
- {"1.2.3.0/255.255.255.0", "1.2.3.0/24"},
- {"1.2.3.0...1.2.3.5", "1.2.3.0...1.2.3.5"},
- {"1.2.3.4.5", NULL},
- {"1.2.3.4/", NULL},
- {"1.2.3.4...", NULL},
- {"1.2.3.4....", NULL},
- {"localhost/32", "127.0.0.1/32"},
- {"localhost...127.0.0.3", "127.0.0.1...127.0.0.3"},
- {"127.0.0.0...localhost", "127.0.0.0...127.0.0.1"},
- {"127.0.0.3...localhost", NULL},
- {NULL, NULL}
-};
-
-void
-regress(void)
-{
- struct rtab *r;
- int status = 0;
- struct in_addr a[2];
- char in[100];
- char buf[100];
- const char *oops;
- size_t n;
- char type;
-
- for (r = rtab; r->input != NULL; r++) {
- strcpy(in, r->input);
- oops = atoasr(in, 0, &type, a);
- if (oops != NULL && r->output == NULL)
- {} /* okay, error expected */
- else if (oops != NULL) {
- printf("`%s' atoasr failed: %s\n", r->input, oops);
- status = 1;
- } else if (r->output == NULL) {
- printf("`%s' atoasr succeeded unexpectedly '%c'\n",
- r->input, type);
- status = 1;
- } else {
- switch (type) {
- case 'a':
- n = addrtoa(a[0], 0, buf, sizeof(buf));
- break;
- case 's':
- n = subnettoa(a[0], a[1], 0, buf, sizeof(buf));
- break;
- case 'r':
- n = rangetoa(a, 0, buf, sizeof(buf));
- break;
- default:
- fprintf(stderr, "`%s' unknown type '%c'\n",
- r->input, type);
- n = 0;
- status = 1;
- break;
- }
- if (n > sizeof(buf)) {
- printf("`%s' '%c' reverse failed: need %ld\n",
- r->input, type, (long)n);
- status = 1;
- } else if (n > 0 && strcmp(r->output, buf) != 0) {
- printf("`%s' '%c' gave `%s', expected `%s'\n",
- r->input, type, buf, r->output);
- status = 1;
- }
- }
- }
- exit(status);
-}
-
-#endif /* ATOASR_MAIN */
diff --git a/src/libfreeswan/atosubnet.c b/src/libfreeswan/atosubnet.c
deleted file mode 100644
index 8b2bfa17e..000000000
--- a/src/libfreeswan/atosubnet.c
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * convert from ASCII form of subnet specification to binary
- * Copyright (C) 1998, 1999 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-#include "internal.h"
-#include "freeswan.h"
-
-#ifndef DEFAULTSUBNET
-#define DEFAULTSUBNET "%default"
-#endif
-
-/*
- - atosubnet - convert ASCII "addr/mask" to address and mask
- * Mask can be integer bit count.
- */
-const char * /* NULL for success, else string literal */
-atosubnet(src, srclen, addrp, maskp)
-const char *src;
-size_t srclen; /* 0 means "apply strlen" */
-struct in_addr *addrp;
-struct in_addr *maskp;
-{
- const char *slash;
- const char *mask;
- size_t mlen;
- const char *oops;
- unsigned long bc;
- static char def[] = DEFAULTSUBNET;
-# define DEFLEN (sizeof(def) - 1) /* -1 for NUL */
- static char defis[] = "0/0";
-# define DEFILEN (sizeof(defis) - 1)
-
- if (srclen == 0)
- srclen = strlen(src);
- if (srclen == 0)
- return "empty string";
-
- if (srclen == DEFLEN && strncmp(src, def, srclen) == 0) {
- src = defis;
- srclen = DEFILEN;
- }
-
- slash = memchr(src, '/', srclen);
- if (slash == NULL)
- return "no / in subnet specification";
- mask = slash + 1;
- mlen = srclen - (mask - src);
-
- oops = atoaddr(src, slash-src, addrp);
- if (oops != NULL)
- return oops;
-
- oops = atoul(mask, mlen, 10, &bc);
- if (oops == NULL) {
- /* atoul succeeded, it's a bit-count mask */
- if (bc > ABITS)
- return "bit-count mask too large";
-#ifdef NOLEADINGZEROS
- if (mlen > 1 && *mask == '0')
- return "octal not allowed in mask";
-#endif /* NOLEADINGZEROS */
- *maskp = bitstomask((int)bc);
- } else {
- oops = atoaddr(mask, mlen, maskp);
- if (oops != NULL)
- return oops;
- if (!goodmask(*maskp))
- return "non-contiguous mask";
- }
-
- addrp->s_addr &= maskp->s_addr;
- return NULL;
-}
-
-
-
-#ifdef ATOSUBNET_MAIN
-
-#include <stdio.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-void regress(void);
-
-int
-main(int argc, char *argv[])
-{
- struct in_addr a;
- struct in_addr m;
- char buf[100];
- const char *oops;
- size_t n;
-
- if (argc < 2) {
- fprintf(stderr, "Usage: %s {addr/mask|-r}\n", argv[0]);
- exit(2);
- }
-
- if (strcmp(argv[1], "-r") == 0) {
- regress();
- fprintf(stderr, "regress() returned?!?\n");
- exit(1);
- }
-
- oops = atosubnet(argv[1], 0, &a, &m);
- if (oops != NULL) {
- fprintf(stderr, "%s: conversion failed: %s\n", argv[0], oops);
- exit(1);
- }
- n = subnettoa(a, m, 0, buf, sizeof(buf));
- if (n > sizeof(buf)) {
- fprintf(stderr, "%s: reverse conversion of ", argv[0]);
- fprintf(stderr, "%s/", inet_ntoa(a));
- fprintf(stderr, "%s", inet_ntoa(m));
- fprintf(stderr, " failed: need %ld bytes, have only %ld\n",
- (long)n, (long)sizeof(buf));
- exit(1);
- }
- printf("%s\n", buf);
-
- exit(0);
-}
-
-struct rtab {
- char *input;
- char *output; /* NULL means error expected */
-} rtab[] = {
- {"1.2.3.0/255.255.255.0", "1.2.3.0/24"},
- {"1.2.3.0/24", "1.2.3.0/24"},
- {"1.2.3.1/255.255.255.240", "1.2.3.0/28"},
- {"1.2.3.1/32", "1.2.3.1/32"},
- {"1.2.3.1/0", "0.0.0.0/0"},
-/* "1.2.3.1/255.255.127.0", "1.2.3.0/255.255.127.0", */
- {"1.2.3.1/255.255.127.0", NULL},
- {"128.009.000.032/32", "128.9.0.32/32"},
- {"128.0x9.0.32/32", NULL},
- {"0x80090020/32", "128.9.0.32/32"},
- {"0x800x0020/32", NULL},
- {"128.9.0.32/0xffFF0000", "128.9.0.0/16"},
- {"128.9.0.32/0xff0000FF", NULL},
- {"128.9.0.32/0x0000ffFF", NULL},
- {"128.9.0.32/0x00ffFF0000", NULL},
- {"128.9.0.32/0xffFF", NULL},
- {"128.9.0.32.27/32", NULL},
- {"128.9.0k32/32", NULL},
- {"328.9.0.32/32", NULL},
- {"128.9..32/32", NULL},
- {"10/8", "10.0.0.0/8"},
- {"10.0/8", "10.0.0.0/8"},
- {"10.0.0/8", "10.0.0.0/8"},
- {"10.0.1/24", "10.0.1.0/24"},
- {"_", NULL},
- {"_/_", NULL},
- {"1.2.3.1", NULL},
- {"1.2.3.1/_", NULL},
- {"1.2.3.1/24._", NULL},
- {"1.2.3.1/99", NULL},
- {"localhost/32", "127.0.0.1/32"},
- {"%default", "0.0.0.0/0"},
- {NULL, NULL}
-};
-
-void
-regress()
-{
- struct rtab *r;
- int status = 0;
- struct in_addr a;
- struct in_addr m;
- char in[100];
- char buf[100];
- const char *oops;
- size_t n;
-
- for (r = rtab; r->input != NULL; r++) {
- strcpy(in, r->input);
- oops = atosubnet(in, 0, &a, &m);
- if (oops != NULL && r->output == NULL)
- {} /* okay, error expected */
- else if (oops != NULL) {
- printf("`%s' atosubnet failed: %s\n", r->input, oops);
- status = 1;
- } else if (r->output == NULL) {
- printf("`%s' atosubnet succeeded unexpectedly\n",
- r->input);
- status = 1;
- } else {
- n = subnettoa(a, m, 0, buf, sizeof(buf));
- if (n > sizeof(buf)) {
- printf("`%s' subnettoa failed: need %ld\n",
- r->input, (long)n);
- status = 1;
- } else if (strcmp(r->output, buf) != 0) {
- printf("`%s' gave `%s', expected `%s'\n",
- r->input, buf, r->output);
- status = 1;
- }
- }
- }
- exit(status);
-}
-
-#endif /* ATOSUBNET_MAIN */
diff --git a/src/libfreeswan/atoul.3 b/src/libfreeswan/atoul.3
deleted file mode 100644
index 6737b6b54..000000000
--- a/src/libfreeswan/atoul.3
+++ /dev/null
@@ -1,160 +0,0 @@
-.TH IPSEC_ATOUL 3 "11 June 2001"
-.SH NAME
-ipsec atoul, ultoa \- convert unsigned-long numbers to and from ASCII
-.SH SYNOPSIS
-.B "#include <freeswan.h>
-.sp
-.B "const char *atoul(const char *src, size_t srclen,"
-.ti +1c
-.B "int base, unsigned long *n);"
-.br
-.B "size_t ultoa(unsigned long n, int base, char *dst,"
-.ti +1c
-.B "size_t dstlen);"
-.SH DESCRIPTION
-These functions are obsolete; see
-.IR ipsec_ttoul (3)
-for their replacements.
-.PP
-.I Atoul
-converts an ASCII number into a binary
-.B "unsigned long"
-value.
-.I Ultoa
-does the reverse conversion, back to an ASCII version.
-.PP
-Numbers are specified in ASCII as
-decimal (e.g.
-.BR 123 ),
-octal with a leading zero (e.g.
-.BR 012 ,
-which has value 10),
-or hexadecimal with a leading
-.B 0x
-(e.g.
-.BR 0x1f ,
-which has value 31)
-in either upper or lower case.
-.PP
-The
-.I srclen
-parameter of
-.I atoul
-specifies the length of the ASCII string pointed to by
-.IR src ;
-it is an error for there to be anything else
-(e.g., a terminating NUL) within that length.
-As a convenience for cases where an entire NUL-terminated string is
-to be converted,
-a
-.I srclen
-value of
-.B 0
-is taken to mean
-.BR strlen(src) .
-.PP
-The
-.I base
-parameter of
-.I atoul
-can be
-.BR 8 ,
-.BR 10 ,
-or
-.BR 16 ,
-in which case the number supplied is assumed to be of that form
-(and in the case of
-.BR 16 ,
-to lack any
-.B 0x
-prefix).
-It can also be
-.BR 0 ,
-in which case the number is examined for a leading zero
-or a leading
-.B 0x
-to determine its base,
-or
-.B 13
-(halfway between 10 and 16),
-which has the same effect as
-.B 0
-except that a non-hexadecimal
-number is considered decimal regardless of any leading zero.
-.PP
-The
-.I dstlen
-parameter of
-.I ultoa
-specifies the size of the
-.I dst
-parameter;
-under no circumstances are more than
-.I dstlen
-bytes written to
-.IR dst .
-A result which will not fit is truncated.
-.I Dstlen
-can be zero, in which case
-.I dst
-need not be valid and no result is written,
-but the return value is unaffected;
-in all other cases, the (possibly truncated) result is NUL-terminated.
-.PP
-The
-.I base
-parameter of
-.I ultoa
-must be
-.BR 8 ,
-.BR 10 ,
-or
-.BR 16 .
-.PP
-.I Atoul
-returns NULL for success and
-a pointer to a string-literal error message for failure;
-see DIAGNOSTICS.
-.I Ultoa
-returns the size of buffer which would
-be needed to
-accommodate the full conversion result, including terminating NUL;
-it is the caller's responsibility to check this against the size of
-the provided buffer to determine whether truncation has occurred.
-.SH SEE ALSO
-atol(3), strtoul(3)
-.SH DIAGNOSTICS
-Fatal errors in
-.I atoul
-are:
-empty input;
-unknown
-.IR base ;
-non-digit character found;
-number too large for an
-.BR "unsigned long" .
-.SH HISTORY
-Written for the FreeS/WAN project by Henry Spencer.
-.SH BUGS
-There is no provision for reporting an invalid
-.I base
-parameter given to
-.IR ultoa .
-.PP
-The restriction of error reports to literal strings
-(so that callers don't need to worry about freeing them or copying them)
-does limit the precision of error reporting.
-.PP
-The error-reporting convention lends itself to slightly obscure code,
-because many readers will not think of NULL as signifying success.
-A good way to make it clearer is to write something like:
-.PP
-.RS
-.nf
-.B "const char *error;"
-.sp
-.B "error = atoul( /* ... */ );"
-.B "if (error != NULL) {"
-.B " /* something went wrong */"
-.fi
-.RE
diff --git a/src/libfreeswan/atoul.c b/src/libfreeswan/atoul.c
deleted file mode 100644
index d8e1528cb..000000000
--- a/src/libfreeswan/atoul.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * convert from ASCII form of unsigned long to binary
- * Copyright (C) 1998, 1999 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-#include "internal.h"
-#include "freeswan.h"
-
-/*
- - atoul - convert ASCII substring to unsigned long number
- */
-const char * /* NULL for success, else string literal */
-atoul(src, srclen, base, resultp)
-const char *src;
-size_t srclen; /* 0 means strlen(src) */
-int base; /* 0 means figure it out */
-unsigned long *resultp;
-{
- const char *stop;
- static char hex[] = "0123456789abcdef";
- static char uchex[] = "0123456789ABCDEF";
- int d;
- char c;
- char *p;
- unsigned long r;
- unsigned long rlimit;
- int dlimit;
-
- if (srclen == 0)
- srclen = strlen(src);
- if (srclen == 0)
- return "empty string";
-
- if (base == 0 || base == 13) {
- if (srclen > 2 && *src == '0' && CIEQ(*(src+1), 'x'))
- return atoul(src+2, srclen-2, 16, resultp);
- if (srclen > 1 && *src == '0' && base != 13)
- return atoul(src+1, srclen-1, 8, resultp);
- return atoul(src, srclen, 10, resultp);
- }
- if (base != 8 && base != 10 && base != 16)
- return "unsupported number base";
-
- r = 0;
- stop = src + srclen;
- if (base == 16) {
- while (src < stop) {
- c = *src++;
- p = strchr(hex, c);
- if (p != NULL)
- d = p - hex;
- else {
- p = strchr(uchex, c);
- if (p == NULL)
- return "non-hex-digit in hex number";
- d = p - uchex;
- }
- r = (r << 4) | d;
- }
- /* defer length check to catch invalid digits first */
- if (srclen > sizeof(unsigned long) * 2)
- return "hex number too long";
- } else {
- rlimit = ULONG_MAX / base;
- dlimit = (int)(ULONG_MAX - rlimit*base);
- while (src < stop) {
- c = *src++;
- d = c - '0';
- if (d < 0 || d >= base)
- return "non-digit in number";
- if (r > rlimit || (r == rlimit && d > dlimit))
- return "unsigned-long overflow";
- r = r*base + d;
- }
- }
-
- *resultp = r;
- return NULL;
-}
diff --git a/src/libfreeswan/copyright.c b/src/libfreeswan/copyright.c
deleted file mode 100644
index e55e849f7..000000000
--- a/src/libfreeswan/copyright.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * return IPsec copyright notice
- * Copyright (C) 2001, 2002 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-#include "internal.h"
-#include "freeswan.h"
-
-static const char *co[] = {
- "Copyright (C) 1999-2009 Henry Spencer, Richard Guy Briggs,",
- " D. Hugh Redelmeier, Sandy Harris, Claudia Schmeing,",
- " Michael Richardson, Angelos D. Keromytis, John Ioannidis,",
- "",
- " Ken Bantoft, Stephen J. Bevan, JuanJo Ciarlante, Mathieu Lafon,",
- " Stephane Laroche, Kai Martius, Stephan Scholz, Tuomo Soini, Herbert Xu,",
- "",
- " Martin Berner, Marco Bertossa, David Buechi, Ueli Galizzi,",
- " Christoph Gysin, Andreas Hess, Patric Lichtsteiner, Michael Meier,",
- " Andreas Schleiss, Ariane Seiler, Mario Strasser, Lukas Suter,",
- " Roger Wegmann, Simon Zwahlen,",
- " ZHW Zuercher Hochschule Winterthur (Switzerland).",
- "",
- " Philip Boetschi, Tobias Brunner, Sansar Choinyambuu, Adrian Doerig,",
- " Andreas Eigenmann, Fabian Hartmann, Noah Heusser, Jan Hutter,",
- " Thomas Kallenberg, Daniel Roethlisberger, Joel Stillhart, Martin Willi,",
- " Daniel Wydler, Andreas Steffen,",
- " HSR Hochschule fuer Technik Rapperswil (Switzerland).",
- "",
- "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 (file COPYING in the distribution) for more details.",
- NULL
-};
-
-/*
- - ipsec_copyright_notice - return copyright notice, as a vector of strings
- */
-const char **
-ipsec_copyright_notice()
-{
- return co;
-}
diff --git a/src/libfreeswan/datatot.c b/src/libfreeswan/datatot.c
deleted file mode 100644
index e3b9d6417..000000000
--- a/src/libfreeswan/datatot.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * convert from binary data (e.g. key) to text form
- * Copyright (C) 2000 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-#include "internal.h"
-#include "freeswan.h"
-
-static void convert(const char *src, size_t nreal, int format, char *out);
-
-/*
- - datatot - convert data bytes to text
- */
-size_t /* true length (with NUL) for success */
-datatot(src, srclen, format, dst, dstlen)
-const char *src;
-size_t srclen;
-int format; /* character indicating what format */
-char *dst; /* need not be valid if dstlen is 0 */
-size_t dstlen;
-{
- size_t inblocksize; /* process this many bytes at a time */
- size_t outblocksize; /* producing this many */
- size_t breakevery; /* add a _ every this many (0 means don't) */
- size_t sincebreak; /* output bytes since last _ */
- char breakchar; /* character used to break between groups */
- char inblock[10]; /* enough for any format */
- char outblock[10]; /* enough for any format */
- char fake[1]; /* fake output area for dstlen == 0 */
- size_t needed; /* return value */
- char *stop; /* where the terminating NUL will go */
- size_t ntodo; /* remaining input */
- size_t nreal;
- char *out;
- char *prefix;
-
- breakevery = 0;
- breakchar = '_';
-
- switch (format) {
- case 0:
- case 'h':
- format = 'x';
- breakevery = 8;
- /* FALLTHROUGH */
- case 'x':
- inblocksize = 1;
- outblocksize = 2;
- prefix = "0x";
- break;
- case ':':
- breakevery = 2;
- breakchar = ':';
- /* FALLTHROUGH */
- case 16:
- inblocksize = 1;
- outblocksize = 2;
- prefix = "";
- format = 'x';
- break;
- case 's':
- inblocksize = 3;
- outblocksize = 4;
- prefix = "0s";
- break;
- case 64: /* beware, equals ' ' */
- inblocksize = 3;
- outblocksize = 4;
- prefix = "";
- format = 's';
- break;
- default:
- return 0;
- break;
- }
- assert(inblocksize < sizeof(inblock));
- assert(outblocksize < sizeof(outblock));
- assert(breakevery % outblocksize == 0);
-
- if (srclen == 0)
- return 0;
- ntodo = srclen;
-
- if (dstlen == 0) { /* dispose of awkward special case */
- dst = fake;
- dstlen = 1;
- }
- stop = dst + dstlen - 1;
-
- nreal = strlen(prefix);
- needed = nreal; /* for starters */
- if (dstlen <= nreal) { /* prefix won't fit */
- strncpy(dst, prefix, dstlen - 1);
- dst += dstlen - 1;
- } else {
- strcpy(dst, prefix);
- dst += nreal;
- }
- assert(dst <= stop);
- sincebreak = 0;
-
- while (ntodo > 0) {
- if (ntodo < inblocksize) { /* incomplete input */
- memset(inblock, 0, sizeof(inblock));
- memcpy(inblock, src, ntodo);
- src = inblock;
- nreal = ntodo;
- ntodo = inblocksize;
- } else
- nreal = inblocksize;
- out = (outblocksize > stop - dst) ? outblock : dst;
-
- convert(src, nreal, format, out);
- needed += outblocksize;
- sincebreak += outblocksize;
- if (dst < stop) {
- if (out != dst) {
- assert(outblocksize > stop - dst);
- memcpy(dst, out, stop - dst);
- dst = stop;
- } else
- dst += outblocksize;
- }
-
- src += inblocksize;
- ntodo -= inblocksize;
- if (breakevery != 0 && sincebreak >= breakevery && ntodo > 0) {
- if (dst < stop)
- *dst++ = breakchar;
- needed++;
- sincebreak = 0;
- }
- }
-
- assert(dst <= stop);
- *dst++ = '\0';
- needed++;
-
- return needed;
-}
-
-/*
- - convert - convert one input block to one output block
- */
-static void
-convert(src, nreal, format, out)
-const char *src;
-size_t nreal; /* how much of the input block is real */
-int format;
-char *out;
-{
- static char hex[] = "0123456789abcdef";
- static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789+/";
- unsigned char c;
- unsigned char c1, c2, c3;
-
- assert(nreal > 0);
- switch (format) {
- case 'x':
- assert(nreal == 1);
- c = (unsigned char)*src;
- *out++ = hex[c >> 4];
- *out++ = hex[c & 0xf];
- break;
- case 's':
- c1 = (unsigned char)*src++;
- c2 = (unsigned char)*src++;
- c3 = (unsigned char)*src++;
- *out++ = base64[c1 >> 2]; /* top 6 bits of c1 */
- c = (c1 & 0x3) << 4; /* bottom 2 of c1... */
- c |= c2 >> 4; /* ...top 4 of c2 */
- *out++ = base64[c];
- if (nreal == 1)
- *out++ = '=';
- else {
- c = (c2 & 0xf) << 2; /* bottom 4 of c2... */
- c |= c3 >> 6; /* ...top 2 of c3 */
- *out++ = base64[c];
- }
- if (nreal <= 2)
- *out++ = '=';
- else
- *out++ = base64[c3 & 0x3f]; /* bottom 6 of c3 */
- break;
- default:
- assert(nreal == 0); /* unknown format */
- break;
- }
-}
-
-/*
- - datatoa - convert data to ASCII
- * backward-compatibility synonym for datatot
- */
-size_t /* true length (with NUL) for success */
-datatoa(src, srclen, format, dst, dstlen)
-const char *src;
-size_t srclen;
-int format; /* character indicating what format */
-char *dst; /* need not be valid if dstlen is 0 */
-size_t dstlen;
-{
- return datatot(src, srclen, format, dst, dstlen);
-}
-
-/*
- - bytestoa - convert data bytes to ASCII
- * backward-compatibility synonym for datatot
- */
-size_t /* true length (with NUL) for success */
-bytestoa(src, srclen, format, dst, dstlen)
-const char *src;
-size_t srclen;
-int format; /* character indicating what format */
-char *dst; /* need not be valid if dstlen is 0 */
-size_t dstlen;
-{
- return datatot(src, srclen, format, dst, dstlen);
-}
diff --git a/src/libfreeswan/freeswan.h b/src/libfreeswan/freeswan.h
deleted file mode 100644
index 724165bde..000000000
--- a/src/libfreeswan/freeswan.h
+++ /dev/null
@@ -1,371 +0,0 @@
-#ifndef _FREESWAN_H
-/*
- * header file for FreeS/WAN library functions
- * Copyright (C) 1998, 1999, 2000 Henry Spencer.
- * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-#define _FREESWAN_H /* seen it, no need to see it again */
-
-# include <sys/types.h>
-# include <stdio.h>
-# include <netinet/in.h>
-
-# define DEBUG_NO_STATIC static
-
-#include <ipsec_param.h>
-#include <utils.h>
-
-/*
- * We assume header files have IPv6 (i.e. kernel version >= 2.1.0)
- */
-#define NET_21
-
-#ifndef IPPROTO_COMP
-# define IPPROTO_COMP 108
-#endif /* !IPPROTO_COMP */
-
-#ifndef IPPROTO_INT
-# define IPPROTO_INT 61
-#endif /* !IPPROTO_INT */
-
-#ifdef CONFIG_IPSEC_DEBUG
-# define DEBUG_NO_STATIC
-#else /* CONFIG_IPSEC_DEBUG */
-# define DEBUG_NO_STATIC static
-#endif /* CONFIG_IPSEC_DEBUG */
-
-#define ESPINUDP_WITH_NON_IKE 1 /* draft-ietf-ipsec-nat-t-ike-00/01 */
-#define ESPINUDP_WITH_NON_ESP 2 /* draft-ietf-ipsec-nat-t-ike-02 */
-
-/*
- * Basic data types for the address-handling functions.
- * ip_address and ip_subnet are supposed to be opaque types; do not
- * use their definitions directly, they are subject to change!
- */
-
-/* then the main types */
-typedef struct {
- union {
- struct sockaddr_in v4;
- struct sockaddr_in6 v6;
- } u;
-} ip_address;
-typedef struct {
- ip_address addr;
- int maskbits;
-} ip_subnet;
-
-/* and the SA ID stuff */
-typedef u_int32_t ipsec_spi_t;
-typedef struct { /* to identify an SA, we need: */
- ip_address dst; /* A. destination host */
- ipsec_spi_t spi; /* B. 32-bit SPI, assigned by dest. host */
-# define SPI_PASS 256 /* magic values... */
-# define SPI_DROP 257 /* ...for use... */
-# define SPI_REJECT 258 /* ...with SA_INT */
-# define SPI_HOLD 259
-# define SPI_TRAP 260
-# define SPI_TRAPSUBNET 261
- int proto; /* C. protocol */
-# define SA_ESP 50 /* IPPROTO_ESP */
-# define SA_AH 51 /* IPPROTO_AH */
-# define SA_IPIP 4 /* IPPROTO_IPIP */
-# define SA_COMP 108 /* IPPROTO_COMP */
-# define SA_INT 61 /* IANA reserved for internal use */
-} ip_said;
-struct sa_id { /* old v4-only version */
- struct in_addr dst;
- ipsec_spi_t spi;
- int proto;
-};
-
-/* misc */
-struct prng { /* pseudo-random-number-generator guts */
- unsigned char sbox[256];
- int i, j;
- unsigned long count;
-};
-
-
-/*
- * definitions for user space, taken from freeswan/ipsec_sa.h
- */
-typedef uint32_t IPsecSAref_t;
-
-#define IPSEC_SA_REF_TABLE_NUM_ENTRIES (1 << IPSEC_SA_REF_TABLE_IDX_WIDTH)
-
-#define IPSEC_SA_REF_FIELD_WIDTH (8 * sizeof(IPsecSAref_t))
-
-#define IPsecSAref2NFmark(x) ((x) << (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_TABLE_IDX_WIDTH))
-#define NFmark2IPsecSAref(x) ((x) >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_TABLE_IDX_WIDTH))
-
-#define IPSEC_SAREF_NULL (~((IPsecSAref_t)0))
-
-/* GCC magic for use in function definitions! */
-#ifdef GCC_LINT
-# define PRINTF_LIKE(n) __attribute__ ((format(printf, n, n+1)))
-# define NEVER_RETURNS __attribute__ ((noreturn))
-# define UNUSED __attribute__ ((unused))
-# define BLANK_FORMAT " " /* GCC_LINT whines about empty formats */
-#else
-# define PRINTF_LIKE(n) /* ignore */
-# define NEVER_RETURNS /* ignore */
-# define UNUSED /* ignore */
-# define BLANK_FORMAT ""
-#endif
-
-
-
-
-
-/*
- * new IPv6-compatible functions
- */
-
-/* text conversions */
-err_t ttoul(const char *src, size_t srclen, int format, unsigned long *dst);
-size_t ultot(unsigned long src, int format, char *buf, size_t buflen);
-#define ULTOT_BUF (22+1) /* holds 64 bits in octal */
-err_t ttoaddr(const char *src, size_t srclen, int af, ip_address *dst);
-err_t tnatoaddr(const char *src, size_t srclen, int af, ip_address *dst);
-size_t addrtot(const ip_address *src, int format, char *buf, size_t buflen);
-/* RFC 1886 old IPv6 reverse-lookup format is the bulkiest */
-#define ADDRTOT_BUF (32*2 + 3 + 1 + 3 + 1 + 1)
-err_t ttosubnet(const char *src, size_t srclen, int af, ip_subnet *dst);
-size_t subnettot(const ip_subnet *src, int format, char *buf, size_t buflen);
-#define SUBNETTOT_BUF (ADDRTOT_BUF + 1 + 3)
-err_t ttosa(const char *src, size_t srclen, ip_said *dst);
-size_t satot(const ip_said *src, int format, char *bufptr, size_t buflen);
-#define SATOT_BUF (5 + ULTOA_BUF + 1 + ADDRTOT_BUF)
-err_t ttodata(const char *src, size_t srclen, int base, char *buf,
- size_t buflen, size_t *needed);
-err_t ttodatav(const char *src, size_t srclen, int base,
- char *buf, size_t buflen, size_t *needed,
- char *errp, size_t errlen, unsigned int flags);
-#define TTODATAV_BUF 40 /* ttodatav's largest non-literal message */
-#define TTODATAV_IGNORESPACE (1<<1) /* ignore spaces in base64 encodings*/
-#define TTODATAV_SPACECOUNTS 0 /* do not ignore spaces in base64 */
-
-size_t datatot(const char *src, size_t srclen, int format, char *buf,
- size_t buflen);
-err_t ttoprotoport(char *src, size_t src_len, u_int8_t *proto, u_int16_t *port,
- bool *has_port_wildcard);
-
-/* initializations */
-void initsaid(const ip_address *addr, ipsec_spi_t spi, int proto, ip_said *dst);
-err_t loopbackaddr(int af, ip_address *dst);
-err_t unspecaddr(int af, ip_address *dst);
-err_t anyaddr(int af, ip_address *dst);
-err_t initaddr(const unsigned char *src, size_t srclen, int af, ip_address *dst);
-err_t initsubnet(const ip_address *addr, int maskbits, int clash, ip_subnet *dst);
-err_t addrtosubnet(const ip_address *addr, ip_subnet *dst);
-
-/* misc. conversions and related */
-err_t rangetosubnet(const ip_address *from, const ip_address *to, ip_subnet *dst);
-int addrtypeof(const ip_address *src);
-int subnettypeof(const ip_subnet *src);
-size_t addrlenof(const ip_address *src);
-size_t addrbytesptr(const ip_address *src, const unsigned char **dst);
-size_t addrbytesof(const ip_address *src, unsigned char *dst, size_t dstlen);
-int masktocount(const ip_address *src);
-void networkof(const ip_subnet *src, ip_address *dst);
-void maskof(const ip_subnet *src, ip_address *dst);
-
-/* tests */
-int sameaddr(const ip_address *a, const ip_address *b);
-int addrcmp(const ip_address *a, const ip_address *b);
-int samesubnet(const ip_subnet *a, const ip_subnet *b);
-int addrinsubnet(const ip_address *a, const ip_subnet *s);
-int subnetinsubnet(const ip_subnet *a, const ip_subnet *b);
-int subnetishost(const ip_subnet *s);
-int samesaid(const ip_said *a, const ip_said *b);
-int sameaddrtype(const ip_address *a, const ip_address *b);
-int samesubnettype(const ip_subnet *a, const ip_subnet *b);
-int isanyaddr(const ip_address *src);
-int isunspecaddr(const ip_address *src);
-int isloopbackaddr(const ip_address *src);
-
-/* low-level grot */
-int portof(const ip_address *src);
-void setportof(int port, ip_address *dst);
-struct sockaddr *sockaddrof(ip_address *src);
-size_t sockaddrlenof(const ip_address *src);
-
-/* odds and ends */
-const char **ipsec_copyright_notice(void);
-
-const char *dns_string_rr(int rr, char *buf, int bufsize);
-const char *dns_string_datetime(time_t seconds,
- char *buf,
- int bufsize);
-
-
-/*
- * old functions, to be deleted eventually
- */
-
-/* unsigned long */
-const char * /* NULL for success, else string literal */
-atoul(
- const char *src,
- size_t srclen, /* 0 means strlen(src) */
- int base, /* 0 means figure it out */
- unsigned long *resultp
-);
-size_t /* space needed for full conversion */
-ultoa(
- unsigned long n,
- int base,
- char *dst,
- size_t dstlen
-);
-#define ULTOA_BUF 21 /* just large enough for largest result, */
- /* assuming 64-bit unsigned long! */
-
-/* Internet addresses */
-const char * /* NULL for success, else string literal */
-atoaddr(
- const char *src,
- size_t srclen, /* 0 means strlen(src) */
- struct in_addr *addr
-);
-size_t /* space needed for full conversion */
-addrtoa(
- struct in_addr addr,
- int format, /* character; 0 means default */
- char *dst,
- size_t dstlen
-);
-#define ADDRTOA_BUF 16 /* just large enough for largest result */
-
-/* subnets */
-const char * /* NULL for success, else string literal */
-atosubnet(
- const char *src,
- size_t srclen, /* 0 means strlen(src) */
- struct in_addr *addr,
- struct in_addr *mask
-);
-size_t /* space needed for full conversion */
-subnettoa(
- struct in_addr addr,
- struct in_addr mask,
- int format, /* character; 0 means default */
- char *dst,
- size_t dstlen
-);
-#define SUBNETTOA_BUF 32 /* large enough for worst case result */
-
-/* ranges */
-const char * /* NULL for success, else string literal */
-atoasr(
- const char *src,
- size_t srclen, /* 0 means strlen(src) */
- char *type, /* 'a', 's', 'r' */
- struct in_addr *addrs /* two-element array */
-);
-size_t /* space needed for full conversion */
-rangetoa(
- struct in_addr *addrs, /* two-element array */
- int format, /* character; 0 means default */
- char *dst,
- size_t dstlen
-);
-#define RANGETOA_BUF 34 /* large enough for worst case result */
-
-/* generic data, e.g. keys */
-const char * /* NULL for success, else string literal */
-atobytes(
- const char *src,
- size_t srclen, /* 0 means strlen(src) */
- char *dst,
- size_t dstlen,
- size_t *lenp /* NULL means don't bother telling me */
-);
-size_t /* 0 failure, else true size */
-bytestoa(
- const char *src,
- size_t srclen,
- int format, /* character; 0 means default */
- char *dst,
- size_t dstlen
-);
-
-/* old versions of generic-data functions; deprecated */
-size_t /* 0 failure, else true size */
-atodata(
- const char *src,
- size_t srclen, /* 0 means strlen(src) */
- char *dst,
- size_t dstlen
-);
-size_t /* 0 failure, else true size */
-datatoa(
- const char *src,
- size_t srclen,
- int format, /* character; 0 means default */
- char *dst,
- size_t dstlen
-);
-
-/* part extraction and special addresses */
-struct in_addr
-subnetof(
- struct in_addr addr,
- struct in_addr mask
-);
-struct in_addr
-hostof(
- struct in_addr addr,
- struct in_addr mask
-);
-struct in_addr
-broadcastof(
- struct in_addr addr,
- struct in_addr mask
-);
-
-/* mask handling */
-int
-goodmask(
- struct in_addr mask
-);
-int
-masktobits(
- struct in_addr mask
-);
-struct in_addr
-bitstomask(
- int n
-);
-
-/*
- * Debugging levels for pfkey_lib_debug
- */
-#define PF_KEY_DEBUG_PARSE_NONE 0
-#define PF_KEY_DEBUG_PARSE_PROBLEM 1
-#define PF_KEY_DEBUG_PARSE_STRUCT 2
-#define PF_KEY_DEBUG_PARSE_FLOW 4
-#define PF_KEY_DEBUG_PARSE_MAX 7
-
-extern unsigned int pfkey_lib_debug; /* bits selecting what to report */
-
-/*
- * pluto and lwdnsq need to know the maximum size of the commands to,
- * and replies from lwdnsq.
- */
-
-#define LWDNSQ_CMDBUF_LEN 1024
-#define LWDNSQ_RESULT_LEN_MAX 4096
-
-#endif /* _FREESWAN_H */
diff --git a/src/libfreeswan/goodmask.3 b/src/libfreeswan/goodmask.3
deleted file mode 100644
index b76d431ca..000000000
--- a/src/libfreeswan/goodmask.3
+++ /dev/null
@@ -1,56 +0,0 @@
-.TH IPSEC_GOODMASK 3 "11 June 2001"
-.SH NAME
-ipsec goodmask \- is this Internet subnet mask a valid one?
-.br
-ipsec masktobits \- convert Internet subnet mask to bit count
-.br
-ipsec bitstomask \- convert bit count to Internet subnet mask
-.SH SYNOPSIS
-.B "#include <freeswan.h>
-.sp
-.B "int goodmask(struct in_addr mask);"
-.br
-.B "int masktobits(struct in_addr mask);"
-.br
-.B "struct in_addr bitstomask(int n);"
-.SH DESCRIPTION
-These functions are obsolete;
-see
-.IR ipsec_masktocount (3)
-for a partial replacement.
-.PP
-.I Goodmask
-reports whether the subnet
-.I mask
-is a valid one,
-i.e. consists of a (possibly empty) sequence of
-.BR 1 s
-followed by a (possibly empty) sequence of
-.BR 0 s.
-.I Masktobits
-takes a (valid) subnet mask and returns the number of
-.B 1
-bits in it.
-.I Bitstomask
-reverses this,
-returning the subnet mask corresponding to bit count
-.IR n .
-.PP
-All masks are in network byte order.
-.SH SEE ALSO
-inet(3), ipsec_atosubnet(3)
-.SH DIAGNOSTICS
-.I Masktobits
-returns
-.B \-1
-for an invalid mask.
-.I Bitstomask
-returns an all-zeros mask for a negative or out-of-range
-.IR n .
-.SH HISTORY
-Written for the FreeS/WAN project by Henry Spencer.
-.SH BUGS
-The error-reporting convention of
-.I bitstomask
-is less than ideal;
-zero is sometimes a legitimate mask.
diff --git a/src/libfreeswan/goodmask.c b/src/libfreeswan/goodmask.c
deleted file mode 100644
index 66edae20f..000000000
--- a/src/libfreeswan/goodmask.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * minor utilities for subnet-mask manipulation
- * Copyright (C) 1998, 1999 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-#include "internal.h"
-#include "freeswan.h"
-
-/*
- - goodmask - is this a good (^1*0*$) subnet mask?
- * You are not expected to understand this. See Henry S. Warren Jr,
- * "Functions realizable with word-parallel logical and two's-complement
- * addition instructions", CACM 20.6 (June 1977), p.439.
- */
-int /* predicate */
-goodmask(mask)
-struct in_addr mask;
-{
- unsigned long x = ntohl(mask.s_addr);
- /* clear rightmost contiguous string of 1-bits */
-# define CRCS1B(x) (((x|(x-1))+1)&x)
-# define TOPBIT (1UL << 31)
-
- /* either zero, or has one string of 1-bits which is left-justified */
- if (x == 0 || (CRCS1B(x) == 0 && (x&TOPBIT)))
- return 1;
- return 0;
-}
-
-/*
- - masktobits - how many bits in this mask?
- * The algorithm is essentially a binary search, but highly optimized
- * for this particular task.
- */
-int /* -1 means !goodmask() */
-masktobits(mask)
-struct in_addr mask;
-{
- unsigned long m = ntohl(mask.s_addr);
- int masklen;
-
- if (!goodmask(mask))
- return -1;
-
- if (m&0x00000001UL)
- return 32;
- masklen = 0;
- if (m&(0x0000ffffUL<<1)) { /* <<1 for 1-origin numbering */
- masklen |= 0x10;
- m <<= 16;
- }
- if (m&(0x00ff0000UL<<1)) {
- masklen |= 0x08;
- m <<= 8;
- }
- if (m&(0x0f000000UL<<1)) {
- masklen |= 0x04;
- m <<= 4;
- }
- if (m&(0x30000000UL<<1)) {
- masklen |= 0x02;
- m <<= 2;
- }
- if (m&(0x40000000UL<<1))
- masklen |= 0x01;
-
- return masklen;
-}
-
-/*
- - bitstomask - return a mask with this many high bits on
- */
-struct in_addr
-bitstomask(n)
-int n;
-{
- struct in_addr result;
-
- if (n > 0 && n <= ABITS)
- result.s_addr = htonl(~((1UL << (ABITS - n)) - 1));
- else if (n == 0)
- result.s_addr = 0;
- else
- result.s_addr = 0; /* best error report we can do */
- return result;
-}
diff --git a/src/libfreeswan/initaddr.3 b/src/libfreeswan/initaddr.3
deleted file mode 100644
index 071e507aa..000000000
--- a/src/libfreeswan/initaddr.3
+++ /dev/null
@@ -1,128 +0,0 @@
-.TH IPSEC_INITADDR 3 "11 Sept 2000"
-.SH NAME
-ipsec initaddr \- initialize an ip_address
-.br
-ipsec addrtypeof \- get address type of an ip_address
-.br
-ipsec addrlenof \- get length of address within an ip_address
-.br
-ipsec addrbytesof \- get copy of address within an ip_address
-.br
-ipsec addrbytesptr \- get pointer to address within an ip_address
-.SH SYNOPSIS
-.B "#include <freeswan.h>"
-.sp
-.B "const char *initaddr(const char *src, size_t srclen,"
-.ti +1c
-.B "int af, ip_address *dst);"
-.br
-.B "int addrtypeof(const ip_address *src);"
-.br
-.B "size_t addrlenof(const ip_address *src);"
-.br
-.B "size_t addrbytesof(const ip_address *src,"
-.ti +1c
-.B "unsigned char *dst, size_t dstlen);"
-.br
-.B "size_t addrbytesptr(const ip_address *src,"
-.ti +1c
-.B "const unsigned char **dst);"
-.SH DESCRIPTION
-The
-.B <freeswan.h>
-library uses an internal type
-.I ip_address
-to contain one of the (currently two) types of IP address.
-These functions provide basic tools for creating and examining this type.
-.PP
-.I Initaddr
-initializes a variable
-.I *dst
-of type
-.I ip_address
-from an address
-(in network byte order,
-indicated by a pointer
-.I src
-and a length
-.IR srclen )
-and an address family
-.I af
-(typically
-.B AF_INET
-or
-.BR AF_INET6 ).
-The length must be consistent with the address family.
-.PP
-.I Addrtypeof
-returns the address type of an address,
-normally
-.B AF_INET
-or
-.BR AF_INET6 .
-(The
-.B <freeswan.h>
-header file arranges to include the necessary headers for these
-names to be known.)
-.PP
-.I Addrlenof
-returns the size (in bytes) of the address within an
-.IR ip_address ,
-to permit storage allocation etc.
-.PP
-.I Addrbytesof
-copies the address within the
-.I ip_address
-.I src
-to the buffer indicated by the pointer
-.I dst
-and the length
-.IR dstlen ,
-and returns the address length (in bytes).
-If the address will not fit,
-as many bytes as will fit are copied;
-the returned length is still the full length.
-It is the caller's responsibility to check the
-returned value to ensure that there was enough room.
-.PP
-.I Addrbytesptr
-sets
-.I *dst
-to a pointer to the internal address within the
-.IR ip_address ,
-and returns the address length (in bytes).
-If
-.I dst
-is
-.BR NULL ,
-it just returns the address length.
-The pointer points to
-.B const
-to discourage misuse.
-.PP
-.I Initaddr
-returns
-.B NULL
-for success and
-a pointer to a string-literal error message for failure;
-see DIAGNOSTICS.
-.PP
-The functions which return
-.I size_t
-return
-.B 0
-for a failure.
-.SH SEE ALSO
-inet(3), ipsec_ttoaddr(3)
-.SH DIAGNOSTICS
-An unknown address family is a fatal error for any of these functions
-except
-.IR addrtypeof .
-An address-size mismatch is a fatal error for
-.IR initaddr .
-.SH HISTORY
-Written for the FreeS/WAN project by Henry Spencer.
-.SH BUGS
-.I Addrtypeof
-should probably have been named
-.IR addrfamilyof .
diff --git a/src/libfreeswan/initaddr.c b/src/libfreeswan/initaddr.c
deleted file mode 100644
index c84006f47..000000000
--- a/src/libfreeswan/initaddr.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * initialize address structure
- * Copyright (C) 2000 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-#include <sys/socket.h>
-
-#include "internal.h"
-#include "freeswan.h"
-
-/*
- - initaddr - initialize ip_address from bytes
- */
-err_t /* NULL for success, else string literal */
-initaddr(src, srclen, af, dst)
-const unsigned char *src;
-size_t srclen;
-int af; /* address family */
-ip_address *dst;
-{
- switch (af) {
- case AF_INET:
- if (srclen != 4)
- return "IPv4 address must be exactly 4 bytes";
- dst->u.v4.sin_family = af;
- dst->u.v4.sin_port = 0; /* unused */
- memcpy((char *)&dst->u.v4.sin_addr.s_addr, src, srclen);
- break;
- case AF_INET6:
- if (srclen != 16)
- return "IPv6 address must be exactly 16 bytes";
- dst->u.v6.sin6_family = af;
- dst->u.v6.sin6_flowinfo = 0; /* unused */
- dst->u.v6.sin6_port = 0; /* unused */
- memcpy((char *)&dst->u.v6.sin6_addr, src, srclen);
- break;
- default:
- return "unknown address family in initaddr";
- break;
- }
- return NULL;
-}
diff --git a/src/libfreeswan/initsaid.c b/src/libfreeswan/initsaid.c
deleted file mode 100644
index 4e4bc9a35..000000000
--- a/src/libfreeswan/initsaid.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * initialize SA ID structure
- * Copyright (C) 2000 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-#include "internal.h"
-#include "freeswan.h"
-
-/*
- - initsaid - initialize SA ID from bits
- */
-void
-initsaid(addr, spi, proto, dst)
-const ip_address *addr;
-ipsec_spi_t spi;
-int proto;
-ip_said *dst;
-{
- dst->dst = *addr;
- dst->spi = spi;
- dst->proto = proto;
-}
diff --git a/src/libfreeswan/initsubnet.3 b/src/libfreeswan/initsubnet.3
deleted file mode 100644
index 3545fd426..000000000
--- a/src/libfreeswan/initsubnet.3
+++ /dev/null
@@ -1,136 +0,0 @@
-.TH IPSEC_INITSUBNET 3 "12 March 2002"
-.SH NAME
-ipsec initsubnet \- initialize an ip_subnet
-.br
-ipsec addrtosubnet \- initialize a singleton ip_subnet
-.br
-ipsec subnettypeof \- get address type of an ip_subnet
-.br
-ipsec masktocount \- convert subnet mask to bit count
-.br
-ipsec networkof \- get base address of an ip_subnet
-.br
-ipsec maskof \- get subnet mask of an ip_subnet
-.SH SYNOPSIS
-.B "#include <freeswan.h>"
-.sp
-.B "const char *initsubnet(const ip_address *addr,"
-.ti +1c
-.B "int maskbits, int clash, ip_subnet *dst);"
-.br
-.B "const char *addrtosubnet(const ip_address *addr,"
-.ti +1c
-.B "ip_subnet *dst);"
-.sp
-.B "int subnettypeof(const ip_subnet *src);"
-.br
-.B "int masktocount(const ip_address *src);"
-.br
-.B "void networkof(const ip_subnet *src, ip_address *dst);"
-.br
-.B "void maskof(const ip_subnet *src, ip_address *dst);"
-.SH DESCRIPTION
-The
-.B <freeswan.h>
-library uses an internal type
-.I ip_subnet
-to contain a description of an IP subnet
-(base address plus mask).
-These functions provide basic tools for creating and examining this type.
-.PP
-.I Initsubnet
-initializes a variable
-.I *dst
-of type
-.I ip_subnet
-from a base address and
-a count of mask bits.
-The
-.I clash
-parameter specifies what to do if the base address includes
-.B 1
-bits outside the prefix specified by the mask
-(that is, in the ``host number'' part of the address):
-.RS
-.IP '0' 5
-zero out host-number bits
-.IP 'x'
-non-zero host-number bits are an error
-.RE
-.PP
-.I Initsubnet
-returns
-.B NULL
-for success and
-a pointer to a string-literal error message for failure;
-see DIAGNOSTICS.
-.PP
-.I Addrtosubnet
-initializes an
-.I ip_subnet
-variable
-.I *dst
-to a ``singleton subnet'' containing the single address
-.IR *addr .
-It returns
-.B NULL
-for success and
-a pointer to a string-literal error message for failure.
-.PP
-.I Subnettypeof
-returns the address type of a subnet,
-normally
-.B AF_INET
-or
-.BR AF_INET6 .
-(The
-.B <freeswan.h>
-header file arranges to include the necessary headers for these
-names to be known.)
-.PP
-.I Masktocount
-converts a subnet mask, expressed as an address, to a bit count
-suitable for use with
-.IR initsubnet .
-It returns
-.B \-1
-for error; see DIAGNOSTICS.
-.PP
-.I Networkof
-fills in
-.I *dst
-with the base address of subnet
-.IR src .
-.PP
-.I Maskof
-fills in
-.I *dst
-with the subnet mask of subnet
-.IR src ,
-expressed as an address.
-.SH SEE ALSO
-inet(3), ipsec_ttosubnet(3), ipsec_rangetosubnet(3)
-.SH DIAGNOSTICS
-Fatal errors in
-.I initsubnet
-are:
-unknown address family;
-unknown
-.I clash
-value;
-impossible mask bit count;
-non-zero host-number bits and
-.I clash
-is
-.BR 'x' .
-Fatal errors in
-.I addrtosubnet
-are:
-unknown address family.
-Fatal errors in
-.I masktocount
-are:
-unknown address family;
-mask bits not contiguous.
-.SH HISTORY
-Written for the FreeS/WAN project by Henry Spencer.
diff --git a/src/libfreeswan/initsubnet.c b/src/libfreeswan/initsubnet.c
deleted file mode 100644
index 27faddabc..000000000
--- a/src/libfreeswan/initsubnet.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * initialize subnet structure
- * Copyright (C) 2000, 2002 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-#include "internal.h"
-#include "freeswan.h"
-
-/*
- - initsubnet - initialize ip_subnet from address and count
- *
- * The only hard part is checking for host-part bits turned on.
- */
-err_t /* NULL for success, else string literal */
-initsubnet(addr, count, clash, dst)
-const ip_address *addr;
-int count;
-int clash; /* '0' zero host-part bits, 'x' die on them */
-ip_subnet *dst;
-{
- unsigned char *p;
- int n;
- int c;
- unsigned m;
- int die;
-
- dst->addr = *addr;
- n = addrbytesptr(&dst->addr, (const unsigned char **)&p);
- if (n == 0)
- return "unknown address family";
-
- switch (clash) {
- case '0':
- die = 0;
- break;
- case 'x':
- die = 1;
- break;
- default:
- return "unknown clash-control value in initsubnet";
- break;
- }
-
- c = count / 8;
- if (c > n)
- return "impossible mask count";
- p += c;
- n -= c;
-
- m = 0xff;
- c = count % 8;
- if (n > 0 && c != 0) /* partial byte */
- m >>= c;
- for (; n > 0; n--) {
- if ((*p & m) != 0) {
- if (die)
- return "improper subnet, host-part bits on";
- *p &= ~m;
- }
- m = 0xff;
- p++;
- }
-
- dst->maskbits = count;
- return NULL;
-}
-
-/*
- - addrtosubnet - initialize ip_subnet from a single address
- */
-err_t /* NULL for success, else string literal */
-addrtosubnet(addr, dst)
-const ip_address *addr;
-ip_subnet *dst;
-{
- int n;
-
- dst->addr = *addr;
- n = addrbytesptr(&dst->addr, (const unsigned char **)NULL);
- if (n == 0)
- return "unknown address family";
- dst->maskbits = n*8;
- return NULL;
-}
diff --git a/src/libfreeswan/internal.h b/src/libfreeswan/internal.h
deleted file mode 100644
index 832c8a53d..000000000
--- a/src/libfreeswan/internal.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * internal definitions for use within the library; do not export!
- * Copyright (C) 1998, 1999 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-
-#ifndef ABITS
-#define ABITS 32 /* bits in an IPv4 address */
-#endif
-
-/* case-independent ASCII character equality comparison */
-#define CIEQ(c1, c2) ( ((c1)&~040) == ((c2)&~040) )
-
-/* syntax for passthrough SA */
-#ifndef PASSTHROUGHNAME
-#define PASSTHROUGHNAME "%passthrough"
-#define PASSTHROUGH4NAME "%passthrough4"
-#define PASSTHROUGH6NAME "%passthrough6"
-#define PASSTHROUGHIS "tun0@0.0.0.0"
-#define PASSTHROUGH4IS "tun0@0.0.0.0"
-#define PASSTHROUGH6IS "tun0@::"
-#define PASSTHROUGHTYPE "tun"
-#define PASSTHROUGHSPI 0
-#define PASSTHROUGHDST 0
-#endif
-
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <string.h>
-#include <ctype.h>
-#include <assert.h>
-#include <limits.h>
-#include <netdb.h>
-#include <stdlib.h>
-#define MALLOC(n) malloc(n)
-#define FREE(p) free(p)
-
diff --git a/src/libfreeswan/ipsec_param.h b/src/libfreeswan/ipsec_param.h
deleted file mode 100644
index 93426b8ee..000000000
--- a/src/libfreeswan/ipsec_param.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * @(#) FreeSWAN tunable paramaters
- *
- * Copyright (C) 2001 Richard Guy Briggs <rgb@freeswan.org>
- * and Michael Richardson <mcr@freeswan.org>
- *
- * 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.
- */
-
-/*
- * This file provides a set of #define's which may be tuned by various
- * people/configurations. It keeps all compile-time tunables in one place.
- *
- * This file should be included before all other IPsec kernel-only files.
- *
- */
-
-#ifndef _IPSEC_PARAM_H_
-
-/*
- * This is for the SA reference table. This number is related to the
- * maximum number of SAs that KLIPS can concurrently deal with, plus enough
- * space for keeping expired SAs around.
- *
- * TABLE_MAX_WIDTH is the number of bits that we will use.
- * MAIN_TABLE_WIDTH is the number of bits used for the primary index table.
- *
- */
-#ifndef IPSEC_SA_REF_TABLE_IDX_WIDTH
-# define IPSEC_SA_REF_TABLE_IDX_WIDTH 16
-#endif
-
-#ifndef IPSEC_SA_REF_MAINTABLE_IDX_WIDTH
-# define IPSEC_SA_REF_MAINTABLE_IDX_WIDTH 4
-#endif
-
-#ifndef IPSEC_SA_REF_FREELIST_NUM_ENTRIES
-# define IPSEC_SA_REF_FREELIST_NUM_ENTRIES 256
-#endif
-
-#ifndef IPSEC_SA_REF_CODE
-# define IPSEC_SA_REF_CODE 1
-#endif
-
-#define _IPSEC_PARAM_H_
-#endif /* _IPSEC_PARAM_H_ */
diff --git a/src/libfreeswan/pfkey.h b/src/libfreeswan/pfkey.h
deleted file mode 100644
index 993678c8b..000000000
--- a/src/libfreeswan/pfkey.h
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * FreeS/WAN specific PF_KEY headers
- * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs.
- *
- * 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.
- */
-
-#ifndef __NET_IPSEC_PF_KEY_H
-#define __NET_IPSEC_PF_KEY_H
-
-extern void (*pfkey_debug_func)(const char *message, ...);
-
-extern uint8_t satype2proto(uint8_t satype);
-extern uint8_t proto2satype(uint8_t proto);
-extern char* satype2name(uint8_t satype);
-extern char* proto2name(uint8_t proto);
-
-struct key_opt
-{
- uint32_t key_pid; /* process ID */
- struct sock *sk;
-};
-
-#define key_pid(sk) ((struct key_opt*)&((sk)->protinfo))->key_pid
-
-#define IPSEC_PFKEYv2_ALIGN (sizeof(uint64_t)/sizeof(uint8_t))
-#define BITS_PER_OCTET 8
-#define OCTETBITS 8
-#define PFKEYBITS 64
-#define DIVUP(x,y) ((x + y -1) / y) /* divide, rounding upwards */
-#define ALIGN_N(x,y) (DIVUP(x,y) * y) /* align on y boundary */
-
-#define PFKEYv2_MAX_MSGSIZE 4096
-
-/*
- * PF_KEYv2 permitted and required extensions in and out bitmaps
- */
-struct pf_key_ext_parsers_def {
- int (*parser)(struct sadb_ext*);
- char *parser_name;
-};
-
-
-extern unsigned int extensions_bitmaps[2/*in/out*/][2/*perm/req*/][SADB_MAX + 1/*ext*/];
-#define EXT_BITS_IN 0
-#define EXT_BITS_OUT 1
-#define EXT_BITS_PERM 0
-#define EXT_BITS_REQ 1
-
-extern void pfkey_extensions_init(struct sadb_ext *extensions[SADB_EXT_MAX + 1]);
-extern void pfkey_extensions_free(struct sadb_ext *extensions[SADB_EXT_MAX + 1]);
-extern void pfkey_msg_free(struct sadb_msg **pfkey_msg);
-
-extern int pfkey_msg_parse(struct sadb_msg *pfkey_msg,
- struct pf_key_ext_parsers_def *ext_parsers[],
- struct sadb_ext **extensions,
- int dir);
-
-/*
- * PF_KEYv2 build function prototypes
- */
-
-int
-pfkey_msg_hdr_build(struct sadb_ext** pfkey_ext,
- uint8_t msg_type,
- uint8_t satype,
- uint8_t msg_errno,
- uint32_t seq,
- uint32_t pid);
-
-int
-pfkey_sa_ref_build(struct sadb_ext ** pfkey_ext,
- uint16_t exttype,
- uint32_t spi, /* in network order */
- uint8_t replay_window,
- uint8_t sa_state,
- uint8_t auth,
- uint8_t encrypt,
- uint32_t flags,
- uint32_t/*IPsecSAref_t*/ ref);
-
-int
-pfkey_sa_build(struct sadb_ext ** pfkey_ext,
- uint16_t exttype,
- uint32_t spi, /* in network order */
- uint8_t replay_window,
- uint8_t sa_state,
- uint8_t auth,
- uint8_t encrypt,
- uint32_t flags);
-
-int
-pfkey_lifetime_build(struct sadb_ext ** pfkey_ext,
- uint16_t exttype,
- uint32_t allocations,
- uint64_t bytes,
- uint64_t addtime,
- uint64_t usetime,
- uint32_t packets);
-
-int
-pfkey_address_build(struct sadb_ext** pfkey_ext,
- uint16_t exttype,
- uint8_t proto,
- uint8_t prefixlen,
- struct sockaddr* address);
-
-int
-pfkey_key_build(struct sadb_ext** pfkey_ext,
- uint16_t exttype,
- uint16_t key_bits,
- char* key);
-
-int
-pfkey_ident_build(struct sadb_ext** pfkey_ext,
- uint16_t exttype,
- uint16_t ident_type,
- uint64_t ident_id,
- uint8_t ident_len,
- char* ident_string);
-
-int
-pfkey_x_nat_t_type_build(struct sadb_ext** pfkey_ext,
- uint8_t type);
-int
-pfkey_x_nat_t_port_build(struct sadb_ext** pfkey_ext,
- uint16_t exttype,
- uint16_t port);
-
-int
-pfkey_sens_build(struct sadb_ext** pfkey_ext,
- uint32_t dpd,
- uint8_t sens_level,
- uint8_t sens_len,
- uint64_t* sens_bitmap,
- uint8_t integ_level,
- uint8_t integ_len,
- uint64_t* integ_bitmap);
-
-int
-pfkey_x_protocol_build(struct sadb_ext **, uint8_t);
-
-
-int
-pfkey_prop_build(struct sadb_ext** pfkey_ext,
- uint8_t replay,
- unsigned int comb_num,
- struct sadb_comb* comb);
-
-int
-pfkey_supported_build(struct sadb_ext** pfkey_ext,
- uint16_t exttype,
- unsigned int alg_num,
- struct sadb_alg* alg);
-
-int
-pfkey_spirange_build(struct sadb_ext** pfkey_ext,
- uint16_t exttype,
- uint32_t min,
- uint32_t max);
-
-int
-pfkey_x_kmprivate_build(struct sadb_ext** pfkey_ext);
-
-int
-pfkey_x_satype_build(struct sadb_ext** pfkey_ext,
- uint8_t satype);
-
-int
-pfkey_x_debug_build(struct sadb_ext** pfkey_ext,
- uint32_t tunnel,
- uint32_t netlink,
- uint32_t xform,
- uint32_t eroute,
- uint32_t spi,
- uint32_t radij,
- uint32_t esp,
- uint32_t ah,
- uint32_t rcv,
- uint32_t pfkey,
- uint32_t ipcomp,
- uint32_t verbose);
-
-int
-pfkey_msg_build(struct sadb_msg** pfkey_msg,
- struct sadb_ext* extensions[],
- int dir);
-
-/* in pfkey_v2_debug.c - routines to decode numbers -> strings */
-const char *
-pfkey_v2_sadb_ext_string(int extnum);
-
-const char *
-pfkey_v2_sadb_type_string(int sadb_type);
-
-
-#endif /* __NET_IPSEC_PF_KEY_H */
diff --git a/src/libfreeswan/pfkey_v2_build.c b/src/libfreeswan/pfkey_v2_build.c
deleted file mode 100644
index c0bb369cb..000000000
--- a/src/libfreeswan/pfkey_v2_build.c
+++ /dev/null
@@ -1,1388 +0,0 @@
-/*
- * RFC2367 PF_KEYv2 Key management API message parser
- * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs.
- *
- * 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.
- */
-
-/*
- * Template from klips/net/ipsec/ipsec/ipsec_parser.c.
- */
-
-char pfkey_v2_build_c_version[] = "";
-
-# include <sys/types.h>
-# include <sys/socket.h>
-# include <stdlib.h>
-# include <errno.h>
-# include <string.h> /* memset */
-
-# include <freeswan.h>
-unsigned int pfkey_lib_debug = 0;
-
-void (*pfkey_debug_func)(const char *message, ...) PRINTF_LIKE(1);
-
-#define DEBUGGING(args...) if(pfkey_lib_debug) { \
- if(pfkey_debug_func != NULL) { \
- (*pfkey_debug_func)("pfkey_lib_debug:" args); \
- } else { \
- printf("pfkey_lib_debug:" args); \
- } }
-# define MALLOC(size) malloc(size)
-# define FREE(obj) free(obj)
-
-#include <pfkeyv2.h>
-#include <pfkey.h>
-
-#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0)
-
-void
-pfkey_extensions_init(struct sadb_ext *extensions[SADB_EXT_MAX + 1])
-{
- int i;
-
- for (i = 0; i != SADB_EXT_MAX + 1; i++) {
- extensions[i] = NULL;
- }
-}
-
-void
-pfkey_extensions_free(struct sadb_ext *extensions[SADB_EXT_MAX + 1])
-{
- int i;
-
- if (!extensions) {
- return;
- }
-
- if (extensions[0]) {
- memset(extensions[0], 0, sizeof(struct sadb_msg));
- FREE(extensions[0]);
- extensions[0] = NULL;
- }
-
- for (i = 1; i != SADB_EXT_MAX + 1; i++) {
- if(extensions[i]) {
- memset(extensions[i], 0, extensions[i]->sadb_ext_len * IPSEC_PFKEYv2_ALIGN);
- FREE(extensions[i]);
- extensions[i] = NULL;
- }
- }
-}
-
-void
-pfkey_msg_free(struct sadb_msg **pfkey_msg)
-{
- if (*pfkey_msg) {
- memset(*pfkey_msg, 0, (*pfkey_msg)->sadb_msg_len * IPSEC_PFKEYv2_ALIGN);
- FREE(*pfkey_msg);
- *pfkey_msg = NULL;
- }
-}
-
-/* Default extension builders taken from the KLIPS code */
-
-int
-pfkey_msg_hdr_build(struct sadb_ext** pfkey_ext,
- uint8_t msg_type,
- uint8_t satype,
- uint8_t msg_errno,
- uint32_t seq,
- uint32_t pid)
-{
- int error = 0;
- struct sadb_msg *pfkey_msg = (struct sadb_msg *)*pfkey_ext;
-
- DEBUGGING(
- "pfkey_msg_hdr_build:\n");
- DEBUGGING(
- "pfkey_msg_hdr_build: "
- "on_entry &pfkey_ext=0p%p pfkey_ext=0p%p *pfkey_ext=0p%p.\n",
- &pfkey_ext,
- pfkey_ext,
- *pfkey_ext);
- /* sanity checks... */
- if (pfkey_msg) {
- DEBUGGING(
- "pfkey_msg_hdr_build: "
- "why is pfkey_msg already pointing to something?\n");
- SENDERR(EINVAL);
- }
-
- if (!msg_type) {
- DEBUGGING(
- "pfkey_msg_hdr_build: "
- "msg type not set, must be non-zero..\n");
- SENDERR(EINVAL);
- }
-
- if (msg_type > SADB_MAX) {
- DEBUGGING(
- "pfkey_msg_hdr_build: "
- "msg type too large:%d.\n",
- msg_type);
- SENDERR(EINVAL);
- }
-
- if (satype > SADB_SATYPE_MAX) {
- DEBUGGING(
- "pfkey_msg_hdr_build: "
- "satype %d > max %d\n",
- satype, SADB_SATYPE_MAX);
- SENDERR(EINVAL);
- }
-
- pfkey_msg = (struct sadb_msg*)MALLOC(sizeof(struct sadb_msg));
- *pfkey_ext = (struct sadb_ext*)pfkey_msg;
-
- if (pfkey_msg == NULL) {
- DEBUGGING(
- "pfkey_msg_hdr_build: "
- "memory allocation failed\n");
- SENDERR(ENOMEM);
- }
- memset(pfkey_msg, 0, sizeof(struct sadb_msg));
-
- pfkey_msg->sadb_msg_len = sizeof(struct sadb_msg) / IPSEC_PFKEYv2_ALIGN;
-
- pfkey_msg->sadb_msg_type = msg_type;
- pfkey_msg->sadb_msg_satype = satype;
-
- pfkey_msg->sadb_msg_version = PF_KEY_V2;
- pfkey_msg->sadb_msg_errno = msg_errno;
- pfkey_msg->sadb_msg_reserved = 0;
- pfkey_msg->sadb_msg_seq = seq;
- pfkey_msg->sadb_msg_pid = pid;
- DEBUGGING(
- "pfkey_msg_hdr_build: "
- "on_exit &pfkey_ext=0p%p pfkey_ext=0p%p *pfkey_ext=0p%p.\n",
- &pfkey_ext,
- pfkey_ext,
- *pfkey_ext);
-errlab:
- return error;
-}
-
-int
-pfkey_sa_ref_build(struct sadb_ext ** pfkey_ext,
- uint16_t exttype,
- uint32_t spi,
- uint8_t replay_window,
- uint8_t sa_state,
- uint8_t auth,
- uint8_t encrypt,
- uint32_t flags,
- uint32_t/*IPsecSAref_t*/ ref)
-{
- int error = 0;
- struct sadb_sa *pfkey_sa = (struct sadb_sa *)*pfkey_ext;
-
- DEBUGGING(
- "pfkey_sa_build: "
- "spi=%08x replay=%d sa_state=%d auth=%d encrypt=%d flags=%d\n",
- ntohl(spi), /* in network order */
- replay_window,
- sa_state,
- auth,
- encrypt,
- flags);
- /* sanity checks... */
- if (pfkey_sa) {
- DEBUGGING(
- "pfkey_sa_build: "
- "why is pfkey_sa already pointing to something?\n");
- SENDERR(EINVAL);
- }
-
- if (exttype != SADB_EXT_SA
- && exttype != SADB_X_EXT_SA2) {
- DEBUGGING(
- "pfkey_sa_build: "
- "invalid exttype=%d.\n",
- exttype);
- SENDERR(EINVAL);
- }
-
- if (replay_window > 64) {
- DEBUGGING(
- "pfkey_sa_build: "
- "replay window size: %d -- must be 0 <= size <= 64\n",
- replay_window);
- SENDERR(EINVAL);
- }
-
- if (auth > SADB_AALG_MAX) {
- DEBUGGING(
- "pfkey_sa_build: "
- "auth=%d > SADB_AALG_MAX=%d.\n",
- auth,
- SADB_AALG_MAX);
- SENDERR(EINVAL);
- }
-
- if (encrypt > SADB_EALG_MAX) {
- DEBUGGING(
- "pfkey_sa_build: "
- "encrypt=%d > SADB_EALG_MAX=%d.\n",
- encrypt,
- SADB_EALG_MAX);
- SENDERR(EINVAL);
- }
-
- if (sa_state > SADB_SASTATE_MAX) {
- DEBUGGING(
- "pfkey_sa_build: "
- "sa_state=%d exceeds MAX=%d.\n",
- sa_state,
- SADB_SASTATE_MAX);
- SENDERR(EINVAL);
- }
-
- if (sa_state == SADB_SASTATE_DEAD) {
- DEBUGGING(
- "pfkey_sa_build: "
- "sa_state=%d is DEAD=%d is not allowed.\n",
- sa_state,
- SADB_SASTATE_DEAD);
- SENDERR(EINVAL);
- }
-
- if ((IPSEC_SAREF_NULL != ref) && (ref >= (1 << IPSEC_SA_REF_TABLE_IDX_WIDTH))) {
- DEBUGGING(
- "pfkey_sa_build: "
- "SAref=%d must be (SAref == IPSEC_SAREF_NULL(%d) || SAref < IPSEC_SA_REF_TABLE_NUM_ENTRIES(%d)).\n",
- ref,
- IPSEC_SAREF_NULL,
- IPSEC_SA_REF_TABLE_NUM_ENTRIES);
- SENDERR(EINVAL);
- }
-
- pfkey_sa = (struct sadb_sa*)MALLOC(sizeof(struct sadb_sa));
- *pfkey_ext = (struct sadb_ext*)pfkey_sa;
-
- if (pfkey_sa == NULL) {
- DEBUGGING(
- "pfkey_sa_build: "
- "memory allocation failed\n");
- SENDERR(ENOMEM);
- }
- memset(pfkey_sa, 0, sizeof(struct sadb_sa));
-
- pfkey_sa->sadb_sa_len = sizeof(*pfkey_sa) / IPSEC_PFKEYv2_ALIGN;
- pfkey_sa->sadb_sa_exttype = exttype;
- pfkey_sa->sadb_sa_spi = spi;
- pfkey_sa->sadb_sa_replay = replay_window;
- pfkey_sa->sadb_sa_state = sa_state;
- pfkey_sa->sadb_sa_auth = auth;
- pfkey_sa->sadb_sa_encrypt = encrypt;
- pfkey_sa->sadb_sa_flags = flags;
- pfkey_sa->sadb_x_sa_ref = ref;
-
-errlab:
- return error;
-}
-
-int
-pfkey_sa_build(struct sadb_ext ** pfkey_ext,
- uint16_t exttype,
- uint32_t spi,
- uint8_t replay_window,
- uint8_t sa_state,
- uint8_t auth,
- uint8_t encrypt,
- uint32_t flags)
-{
- return pfkey_sa_ref_build(pfkey_ext,
- exttype,
- spi,
- replay_window,
- sa_state,
- auth,
- encrypt,
- flags,
- IPSEC_SAREF_NULL);
-}
-
-int
-pfkey_lifetime_build(struct sadb_ext ** pfkey_ext,
- uint16_t exttype,
- uint32_t allocations,
- uint64_t bytes,
- uint64_t addtime,
- uint64_t usetime,
- uint32_t packets)
-{
- int error = 0;
- struct sadb_lifetime *pfkey_lifetime = (struct sadb_lifetime *)*pfkey_ext;
-
- DEBUGGING(
- "pfkey_lifetime_build:\n");
- /* sanity checks... */
- if (pfkey_lifetime) {
- DEBUGGING(
- "pfkey_lifetime_build: "
- "why is pfkey_lifetime already pointing to something?\n");
- SENDERR(EINVAL);
- }
-
- if (exttype != SADB_EXT_LIFETIME_CURRENT
- && exttype != SADB_EXT_LIFETIME_HARD
- && exttype != SADB_EXT_LIFETIME_SOFT) {
- DEBUGGING(
- "pfkey_lifetime_build: "
- "invalid exttype=%d.\n",
- exttype);
- SENDERR(EINVAL);
- }
-
- pfkey_lifetime = (struct sadb_lifetime*)MALLOC(sizeof(struct sadb_lifetime));
- *pfkey_ext = (struct sadb_ext*)pfkey_lifetime;
-
- if (pfkey_lifetime == NULL) {
- DEBUGGING(
- "pfkey_lifetime_build: "
- "memory allocation failed\n");
- SENDERR(ENOMEM);
- }
- memset(pfkey_lifetime, 0, sizeof(struct sadb_lifetime));
-
- pfkey_lifetime->sadb_lifetime_len = sizeof(struct sadb_lifetime) / IPSEC_PFKEYv2_ALIGN;
- pfkey_lifetime->sadb_lifetime_exttype = exttype;
- pfkey_lifetime->sadb_lifetime_allocations = allocations;
- pfkey_lifetime->sadb_lifetime_bytes = bytes;
- pfkey_lifetime->sadb_lifetime_addtime = addtime;
- pfkey_lifetime->sadb_lifetime_usetime = usetime;
- pfkey_lifetime->sadb_x_lifetime_packets = packets;
-
-errlab:
- return error;
-}
-
-int
-pfkey_address_build(struct sadb_ext** pfkey_ext,
- uint16_t exttype,
- uint8_t proto,
- uint8_t prefixlen,
- struct sockaddr* address)
-{
- int error = 0;
- int saddr_len = 0;
- char ipaddr_txt[ADDRTOT_BUF + 6/*extra for port number*/];
- struct sadb_address *pfkey_address = (struct sadb_address *)*pfkey_ext;
-
- DEBUGGING(
- "pfkey_address_build: "
- "exttype=%d proto=%d prefixlen=%d\n",
- exttype,
- proto,
- prefixlen);
- /* sanity checks... */
- if (pfkey_address) {
- DEBUGGING(
- "pfkey_address_build: "
- "why is pfkey_address already pointing to something?\n");
- SENDERR(EINVAL);
- }
-
- if (!address) {
- DEBUGGING("pfkey_address_build: "
- "address is NULL\n");
- SENDERR(EINVAL);
- }
-
- switch(exttype) {
- case SADB_EXT_ADDRESS_SRC:
- case SADB_EXT_ADDRESS_DST:
- case SADB_EXT_ADDRESS_PROXY:
- case SADB_X_EXT_ADDRESS_DST2:
- case SADB_X_EXT_ADDRESS_SRC_FLOW:
- case SADB_X_EXT_ADDRESS_DST_FLOW:
- case SADB_X_EXT_ADDRESS_SRC_MASK:
- case SADB_X_EXT_ADDRESS_DST_MASK:
- case SADB_X_EXT_NAT_T_OA:
- break;
- default:
- DEBUGGING(
- "pfkey_address_build: "
- "unrecognised ext_type=%d.\n",
- exttype);
- SENDERR(EINVAL);
- }
-
- switch (address->sa_family) {
- case AF_INET:
- DEBUGGING(
- "pfkey_address_build: "
- "found address family AF_INET.\n");
- saddr_len = sizeof(struct sockaddr_in);
- sprintf(ipaddr_txt, "%d.%d.%d.%d:%d"
- , (((struct sockaddr_in*)address)->sin_addr.s_addr >> 0) & 0xFF
- , (((struct sockaddr_in*)address)->sin_addr.s_addr >> 8) & 0xFF
- , (((struct sockaddr_in*)address)->sin_addr.s_addr >> 16) & 0xFF
- , (((struct sockaddr_in*)address)->sin_addr.s_addr >> 24) & 0xFF
- , ntohs(((struct sockaddr_in*)address)->sin_port));
- break;
- case AF_INET6:
- DEBUGGING(
- "pfkey_address_build: "
- "found address family AF_INET6.\n");
- saddr_len = sizeof(struct sockaddr_in6);
- sprintf(ipaddr_txt, "%x:%x:%x:%x:%x:%x:%x:%x-%x"
- , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr[0])
- , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr[1])
- , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr[2])
- , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr[3])
- , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr[4])
- , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr[5])
- , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr[6])
- , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr[7])
- , ntohs(((struct sockaddr_in6*)address)->sin6_port));
- break;
- default:
- DEBUGGING(
- "pfkey_address_build: "
- "address->sa_family=%d not supported.\n",
- address->sa_family);
- SENDERR(EPFNOSUPPORT);
- }
-
- DEBUGGING(
- "pfkey_address_build: "
- "found address=%s.\n",
- ipaddr_txt);
- if (prefixlen != 0) {
- DEBUGGING(
- "pfkey_address_build: "
- "address prefixes not supported yet.\n");
- SENDERR(EAFNOSUPPORT); /* not supported yet */
- }
-
- pfkey_address = (struct sadb_address*)
- MALLOC(ALIGN_N(sizeof(struct sadb_address) + saddr_len, IPSEC_PFKEYv2_ALIGN));
- *pfkey_ext = (struct sadb_ext*)pfkey_address;
-
- if (pfkey_address == NULL) {
- DEBUGGING(
- "pfkey_lifetime_build: "
- "memory allocation failed\n");
- SENDERR(ENOMEM);
- }
- memset(pfkey_address,
- 0,
- ALIGN_N(sizeof(struct sadb_address) + saddr_len,
- IPSEC_PFKEYv2_ALIGN));
-
- pfkey_address->sadb_address_len = DIVUP(sizeof(struct sadb_address) + saddr_len,
- IPSEC_PFKEYv2_ALIGN);
-
- pfkey_address->sadb_address_exttype = exttype;
- pfkey_address->sadb_address_proto = proto;
- pfkey_address->sadb_address_prefixlen = prefixlen;
- pfkey_address->sadb_address_reserved = 0;
-
- memcpy((char*)pfkey_address + sizeof(struct sadb_address),
- address,
- saddr_len);
-
-#if 0
- for (i = 0; i < sizeof(struct sockaddr_in) - offsetof(struct sockaddr_in, sin_zero); i++) {
- pfkey_address_s_ska.sin_zero[i] = 0;
- }
-#endif
- DEBUGGING(
- "pfkey_address_build: "
- "successful.\n");
-
- errlab:
- return error;
-}
-
-int
-pfkey_key_build(struct sadb_ext** pfkey_ext,
- uint16_t exttype,
- uint16_t key_bits,
- char* key)
-{
- int error = 0;
- struct sadb_key *pfkey_key = (struct sadb_key *)*pfkey_ext;
-
- DEBUGGING(
- "pfkey_key_build:\n");
- /* sanity checks... */
- if (pfkey_key) {
- DEBUGGING(
- "pfkey_key_build: "
- "why is pfkey_key already pointing to something?\n");
- SENDERR(EINVAL);
- }
-
- if (!key_bits) {
- DEBUGGING(
- "pfkey_key_build: "
- "key_bits is zero, it must be non-zero.\n");
- SENDERR(EINVAL);
- }
-
- if ( !((exttype == SADB_EXT_KEY_AUTH) || (exttype == SADB_EXT_KEY_ENCRYPT))) {
- DEBUGGING(
- "pfkey_key_build: "
- "unsupported extension type=%d.\n",
- exttype);
- SENDERR(EINVAL);
- }
-
- pfkey_key = (struct sadb_key*)
- MALLOC(sizeof(struct sadb_key) +
- DIVUP(key_bits, 64) * IPSEC_PFKEYv2_ALIGN);
- *pfkey_ext = (struct sadb_ext*)pfkey_key;
-
- if (pfkey_key == NULL) {
- DEBUGGING(
- "pfkey_key_build: "
- "memory allocation failed\n");
- SENDERR(ENOMEM);
- }
- memset(pfkey_key,
- 0,
- sizeof(struct sadb_key) +
- DIVUP(key_bits, 64) * IPSEC_PFKEYv2_ALIGN);
-
- pfkey_key->sadb_key_len = DIVUP(sizeof(struct sadb_key) * IPSEC_PFKEYv2_ALIGN + key_bits,
- 64);
- pfkey_key->sadb_key_exttype = exttype;
- pfkey_key->sadb_key_bits = key_bits;
- pfkey_key->sadb_key_reserved = 0;
- memcpy((char*)pfkey_key + sizeof(struct sadb_key),
- key,
- DIVUP(key_bits, 8));
-
-errlab:
- return error;
-}
-
-int
-pfkey_ident_build(struct sadb_ext** pfkey_ext,
- uint16_t exttype,
- uint16_t ident_type,
- uint64_t ident_id,
- uint8_t ident_len,
- char* ident_string)
-{
- int error = 0;
- struct sadb_ident *pfkey_ident = (struct sadb_ident *)*pfkey_ext;
- int data_len = ident_len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident);
-
- DEBUGGING(
- "pfkey_ident_build:\n");
- /* sanity checks... */
- if (pfkey_ident) {
- DEBUGGING(
- "pfkey_ident_build: "
- "why is pfkey_ident already pointing to something?\n");
- SENDERR(EINVAL);
- }
-
- if ( !((exttype == SADB_EXT_IDENTITY_SRC) ||
- (exttype == SADB_EXT_IDENTITY_DST))) {
- DEBUGGING(
- "pfkey_ident_build: "
- "unsupported extension type=%d.\n",
- exttype);
- SENDERR(EINVAL);
- }
-
- if (ident_type == SADB_IDENTTYPE_RESERVED) {
- DEBUGGING(
- "pfkey_ident_build: "
- "ident_type must be non-zero.\n");
- SENDERR(EINVAL);
- }
-
- if (ident_type > SADB_IDENTTYPE_MAX) {
- DEBUGGING(
- "pfkey_ident_build: "
- "identtype=%d out of range.\n",
- ident_type);
- SENDERR(EINVAL);
- }
-
- if ((ident_type == SADB_IDENTTYPE_PREFIX ||
- ident_type == SADB_IDENTTYPE_FQDN) &&
- !ident_string) {
- DEBUGGING(
- "pfkey_ident_build: "
- "string required to allocate size of extension.\n");
- SENDERR(EINVAL);
- }
-
-#if 0
- if (ident_type == SADB_IDENTTYPE_USERFQDN) {
- }
-#endif
-
- pfkey_ident = (struct sadb_ident*)
- MALLOC(ident_len * IPSEC_PFKEYv2_ALIGN);
- *pfkey_ext = (struct sadb_ext*)pfkey_ident;
-
- if (pfkey_ident == NULL) {
- DEBUGGING(
- "pfkey_ident_build: "
- "memory allocation failed\n");
- SENDERR(ENOMEM);
- }
- memset(pfkey_ident, 0, ident_len * IPSEC_PFKEYv2_ALIGN);
-
- pfkey_ident->sadb_ident_len = ident_len;
- pfkey_ident->sadb_ident_exttype = exttype;
- pfkey_ident->sadb_ident_type = ident_type;
- pfkey_ident->sadb_ident_reserved = 0;
- pfkey_ident->sadb_ident_id = ident_id;
- memcpy((char*)pfkey_ident + sizeof(struct sadb_ident),
- ident_string,
- data_len);
-
-errlab:
- return error;
-}
-
-int
-pfkey_sens_build(struct sadb_ext** pfkey_ext,
- uint32_t dpd,
- uint8_t sens_level,
- uint8_t sens_len,
- uint64_t* sens_bitmap,
- uint8_t integ_level,
- uint8_t integ_len,
- uint64_t* integ_bitmap)
-{
- int error = 0;
- struct sadb_sens *pfkey_sens = (struct sadb_sens *)*pfkey_ext;
- int i;
- uint64_t* bitmap;
-
- DEBUGGING(
- "pfkey_sens_build:\n");
- /* sanity checks... */
- if (pfkey_sens) {
- DEBUGGING(
- "pfkey_sens_build: "
- "why is pfkey_sens already pointing to something?\n");
- SENDERR(EINVAL);
- }
-
- DEBUGGING(
- "pfkey_sens_build: "
- "Sorry, I can't build exttype=%d yet.\n",
- (*pfkey_ext)->sadb_ext_type);
- SENDERR(EINVAL); /* don't process these yet */
-
- pfkey_sens = (struct sadb_sens*)
- MALLOC(sizeof(struct sadb_sens) +
- (sens_len + integ_len) * sizeof(uint64_t));
- *pfkey_ext = (struct sadb_ext*)pfkey_sens;
-
- if (pfkey_sens == NULL) {
- DEBUGGING(
- "pfkey_sens_build: "
- "memory allocation failed\n");
- SENDERR(ENOMEM);
- }
- memset(pfkey_sens,
- 0,
- sizeof(struct sadb_sens) +
- (sens_len + integ_len) * sizeof(uint64_t));
-
- pfkey_sens->sadb_sens_len = (sizeof(struct sadb_sens) +
- (sens_len + integ_len) * sizeof(uint64_t)) / IPSEC_PFKEYv2_ALIGN;
- pfkey_sens->sadb_sens_exttype = SADB_EXT_SENSITIVITY;
- pfkey_sens->sadb_sens_dpd = dpd;
- pfkey_sens->sadb_sens_sens_level = sens_level;
- pfkey_sens->sadb_sens_sens_len = sens_len;
- pfkey_sens->sadb_sens_integ_level = integ_level;
- pfkey_sens->sadb_sens_integ_len = integ_len;
- pfkey_sens->sadb_sens_reserved = 0;
-
- bitmap = (uint64_t*)((char*)pfkey_ext + sizeof(struct sadb_sens));
- for (i = 0; i < sens_len; i++) {
- *bitmap = sens_bitmap[i];
- bitmap++;
- }
- for (i = 0; i < integ_len; i++) {
- *bitmap = integ_bitmap[i];
- bitmap++;
- }
-
-errlab:
- return error;
-}
-
-int
-pfkey_prop_build(struct sadb_ext** pfkey_ext,
- uint8_t replay,
- unsigned int comb_num,
- struct sadb_comb* comb)
-{
- int error = 0;
- int i;
- struct sadb_prop *pfkey_prop = (struct sadb_prop *)*pfkey_ext;
- struct sadb_comb *combp;
-
- DEBUGGING(
- "pfkey_prop_build:\n");
- /* sanity checks... */
- if (pfkey_prop) {
- DEBUGGING(
- "pfkey_prop_build: "
- "why is pfkey_prop already pointing to something?\n");
- SENDERR(EINVAL);
- }
-
- pfkey_prop = (struct sadb_prop*)
- MALLOC(sizeof(struct sadb_prop) +
- comb_num * sizeof(struct sadb_comb));
-
- *pfkey_ext = (struct sadb_ext*)pfkey_prop;
-
- if (pfkey_prop == NULL) {
- DEBUGGING(
- "pfkey_prop_build: "
- "memory allocation failed\n");
- SENDERR(ENOMEM);
- }
- memset(pfkey_prop,
- 0,
- sizeof(struct sadb_prop) +
- comb_num * sizeof(struct sadb_comb));
-
- pfkey_prop->sadb_prop_len = (sizeof(struct sadb_prop) +
- comb_num * sizeof(struct sadb_comb)) / IPSEC_PFKEYv2_ALIGN;
-
- pfkey_prop->sadb_prop_exttype = SADB_EXT_PROPOSAL;
- pfkey_prop->sadb_prop_replay = replay;
-
- for (i=0; i<3; i++) {
- pfkey_prop->sadb_prop_reserved[i] = 0;
- }
-
- combp = (struct sadb_comb*)((char*)*pfkey_ext + sizeof(struct sadb_prop));
- for (i = 0; i < comb_num; i++) {
- memcpy (combp, &(comb[i]), sizeof(struct sadb_comb));
- combp++;
- }
-
-#if 0
- uint8_t sadb_comb_auth;
- uint8_t sadb_comb_encrypt;
- uint16_t sadb_comb_flags;
- uint16_t sadb_comb_auth_minbits;
- uint16_t sadb_comb_auth_maxbits;
- uint16_t sadb_comb_encrypt_minbits;
- uint16_t sadb_comb_encrypt_maxbits;
- uint32_t sadb_comb_reserved;
- uint32_t sadb_comb_soft_allocations;
- uint32_t sadb_comb_hard_allocations;
- uint64_t sadb_comb_soft_bytes;
- uint64_t sadb_comb_hard_bytes;
- uint64_t sadb_comb_soft_addtime;
- uint64_t sadb_comb_hard_addtime;
- uint64_t sadb_comb_soft_usetime;
- uint64_t sadb_comb_hard_usetime;
- uint32_t sadb_comb_soft_packets;
- uint32_t sadb_comb_hard_packets;
-#endif
-errlab:
- return error;
-}
-
-int
-pfkey_supported_build(struct sadb_ext** pfkey_ext,
- uint16_t exttype,
- unsigned int alg_num,
- struct sadb_alg* alg)
-{
- int error = 0;
- unsigned int i;
- struct sadb_supported *pfkey_supported = (struct sadb_supported *)*pfkey_ext;
- struct sadb_alg *pfkey_alg;
-
- /* sanity checks... */
- if (pfkey_supported) {
- DEBUGGING(
- "pfkey_supported_build: "
- "why is pfkey_supported already pointing to something?\n");
- SENDERR(EINVAL);
- }
-
- if ( !((exttype == SADB_EXT_SUPPORTED_AUTH) || (exttype == SADB_EXT_SUPPORTED_ENCRYPT))) {
- DEBUGGING(
- "pfkey_supported_build: "
- "unsupported extension type=%d.\n",
- exttype);
- SENDERR(EINVAL);
- }
-
- pfkey_supported = (struct sadb_supported*)
- MALLOC(sizeof(struct sadb_supported) +
- alg_num * sizeof(struct sadb_alg));
-
- *pfkey_ext = (struct sadb_ext*)pfkey_supported;
-
- if (pfkey_supported == NULL) {
- DEBUGGING(
- "pfkey_supported_build: "
- "memory allocation failed\n");
- SENDERR(ENOMEM);
- }
- memset(pfkey_supported,
- 0,
- sizeof(struct sadb_supported) +
- alg_num *
- sizeof(struct sadb_alg));
-
- pfkey_supported->sadb_supported_len = (sizeof(struct sadb_supported) +
- alg_num *
- sizeof(struct sadb_alg)) /
- IPSEC_PFKEYv2_ALIGN;
- pfkey_supported->sadb_supported_exttype = exttype;
- pfkey_supported->sadb_supported_reserved = 0;
-
- pfkey_alg = (struct sadb_alg*)((char*)pfkey_supported + sizeof(struct sadb_supported));
- for(i = 0; i < alg_num; i++) {
- memcpy (pfkey_alg, &(alg[i]), sizeof(struct sadb_alg));
- pfkey_alg->sadb_alg_reserved = 0;
- pfkey_alg++;
- }
-
-#if 0
- DEBUGGING(
- "pfkey_supported_build: "
- "Sorry, I can't build exttype=%d yet.\n",
- (*pfkey_ext)->sadb_ext_type);
- SENDERR(EINVAL); /* don't process these yet */
-
- uint8_t sadb_alg_id;
- uint8_t sadb_alg_ivlen;
- uint16_t sadb_alg_minbits;
- uint16_t sadb_alg_maxbits;
- uint16_t sadb_alg_reserved;
-#endif
-errlab:
- return error;
-}
-
-int
-pfkey_spirange_build(struct sadb_ext** pfkey_ext,
- uint16_t exttype,
- uint32_t min, /* in network order */
- uint32_t max) /* in network order */
-{
- int error = 0;
- struct sadb_spirange *pfkey_spirange = (struct sadb_spirange *)*pfkey_ext;
-
- /* sanity checks... */
- if (pfkey_spirange) {
- DEBUGGING(
- "pfkey_spirange_build: "
- "why is pfkey_spirange already pointing to something?\n");
- SENDERR(EINVAL);
- }
-
- if (ntohl(max) < ntohl(min)) {
- DEBUGGING(
- "pfkey_spirange_build: "
- "minspi=%08x must be < maxspi=%08x.\n",
- ntohl(min),
- ntohl(max));
- SENDERR(EINVAL);
- }
-
- if (ntohl(min) <= 255) {
- DEBUGGING(
- "pfkey_spirange_build: "
- "minspi=%08x must be > 255.\n",
- ntohl(min));
- SENDERR(EEXIST);
- }
-
- pfkey_spirange = (struct sadb_spirange*)
- MALLOC(sizeof(struct sadb_spirange));
- *pfkey_ext = (struct sadb_ext*)pfkey_spirange;
-
- if (pfkey_spirange == NULL) {
- DEBUGGING(
- "pfkey_spirange_build: "
- "memory allocation failed\n");
- SENDERR(ENOMEM);
- }
- memset(pfkey_spirange,
- 0,
- sizeof(struct sadb_spirange));
-
- pfkey_spirange->sadb_spirange_len = sizeof(struct sadb_spirange) / IPSEC_PFKEYv2_ALIGN;
-
- pfkey_spirange->sadb_spirange_exttype = SADB_EXT_SPIRANGE;
- pfkey_spirange->sadb_spirange_min = min;
- pfkey_spirange->sadb_spirange_max = max;
- pfkey_spirange->sadb_spirange_reserved = 0;
- errlab:
- return error;
-}
-
-int
-pfkey_x_kmprivate_build(struct sadb_ext** pfkey_ext)
-{
- int error = 0;
- struct sadb_x_kmprivate *pfkey_x_kmprivate = (struct sadb_x_kmprivate *)*pfkey_ext;
-
- /* sanity checks... */
- if (pfkey_x_kmprivate) {
- DEBUGGING(
- "pfkey_x_kmprivate_build: "
- "why is pfkey_x_kmprivate already pointing to something?\n");
- SENDERR(EINVAL);
- }
-
- pfkey_x_kmprivate->sadb_x_kmprivate_reserved = 0;
-
- DEBUGGING(
- "pfkey_x_kmprivate_build: "
- "Sorry, I can't build exttype=%d yet.\n",
- (*pfkey_ext)->sadb_ext_type);
- SENDERR(EINVAL); /* don't process these yet */
-
- pfkey_x_kmprivate = (struct sadb_x_kmprivate*)
- MALLOC(sizeof(struct sadb_x_kmprivate));
- *pfkey_ext = (struct sadb_ext*)pfkey_x_kmprivate;
-
- if (pfkey_x_kmprivate == NULL) {
- DEBUGGING(
- "pfkey_x_kmprivate_build: "
- "memory allocation failed\n");
- SENDERR(ENOMEM);
- }
- memset(pfkey_x_kmprivate,
- 0,
- sizeof(struct sadb_x_kmprivate));
-
- pfkey_x_kmprivate->sadb_x_kmprivate_len =
- sizeof(struct sadb_x_kmprivate) / IPSEC_PFKEYv2_ALIGN;
-
- pfkey_x_kmprivate->sadb_x_kmprivate_exttype = SADB_X_EXT_KMPRIVATE;
- pfkey_x_kmprivate->sadb_x_kmprivate_reserved = 0;
-errlab:
- return error;
-}
-
-int
-pfkey_x_satype_build(struct sadb_ext** pfkey_ext,
- uint8_t satype)
-{
- int error = 0;
- int i;
- struct sadb_x_satype *pfkey_x_satype = (struct sadb_x_satype *)*pfkey_ext;
-
- DEBUGGING(
- "pfkey_x_satype_build:\n");
- /* sanity checks... */
- if (pfkey_x_satype) {
- DEBUGGING(
- "pfkey_x_satype_build: "
- "why is pfkey_x_satype already pointing to something?\n");
- SENDERR(EINVAL);
- }
-
- if (!satype) {
- DEBUGGING(
- "pfkey_x_satype_build: "
- "SA type not set, must be non-zero.\n");
- SENDERR(EINVAL);
- }
-
- if (satype > SADB_SATYPE_MAX) {
- DEBUGGING(
- "pfkey_x_satype_build: "
- "satype %d > max %d\n",
- satype, SADB_SATYPE_MAX);
- SENDERR(EINVAL);
- }
-
- pfkey_x_satype = (struct sadb_x_satype*)
- MALLOC(sizeof(struct sadb_x_satype));
-
- *pfkey_ext = (struct sadb_ext*)pfkey_x_satype;
-
- if (pfkey_x_satype == NULL) {
- DEBUGGING(
- "pfkey_x_satype_build: "
- "memory allocation failed\n");
- SENDERR(ENOMEM);
- }
- memset(pfkey_x_satype,
- 0,
- sizeof(struct sadb_x_satype));
-
- pfkey_x_satype->sadb_x_satype_len = sizeof(struct sadb_x_satype) / IPSEC_PFKEYv2_ALIGN;
-
- pfkey_x_satype->sadb_x_satype_exttype = SADB_X_EXT_SATYPE2;
- pfkey_x_satype->sadb_x_satype_satype = satype;
- for (i=0; i<3; i++) {
- pfkey_x_satype->sadb_x_satype_reserved[i] = 0;
- }
-
-errlab:
- return error;
-}
-
-int
-pfkey_x_debug_build(struct sadb_ext** pfkey_ext,
- uint32_t tunnel,
- uint32_t netlink,
- uint32_t xform,
- uint32_t eroute,
- uint32_t spi,
- uint32_t radij,
- uint32_t esp,
- uint32_t ah,
- uint32_t rcv,
- uint32_t pfkey,
- uint32_t ipcomp,
- uint32_t verbose)
-{
- int error = 0;
- int i;
- struct sadb_x_debug *pfkey_x_debug = (struct sadb_x_debug *)*pfkey_ext;
-
- DEBUGGING(
- "pfkey_x_debug_build:\n");
- /* sanity checks... */
- if (pfkey_x_debug) {
- DEBUGGING(
- "pfkey_x_debug_build: "
- "why is pfkey_x_debug already pointing to something?\n");
- SENDERR(EINVAL);
- }
-
- DEBUGGING(
- "pfkey_x_debug_build: "
- "tunnel=%x netlink=%x xform=%x eroute=%x spi=%x radij=%x esp=%x ah=%x rcv=%x pfkey=%x ipcomp=%x verbose=%x?\n",
- tunnel, netlink, xform, eroute, spi, radij, esp, ah, rcv, pfkey, ipcomp, verbose);
-
- pfkey_x_debug = (struct sadb_x_debug*)
- MALLOC(sizeof(struct sadb_x_debug));
- *pfkey_ext = (struct sadb_ext*)pfkey_x_debug;
-
- if (pfkey_x_debug == NULL) {
- DEBUGGING(
- "pfkey_x_debug_build: "
- "memory allocation failed\n");
- SENDERR(ENOMEM);
- }
-#if 0
- memset(pfkey_x_debug,
- 0,
- sizeof(struct sadb_x_debug));
-#endif
-
- pfkey_x_debug->sadb_x_debug_len = sizeof(struct sadb_x_debug) / IPSEC_PFKEYv2_ALIGN;
- pfkey_x_debug->sadb_x_debug_exttype = SADB_X_EXT_DEBUG;
-
- pfkey_x_debug->sadb_x_debug_tunnel = tunnel;
- pfkey_x_debug->sadb_x_debug_netlink = netlink;
- pfkey_x_debug->sadb_x_debug_xform = xform;
- pfkey_x_debug->sadb_x_debug_eroute = eroute;
- pfkey_x_debug->sadb_x_debug_spi = spi;
- pfkey_x_debug->sadb_x_debug_radij = radij;
- pfkey_x_debug->sadb_x_debug_esp = esp;
- pfkey_x_debug->sadb_x_debug_ah = ah;
- pfkey_x_debug->sadb_x_debug_rcv = rcv;
- pfkey_x_debug->sadb_x_debug_pfkey = pfkey;
- pfkey_x_debug->sadb_x_debug_ipcomp = ipcomp;
- pfkey_x_debug->sadb_x_debug_verbose = verbose;
-
- for (i=0; i<4; i++) {
- pfkey_x_debug->sadb_x_debug_reserved[i] = 0;
- }
-
-errlab:
- return error;
-}
-
-int
-pfkey_x_nat_t_type_build(struct sadb_ext** pfkey_ext,
- uint8_t type)
-{
- int error = 0;
- int i;
- struct sadb_x_nat_t_type *pfkey_x_nat_t_type = (struct sadb_x_nat_t_type *)*pfkey_ext;
-
- DEBUGGING(
- "pfkey_x_nat_t_type_build:\n");
- /* sanity checks... */
- if (pfkey_x_nat_t_type) {
- DEBUGGING(
- "pfkey_x_nat_t_type_build: "
- "why is pfkey_x_nat_t_type already pointing to something?\n");
- SENDERR(EINVAL);
- }
-
- DEBUGGING(
- "pfkey_x_nat_t_type_build: "
- "type=%d\n", type);
-
- pfkey_x_nat_t_type = (struct sadb_x_nat_t_type*)
- MALLOC(sizeof(struct sadb_x_nat_t_type));
-
- *pfkey_ext = (struct sadb_ext*)pfkey_x_nat_t_type;
- if (pfkey_x_nat_t_type == NULL) {
- DEBUGGING(
- "pfkey_x_nat_t_type_build: "
- "memory allocation failed\n");
- SENDERR(ENOMEM);
- }
-
- pfkey_x_nat_t_type->sadb_x_nat_t_type_len = sizeof(struct sadb_x_nat_t_type) / IPSEC_PFKEYv2_ALIGN;
- pfkey_x_nat_t_type->sadb_x_nat_t_type_exttype = SADB_X_EXT_NAT_T_TYPE;
- pfkey_x_nat_t_type->sadb_x_nat_t_type_type = type;
- for (i=0; i<3; i++) {
- pfkey_x_nat_t_type->sadb_x_nat_t_type_reserved[i] = 0;
- }
-
-errlab:
- return error;
-}
-
-int
-pfkey_x_nat_t_port_build(struct sadb_ext** pfkey_ext,
- uint16_t exttype,
- uint16_t port)
-{
- int error = 0;
- struct sadb_x_nat_t_port *pfkey_x_nat_t_port = (struct sadb_x_nat_t_port *)*pfkey_ext;
-
- DEBUGGING(
- "pfkey_x_nat_t_port_build:\n");
- /* sanity checks... */
- if (pfkey_x_nat_t_port) {
- DEBUGGING(
- "pfkey_x_nat_t_port_build: "
- "why is pfkey_x_nat_t_port already pointing to something?\n");
- SENDERR(EINVAL);
- }
-
- switch (exttype) {
- case SADB_X_EXT_NAT_T_SPORT:
- case SADB_X_EXT_NAT_T_DPORT:
- break;
- default:
- DEBUGGING(
- "pfkey_nat_t_port_build: "
- "unrecognised ext_type=%d.\n",
- exttype);
- SENDERR(EINVAL);
- }
-
- DEBUGGING(
- "pfkey_x_nat_t_port_build: "
- "ext=%d, port=%d\n", exttype, port);
-
- pfkey_x_nat_t_port = (struct sadb_x_nat_t_port*)
- MALLOC(sizeof(struct sadb_x_nat_t_port));
- *pfkey_ext = (struct sadb_ext*)pfkey_x_nat_t_port;
-
- if (pfkey_x_nat_t_port == NULL) {
- DEBUGGING(
- "pfkey_x_nat_t_port_build: "
- "memory allocation failed\n");
- SENDERR(ENOMEM);
- }
-
- pfkey_x_nat_t_port->sadb_x_nat_t_port_len = sizeof(struct sadb_x_nat_t_port) / IPSEC_PFKEYv2_ALIGN;
- pfkey_x_nat_t_port->sadb_x_nat_t_port_exttype = exttype;
- pfkey_x_nat_t_port->sadb_x_nat_t_port_port = port;
- pfkey_x_nat_t_port->sadb_x_nat_t_port_reserved = 0;
-
-errlab:
- return error;
-}
-
-int pfkey_x_protocol_build(struct sadb_ext **pfkey_ext,
- uint8_t protocol)
-{
- int error = 0;
- struct sadb_protocol * p = (struct sadb_protocol *)*pfkey_ext;
- DEBUGGING("pfkey_x_protocol_build: protocol=%u\n", protocol);
- /* sanity checks... */
- if (p != 0) {
- DEBUGGING("pfkey_x_protocol_build: bogus protocol pointer\n");
- SENDERR(EINVAL);
- }
- if ((p = (struct sadb_protocol*)MALLOC(sizeof(*p))) == 0) {
- DEBUGGING("pfkey_build: memory allocation failed\n");
- SENDERR(ENOMEM);
- }
- *pfkey_ext = (struct sadb_ext *)p;
- p->sadb_protocol_len = sizeof(*p) / sizeof(uint64_t);
- p->sadb_protocol_exttype = SADB_X_EXT_PROTOCOL;
- p->sadb_protocol_proto = protocol;
- p->sadb_protocol_flags = 0;
- p->sadb_protocol_reserved2 = 0;
- errlab:
- return error;
-}
-
-
-#if I_DONT_THINK_THIS_WILL_BE_USEFUL
-int (*ext_default_builders[SADB_EXT_MAX +1])(struct sadb_msg*, struct sadb_ext*)
- =
-{
- NULL, /* pfkey_msg_build, */
- pfkey_sa_build,
- pfkey_lifetime_build,
- pfkey_lifetime_build,
- pfkey_lifetime_build,
- pfkey_address_build,
- pfkey_address_build,
- pfkey_address_build,
- pfkey_key_build,
- pfkey_key_build,
- pfkey_ident_build,
- pfkey_ident_build,
- pfkey_sens_build,
- pfkey_prop_build,
- pfkey_supported_build,
- pfkey_supported_build,
- pfkey_spirange_build,
- pfkey_x_kmprivate_build,
- pfkey_x_satype_build,
- pfkey_sa_build,
- pfkey_address_build,
- pfkey_address_build,
- pfkey_address_build,
- pfkey_address_build,
- pfkey_address_build,
- pfkey_x_ext_debug_build
-};
-#endif
-
-int
-pfkey_msg_build(struct sadb_msg **pfkey_msg, struct sadb_ext *extensions[], int dir)
-{
- int error = 0;
- unsigned ext;
- unsigned total_size;
- struct sadb_ext *pfkey_ext;
- int extensions_seen = 0;
- struct sadb_ext *extensions_check[SADB_EXT_MAX + 1];
-
- if (!extensions[0]) {
- DEBUGGING(
- "pfkey_msg_build: "
- "extensions[0] must be specified (struct sadb_msg).\n");
- SENDERR(EINVAL);
- }
-
- total_size = sizeof(struct sadb_msg) / IPSEC_PFKEYv2_ALIGN;
- for (ext = 1; ext <= SADB_EXT_MAX; ext++) {
- if(extensions[ext]) {
- total_size += (extensions[ext])->sadb_ext_len;
- }
- }
-
- if (!(*pfkey_msg = (struct sadb_msg*)MALLOC(total_size * IPSEC_PFKEYv2_ALIGN))) {
- DEBUGGING(
- "pfkey_msg_build: "
- "memory allocation failed\n");
- SENDERR(ENOMEM);
- }
-
- DEBUGGING(
- "pfkey_msg_build: "
- "pfkey_msg=0p%p allocated %lu bytes, &(extensions[0])=0p%p\n",
- *pfkey_msg,
- (unsigned long)(total_size * IPSEC_PFKEYv2_ALIGN),
- &(extensions[0]));
- memcpy(*pfkey_msg,
- extensions[0],
- sizeof(struct sadb_msg));
- (*pfkey_msg)->sadb_msg_len = total_size;
- (*pfkey_msg)->sadb_msg_reserved = 0;
- extensions_seen = 1 ;
-
- pfkey_ext = (struct sadb_ext*)(((char*)(*pfkey_msg)) + sizeof(struct sadb_msg));
-
- for (ext = 1; ext <= SADB_EXT_MAX; ext++) {
- /* copy from extension[ext] to buffer */
- if (extensions[ext]) {
- /* Is this type of extension permitted for this type of message? */
- if (!(extensions_bitmaps[dir][EXT_BITS_PERM][(*pfkey_msg)->sadb_msg_type] &
- 1<<ext)) {
- DEBUGGING(
- "pfkey_msg_build: "
- "ext type %d not permitted, exts_perm=%08x, 1<<type=%08x\n",
- ext,
- extensions_bitmaps[dir][EXT_BITS_PERM][(*pfkey_msg)->sadb_msg_type],
- 1<<ext);
- SENDERR(EINVAL);
- }
- DEBUGGING(
- "pfkey_msg_build: "
- "copying %lu bytes from extensions[%u]=0p%p to=0p%p\n",
- (unsigned long)(extensions[ext]->sadb_ext_len * IPSEC_PFKEYv2_ALIGN),
- ext,
- extensions[ext],
- pfkey_ext);
- memcpy(pfkey_ext,
- extensions[ext],
- (extensions[ext])->sadb_ext_len * IPSEC_PFKEYv2_ALIGN);
- {
- char *pfkey_ext_c = (char *)pfkey_ext;
-
- pfkey_ext_c += (extensions[ext])->sadb_ext_len * IPSEC_PFKEYv2_ALIGN;
- pfkey_ext = (struct sadb_ext *)pfkey_ext_c;
- }
- /* Mark that we have seen this extension and remember the header location */
- extensions_seen |= ( 1 << ext );
- }
- }
-
- /* check required extensions */
- DEBUGGING(
- "pfkey_msg_build: "
- "extensions permitted=%08x, seen=%08x, required=%08x.\n",
- extensions_bitmaps[dir][EXT_BITS_PERM][(*pfkey_msg)->sadb_msg_type],
- extensions_seen,
- extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]);
-
- if ((extensions_seen &
- extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]) !=
- extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]) {
- DEBUGGING(
- "pfkey_msg_build: "
- "required extensions missing:%08x.\n",
- extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type] -
- (extensions_seen &
- extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]) );
- SENDERR(EINVAL);
- }
-
- error = pfkey_msg_parse(*pfkey_msg, NULL, extensions_check, dir);
- if (error) {
- DEBUGGING(
- "pfkey_msg_build: "
- "Trouble parsing newly built pfkey message, error=%d.\n",
- error);
- SENDERR(-error);
- }
-
-errlab:
-
- return error;
-}
diff --git a/src/libfreeswan/pfkey_v2_debug.c b/src/libfreeswan/pfkey_v2_debug.c
deleted file mode 100644
index 0762d8f2b..000000000
--- a/src/libfreeswan/pfkey_v2_debug.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * @(#) pfkey version 2 debugging messages
- *
- * Copyright (C) 2001 Richard Guy Briggs <rgb@freeswan.org>
- * and Michael Richardson <mcr@freeswan.org>
- *
- * 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 <sys/types.h>
-# include <errno.h>
-
-#include "freeswan.h"
-#include "pfkeyv2.h"
-#include "pfkey.h"
-
-/*
- * This file provides ASCII translations of PF_KEY magic numbers.
- *
- */
-
-static char *pfkey_sadb_ext_strings[]={
- "reserved", /* SADB_EXT_RESERVED 0 */
- "security-association", /* SADB_EXT_SA 1 */
- "lifetime-current", /* SADB_EXT_LIFETIME_CURRENT 2 */
- "lifetime-hard", /* SADB_EXT_LIFETIME_HARD 3 */
- "lifetime-soft", /* SADB_EXT_LIFETIME_SOFT 4 */
- "source-address", /* SADB_EXT_ADDRESS_SRC 5 */
- "destination-address", /* SADB_EXT_ADDRESS_DST 6 */
- "proxy-address", /* SADB_EXT_ADDRESS_PROXY 7 */
- "authentication-key", /* SADB_EXT_KEY_AUTH 8 */
- "cipher-key", /* SADB_EXT_KEY_ENCRYPT 9 */
- "source-identity", /* SADB_EXT_IDENTITY_SRC 10 */
- "destination-identity", /* SADB_EXT_IDENTITY_DST 11 */
- "sensitivity-label", /* SADB_EXT_SENSITIVITY 12 */
- "proposal", /* SADB_EXT_PROPOSAL 13 */
- "supported-auth", /* SADB_EXT_SUPPORTED_AUTH 14 */
- "supported-cipher", /* SADB_EXT_SUPPORTED_ENCRYPT 15 */
- "spi-range", /* SADB_EXT_SPIRANGE 16 */
- "X-kmpprivate", /* SADB_X_EXT_KMPRIVATE 17 */
- "X-satype2", /* SADB_X_EXT_SATYPE2 18 */
- "X-security-association", /* SADB_X_EXT_SA2 19 */
- "X-destination-address2", /* SADB_X_EXT_ADDRESS_DST2 20 */
- "X-source-flow-address", /* SADB_X_EXT_ADDRESS_SRC_FLOW 21 */
- "X-dest-flow-address", /* SADB_X_EXT_ADDRESS_DST_FLOW 22 */
- "X-source-mask", /* SADB_X_EXT_ADDRESS_SRC_MASK 23 */
- "X-dest-mask", /* SADB_X_EXT_ADDRESS_DST_MASK 24 */
- "X-set-debug", /* SADB_X_EXT_DEBUG 25 */
- "X-protocol", /* SADB_X_EXT_PROTOCOL 26 */
- "X-NAT-T-type", /* SADB_X_EXT_NAT_T_TYPE 27 */
- "X-NAT-T-sport", /* SADB_X_EXT_NAT_T_SPORT 28 */
- "X-NAT-T-dport", /* SADB_X_EXT_NAT_T_DPORT 29 */
- "X-NAT-T-OA", /* SADB_X_EXT_NAT_T_OA 30 */
-};
-
-const char *
-pfkey_v2_sadb_ext_string(int ext)
-{
- if(ext <= SADB_EXT_MAX) {
- return pfkey_sadb_ext_strings[ext];
- } else {
- return "unknown-ext";
- }
-}
-
-
-static char *pfkey_sadb_type_strings[]={
- "reserved", /* SADB_RESERVED */
- "getspi", /* SADB_GETSPI */
- "update", /* SADB_UPDATE */
- "add", /* SADB_ADD */
- "delete", /* SADB_DELETE */
- "get", /* SADB_GET */
- "acquire", /* SADB_ACQUIRE */
- "register", /* SADB_REGISTER */
- "expire", /* SADB_EXPIRE */
- "flush", /* SADB_FLUSH */
- "dump", /* SADB_DUMP */
- "x-promisc", /* SADB_X_PROMISC */
- "x-pchange", /* SADB_X_PCHANGE */
- "x-groupsa", /* SADB_X_GRPSA */
- "x-addflow(eroute)", /* SADB_X_ADDFLOW */
- "x-delflow(eroute)", /* SADB_X_DELFLOW */
- "x-debug", /* SADB_X_DEBUG */
- "x-nat-t-new-mapping", /* SADB_X_NAT_T_NEW_MAPPING */
-};
-
-const char *
-pfkey_v2_sadb_type_string(int sadb_type)
-{
- if(sadb_type <= SADB_MAX) {
- return pfkey_sadb_type_strings[sadb_type];
- } else {
- return "unknown-sadb-type";
- }
-}
diff --git a/src/libfreeswan/pfkey_v2_ext_bits.c b/src/libfreeswan/pfkey_v2_ext_bits.c
deleted file mode 100644
index 49b4aa567..000000000
--- a/src/libfreeswan/pfkey_v2_ext_bits.c
+++ /dev/null
@@ -1,692 +0,0 @@
-/*
- * RFC2367 PF_KEYv2 Key management API message parser
- * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs.
- *
- * 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.
- */
-
-/*
- * Template from klips/net/ipsec/ipsec/ipsec_parse.c.
- */
-
-char pfkey_v2_ext_bits_c_version[] = "";
-
-# include <sys/types.h>
-# include <errno.h>
-
-#include <freeswan.h>
-#include <pfkeyv2.h>
-#include <pfkey.h>
-
-unsigned int extensions_bitmaps[2/*in/out*/][2/*perm/req*/][SADB_MAX + 1/*ext*/] = {
-
-/* INBOUND EXTENSIONS */
-{
-
-/* PERMITTED IN */
-{
-/* SADB_RESERVED */
-0
-,
-/* SADB_GETSPI */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_EXT_ADDRESS_PROXY
-| 1<<SADB_EXT_SPIRANGE
-,
-/* SADB_UPDATE */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_LIFETIME_CURRENT
-| 1<<SADB_EXT_LIFETIME_HARD
-| 1<<SADB_EXT_LIFETIME_SOFT
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_EXT_ADDRESS_PROXY
-| 1<<SADB_EXT_KEY_AUTH
-| 1<<SADB_EXT_KEY_ENCRYPT
-| 1<<SADB_EXT_IDENTITY_SRC
-| 1<<SADB_EXT_IDENTITY_DST
-| 1<<SADB_EXT_SENSITIVITY
-| 1<<SADB_X_EXT_NAT_T_SPORT
-| 1<<SADB_X_EXT_NAT_T_DPORT
-,
-/* SADB_ADD */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_LIFETIME_HARD
-| 1<<SADB_EXT_LIFETIME_SOFT
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_EXT_ADDRESS_PROXY
-| 1<<SADB_EXT_KEY_AUTH
-| 1<<SADB_EXT_KEY_ENCRYPT
-| 1<<SADB_EXT_IDENTITY_SRC
-| 1<<SADB_EXT_IDENTITY_DST
-| 1<<SADB_EXT_SENSITIVITY
-| 1<<SADB_X_EXT_NAT_T_TYPE
-| 1<<SADB_X_EXT_NAT_T_SPORT
-| 1<<SADB_X_EXT_NAT_T_DPORT
-| 1<<SADB_X_EXT_NAT_T_OA
-,
-/* SADB_DELETE */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-,
-/* SADB_GET */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-,
-/* SADB_ACQUIRE */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_EXT_ADDRESS_PROXY
-| 1<<SADB_EXT_IDENTITY_SRC
-| 1<<SADB_EXT_IDENTITY_DST
-| 1<<SADB_EXT_SENSITIVITY
-| 1<<SADB_EXT_PROPOSAL
-,
-/* SADB_REGISTER */
-1<<SADB_EXT_RESERVED
-,
-/* SADB_EXPIRE */
-0
-,
-/* SADB_FLUSH */
-1<<SADB_EXT_RESERVED
-,
-/* SADB_DUMP */
-1<<SADB_EXT_RESERVED
-,
-/* SADB_X_PROMISC */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_LIFETIME_CURRENT
-| 1<<SADB_EXT_LIFETIME_HARD
-| 1<<SADB_EXT_LIFETIME_SOFT
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_EXT_ADDRESS_PROXY
-| 1<<SADB_EXT_KEY_AUTH
-| 1<<SADB_EXT_KEY_ENCRYPT
-| 1<<SADB_EXT_IDENTITY_SRC
-| 1<<SADB_EXT_IDENTITY_DST
-| 1<<SADB_EXT_SENSITIVITY
-| 1<<SADB_EXT_PROPOSAL
-| 1<<SADB_EXT_SUPPORTED_AUTH
-| 1<<SADB_EXT_SUPPORTED_ENCRYPT
-| 1<<SADB_EXT_SPIRANGE
-| 1<<SADB_X_EXT_KMPRIVATE
-| 1<<SADB_X_EXT_SATYPE2
-| 1<<SADB_X_EXT_SA2
-| 1<<SADB_X_EXT_ADDRESS_DST2
-,
-/* SADB_X_PCHANGE */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_LIFETIME_CURRENT
-| 1<<SADB_EXT_LIFETIME_HARD
-| 1<<SADB_EXT_LIFETIME_SOFT
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_EXT_ADDRESS_PROXY
-| 1<<SADB_EXT_KEY_AUTH
-| 1<<SADB_EXT_KEY_ENCRYPT
-| 1<<SADB_EXT_IDENTITY_SRC
-| 1<<SADB_EXT_IDENTITY_DST
-| 1<<SADB_EXT_SENSITIVITY
-| 1<<SADB_EXT_PROPOSAL
-| 1<<SADB_EXT_SUPPORTED_AUTH
-| 1<<SADB_EXT_SUPPORTED_ENCRYPT
-| 1<<SADB_EXT_SPIRANGE
-| 1<<SADB_X_EXT_KMPRIVATE
-| 1<<SADB_X_EXT_SATYPE2
-| 1<<SADB_X_EXT_SA2
-| 1<<SADB_X_EXT_ADDRESS_DST2
-,
-/* SADB_X_GRPSA */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_X_EXT_SATYPE2
-| 1<<SADB_X_EXT_SA2
-| 1<<SADB_X_EXT_ADDRESS_DST2
-,
-/* SADB_X_ADDFLOW */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
-| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
-| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
-| 1<<SADB_X_EXT_ADDRESS_DST_MASK
-| 1<<SADB_EXT_IDENTITY_SRC
-| 1<<SADB_EXT_IDENTITY_DST
-| 1<<SADB_X_EXT_PROTOCOL
-,
-/* SADB_X_DELFLOW */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
-| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
-| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
-| 1<<SADB_X_EXT_ADDRESS_DST_MASK
-| 1<<SADB_EXT_IDENTITY_SRC
-| 1<<SADB_EXT_IDENTITY_DST
-| 1<<SADB_X_EXT_PROTOCOL
-,
-/* SADB_X_DEBUG */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_X_EXT_DEBUG
-,
-/* SADB_X_NAT_T_NEW_MAPPING */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_X_EXT_NAT_T_SPORT
-| 1<<SADB_X_EXT_NAT_T_DPORT
-},
-
-/* REQUIRED IN */
-{
-/* SADB_RESERVED */
-0
-,
-/* SADB_GETSPI */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_EXT_SPIRANGE
-,
-/* SADB_UPDATE */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-/*| 1<<SADB_EXT_KEY_AUTH*/
-/*| 1<<SADB_EXT_KEY_ENCRYPT*/
-,
-/* SADB_ADD */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-/*| 1<<SADB_EXT_KEY_AUTH*/
-/*| 1<<SADB_EXT_KEY_ENCRYPT*/
-,
-/* SADB_DELETE */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-,
-/* SADB_GET */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-,
-/* SADB_ACQUIRE */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_EXT_PROPOSAL
-,
-/* SADB_REGISTER */
-1<<SADB_EXT_RESERVED
-,
-/* SADB_EXPIRE */
-0
-,
-/* SADB_FLUSH */
-1<<SADB_EXT_RESERVED
-,
-/* SADB_DUMP */
-1<<SADB_EXT_RESERVED
-,
-/* SADB_X_PROMISC */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_LIFETIME_CURRENT
-| 1<<SADB_EXT_LIFETIME_HARD
-| 1<<SADB_EXT_LIFETIME_SOFT
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_EXT_ADDRESS_PROXY
-| 1<<SADB_EXT_KEY_AUTH
-| 1<<SADB_EXT_KEY_ENCRYPT
-| 1<<SADB_EXT_IDENTITY_SRC
-| 1<<SADB_EXT_IDENTITY_DST
-| 1<<SADB_EXT_SENSITIVITY
-| 1<<SADB_EXT_PROPOSAL
-| 1<<SADB_EXT_SUPPORTED_AUTH
-| 1<<SADB_EXT_SUPPORTED_ENCRYPT
-| 1<<SADB_EXT_SPIRANGE
-| 1<<SADB_X_EXT_KMPRIVATE
-| 1<<SADB_X_EXT_SATYPE2
-| 1<<SADB_X_EXT_SA2
-| 1<<SADB_X_EXT_ADDRESS_DST2
-,
-/* SADB_X_PCHANGE */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_LIFETIME_CURRENT
-| 1<<SADB_EXT_LIFETIME_HARD
-| 1<<SADB_EXT_LIFETIME_SOFT
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_EXT_ADDRESS_PROXY
-| 1<<SADB_EXT_KEY_AUTH
-| 1<<SADB_EXT_KEY_ENCRYPT
-| 1<<SADB_EXT_IDENTITY_SRC
-| 1<<SADB_EXT_IDENTITY_DST
-| 1<<SADB_EXT_SENSITIVITY
-| 1<<SADB_EXT_PROPOSAL
-| 1<<SADB_EXT_SUPPORTED_AUTH
-| 1<<SADB_EXT_SUPPORTED_ENCRYPT
-| 1<<SADB_EXT_SPIRANGE
-| 1<<SADB_X_EXT_KMPRIVATE
-| 1<<SADB_X_EXT_SATYPE2
-| 1<<SADB_X_EXT_SA2
-| 1<<SADB_X_EXT_ADDRESS_DST2
-,
-/* SADB_X_GRPSA */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_ADDRESS_DST
-/*| 1<<SADB_X_EXT_SATYPE2*/
-/*| 1<<SADB_X_EXT_SA2*/
-/*| 1<<SADB_X_EXT_ADDRESS_DST2*/
-,
-/* SADB_X_ADDFLOW */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
-| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
-| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
-| 1<<SADB_X_EXT_ADDRESS_DST_MASK
-,
-/* SADB_X_DELFLOW */
-1<<SADB_EXT_RESERVED
-/*| 1<<SADB_EXT_SA*/
-#if 0 /* SADB_X_CLREROUTE doesn't need all these... */
-| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
-| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
-| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
-| 1<<SADB_X_EXT_ADDRESS_DST_MASK
-#endif
-,
-/* SADB_X_DEBUG */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_X_EXT_DEBUG
-,
-/* SADB_X_NAT_T_NEW_MAPPING */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_X_EXT_NAT_T_SPORT
-| 1<<SADB_X_EXT_NAT_T_DPORT
-}
-
-},
-
-/* OUTBOUND EXTENSIONS */
-{
-
-/* PERMITTED OUT */
-{
-/* SADB_RESERVED */
-0
-,
-/* SADB_GETSPI */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-,
-/* SADB_UPDATE */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_LIFETIME_CURRENT
-| 1<<SADB_EXT_LIFETIME_HARD
-| 1<<SADB_EXT_LIFETIME_SOFT
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_EXT_ADDRESS_PROXY
-| 1<<SADB_EXT_IDENTITY_SRC
-| 1<<SADB_EXT_IDENTITY_DST
-| 1<<SADB_EXT_SENSITIVITY
-,
-/* SADB_ADD */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_LIFETIME_HARD
-| 1<<SADB_EXT_LIFETIME_SOFT
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_EXT_IDENTITY_SRC
-| 1<<SADB_EXT_IDENTITY_DST
-| 1<<SADB_EXT_SENSITIVITY
-| 1<<SADB_X_EXT_NAT_T_TYPE
-| 1<<SADB_X_EXT_NAT_T_SPORT
-| 1<<SADB_X_EXT_NAT_T_DPORT
-| 1<<SADB_X_EXT_NAT_T_OA
-,
-/* SADB_DELETE */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-,
-/* SADB_GET */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_LIFETIME_CURRENT
-| 1<<SADB_EXT_LIFETIME_HARD
-| 1<<SADB_EXT_LIFETIME_SOFT
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_EXT_ADDRESS_PROXY
-| 1<<SADB_EXT_KEY_AUTH
-| 1<<SADB_EXT_KEY_ENCRYPT
-| 1<<SADB_EXT_IDENTITY_SRC
-| 1<<SADB_EXT_IDENTITY_DST
-| 1<<SADB_EXT_SENSITIVITY
-,
-/* SADB_ACQUIRE */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_EXT_ADDRESS_PROXY
-| 1<<SADB_EXT_IDENTITY_SRC
-| 1<<SADB_EXT_IDENTITY_DST
-| 1<<SADB_EXT_SENSITIVITY
-| 1<<SADB_EXT_PROPOSAL
-,
-/* SADB_REGISTER */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SUPPORTED_AUTH
-| 1<<SADB_EXT_SUPPORTED_ENCRYPT
-,
-/* SADB_EXPIRE */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_LIFETIME_CURRENT
-| 1<<SADB_EXT_LIFETIME_HARD
-| 1<<SADB_EXT_LIFETIME_SOFT
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-,
-/* SADB_FLUSH */
-1<<SADB_EXT_RESERVED
-,
-/* SADB_DUMP */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_LIFETIME_CURRENT
-| 1<<SADB_EXT_LIFETIME_HARD
-| 1<<SADB_EXT_LIFETIME_SOFT
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_EXT_ADDRESS_PROXY
-| 1<<SADB_EXT_KEY_AUTH
-| 1<<SADB_EXT_KEY_ENCRYPT
-| 1<<SADB_EXT_IDENTITY_SRC
-| 1<<SADB_EXT_IDENTITY_DST
-| 1<<SADB_EXT_SENSITIVITY
-,
-/* SADB_X_PROMISC */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_LIFETIME_CURRENT
-| 1<<SADB_EXT_LIFETIME_HARD
-| 1<<SADB_EXT_LIFETIME_SOFT
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_EXT_ADDRESS_PROXY
-| 1<<SADB_EXT_KEY_AUTH
-| 1<<SADB_EXT_KEY_ENCRYPT
-| 1<<SADB_EXT_IDENTITY_SRC
-| 1<<SADB_EXT_IDENTITY_DST
-| 1<<SADB_EXT_SENSITIVITY
-| 1<<SADB_EXT_PROPOSAL
-| 1<<SADB_EXT_SUPPORTED_AUTH
-| 1<<SADB_EXT_SUPPORTED_ENCRYPT
-| 1<<SADB_EXT_SPIRANGE
-| 1<<SADB_X_EXT_KMPRIVATE
-| 1<<SADB_X_EXT_SATYPE2
-| 1<<SADB_X_EXT_SA2
-| 1<<SADB_X_EXT_ADDRESS_DST2
-,
-/* SADB_X_PCHANGE */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_LIFETIME_CURRENT
-| 1<<SADB_EXT_LIFETIME_HARD
-| 1<<SADB_EXT_LIFETIME_SOFT
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_EXT_ADDRESS_PROXY
-| 1<<SADB_EXT_KEY_AUTH
-| 1<<SADB_EXT_KEY_ENCRYPT
-| 1<<SADB_EXT_IDENTITY_SRC
-| 1<<SADB_EXT_IDENTITY_DST
-| 1<<SADB_EXT_SENSITIVITY
-| 1<<SADB_EXT_PROPOSAL
-| 1<<SADB_EXT_SUPPORTED_AUTH
-| 1<<SADB_EXT_SUPPORTED_ENCRYPT
-| 1<<SADB_EXT_SPIRANGE
-| 1<<SADB_X_EXT_KMPRIVATE
-| 1<<SADB_X_EXT_SATYPE2
-| 1<<SADB_X_EXT_SA2
-| 1<<SADB_X_EXT_ADDRESS_DST2
-,
-/* SADB_X_GRPSA */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_X_EXT_SATYPE2
-| 1<<SADB_X_EXT_SA2
-| 1<<SADB_X_EXT_ADDRESS_DST2
-,
-/* SADB_X_ADDFLOW */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
-| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
-| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
-| 1<<SADB_X_EXT_ADDRESS_DST_MASK
-| 1<<SADB_X_EXT_PROTOCOL
-,
-/* SADB_X_DELFLOW */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
-| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
-| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
-| 1<<SADB_X_EXT_ADDRESS_DST_MASK
-| 1<<SADB_X_EXT_PROTOCOL
-,
-/* SADB_X_DEBUG */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_X_EXT_DEBUG
-,
-/* SADB_X_NAT_T_NEW_MAPPING */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_X_EXT_NAT_T_SPORT
-| 1<<SADB_X_EXT_NAT_T_DPORT
-},
-
-/* REQUIRED OUT */
-{
-/* SADB_RESERVED */
-0
-,
-/* SADB_GETSPI */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-,
-/* SADB_UPDATE */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-,
-/* SADB_ADD */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-,
-/* SADB_DELETE */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-,
-/* SADB_GET */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-/* | 1<<SADB_EXT_KEY_AUTH */
-/* | 1<<SADB_EXT_KEY_ENCRYPT */
-,
-/* SADB_ACQUIRE */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_EXT_PROPOSAL
-,
-/* SADB_REGISTER */
-1<<SADB_EXT_RESERVED
-/* | 1<<SADB_EXT_SUPPORTED_AUTH
- | 1<<SADB_EXT_SUPPORTED_ENCRYPT */
-,
-/* SADB_EXPIRE */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_LIFETIME_CURRENT
-/* | 1<<SADB_EXT_LIFETIME_HARD
- | 1<<SADB_EXT_LIFETIME_SOFT */
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-,
-/* SADB_FLUSH */
-1<<SADB_EXT_RESERVED
-,
-/* SADB_DUMP */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_EXT_KEY_AUTH
-| 1<<SADB_EXT_KEY_ENCRYPT
-,
-/* SADB_X_PROMISC */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_LIFETIME_CURRENT
-| 1<<SADB_EXT_LIFETIME_HARD
-| 1<<SADB_EXT_LIFETIME_SOFT
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_EXT_ADDRESS_PROXY
-| 1<<SADB_EXT_KEY_AUTH
-| 1<<SADB_EXT_KEY_ENCRYPT
-| 1<<SADB_EXT_IDENTITY_SRC
-| 1<<SADB_EXT_IDENTITY_DST
-| 1<<SADB_EXT_SENSITIVITY
-| 1<<SADB_EXT_PROPOSAL
-| 1<<SADB_EXT_SUPPORTED_AUTH
-| 1<<SADB_EXT_SUPPORTED_ENCRYPT
-| 1<<SADB_EXT_SPIRANGE
-| 1<<SADB_X_EXT_KMPRIVATE
-| 1<<SADB_X_EXT_SATYPE2
-| 1<<SADB_X_EXT_SA2
-| 1<<SADB_X_EXT_ADDRESS_DST2
-,
-/* SADB_X_PCHANGE */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_LIFETIME_CURRENT
-| 1<<SADB_EXT_LIFETIME_HARD
-| 1<<SADB_EXT_LIFETIME_SOFT
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_EXT_ADDRESS_PROXY
-| 1<<SADB_EXT_KEY_AUTH
-| 1<<SADB_EXT_KEY_ENCRYPT
-| 1<<SADB_EXT_IDENTITY_SRC
-| 1<<SADB_EXT_IDENTITY_DST
-| 1<<SADB_EXT_SENSITIVITY
-| 1<<SADB_EXT_PROPOSAL
-| 1<<SADB_EXT_SUPPORTED_AUTH
-| 1<<SADB_EXT_SUPPORTED_ENCRYPT
-| 1<<SADB_EXT_SPIRANGE
-| 1<<SADB_X_EXT_KMPRIVATE
-| 1<<SADB_X_EXT_SATYPE2
-| 1<<SADB_X_EXT_SA2
-| 1<<SADB_X_EXT_ADDRESS_DST2
-,
-/* SADB_X_GRPSA */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_ADDRESS_DST
-,
-/* SADB_X_ADDFLOW */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
-| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
-| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
-| 1<<SADB_X_EXT_ADDRESS_DST_MASK
-,
-/* SADB_X_DELFLOW */
-1<<SADB_EXT_RESERVED
-/*| 1<<SADB_EXT_SA*/
-| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
-| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
-| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
-| 1<<SADB_X_EXT_ADDRESS_DST_MASK
-,
-/* SADB_X_DEBUG */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_X_EXT_DEBUG
-,
-/* SADB_X_NAT_T_NEW_MAPPING */
-1<<SADB_EXT_RESERVED
-| 1<<SADB_EXT_SA
-| 1<<SADB_EXT_ADDRESS_SRC
-| 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_X_EXT_NAT_T_SPORT
-| 1<<SADB_X_EXT_NAT_T_DPORT
-}
-}
-};
diff --git a/src/libfreeswan/pfkey_v2_parse.c b/src/libfreeswan/pfkey_v2_parse.c
deleted file mode 100644
index 8fec9d119..000000000
--- a/src/libfreeswan/pfkey_v2_parse.c
+++ /dev/null
@@ -1,1539 +0,0 @@
-/*
- * RFC2367 PF_KEYv2 Key management API message parser
- * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs.
- *
- * 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.
- */
-
-/*
- * Template from klips/net/ipsec/ipsec/ipsec_parser.c.
- */
-
-char pfkey_v2_parse_c_version[] = "";
-
-# include <sys/types.h>
-# include <sys/socket.h>
-# include <errno.h>
-
-# include <freeswan.h>
-# include <constants.h>
-# include <defs.h> /* for PRINTF_LIKE */
-# include <log.h> /* for debugging and DBG_log */
-
-# ifdef PLUTO
-# define DEBUGGING(level, args...) { DBG_log("pfkey_lib_debug:" args); }
-# else
-# define DEBUGGING(level, args...) if(pfkey_lib_debug & level) { printf("pfkey_lib_debug:" args); } else { ; }
-# endif
-
-#include <pfkeyv2.h>
-#include <pfkey.h>
-
-
-#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0)
-
-static struct {
- uint8_t proto;
- uint8_t satype;
- char* name;
-} satype_tbl[] = {
- { SA_ESP, SADB_SATYPE_ESP, "ESP" },
- { SA_AH, SADB_SATYPE_AH, "AH" },
- { SA_IPIP, SADB_X_SATYPE_IPIP, "IPIP" },
- { SA_COMP, SADB_X_SATYPE_COMP, "COMP" },
- { SA_INT, SADB_X_SATYPE_INT, "INT" },
- { 0, 0, "UNKNOWN" }
-};
-
-uint8_t
-satype2proto(uint8_t satype)
-{
- int i =0;
-
- while(satype_tbl[i].satype != satype && satype_tbl[i].satype != 0) {
- i++;
- }
- return satype_tbl[i].proto;
-}
-
-uint8_t
-proto2satype(uint8_t proto)
-{
- int i = 0;
-
- while(satype_tbl[i].proto != proto && satype_tbl[i].proto != 0) {
- i++;
- }
- return satype_tbl[i].satype;
-}
-
-char*
-satype2name(uint8_t satype)
-{
- int i = 0;
-
- while(satype_tbl[i].satype != satype && satype_tbl[i].satype != 0) {
- i++;
- }
- return satype_tbl[i].name;
-}
-
-char*
-proto2name(uint8_t proto)
-{
- int i = 0;
-
- while(satype_tbl[i].proto != proto && satype_tbl[i].proto != 0) {
- i++;
- }
- return satype_tbl[i].name;
-}
-
-/* Default extension parsers taken from the KLIPS code */
-
-DEBUG_NO_STATIC int
-pfkey_sa_parse(struct sadb_ext *pfkey_ext)
-{
- int error = 0;
- struct sadb_sa *pfkey_sa = (struct sadb_sa *)pfkey_ext;
-#if 0
- struct sadb_sa sav2;
-#endif
-
- DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
- "pfkey_sa_parse: entry\n");
- /* sanity checks... */
- if(!pfkey_sa) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_sa_parse: "
- "NULL pointer passed in.\n");
- SENDERR(EINVAL);
- }
-
-#if 0
- /* check if this structure is short, and if so, fix it up.
- * XXX this is NOT the way to do things.
- */
- if(pfkey_sa->sadb_sa_len == sizeof(struct sadb_sa_v1)/IPSEC_PFKEYv2_ALIGN) {
-
- /* yes, so clear out a temporary structure, and copy first */
- memset(&sav2, 0, sizeof(sav2));
- memcpy(&sav2, pfkey_sa, sizeof(struct sadb_sa_v1));
- sav2.sadb_x_sa_ref=-1;
- sav2.sadb_sa_len = sizeof(struct sadb_sa) / IPSEC_PFKEYv2_ALIGN;
-
- pfkey_sa = &sav2;
- }
-#endif
-
-
- if(pfkey_sa->sadb_sa_len != sizeof(struct sadb_sa) / IPSEC_PFKEYv2_ALIGN) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_sa_parse: "
- "length wrong pfkey_sa->sadb_sa_len=%d sizeof(struct sadb_sa)=%d.\n",
- pfkey_sa->sadb_sa_len,
- (int)sizeof(struct sadb_sa));
- SENDERR(EINVAL);
- }
-
- if(pfkey_sa->sadb_sa_encrypt > SADB_EALG_MAX) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_sa_parse: "
- "pfkey_sa->sadb_sa_encrypt=%d > SADB_EALG_MAX=%d.\n",
- pfkey_sa->sadb_sa_encrypt,
- SADB_EALG_MAX);
- SENDERR(EINVAL);
- }
-
- if(pfkey_sa->sadb_sa_auth > SADB_AALG_MAX) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_sa_parse: "
- "pfkey_sa->sadb_sa_auth=%d > SADB_AALG_MAX=%d.\n",
- pfkey_sa->sadb_sa_auth,
- SADB_AALG_MAX);
- SENDERR(EINVAL);
- }
-
- if(pfkey_sa->sadb_sa_state > SADB_SASTATE_MAX) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_sa_parse: "
- "state=%d exceeds MAX=%d.\n",
- pfkey_sa->sadb_sa_state,
- SADB_SASTATE_MAX);
- SENDERR(EINVAL);
- }
-
- if(pfkey_sa->sadb_sa_state == SADB_SASTATE_DEAD) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_sa_parse: "
- "state=%d is DEAD=%d.\n",
- pfkey_sa->sadb_sa_state,
- SADB_SASTATE_DEAD);
- SENDERR(EINVAL);
- }
-
- if(pfkey_sa->sadb_sa_replay > 64) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_sa_parse: "
- "replay window size: %d -- must be 0 <= size <= 64\n",
- pfkey_sa->sadb_sa_replay);
- SENDERR(EINVAL);
- }
-
- if(! ((pfkey_sa->sadb_sa_exttype == SADB_EXT_SA) ||
- (pfkey_sa->sadb_sa_exttype == SADB_X_EXT_SA2)))
- {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_sa_parse: "
- "unknown exttype=%d, expecting SADB_EXT_SA=%d or SADB_X_EXT_SA2=%d.\n",
- pfkey_sa->sadb_sa_exttype,
- SADB_EXT_SA,
- SADB_X_EXT_SA2);
- SENDERR(EINVAL);
- }
-
- if((IPSEC_SAREF_NULL != pfkey_sa->sadb_x_sa_ref) && (pfkey_sa->sadb_x_sa_ref >= (1 << IPSEC_SA_REF_TABLE_IDX_WIDTH))) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_sa_parse: "
- "SAref=%d must be (SAref == IPSEC_SAREF_NULL(%d) || SAref < IPSEC_SA_REF_TABLE_NUM_ENTRIES(%d)).\n",
- pfkey_sa->sadb_x_sa_ref,
- IPSEC_SAREF_NULL,
- IPSEC_SA_REF_TABLE_NUM_ENTRIES);
- SENDERR(EINVAL);
- }
-
- DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
- "pfkey_sa_parse: "
- "successfully found len=%d exttype=%d(%s) spi=%08lx replay=%d state=%d auth=%d encrypt=%d flags=%d ref=%d.\n",
- pfkey_sa->sadb_sa_len,
- pfkey_sa->sadb_sa_exttype,
- pfkey_v2_sadb_ext_string(pfkey_sa->sadb_sa_exttype),
- (long unsigned int)ntohl(pfkey_sa->sadb_sa_spi),
- pfkey_sa->sadb_sa_replay,
- pfkey_sa->sadb_sa_state,
- pfkey_sa->sadb_sa_auth,
- pfkey_sa->sadb_sa_encrypt,
- pfkey_sa->sadb_sa_flags,
- pfkey_sa->sadb_x_sa_ref);
-
- errlab:
- return error;
-}
-
-DEBUG_NO_STATIC int
-pfkey_lifetime_parse(struct sadb_ext *pfkey_ext)
-{
- int error = 0;
- struct sadb_lifetime *pfkey_lifetime = (struct sadb_lifetime *)pfkey_ext;
-
- DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
- "pfkey_lifetime_parse:enter\n");
- /* sanity checks... */
- if(!pfkey_lifetime) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_lifetime_parse: "
- "NULL pointer passed in.\n");
- SENDERR(EINVAL);
- }
-
- if(pfkey_lifetime->sadb_lifetime_len !=
- sizeof(struct sadb_lifetime) / IPSEC_PFKEYv2_ALIGN) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_lifetime_parse: "
- "length wrong pfkey_lifetime->sadb_lifetime_len=%d sizeof(struct sadb_lifetime)=%d.\n",
- pfkey_lifetime->sadb_lifetime_len,
- (int)sizeof(struct sadb_lifetime));
- SENDERR(EINVAL);
- }
-
- if((pfkey_lifetime->sadb_lifetime_exttype != SADB_EXT_LIFETIME_HARD) &&
- (pfkey_lifetime->sadb_lifetime_exttype != SADB_EXT_LIFETIME_SOFT) &&
- (pfkey_lifetime->sadb_lifetime_exttype != SADB_EXT_LIFETIME_CURRENT)) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_lifetime_parse: "
- "unexpected ext_type=%d.\n",
- pfkey_lifetime->sadb_lifetime_exttype);
- SENDERR(EINVAL);
- }
-
- DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
- "pfkey_lifetime_parse: "
- "life_type=%d(%s) alloc=%u bytes=%u add=%u use=%u pkts=%u.\n",
- pfkey_lifetime->sadb_lifetime_exttype,
- pfkey_v2_sadb_ext_string(pfkey_lifetime->sadb_lifetime_exttype),
- pfkey_lifetime->sadb_lifetime_allocations,
- (unsigned)pfkey_lifetime->sadb_lifetime_bytes,
- (unsigned)pfkey_lifetime->sadb_lifetime_addtime,
- (unsigned)pfkey_lifetime->sadb_lifetime_usetime,
- pfkey_lifetime->sadb_x_lifetime_packets);
-errlab:
- return error;
-}
-
-DEBUG_NO_STATIC int
-pfkey_address_parse(struct sadb_ext *pfkey_ext)
-{
- int error = 0;
- int saddr_len = 0;
- struct sadb_address *pfkey_address = (struct sadb_address *)pfkey_ext;
- struct sockaddr* s = (struct sockaddr*)((char*)pfkey_address + sizeof(*pfkey_address));
- char ipaddr_txt[ADDRTOT_BUF];
-
- DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
- "pfkey_address_parse:enter\n");
- /* sanity checks... */
- if(!pfkey_address) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_address_parse: "
- "NULL pointer passed in.\n");
- SENDERR(EINVAL);
- }
-
- if(pfkey_address->sadb_address_len <
- (sizeof(struct sadb_address) + sizeof(struct sockaddr))/
- IPSEC_PFKEYv2_ALIGN) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_address_parse: "
- "size wrong 1 ext_len=%d, adr_ext_len=%d, saddr_len=%d.\n",
- pfkey_address->sadb_address_len,
- (int)sizeof(struct sadb_address),
- (int)sizeof(struct sockaddr));
- SENDERR(EINVAL);
- }
-
- if(pfkey_address->sadb_address_reserved) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_address_parse: "
- "res=%d, must be zero.\n",
- pfkey_address->sadb_address_reserved);
- SENDERR(EINVAL);
- }
-
- switch(pfkey_address->sadb_address_exttype) {
- case SADB_EXT_ADDRESS_SRC:
- case SADB_EXT_ADDRESS_DST:
- case SADB_EXT_ADDRESS_PROXY:
- case SADB_X_EXT_ADDRESS_DST2:
- case SADB_X_EXT_ADDRESS_SRC_FLOW:
- case SADB_X_EXT_ADDRESS_DST_FLOW:
- case SADB_X_EXT_ADDRESS_SRC_MASK:
- case SADB_X_EXT_ADDRESS_DST_MASK:
- case SADB_X_EXT_NAT_T_OA:
- break;
- default:
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_address_parse: "
- "unexpected ext_type=%d.\n",
- pfkey_address->sadb_address_exttype);
- SENDERR(EINVAL);
- }
-
- switch(s->sa_family) {
- case AF_INET:
- saddr_len = sizeof(struct sockaddr_in);
- sprintf(ipaddr_txt, "%d.%d.%d.%d"
- , (((struct sockaddr_in*)s)->sin_addr.s_addr >> 0) & 0xFF
- , (((struct sockaddr_in*)s)->sin_addr.s_addr >> 8) & 0xFF
- , (((struct sockaddr_in*)s)->sin_addr.s_addr >> 16) & 0xFF
- , (((struct sockaddr_in*)s)->sin_addr.s_addr >> 24) & 0xFF);
- DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
- "pfkey_address_parse: "
- "found exttype=%u(%s) family=%d(AF_INET) address=%s proto=%u port=%u.\n",
- pfkey_address->sadb_address_exttype,
- pfkey_v2_sadb_ext_string(pfkey_address->sadb_address_exttype),
- s->sa_family,
- ipaddr_txt,
- pfkey_address->sadb_address_proto,
- ntohs(((struct sockaddr_in*)s)->sin_port));
- break;
- case AF_INET6:
- saddr_len = sizeof(struct sockaddr_in6);
- sprintf(ipaddr_txt, "%x:%x:%x:%x:%x:%x:%x:%x"
- , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr[0])
- , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr[1])
- , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr[2])
- , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr[3])
- , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr[4])
- , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr[5])
- , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr[6])
- , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr[7]));
- DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
- "pfkey_address_parse: "
- "found exttype=%u(%s) family=%d(AF_INET6) address=%s proto=%u port=%u.\n",
- pfkey_address->sadb_address_exttype,
- pfkey_v2_sadb_ext_string(pfkey_address->sadb_address_exttype),
- s->sa_family,
- ipaddr_txt,
- pfkey_address->sadb_address_proto,
- ((struct sockaddr_in6*)s)->sin6_port);
- break;
- default:
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_address_parse: "
- "s->sa_family=%d not supported.\n",
- s->sa_family);
- SENDERR(EPFNOSUPPORT);
- }
-
- if(pfkey_address->sadb_address_len !=
- DIVUP(sizeof(struct sadb_address) + saddr_len, IPSEC_PFKEYv2_ALIGN)) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_address_parse: "
- "size wrong 2 ext_len=%d, adr_ext_len=%d, saddr_len=%d.\n",
- pfkey_address->sadb_address_len,
- (int)sizeof(struct sadb_address),
- saddr_len);
- SENDERR(EINVAL);
- }
-
- if(pfkey_address->sadb_address_prefixlen != 0) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_address_parse: "
- "address prefixes not supported yet.\n");
- SENDERR(EAFNOSUPPORT); /* not supported yet */
- }
-
- /* XXX check if port!=0 */
-
- DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
- "pfkey_address_parse: successful.\n");
- errlab:
- return error;
-}
-
-DEBUG_NO_STATIC int
-pfkey_key_parse(struct sadb_ext *pfkey_ext)
-{
- int error = 0;
- struct sadb_key *pfkey_key = (struct sadb_key *)pfkey_ext;
-
- DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
- "pfkey_key_parse:enter\n");
- /* sanity checks... */
-
- if(!pfkey_key) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_key_parse: "
- "NULL pointer passed in.\n");
- SENDERR(EINVAL);
- }
-
- if(pfkey_key->sadb_key_len < sizeof(struct sadb_key) / IPSEC_PFKEYv2_ALIGN) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_key_parse: "
- "size wrong ext_len=%d, key_ext_len=%d.\n",
- pfkey_key->sadb_key_len,
- (int)sizeof(struct sadb_key));
- SENDERR(EINVAL);
- }
-
- if(!pfkey_key->sadb_key_bits) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_key_parse: "
- "key length set to zero, must be non-zero.\n");
- SENDERR(EINVAL);
- }
-
- if(pfkey_key->sadb_key_len !=
- DIVUP(sizeof(struct sadb_key) * OCTETBITS + pfkey_key->sadb_key_bits,
- PFKEYBITS)) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_key_parse: "
- "key length=%d does not agree with extension length=%d.\n",
- pfkey_key->sadb_key_bits,
- pfkey_key->sadb_key_len);
- SENDERR(EINVAL);
- }
-
- if(pfkey_key->sadb_key_reserved) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_key_parse: "
- "res=%d, must be zero.\n",
- pfkey_key->sadb_key_reserved);
- SENDERR(EINVAL);
- }
-
- if(! ( (pfkey_key->sadb_key_exttype == SADB_EXT_KEY_AUTH) ||
- (pfkey_key->sadb_key_exttype == SADB_EXT_KEY_ENCRYPT))) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_key_parse: "
- "expecting extension type AUTH or ENCRYPT, got %d.\n",
- pfkey_key->sadb_key_exttype);
- SENDERR(EINVAL);
- }
-
- DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
- "pfkey_key_parse: "
- "success, found len=%d exttype=%d(%s) bits=%d reserved=%d.\n",
- pfkey_key->sadb_key_len,
- pfkey_key->sadb_key_exttype,
- pfkey_v2_sadb_ext_string(pfkey_key->sadb_key_exttype),
- pfkey_key->sadb_key_bits,
- pfkey_key->sadb_key_reserved);
-
-errlab:
- return error;
-}
-
-DEBUG_NO_STATIC int
-pfkey_ident_parse(struct sadb_ext *pfkey_ext)
-{
- int error = 0;
- struct sadb_ident *pfkey_ident = (struct sadb_ident *)pfkey_ext;
-
- /* sanity checks... */
- if(pfkey_ident->sadb_ident_len < sizeof(struct sadb_ident) / IPSEC_PFKEYv2_ALIGN) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_ident_parse: "
- "size wrong ext_len=%d, key_ext_len=%d.\n",
- pfkey_ident->sadb_ident_len,
- (int)sizeof(struct sadb_ident));
- SENDERR(EINVAL);
- }
-
- if(pfkey_ident->sadb_ident_type > SADB_IDENTTYPE_MAX) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_ident_parse: "
- "ident_type=%d out of range, must be less than %d.\n",
- pfkey_ident->sadb_ident_type,
- SADB_IDENTTYPE_MAX);
- SENDERR(EINVAL);
- }
-
- if(pfkey_ident->sadb_ident_reserved) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_ident_parse: "
- "res=%d, must be zero.\n",
- pfkey_ident->sadb_ident_reserved);
- SENDERR(EINVAL);
- }
-
- /* string terminator/padding must be zero */
- if(pfkey_ident->sadb_ident_len > sizeof(struct sadb_ident) / IPSEC_PFKEYv2_ALIGN) {
- if(*((char*)pfkey_ident + pfkey_ident->sadb_ident_len * IPSEC_PFKEYv2_ALIGN - 1)) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_ident_parse: "
- "string padding must be zero, last is 0x%02x.\n",
- *((char*)pfkey_ident +
- pfkey_ident->sadb_ident_len * IPSEC_PFKEYv2_ALIGN - 1));
- SENDERR(EINVAL);
- }
- }
-
- if( ! ((pfkey_ident->sadb_ident_exttype == SADB_EXT_IDENTITY_SRC) ||
- (pfkey_ident->sadb_ident_exttype == SADB_EXT_IDENTITY_DST))) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_key_parse: "
- "expecting extension type IDENTITY_SRC or IDENTITY_DST, got %d.\n",
- pfkey_ident->sadb_ident_exttype);
- SENDERR(EINVAL);
- }
-
-errlab:
- return error;
-}
-
-DEBUG_NO_STATIC int
-pfkey_sens_parse(struct sadb_ext *pfkey_ext)
-{
- int error = 0;
- struct sadb_sens *pfkey_sens = (struct sadb_sens *)pfkey_ext;
-
- /* sanity checks... */
- if(pfkey_sens->sadb_sens_len < sizeof(struct sadb_sens) / IPSEC_PFKEYv2_ALIGN) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_sens_parse: "
- "size wrong ext_len=%d, key_ext_len=%d.\n",
- pfkey_sens->sadb_sens_len,
- (int)sizeof(struct sadb_sens));
- SENDERR(EINVAL);
- }
-
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_sens_parse: "
- "Sorry, I can't parse exttype=%d yet.\n",
- pfkey_ext->sadb_ext_type);
-#if 0
- SENDERR(EINVAL); /* don't process these yet */
-#endif
-
-errlab:
- return error;
-}
-
-DEBUG_NO_STATIC int
-pfkey_prop_parse(struct sadb_ext *pfkey_ext)
-{
- int error = 0;
- int i, num_comb;
- struct sadb_prop *pfkey_prop = (struct sadb_prop *)pfkey_ext;
- struct sadb_comb *pfkey_comb = (struct sadb_comb *)((char*)pfkey_ext + sizeof(struct sadb_prop));
-
- /* sanity checks... */
- if((pfkey_prop->sadb_prop_len < sizeof(struct sadb_prop) / IPSEC_PFKEYv2_ALIGN) ||
- (((pfkey_prop->sadb_prop_len * IPSEC_PFKEYv2_ALIGN) - sizeof(struct sadb_prop)) % sizeof(struct sadb_comb))) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_prop_parse: "
- "size wrong ext_len=%d, prop_ext_len=%d comb_ext_len=%d.\n",
- pfkey_prop->sadb_prop_len,
- (int)sizeof(struct sadb_prop),
- (int)sizeof(struct sadb_comb));
- SENDERR(EINVAL);
- }
-
- if(pfkey_prop->sadb_prop_replay > 64) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_prop_parse: "
- "replay window size: %d -- must be 0 <= size <= 64\n",
- pfkey_prop->sadb_prop_replay);
- SENDERR(EINVAL);
- }
-
- for(i=0; i<3; i++) {
- if(pfkey_prop->sadb_prop_reserved[i]) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_prop_parse: "
- "res[%d]=%d, must be zero.\n",
- i, pfkey_prop->sadb_prop_reserved[i]);
- SENDERR(EINVAL);
- }
- }
-
- num_comb = ((pfkey_prop->sadb_prop_len * IPSEC_PFKEYv2_ALIGN) - sizeof(struct sadb_prop)) / sizeof(struct sadb_comb);
-
- for(i = 0; i < num_comb; i++) {
- if(pfkey_comb->sadb_comb_auth > SADB_AALG_MAX) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_prop_parse: "
- "pfkey_comb[%d]->sadb_comb_auth=%d > SADB_AALG_MAX=%d.\n",
- i,
- pfkey_comb->sadb_comb_auth,
- SADB_AALG_MAX);
- SENDERR(EINVAL);
- }
-
- if(pfkey_comb->sadb_comb_auth) {
- if(!pfkey_comb->sadb_comb_auth_minbits) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_prop_parse: "
- "pfkey_comb[%d]->sadb_comb_auth_minbits=0, fatal.\n",
- i);
- SENDERR(EINVAL);
- }
- if(!pfkey_comb->sadb_comb_auth_maxbits) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_prop_parse: "
- "pfkey_comb[%d]->sadb_comb_auth_maxbits=0, fatal.\n",
- i);
- SENDERR(EINVAL);
- }
- if(pfkey_comb->sadb_comb_auth_minbits > pfkey_comb->sadb_comb_auth_maxbits) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_prop_parse: "
- "pfkey_comb[%d]->sadb_comb_auth_minbits=%d > maxbits=%d, fatal.\n",
- i,
- pfkey_comb->sadb_comb_auth_minbits,
- pfkey_comb->sadb_comb_auth_maxbits);
- SENDERR(EINVAL);
- }
- } else {
- if(pfkey_comb->sadb_comb_auth_minbits) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_prop_parse: "
- "pfkey_comb[%d]->sadb_comb_auth_minbits=%d != 0, fatal.\n",
- i,
- pfkey_comb->sadb_comb_auth_minbits);
- SENDERR(EINVAL);
- }
- if(pfkey_comb->sadb_comb_auth_maxbits) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_prop_parse: "
- "pfkey_comb[%d]->sadb_comb_auth_maxbits=%d != 0, fatal.\n",
- i,
- pfkey_comb->sadb_comb_auth_maxbits);
- SENDERR(EINVAL);
- }
- }
-
- if(pfkey_comb->sadb_comb_encrypt > SADB_EALG_MAX) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_comb_parse: "
- "pfkey_comb[%d]->sadb_comb_encrypt=%d > SADB_EALG_MAX=%d.\n",
- i,
- pfkey_comb->sadb_comb_encrypt,
- SADB_EALG_MAX);
- SENDERR(EINVAL);
- }
-
- if(pfkey_comb->sadb_comb_encrypt) {
- if(!pfkey_comb->sadb_comb_encrypt_minbits) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_prop_parse: "
- "pfkey_comb[%d]->sadb_comb_encrypt_minbits=0, fatal.\n",
- i);
- SENDERR(EINVAL);
- }
- if(!pfkey_comb->sadb_comb_encrypt_maxbits) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_prop_parse: "
- "pfkey_comb[%d]->sadb_comb_encrypt_maxbits=0, fatal.\n",
- i);
- SENDERR(EINVAL);
- }
- if(pfkey_comb->sadb_comb_encrypt_minbits > pfkey_comb->sadb_comb_encrypt_maxbits) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_prop_parse: "
- "pfkey_comb[%d]->sadb_comb_encrypt_minbits=%d > maxbits=%d, fatal.\n",
- i,
- pfkey_comb->sadb_comb_encrypt_minbits,
- pfkey_comb->sadb_comb_encrypt_maxbits);
- SENDERR(EINVAL);
- }
- } else {
- if(pfkey_comb->sadb_comb_encrypt_minbits) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_prop_parse: "
- "pfkey_comb[%d]->sadb_comb_encrypt_minbits=%d != 0, fatal.\n",
- i,
- pfkey_comb->sadb_comb_encrypt_minbits);
- SENDERR(EINVAL);
- }
- if(pfkey_comb->sadb_comb_encrypt_maxbits) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_prop_parse: "
- "pfkey_comb[%d]->sadb_comb_encrypt_maxbits=%d != 0, fatal.\n",
- i,
- pfkey_comb->sadb_comb_encrypt_maxbits);
- SENDERR(EINVAL);
- }
- }
-
- /* XXX do sanity check on flags */
-
- if(pfkey_comb->sadb_comb_hard_allocations && pfkey_comb->sadb_comb_soft_allocations > pfkey_comb->sadb_comb_hard_allocations) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_prop_parse: "
- "pfkey_comb[%d]->sadb_comb_soft_allocations=%d > hard_allocations=%d, fatal.\n",
- i,
- pfkey_comb->sadb_comb_soft_allocations,
- pfkey_comb->sadb_comb_hard_allocations);
- SENDERR(EINVAL);
- }
-
- if(pfkey_comb->sadb_comb_hard_bytes && pfkey_comb->sadb_comb_soft_bytes > pfkey_comb->sadb_comb_hard_bytes) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_prop_parse: "
- "pfkey_comb[%d]->sadb_comb_soft_bytes=%Ld > hard_bytes=%Ld, fatal.\n",
- i,
- (unsigned long long int)pfkey_comb->sadb_comb_soft_bytes,
- (unsigned long long int)pfkey_comb->sadb_comb_hard_bytes);
- SENDERR(EINVAL);
- }
-
- if(pfkey_comb->sadb_comb_hard_addtime && pfkey_comb->sadb_comb_soft_addtime > pfkey_comb->sadb_comb_hard_addtime) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_prop_parse: "
- "pfkey_comb[%d]->sadb_comb_soft_addtime=%Ld > hard_addtime=%Ld, fatal.\n",
- i,
- (unsigned long long int)pfkey_comb->sadb_comb_soft_addtime,
- (unsigned long long int)pfkey_comb->sadb_comb_hard_addtime);
- SENDERR(EINVAL);
- }
-
- if(pfkey_comb->sadb_comb_hard_usetime && pfkey_comb->sadb_comb_soft_usetime > pfkey_comb->sadb_comb_hard_usetime) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_prop_parse: "
- "pfkey_comb[%d]->sadb_comb_soft_usetime=%Ld > hard_usetime=%Ld, fatal.\n",
- i,
- (unsigned long long int)pfkey_comb->sadb_comb_soft_usetime,
- (unsigned long long int)pfkey_comb->sadb_comb_hard_usetime);
- SENDERR(EINVAL);
- }
-
- if(pfkey_comb->sadb_x_comb_hard_packets && pfkey_comb->sadb_x_comb_soft_packets > pfkey_comb->sadb_x_comb_hard_packets) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_prop_parse: "
- "pfkey_comb[%d]->sadb_x_comb_soft_packets=%d > hard_packets=%d, fatal.\n",
- i,
- pfkey_comb->sadb_x_comb_soft_packets,
- pfkey_comb->sadb_x_comb_hard_packets);
- SENDERR(EINVAL);
- }
-
- if(pfkey_comb->sadb_comb_reserved) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_prop_parse: "
- "comb[%d].res=%d, must be zero.\n",
- i,
- pfkey_comb->sadb_comb_reserved);
- SENDERR(EINVAL);
- }
- pfkey_comb++;
- }
-
-errlab:
- return error;
-}
-
-DEBUG_NO_STATIC int
-pfkey_supported_parse(struct sadb_ext *pfkey_ext)
-{
- int error = 0;
- unsigned int i, num_alg;
- struct sadb_supported *pfkey_supported = (struct sadb_supported *)pfkey_ext;
- struct sadb_alg *pfkey_alg = (struct sadb_alg*)((char*)pfkey_ext + sizeof(struct sadb_supported));
-
- /* sanity checks... */
- if((pfkey_supported->sadb_supported_len <
- sizeof(struct sadb_supported) / IPSEC_PFKEYv2_ALIGN) ||
- (((pfkey_supported->sadb_supported_len * IPSEC_PFKEYv2_ALIGN) -
- sizeof(struct sadb_supported)) % sizeof(struct sadb_alg))) {
-
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_supported_parse: "
- "size wrong ext_len=%d, supported_ext_len=%d alg_ext_len=%d.\n",
- pfkey_supported->sadb_supported_len,
- (int)sizeof(struct sadb_supported),
- (int)sizeof(struct sadb_alg));
- SENDERR(EINVAL);
- }
-
- if(pfkey_supported->sadb_supported_reserved) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_supported_parse: "
- "res=%d, must be zero.\n",
- pfkey_supported->sadb_supported_reserved);
- SENDERR(EINVAL);
- }
-
- num_alg = ((pfkey_supported->sadb_supported_len * IPSEC_PFKEYv2_ALIGN) - sizeof(struct sadb_supported)) / sizeof(struct sadb_alg);
-
- for(i = 0; i < num_alg; i++) {
- /* process algo description */
- if(pfkey_alg->sadb_alg_reserved) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_supported_parse: "
- "alg[%d], id=%d, ivlen=%d, minbits=%d, maxbits=%d, res=%d, must be zero.\n",
- i,
- pfkey_alg->sadb_alg_id,
- pfkey_alg->sadb_alg_ivlen,
- pfkey_alg->sadb_alg_minbits,
- pfkey_alg->sadb_alg_maxbits,
- pfkey_alg->sadb_alg_reserved);
- SENDERR(EINVAL);
- }
-
- /* XXX can alg_id auth/enc be determined from info given?
- Yes, but OpenBSD's method does not iteroperate with rfc2367.
- rgb, 2000-04-06 */
-
- switch(pfkey_supported->sadb_supported_exttype) {
- case SADB_EXT_SUPPORTED_AUTH:
- if(pfkey_alg->sadb_alg_id > SADB_AALG_MAX) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_supported_parse: "
- "alg[%d], alg_id=%d > SADB_AALG_MAX=%d, fatal.\n",
- i,
- pfkey_alg->sadb_alg_id,
- SADB_AALG_MAX);
- SENDERR(EINVAL);
- }
- break;
- case SADB_EXT_SUPPORTED_ENCRYPT:
- if(pfkey_alg->sadb_alg_id > SADB_EALG_MAX) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_supported_parse: "
- "alg[%d], alg_id=%d > SADB_EALG_MAX=%d, fatal.\n",
- i,
- pfkey_alg->sadb_alg_id,
- SADB_EALG_MAX);
- SENDERR(EINVAL);
- }
- break;
- default:
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_supported_parse: "
- "alg[%d], alg_id=%d > SADB_EALG_MAX=%d, fatal.\n",
- i,
- pfkey_alg->sadb_alg_id,
- SADB_EALG_MAX);
- SENDERR(EINVAL);
- }
- pfkey_alg++;
- }
-
- errlab:
- return error;
-}
-
-DEBUG_NO_STATIC int
-pfkey_spirange_parse(struct sadb_ext *pfkey_ext)
-{
- int error = 0;
- struct sadb_spirange *pfkey_spirange = (struct sadb_spirange *)pfkey_ext;
-
- /* sanity checks... */
- if(pfkey_spirange->sadb_spirange_len !=
- sizeof(struct sadb_spirange) / IPSEC_PFKEYv2_ALIGN) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_spirange_parse: "
- "size wrong ext_len=%d, key_ext_len=%d.\n",
- pfkey_spirange->sadb_spirange_len,
- (int)sizeof(struct sadb_spirange));
- SENDERR(EINVAL);
- }
-
- if(pfkey_spirange->sadb_spirange_reserved) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_spirange_parse: "
- "reserved=%d must be set to zero.\n",
- pfkey_spirange->sadb_spirange_reserved);
- SENDERR(EINVAL);
- }
-
- if(ntohl(pfkey_spirange->sadb_spirange_max) < ntohl(pfkey_spirange->sadb_spirange_min)) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_spirange_parse: "
- "minspi=%08x must be < maxspi=%08x.\n",
- ntohl(pfkey_spirange->sadb_spirange_min),
- ntohl(pfkey_spirange->sadb_spirange_max));
- SENDERR(EINVAL);
- }
-
- if(ntohl(pfkey_spirange->sadb_spirange_min) <= 255) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_spirange_parse: "
- "minspi=%08x must be > 255.\n",
- ntohl(pfkey_spirange->sadb_spirange_min));
- SENDERR(EEXIST);
- }
-
- DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
- "pfkey_spirange_parse: "
- "ext_len=%u ext_type=%u(%s) min=%u max=%u res=%u.\n",
- pfkey_spirange->sadb_spirange_len,
- pfkey_spirange->sadb_spirange_exttype,
- pfkey_v2_sadb_ext_string(pfkey_spirange->sadb_spirange_exttype),
- pfkey_spirange->sadb_spirange_min,
- pfkey_spirange->sadb_spirange_max,
- pfkey_spirange->sadb_spirange_reserved);
- errlab:
- return error;
-}
-
-DEBUG_NO_STATIC int
-pfkey_x_kmprivate_parse(struct sadb_ext *pfkey_ext)
-{
- int error = 0;
- struct sadb_x_kmprivate *pfkey_x_kmprivate = (struct sadb_x_kmprivate *)pfkey_ext;
-
- /* sanity checks... */
- if(pfkey_x_kmprivate->sadb_x_kmprivate_len <
- sizeof(struct sadb_x_kmprivate) / IPSEC_PFKEYv2_ALIGN) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_x_kmprivate_parse: "
- "size wrong ext_len=%d, key_ext_len=%d.\n",
- pfkey_x_kmprivate->sadb_x_kmprivate_len,
- (int)sizeof(struct sadb_x_kmprivate));
- SENDERR(EINVAL);
- }
-
- if(pfkey_x_kmprivate->sadb_x_kmprivate_reserved) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_x_kmprivate_parse: "
- "reserved=%d must be set to zero.\n",
- pfkey_x_kmprivate->sadb_x_kmprivate_reserved);
- SENDERR(EINVAL);
- }
-
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_x_kmprivate_parse: "
- "Sorry, I can't parse exttype=%d yet.\n",
- pfkey_ext->sadb_ext_type);
- SENDERR(EINVAL); /* don't process these yet */
-
-errlab:
- return error;
-}
-
-DEBUG_NO_STATIC int
-pfkey_x_satype_parse(struct sadb_ext *pfkey_ext)
-{
- int error = 0;
- int i;
- struct sadb_x_satype *pfkey_x_satype = (struct sadb_x_satype *)pfkey_ext;
-
- DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
- "pfkey_x_satype_parse: enter\n");
- /* sanity checks... */
- if(pfkey_x_satype->sadb_x_satype_len !=
- sizeof(struct sadb_x_satype) / IPSEC_PFKEYv2_ALIGN) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_x_satype_parse: "
- "size wrong ext_len=%d, key_ext_len=%d.\n",
- pfkey_x_satype->sadb_x_satype_len,
- (int)sizeof(struct sadb_x_satype));
- SENDERR(EINVAL);
- }
-
- if(!pfkey_x_satype->sadb_x_satype_satype) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_x_satype_parse: "
- "satype is zero, must be non-zero.\n");
- SENDERR(EINVAL);
- }
-
- if(pfkey_x_satype->sadb_x_satype_satype > SADB_SATYPE_MAX) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_x_satype_parse: "
- "satype %d > max %d, invalid.\n",
- pfkey_x_satype->sadb_x_satype_satype, SADB_SATYPE_MAX);
- SENDERR(EINVAL);
- }
-
- if(!(satype2proto(pfkey_x_satype->sadb_x_satype_satype))) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_x_satype_parse: "
- "proto lookup from satype=%d failed.\n",
- pfkey_x_satype->sadb_x_satype_satype);
- SENDERR(EINVAL);
- }
-
- for(i = 0; i < 3; i++) {
- if(pfkey_x_satype->sadb_x_satype_reserved[i]) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_x_satype_parse: "
- "reserved[%d]=%d must be set to zero.\n",
- i, pfkey_x_satype->sadb_x_satype_reserved[i]);
- SENDERR(EINVAL);
- }
- }
-
- DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
- "pfkey_x_satype_parse: "
- "len=%u ext=%u(%s) satype=%u(%s) res=%u,%u,%u.\n",
- pfkey_x_satype->sadb_x_satype_len,
- pfkey_x_satype->sadb_x_satype_exttype,
- pfkey_v2_sadb_ext_string(pfkey_x_satype->sadb_x_satype_exttype),
- pfkey_x_satype->sadb_x_satype_satype,
- satype2name(pfkey_x_satype->sadb_x_satype_satype),
- pfkey_x_satype->sadb_x_satype_reserved[0],
- pfkey_x_satype->sadb_x_satype_reserved[1],
- pfkey_x_satype->sadb_x_satype_reserved[2]);
-errlab:
- return error;
-}
-
-DEBUG_NO_STATIC int
-pfkey_x_ext_debug_parse(struct sadb_ext *pfkey_ext)
-{
- int error = 0;
- int i;
- struct sadb_x_debug *pfkey_x_debug = (struct sadb_x_debug *)pfkey_ext;
-
- DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
- "pfkey_x_debug_parse: enter\n");
- /* sanity checks... */
- if(pfkey_x_debug->sadb_x_debug_len !=
- sizeof(struct sadb_x_debug) / IPSEC_PFKEYv2_ALIGN) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_x_debug_parse: "
- "size wrong ext_len=%d, key_ext_len=%d.\n",
- pfkey_x_debug->sadb_x_debug_len,
- (int)sizeof(struct sadb_x_debug));
- SENDERR(EINVAL);
- }
-
- for(i = 0; i < 4; i++) {
- if(pfkey_x_debug->sadb_x_debug_reserved[i]) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_x_debug_parse: "
- "reserved[%d]=%d must be set to zero.\n",
- i, pfkey_x_debug->sadb_x_debug_reserved[i]);
- SENDERR(EINVAL);
- }
- }
-
-errlab:
- return error;
-}
-
-DEBUG_NO_STATIC int
-pfkey_x_ext_protocol_parse(struct sadb_ext *pfkey_ext)
-{
- int error = 0;
- struct sadb_protocol *p = (struct sadb_protocol *)pfkey_ext;
-
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_protocol_parse:\n");
- /* sanity checks... */
-
- if (p->sadb_protocol_len != sizeof(*p)/IPSEC_PFKEYv2_ALIGN) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_x_protocol_parse: size wrong ext_len=%d, key_ext_len=%d.\n",
- p->sadb_protocol_len, (int)sizeof(*p));
- SENDERR(EINVAL);
- }
-
- if (p->sadb_protocol_reserved2 != 0) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_protocol_parse: res=%d, must be zero.\n",
- p->sadb_protocol_reserved2);
- SENDERR(EINVAL);
- }
-
- errlab:
- return error;
-}
-
-DEBUG_NO_STATIC int
-pfkey_x_ext_nat_t_type_parse(struct sadb_ext *pfkey_ext)
-{
- return 0;
-}
-
-DEBUG_NO_STATIC int
-pfkey_x_ext_nat_t_port_parse(struct sadb_ext *pfkey_ext)
-{
- return 0;
-}
-
-#define DEFINEPARSER(NAME) static struct pf_key_ext_parsers_def NAME##_def={NAME, #NAME};
-
-DEFINEPARSER(pfkey_sa_parse);
-DEFINEPARSER(pfkey_lifetime_parse);
-DEFINEPARSER(pfkey_address_parse);
-DEFINEPARSER(pfkey_key_parse);
-DEFINEPARSER(pfkey_ident_parse);
-DEFINEPARSER(pfkey_sens_parse);
-DEFINEPARSER(pfkey_prop_parse);
-DEFINEPARSER(pfkey_supported_parse);
-DEFINEPARSER(pfkey_spirange_parse);
-DEFINEPARSER(pfkey_x_kmprivate_parse);
-DEFINEPARSER(pfkey_x_satype_parse);
-DEFINEPARSER(pfkey_x_ext_debug_parse);
-DEFINEPARSER(pfkey_x_ext_protocol_parse);
-DEFINEPARSER(pfkey_x_ext_nat_t_type_parse);
-DEFINEPARSER(pfkey_x_ext_nat_t_port_parse);
-
-struct pf_key_ext_parsers_def *ext_default_parsers[]=
-{
- NULL, /* pfkey_msg_parse, */
- &pfkey_sa_parse_def,
- &pfkey_lifetime_parse_def,
- &pfkey_lifetime_parse_def,
- &pfkey_lifetime_parse_def,
- &pfkey_address_parse_def,
- &pfkey_address_parse_def,
- &pfkey_address_parse_def,
- &pfkey_key_parse_def,
- &pfkey_key_parse_def,
- &pfkey_ident_parse_def,
- &pfkey_ident_parse_def,
- &pfkey_sens_parse_def,
- &pfkey_prop_parse_def,
- &pfkey_supported_parse_def,
- &pfkey_supported_parse_def,
- &pfkey_spirange_parse_def,
- &pfkey_x_kmprivate_parse_def,
- &pfkey_x_satype_parse_def,
- &pfkey_sa_parse_def,
- &pfkey_address_parse_def,
- &pfkey_address_parse_def,
- &pfkey_address_parse_def,
- &pfkey_address_parse_def,
- &pfkey_address_parse_def,
- &pfkey_x_ext_debug_parse_def,
- &pfkey_x_ext_protocol_parse_def ,
- &pfkey_x_ext_nat_t_type_parse_def,
- &pfkey_x_ext_nat_t_port_parse_def,
- &pfkey_x_ext_nat_t_port_parse_def,
- &pfkey_address_parse_def
-};
-
-int
-pfkey_msg_parse(struct sadb_msg *pfkey_msg,
- struct pf_key_ext_parsers_def *ext_parsers[],
- struct sadb_ext *extensions[],
- int dir)
-{
- int error = 0;
- int remain;
- struct sadb_ext *pfkey_ext;
- int extensions_seen = 0;
-
- DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
- "pfkey_msg_parse: "
- "parsing message ver=%d, type=%d(%s), errno=%d, satype=%d(%s), len=%d, res=%d, seq=%d, pid=%d.\n",
- pfkey_msg->sadb_msg_version,
- pfkey_msg->sadb_msg_type,
- pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type),
- pfkey_msg->sadb_msg_errno,
- pfkey_msg->sadb_msg_satype,
- satype2name(pfkey_msg->sadb_msg_satype),
- pfkey_msg->sadb_msg_len,
- pfkey_msg->sadb_msg_reserved,
- pfkey_msg->sadb_msg_seq,
- pfkey_msg->sadb_msg_pid);
-
- if(ext_parsers == NULL) ext_parsers = ext_default_parsers;
-
- pfkey_extensions_init(extensions);
-
- remain = pfkey_msg->sadb_msg_len;
- remain -= sizeof(struct sadb_msg) / IPSEC_PFKEYv2_ALIGN;
-
- pfkey_ext = (struct sadb_ext*)((char*)pfkey_msg +
- sizeof(struct sadb_msg));
-
- extensions[0] = (struct sadb_ext *) pfkey_msg;
-
-
- if(pfkey_msg->sadb_msg_version != PF_KEY_V2) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_msg_parse: "
- "not PF_KEY_V2 msg, found %d, should be %d.\n",
- pfkey_msg->sadb_msg_version,
- PF_KEY_V2);
- SENDERR(EINVAL);
- }
-
- if(!pfkey_msg->sadb_msg_type) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_msg_parse: "
- "msg type not set, must be non-zero..\n");
- SENDERR(EINVAL);
- }
-
- if(pfkey_msg->sadb_msg_type > SADB_MAX) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_msg_parse: "
- "msg type=%d > max=%d.\n",
- pfkey_msg->sadb_msg_type,
- SADB_MAX);
- SENDERR(EINVAL);
- }
-
- switch(pfkey_msg->sadb_msg_type) {
- case SADB_GETSPI:
- case SADB_UPDATE:
- case SADB_ADD:
- case SADB_DELETE:
- case SADB_GET:
- case SADB_X_GRPSA:
- case SADB_X_ADDFLOW:
- if(!satype2proto(pfkey_msg->sadb_msg_satype)) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_msg_parse: "
- "satype %d conversion to proto failed for msg_type %d (%s).\n",
- pfkey_msg->sadb_msg_satype,
- pfkey_msg->sadb_msg_type,
- pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type));
- SENDERR(EINVAL);
- } else {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_msg_parse: "
- "satype %d(%s) conversion to proto gives %d for msg_type %d(%s).\n",
- pfkey_msg->sadb_msg_satype,
- satype2name(pfkey_msg->sadb_msg_satype),
- satype2proto(pfkey_msg->sadb_msg_satype),
- pfkey_msg->sadb_msg_type,
- pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type));
- }
- /* fall through */
- case SADB_ACQUIRE:
- case SADB_REGISTER:
- case SADB_EXPIRE:
- if(!pfkey_msg->sadb_msg_satype) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_msg_parse: "
- "satype is zero, must be non-zero for msg_type %d(%s).\n",
- pfkey_msg->sadb_msg_type,
- pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type));
- SENDERR(EINVAL);
- }
- default:
- break;
- }
-
- /* errno must not be set in downward messages */
- /* this is not entirely true... a response to an ACQUIRE could return an error */
- if((dir == EXT_BITS_IN) && (pfkey_msg->sadb_msg_type != SADB_ACQUIRE) && pfkey_msg->sadb_msg_errno) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_msg_parse: "
- "errno set to %d.\n",
- pfkey_msg->sadb_msg_errno);
- SENDERR(EINVAL);
- }
-
- DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
- "pfkey_msg_parse: "
- "remain=%d, ext_type=%d(%s), ext_len=%d.\n",
- remain,
- pfkey_ext->sadb_ext_type,
- pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type),
- pfkey_ext->sadb_ext_len);
-
- DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
- "pfkey_msg_parse: "
- "extensions permitted=%08x, required=%08x.\n",
- extensions_bitmaps[dir][EXT_BITS_PERM][pfkey_msg->sadb_msg_type],
- extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]);
-
- extensions_seen = 1;
-
- while( (remain * IPSEC_PFKEYv2_ALIGN) >= sizeof(struct sadb_ext) ) {
- /* Is there enough message left to support another extension header? */
- if(remain < pfkey_ext->sadb_ext_len) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_msg_parse: "
- "remain %d less than ext len %d.\n",
- remain, pfkey_ext->sadb_ext_len);
- SENDERR(EINVAL);
- }
-
- DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
- "pfkey_msg_parse: "
- "parsing ext type=%d(%s) remain=%d.\n",
- pfkey_ext->sadb_ext_type,
- pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type),
- remain);
-
- /* Is the extension header type valid? */
- if((pfkey_ext->sadb_ext_type > SADB_EXT_MAX) || (!pfkey_ext->sadb_ext_type)) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_msg_parse: "
- "ext type %d(%s) invalid, SADB_EXT_MAX=%d.\n",
- pfkey_ext->sadb_ext_type,
- pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type),
- SADB_EXT_MAX);
- SENDERR(EINVAL);
- }
-
- /* Have we already seen this type of extension? */
- if((extensions_seen & ( 1 << pfkey_ext->sadb_ext_type )) != 0)
- {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_msg_parse: "
- "ext type %d(%s) already seen.\n",
- pfkey_ext->sadb_ext_type,
- pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type));
- SENDERR(EINVAL);
- }
-
- /* Do I even know about this type of extension? */
- if(ext_parsers[pfkey_ext->sadb_ext_type]==NULL) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_msg_parse: "
- "ext type %d(%s) unknown, ignoring.\n",
- pfkey_ext->sadb_ext_type,
- pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type));
- goto next_ext;
- }
-
- /* Is this type of extension permitted for this type of message? */
- if(!(extensions_bitmaps[dir][EXT_BITS_PERM][pfkey_msg->sadb_msg_type] &
- 1<<pfkey_ext->sadb_ext_type)) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_msg_parse: "
- "ext type %d(%s) not permitted, exts_perm_in=%08x, 1<<type=%08x\n",
- pfkey_ext->sadb_ext_type,
- pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type),
- extensions_bitmaps[dir][EXT_BITS_PERM][pfkey_msg->sadb_msg_type],
- 1<<pfkey_ext->sadb_ext_type);
- SENDERR(EINVAL);
- }
-
- DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
- "pfkey_msg_parse: "
- "remain=%d ext_type=%d(%s) ext_len=%d parsing ext 0p%p with parser %s.\n",
- remain,
- pfkey_ext->sadb_ext_type,
- pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type),
- pfkey_ext->sadb_ext_len,
- pfkey_ext,
- ext_parsers[pfkey_ext->sadb_ext_type]->parser_name);
-
- /* Parse the extension */
- if((error =
- (*ext_parsers[pfkey_ext->sadb_ext_type]->parser)(pfkey_ext))) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_msg_parse: "
- "extension parsing for type %d(%s) failed with error %d.\n",
- pfkey_ext->sadb_ext_type,
- pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type),
- error);
- SENDERR(-error);
- }
- DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
- "pfkey_msg_parse: "
- "Extension %d(%s) parsed.\n",
- pfkey_ext->sadb_ext_type,
- pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type));
-
- /* Mark that we have seen this extension and remember the header location */
- extensions_seen |= ( 1 << pfkey_ext->sadb_ext_type );
- extensions[pfkey_ext->sadb_ext_type] = pfkey_ext;
-
- next_ext:
- /* Calculate how much message remains */
- remain -= pfkey_ext->sadb_ext_len;
-
- if(!remain) {
- break;
- }
- /* Find the next extension header */
- pfkey_ext = (struct sadb_ext*)((char*)pfkey_ext +
- pfkey_ext->sadb_ext_len * IPSEC_PFKEYv2_ALIGN);
- }
-
- if(remain) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_msg_parse: "
- "unexpected remainder of %d.\n",
- remain);
- /* why is there still something remaining? */
- SENDERR(EINVAL);
- }
-
- /* check required extensions */
- DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
- "pfkey_msg_parse: "
- "extensions permitted=%08x, seen=%08x, required=%08x.\n",
- extensions_bitmaps[dir][EXT_BITS_PERM][pfkey_msg->sadb_msg_type],
- extensions_seen,
- extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]);
-
- /* don't check further if it is an error return message since it
- may not have a body */
- if(pfkey_msg->sadb_msg_errno) {
- SENDERR(-error);
- }
-
- if((extensions_seen &
- extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]) !=
- extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_msg_parse: "
- "required extensions missing:%08x.\n",
- extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type] -
- (extensions_seen &
- extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]));
- SENDERR(EINVAL);
- }
-
- if((dir == EXT_BITS_IN) && (pfkey_msg->sadb_msg_type == SADB_X_DELFLOW)
- && ((extensions_seen & SADB_X_EXT_ADDRESS_DELFLOW)
- != SADB_X_EXT_ADDRESS_DELFLOW)
- && (((extensions_seen & (1<<SADB_EXT_SA)) != (1<<SADB_EXT_SA))
- || ((((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_flags
- & SADB_X_SAFLAGS_CLEARFLOW)
- != SADB_X_SAFLAGS_CLEARFLOW))) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_msg_parse: "
- "required SADB_X_DELFLOW extensions missing: either %08x must be present or %08x must be present with SADB_X_SAFLAGS_CLEARFLOW set.\n",
- SADB_X_EXT_ADDRESS_DELFLOW
- - (extensions_seen & SADB_X_EXT_ADDRESS_DELFLOW),
- (1<<SADB_EXT_SA) - (extensions_seen & (1<<SADB_EXT_SA)));
- SENDERR(EINVAL);
- }
-
- switch(pfkey_msg->sadb_msg_type) {
- case SADB_ADD:
- case SADB_UPDATE:
- /* check maturity */
- if(((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state !=
- SADB_SASTATE_MATURE) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_msg_parse: "
- "state=%d for add or update should be MATURE=%d.\n",
- ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state,
- SADB_SASTATE_MATURE);
- SENDERR(EINVAL);
- }
-
- /* check AH and ESP */
- switch(((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype) {
- case SADB_SATYPE_AH:
- if(!(((struct sadb_sa*)extensions[SADB_EXT_SA]) &&
- ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_auth !=
- SADB_AALG_NONE)) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_msg_parse: "
- "auth alg is zero, must be non-zero for AH SAs.\n");
- SENDERR(EINVAL);
- }
- if(((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_encrypt !=
- SADB_EALG_NONE) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_msg_parse: "
- "AH handed encalg=%d, must be zero.\n",
- ((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_encrypt);
- SENDERR(EINVAL);
- }
- break;
- case SADB_SATYPE_ESP:
- if(!(((struct sadb_sa*)extensions[SADB_EXT_SA]) &&
- ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt !=
- SADB_EALG_NONE)) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_msg_parse: "
- "encrypt alg=%d is zero, must be non-zero for ESP=%d SAs.\n",
- ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt,
- ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype);
- SENDERR(EINVAL);
- }
- if((((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_encrypt ==
- SADB_EALG_NULL) &&
- (((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_auth ==
- SADB_AALG_NONE) ) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_msg_parse: "
- "ESP handed encNULL+authNONE, illegal combination.\n");
- SENDERR(EINVAL);
- }
- break;
- case SADB_X_SATYPE_COMP:
- if(!(((struct sadb_sa*)extensions[SADB_EXT_SA]) &&
- ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt !=
- SADB_EALG_NONE)) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_msg_parse: "
- "encrypt alg=%d is zero, must be non-zero for COMP=%d SAs.\n",
- ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt,
- ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype);
- SENDERR(EINVAL);
- }
- if(((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_auth !=
- SADB_AALG_NONE) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_msg_parse: "
- "COMP handed auth=%d, must be zero.\n",
- ((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_auth);
- SENDERR(EINVAL);
- }
- break;
- default:
- break;
- }
- if(ntohl(((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_spi) <= 255) {
- DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
- "pfkey_msg_parse: "
- "spi=%08x must be > 255.\n",
- ntohl(((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_spi));
- SENDERR(EINVAL);
- }
- default:
- break;
- }
-errlab:
-
- return error;
-}
diff --git a/src/libfreeswan/pfkeyv2.h b/src/libfreeswan/pfkeyv2.h
deleted file mode 100644
index 725997ebc..000000000
--- a/src/libfreeswan/pfkeyv2.h
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
-RFC 2367 PF_KEY Key Management API July 1998
-
-
-Appendix D: Sample Header File
-
-This file defines structures and symbols for the PF_KEY Version 2
-key management interface. It was written at the U.S. Naval Research
-Laboratory. This file is in the public domain. The authors ask that
-you leave this credit intact on any copies of this file.
-*/
-#ifndef __PFKEY_V2_H
-#define __PFKEY_V2_H 1
-
-#define PF_KEY_V2 2
-#define PFKEYV2_REVISION 199806L
-
-#define SADB_RESERVED 0
-#define SADB_GETSPI 1
-#define SADB_UPDATE 2
-#define SADB_ADD 3
-#define SADB_DELETE 4
-#define SADB_GET 5
-#define SADB_ACQUIRE 6
-#define SADB_REGISTER 7
-#define SADB_EXPIRE 8
-#define SADB_FLUSH 9
-#define SADB_DUMP 10
-#define SADB_X_PROMISC 11
-#define SADB_X_PCHANGE 12
-#define SADB_X_GRPSA 13
-#define SADB_X_ADDFLOW 14
-#define SADB_X_DELFLOW 15
-#define SADB_X_DEBUG 16
-#define SADB_X_NAT_T_NEW_MAPPING 17
-#define SADB_MAX 17
-
-struct sadb_msg {
- uint8_t sadb_msg_version;
- uint8_t sadb_msg_type;
- uint8_t sadb_msg_errno;
- uint8_t sadb_msg_satype;
- uint16_t sadb_msg_len;
- uint16_t sadb_msg_reserved;
- uint32_t sadb_msg_seq;
- uint32_t sadb_msg_pid;
-};
-
-struct sadb_ext {
- uint16_t sadb_ext_len;
- uint16_t sadb_ext_type;
-};
-
-struct sadb_sa {
- uint16_t sadb_sa_len;
- uint16_t sadb_sa_exttype;
- uint32_t sadb_sa_spi;
- uint8_t sadb_sa_replay;
- uint8_t sadb_sa_state;
- uint8_t sadb_sa_auth;
- uint8_t sadb_sa_encrypt;
- uint32_t sadb_sa_flags;
- uint32_t /*IPsecSAref_t*/ sadb_x_sa_ref; /* 32 bits */
- uint8_t sadb_x_reserved[4];
-};
-
-struct sadb_sa_v1 {
- uint16_t sadb_sa_len;
- uint16_t sadb_sa_exttype;
- uint32_t sadb_sa_spi;
- uint8_t sadb_sa_replay;
- uint8_t sadb_sa_state;
- uint8_t sadb_sa_auth;
- uint8_t sadb_sa_encrypt;
- uint32_t sadb_sa_flags;
-};
-
-struct sadb_lifetime {
- uint16_t sadb_lifetime_len;
- uint16_t sadb_lifetime_exttype;
- uint32_t sadb_lifetime_allocations;
- uint64_t sadb_lifetime_bytes;
- uint64_t sadb_lifetime_addtime;
- uint64_t sadb_lifetime_usetime;
- uint32_t sadb_x_lifetime_packets;
- uint32_t sadb_x_lifetime_reserved;
-};
-
-struct sadb_address {
- uint16_t sadb_address_len;
- uint16_t sadb_address_exttype;
- uint8_t sadb_address_proto;
- uint8_t sadb_address_prefixlen;
- uint16_t sadb_address_reserved;
-};
-
-struct sadb_key {
- uint16_t sadb_key_len;
- uint16_t sadb_key_exttype;
- uint16_t sadb_key_bits;
- uint16_t sadb_key_reserved;
-};
-
-struct sadb_ident {
- uint16_t sadb_ident_len;
- uint16_t sadb_ident_exttype;
- uint16_t sadb_ident_type;
- uint16_t sadb_ident_reserved;
- uint64_t sadb_ident_id;
-};
-
-struct sadb_sens {
- uint16_t sadb_sens_len;
- uint16_t sadb_sens_exttype;
- uint32_t sadb_sens_dpd;
- uint8_t sadb_sens_sens_level;
- uint8_t sadb_sens_sens_len;
- uint8_t sadb_sens_integ_level;
- uint8_t sadb_sens_integ_len;
- uint32_t sadb_sens_reserved;
-};
-
-struct sadb_prop {
- uint16_t sadb_prop_len;
- uint16_t sadb_prop_exttype;
- uint8_t sadb_prop_replay;
- uint8_t sadb_prop_reserved[3];
-};
-
-struct sadb_comb {
- uint8_t sadb_comb_auth;
- uint8_t sadb_comb_encrypt;
- uint16_t sadb_comb_flags;
- uint16_t sadb_comb_auth_minbits;
- uint16_t sadb_comb_auth_maxbits;
- uint16_t sadb_comb_encrypt_minbits;
- uint16_t sadb_comb_encrypt_maxbits;
- uint32_t sadb_comb_reserved;
- uint32_t sadb_comb_soft_allocations;
- uint32_t sadb_comb_hard_allocations;
- uint64_t sadb_comb_soft_bytes;
- uint64_t sadb_comb_hard_bytes;
- uint64_t sadb_comb_soft_addtime;
- uint64_t sadb_comb_hard_addtime;
- uint64_t sadb_comb_soft_usetime;
- uint64_t sadb_comb_hard_usetime;
- uint32_t sadb_x_comb_soft_packets;
- uint32_t sadb_x_comb_hard_packets;
-};
-
-struct sadb_supported {
- uint16_t sadb_supported_len;
- uint16_t sadb_supported_exttype;
- uint32_t sadb_supported_reserved;
-};
-
-struct sadb_alg {
- uint8_t sadb_alg_id;
- uint8_t sadb_alg_ivlen;
- uint16_t sadb_alg_minbits;
- uint16_t sadb_alg_maxbits;
- uint16_t sadb_alg_reserved;
-};
-
-struct sadb_spirange {
- uint16_t sadb_spirange_len;
- uint16_t sadb_spirange_exttype;
- uint32_t sadb_spirange_min;
- uint32_t sadb_spirange_max;
- uint32_t sadb_spirange_reserved;
-};
-
-struct sadb_x_kmprivate {
- uint16_t sadb_x_kmprivate_len;
- uint16_t sadb_x_kmprivate_exttype;
- uint32_t sadb_x_kmprivate_reserved;
-};
-
-struct sadb_x_satype {
- uint16_t sadb_x_satype_len;
- uint16_t sadb_x_satype_exttype;
- uint8_t sadb_x_satype_satype;
- uint8_t sadb_x_satype_reserved[3];
-};
-
-struct sadb_x_policy {
- uint16_t sadb_x_policy_len;
- uint16_t sadb_x_policy_exttype;
- uint16_t sadb_x_policy_type;
- uint8_t sadb_x_policy_dir;
- uint8_t sadb_x_policy_reserved;
- uint32_t sadb_x_policy_id;
- uint32_t sadb_x_policy_reserved2;
-};
-
-struct sadb_x_debug {
- uint16_t sadb_x_debug_len;
- uint16_t sadb_x_debug_exttype;
- uint32_t sadb_x_debug_tunnel;
- uint32_t sadb_x_debug_netlink;
- uint32_t sadb_x_debug_xform;
- uint32_t sadb_x_debug_eroute;
- uint32_t sadb_x_debug_spi;
- uint32_t sadb_x_debug_radij;
- uint32_t sadb_x_debug_esp;
- uint32_t sadb_x_debug_ah;
- uint32_t sadb_x_debug_rcv;
- uint32_t sadb_x_debug_pfkey;
- uint32_t sadb_x_debug_ipcomp;
- uint32_t sadb_x_debug_verbose;
- uint8_t sadb_x_debug_reserved[4];
-};
-
-struct sadb_x_nat_t_type {
- uint16_t sadb_x_nat_t_type_len;
- uint16_t sadb_x_nat_t_type_exttype;
- uint8_t sadb_x_nat_t_type_type;
- uint8_t sadb_x_nat_t_type_reserved[3];
-};
-struct sadb_x_nat_t_port {
- uint16_t sadb_x_nat_t_port_len;
- uint16_t sadb_x_nat_t_port_exttype;
- uint16_t sadb_x_nat_t_port_port;
- uint16_t sadb_x_nat_t_port_reserved;
-};
-
-/*
- * A protocol structure for passing through the transport level
- * protocol. It contains more fields than are actually used/needed
- * but it is this way to be compatible with the structure used in
- * OpenBSD (http://www.openbsd.org/cgi-bin/cvsweb/src/sys/net/pfkeyv2.h)
- */
-struct sadb_protocol {
- uint16_t sadb_protocol_len;
- uint16_t sadb_protocol_exttype;
- uint8_t sadb_protocol_proto;
- uint8_t sadb_protocol_direction;
- uint8_t sadb_protocol_flags;
- uint8_t sadb_protocol_reserved2;
-};
-
-#define SADB_EXT_RESERVED 0
-#define SADB_EXT_SA 1
-#define SADB_EXT_LIFETIME_CURRENT 2
-#define SADB_EXT_LIFETIME_HARD 3
-#define SADB_EXT_LIFETIME_SOFT 4
-#define SADB_EXT_ADDRESS_SRC 5
-#define SADB_EXT_ADDRESS_DST 6
-#define SADB_EXT_ADDRESS_PROXY 7
-#define SADB_EXT_KEY_AUTH 8
-#define SADB_EXT_KEY_ENCRYPT 9
-#define SADB_EXT_IDENTITY_SRC 10
-#define SADB_EXT_IDENTITY_DST 11
-#define SADB_EXT_SENSITIVITY 12
-#define SADB_EXT_PROPOSAL 13
-#define SADB_EXT_SUPPORTED_AUTH 14
-#define SADB_EXT_SUPPORTED_ENCRYPT 15
-#define SADB_EXT_SPIRANGE 16
-#define SADB_X_EXT_KMPRIVATE 17
-#define SADB_X_EXT_SATYPE2 18
-#ifdef KERNEL26_HAS_KAME_DUPLICATES
-#define SADB_X_EXT_POLICY 18
-#endif
-#define SADB_X_EXT_SA2 19
-#define SADB_X_EXT_ADDRESS_DST2 20
-#define SADB_X_EXT_ADDRESS_SRC_FLOW 21
-#define SADB_X_EXT_ADDRESS_DST_FLOW 22
-#define SADB_X_EXT_ADDRESS_SRC_MASK 23
-#define SADB_X_EXT_ADDRESS_DST_MASK 24
-#define SADB_X_EXT_DEBUG 25
-#define SADB_X_EXT_PROTOCOL 26
-#define SADB_X_EXT_NAT_T_TYPE 27
-#define SADB_X_EXT_NAT_T_SPORT 28
-#define SADB_X_EXT_NAT_T_DPORT 29
-#define SADB_X_EXT_NAT_T_OA 30
-#define SADB_EXT_MAX 30
-
-/* SADB_X_DELFLOW required over and above SADB_X_SAFLAGS_CLEARFLOW */
-#define SADB_X_EXT_ADDRESS_DELFLOW \
- ( (1<<SADB_X_EXT_ADDRESS_SRC_FLOW) \
- | (1<<SADB_X_EXT_ADDRESS_DST_FLOW) \
- | (1<<SADB_X_EXT_ADDRESS_SRC_MASK) \
- | (1<<SADB_X_EXT_ADDRESS_DST_MASK))
-
-#define SADB_SATYPE_UNSPEC 0
-#define SADB_SATYPE_AH 2
-#define SADB_SATYPE_ESP 3
-#define SADB_SATYPE_RSVP 5
-#define SADB_SATYPE_OSPFV2 6
-#define SADB_SATYPE_RIPV2 7
-#define SADB_SATYPE_MIP 8
-#define SADB_X_SATYPE_IPIP 9
-#ifdef KERNEL26_HAS_KAME_DUPLICATES
-#define SADB_X_SATYPE_IPCOMP 9 /* ICK! */
-#endif
-#define SADB_X_SATYPE_COMP 10
-#define SADB_X_SATYPE_INT 11
-#define SADB_SATYPE_MAX 11
-
-#define SADB_SASTATE_LARVAL 0
-#define SADB_SASTATE_MATURE 1
-#define SADB_SASTATE_DYING 2
-#define SADB_SASTATE_DEAD 3
-#define SADB_SASTATE_MAX 3
-
-#define SADB_SAFLAGS_PFS 1
-#define SADB_X_SAFLAGS_REPLACEFLOW 2
-#define SADB_X_SAFLAGS_CLEARFLOW 4
-#define SADB_X_SAFLAGS_INFLOW 8
-
-/* Authentication algorithms */
-#define SADB_AALG_NONE 0
-#define SADB_AALG_MD5HMAC 2
-#define SADB_AALG_SHA1HMAC 3
-#define SADB_X_AALG_SHA2_256HMAC 5
-#define SADB_X_AALG_SHA2_384HMAC 6
-#define SADB_X_AALG_SHA2_512HMAC 7
-#define SADB_X_AALG_RIPEMD160HMAC 8
-#define SADB_X_AALG_AES_XCBC_MAC 9
-#define SADB_X_AALG_NULL 251 /* kame */
-#define SADB_X_AALG_SHA2_256_96HMAC 252
-#define SADB_AALG_MAX 252
-
-/* Encryption algorithms */
-#define SADB_EALG_NONE 0
-#define SADB_EALG_DESCBC 2
-#define SADB_EALG_3DESCBC 3
-#define SADB_X_EALG_CASTCBC 6
-#define SADB_X_EALG_BLOWFISHCBC 7
-#define SADB_EALG_NULL 11
-#define SADB_X_EALG_AESCBC 12
-#define SADB_X_EALG_AESCTR 13
-#define SADB_X_EALG_AES_CCM_ICV8 14
-#define SADB_X_EALG_AES_CCM_ICV12 15
-#define SADB_X_EALG_AES_CCM_ICV16 16
-#define SADB_X_EALG_AES_GCM_ICV8 18
-#define SADB_X_EALG_AES_GCM_ICV12 19
-#define SADB_X_EALG_AES_GCM_ICV16 20
-#define SADB_X_EALG_CAMELLIACBC 22
-#define SADB_X_EALG_NULL_AES_GMAC 23
-#define SADB_EALG_MAX 253 /* last EALG */
-/* private allocations should use 249-255 (RFC2407) */
-#define SADB_X_EALG_SERPENTCBC 252 /* draft-ietf-ipsec-ciph-aes-cbc-00 */
-#define SADB_X_EALG_TWOFISHCBC 253 /* draft-ietf-ipsec-ciph-aes-cbc-00 */
-
-/* Compression algorithms */
-#define SADB_X_CALG_NONE 0
-#define SADB_X_CALG_OUI 1
-#define SADB_X_CALG_DEFLATE 2
-#define SADB_X_CALG_LZS 3
-#define SADB_X_CALG_LZJH 4
-#define SADB_X_CALG_MAX 4
-
-#define SADB_X_TALG_NONE 0
-#define SADB_X_TALG_IPv4_in_IPv4 1
-#define SADB_X_TALG_IPv6_in_IPv4 2
-#define SADB_X_TALG_IPv4_in_IPv6 3
-#define SADB_X_TALG_IPv6_in_IPv6 4
-#define SADB_X_TALG_MAX 4
-
-/* Identity Extension values */
-#define SADB_IDENTTYPE_RESERVED 0
-#define SADB_IDENTTYPE_PREFIX 1
-#define SADB_IDENTTYPE_FQDN 2
-#define SADB_IDENTTYPE_USERFQDN 3
-#define SADB_IDENTTYPE_MAX 3
-
-#endif /* __PFKEY_V2_H */
diff --git a/src/libfreeswan/portof.3 b/src/libfreeswan/portof.3
deleted file mode 100644
index 112def560..000000000
--- a/src/libfreeswan/portof.3
+++ /dev/null
@@ -1,69 +0,0 @@
-.TH IPSEC_PORTOF 3 "8 Sept 2000"
-.SH NAME
-ipsec portof \- get port field of an ip_address
-.br
-ipsec setportof \- set port field of an ip_address
-.br
-ipsec sockaddrof \- get pointer to internal sockaddr of an ip_address
-.br
-ipsec sockaddrlenof \- get length of internal sockaddr of an ip_address
-.SH SYNOPSIS
-.B "#include <freeswan.h>"
-.sp
-.B "int portof(const ip_address *src);"
-.br
-.B "void setportof(int port, ip_address *dst);"
-.br
-.B "struct sockaddr *sockaddrof(ip_address *src);"
-.br
-.B "size_t sockaddrlenof(const ip_address *src);"
-.SH DESCRIPTION
-The
-.B <freeswan.h>
-internal type
-.I ip_address
-contains one of the
-.I sockaddr
-types internally.
-\fIReliance on this feature is discouraged\fR,
-but it may occasionally be necessary.
-These functions provide low-level tools for this purpose.
-.PP
-.I Portof
-and
-.I setportof
-respectively read and write the port-number field of the internal
-.IR sockaddr .
-The values are in network byte order.
-.PP
-.I Sockaddrof
-returns a pointer to the internal
-.IR sockaddr ,
-for passing to other functions.
-.PP
-.I Sockaddrlenof
-reports the size of the internal
-.IR sockaddr ,
-for use in storage allocation.
-.SH SEE ALSO
-inet(3), ipsec_initaddr(3)
-.SH DIAGNOSTICS
-.I Portof
-returns
-.BR \-1 ,
-.I sockaddrof
-returns
-.BR NULL ,
-and
-.I sockaddrlenof
-returns
-.B 0
-if an unknown address family is found within the
-.IR ip_address .
-.SH HISTORY
-Written for the FreeS/WAN project by Henry Spencer.
-.SH BUGS
-These functions all depend on low-level details of the
-.I ip_address
-type, which are in principle subject to change.
-Avoid using them unless really necessary.
diff --git a/src/libfreeswan/portof.c b/src/libfreeswan/portof.c
deleted file mode 100644
index c44b839f3..000000000
--- a/src/libfreeswan/portof.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * low-level ip_address ugliness
- * Copyright (C) 2000 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-#include <sys/socket.h>
-
-#include "internal.h"
-#include "freeswan.h"
-
-/*
- - portof - get the port field of an ip_address
- */
-int /* network order */
-portof(src)
-const ip_address *src;
-{
- switch (src->u.v4.sin_family) {
- case AF_INET:
- return src->u.v4.sin_port;
- break;
- case AF_INET6:
- return src->u.v6.sin6_port;
- break;
- default:
- return -1; /* "can't happen" */
- break;
- }
-}
-
-/*
- - setportof - set the port field of an ip_address
- */
-void
-setportof(port, dst)
-int port; /* network order */
-ip_address *dst;
-{
- switch (dst->u.v4.sin_family) {
- case AF_INET:
- dst->u.v4.sin_port = port;
- break;
- case AF_INET6:
- dst->u.v6.sin6_port = port;
- break;
- }
-}
-
-/*
- - sockaddrof - get a pointer to the sockaddr hiding inside an ip_address
- */
-struct sockaddr *
-sockaddrof(src)
-ip_address *src;
-{
- switch (src->u.v4.sin_family) {
- case AF_INET:
- return (struct sockaddr *)&src->u.v4;
- break;
- case AF_INET6:
- return (struct sockaddr *)&src->u.v6;
- break;
- default:
- return NULL; /* "can't happen" */
- break;
- }
-}
-
-/*
- - sockaddrlenof - get length of the sockaddr hiding inside an ip_address
- */
-size_t /* 0 for error */
-sockaddrlenof(src)
-const ip_address *src;
-{
- switch (src->u.v4.sin_family) {
- case AF_INET:
- return sizeof(src->u.v4);
- break;
- case AF_INET6:
- return sizeof(src->u.v6);
- break;
- default:
- return 0;
- break;
- }
-}
diff --git a/src/libfreeswan/rangetoa.c b/src/libfreeswan/rangetoa.c
deleted file mode 100644
index 704558248..000000000
--- a/src/libfreeswan/rangetoa.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * convert binary form of address range to ASCII
- * Copyright (C) 1998, 1999 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-#include "internal.h"
-#include "freeswan.h"
-
-/*
- - rangetoa - convert address range to ASCII
- */
-size_t /* space needed for full conversion */
-rangetoa(addrs, format, dst, dstlen)
-struct in_addr addrs[2];
-int format; /* character */
-char *dst; /* need not be valid if dstlen is 0 */
-size_t dstlen;
-{
- size_t len;
- size_t rest;
- int n;
- char *p;
-
- switch (format) {
- case 0:
- break;
- default:
- return 0;
- break;
- }
-
- len = addrtoa(addrs[0], 0, dst, dstlen);
- if (len < dstlen)
- for (p = dst + len - 1, n = 3; len < dstlen && n > 0;
- p++, len++, n--)
- *p = '.';
- else
- p = NULL;
- if (len < dstlen)
- rest = dstlen - len;
- else {
- if (dstlen > 0)
- *(dst + dstlen - 1) = '\0';
- rest = 0;
- }
-
- len += addrtoa(addrs[1], 0, p, rest);
-
- return len;
-}
diff --git a/src/libfreeswan/rangetosubnet.3 b/src/libfreeswan/rangetosubnet.3
deleted file mode 100644
index 100b42bd9..000000000
--- a/src/libfreeswan/rangetosubnet.3
+++ /dev/null
@@ -1,58 +0,0 @@
-.TH IPSEC_RANGETOSUBNET 3 "8 Sept 2000"
-.SH NAME
-ipsec rangetosubnet \- convert address range to subnet
-.SH SYNOPSIS
-.B "#include <freeswan.h>"
-.sp
-.B "const char *rangetosubnet(const ip_address *start,"
-.ti +1c
-.B "const ip_address *stop, ip_subnet *dst);"
-.SH DESCRIPTION
-.I Rangetosubnet
-accepts two IP addresses which define an address range,
-from
-.I start
-to
-.I stop
-inclusive,
-and converts this to a subnet if possible.
-The addresses must both be IPv4 or both be IPv6,
-and the address family of the resulting subnet is the same.
-.PP
-.I Rangetosubnet
-returns NULL for success and
-a pointer to a string-literal error message for failure;
-see DIAGNOSTICS.
-.SH SEE ALSO
-ipsec_initsubnet(3), ipsec_ttosubnet(3)
-.SH DIAGNOSTICS
-Fatal errors in
-.I rangetosubnet
-are:
-mixed address families;
-unknown address family;
-.I start
-and
-.I stop
-do not define a subnet.
-.SH HISTORY
-Written for the FreeS/WAN project by Henry Spencer.
-.SH BUGS
-The restriction of error reports to literal strings
-(so that callers don't need to worry about freeing them or copying them)
-does limit the precision of error reporting.
-.PP
-The error-reporting convention lends itself
-to slightly obscure code,
-because many readers will not think of NULL as signifying success.
-A good way to make it clearer is to write something like:
-.PP
-.RS
-.nf
-.B "const char *error;"
-.sp
-.B "error = rangetosubnet( /* ... */ );"
-.B "if (error != NULL) {"
-.B " /* something went wrong */"
-.fi
-.RE
diff --git a/src/libfreeswan/rangetosubnet.c b/src/libfreeswan/rangetosubnet.c
deleted file mode 100644
index 2a989300e..000000000
--- a/src/libfreeswan/rangetosubnet.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * express an address range as a subnet (if possible)
- * Copyright (C) 2000 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-#include "internal.h"
-#include "freeswan.h"
-
-/*
- - rangetosubnet - turn an address range into a subnet, if possible
- *
- * A range which is a valid subnet will have a network part which is the
- * same in the from value and the to value, followed by a host part which
- * is all 0 in the from value and all 1 in the to value.
- */
-err_t
-rangetosubnet(from, to, dst)
-const ip_address *from;
-const ip_address *to;
-ip_subnet *dst;
-{
- unsigned const char *fp;
- unsigned const char *tp;
- unsigned fb;
- unsigned tb;
- unsigned const char *f;
- unsigned const char *t;
- size_t n;
- size_t n2;
- int i;
- int nnet;
- unsigned m;
-
- if (addrtypeof(from) != addrtypeof(to))
- return "mismatched address types";
- n = addrbytesptr(from, &fp);
- if (n == 0)
- return "unknown address type";
- n2 = addrbytesptr(to, &tp);
- if (n != n2)
- return "internal size mismatch in rangetosubnet";
-
- f = fp;
- t = tp;
- nnet = 0;
- for (i = n; i > 0 && *f == *t; i--, f++, t++)
- nnet += 8;
- if (i > 0 && !(*f == 0x00 && *t == 0xff)) { /* mid-byte bdry. */
- fb = *f++;
- tb = *t++;
- i--;
- m = 0x80;
- while ((fb&m) == (tb&m)) {
- fb &= ~m;
- tb |= m;
- m >>= 1;
- nnet++;
- }
- if (fb != 0x00 || tb != 0xff)
- return "not a valid subnet";
- }
- for (; i > 0 && *f == 0x00 && *t == 0xff; i--, f++, t++)
- continue;
-
- if (i != 0)
- return "invalid subnet";
-
- return initsubnet(from, nnet, 'x', dst);
-}
-
-
-
-#ifdef RANGETOSUBNET_MAIN
-
-#include <stdio.h>
-
-void regress(void);
-
-int
-main(int argc, char *argv[])
-{
- ip_address start;
- ip_address stop;
- ip_subnet sub;
- char buf[100];
- const char *oops;
- size_t n;
- int af;
- int i;
-
- if (argc == 2 && strcmp(argv[1], "-r") == 0) {
- regress();
- fprintf(stderr, "regress() returned?!?\n");
- exit(1);
- }
-
- if (argc < 3) {
- fprintf(stderr, "Usage: %s [-6] start stop\n", argv[0]);
- fprintf(stderr, " or: %s -r\n", argv[0]);
- exit(2);
- }
-
- af = AF_INET;
- i = 1;
- if (strcmp(argv[i], "-6") == 0) {
- af = AF_INET6;
- i++;
- }
-
- oops = ttoaddr(argv[i], 0, af, &start);
- if (oops != NULL) {
- fprintf(stderr, "%s: start conversion failed: %s\n", argv[0], oops);
- exit(1);
- }
- oops = ttoaddr(argv[i+1], 0, af, &stop);
- if (oops != NULL) {
- fprintf(stderr, "%s: stop conversion failed: %s\n", argv[0], oops);
- exit(1);
- }
- oops = rangetosubnet(&start, &stop, &sub);
- if (oops != NULL) {
- fprintf(stderr, "%s: rangetosubnet failed: %s\n", argv[0], oops);
- exit(1);
- }
- n = subnettot(&sub, 0, buf, sizeof(buf));
- if (n > sizeof(buf)) {
- fprintf(stderr, "%s: reverse conversion", argv[0]);
- fprintf(stderr, " failed: need %ld bytes, have only %ld\n",
- (long)n, (long)sizeof(buf));
- exit(1);
- }
- printf("%s\n", buf);
-
- exit(0);
-}
-
-struct rtab {
- int family;
- char *start;
- char *stop;
- char *output; /* NULL means error expected */
-} rtab[] = {
- {4, "1.2.3.0", "1.2.3.255", "1.2.3.0/24"},
- {4, "1.2.3.0", "1.2.3.7", "1.2.3.0/29"},
- {4, "1.2.3.240", "1.2.3.255", "1.2.3.240/28"},
- {4, "0.0.0.0", "255.255.255.255", "0.0.0.0/0"},
- {4, "1.2.3.4", "1.2.3.4", "1.2.3.4/32"},
- {4, "1.2.3.0", "1.2.3.254", NULL},
- {4, "1.2.3.0", "1.2.3.126", NULL},
- {4, "1.2.3.0", "1.2.3.125", NULL},
- {4, "1.2.0.0", "1.2.255.255", "1.2.0.0/16"},
- {4, "1.2.0.0", "1.2.0.255", "1.2.0.0/24"},
- {4, "1.2.255.0", "1.2.255.255", "1.2.255.0/24"},
- {4, "1.2.255.0", "1.2.254.255", NULL},
- {4, "1.2.255.1", "1.2.255.255", NULL},
- {4, "1.2.0.1", "1.2.255.255", NULL},
- {6, "1:2:3:4:5:6:7:0", "1:2:3:4:5:6:7:ffff", "1:2:3:4:5:6:7:0/112"},
- {6, "1:2:3:4:5:6:7:0", "1:2:3:4:5:6:7:fff", "1:2:3:4:5:6:7:0/116"},
- {6, "1:2:3:4:5:6:7:f0", "1:2:3:4:5:6:7:ff", "1:2:3:4:5:6:7:f0/124"},
- {4, NULL, NULL, NULL},
-};
-
-void
-regress()
-{
- struct rtab *r;
- int status = 0;
- ip_address start;
- ip_address stop;
- ip_subnet sub;
- char buf[100];
- const char *oops;
- size_t n;
- int af;
-
- for (r = rtab; r->start != NULL; r++) {
- af = (r->family == 4) ? AF_INET : AF_INET6;
- oops = ttoaddr(r->start, 0, af, &start);
- if (oops != NULL) {
- printf("surprise failure converting `%s'\n", r->start);
- exit(1);
- }
- oops = ttoaddr(r->stop, 0, af, &stop);
- if (oops != NULL) {
- printf("surprise failure converting `%s'\n", r->stop);
- exit(1);
- }
- oops = rangetosubnet(&start, &stop, &sub);
- if (oops != NULL && r->output == NULL)
- {} /* okay, error expected */
- else if (oops != NULL) {
- printf("`%s'-`%s' rangetosubnet failed: %s\n",
- r->start, r->stop, oops);
- status = 1;
- } else if (r->output == NULL) {
- printf("`%s'-`%s' rangetosubnet succeeded unexpectedly\n",
- r->start, r->stop);
- status = 1;
- } else {
- n = subnettot(&sub, 0, buf, sizeof(buf));
- if (n > sizeof(buf)) {
- printf("`%s'-`%s' subnettot failed: need %ld\n",
- r->start, r->stop, (long)n);
- status = 1;
- } else if (strcmp(r->output, buf) != 0) {
- printf("`%s'-`%s' gave `%s', expected `%s'\n",
- r->start, r->stop, buf, r->output);
- status = 1;
- }
- }
- }
- exit(status);
-}
-
-#endif /* RANGETOSUBNET_MAIN */
diff --git a/src/libfreeswan/sameaddr.3 b/src/libfreeswan/sameaddr.3
deleted file mode 100644
index 62886bf1a..000000000
--- a/src/libfreeswan/sameaddr.3
+++ /dev/null
@@ -1,164 +0,0 @@
-.TH IPSEC_ANYADDR 3 "28 Nov 2000"
-.SH NAME
-ipsec sameaddr \- are two addresses the same?
-.br
-ipsec addrcmp \- ordered comparison of addresses
-.br
-ipsec samesubnet \- are two subnets the same?
-.br
-ipsec addrinsubnet \- is an address within a subnet?
-.br
-ipsec subnetinsubnet \- is a subnet within another subnet?
-.br
-ipsec subnetishost \- is a subnet a single host?
-.br
-ipsec samesaid \- are two SA IDs the same?
-.br
-ipsec sameaddrtype \- are two addresses of the same address family?
-.br
-ipsec samesubnettype \- are two subnets of the same address family?
-.SH SYNOPSIS
-.B "#include <freeswan.h>
-.sp
-.B "int sameaddr(const ip_address *a, const ip_address *b);"
-.br
-.B "int addrcmp(const ip_address *a, const ip_address *b);"
-.br
-.B "int samesubnet(const ip_subnet *a, const ip_subnet *b);"
-.br
-.B "int addrinsubnet(const ip_address *a, const ip_subnet *s);"
-.br
-.B "int subnetinsubnet(const ip_subnet *a, const ip_subnet *b);"
-.br
-.B "int subnetishost(const ip_subnet *s);"
-.br
-.B "int samesaid(const ip_said *a, const ip_said *b);"
-.br
-.B "int sameaddrtype(const ip_address *a, const ip_address *b);"
-.br
-.B "int samesubnettype(const ip_subnet *a, const ip_subnet *b);"
-.SH DESCRIPTION
-These functions do various comparisons and tests on the
-.I ip_address
-type and
-.I ip_subnet
-types.
-.PP
-.I Sameaddr
-returns
-non-zero
-if addresses
-.I a
-and
-.IR b
-are identical,
-and
-.B 0
-otherwise.
-Addresses of different families are never identical.
-.PP
-.I Addrcmp
-returns
-.BR \-1 ,
-.BR 0 ,
-or
-.BR 1
-respectively
-if address
-.I a
-is less than, equal to, or greater than
-.IR b .
-If they are not of the same address family,
-they are never equal;
-the ordering reported in this case is arbitrary
-(and probably not useful) but consistent.
-.PP
-.I Samesubnet
-returns
-non-zero
-if subnets
-.I a
-and
-.IR b
-are identical,
-and
-.B 0
-otherwise.
-Subnets of different address families are never identical.
-.PP
-.I Addrinsubnet
-returns
-non-zero
-if address
-.I a
-is within subnet
-.IR s
-and
-.B 0
-otherwise.
-An address is never within a
-subnet of a different address family.
-.PP
-.I Subnetinsubnet
-returns
-non-zero
-if subnet
-.I a
-is a subset of subnet
-.IR b
-and
-.B 0
-otherwise.
-A subnet is deemed to be a subset of itself.
-A subnet is never a subset of another
-subnet if their address families differ.
-.PP
-.I Subnetishost
-returns
-non-zero
-if subnet
-.I s
-is in fact only a single host,
-and
-.B 0
-otherwise.
-.PP
-.I Samesaid
-returns
-non-zero
-if SA IDs
-.I a
-and
-.IR b
-are identical,
-and
-.B 0
-otherwise.
-.PP
-.I Sameaddrtype
-returns
-non-zero
-if addresses
-.I a
-and
-.IR b
-are of the same address family,
-and
-.B 0
-otherwise.
-.PP
-.I Samesubnettype
-returns
-non-zero
-if subnets
-.I a
-and
-.IR b
-are of the same address family,
-and
-.B 0
-otherwise.
-.SH SEE ALSO
-inet(3), ipsec_initaddr(3)
-.SH HISTORY
-Written for the FreeS/WAN project by Henry Spencer.
diff --git a/src/libfreeswan/sameaddr.c b/src/libfreeswan/sameaddr.c
deleted file mode 100644
index 47daaa4ee..000000000
--- a/src/libfreeswan/sameaddr.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * comparisons
- * Copyright (C) 2000 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-#include "internal.h"
-#include "freeswan.h"
-
-static int samenbits(const ip_address *a, const ip_address *b, int n);
-
-/*
- - addrcmp - compare two addresses
- * Caution, the order of the tests is subtle: doing type test before
- * size test can yield cases where a<b, b<c, but a>c.
- */
-int /* like memcmp */
-addrcmp(a, b)
-const ip_address *a;
-const ip_address *b;
-{
- int at = addrtypeof(a);
- int bt = addrtypeof(b);
- const unsigned char *ap;
- const unsigned char *bp;
- size_t as = addrbytesptr(a, &ap);
- size_t bs = addrbytesptr(b, &bp);
- size_t n = (as < bs) ? as : bs; /* min(as, bs) */
- int c = memcmp(ap, bp, n);
-
- if (c != 0) /* bytes differ */
- return (c < 0) ? -1 : 1;
- if (as != bs) /* comparison incomplete: lexical order */
- return (as < bs) ? -1 : 1;
- if (at != bt) /* bytes same but not same type: break tie */
- return (at < bt) ? -1 : 1;
- return 0;
-}
-
-/*
- - sameaddr - are two addresses the same?
- */
-int
-sameaddr(a, b)
-const ip_address *a;
-const ip_address *b;
-{
- return (addrcmp(a, b) == 0) ? 1 : 0;
-}
-
-/*
- - samesubnet - are two subnets the same?
- */
-int
-samesubnet(a, b)
-const ip_subnet *a;
-const ip_subnet *b;
-{
- if (!sameaddr(&a->addr, &b->addr)) /* also does type check */
- return 0;
- if (a->maskbits != b->maskbits)
- return 0;
- return 1;
-}
-
-/*
- - subnetishost - is a subnet in fact a single host?
- */
-int
-subnetishost(a)
-const ip_subnet *a;
-{
- return (a->maskbits == addrlenof(&a->addr)*8) ? 1 : 0;
-}
-
-/*
- - samesaid - are two SA IDs the same?
- */
-int
-samesaid(a, b)
-const ip_said *a;
-const ip_said *b;
-{
- if (a->spi != b->spi) /* test first, most likely to be different */
- return 0;
- if (!sameaddr(&a->dst, &b->dst))
- return 0;
- if (a->proto != b->proto)
- return 0;
- return 1;
-}
-
-/*
- - sameaddrtype - do two addresses have the same type?
- */
-int
-sameaddrtype(a, b)
-const ip_address *a;
-const ip_address *b;
-{
- return (addrtypeof(a) == addrtypeof(b)) ? 1 : 0;
-}
-
-/*
- - samesubnettype - do two subnets have the same type?
- */
-int
-samesubnettype(a, b)
-const ip_subnet *a;
-const ip_subnet *b;
-{
- return (subnettypeof(a) == subnettypeof(b)) ? 1 : 0;
-}
-
-/*
- - addrinsubnet - is this address in this subnet?
- */
-int
-addrinsubnet(a, s)
-const ip_address *a;
-const ip_subnet *s;
-{
- if (addrtypeof(a) != subnettypeof(s))
- return 0;
- if (!samenbits(a, &s->addr, s->maskbits))
- return 0;
- return 1;
-}
-
-/*
- - subnetinsubnet - is one subnet within another?
- */
-int
-subnetinsubnet(a, b)
-const ip_subnet *a;
-const ip_subnet *b;
-{
- if (subnettypeof(a) != subnettypeof(b))
- return 0;
- if (a->maskbits < b->maskbits) /* a is bigger than b */
- return 0;
- if (!samenbits(&a->addr, &b->addr, b->maskbits))
- return 0;
- return 1;
-}
-
-/*
- - samenbits - do two addresses have the same first n bits?
- */
-static int
-samenbits(a, b, nbits)
-const ip_address *a;
-const ip_address *b;
-int nbits;
-{
- const unsigned char *ap;
- const unsigned char *bp;
- size_t n;
- int m;
-
- if (addrtypeof(a) != addrtypeof(b))
- return 0; /* arbitrary */
- n = addrbytesptr(a, &ap);
- if (n == 0)
- return 0; /* arbitrary */
- (void) addrbytesptr(b, &bp);
- if (nbits > n*8)
- return 0; /* "can't happen" */
-
- for (; nbits >= 8 && *ap == *bp; nbits -= 8, ap++, bp++)
- continue;
- if (nbits >= 8)
- return 0;
- if (nbits > 0) { /* partial byte */
- m = ~(0xff >> nbits);
- if ((*ap & m) != (*bp & m))
- return 0;
- }
- return 1;
-}
diff --git a/src/libfreeswan/satot.c b/src/libfreeswan/satot.c
deleted file mode 100644
index a3feb1591..000000000
--- a/src/libfreeswan/satot.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * convert from binary form of SA ID to text
- * Copyright (C) 2000, 2001 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-#include <sys/socket.h>
-
-#include "internal.h"
-#include "freeswan.h"
-
-static struct typename {
- char type;
- char *name;
-} typenames[] = {
- { SA_AH, "ah" },
- { SA_ESP, "esp" },
- { SA_IPIP, "tun" },
- { SA_COMP, "comp" },
- { SA_INT, "int" },
- { 0, NULL }
-};
-
-/*
- - satot - convert SA to text "ah507@1.2.3.4"
- */
-size_t /* space needed for full conversion */
-satot(sa, format, dst, dstlen)
-const ip_said *sa;
-int format; /* character */
-char *dst; /* need not be valid if dstlen is 0 */
-size_t dstlen;
-{
- size_t len = 0; /* 0 means "not recognized yet" */
- int base;
- int showversion; /* use delimiter to show IP version? */
- struct typename *tn;
- char *p;
- char *pre;
- char buf[10+1+ULTOT_BUF+ADDRTOT_BUF];
- char unk[10];
-
- switch (format) {
- case 0:
- base = 16;
- showversion = 1;
- break;
- case 'f':
- base = 17;
- showversion = 1;
- break;
- case 'x':
- base = 'x';
- showversion = 0;
- break;
- case 'd':
- base = 10;
- showversion = 0;
- break;
- default:
- return 0;
- break;
- }
-
- pre = NULL;
- for (tn = typenames; tn->name != NULL; tn++)
- if (sa->proto == tn->type) {
- pre = tn->name;
- break; /* NOTE BREAK OUT */
- }
- if (pre == NULL) { /* unknown protocol */
- strncpy(unk, "unk", sizeof(unk));
- (void) ultot((unsigned char)sa->proto, 10, unk+strlen(unk),
- sizeof(unk)-strlen(unk));
- pre = unk;
- }
-
- if (strcmp(pre, PASSTHROUGHTYPE) == 0 &&
- sa->spi == PASSTHROUGHSPI &&
- isunspecaddr(&sa->dst)) {
- strncpy(buf, (addrtypeof(&sa->dst) == AF_INET) ?
- PASSTHROUGH4NAME :
- PASSTHROUGH6NAME, sizeof(buf));
- len = strlen(buf);
- }
-
- if (sa->proto == SA_INT && addrtypeof(&sa->dst) == AF_INET &&
- isunspecaddr(&sa->dst)) {
- switch (ntohl(sa->spi)) {
- case SPI_PASS: p = "%pass"; break;
- case SPI_DROP: p = "%drop"; break;
- case SPI_REJECT: p = "%reject"; break;
- case SPI_HOLD: p = "%hold"; break;
- case SPI_TRAP: p = "%trap"; break;
- case SPI_TRAPSUBNET: p = "%trapsubnet"; break;
- default: p = NULL; break;
- }
- if (p != NULL) {
- strncpy(buf, p, sizeof(buf));
- len = strlen(buf);
- }
- }
-
- if (len == 0) { /* general case needed */
- strncpy(buf, pre, sizeof(buf));
- len = strlen(buf);
- if (showversion) {
- *(buf+len) = (addrtypeof(&sa->dst) == AF_INET) ? '.' :
- ':';
- len++;
- *(buf+len) = '\0';
- }
- len += ultot(ntohl(sa->spi), base, buf+len, sizeof(buf)-len);
- *(buf+len-1) = '@';
- len += addrtot(&sa->dst, 0, buf+len, sizeof(buf)-len);
- }
-
- if (dst != NULL) {
- if (len > dstlen)
- *(buf+dstlen-1) = '\0';
- strncpy(dst, buf, dstlen);
- }
- return len;
-}
diff --git a/src/libfreeswan/subnetof.3 b/src/libfreeswan/subnetof.3
deleted file mode 100644
index aacc76d2c..000000000
--- a/src/libfreeswan/subnetof.3
+++ /dev/null
@@ -1,46 +0,0 @@
-.TH IPSEC_SUBNETOF 3 "11 June 2001"
-.SH NAME
-ipsec subnetof \- given Internet address and subnet mask, return subnet number
-.br
-ipsec hostof \- given Internet address and subnet mask, return host part
-.br
-ipsec broadcastof \- given Internet address and subnet mask, return broadcast address
-.SH SYNOPSIS
-.B "#include <freeswan.h>
-.sp
-.B "struct in_addr subnetof(struct in_addr addr,"
-.ti +1c
-.B "struct in_addr mask);"
-.br
-.B "struct in_addr hostof(struct in_addr addr,"
-.ti +1c
-.B "struct in_addr mask);"
-.br
-.B "struct in_addr broadcastof(struct in_addr addr,"
-.ti +1c
-.B "struct in_addr mask);"
-.SH DESCRIPTION
-These functions are obsolete; see
-.IR ipsec_networkof (3)
-for their replacements.
-.PP
-.I Subnetof
-takes an Internet
-.I address
-and a subnet
-.I mask
-and returns the network part of the address
-(all in network byte order).
-.I Hostof
-similarly returns the host part, and
-.I broadcastof
-returns the broadcast address (all-1s convention) for the network.
-.PP
-These functions are provided to hide the Internet bit-munging inside
-an API, in hopes of easing the eventual transition to IPv6.
-.SH SEE ALSO
-inet(3), ipsec_atosubnet(3)
-.SH HISTORY
-Written for the FreeS/WAN project by Henry Spencer.
-.SH BUGS
-Calling functions for this is more costly than doing it yourself.
diff --git a/src/libfreeswan/subnetof.c b/src/libfreeswan/subnetof.c
deleted file mode 100644
index ec9b8ec7d..000000000
--- a/src/libfreeswan/subnetof.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * minor network-address manipulation utilities
- * Copyright (C) 1998, 1999 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-#include "internal.h"
-#include "freeswan.h"
-
-/*
- - subnetof - given address and mask, return subnet part
- */
-struct in_addr
-subnetof(addr, mask)
-struct in_addr addr;
-struct in_addr mask;
-{
- struct in_addr result;
-
- result.s_addr = addr.s_addr & mask.s_addr;
- return result;
-}
-
-/*
- - hostof - given address and mask, return host part
- */
-struct in_addr
-hostof(addr, mask)
-struct in_addr addr;
-struct in_addr mask;
-{
- struct in_addr result;
-
- result.s_addr = addr.s_addr & ~mask.s_addr;
- return result;
-}
-
-/*
- - broadcastof - given (network) address and mask, return broadcast address
- */
-struct in_addr
-broadcastof(addr, mask)
-struct in_addr addr;
-struct in_addr mask;
-{
- struct in_addr result;
-
- result.s_addr = addr.s_addr | ~mask.s_addr;
- return result;
-}
diff --git a/src/libfreeswan/subnettoa.c b/src/libfreeswan/subnettoa.c
deleted file mode 100644
index 694fa40da..000000000
--- a/src/libfreeswan/subnettoa.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * convert binary form of subnet description to ASCII
- * Copyright (C) 1998, 1999 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-#include "internal.h"
-#include "freeswan.h"
-
-/*
- - subnettoa - convert address and mask to ASCII "addr/mask"
- * Output expresses the mask as a bit count if possible, else dotted decimal.
- */
-size_t /* space needed for full conversion */
-subnettoa(addr, mask, format, dst, dstlen)
-struct in_addr addr;
-struct in_addr mask;
-int format; /* character */
-char *dst; /* need not be valid if dstlen is 0 */
-size_t dstlen;
-{
- size_t len;
- size_t rest;
- int n;
- char *p;
-
- switch (format) {
- case 0:
- break;
- default:
- return 0;
- break;
- }
-
- len = addrtoa(addr, 0, dst, dstlen);
- if (len < dstlen) {
- dst[len - 1] = '/';
- p = dst + len;
- rest = dstlen - len;
- } else {
- p = NULL;
- rest = 0;
- }
-
- n = masktobits(mask);
- if (n >= 0)
- len += ultoa((unsigned long)n, 10, p, rest);
- else
- len += addrtoa(mask, 0, p, rest);
-
- return len;
-}
diff --git a/src/libfreeswan/subnettot.c b/src/libfreeswan/subnettot.c
deleted file mode 100644
index 64d511ba2..000000000
--- a/src/libfreeswan/subnettot.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * convert binary form of subnet description to text
- * Copyright (C) 2000 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-#include "internal.h"
-#include "freeswan.h"
-
-/*
- - subnettot - convert subnet to text "addr/bitcount"
- */
-size_t /* space needed for full conversion */
-subnettot(sub, format, dst, dstlen)
-const ip_subnet *sub;
-int format; /* character */
-char *dst; /* need not be valid if dstlen is 0 */
-size_t dstlen;
-{
- size_t len;
- size_t rest;
- char *p;
-
- switch (format) {
- case 0:
- break;
- default:
- return 0;
- break;
- }
-
- len = addrtot(&sub->addr, format, dst, dstlen);
- if (len < dstlen) {
- dst[len - 1] = '/';
- p = dst + len;
- rest = dstlen - len;
- } else {
- p = NULL;
- rest = 0;
- }
-
-
- len += ultoa((unsigned long)sub->maskbits, 10, p, rest);
-
- return len;
-}
diff --git a/src/libfreeswan/subnettypeof.c b/src/libfreeswan/subnettypeof.c
deleted file mode 100644
index 96c283c04..000000000
--- a/src/libfreeswan/subnettypeof.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * extract parts of an ip_subnet, and related
- * Copyright (C) 2000 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-#include "internal.h"
-#include "freeswan.h"
-
-/*
- - subnettypeof - get the address type of an ip_subnet
- */
-int
-subnettypeof(src)
-const ip_subnet *src;
-{
- return src->addr.u.v4.sin_family;
-}
-
-/*
- - networkof - get the network address of a subnet
- */
-void
-networkof(src, dst)
-const ip_subnet *src;
-ip_address *dst;
-{
- *dst = src->addr;
-}
-
-/*
- - maskof - get the mask of a subnet, as an address
- */
-void
-maskof(src, dst)
-const ip_subnet *src;
-ip_address *dst;
-{
- int b;
- unsigned char buf[16];
- size_t n = addrlenof(&src->addr);
- unsigned char *p;
-
- if (src->maskbits > n*8 || n > sizeof(buf))
- return; /* "can't happen" */
-
- p = buf;
- for (b = src->maskbits; b >= 8; b -= 8)
- *p++ = 0xff;
- if (b != 0)
- *p++ = (0xff << (8 - b)) & 0xff;
- while (p - buf < n)
- *p++ = 0;
-
- (void) initaddr(buf, n, addrtypeof(&src->addr), dst);
-}
-
-/*
- - masktocount - convert a mask, expressed as an address, to a bit count
- */
-int /* -1 if not valid mask */
-masktocount(src)
-const ip_address *src;
-{
- int b;
- unsigned const char *bp;
- size_t n;
- unsigned const char *p;
- unsigned const char *stop;
-
- n = addrbytesptr(src, &bp);
- if (n == 0)
- return -1;
-
- p = bp;
- stop = bp + n;
-
- n = 0;
- while (p < stop && *p == 0xff) {
- p++;
- n += 8;
- }
- if (p < stop && *p != 0) { /* boundary in mid-byte */
- b = *p++;
- while (b&0x80) {
- b <<= 1;
- n++;
- }
- if ((b&0xff) != 0)
- return -1; /* bits not contiguous */
- }
- while (p < stop && *p == 0)
- p++;
-
- if (p != stop)
- return -1;
-
- return n;
-}
diff --git a/src/libfreeswan/ttoaddr.3 b/src/libfreeswan/ttoaddr.3
deleted file mode 100644
index d43d2b16f..000000000
--- a/src/libfreeswan/ttoaddr.3
+++ /dev/null
@@ -1,374 +0,0 @@
-.TH IPSEC_TTOADDR 3 "28 Sept 2001"
-.SH NAME
-ipsec ttoaddr, tnatoaddr, addrtot \- convert Internet addresses to and from text
-.br
-ipsec ttosubnet, subnettot \- convert subnet/mask text form to and from addresses
-.SH SYNOPSIS
-.B "#include <freeswan.h>
-.sp
-.B "const char *ttoaddr(const char *src, size_t srclen,"
-.ti +1c
-.B "int af, ip_address *addr);"
-.br
-.B "const char *tnatoaddr(const char *src, size_t srclen,"
-.ti +1c
-.B "int af, ip_address *addr);"
-.br
-.B "size_t addrtot(const ip_address *addr, int format,"
-.ti +1c
-.B "char *dst, size_t dstlen);"
-.sp
-.B "const char *ttosubnet(const char *src, size_t srclen,"
-.ti +1c
-.B "int af, ip_subnet *dst);"
-.br
-.B "size_t subnettot(const ip_subnet *sub, int format,"
-.ti +1c
-.B "char *dst, size_t dstlen);"
-.SH DESCRIPTION
-.I Ttoaddr
-converts a text-string name or numeric address into a binary address
-(in network byte order).
-.I Tnatoaddr
-does the same conversion,
-but the only text forms it accepts are
-the ``official'' forms of
-numeric address (dotted-decimal for IPv4, colon-hex for IPv6).
-.I Addrtot
-does the reverse conversion, from binary address back to a text form.
-.I Ttosubnet
-and
-.I subnettot
-do likewise for the ``address/mask'' form used to write a
-specification of a subnet.
-.PP
-An IPv4 address is specified in text as a
-dotted-decimal address (e.g.
-.BR 1.2.3.4 ),
-an eight-digit network-order hexadecimal number with the usual C prefix (e.g.
-.BR 0x01020304 ,
-which is synonymous with
-.BR 1.2.3.4 ),
-an eight-digit host-order hexadecimal number with a
-.B 0h
-prefix (e.g.
-.BR 0h01020304 ,
-which is synonymous with
-.B 1.2.3.4
-on a big-endian host and
-.B 4.3.2.1
-on a little-endian host),
-a DNS name to be looked up via
-.IR getaddrinfo (3),
-or an old-style network name to be looked up via
-.IR getnetbyname (3).
-.PP
-A dotted-decimal address may be incomplete, in which case
-text-to-binary conversion implicitly appends
-as many instances of
-.B .0
-as necessary to bring it up to four components.
-The components of a dotted-decimal address are always taken as
-decimal, and leading zeros are ignored.
-For example,
-.B 10
-is synonymous with
-.BR 10.0.0.0 ,
-and
-.B 128.009.000.032
-is synonymous with
-.BR 128.9.0.32
-(the latter example is verbatim from RFC 1166).
-The result of applying
-.I addrtot
-to an IPv4 address is always complete and does not contain leading zeros.
-.PP
-Use of hexadecimal addresses is
-.B strongly
-.BR discouraged ;
-they are included only to save hassles when dealing with
-the handful of perverted programs which already print
-network addresses in hexadecimal.
-.PP
-An IPv6 address is specified in text with
-colon-hex notation (e.g.
-.BR 0:56:78ab:22:33:44:55:66 ),
-colon-hex with
-.B ::
-abbreviating at most one subsequence of multiple zeros (e.g.
-.BR 99:ab::54:068 ,
-which is synonymous with
-.BR 99:ab:0:0:0:0:54:68 ),
-or a DNS name to be looked up via
-.IR getaddrinfo (3).
-The result of applying
-.I addrtot
-to an IPv6 address will use
-.B ::
-abbreviation if possible,
-and will not contain leading zeros.
-.PP
-The letters in hexadecimal
-may be uppercase or lowercase or any mixture thereof.
-.PP
-DNS names may be complete (optionally terminated with a ``.'')
-or incomplete, and are looked up as specified by local system configuration
-(see
-.IR resolver (5)).
-The first value returned by
-.IR getaddrinfo (3)
-is used,
-so with current DNS implementations,
-the result when the name corresponds to more than one address is
-difficult to predict.
-IPv4 name lookup resorts to
-.IR getnetbyname (3)
-only if
-.IR getaddrinfo (3)
-fails.
-.PP
-A subnet specification is of the form \fInetwork\fB/\fImask\fR.
-The
-.I network
-and
-.I mask
-can be any form acceptable to
-.IR ttoaddr .
-In addition, and preferably, the
-.I mask
-can be a decimal integer (leading zeros ignored) giving a bit count,
-in which case
-it stands for a mask with that number of high bits on and all others off
-(e.g.,
-.B 24
-in IPv4 means
-.BR 255.255.255.0 ).
-In any case, the mask must be contiguous
-(a sequence of high bits on and all remaining low bits off).
-As a special case, the subnet specification
-.B %default
-is a synonym for
-.B 0.0.0.0/0
-or
-.B ::/0
-in IPv4 or IPv6 respectively.
-.PP
-.I Ttosubnet
-ANDs the mask with the address before returning,
-so that any non-network bits in the address are turned off
-(e.g.,
-.B 10.1.2.3/24
-is synonymous with
-.BR 10.1.2.0/24 ).
-.I Subnettot
-always generates the decimal-integer-bit-count
-form of the mask,
-with no leading zeros.
-.PP
-The
-.I srclen
-parameter of
-.I ttoaddr
-and
-.I ttosubnet
-specifies the length of the text string pointed to by
-.IR src ;
-it is an error for there to be anything else
-(e.g., a terminating NUL) within that length.
-As a convenience for cases where an entire NUL-terminated string is
-to be converted,
-a
-.I srclen
-value of
-.B 0
-is taken to mean
-.BR strlen(src) .
-.PP
-The
-.I af
-parameter of
-.I ttoaddr
-and
-.I ttosubnet
-specifies the address family of interest.
-It should be either
-.B AF_INET
-or
-.BR AF_INET6 .
-.PP
-The
-.I dstlen
-parameter of
-.I addrtot
-and
-.I subnettot
-specifies the size of the
-.I dst
-parameter;
-under no circumstances are more than
-.I dstlen
-bytes written to
-.IR dst .
-A result which will not fit is truncated.
-.I Dstlen
-can be zero, in which case
-.I dst
-need not be valid and no result is written,
-but the return value is unaffected;
-in all other cases, the (possibly truncated) result is NUL-terminated.
-The
-.I freeswan.h
-header file defines constants,
-.B ADDRTOT_BUF
-and
-.BR SUBNETTOT_BUF ,
-which are the sizes of buffers just large enough for worst-case results.
-.PP
-The
-.I format
-parameter of
-.I addrtot
-and
-.I subnettot
-specifies what format is to be used for the conversion.
-The value
-.B 0
-(not the character
-.BR '0' ,
-but a zero value)
-specifies a reasonable default,
-and is in fact the only format currently available in
-.IR subnettot .
-.I Addrtot
-also accepts format values
-.B 'r'
-(signifying a text form suitable for DNS reverse lookups,
-e.g.
-.B 4.3.2.1.IN-ADDR.ARPA.
-for IPv4 and
-RFC 2874 format for IPv6),
-and
-.B 'R'
-(signifying an alternate reverse-lookup form,
-an error for IPv4 and RFC 1886 format for IPv6).
-Reverse-lookup names always end with a ``.''.
-.PP
-The text-to-binary functions return NULL for success and
-a pointer to a string-literal error message for failure;
-see DIAGNOSTICS.
-The binary-to-text functions return
-.B 0
-for a failure, and otherwise
-always return the size of buffer which would
-be needed to
-accommodate the full conversion result, including terminating NUL;
-it is the caller's responsibility to check this against the size of
-the provided buffer to determine whether truncation has occurred.
-.SH SEE ALSO
-inet(3)
-.SH DIAGNOSTICS
-Fatal errors in
-.I ttoaddr
-are:
-empty input;
-unknown address family;
-attempt to allocate temporary storage for a very long name failed;
-name lookup failed;
-syntax error in dotted-decimal or colon-hex form;
-dotted-decimal or colon-hex component too large.
-.PP
-Fatal errors in
-.I ttosubnet
-are:
-no
-.B /
-in
-.IR src ;
-.I ttoaddr
-error in conversion of
-.I network
-or
-.IR mask ;
-bit-count mask too big;
-mask non-contiguous.
-.PP
-Fatal errors in
-.I addrtot
-and
-.I subnettot
-are:
-unknown format.
-.SH HISTORY
-Written for the FreeS/WAN project by Henry Spencer.
-.SH BUGS
-The interpretation of incomplete dotted-decimal addresses
-(e.g.
-.B 10/24
-means
-.BR 10.0.0.0/24 )
-differs from that of some older conversion
-functions, e.g. those of
-.IR inet (3).
-The behavior of the older functions has never been
-particularly consistent or particularly useful.
-.PP
-Ignoring leading zeros in dotted-decimal components and bit counts
-is arguably the most useful behavior in this application,
-but it might occasionally cause confusion with the historical use of leading
-zeros to denote octal numbers.
-.PP
-.I Ttoaddr
-does not support the mixed colon-hex-dotted-decimal
-convention used to embed an IPv4 address in an IPv6 address.
-.PP
-.I Addrtot
-always uses the
-.B ::
-abbreviation (which can appear only once in an address) for the
-.I first
-sequence of multiple zeros in an IPv6 address.
-One can construct addresses (unlikely ones) in which this is suboptimal.
-.PP
-.I Addrtot
-.B 'r'
-conversion of an IPv6 address uses lowercase hexadecimal,
-not the uppercase used in RFC 2874's examples.
-It takes careful reading of RFCs 2874, 2673, and 2234 to realize
-that lowercase is technically legitimate here,
-and there may be software which botches this
-and hence would have trouble with lowercase hex.
-.PP
-Possibly
-.I subnettot
-ought to recognize the
-.B %default
-case and generate that string as its output.
-Currently it doesn't.
-.PP
-It is barely possible that somebody, somewhere,
-might have a legitimate use for non-contiguous subnet masks.
-.PP
-.IR Getnetbyname (3)
-is a historical dreg.
-.PP
-.I Tnatoaddr
-probably should enforce completeness of dotted-decimal addresses.
-.PP
-The restriction of text-to-binary error reports to literal strings
-(so that callers don't need to worry about freeing them or copying them)
-does limit the precision of error reporting.
-.PP
-The text-to-binary error-reporting convention lends itself
-to slightly obscure code,
-because many readers will not think of NULL as signifying success.
-A good way to make it clearer is to write something like:
-.PP
-.RS
-.nf
-.B "const char *error;"
-.sp
-.B "error = ttoaddr( /* ... */ );"
-.B "if (error != NULL) {"
-.B " /* something went wrong */"
-.fi
-.RE
diff --git a/src/libfreeswan/ttoaddr.c b/src/libfreeswan/ttoaddr.c
deleted file mode 100644
index 234c9d8e7..000000000
--- a/src/libfreeswan/ttoaddr.c
+++ /dev/null
@@ -1,471 +0,0 @@
-/*
- * conversion from text forms of addresses to internal ones
- * Copyright (C) 2000 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-#include <sys/socket.h>
-
-#include "internal.h"
-#include "freeswan.h"
-
-/*
- * Legal ASCII characters in a domain name. Underscore technically is not,
- * but is a common misunderstanding. Non-ASCII characters are simply
- * exempted from checking at the moment, to allow for UTF-8 encoded stuff;
- * the purpose of this check is merely to catch blatant errors.
- */
-static const char namechars[] = "abcdefghijklmnopqrstuvwxyz0123456789"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ-_.";
-#define ISASCII(c) (((c) & 0x80) == 0)
-
-static err_t tryname(const char *, size_t, int, int, ip_address *);
-static err_t tryhex(const char *, size_t, int, ip_address *);
-static err_t trydotted(const char *, size_t, ip_address *);
-static err_t getbyte(const char **, const char *, int *);
-static err_t colon(const char *, size_t, ip_address *);
-static err_t getpiece(const char **, const char *, unsigned *);
-
-/*
- - ttoaddr - convert text name or dotted-decimal address to binary address
- */
-err_t /* NULL for success, else string literal */
-ttoaddr(src, srclen, af, dst)
-const char *src;
-size_t srclen; /* 0 means "apply strlen" */
-int af; /* address family */
-ip_address *dst;
-{
- err_t oops;
-# define HEXLEN 10 /* strlen("0x11223344") */
- int nultermd;
-
- if (srclen == 0) {
- srclen = strlen(src);
- if (srclen == 0)
- return "empty string";
- nultermd = 1;
- } else
- nultermd = 0; /* at least, not *known* to be terminated */
-
- switch (af) {
- case AF_INET:
- case AF_INET6:
- case 0: /* guess */
- break;
-
- default:
- return "invalid address family";
- }
-
- if (af == AF_INET && srclen == HEXLEN && *src == '0') {
- if (*(src+1) == 'x' || *(src+1) == 'X')
- return tryhex(src+2, srclen-2, 'x', dst);
- if (*(src+1) == 'h' || *(src+1) == 'H')
- return tryhex(src+2, srclen-2, 'h', dst);
- }
-
- if (memchr(src, ':', srclen) != NULL) {
- if(af == 0)
- {
- af = AF_INET6;
- }
-
- if (af != AF_INET6)
- return "non-ipv6 address may not contain `:'";
- return colon(src, srclen, dst);
- }
-
- if (af == 0 || af == AF_INET) {
- oops = trydotted(src, srclen, dst);
- if (oops == NULL)
- return NULL; /* it worked */
- if (*oops != '?')
- return oops; /* probably meant as d-d */
- }
-
- return tryname(src, srclen, nultermd, af, dst);
-}
-
-/*
- - tnatoaddr - convert text numeric address (only) to binary address
- */
-err_t /* NULL for success, else string literal */
-tnatoaddr(src, srclen, af, dst)
-const char *src;
-size_t srclen; /* 0 means "apply strlen" */
-int af; /* address family */
-ip_address *dst;
-{
- err_t oops;
-
- if (srclen == 0) {
- srclen = strlen(src);
- if (srclen == 0)
- return "empty string";
- }
-
- switch (af) {
- case 0: /* guess */
- oops = colon(src, srclen, dst);
- if(oops == NULL)
- {
- return NULL;
- }
- oops = trydotted(src, srclen, dst);
- if(oops == NULL)
- {
- return NULL;
- }
- return "does not appear to be either IPv4 or IPv6 numeric address";
- break;
-
- case AF_INET6:
- return colon(src, srclen, dst);
- break;
- case AF_INET:
- oops = trydotted(src, srclen, dst);
- if (oops == NULL)
- return NULL; /* it worked */
- if (*oops != '?')
- return oops; /* probably meant as d-d */
- return "does not appear to be numeric address";
- break;
- default:
- return "unknown address family in tnatoaddr";
- break;
- }
-}
-
-/*
- - tryname - try it as a name
- * Slightly complicated by lack of reliable NUL termination in source.
- */
-static err_t
-tryname(src, srclen, nultermd, af, dst)
-const char *src;
-size_t srclen;
-int nultermd; /* is it known to be NUL-terminated? */
-int af;
-ip_address *dst;
-{
- struct addrinfo hints, *res;
- struct netent *ne = NULL;
- char namebuf[100]; /* enough for most DNS names */
- const char *cp;
- char *p = namebuf;
- unsigned char *addr = NULL;
- size_t n;
- int error;
- err_t err = NULL;
-
- for (cp = src, n = srclen; n > 0; cp++, n--)
- if (ISASCII(*cp) && strchr(namechars, *cp) == NULL)
- return "illegal (non-DNS-name) character in name";
-
- if (nultermd)
- cp = src;
- else {
- if (srclen+1 > sizeof(namebuf)) {
- p = (char *) MALLOC(srclen+1);
- if (p == NULL)
- return "unable to get temporary space for name";
- }
- p[0] = '\0'; /* strncpy semantics are wrong */
- strncat(p, src, srclen);
- cp = (const char *)p;
- }
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = af;
- error = getaddrinfo(cp, NULL, &hints, &res);
- if (error != 0)
- { /* getaddrinfo failed, try getnetbyname */
- if (af == AF_INET)
- {
- ne = getnetbyname(cp);
- if (ne != NULL)
- {
- ne->n_net = htonl(ne->n_net);
- addr = (unsigned char*)&ne->n_net;
- err = initaddr(addr, sizeof(ne->n_net), af, dst);
- }
- }
- }
- else
- {
- struct addrinfo *r = res;
- while (r)
- {
- size_t addr_len;
- switch (r->ai_family)
- {
- case AF_INET:
- {
- struct sockaddr_in *in = (struct sockaddr_in*)r->ai_addr;
- addr_len = 4;
- addr = (unsigned char*)&in->sin_addr.s_addr;
- break;
- }
- case AF_INET6:
- {
- struct sockaddr_in6 *in6 = (struct sockaddr_in6*)r->ai_addr;
- addr_len = 16;
- addr = (unsigned char*)&in6->sin6_addr.s6_addr;
- break;
- }
- default:
- { /* unknown family, try next result */
- r = r->ai_next;
- continue;
- }
- }
- err = initaddr(addr, addr_len, r->ai_family, dst);
- break;
- }
- freeaddrinfo(res);
- }
-
- if (p != namebuf)
- {
- FREE(p);
- }
-
- if (addr == NULL)
- {
- return "does not look numeric and name lookup failed";
- }
-
- return err;
-}
-
-/*
- - tryhex - try conversion as an eight-digit hex number (AF_INET only)
- */
-static err_t
-tryhex(src, srclen, flavor, dst)
-const char *src;
-size_t srclen; /* should be 8 */
-int flavor; /* 'x' for network order, 'h' for host order */
-ip_address *dst;
-{
- err_t oops;
- unsigned long ul;
- union {
- uint32_t addr;
- unsigned char buf[4];
- } u;
-
- if (srclen != 8)
- return "internal error, tryhex called with bad length";
-
- oops = ttoul(src, srclen, 16, &ul);
- if (oops != NULL)
- return oops;
-
- u.addr = (flavor == 'h') ? ul : htonl(ul);
- return initaddr(u.buf, sizeof(u.buf), AF_INET, dst);
-}
-
-/*
- - trydotted - try conversion as dotted decimal (AF_INET only)
- *
- * If the first char of a complaint is '?', that means "didn't look like
- * dotted decimal at all".
- */
-static err_t
-trydotted(src, srclen, dst)
-const char *src;
-size_t srclen;
-ip_address *dst;
-{
- const char *stop = src + srclen; /* just past end */
- int byte;
- err_t oops;
-# define NBYTES 4
- unsigned char buf[NBYTES];
- int i;
-
- memset(buf, 0, sizeof(buf));
- for (i = 0; i < NBYTES && src < stop; i++) {
- oops = getbyte(&src, stop, &byte);
- if (oops != NULL) {
- if (*oops != '?')
- return oops; /* bad number */
- if (i > 1)
- return oops+1; /* failed number */
- return oops; /* with leading '?' */
- }
- buf[i] = byte;
- if (i < 3 && src < stop && *src++ != '.') {
- if (i == 0)
- return "?syntax error in dotted-decimal address";
- else
- return "syntax error in dotted-decimal address";
- }
- }
- if (src != stop)
- return "extra garbage on end of dotted-decimal address";
-
- return initaddr(buf, sizeof(buf), AF_INET, dst);
-}
-
-/*
- - getbyte - try to scan a byte in dotted decimal
- * A subtlety here is that all this arithmetic on ASCII digits really is
- * highly portable -- ANSI C guarantees that digits 0-9 are contiguous.
- * It's easier to just do it ourselves than set up for a call to ttoul().
- *
- * If the first char of a complaint is '?', that means "didn't look like a
- * number at all".
- */
-err_t
-getbyte(srcp, stop, retp)
-const char **srcp; /* *srcp is updated */
-const char *stop; /* first untouchable char */
-int *retp; /* return-value pointer */
-{
- char c;
- const char *p;
- int no;
-
- if (*srcp >= stop)
- return "?empty number in dotted-decimal address";
-
- no = 0;
- p = *srcp;
- while (p < stop && no <= 255 && (c = *p) >= '0' && c <= '9') {
- no = no*10 + (c - '0');
- p++;
- }
- if (p == *srcp)
- return "?non-numeric component in dotted-decimal address";
- *srcp = p;
- if (no > 255)
- return "byte overflow in dotted-decimal address";
- *retp = no;
- return NULL;
-}
-
-/*
- - colon - convert IPv6 "numeric" address
- */
-static err_t
-colon(src, srclen, dst)
-const char *src;
-size_t srclen; /* known to be >0 */
-ip_address *dst;
-{
- const char *stop = src + srclen; /* just past end */
- unsigned piece = 0;
- int gapat; /* where was empty piece seen */
- err_t oops;
-# define NPIECES 8
- unsigned char buf[NPIECES*2]; /* short may have wrong byte order */
- int i;
- int j;
-# define IT "IPv6 numeric address"
- int naftergap;
-
- /* leading or trailing :: becomes single empty field */
- if (*src == ':') { /* legal only if leading :: */
- if (srclen == 1 || *(src+1) != ':')
- return "illegal leading `:' in " IT;
- if (srclen == 2) {
- unspecaddr(AF_INET6, dst);
- return NULL;
- }
- src++; /* past first but not second */
- srclen--;
- }
- if (*(stop-1) == ':') { /* legal only if trailing :: */
- if (srclen == 1 || *(stop-2) != ':')
- return "illegal trailing `:' in " IT;
- srclen--; /* leave one */
- }
-
- gapat = -1;
- for (i = 0; i < NPIECES && src < stop; i++) {
- oops = getpiece(&src, stop, &piece);
- if (oops != NULL && *oops == ':') { /* empty field */
- if (gapat >= 0)
- return "more than one :: in " IT;
- gapat = i;
- } else if (oops != NULL)
- return oops;
- buf[2*i] = piece >> 8;
- buf[2*i + 1] = piece & 0xff;
- if (i < NPIECES-1) { /* there should be more input */
- if (src == stop && gapat < 0)
- return IT " ends prematurely";
- if (src != stop && *src++ != ':')
- return "syntax error in " IT;
- }
- }
- if (src != stop)
- return "extra garbage on end of " IT;
-
- if (gapat < 0 && i < NPIECES) /* should have been caught earlier */
- return "incomplete " IT " (internal error)";
- if (gapat >= 0 && i == NPIECES)
- return "non-abbreviating empty field in " IT;
- if (gapat >= 0) {
- naftergap = i - (gapat + 1);
- for (i--, j = NPIECES-1; naftergap > 0; i--, j--, naftergap--) {
- buf[2*j] = buf[2*i];
- buf[2*j + 1] = buf[2*i + 1];
- }
- for (; j >= gapat; j--)
- buf[2*j] = buf[2*j + 1] = 0;
- }
-
- return initaddr(buf, sizeof(buf), AF_INET6, dst);
-}
-
-/*
- - getpiece - try to scan one 16-bit piece of an IPv6 address
- */
-err_t /* ":" means "empty field seen" */
-getpiece(srcp, stop, retp)
-const char **srcp; /* *srcp is updated */
-const char *stop; /* first untouchable char */
-unsigned *retp; /* return-value pointer */
-{
- const char *p;
-# define NDIG 4
- int d;
- unsigned long ret;
- err_t oops;
-
- if (*srcp >= stop || **srcp == ':') { /* empty field */
- *retp = 0;
- return ":";
- }
-
- p = *srcp;
- d = 0;
- while (p < stop && d < NDIG && isxdigit(*p)) {
- p++;
- d++;
- }
- if (d == 0)
- return "non-hex field in IPv6 numeric address";
- if (p < stop && d == NDIG && isxdigit(*p))
- return "field in IPv6 numeric address longer than 4 hex digits";
-
- oops = ttoul(*srcp, d, 16, &ret);
- if (oops != NULL) /* shouldn't happen, really... */
- return oops;
-
- *srcp = p;
- *retp = ret;
- return NULL;
-}
diff --git a/src/libfreeswan/ttodata.3 b/src/libfreeswan/ttodata.3
deleted file mode 100644
index 8f4b1ec93..000000000
--- a/src/libfreeswan/ttodata.3
+++ /dev/null
@@ -1,280 +0,0 @@
-.TH IPSEC_TTODATA 3 "16 August 2003"
-.SH NAME
-ipsec ttodata, datatot \- convert binary data bytes from and to text formats
-.SH SYNOPSIS
-.B "#include <freeswan.h>"
-.sp
-.B "const char *ttodata(const char *src, size_t srclen,"
-.ti +1c
-.B "int base, char *dst, size_t dstlen, size_t *lenp);"
-.br
-.B "const char *ttodatav(const char *src, size_t srclen,"
-.ti +1c
-.B "int base, char *dst, size_t dstlen, size_t *lenp,"
-.ti +1c
-.B "char *errp, size_t errlen, int flags);"
-.br
-.B "size_t datatot(const char *src, size_t srclen,"
-.ti +1c
-.B "int format, char *dst, size_t dstlen);"
-.SH DESCRIPTION
-.IR Ttodata ,
-.IR ttodatav ,
-and
-.I datatot
-convert arbitrary binary data (e.g. encryption or authentication keys)
-from and to more-or-less human-readable text formats.
-.PP
-Currently supported formats are hexadecimal, base64, and characters.
-.PP
-A hexadecimal text value begins with a
-.B 0x
-(or
-.BR 0X )
-prefix and continues with two-digit groups
-of hexadecimal digits (0-9, and a-f or A-F),
-each group encoding the value of one binary byte, high-order digit first.
-A single
-.B _
-(underscore)
-between consecutive groups is ignored, permitting punctuation to improve
-readability; doing this every eight digits seems about right.
-.PP
-A base64 text value begins with a
-.B 0s
-(or
-.BR 0S )
-prefix
-and continues with four-digit groups of base64 digits (A-Z, a-z, 0-9, +, and /),
-each group encoding the value of three binary bytes as described in
-section 6.8 of RFC 2045.
-If
-.B flags
-has the
-.B TTODATAV_IGNORESPACE
-bit on, blanks are ignore (after the prefix).
-Note that the last one or two digits of a base64 group can be
-.B =
-to indicate that fewer than three binary bytes are encoded.
-.PP
-A character text value begins with a
-.B 0t
-(or
-.BR 0T )
-prefix
-and continues with text characters, each being the value of one binary byte.
-.PP
-All these functions basically copy data from
-.I src
-(whose size is specified by
-.IR srclen )
-to
-.I dst
-(whose size is specified by
-.IR dstlen ),
-doing the conversion en route.
-If the result will not fit in
-.IR dst ,
-it is truncated;
-under no circumstances are more than
-.I dstlen
-bytes of result written to
-.IR dst .
-.I Dstlen
-can be zero, in which case
-.I dst
-need not be valid and no result bytes are written at all.
-.PP
-The
-.I base
-parameter of
-.I ttodata
-and
-.I ttodatav
-specifies what format the input is in;
-normally it should be
-.B 0
-to signify that this gets figured out from the prefix.
-Values of
-.BR 16 ,
-.BR 64 ,
-and
-.BR 256
-respectively signify hexadecimal, base64, and character-text formats
-without prefixes.
-.PP
-The
-.I format
-parameter of
-.IR datatot ,
-a single character used as a type code,
-specifies which text format is wanted.
-The value
-.B 0
-(not ASCII
-.BR '0' ,
-but a zero value) specifies a reasonable default.
-Other currently-supported values are:
-.RS 2
-.TP 4
-.B 'x'
-continuous lower-case hexadecimal with a
-.B 0x
-prefix
-.TP
-.B 'h'
-lower-case hexadecimal with a
-.B 0x
-prefix and a
-.B _
-every eight digits
-.TP
-.B ':'
-lower-case hexadecimal with no prefix and a
-.B :
-(colon) every two digits
-.TP
-.B 16
-lower-case hexadecimal with no prefix or
-.B _
-.TP
-.B 's'
-continuous base64 with a
-.B 0s
-prefix
-.TP
-.B 64
-continuous base64 with no prefix
-.RE
-.PP
-The default format is currently
-.BR 'h' .
-.PP
-.I Ttodata
-returns NULL for success and
-a pointer to a string-literal error message for failure;
-see DIAGNOSTICS.
-On success,
-if and only if
-.I lenp
-is non-NULL,
-.B *lenp
-is set to the number of bytes required to contain the full untruncated result.
-It is the caller's responsibility to check this against
-.I dstlen
-to determine whether he has obtained a complete result.
-The
-.B *lenp
-value is correct even if
-.I dstlen
-is zero, which offers a way to determine how much space would be needed
-before having to allocate any.
-.PP
-.I Ttodatav
-is just like
-.I ttodata
-except that in certain cases,
-if
-.I errp
-is non-NULL,
-the buffer pointed to by
-.I errp
-(whose length is given by
-.IR errlen )
-is used to hold a more detailed error message.
-The return value is NULL for success,
-and is either
-.I errp
-or a pointer to a string literal for failure.
-If the size of the error-message buffer is
-inadequate for the desired message,
-.I ttodatav
-will fall back on returning a pointer to a literal string instead.
-The
-.I freeswan.h
-header file defines a constant
-.B TTODATAV_BUF
-which is the size of a buffer large enough for worst-case results.
-.PP
-The normal return value of
-.IR datatot
-is the number of bytes required
-to contain the full untruncated result.
-It is the caller's responsibility to check this against
-.I dstlen
-to determine whether he has obtained a complete result.
-The return value is correct even if
-.I dstlen
-is zero, which offers a way to determine how much space would be needed
-before having to allocate any.
-A return value of
-.B 0
-signals a fatal error of some kind
-(see DIAGNOSTICS).
-.PP
-A zero value for
-.I srclen
-in
-.I ttodata
-(but not
-.IR datatot !)
-is synonymous with
-.BR strlen(src) .
-A non-zero
-.I srclen
-in
-.I ttodata
-must not include the terminating NUL.
-.PP
-Unless
-.I dstlen
-is zero,
-the result supplied by
-.I datatot
-is always NUL-terminated,
-and its needed-size return value includes space for the terminating NUL.
-.PP
-Several obsolete variants of these functions
-.RI ( atodata ,
-.IR datatoa ,
-.IR atobytes ,
-and
-.IR bytestoa )
-are temporarily also supported.
-.SH SEE ALSO
-sprintf(3), ipsec_atoaddr(3)
-.SH DIAGNOSTICS
-Fatal errors in
-.I ttodata
-and
-.I ttodatav
-are:
-unknown characters in the input;
-unknown or missing prefix;
-unknown base;
-incomplete digit group;
-non-zero padding in a base64 less-than-three-bytes digit group;
-zero-length input.
-.PP
-Fatal errors in
-.I datatot
-are:
-unknown format code;
-zero-length input.
-.SH HISTORY
-Written for the FreeS/WAN project by Henry Spencer.
-.SH BUGS
-.I Datatot
-should have a format code to produce character-text output.
-.PP
-The
-.B 0s
-and
-.B 0t
-prefixes are the author's inventions and are not a standard
-of any kind.
-They have been chosen to avoid collisions with existing practice
-(some C implementations use
-.B 0b
-for binary)
-and possible confusion with unprefixed hexadecimal.
diff --git a/src/libfreeswan/ttodata.c b/src/libfreeswan/ttodata.c
deleted file mode 100644
index ef3717797..000000000
--- a/src/libfreeswan/ttodata.c
+++ /dev/null
@@ -1,720 +0,0 @@
-/*
- * convert from text form of arbitrary data (e.g., keys) to binary
- * Copyright (C) 2000 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-#include "internal.h"
-#include "freeswan.h"
-
-/* converters and misc */
-static int unhex(const char *, char *, size_t);
-static int unb64(const char *, char *, size_t);
-static int untext(const char *, char *, size_t);
-static const char *badch(const char *, int, char *, size_t);
-
-/* internal error codes for converters */
-#define SHORT (-2) /* internal buffer too short */
-#define BADPAD (-3) /* bad base64 padding */
-#define BADCH0 (-4) /* invalid character 0 */
-#define BADCH1 (-5) /* invalid character 1 */
-#define BADCH2 (-6) /* invalid character 2 */
-#define BADCH3 (-7) /* invalid character 3 */
-#define BADOFF(code) (BADCH0-(code))
-
-/*
- - ttodatav - convert text to data, with verbose error reports
- * If some of this looks slightly odd, it's because it has changed
- * repeatedly (from the original atodata()) without a major rewrite.
- */
-const char * /* NULL on success, else literal or errp */
-ttodatav(src, srclen, base, dst, dstlen, lenp, errp, errlen, flags)
-const char *src;
-size_t srclen; /* 0 means apply strlen() */
-int base; /* 0 means figure it out */
-char *dst; /* need not be valid if dstlen is 0 */
-size_t dstlen;
-size_t *lenp; /* where to record length (NULL is nowhere) */
-char *errp; /* error buffer */
-size_t errlen;
-unsigned int flags;
-{
- size_t ingroup; /* number of input bytes converted at once */
- char buf[4]; /* output from conversion */
- int nbytes; /* size of output */
- int (*decode)(const char *, char *, size_t);
- char *stop;
- int ndone;
- int i;
- int underscoreok;
- int skipSpace = 0;
-
- if (srclen == 0)
- srclen = strlen(src);
- if (dstlen == 0)
- dst = buf; /* point it somewhere valid */
- stop = dst + dstlen;
-
- if (base == 0) {
- if (srclen < 2)
- return "input too short to be valid";
- if (*src++ != '0')
- return "input does not begin with format prefix";
- switch (*src++) {
- case 'x':
- case 'X':
- base = 16;
- break;
- case 's':
- case 'S':
- base = 64;
- break;
- case 't':
- case 'T':
- base = 256;
- break;
- default:
- return "unknown format prefix";
- }
- srclen -= 2;
- }
- switch (base) {
- case 16:
- decode = unhex;
- underscoreok = 1;
- ingroup = 2;
- break;
- case 64:
- decode = unb64;
- underscoreok = 0;
- ingroup = 4;
- if(flags & TTODATAV_IGNORESPACE) {
- skipSpace = 1;
- }
- break;
-
- case 256:
- decode = untext;
- ingroup = 1;
- underscoreok = 0;
- break;
- default:
- return "unknown base";
- }
-
- /* proceed */
- ndone = 0;
- while (srclen > 0) {
- char stage[4]; /* staging area for group */
- size_t sl = 0;
-
- /* Grab ingroup characters into stage,
- * squeezing out blanks if we are supposed to ignore them.
- */
- for (sl = 0; sl < ingroup; src++, srclen--) {
- if (srclen == 0)
- return "input ends in mid-byte, perhaps truncated";
- else if (!(skipSpace && (*src == ' ' || *src == '\t')))
- stage[sl++] = *src;
- }
-
- nbytes = (*decode)(stage, buf, sizeof(buf));
- switch (nbytes) {
- case BADCH0:
- case BADCH1:
- case BADCH2:
- case BADCH3:
- return badch(stage, nbytes, errp, errlen);
- case SHORT:
- return "internal buffer too short (\"can't happen\")";
- case BADPAD:
- return "bad (non-zero) padding at end of base64 input";
- }
- if (nbytes <= 0)
- return "unknown internal error";
- for (i = 0; i < nbytes; i++) {
- if (dst < stop)
- *dst++ = buf[i];
- ndone++;
- }
- while (srclen >= 1 && skipSpace && (*src == ' ' || *src == '\t')){
- src++;
- srclen--;
- }
- if (underscoreok && srclen > 1 && *src == '_') {
- /* srclen > 1 means not last character */
- src++;
- srclen--;
- }
- }
-
- if (ndone == 0)
- return "no data bytes specified by input";
- if (lenp != NULL)
- *lenp = ndone;
- return NULL;
-}
-
-/*
- - ttodata - convert text to data
- */
-const char * /* NULL on success, else literal */
-ttodata(src, srclen, base, dst, dstlen, lenp)
-const char *src;
-size_t srclen; /* 0 means apply strlen() */
-int base; /* 0 means figure it out */
-char *dst; /* need not be valid if dstlen is 0 */
-size_t dstlen;
-size_t *lenp; /* where to record length (NULL is nowhere) */
-{
- return ttodatav(src, srclen, base, dst, dstlen, lenp, (char *)NULL,
- (size_t)0, TTODATAV_SPACECOUNTS);
-}
-
-/*
- - atodata - convert ASCII to data
- * backward-compatibility interface
- */
-size_t /* 0 for failure, true length for success */
-atodata(src, srclen, dst, dstlen)
-const char *src;
-size_t srclen;
-char *dst;
-size_t dstlen;
-{
- size_t len;
- const char *err;
-
- err = ttodata(src, srclen, 0, dst, dstlen, &len);
- if (err != NULL)
- return 0;
- return len;
-}
-
-/*
- - atobytes - convert ASCII to data bytes
- * another backward-compatibility interface
- */
-const char *
-atobytes(src, srclen, dst, dstlen, lenp)
-const char *src;
-size_t srclen;
-char *dst;
-size_t dstlen;
-size_t *lenp;
-{
- return ttodata(src, srclen, 0, dst, dstlen, lenp);
-}
-
-/*
- - unhex - convert two ASCII hex digits to byte
- */
-static int /* number of result bytes, or error code */
-unhex(src, dst, dstlen)
-const char *src; /* known to be full length */
-char *dst;
-size_t dstlen; /* not large enough is a failure */
-{
- char *p;
- unsigned byte;
- static char hex[] = "0123456789abcdef";
-
- if (dstlen < 1)
- return SHORT;
-
- p = strchr(hex, *src);
- if (p == NULL)
- p = strchr(hex, tolower(*src));
- if (p == NULL)
- return BADCH0;
- byte = (p - hex) << 4;
- src++;
-
- p = strchr(hex, *src);
- if (p == NULL)
- p = strchr(hex, tolower(*src));
- if (p == NULL)
- return BADCH1;
- byte |= (p - hex);
-
- *dst = byte;
- return 1;
-}
-
-/*
- - unb64 - convert four ASCII base64 digits to three bytes
- * Note that a base64 digit group is padded out with '=' if it represents
- * less than three bytes: one byte is dd==, two is ddd=, three is dddd.
- */
-static int /* number of result bytes, or error code */
-unb64(src, dst, dstlen)
-const char *src; /* known to be full length */
-char *dst;
-size_t dstlen;
-{
- char *p;
- unsigned byte1;
- unsigned byte2;
- static char base64[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
- if (dstlen < 3)
- return SHORT;
-
- p = strchr(base64, *src++);
-
- if (p == NULL)
- return BADCH0;
- byte1 = (p - base64) << 2; /* first six bits */
-
- p = strchr(base64, *src++);
- if (p == NULL) {
- return BADCH1;
- }
-
- byte2 = p - base64; /* next six: two plus four */
- *dst++ = byte1 | (byte2 >> 4);
- byte1 = (byte2 & 0xf) << 4;
-
- p = strchr(base64, *src++);
- if (p == NULL) {
- if (*(src-1) == '=' && *src == '=') {
- if (byte1 != 0) /* bad padding */
- return BADPAD;
- return 1;
- }
- return BADCH2;
- }
-
- byte2 = p - base64; /* next six: four plus two */
- *dst++ = byte1 | (byte2 >> 2);
- byte1 = (byte2 & 0x3) << 6;
-
- p = strchr(base64, *src++);
- if (p == NULL) {
- if (*(src-1) == '=') {
- if (byte1 != 0) /* bad padding */
- return BADPAD;
- return 2;
- }
- return BADCH3;
- }
- byte2 = p - base64; /* last six */
- *dst++ = byte1 | byte2;
-
- return 3;
-}
-
-/*
- - untext - convert one ASCII character to byte
- */
-static int /* number of result bytes, or error code */
-untext(src, dst, dstlen)
-const char *src; /* known to be full length */
-char *dst;
-size_t dstlen; /* not large enough is a failure */
-{
- if (dstlen < 1)
- return SHORT;
-
- *dst = *src;
- return 1;
-}
-
-/*
- - badch - produce a nice complaint about an unknown character
- *
- * If the compiler complains that the array bigenough[] has a negative
- * size, that means the TTODATAV_BUF constant has been set too small.
- */
-static const char * /* literal or errp */
-badch(src, errcode, errp, errlen)
-const char *src;
-int errcode;
-char *errp; /* might be NULL */
-size_t errlen;
-{
- static const char pre[] = "unknown character (`";
- static const char suf[] = "') in input";
- char buf[5];
-# define REQD (sizeof(pre) - 1 + sizeof(buf) - 1 + sizeof(suf))
- struct sizecheck {
- char bigenough[TTODATAV_BUF - REQD]; /* see above */
- };
- char ch;
-
- if (errp == NULL || errlen < REQD)
- return "unknown character in input";
- strcpy(errp, pre);
- ch = *(src + BADOFF(errcode));
- if (isprint(ch)) {
- buf[0] = ch;
- buf[1] = '\0';
- } else {
- buf[0] = '\\';
- buf[1] = ((ch & 0700) >> 6) + '0';
- buf[2] = ((ch & 0070) >> 3) + '0';
- buf[3] = ((ch & 0007) >> 0) + '0';
- buf[4] = '\0';
- }
- strcat(errp, buf);
- strcat(errp, suf);
- return (const char *)errp;
-}
-
-
-
-#ifdef TTODATA_MAIN
-
-#include <stdio.h>
-
-struct artab;
-static void check(struct artab *r, char *buf, size_t n, err_t oops, int *status);
-static void regress(char *pgm);
-static void hexout(const char *s, size_t len, FILE *f);
-
-/*
- - main - convert first argument to hex, or run regression
- */
-int
-main(int argc, char *argv[])
-{
- char buf[1024];
- char buf2[1024];
- char err[512];
- size_t n;
- size_t i;
- char *p = buf;
- char *p2 = buf2;
- char *pgm = argv[0];
- const char *oops;
-
- if (argc < 2) {
- fprintf(stderr, "Usage: %s {0x<hex>|0s<base64>|-r}\n", pgm);
- exit(2);
- }
-
- if (strcmp(argv[1], "-r") == 0) {
- regress(pgm); /* should not return */
- fprintf(stderr, "%s: regress() returned?!?\n", pgm);
- exit(1);
- }
-
- oops = ttodatav(argv[1], 0, 0, buf, sizeof(buf), &n,
- err, sizeof(err), TTODATAV_IGNORESPACE);
- if (oops != NULL) {
- fprintf(stderr, "%s: ttodata error `%s' in `%s'\n", pgm,
- oops, argv[1]);
- exit(1);
- }
-
- if (n > sizeof(buf)) {
- p = (char *)malloc((size_t)n);
- if (p == NULL) {
- fprintf(stderr,
- "%s: unable to malloc %d bytes for result\n",
- pgm, n);
- exit(1);
- }
- oops = ttodata(argv[1], 0, 0, p, n, &n);
- if (oops != NULL) {
- fprintf(stderr, "%s: error `%s' in ttodata retry?!?\n",
- pgm, oops);
- exit(1);
- }
- }
-
- hexout(p, n, stdout);
- printf("\n");
-
- i = datatot(buf, n, 'h', buf2, sizeof(buf2));
- if (i == 0) {
- fprintf(stderr, "%s: datatot reports error in `%s'\n", pgm,
- argv[1]);
- exit(1);
- }
-
- if (i > sizeof(buf2)) {
- p2 = (char *)malloc((size_t)i);
- if (p == NULL) {
- fprintf(stderr,
- "%s: unable to malloc %d bytes for result\n",
- pgm, i);
- exit(1);
- }
- i = datatot(buf, n, 'h', p2, i);
- if (i == 0) {
- fprintf(stderr, "%s: error in datatoa retry?!?\n", pgm);
- exit(1);
- }
- }
-
- printf("%s\n", p2);
-
- exit(0);
-}
-
-/*
- - hexout - output an arbitrary-length string in hex
- */
-static void
-hexout(s, len, f)
-const char *s;
-size_t len;
-FILE *f;
-{
- size_t i;
-
- fprintf(f, "0x");
- for (i = 0; i < len; i++)
- fprintf(f, "%02x", (unsigned char)s[i]);
-}
-
-struct artab {
- int base;
-# define IGNORESPACE_BIAS 1000
- char *ascii; /* NULL for end */
- char *data; /* NULL for error expected */
-} atodatatab[] = {
- { 0, "", NULL, },
- { 0, "0", NULL, },
- { 0, "0x", NULL, },
- { 0, "0xa", NULL, },
- { 0, "0xab", "\xab", },
- { 0, "0xabc", NULL, },
- { 0, "0xabcd", "\xab\xcd", },
- { 0, "0x0123456789", "\x01\x23\x45\x67\x89", },
- { 0, "0x01x", NULL, },
- { 0, "0xabcdef", "\xab\xcd\xef", },
- { 0, "0xABCDEF", "\xab\xcd\xef", },
- { 0, "0XaBc0eEd81f", "\xab\xc0\xee\xd8\x1f", },
- { 0, "0XaBc0_eEd8", "\xab\xc0\xee\xd8", },
- { 0, "0XaBc0_", NULL, },
- { 0, "0X_aBc0", NULL, },
- { 0, "0Xa_Bc0", NULL, },
- { 16, "aBc0eEd8", "\xab\xc0\xee\xd8", },
- { 0, "0s", NULL, },
- { 0, "0sA", NULL, },
- { 0, "0sBA", NULL, },
- { 0, "0sCBA", NULL, },
- { 0, "0sDCBA", "\x0c\x20\x40", },
- { 0, "0SDCBA", "\x0c\x20\x40", },
- { 0, "0sDA==", "\x0c", },
- { 0, "0sDC==", NULL, },
- { 0, "0sDCA=", "\x0c\x20", },
- { 0, "0sDCB=", NULL, },
- { 0, "0sDCAZ", "\x0c\x20\x19", },
- { 0, "0sDCAa", "\x0c\x20\x1a", },
- { 0, "0sDCAz", "\x0c\x20\x33", },
- { 0, "0sDCA0", "\x0c\x20\x34", },
- { 0, "0sDCA9", "\x0c\x20\x3d", },
- { 0, "0sDCA+", "\x0c\x20\x3e", },
- { 0, "0sDCA/", "\x0c\x20\x3f", },
- { 0, "0sAbraCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
- { IGNORESPACE_BIAS + 0, "0s AbraCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
- { IGNORESPACE_BIAS + 0, "0sA braCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
- { IGNORESPACE_BIAS + 0, "0sAb raCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
- { IGNORESPACE_BIAS + 0, "0sAbr aCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
- { IGNORESPACE_BIAS + 0, "0sAbra Cadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
- { IGNORESPACE_BIAS + 0, "0sAbraC adabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
- { IGNORESPACE_BIAS + 0, "0sAbraCa dabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
- { IGNORESPACE_BIAS + 0, "0sAbraCad abra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
- { IGNORESPACE_BIAS + 0, "0sAbraCada bra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
- { IGNORESPACE_BIAS + 0, "0sAbraCadab ra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
- { IGNORESPACE_BIAS + 0, "0sAbraCadabr a+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
- { IGNORESPACE_BIAS + 0, "0sAbraCadabra +", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
- { IGNORESPACE_BIAS + 0, "0sAbraCadabra+ ", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
- { 0, "0t", NULL, },
- { 0, "0tabc_xyz", "abc_xyz", },
- { 256, "abc_xyz", "abc_xyz", },
- { 0, NULL, NULL, },
-};
-
-struct drtab {
- char *data; /* input; NULL for end */
- char format;
- int buflen; /* -1 means big buffer */
- int outlen; /* -1 means strlen(ascii)+1 */
- char *ascii; /* NULL for error expected */
-} datatoatab[] = {
- { "", 'x', -1, -1, NULL, },
- { "", 'X', -1, -1, NULL, },
- { "", 'n', -1, -1, NULL, },
- { "0", 'x', -1, -1, "0x30", },
- { "0", 'x', 0, 5, "---", },
- { "0", 'x', 1, 5, "", },
- { "0", 'x', 2, 5, "0", },
- { "0", 'x', 3, 5, "0x", },
- { "0", 'x', 4, 5, "0x3", },
- { "0", 'x', 5, 5, "0x30", },
- { "0", 'x', 6, 5, "0x30", },
- { "\xab\xcd", 'x', -1, -1, "0xabcd", },
- { "\x01\x23\x45\x67\x89", 'x', -1, -1, "0x0123456789", },
- { "\xab\xcd\xef", 'x', -1, -1, "0xabcdef", },
- { "\xab\xc0\xee\xd8\x1f", 'x', -1, -1, "0xabc0eed81f", },
- { "\x01\x02", 'h', -1, -1, "0x0102", },
- { "\x01\x02\x03\x04\x05\x06", 'h', -1, -1, "0x01020304_0506", },
- { "\xab\xc0\xee\xd8\x1f", 16, -1, -1, "abc0eed81f", },
- { "\x0c\x20\x40", 's', -1, -1, "0sDCBA", },
- { "\x0c\x20\x40", 's', 0, 7, "---", },
- { "\x0c\x20\x40", 's', 1, 7, "", },
- { "\x0c\x20\x40", 's', 2, 7, "0", },
- { "\x0c\x20\x40", 's', 3, 7, "0s", },
- { "\x0c\x20\x40", 's', 4, 7, "0sD", },
- { "\x0c\x20\x40", 's', 5, 7, "0sDC", },
- { "\x0c\x20\x40", 's', 6, 7, "0sDCB", },
- { "\x0c\x20\x40", 's', 7, 7, "0sDCBA", },
- { "\x0c\x20\x40", 's', 8, 7, "0sDCBA", },
- { "\x0c", 's', -1, -1, "0sDA==", },
- { "\x0c\x20", 's', -1, -1, "0sDCA=", },
- { "\x0c\x20\x19", 's', -1, -1, "0sDCAZ", },
- { "\x0c\x20\x1a", 's', -1, -1, "0sDCAa", },
- { "\x0c\x20\x33", 's', -1, -1, "0sDCAz", },
- { "\x0c\x20\x34", 's', -1, -1, "0sDCA0", },
- { "\x0c\x20\x3d", 's', -1, -1, "0sDCA9", },
- { "\x0c\x20\x3e", 's', -1, -1, "0sDCA+", },
- { "\x0c\x20\x3f", 's', -1, -1, "0sDCA/", },
- { "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", 's', -1, -1, "0sAbraCadabra+", },
- { "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", 64, -1, -1, "AbraCadabra+", },
- { NULL, 'x', -1, -1, NULL, },
-};
-
-/*
- - regress - regression-test ttodata() and datatot()
- */
-static void
-check(r, buf, n, oops, status)
-struct artab *r;
-char *buf;
-size_t n;
-err_t oops;
-int *status;
-{
- if (oops != NULL && r->data == NULL)
- {} /* error expected */
- else if (oops != NULL) {
- printf("`%s' gave error `%s', expecting %d `", r->ascii,
- oops, strlen(r->data));
- hexout(r->data, strlen(r->data), stdout);
- printf("'\n");
- *status = 1;
- } else if (r->data == NULL) {
- printf("`%s' gave %d `", r->ascii, n);
- hexout(buf, n, stdout);
- printf("', expecting error\n");
- *status = 1;
- } else if (n != strlen(r->data)) {
- printf("length wrong in `%s': got %d `", r->ascii, n);
- hexout(buf, n, stdout);
- printf("', expecting %d `", strlen(r->data));
- hexout(r->data, strlen(r->data), stdout);
- printf("'\n");
- *status = 1;
- } else if (memcmp(buf, r->data, n) != 0) {
- printf("`%s' gave %d `", r->ascii, n);
- hexout(buf, n, stdout);
- printf("', expecting %d `", strlen(r->data));
- hexout(r->data, strlen(r->data), stdout);
- printf("'\n");
- *status = 1;
- }
- fflush(stdout);
-}
-
-static void /* should not return at all, in fact */
-regress(pgm)
-char *pgm;
-{
- struct artab *r;
- struct drtab *dr;
- char buf[100];
- size_t n;
- int status = 0;
-
- for (r = atodatatab; r->ascii != NULL; r++) {
- int base = r->base;
- int xbase = 0;
-
- if ((base == 0 || base == IGNORESPACE_BIAS + 0) && r->ascii[0] == '0') {
- switch (r->ascii[1]) {
- case 'x':
- case 'X':
- xbase = 16;
- break;
- case 's':
- case 'S':
- xbase = 64;
- break;
- case 't':
- case 'T':
- xbase = 256;
- break;
- }
- }
-
- if (base >= IGNORESPACE_BIAS) {
- base = base - IGNORESPACE_BIAS;
- check(r, buf, n, ttodatav(r->ascii, 0, base, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status);
- if (xbase != 0)
- check(r, buf, n, ttodatav(r->ascii+2, 0, xbase, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status);
- } else {
- check(r, buf, n, ttodata(r->ascii, 0, base, buf, sizeof(buf), &n), &status);
- if (base == 64 || xbase == 64)
- check(r, buf, n, ttodatav(r->ascii, 0, base, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status);
- if (xbase != 0) {
- check(r, buf, n, ttodata(r->ascii+2, 0, xbase, buf, sizeof(buf), &n), &status);
- if (base == 64 || xbase == 64)
- check(r, buf, n, ttodatav(r->ascii+2, 0, xbase, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status);
- }
- }
- }
- for (dr = datatoatab; dr->data != NULL; dr++) {
- size_t should;
-
- strcpy(buf, "---");
- n = datatot(dr->data, strlen(dr->data), dr->format, buf,
- (dr->buflen == -1) ? sizeof(buf) : dr->buflen);
- should = (dr->ascii == NULL) ? 0 : strlen(dr->ascii) + 1;
- if (dr->outlen != -1)
- should = dr->outlen;
- if (n == 0 && dr->ascii == NULL)
- {} /* error expected */
- else if (n == 0) {
- printf("`");
- hexout(dr->data, strlen(dr->data), stdout);
- printf("' %c gave error, expecting %d `%s'\n",
- dr->format, should, dr->ascii);
- status = 1;
- } else if (dr->ascii == NULL) {
- printf("`");
- hexout(dr->data, strlen(dr->data), stdout);
- printf("' %c gave %d `%.*s', expecting error\n",
- dr->format, n, (int)n, buf);
- status = 1;
- } else if (n != should) {
- printf("length wrong in `");
- hexout(dr->data, strlen(dr->data), stdout);
- printf("': got %d `%s'", n, buf);
- printf(", expecting %d `%s'\n", should, dr->ascii);
- status = 1;
- } else if (strcmp(buf, dr->ascii) != 0) {
- printf("`");
- hexout(dr->data, strlen(dr->data), stdout);
- printf("' gave %d `%s'", n, buf);
- printf(", expecting %d `%s'\n", should, dr->ascii);
- status = 1;
- }
- fflush(stdout);
- }
- exit(status);
-}
-
-#endif /* TTODATA_MAIN */
diff --git a/src/libfreeswan/ttoprotoport.c b/src/libfreeswan/ttoprotoport.c
deleted file mode 100644
index e75b206be..000000000
--- a/src/libfreeswan/ttoprotoport.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * conversion from protocol/port string to protocol and port
- * Copyright (C) 2002 Mario Strasser <mast@gmx.net>,
- * Zuercher Hochschule Winterthur,
- *
- * 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 "internal.h"
-#include "freeswan.h"
-
-/*
- * ttoprotoport - converts from protocol/port string to protocol and port
- */
-err_t
-ttoprotoport(src, src_len, proto, port, has_port_wildcard)
-char *src; /* input string */
-size_t src_len; /* length of input string, use strlen() if 0 */
-u_int8_t *proto; /* extracted protocol number */
-u_int16_t *port; /* extracted port number if it exists */
-bool *has_port_wildcard; /* set if port is %any */
-{
- char *end, *service_name;
- char proto_name[16];
- int proto_len;
- long int l;
- struct protoent *protocol;
- struct servent *service;
-
- /* get the length of the string */
- if (!src_len) src_len = strlen(src);
-
- /* locate delimiter '/' between protocol and port */
- end = strchr(src, '/');
- if (end != NULL) {
- proto_len = end - src;
- service_name = end + 1;
- } else {
- proto_len = src_len;
- service_name = src + src_len;
- }
-
- /* copy protocol name*/
- memset(proto_name, '\0', sizeof(proto_name));
- memcpy(proto_name, src, proto_len);
-
- /* extract protocol by trying to resolve it by name */
- protocol = getprotobyname(proto_name);
- if (protocol != NULL) {
- *proto = protocol->p_proto;
- }
- else /* failed, now try it by number */
- {
- l = strtol(proto_name, &end, 0);
-
- if (*proto_name && *end)
- return "<protocol> is neither a number nor a valid name";
-
- if (l < 0 || l > 0xff)
- return "<protocol> must be between 0 and 255";
-
- *proto = (u_int8_t)l;
- }
-
- /* is there a port wildcard? */
- *has_port_wildcard = (strcmp(service_name, "%any") == 0);
-
- if (*has_port_wildcard)
- {
- *port = 0;
- return NULL;
- }
-
- /* extract port by trying to resolve it by name */
- service = getservbyname(service_name, NULL);
- if (service != NULL) {
- *port = ntohs(service->s_port);
- }
- else /* failed, now try it by number */
- {
- l = strtol(service_name, &end, 0);
-
- if (*service_name && *end)
- return "<port> is neither a number nor a valid name";
-
- if (l < 0 || l > 0xffff)
- return "<port> must be between 0 and 65535";
-
- *port = (u_int16_t)l;
- }
- return NULL;
-}
-
diff --git a/src/libfreeswan/ttosa.3 b/src/libfreeswan/ttosa.3
deleted file mode 100644
index f9ea36a09..000000000
--- a/src/libfreeswan/ttosa.3
+++ /dev/null
@@ -1,287 +0,0 @@
-.TH IPSEC_TTOSA 3 "26 Nov 2001"
-.SH NAME
-ipsec ttosa, satot \- convert IPsec Security Association IDs to and from text
-.br
-ipsec initsaid \- initialize an SA ID
-.SH SYNOPSIS
-.B "#include <freeswan.h>
-.sp
-.B "typedef struct {"
-.ti +1c
-.B "ip_address dst;"
-.ti +1c
-.B "ipsec_spi_t spi;"
-.ti +1c
-.B "int proto;"
-.br
-.B "} ip_said;"
-.sp
-.B "const char *ttosa(const char *src, size_t srclen,"
-.ti +1c
-.B "ip_said *sa);
-.br
-.B "size_t satot(const ip_said *sa, int format,"
-.ti +1c
-.B "char *dst, size_t dstlen);"
-.br
-.B "void initsaid(const ip_address *addr, ipsec_spi_t spi,"
-.ti +1c
-.B "int proto, ip_said *dst);"
-.SH DESCRIPTION
-.I Ttosa
-converts an ASCII Security Association (SA) specifier into an
-.B ip_said
-structure (containing
-a destination-host address
-in network byte order,
-an SPI number in network byte order, and
-a protocol code).
-.I Satot
-does the reverse conversion, back to a text SA specifier.
-.I Initsaid
-initializes an
-.B ip_said
-from separate items of information.
-.PP
-An SA is specified in text with a mail-like syntax, e.g.
-.BR esp.5a7@1.2.3.4 .
-An SA specifier contains
-a protocol prefix (currently
-.BR ah ,
-.BR esp ,
-.BR tun ,
-.BR comp ,
-or
-.BR int ),
-a single character indicating the address family
-.RB ( .
-for IPv4,
-.B :
-for IPv6),
-an unsigned integer SPI number in hexadecimal (with no
-.B 0x
-prefix),
-and an IP address.
-The IP address can be any form accepted by
-.IR ipsec_ttoaddr (3),
-e.g. dotted-decimal IPv4 address,
-colon-hex IPv6 address,
-or DNS name.
-.PP
-As a special case, the SA specifier
-.B %passthrough4
-or
-.B %passthrough6
-signifies the special SA used to indicate that packets should be
-passed through unaltered.
-(At present, these are synonyms for
-.B tun.0@0.0.0.0
-and
-.B tun:0@::
-respectively,
-but that is subject to change without notice.)
-.B %passthrough
-is a historical synonym for
-.BR %passthrough4 .
-These forms are known to both
-.I ttosa
-and
-.IR satot ,
-so the internal representation is never visible.
-.PP
-Similarly, the SA specifiers
-.BR %pass ,
-.BR %drop ,
-.BR %reject ,
-.BR %hold ,
-.BR %trap ,
-and
-.BR %trapsubnet
-signify special ``magic'' SAs used to indicate that packets should be
-passed, dropped, rejected (dropped with ICMP notification),
-held,
-and trapped (sent up to
-.IR ipsec_pluto (8),
-with either of two forms of
-.B %hold
-automatically installed)
-respectively.
-These forms too are known to both routines,
-so the internal representation of the magic SAs should never be visible.
-.PP
-The
-.B <freeswan.h>
-header file supplies the
-.B ip_said
-structure, as well as a data type
-.B ipsec_spi_t
-which is an unsigned 32-bit integer.
-(There is no consistency between kernel and user on what such a type
-is called, hence the header hides the differences.)
-.PP
-The protocol code uses the same numbers that IP does.
-For user convenience, given the difficulty in acquiring the exact set of
-protocol names used by the kernel,
-.B <freeswan.h>
-defines the names
-.BR SA_ESP ,
-.BR SA_AH ,
-.BR SA_IPIP ,
-and
-.BR SA_COMP
-to have the same values as the kernel names
-.BR IPPROTO_ESP ,
-.BR IPPROTO_AH ,
-.BR IPPROTO_IPIP ,
-and
-.BR IPPROTO_COMP .
-.PP
-.B <freeswan.h>
-also defines
-.BR SA_INT
-to have the value
-.BR 61
-(reserved by IANA for ``any host internal protocol'')
-and
-.BR SPI_PASS ,
-.BR SPI_DROP ,
-.BR SPI_REJECT ,
-.BR SPI_HOLD ,
-and
-.B SPI_TRAP
-to have the values 256-260 (in \fIhost\fR byte order) respectively.
-These are used in constructing the magic SAs
-(which always have address
-.BR 0.0.0.0 ).
-.PP
-If
-.I satot
-encounters an unknown protocol code, e.g. 77,
-it yields output using a prefix
-showing the code numerically, e.g. ``unk77''.
-This form is
-.I not
-recognized by
-.IR ttosa .
-.PP
-The
-.I srclen
-parameter of
-.I ttosa
-specifies the length of the string pointed to by
-.IR src ;
-it is an error for there to be anything else
-(e.g., a terminating NUL) within that length.
-As a convenience for cases where an entire NUL-terminated string is
-to be converted,
-a
-.I srclen
-value of
-.B 0
-is taken to mean
-.BR strlen(src) .
-.PP
-The
-.I dstlen
-parameter of
-.I satot
-specifies the size of the
-.I dst
-parameter;
-under no circumstances are more than
-.I dstlen
-bytes written to
-.IR dst .
-A result which will not fit is truncated.
-.I Dstlen
-can be zero, in which case
-.I dst
-need not be valid and no result is written,
-but the return value is unaffected;
-in all other cases, the (possibly truncated) result is NUL-terminated.
-The
-.B <freeswan.h>
-header file defines a constant,
-.BR SATOT_BUF ,
-which is the size of a buffer just large enough for worst-case results.
-.PP
-The
-.I format
-parameter of
-.I satot
-specifies what format is to be used for the conversion.
-The value
-.B 0
-(not the ASCII character
-.BR '0' ,
-but a zero value)
-specifies a reasonable default
-(currently
-lowercase protocol prefix, lowercase hexadecimal SPI,
-dotted-decimal or colon-hex address).
-The value
-.B 'f'
-is similar except that the SPI is padded with
-.BR 0 s
-to a fixed 32-bit width, to ease aligning displayed tables.
-.PP
-.I Ttosa
-returns
-.B NULL
-for success and
-a pointer to a string-literal error message for failure;
-see DIAGNOSTICS.
-.I Satot
-returns
-.B 0
-for a failure, and otherwise
-always returns the size of buffer which would
-be needed to
-accommodate the full conversion result, including terminating NUL;
-it is the caller's responsibility to check this against the size of
-the provided buffer to determine whether truncation has occurred.
-.PP
-There is also, temporarily, support for some obsolete
-forms of SA specifier which lack the address-family indicator.
-.SH SEE ALSO
-ipsec_ttoul(3), ipsec_ttoaddr(3), ipsec_samesaid(3), inet(3)
-.SH DIAGNOSTICS
-Fatal errors in
-.I ttosa
-are:
-empty input;
-input too small to be a legal SA specifier;
-no
-.B @
-in input;
-unknown protocol prefix;
-conversion error in
-.I ttoul
-or
-.IR ttoaddr .
-.PP
-Fatal errors in
-.I satot
-are:
-unknown format.
-.SH HISTORY
-Written for the FreeS/WAN project by Henry Spencer.
-.SH BUGS
-The restriction of text-to-binary error reports to literal strings
-(so that callers don't need to worry about freeing them or copying them)
-does limit the precision of error reporting.
-.PP
-The text-to-binary error-reporting convention lends itself
-to slightly obscure code,
-because many readers will not think of NULL as signifying success.
-A good way to make it clearer is to write something like:
-.PP
-.RS
-.nf
-.B "const char *error;"
-.sp
-.B "error = ttosa( /* ... */ );"
-.B "if (error != NULL) {"
-.B " /* something went wrong */"
-.fi
-.RE
diff --git a/src/libfreeswan/ttosa.c b/src/libfreeswan/ttosa.c
deleted file mode 100644
index 9873231c0..000000000
--- a/src/libfreeswan/ttosa.c
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * convert from text form of SA ID to binary
- * Copyright (C) 2000, 2001 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-#include <sys/socket.h>
-
-#include "internal.h"
-#include "freeswan.h"
-
-static struct satype {
- char *prefix;
- size_t prelen; /* strlen(prefix) */
- int proto;
-} satypes[] = {
- { "ah", 2, SA_AH },
- { "esp", 3, SA_ESP },
- { "tun", 3, SA_IPIP },
- { "comp", 4, SA_COMP },
- { "int", 3, SA_INT },
- { NULL, 0, 0, }
-};
-
-static struct magic {
- char *name;
- char *really;
-} magic[] = {
- { PASSTHROUGHNAME, PASSTHROUGH4IS },
- { PASSTHROUGH4NAME, PASSTHROUGH4IS },
- { PASSTHROUGH6NAME, PASSTHROUGH6IS },
- { "%pass", "int256@0.0.0.0" },
- { "%drop", "int257@0.0.0.0" },
- { "%reject", "int258@0.0.0.0" },
- { "%hold", "int259@0.0.0.0" },
- { "%trap", "int260@0.0.0.0" },
- { "%trapsubnet", "int261@0.0.0.0" },
- { NULL, NULL }
-};
-
-/*
- - ttosa - convert text "ah507@10.0.0.1" to SA identifier
- */
-err_t /* NULL for success, else string literal */
-ttosa(src, srclen, sa)
-const char *src;
-size_t srclen; /* 0 means "apply strlen" */
-ip_said *sa;
-{
- const char *at;
- const char *addr;
- size_t alen;
- const char *spi = NULL;
- struct satype *sat;
- unsigned long ul;
- const char *oops;
- struct magic *mp;
- size_t nlen;
-# define MINLEN 5 /* ah0@0 is as short as it can get */
- int af;
- int base;
-
- if (srclen == 0)
- srclen = strlen(src);
- if (srclen == 0)
- return "empty string";
- if (srclen < MINLEN)
- return "string too short to be SA identifier";
- if (*src == '%') {
- for (mp = magic; mp->name != NULL; mp++) {
- nlen = strlen(mp->name);
- if (srclen == nlen && memcmp(src, mp->name, nlen) == 0)
- break;
- }
- if (mp->name == NULL)
- return "unknown % keyword";
- src = mp->really;
- srclen = strlen(src);
- }
-
- at = memchr(src, '@', srclen);
- if (at == NULL)
- return "no @ in SA specifier";
-
- for (sat = satypes; sat->prefix != NULL; sat++)
- if (sat->prelen < srclen &&
- strncmp(src, sat->prefix, sat->prelen) == 0) {
- sa->proto = sat->proto;
- spi = src + sat->prelen;
- break; /* NOTE BREAK OUT */
- }
- if (sat->prefix == NULL)
- return "SA specifier lacks valid protocol prefix";
-
- if (spi >= at)
- return "no SPI in SA specifier";
- switch (*spi) {
- case '.':
- af = AF_INET;
- spi++;
- base = 16;
- break;
- case ':':
- af = AF_INET6;
- spi++;
- base = 16;
- break;
- default:
- af = AF_UNSPEC; /* not known yet */
- base = 0;
- break;
- }
- if (spi >= at)
- return "no SPI found in SA specifier";
- oops = ttoul(spi, at - spi, base, &ul);
- if (oops != NULL)
- return oops;
- sa->spi = htonl(ul);
-
- addr = at + 1;
- alen = srclen - (addr - src);
- if (af == AF_UNSPEC)
- af = (memchr(addr, ':', alen) != NULL) ? AF_INET6 : AF_INET;
- oops = ttoaddr(addr, alen, af, &sa->dst);
- if (oops != NULL)
- return oops;
-
- return NULL;
-}
-
-
-
-#ifdef TTOSA_MAIN
-
-#include <stdio.h>
-
-void regress(void);
-
-int
-main(int argc, char *argv[])
-{
- ip_said sa;
- char buf[100];
- char buf2[100];
- const char *oops;
- size_t n;
-
- if (argc < 2) {
- fprintf(stderr, "Usage: %s {ahnnn@aaa|-r}\n", argv[0]);
- exit(2);
- }
-
- if (strcmp(argv[1], "-r") == 0) {
- regress();
- fprintf(stderr, "regress() returned?!?\n");
- exit(1);
- }
-
- oops = ttosa(argv[1], 0, &sa);
- if (oops != NULL) {
- fprintf(stderr, "%s: conversion failed: %s\n", argv[0], oops);
- exit(1);
- }
- n = satot(&sa, 0, buf, sizeof(buf));
- if (n > sizeof(buf)) {
- fprintf(stderr, "%s: reverse conv of `%d'", argv[0], sa.proto);
- fprintf(stderr, "%lx@", (long unsigned int)sa.spi);
- (void) addrtot(&sa.dst, 0, buf2, sizeof(buf2));
- fprintf(stderr, "%s", buf2);
- fprintf(stderr, " failed: need %ld bytes, have only %ld\n",
- (long)n, (long)sizeof(buf));
- exit(1);
- }
- printf("%s\n", buf);
-
- exit(0);
-}
-
-struct rtab {
- int format;
-# define FUDGE 0x1000
- char *input;
- char *output; /* NULL means error expected */
-} rtab[] = {
- {0, "esp257@1.2.3.0", "esp.101@1.2.3.0"},
- {0, "ah0x20@1.2.3.4", "ah.20@1.2.3.4"},
- {0, "tun20@1.2.3.4", "tun.14@1.2.3.4"},
- {0, "comp20@1.2.3.4", "comp.14@1.2.3.4"},
- {0, "esp257@::1", "esp:101@::1"},
- {0, "esp257@0bc:12de::1", "esp:101@bc:12de::1"},
- {0, "esp78@1049:1::8007:2040", "esp:4e@1049:1::8007:2040"},
- {0, "esp0x78@1049:1::8007:2040", "esp:78@1049:1::8007:2040"},
- {0, "ah78@1049:1::8007:2040", "ah:4e@1049:1::8007:2040"},
- {0, "ah0x78@1049:1::8007:2040", "ah:78@1049:1::8007:2040"},
- {0, "tun78@1049:1::8007:2040", "tun:4e@1049:1::8007:2040"},
- {0, "tun0x78@1049:1::8007:2040", "tun:78@1049:1::8007:2040"},
- {0, "duk99@3ffe:370:400:ff::9001:3001", NULL},
- {0, "esp78x@1049:1::8007:2040", NULL},
- {0, "esp0x78@1049:1:0xfff::8007:2040", NULL},
- {0, "es78@1049:1::8007:2040", NULL},
- {0, "", NULL},
- {0, "_", NULL},
- {0, "ah2.2", NULL},
- {0, "goo2@1.2.3.4", NULL},
- {0, "esp9@1.2.3.4", "esp.9@1.2.3.4"},
- {'f', "esp0xa9@1.2.3.4", "esp.000000a9@1.2.3.4"},
- {0, "espp9@1.2.3.4", NULL},
- {0, "es9@1.2.3.4", NULL},
- {0, "ah@1.2.3.4", NULL},
- {0, "esp7x7@1.2.3.4", NULL},
- {0, "esp77@1.0x2.3.4", NULL},
- {0, PASSTHROUGHNAME, PASSTHROUGH4NAME},
- {0, PASSTHROUGH6NAME, PASSTHROUGH6NAME},
- {0, "%pass", "%pass"},
- {0, "int256@0.0.0.0", "%pass"},
- {0, "%drop", "%drop"},
- {0, "int257@0.0.0.0", "%drop"},
- {0, "%reject", "%reject"},
- {0, "int258@0.0.0.0", "%reject"},
- {0, "%hold", "%hold"},
- {0, "int259@0.0.0.0", "%hold"},
- {0, "%trap", "%trap"},
- {0, "int260@0.0.0.0", "%trap"},
- {0, "%trapsubnet", "%trapsubnet"},
- {0, "int261@0.0.0.0", "%trapsubnet"},
- {0, "int262@0.0.0.0", "int.106@0.0.0.0"},
- {FUDGE, "esp9@1.2.3.4", "unk77.9@1.2.3.4"},
- {0, NULL, NULL}
-};
-
-void
-regress(void)
-{
- struct rtab *r;
- int status = 0;
- ip_said sa;
- char in[100];
- char buf[100];
- const char *oops;
- size_t n;
-
- for (r = rtab; r->input != NULL; r++) {
- strcpy(in, r->input);
- oops = ttosa(in, 0, &sa);
- if (oops != NULL && r->output == NULL)
- {} /* okay, error expected */
- else if (oops != NULL) {
- printf("`%s' ttosa failed: %s\n", r->input, oops);
- status = 1;
- } else if (r->output == NULL) {
- printf("`%s' ttosa succeeded unexpectedly\n",
- r->input);
- status = 1;
- } else {
- if (r->format&FUDGE)
- sa.proto = 77;
- n = satot(&sa, (char)r->format, buf, sizeof(buf));
- if (n > sizeof(buf)) {
- printf("`%s' satot failed: need %ld\n",
- r->input, (long)n);
- status = 1;
- } else if (strcmp(r->output, buf) != 0) {
- printf("`%s' gave `%s', expected `%s'\n",
- r->input, buf, r->output);
- status = 1;
- }
- }
- }
- exit(status);
-}
-
-#endif /* TTOSA_MAIN */
diff --git a/src/libfreeswan/ttosubnet.c b/src/libfreeswan/ttosubnet.c
deleted file mode 100644
index a18a3f326..000000000
--- a/src/libfreeswan/ttosubnet.c
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * convert from text form of subnet specification to binary
- * Copyright (C) 2000 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-#include <sys/socket.h>
-
-#include "internal.h"
-#include "freeswan.h"
-
-#ifndef DEFAULTSUBNET
-#define DEFAULTSUBNET "%default"
-#endif
-
-/*
- - ttosubnet - convert text "addr/mask" to address and mask
- * Mask can be integer bit count.
- */
-err_t
-ttosubnet(src, srclen, af, dst)
-const char *src;
-size_t srclen; /* 0 means "apply strlen" */
-int af; /* AF_INET or AF_INET6 */
-ip_subnet *dst;
-{
- const char *slash;
- const char *colon;
- const char *mask;
- size_t mlen;
- const char *oops;
- unsigned long bc;
- static char def[] = DEFAULTSUBNET;
-# define DEFLEN (sizeof(def) - 1) /* -1 for NUL */
- static char defis4[] = "0/0";
-# define DEFIS4LEN (sizeof(defis4) - 1)
- static char defis6[] = "::/0";
-# define DEFIS6LEN (sizeof(defis6) - 1)
- ip_address addrtmp;
- ip_address masktmp;
- int nbits;
- int i;
-
- if (srclen == 0)
- srclen = strlen(src);
- if (srclen == 0)
- return "empty string";
-
- switch (af) {
- case AF_INET:
- nbits = 32;
- break;
- case AF_INET6:
- nbits = 128;
- break;
- default:
- return "unknown address family in ttosubnet";
- break;
- }
-
- if (srclen == DEFLEN && strncmp(src, def, srclen) == 0) {
- src = (af == AF_INET) ? defis4 : defis6;
- srclen = (af == AF_INET) ? DEFIS4LEN : DEFIS6LEN;
- }
-
- slash = memchr(src, '/', srclen);
- if (slash == NULL)
- return "no / in subnet specification";
- mask = slash + 1;
- mlen = srclen - (mask - src);
-
- oops = ttoaddr(src, slash-src, af, &addrtmp);
- if (oops != NULL)
- return oops;
-
- /* extract port */
- colon = memchr(mask, ':', mlen);
- if (colon == 0)
- {
- setportof(0, &addrtmp);
- }
- else
- {
- long port;
-
- oops = ttoul(colon+1, mlen-(colon-mask+1), 10, &port);
- if (oops != NULL)
- return oops;
- setportof(htons(port), &addrtmp);
- mlen = colon - mask;
- }
-
- /*extract mask */
- oops = ttoul(mask, mlen, 10, &bc);
- if (oops == NULL) {
- /* ttoul succeeded, it's a bit-count mask */
- if (bc > nbits)
- return "subnet mask bit count too large";
- i = bc;
- } else {
- oops = ttoaddr(mask, mlen, af, &masktmp);
- if (oops != NULL)
- return oops;
- i = masktocount(&masktmp);
- if (i < 0)
- return "non-contiguous or otherwise erroneous mask";
- }
-
- return initsubnet(&addrtmp, i, '0', dst);
-}
-
-
-
-#ifdef TTOSUBNET_MAIN
-
-#include <stdio.h>
-
-void regress(void);
-
-int main(int argc, char *argv[])
-{
- ip_subnet s;
- char buf[100];
- char buf2[100];
- const char *oops;
- size_t n;
- int af;
- char *p;
-
- if (argc < 2) {
- fprintf(stderr, "Usage: %s [-6] addr/mask\n", argv[0]);
- fprintf(stderr, " or: %s -r\n", argv[0]);
- exit(2);
- }
-
- if (strcmp(argv[1], "-r") == 0) {
- regress();
- fprintf(stderr, "regress() returned?!?\n");
- exit(1);
- }
-
- af = AF_INET;
- p = argv[1];
- if (strcmp(argv[1], "-6") == 0) {
- af = AF_INET6;
- p = argv[2];
- } else if (strchr(argv[1], ':') != NULL)
- af = AF_INET6;
-
- oops = ttosubnet(p, 0, af, &s);
- if (oops != NULL) {
- fprintf(stderr, "%s: conversion failed: %s\n", argv[0], oops);
- exit(1);
- }
- n = subnettot(&s, 0, buf, sizeof(buf));
- if (n > sizeof(buf)) {
- fprintf(stderr, "%s: reverse conversion of ", argv[0]);
- (void) addrtot(&s.addr, 0, buf2, sizeof(buf2));
- fprintf(stderr, "%s/", buf2);
- fprintf(stderr, "%d", s.maskbits);
- fprintf(stderr, " failed: need %ld bytes, have only %ld\n",
- (long)n, (long)sizeof(buf));
- exit(1);
- }
- printf("%s\n", buf);
-
- exit(0);
-}
-
-struct rtab {
- int family;
- char *input;
- char *output; /* NULL means error expected */
-} rtab[] = {
- {4, "1.2.3.0/255.255.255.0", "1.2.3.0/24"},
- {4, "1.2.3.0/24", "1.2.3.0/24"},
- {4, "1.2.3.0/24:10", "1.2.3.0/24:10"},
- {4, "1.2.3.0/24:-1", NULL},
- {4, "1.2.3.0/24:none", NULL},
- {4, "1.2.3.0/24:", NULL},
- {4, "1.2.3.0/24:0x10", "1.2.3.0/24:16"},
- {4, "1.2.3.0/24:0X10", "1.2.3.0/24:16"},
- {4, "1.2.3.0/24:010", "1.2.3.0/24:8"},
- {4, "1.2.3.1/255.255.255.240", "1.2.3.0/28"},
- {4, "1.2.3.1/32", "1.2.3.1/32"},
- {4, "1.2.3.1/0", "0.0.0.0/0"},
-/* {4, "1.2.3.1/255.255.127.0", "1.2.3.0/255.255.127.0"}, */
- {4, "1.2.3.1/255.255.127.0", NULL},
- {4, "128.009.000.032/32", "128.9.0.32/32"},
- {4, "128.0x9.0.32/32", NULL},
- {4, "0x80090020/32", "128.9.0.32/32"},
- {4, "0x800x0020/32", NULL},
- {4, "128.9.0.32/0xffFF0000", "128.9.0.0/16"},
- {4, "128.9.0.32/0xff0000FF", NULL},
- {4, "128.9.0.32/0x0000ffFF", NULL},
- {4, "128.9.0.32/0x00ffFF0000", NULL},
- {4, "128.9.0.32/0xffFF", NULL},
- {4, "128.9.0.32.27/32", NULL},
- {4, "128.9.0k32/32", NULL},
- {4, "328.9.0.32/32", NULL},
- {4, "128.9..32/32", NULL},
- {4, "10/8", "10.0.0.0/8"},
- {4, "10.0/8", "10.0.0.0/8"},
- {4, "10.0.0/8", "10.0.0.0/8"},
- {4, "10.0.1/24", "10.0.1.0/24"},
- {4, "_", NULL},
- {4, "_/_", NULL},
- {4, "1.2.3.1", NULL},
- {4, "1.2.3.1/_", NULL},
- {4, "1.2.3.1/24._", NULL},
- {4, "1.2.3.1/99", NULL},
- {4, "localhost/32", "127.0.0.1/32"},
- {4, "%default", "0.0.0.0/0"},
- {6, "3049:1::8007:2040/0", "::/0"},
- {6, "3049:1::8007:2040/128", "3049:1::8007:2040/128"},
- {6, "3049:1::192.168.0.1/128", NULL}, /*"3049:1::c0a8:1/128",*/
- {6, "3049:1::8007::2040/128", NULL},
- {6, "3049:1::8007:2040/ffff::0", "3049::/16"},
- {6, "3049:1::8007:2040/64", "3049:1::/64"},
- {6, "3049:1::8007:2040/ffff::", "3049::/16"},
- {6, "3049:1::8007:2040/0000:ffff::0", NULL},
- {6, "3049:1::8007:2040/ff1f::0", NULL},
- {6, "3049:1::8007:x:2040/128", NULL},
- {6, "3049:1t::8007:2040/128", NULL},
- {6, "3049:1::80071:2040/128", NULL},
- {6, "::/21", "::/21"},
- {6, "::1/128", "::1/128"},
- {6, "1::/21", "1::/21"},
- {6, "1::2/128", "1::2/128"},
- {6, "1:0:0:0:0:0:0:2/128", "1::2/128"},
- {6, "1:0:0:0:3:0:0:2/128", "1::3:0:0:2/128"},
- {6, "1:0:0:3:0:0:0:2/128", "1::3:0:0:0:2/128"},
- {6, "1:0:3:0:0:0:0:2/128", "1:0:3::2/128"},
- {6, "abcd:ef01:2345:6789:0:00a:000:20/128", "abcd:ef01:2345:6789:0:a:0:20/128"},
- {6, "3049:1::8007:2040/ffff:ffff:", NULL},
- {6, "3049:1::8007:2040/ffff:88::", NULL},
- {6, "3049:12::9000:3200/ffff:fff0::", "3049:10::/28"},
- {6, "3049:12::9000:3200/28", "3049:10::/28"},
- {6, "3049:12::9000:3200/ff00:::", NULL},
- {6, "3049:12::9000:3200/ffff:::", NULL},
- {6, "3049:12::9000:3200/128_", NULL},
- {6, "3049:12::9000:3200/", NULL},
- {6, "%default", "::/0"},
- {4, NULL, NULL}
-};
-
-void
-regress(void)
-{
- struct rtab *r;
- int status = 0;
- ip_subnet s;
- char in[100];
- char buf[100];
- const char *oops;
- size_t n;
- int af;
-
- for (r = rtab; r->input != NULL; r++) {
- af = (r->family == 4) ? AF_INET : AF_INET6;
- strcpy(in, r->input);
- oops = ttosubnet(in, 0, af, &s);
- if (oops != NULL && r->output == NULL)
- {} /* okay, error expected */
- else if (oops != NULL) {
- printf("`%s' ttosubnet failed: %s\n", r->input, oops);
- status = 1;
- } else if (r->output == NULL) {
- printf("`%s' ttosubnet succeeded unexpectedly\n",
- r->input);
- status = 1;
- } else {
- n = subnettot(&s, 0, buf, sizeof(buf));
- if (n > sizeof(buf)) {
- printf("`%s' subnettot failed: need %ld\n",
- r->input, (long)n);
- status = 1;
- } else if (strcmp(r->output, buf) != 0) {
- printf("`%s' gave `%s', expected `%s'\n",
- r->input, buf, r->output);
- status = 1;
- }
- }
- }
- exit(status);
-}
-
-#endif /* TTOSUBNET_MAIN */
diff --git a/src/libfreeswan/ttoul.3 b/src/libfreeswan/ttoul.3
deleted file mode 100644
index ffd9fb38a..000000000
--- a/src/libfreeswan/ttoul.3
+++ /dev/null
@@ -1,191 +0,0 @@
-.TH IPSEC_TTOUL 3 "16 Aug 2000"
-.SH NAME
-ipsec ttoul, ultot \- convert unsigned-long numbers to and from text
-.SH SYNOPSIS
-.B "#include <freeswan.h>
-.sp
-.B "const char *ttoul(const char *src, size_t srclen,"
-.ti +1c
-.B "int base, unsigned long *n);"
-.br
-.B "size_t ultot(unsigned long n, int format, char *dst,"
-.ti +1c
-.B "size_t dstlen);"
-.SH DESCRIPTION
-.I Ttoul
-converts a text-string number into a binary
-.B "unsigned long"
-value.
-.I Ultot
-does the reverse conversion, back to a text version.
-.PP
-Numbers are specified in text as
-decimal (e.g.
-.BR 123 ),
-octal with a leading zero (e.g.
-.BR 012 ,
-which has value 10),
-or hexadecimal with a leading
-.B 0x
-(e.g.
-.BR 0x1f ,
-which has value 31)
-in either upper or lower case.
-.PP
-The
-.I srclen
-parameter of
-.I ttoul
-specifies the length of the string pointed to by
-.IR src ;
-it is an error for there to be anything else
-(e.g., a terminating NUL) within that length.
-As a convenience for cases where an entire NUL-terminated string is
-to be converted,
-a
-.I srclen
-value of
-.B 0
-is taken to mean
-.BR strlen(src) .
-.PP
-The
-.I base
-parameter of
-.I ttoul
-can be
-.BR 8 ,
-.BR 10 ,
-or
-.BR 16 ,
-in which case the number supplied is assumed to be of that form
-(and in the case of
-.BR 16 ,
-to lack any
-.B 0x
-prefix).
-It can also be
-.BR 0 ,
-in which case the number is examined for a leading zero
-or a leading
-.B 0x
-to determine its base.
-.PP
-The
-.I dstlen
-parameter of
-.I ultot
-specifies the size of the
-.I dst
-parameter;
-under no circumstances are more than
-.I dstlen
-bytes written to
-.IR dst .
-A result which will not fit is truncated.
-.I Dstlen
-can be zero, in which case
-.I dst
-need not be valid and no result is written,
-but the return value is unaffected;
-in all other cases, the (possibly truncated) result is NUL-terminated.
-The
-.I freeswan.h
-header file defines a constant,
-.BR ULTOT_BUF ,
-which is the size of a buffer just large enough for worst-case results.
-.PP
-The
-.I format
-parameter of
-.I ultot
-must be one of:
-.RS
-.IP \fB'o'\fR 4
-octal conversion with leading
-.B 0
-.IP \fB\ 8\fR
-octal conversion with no leading
-.B 0
-.IP \fB'd'\fR
-decimal conversion
-.IP \fB10\fR
-same as
-.B d
-.IP \fB'x'\fR
-hexadecimal conversion, including leading
-.B 0x
-.IP \fB16\fR
-hexadecimal conversion with no leading
-.B 0x
-.IP \fB17\fR
-like
-.B 16
-except padded on left with
-.BR 0 s
-to eight digits (full width of a 32-bit number)
-.RE
-.PP
-.I Ttoul
-returns NULL for success and
-a pointer to a string-literal error message for failure;
-see DIAGNOSTICS.
-.I Ultot
-returns
-.B 0
-for a failure, and otherwise
-returns the size of buffer which would
-be needed to
-accommodate the full conversion result, including terminating NUL
-(it is the caller's responsibility to check this against the size of
-the provided buffer to determine whether truncation has occurred).
-.SH SEE ALSO
-atol(3), strtoul(3)
-.SH DIAGNOSTICS
-Fatal errors in
-.I ttoul
-are:
-empty input;
-unknown
-.IR base ;
-non-digit character found;
-number too large for an
-.BR "unsigned long" .
-.PP
-Fatal errors in
-.I ultot
-are:
-unknown
-.IR format .
-.SH HISTORY
-Written for the FreeS/WAN project by Henry Spencer.
-.SH BUGS
-Conversion of
-.B 0
-with format
-.B o
-yields
-.BR 00 .
-.PP
-.I Ultot
-format
-.B 17
-is a bit of a kludge.
-.PP
-The restriction of error reports to literal strings
-(so that callers don't need to worry about freeing them or copying them)
-does limit the precision of error reporting.
-.PP
-The error-reporting convention lends itself to slightly obscure code,
-because many readers will not think of NULL as signifying success.
-A good way to make it clearer is to write something like:
-.PP
-.RS
-.nf
-.B "const char *error;"
-.sp
-.B "error = ttoul( /* ... */ );"
-.B "if (error != NULL) {"
-.B " /* something went wrong */"
-.fi
-.RE
diff --git a/src/libfreeswan/ttoul.c b/src/libfreeswan/ttoul.c
deleted file mode 100644
index 7524789c4..000000000
--- a/src/libfreeswan/ttoul.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * convert from text form of unsigned long to binary
- * Copyright (C) 2000 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-#include "internal.h"
-#include "freeswan.h"
-
-/*
- - ttoul - convert text substring to unsigned long number
- */
-const char * /* NULL for success, else string literal */
-ttoul(src, srclen, base, resultp)
-const char *src;
-size_t srclen; /* 0 means strlen(src) */
-int base; /* 0 means figure it out */
-unsigned long *resultp;
-{
- const char *stop;
- static char hex[] = "0123456789abcdef";
- static char uchex[] = "0123456789ABCDEF";
- int d;
- char c;
- char *p;
- unsigned long r;
- unsigned long rlimit;
- int dlimit;
-
- if (srclen == 0)
- srclen = strlen(src);
- if (srclen == 0)
- return "empty string";
-
- if (base == 0) {
- if (srclen > 2 && *src == '0' &&
- (*(src+1) == 'x' || *(src+1) == 'X'))
- return ttoul(src+2, srclen-2, 16, resultp);
- if (srclen > 1 && *src == '0')
- return ttoul(src+1, srclen-1, 8, resultp);
- return ttoul(src, srclen, 10, resultp);
- }
- if (base != 8 && base != 10 && base != 16)
- return "unsupported number base";
-
- r = 0;
- stop = src + srclen;
- if (base == 16) {
- while (src < stop) {
- c = *src++;
- p = strchr(hex, c);
- if (p != NULL)
- d = p - hex;
- else {
- p = strchr(uchex, c);
- if (p == NULL)
- return "non-hex digit in hex number";
- d = p - uchex;
- }
- r = (r << 4) | d;
- }
- /* defer length check to catch invalid digits first */
- if (srclen > sizeof(unsigned long) * 2)
- return "hex number too long";
- } else {
- rlimit = ULONG_MAX / base;
- dlimit = (int)(ULONG_MAX - rlimit*base);
- while (src < stop) {
- c = *src++;
- d = c - '0';
- if (d < 0 || d >= base)
- return "non-digit in number";
- if (r > rlimit || (r == rlimit && d > dlimit))
- return "unsigned-long overflow";
- r = r*base + d;
- }
- }
-
- *resultp = r;
- return NULL;
-}
diff --git a/src/libfreeswan/ultoa.c b/src/libfreeswan/ultoa.c
deleted file mode 100644
index 16ddd2c1e..000000000
--- a/src/libfreeswan/ultoa.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * convert unsigned long to ASCII
- * Copyright (C) 1998, 1999 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-#include "internal.h"
-#include "freeswan.h"
-
-/*
- - ultoa - convert unsigned long to decimal ASCII
- */
-size_t /* length required for full conversion */
-ultoa(n, base, dst, dstlen)
-unsigned long n;
-int base;
-char *dst; /* need not be valid if dstlen is 0 */
-size_t dstlen;
-{
- char buf[3*sizeof(unsigned long) + 1];
- char *bufend = buf + sizeof(buf);
- size_t len;
- char *p;
- static char hex[] = "0123456789abcdef";
-
- p = bufend;
- *--p = '\0';
- if (base == 10) {
- do {
- *--p = n%10 + '0';
- n /= 10;
- } while (n != 0);
- } else if (base == 16) {
- do {
- *--p = hex[n&0xf];
- n >>= 4;
- } while (n != 0);
- *--p = 'x';
- *--p = '0';
- } else if (base == 8) {
- do {
- *--p = (n&07) + '0';
- n >>= 3;
- } while (n != 0);
- *--p = '0';
- } else
- *--p = '?';
-
- len = bufend - p;
-
- if (dstlen > 0) {
- if (len > dstlen)
- *(p + dstlen - 1) = '\0';
- strcpy(dst, p);
- }
- return len;
-}
diff --git a/src/libfreeswan/ultot.c b/src/libfreeswan/ultot.c
deleted file mode 100644
index 6685f8f7c..000000000
--- a/src/libfreeswan/ultot.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * convert unsigned long to text
- * Copyright (C) 2000 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
- *
- * This library 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 Library General Public
- * License for more details.
- */
-#include "internal.h"
-#include "freeswan.h"
-
-/*
- - ultot - convert unsigned long to text
- */
-size_t /* length required for full conversion */
-ultot(n, base, dst, dstlen)
-unsigned long n;
-int base;
-char *dst; /* need not be valid if dstlen is 0 */
-size_t dstlen;
-{
- char buf[3*sizeof(unsigned long) + 1];
- char *bufend = buf + sizeof(buf);
- size_t len;
- char *p;
- static char hex[] = "0123456789abcdef";
-# define HEX32 (32/4)
-
- p = bufend;
- *--p = '\0';
- switch (base) {
- case 10:
- case 'd':
- do {
- *--p = n%10 + '0';
- n /= 10;
- } while (n != 0);
- break;
- case 16:
- case 17:
- case 'x':
- do {
- *--p = hex[n&0xf];
- n >>= 4;
- } while (n != 0);
- if (base == 17)
- while (bufend - p < HEX32 + 1)
- *--p = '0';
- if (base == 'x') {
- *--p = 'x';
- *--p = '0';
- }
- break;
- case 8:
- case 'o':
- do {
- *--p = (n&07) + '0';
- n >>= 3;
- } while (n != 0);
- if (base == 'o')
- *--p = '0';
- break;
- default:
- return 0;
- break;
- }
-
- len = bufend - p;
- if (dstlen > 0) {
- if (len > dstlen)
- *(p + dstlen - 1) = '\0';
- strcpy(dst, p);
- }
- return len;
-}
diff --git a/src/libhydra/Makefile.in b/src/libhydra/Makefile.in
index f452719dd..a10981a94 100644
--- a/src/libhydra/Makefile.in
+++ b/src/libhydra/Makefile.in
@@ -63,6 +63,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -94,7 +95,7 @@ libhydra_la_DEPENDENCIES = $(am__append_2) $(am__append_4) \
am_libhydra_la_OBJECTS = hydra.lo attributes.lo attribute_manager.lo \
mem_pool.lo kernel_interface.lo kernel_ipsec.lo kernel_net.lo
libhydra_la_OBJECTS = $(am_libhydra_la_OBJECTS)
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -160,6 +161,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -254,11 +256,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -275,11 +280,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -295,6 +301,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -304,7 +311,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libhydra/attributes/attribute_handler.h b/src/libhydra/attributes/attribute_handler.h
index d042f47ef..6014ef0fa 100644
--- a/src/libhydra/attributes/attribute_handler.h
+++ b/src/libhydra/attributes/attribute_handler.h
@@ -22,8 +22,8 @@
#define ATTRIBUTE_HANDLER_H_
#include <chunk.h>
-#include <utils/host.h>
#include <utils/identification.h>
+#include <utils/linked_list.h>
#include "attributes.h"
@@ -62,11 +62,11 @@ struct attribute_handler_t {
* Enumerate attributes to request from a server.
*
* @param server server identity to request attributes from
- * @param vip virtual IP we are requesting, if any
+ * @param vips list of virtual IPs (host_t*) we are requesting
* @return enumerator (configuration_attribute_type_t, chunk_t)
*/
enumerator_t* (*create_attribute_enumerator)(attribute_handler_t *this,
- identification_t *server, host_t *vip);
+ identification_t *server, linked_list_t *vips);
};
#endif /** ATTRIBUTE_HANDLER_H_ @}*/
diff --git a/src/libhydra/attributes/attribute_manager.c b/src/libhydra/attributes/attribute_manager.c
index 95520531e..000d2e082 100644
--- a/src/libhydra/attributes/attribute_manager.c
+++ b/src/libhydra/attributes/attribute_manager.c
@@ -51,17 +51,17 @@ struct private_attribute_manager_t {
* Data to pass to enumerator filters
*/
typedef struct {
- /** attribute group pool */
- char *pool;
+ /** attribute group pools */
+ linked_list_t *pools;
/** server/peer identity */
identification_t *id;
- /** requesting/assigned virtual IP */
- host_t *vip;
+ /** requesting/assigned virtual IPs */
+ linked_list_t *vips;
} enum_data_t;
METHOD(attribute_manager_t, acquire_address, host_t*,
- private_attribute_manager_t *this, char *pool, identification_t *id,
- host_t *requested)
+ private_attribute_manager_t *this, linked_list_t *pools,
+ identification_t *id, host_t *requested)
{
enumerator_t *enumerator;
attribute_provider_t *current;
@@ -71,7 +71,7 @@ METHOD(attribute_manager_t, acquire_address, host_t*,
enumerator = this->providers->create_enumerator(this->providers);
while (enumerator->enumerate(enumerator, &current))
{
- host = current->acquire_address(current, pool, id, requested);
+ host = current->acquire_address(current, pools, id, requested);
if (host)
{
break;
@@ -80,15 +80,11 @@ METHOD(attribute_manager_t, acquire_address, host_t*,
enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
- if (!host)
- {
- DBG1(DBG_CFG, "acquiring address from pool '%s' failed", pool);
- }
return host;
}
-METHOD(attribute_manager_t, release_address, void,
- private_attribute_manager_t *this, char *pool, host_t *address,
+METHOD(attribute_manager_t, release_address, bool,
+ private_attribute_manager_t *this, linked_list_t *pools, host_t *address,
identification_t *id)
{
enumerator_t *enumerator;
@@ -99,7 +95,7 @@ METHOD(attribute_manager_t, release_address, void,
enumerator = this->providers->create_enumerator(this->providers);
while (enumerator->enumerate(enumerator, &current))
{
- if (current->release_address(current, pool, address, id))
+ if (current->release_address(current, pools, address, id))
{
found = TRUE;
break;
@@ -108,10 +104,7 @@ METHOD(attribute_manager_t, release_address, void,
enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
- if (!found)
- {
- DBG1(DBG_CFG, "releasing address to pool '%s' failed", pool);
- }
+ return found;
}
/**
@@ -120,19 +113,21 @@ METHOD(attribute_manager_t, release_address, void,
static enumerator_t *responder_enum_create(attribute_provider_t *provider,
enum_data_t *data)
{
- return provider->create_attribute_enumerator(provider, data->pool,
- data->id, data->vip);
+ return provider->create_attribute_enumerator(provider, data->pools,
+ data->id, data->vips);
}
METHOD(attribute_manager_t, create_responder_enumerator, enumerator_t*,
- private_attribute_manager_t *this, char *pool, identification_t *id,
- host_t *vip)
+ private_attribute_manager_t *this, linked_list_t *pools,
+ identification_t *id, linked_list_t *vips)
{
- enum_data_t *data = malloc_thing(enum_data_t);
+ enum_data_t *data;
- data->pool = pool;
- data->id = id;
- data->vip = vip;
+ INIT(data,
+ .pools = pools,
+ .id = id,
+ .vips = vips,
+ );
this->lock->read_lock(this->lock);
return enumerator_create_cleaner(
enumerator_create_nested(
@@ -238,8 +233,8 @@ typedef struct {
enumerator_t *inner;
/** server ID we want attributes for */
identification_t *id;
- /** virtual IP we are requesting along with attriubutes */
- host_t *vip;
+ /** virtual IPs we are requesting along with attriubutes */
+ linked_list_t *vips;
} initiator_enumerator_t;
/**
@@ -259,7 +254,7 @@ static bool initiator_enumerate(initiator_enumerator_t *this,
}
DESTROY_IF(this->inner);
this->inner = this->handler->create_attribute_enumerator(this->handler,
- this->id, this->vip);
+ this->id, this->vips);
}
/* inject the handler as additional attribute */
*handler = this->handler;
@@ -278,20 +273,22 @@ static void initiator_destroy(initiator_enumerator_t *this)
}
METHOD(attribute_manager_t, create_initiator_enumerator, enumerator_t*,
- private_attribute_manager_t *this, identification_t *id, host_t *vip)
+ private_attribute_manager_t *this, identification_t *id, linked_list_t *vips)
{
- initiator_enumerator_t *enumerator = malloc_thing(initiator_enumerator_t);
+ initiator_enumerator_t *enumerator;
this->lock->read_lock(this->lock);
- enumerator->public.enumerate = (void*)initiator_enumerate;
- enumerator->public.destroy = (void*)initiator_destroy;
- enumerator->this = this;
- enumerator->id = id;
- enumerator->vip = vip;
- enumerator->outer = this->handlers->create_enumerator(this->handlers);
- enumerator->inner = NULL;
- enumerator->handler = NULL;
+ INIT(enumerator,
+ .public = {
+ .enumerate = (void*)initiator_enumerate,
+ .destroy = (void*)initiator_destroy,
+ },
+ .this = this,
+ .id = id,
+ .vips = vips,
+ .outer = this->handlers->create_enumerator(this->handlers),
+ );
return &enumerator->public;
}
diff --git a/src/libhydra/attributes/attribute_manager.h b/src/libhydra/attributes/attribute_manager.h
index 56afef7c6..99f41772c 100644
--- a/src/libhydra/attributes/attribute_manager.h
+++ b/src/libhydra/attributes/attribute_manager.h
@@ -39,35 +39,38 @@ struct attribute_manager_t {
/**
* Acquire a virtual IP address to assign to a peer.
*
- * @param pool pool name to acquire address from
+ * @param pools list of pool names (char*) to acquire from
* @param id peer identity to get address forua
* @param requested IP in configuration request
* @return allocated address, NULL to serve none
*/
host_t* (*acquire_address)(attribute_manager_t *this,
- char *pool, identification_t *id,
+ linked_list_t *pool, identification_t *id,
host_t *requested);
/**
* Release a previously acquired address.
*
- * @param pool pool name from which the address was acquired
+ * @param pools list of pool names (char*) to release to
* @param address address to release
* @param id peer identity to get address for
+ * @return TRUE if address released to pool
*/
- void (*release_address)(attribute_manager_t *this,
- char *pool, host_t *address, identification_t *id);
+ bool (*release_address)(attribute_manager_t *this,
+ linked_list_t *pools, host_t *address,
+ identification_t *id);
/**
* Create an enumerator over attributes to hand out to a peer.
*
- * @param pool pool name to get attributes from
+ * @param pool list of pools names (char*) to query attributes from
* @param id peer identity to hand out attributes to
- * @param vip virtual IP to assign to peer, if any
+ * @param vip list of virtual IPs (host_t*) to assign to peer
* @return enumerator (configuration_attribute_type_t, chunk_t)
*/
enumerator_t* (*create_responder_enumerator)(attribute_manager_t *this,
- char *pool, identification_t *id, host_t *vip);
+ linked_list_t *pool, identification_t *id,
+ linked_list_t *vips);
/**
* Register an attribute provider to the manager.
@@ -114,11 +117,11 @@ struct attribute_manager_t {
* Create an enumerator over attributes to request from server.
*
* @param id server identity to hand out attributes to
- * @param vip virtual IP going to request, if any
+ * @param vip list of virtual IPs (host_t*) going to request
* @return enumerator (attribute_handler_t, ca_type_t, chunk_t)
*/
enumerator_t* (*create_initiator_enumerator)(attribute_manager_t *this,
- identification_t *id, host_t *vip);
+ identification_t *id, linked_list_t *vips);
/**
* Register an attribute handler to the manager.
diff --git a/src/libhydra/attributes/attribute_provider.h b/src/libhydra/attributes/attribute_provider.h
index e4b4e13f3..e5e556fc4 100644
--- a/src/libhydra/attributes/attribute_provider.h
+++ b/src/libhydra/attributes/attribute_provider.h
@@ -23,6 +23,7 @@
#include <utils/host.h>
#include <utils/identification.h>
+#include <utils/linked_list.h>
typedef struct attribute_provider_t attribute_provider_t;
@@ -34,35 +35,37 @@ struct attribute_provider_t {
/**
* Acquire a virtual IP address to assign to a peer.
*
- * @param pool name of the pool to acquire address from
+ * @param pools list of pool names (char*) to acquire from
* @param id peer ID
* @param requested IP in configuration request
* @return allocated address, NULL to serve none
*/
host_t* (*acquire_address)(attribute_provider_t *this,
- char *pool, identification_t *id,
+ linked_list_t *pools, identification_t *id,
host_t *requested);
/**
* Release a previously acquired address.
*
- * @param pool name of the pool this address was acquired from
+ * @param pools list of pool names (char*) to release to
* @param address address to release
* @param id peer ID
* @return TRUE if the address has been released by the provider
*/
bool (*release_address)(attribute_provider_t *this,
- char *pool, host_t *address, identification_t *id);
+ linked_list_t *pools, host_t *address,
+ identification_t *id);
/**
* Create an enumerator over attributes to hand out to a peer.
*
- * @param pool pool name to get attributes from
+ * @param pool list of pools names (char*) to query attributes from
* @param id peer ID
- * @param vip virtual IP to assign to peer, if any
+ * @param vip list of virtual IPs (host_t*) to assign to peer
* @return enumerator (configuration_attribute_type_t, chunk_t)
*/
enumerator_t* (*create_attribute_enumerator)(attribute_provider_t *this,
- char *pool, identification_t *id, host_t *vip);
+ linked_list_t *pools, identification_t *id,
+ linked_list_t *vips);
};
#endif /** ATTRIBUTE_PROVIDER_H_ @}*/
diff --git a/src/libhydra/attributes/mem_pool.c b/src/libhydra/attributes/mem_pool.c
index 8af97dc78..1e150c794 100644
--- a/src/libhydra/attributes/mem_pool.c
+++ b/src/libhydra/attributes/mem_pool.c
@@ -162,6 +162,12 @@ METHOD(mem_pool_t, get_name, const char*,
return this->name;
}
+METHOD(mem_pool_t, get_base, host_t*,
+ private_mem_pool_t *this)
+{
+ return this->base;
+}
+
METHOD(mem_pool_t, get_size, u_int,
private_mem_pool_t *this)
{
@@ -206,66 +212,68 @@ METHOD(mem_pool_t, get_offline, u_int,
return count;
}
-METHOD(mem_pool_t, acquire_address, host_t*,
- private_mem_pool_t *this, identification_t *id, host_t *requested)
+/**
+ * Get an existing lease for id
+ */
+static int get_existing(private_mem_pool_t *this, identification_t *id,
+ host_t *requested)
{
- uintptr_t offset = 0, current;
enumerator_t *enumerator;
- entry_t *entry, *old;
+ uintptr_t current;
+ entry_t *entry;
+ int offset = 0;
- /* if the pool is empty (e.g. in the %config case) we simply return the
- * requested address */
- if (this->size == 0)
+ entry = this->leases->get(this->leases, id);
+ if (!entry)
{
- return requested->clone(requested);
+ return 0;
}
- if (!requested->is_anyaddr(requested) &&
- requested->get_family(requested) !=
- this->base->get_family(this->base))
+ /* check for a valid offline lease, refresh */
+ enumerator = entry->offline->create_enumerator(entry->offline);
+ if (enumerator->enumerate(enumerator, &current))
{
- DBG1(DBG_CFG, "IP pool address family mismatch");
- return NULL;
+ entry->offline->remove_at(entry->offline, enumerator);
+ entry->online->insert_last(entry->online, (void*)current);
+ offset = current;
+ }
+ enumerator->destroy(enumerator);
+ if (offset)
+ {
+ DBG1(DBG_CFG, "reassigning offline lease to '%Y'", id);
+ return offset;
}
- this->mutex->lock(this->mutex);
- while (TRUE)
+ /* check for a valid online lease to reassign */
+ enumerator = entry->online->create_enumerator(entry->online);
+ while (enumerator->enumerate(enumerator, &current))
{
- entry = this->leases->get(this->leases, id);
- if (entry)
+ if (current == host2offset(this, requested))
{
- /* check for a valid offline lease, refresh */
- enumerator = entry->offline->create_enumerator(entry->offline);
- if (enumerator->enumerate(enumerator, &current))
- {
- entry->offline->remove_at(entry->offline, enumerator);
- entry->online->insert_last(entry->online, (void*)current);
- offset = current;
- }
- enumerator->destroy(enumerator);
- if (offset)
- {
- DBG1(DBG_CFG, "reassigning offline lease to '%Y'", id);
- break;
- }
- /* check for a valid online lease to reassign */
- enumerator = entry->online->create_enumerator(entry->online);
- while (enumerator->enumerate(enumerator, &current))
- {
- if (current == host2offset(this, requested))
- {
- offset = current;
- break;
- }
- }
- enumerator->destroy(enumerator);
- if (offset)
- {
- DBG1(DBG_CFG, "reassigning online lease to '%Y'", id);
- break;
- }
+ offset = current;
+ break;
}
- else
+ }
+ enumerator->destroy(enumerator);
+ if (offset)
+ {
+ DBG1(DBG_CFG, "reassigning online lease to '%Y'", id);
+ }
+ return offset;
+}
+
+/**
+ * Get a new lease for id
+ */
+static int get_new(private_mem_pool_t *this, identification_t *id)
+{
+ entry_t *entry;
+ uintptr_t offset = 0;
+
+ if (this->unused < this->size)
+ {
+ entry = this->leases->get(this->leases, id);
+ if (!entry)
{
INIT(entry,
.id = id->clone(id),
@@ -274,31 +282,88 @@ METHOD(mem_pool_t, acquire_address, host_t*,
);
this->leases->put(this->leases, entry->id, entry);
}
- if (this->unused < this->size)
+ /* assigning offset, starting by 1 */
+ offset = ++this->unused;
+ entry->online->insert_last(entry->online, (void*)offset);
+ DBG1(DBG_CFG, "assigning new lease to '%Y'", id);
+ }
+ return offset;
+}
+
+/**
+ * Get a reassigned lease for id in case the pool is full
+ */
+static int get_reassigned(private_mem_pool_t *this, identification_t *id)
+{
+ enumerator_t *enumerator;
+ entry_t *entry;
+ uintptr_t current, offset = 0;
+
+ enumerator = this->leases->create_enumerator(this->leases);
+ while (enumerator->enumerate(enumerator, NULL, &entry))
+ {
+ if (entry->offline->remove_first(entry->offline,
+ (void**)&current) == SUCCESS)
{
- /* assigning offset, starting by 1 */
- offset = ++this->unused;
- entry->online->insert_last(entry->online, (void*)offset);
- DBG1(DBG_CFG, "assigning new lease to '%Y'", id);
+ offset = current;
+ DBG1(DBG_CFG, "reassigning existing offline lease by '%Y'"
+ " to '%Y'", entry->id, id);
break;
}
+ }
+ enumerator->destroy(enumerator);
- /* no more addresses, replace the first found offline lease */
- enumerator = this->leases->create_enumerator(this->leases);
- while (enumerator->enumerate(enumerator, NULL, &old))
- {
- if (old->offline->remove_first(old->offline,
- (void**)&current) == SUCCESS)
+ if (offset)
+ {
+ INIT(entry,
+ .id = id->clone(id),
+ .online = linked_list_create(),
+ .offline = linked_list_create(),
+ );
+ entry->online->insert_last(entry->online, (void*)offset);
+ this->leases->put(this->leases, entry->id, entry);
+ }
+ return offset;
+}
+
+METHOD(mem_pool_t, acquire_address, host_t*,
+ private_mem_pool_t *this, identification_t *id, host_t *requested,
+ mem_pool_op_t operation)
+{
+ int offset = 0;
+
+ /* if the pool is empty (e.g. in the %config case) we simply return the
+ * requested address */
+ if (this->size == 0)
+ {
+ return requested->clone(requested);
+ }
+
+ if (requested->get_family(requested) !=
+ this->base->get_family(this->base))
+ {
+ return NULL;
+ }
+
+ this->mutex->lock(this->mutex);
+ switch (operation)
+ {
+ case MEM_POOL_EXISTING:
+ offset = get_existing(this, id, requested);
+ break;
+ case MEM_POOL_NEW:
+ offset = get_new(this, id);
+ break;
+ case MEM_POOL_REASSIGN:
+ offset = get_reassigned(this, id);
+ if (!offset)
{
- offset = current;
- entry->online->insert_last(entry->online, (void*)offset);
- DBG1(DBG_CFG, "reassigning existing offline lease by '%Y'"
- " to '%Y'", old->id, id);
- break;
+ DBG1(DBG_CFG, "pool '%s' is full, unable to assign address",
+ this->name);
}
- }
- enumerator->destroy(enumerator);
- break;
+ break;
+ default:
+ break;
}
this->mutex->unlock(this->mutex);
@@ -306,11 +371,6 @@ METHOD(mem_pool_t, acquire_address, host_t*,
{
return offset2host(this, offset);
}
- else
- {
- DBG1(DBG_CFG, "pool '%s' is full, unable to assign address",
- this->name);
- }
return NULL;
}
@@ -463,6 +523,7 @@ mem_pool_t *mem_pool_create(char *name, host_t *base, int bits)
INIT(this,
.public = {
.get_name = _get_name,
+ .get_base = _get_base,
.get_size = _get_size,
.get_online = _get_online,
.get_offline = _get_offline,
@@ -480,6 +541,7 @@ mem_pool_t *mem_pool_create(char *name, host_t *base, int bits)
if (base)
{
addr_bits = base->get_family(base) == AF_INET ? 32 : 128;
+ bits = max(0, min(bits, base->get_family(base) == AF_INET ? 32 : 128));
/* net bits -> host bits */
bits = addr_bits - bits;
if (bits > POOL_LIMIT)
@@ -493,7 +555,7 @@ mem_pool_t *mem_pool_create(char *name, host_t *base, int bits)
if (this->size > 2)
{ /* do not use first and last addresses of a block */
this->unused++;
- this->size--;
+ this->size -= 2;
}
this->base = base->clone(base);
}
diff --git a/src/libhydra/attributes/mem_pool.h b/src/libhydra/attributes/mem_pool.h
index bb963de93..fa4e6485c 100644
--- a/src/libhydra/attributes/mem_pool.h
+++ b/src/libhydra/attributes/mem_pool.h
@@ -22,11 +22,24 @@
#define MEM_POOL_H
typedef struct mem_pool_t mem_pool_t;
+typedef enum mem_pool_op_t mem_pool_op_t;
#include <utils/host.h>
#include <utils/identification.h>
/**
+ * In-memory IP pool acquire operation.
+ */
+enum mem_pool_op_t {
+ /** Check for an exsiting lease */
+ MEM_POOL_EXISTING,
+ /** Get a new lease */
+ MEM_POOL_NEW,
+ /** Replace an existing offline lease of another ID */
+ MEM_POOL_REASSIGN,
+};
+
+/**
* An in-memory IP address pool.
*/
struct mem_pool_t {
@@ -39,6 +52,13 @@ struct mem_pool_t {
const char* (*get_name)(mem_pool_t *this);
/**
+ * Get the base (first) address of this pool.
+ *
+ * @return base address, internal host
+ */
+ host_t* (*get_base)(mem_pool_t *this);
+
+ /**
* Get the size (i.e. number of addresses) of this pool.
*
* @return the size of this pool
@@ -62,12 +82,18 @@ struct mem_pool_t {
/**
* Acquire an address for the given id from this pool.
*
+ * This call is usually invoked several times: The first time to find an
+ * existing lease (MEM_POOL_EXISTING), if none found a second time to
+ * acquire a new lease (MEM_POOL_NEW), and if the pool is full once again
+ * to assign an existing offline lease (MEM_POOL_REASSIGN).
+ *
* @param id the id to acquire an address for
* @param requested acquire this address, if possible
+ * @param existing TRUE to look for an existing lease, FALSE for a new one
* @return the acquired address
*/
host_t* (*acquire_address)(mem_pool_t *this, identification_t *id,
- host_t *requested);
+ host_t *requested, mem_pool_op_t operation);
/**
* Release a previously acquired address.
diff --git a/src/libhydra/hydra.c b/src/libhydra/hydra.c
index f180e36bb..7d6256598 100644
--- a/src/libhydra/hydra.c
+++ b/src/libhydra/hydra.c
@@ -58,12 +58,13 @@ bool libhydra_init(const char *daemon)
INIT(this,
.public = {
.attributes = attribute_manager_create(),
- .kernel_interface = kernel_interface_create(),
.daemon = strdup(daemon ?: "libhydra"),
},
);
hydra = &this->public;
+ this->public.kernel_interface = kernel_interface_create();
+
if (lib->integrity &&
!lib->integrity->check(lib->integrity, "libhydra", libhydra_init))
{
diff --git a/src/libhydra/kernel/kernel_interface.c b/src/libhydra/kernel/kernel_interface.c
index 573557506..5320ee2e9 100644
--- a/src/libhydra/kernel/kernel_interface.c
+++ b/src/libhydra/kernel/kernel_interface.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2011 Tobias Brunner
+ * Copyright (C) 2008-2012 Tobias Brunner
* Hochschule fuer Technik Rapperswil
* Copyright (C) 2010 Martin Willi
* Copyright (C) 2010 revosec AG
@@ -15,14 +15,65 @@
* for more details.
*/
+/*
+ * Copyright (c) 2012 Nanoteq Pty Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
#include "kernel_interface.h"
+#include <hydra.h>
#include <debug.h>
#include <threading/mutex.h>
#include <utils/linked_list.h>
typedef struct private_kernel_interface_t private_kernel_interface_t;
+typedef struct kernel_algorithm_t kernel_algorithm_t;
+
+/**
+ * Mapping of IKE algorithms to kernel-specific algorithm identifiers
+ */
+struct kernel_algorithm_t {
+
+ /**
+ * Transform type of the algorithm
+ */
+ transform_type_t type;
+
+ /**
+ * Identifier specified in IKE
+ */
+ u_int16_t ike;
+
+ /**
+ * Identifier as defined in pfkeyv2.h
+ */
+ u_int16_t kernel;
+
+ /**
+ * Name of the algorithm in linux crypto API
+ */
+ char *name;
+};
+
/**
* Private data of a kernel_interface_t object.
*/
@@ -62,6 +113,28 @@ struct private_kernel_interface_t {
* list of registered listeners
*/
linked_list_t *listeners;
+
+ /**
+ * mutex for algorithm mappings
+ */
+ mutex_t *mutex_algs;
+
+ /**
+ * List of algorithm mappings (kernel_algorithm_t*)
+ */
+ linked_list_t *algorithms;
+
+ /**
+ * List of interface names to include or exclude (char*), NULL if interfaces
+ * are not filtered
+ */
+ linked_list_t *ifaces_filter;
+
+ /**
+ * TRUE to exclude interfaces listed in ifaces_filter, FALSE to consider
+ * only those listed there
+ */
+ bool ifaces_exclude;
};
METHOD(kernel_interface_t, get_spi, status_t,
@@ -209,35 +282,33 @@ METHOD(kernel_interface_t, get_source_addr, host_t*,
}
METHOD(kernel_interface_t, get_nexthop, host_t*,
- private_kernel_interface_t *this, host_t *dest)
+ private_kernel_interface_t *this, host_t *dest, host_t *src)
{
if (!this->net)
{
return NULL;
}
- return this->net->get_nexthop(this->net, dest);
+ return this->net->get_nexthop(this->net, dest, src);
}
-METHOD(kernel_interface_t, get_interface, char*,
- private_kernel_interface_t *this, host_t *host)
+METHOD(kernel_interface_t, get_interface, bool,
+ private_kernel_interface_t *this, host_t *host, char **name)
{
if (!this->net)
{
return NULL;
}
- return this->net->get_interface(this->net, host);
+ return this->net->get_interface(this->net, host, name);
}
METHOD(kernel_interface_t, create_address_enumerator, enumerator_t*,
- private_kernel_interface_t *this, bool include_down_ifaces,
- bool include_virtual_ips)
+ private_kernel_interface_t *this, kernel_address_type_t which)
{
if (!this->net)
{
return enumerator_create_empty();
}
- return this->net->create_address_enumerator(this->net, include_down_ifaces,
- include_virtual_ips);
+ return this->net->create_address_enumerator(this->net, which);
}
METHOD(kernel_interface_t, add_ip, status_t,
@@ -294,6 +365,36 @@ METHOD(kernel_interface_t, bypass_socket, bool,
return this->ipsec->bypass_socket(this->ipsec, fd, family);
}
+METHOD(kernel_interface_t, enable_udp_decap, bool,
+ private_kernel_interface_t *this, int fd, int family, u_int16_t port)
+{
+ if (!this->ipsec)
+ {
+ return FALSE;
+ }
+ return this->ipsec->enable_udp_decap(this->ipsec, fd, family, port);
+}
+
+METHOD(kernel_interface_t, is_interface_usable, bool,
+ private_kernel_interface_t *this, const char *iface)
+{
+ status_t expected;
+
+ if (!this->ifaces_filter)
+ {
+ return TRUE;
+ }
+ expected = this->ifaces_exclude ? NOT_FOUND : SUCCESS;
+ return this->ifaces_filter->find_first(this->ifaces_filter, (void*)streq,
+ NULL, iface) == expected;
+}
+
+METHOD(kernel_interface_t, all_interfaces_usable, bool,
+ private_kernel_interface_t *this)
+{
+ return this->ifaces_filter == NULL;
+}
+
METHOD(kernel_interface_t, get_address_by_ts, status_t,
private_kernel_interface_t *this, traffic_selector_t *ts, host_t **ip)
{
@@ -326,7 +427,7 @@ METHOD(kernel_interface_t, get_address_by_ts, status_t,
}
host->destroy(host);
- addrs = create_address_enumerator(this, TRUE, TRUE);
+ addrs = create_address_enumerator(this, ADDR_TYPE_ALL);
while (addrs->enumerate(addrs, (void**)&host))
{
if (ts->includes(ts, host))
@@ -362,7 +463,7 @@ METHOD(kernel_interface_t, add_ipsec_interface, void,
METHOD(kernel_interface_t, remove_ipsec_interface, void,
private_kernel_interface_t *this, kernel_ipsec_constructor_t constructor)
{
- if (constructor == this->ipsec_constructor)
+ if (constructor == this->ipsec_constructor && this->ipsec)
{
this->ipsec->destroy(this->ipsec);
this->ipsec = NULL;
@@ -382,7 +483,7 @@ METHOD(kernel_interface_t, add_net_interface, void,
METHOD(kernel_interface_t, remove_net_interface, void,
private_kernel_interface_t *this, kernel_net_constructor_t constructor)
{
- if (constructor == this->net_constructor)
+ if (constructor == this->net_constructor && this->net)
{
this->net->destroy(this->net);
this->net = NULL;
@@ -500,13 +601,73 @@ METHOD(kernel_interface_t, roam, void,
this->mutex->unlock(this->mutex);
}
+METHOD(kernel_interface_t, register_algorithm, void,
+ private_kernel_interface_t *this, u_int16_t alg_id, transform_type_t type,
+ u_int16_t kernel_id, char *kernel_name)
+{
+ kernel_algorithm_t *algorithm;
+
+ INIT(algorithm,
+ .type = type,
+ .ike = alg_id,
+ .kernel = kernel_id,
+ .name = strdup(kernel_name),
+ );
+
+ this->mutex_algs->lock(this->mutex_algs);
+ this->algorithms->insert_first(this->algorithms, algorithm);
+ this->mutex_algs->unlock(this->mutex_algs);
+}
+
+METHOD(kernel_interface_t, lookup_algorithm, bool,
+ private_kernel_interface_t *this, u_int16_t alg_id, transform_type_t type,
+ u_int16_t *kernel_id, char **kernel_name)
+{
+ kernel_algorithm_t *algorithm;
+ enumerator_t *enumerator;
+ bool found = FALSE;
+
+ this->mutex_algs->lock(this->mutex_algs);
+ enumerator = this->algorithms->create_enumerator(this->algorithms);
+ while (enumerator->enumerate(enumerator, &algorithm))
+ {
+ if (algorithm->type == type && algorithm->ike == alg_id)
+ {
+ if (kernel_id)
+ {
+ *kernel_id = algorithm->kernel;
+ }
+ if (kernel_name)
+ {
+ *kernel_name = algorithm->name;
+ }
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex_algs->unlock(this->mutex_algs);
+ return found;
+}
+
METHOD(kernel_interface_t, destroy, void,
private_kernel_interface_t *this)
{
+ kernel_algorithm_t *algorithm;
+
+ while (this->algorithms->remove_first(this->algorithms,
+ (void**)&algorithm) == SUCCESS)
+ {
+ free(algorithm->name);
+ free(algorithm);
+ }
+ this->algorithms->destroy(this->algorithms);
+ this->mutex_algs->destroy(this->mutex_algs);
DESTROY_IF(this->ipsec);
DESTROY_IF(this->net);
- this->mutex->destroy(this->mutex);
+ DESTROY_FUNCTION_IF(this->ifaces_filter, (void*)free);
this->listeners->destroy(this->listeners);
+ this->mutex->destroy(this->mutex);
free(this);
}
@@ -516,6 +677,7 @@ METHOD(kernel_interface_t, destroy, void,
kernel_interface_t *kernel_interface_create()
{
private_kernel_interface_t *this;
+ char *ifaces;
INIT(this,
.public = {
@@ -539,7 +701,10 @@ kernel_interface_t *kernel_interface_create()
.add_route = _add_route,
.del_route = _del_route,
.bypass_socket = _bypass_socket,
+ .enable_udp_decap = _enable_udp_decap,
+ .is_interface_usable = _is_interface_usable,
+ .all_interfaces_usable = _all_interfaces_usable,
.get_address_by_ts = _get_address_by_ts,
.add_ipsec_interface = _add_ipsec_interface,
.remove_ipsec_interface = _remove_ipsec_interface,
@@ -548,6 +713,8 @@ kernel_interface_t *kernel_interface_create()
.add_listener = _add_listener,
.remove_listener = _remove_listener,
+ .register_algorithm = _register_algorithm,
+ .lookup_algorithm = _lookup_algorithm,
.acquire = _acquire,
.expire = _expire,
.mapping = _mapping,
@@ -557,8 +724,36 @@ kernel_interface_t *kernel_interface_create()
},
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
.listeners = linked_list_create(),
+ .mutex_algs = mutex_create(MUTEX_TYPE_DEFAULT),
+ .algorithms = linked_list_create(),
);
+ ifaces = lib->settings->get_str(lib->settings,
+ "%s.interfaces_use", NULL, hydra->daemon);
+ if (!ifaces)
+ {
+ this->ifaces_exclude = TRUE;
+ ifaces = lib->settings->get_str(lib->settings,
+ "%s.interfaces_ignore", NULL, hydra->daemon);
+ }
+ if (ifaces)
+ {
+ enumerator_t *enumerator;
+ char *iface;
+
+ enumerator = enumerator_create_token(ifaces, ",", " ");
+ while (enumerator->enumerate(enumerator, &iface))
+ {
+ if (!this->ifaces_filter)
+ {
+ this->ifaces_filter = linked_list_create();
+ }
+ this->ifaces_filter->insert_last(this->ifaces_filter,
+ strdup(iface));
+ }
+ enumerator->destroy(enumerator);
+ }
+
return &this->public;
}
diff --git a/src/libhydra/kernel/kernel_interface.h b/src/libhydra/kernel/kernel_interface.h
index 991cfafd0..88d4a5bce 100644
--- a/src/libhydra/kernel/kernel_interface.h
+++ b/src/libhydra/kernel/kernel_interface.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2011 Tobias Brunner
+ * Copyright (C) 2006-2012 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -16,6 +16,28 @@
* for more details.
*/
+/*
+ * Copyright (c) 2012 Nanoteq Pty Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
/**
* @defgroup kernel_interface kernel_interface
* @{ @ingroup hkernel
@@ -260,7 +282,7 @@ struct kernel_interface_t {
* Does a route lookup to get the source address used to reach dest.
* The returned host is allocated and must be destroyed.
* An optional src address can be used to check if a route is available
- * for given source to dest.
+ * for the given source to dest.
*
* @param dest target destination address
* @param src source address to check, or NULL
@@ -274,19 +296,23 @@ struct kernel_interface_t {
*
* Does a route lookup to get the next hop used to reach dest.
* The returned host is allocated and must be destroyed.
+ * An optional src address can be used to check if a route is available
+ * for the given source to dest.
*
* @param dest target destination address
* @return next hop address, NULL if unreachable
*/
- host_t* (*get_nexthop)(kernel_interface_t *this, host_t *dest);
+ host_t* (*get_nexthop)(kernel_interface_t *this, host_t *dest, host_t *src);
/**
- * Get the interface name of a local address.
+ * Get the interface name of a local address. Interfaces that are down or
+ * ignored by config are not considered.
*
* @param host address to get interface name from
- * @return allocated interface name, or NULL if not found
+ * @param name allocated interface name (optional)
+ * @return TRUE if interface found and usable
*/
- char* (*get_interface) (kernel_interface_t *this, host_t *host);
+ bool (*get_interface)(kernel_interface_t *this, host_t *host, char **name);
/**
* Creates an enumerator over all local addresses.
@@ -295,12 +321,11 @@ struct kernel_interface_t {
* enumerator gets destroyed.
* The hosts are read-only, do not modify of free.
*
- * @param include_down_ifaces TRUE to enumerate addresses from down interfaces
- * @param include_virtual_ips TRUE to enumerate virtual ip addresses
- * @return enumerator over host_t's
+ * @param which a combination of address types to enumerate
+ * @return enumerator over host_t's
*/
enumerator_t *(*create_address_enumerator) (kernel_interface_t *this,
- bool include_down_ifaces, bool include_virtual_ips);
+ kernel_address_type_t which);
/**
* Add a virtual IP to an interface.
@@ -361,20 +386,48 @@ struct kernel_interface_t {
*
* @param fd socket file descriptor to setup policy for
* @param family protocol family of the socket
- * @return TRUE of policy set up successfully
+ * @return TRUE if policy set up successfully
*/
bool (*bypass_socket)(kernel_interface_t *this, int fd, int family);
/**
+ * Enable decapsulation of ESP-in-UDP packets for the given port/socket.
+ *
+ * @param fd socket file descriptor
+ * @param family protocol family of the socket
+ * @param port the UDP port
+ * @return TRUE if UDP decapsulation was enabled successfully
+ */
+ bool (*enable_udp_decap)(kernel_interface_t *this, int fd, int family,
+ u_int16_t port);
+
+
+ /**
* manager methods
*/
/**
- * Tries to find an ip address of a local interface that is included in the
+ * Verifies that the given interface is usable and not excluded by
+ * configuration.
+ *
+ * @param iface interface name
+ * @return TRUE if usable
+ */
+ bool (*is_interface_usable)(kernel_interface_t *this, const char *iface);
+
+ /**
+ * Check if interfaces are excluded by config.
+ *
+ * @return TRUE if no interfaces are exclued by config
+ */
+ bool (*all_interfaces_usable)(kernel_interface_t *this);
+
+ /**
+ * Tries to find an IP address of a local interface that is included in the
* supplied traffic selector.
*
* @param ts traffic selector
- * @param ip returned ip (has to be destroyed)
+ * @param ip returned IP address (has to be destroyed)
* @return SUCCESS if address found
*/
status_t (*get_address_by_ts)(kernel_interface_t *this,
@@ -481,6 +534,32 @@ struct kernel_interface_t {
void (*roam)(kernel_interface_t *this, bool address);
/**
+ * Register a new algorithm with the kernel interface.
+ *
+ * @param alg_id the IKE id of the algorithm
+ * @param type the transform type of the algorithm
+ * @param kernel_id the kernel id of the algorithm
+ * @param kernel_name the kernel name of the algorithm
+ */
+ void (*register_algorithm)(kernel_interface_t *this, u_int16_t alg_id,
+ transform_type_t type, u_int16_t kernel_id,
+ char *kernel_name);
+
+ /**
+ * Return the kernel-specific id and/or name for an algorithms depending on
+ * the arguments specified.
+ *
+ * @param alg_id the IKE id of the algorithm
+ * @param type the transform type of the algorithm
+ * @param kernel_id the kernel id of the algorithm (optional)
+ * @param kernel_name the kernel name of the algorithm (optional)
+ * @return TRUE if algorithm was found
+ */
+ bool (*lookup_algorithm)(kernel_interface_t *this, u_int16_t alg_id,
+ transform_type_t type, u_int16_t *kernel_id,
+ char **kernel_name);
+
+ /**
* Destroys a kernel_interface_manager_t object.
*/
void (*destroy) (kernel_interface_t *this);
diff --git a/src/libhydra/kernel/kernel_ipsec.c b/src/libhydra/kernel/kernel_ipsec.c
index 9b38297cc..1a32ab4e7 100644
--- a/src/libhydra/kernel/kernel_ipsec.c
+++ b/src/libhydra/kernel/kernel_ipsec.c
@@ -17,28 +17,6 @@
#include <hydra.h>
-ENUM(ipsec_mode_names, MODE_TRANSPORT, MODE_DROP,
- "TRANSPORT",
- "TUNNEL",
- "BEET",
- "PASS",
- "DROP"
-);
-
-ENUM(policy_dir_names, POLICY_IN, POLICY_FWD,
- "in",
- "out",
- "fwd"
-);
-
-ENUM(ipcomp_transform_names, IPCOMP_NONE, IPCOMP_LZJH,
- "IPCOMP_NONE",
- "IPCOMP_OUI",
- "IPCOMP_DEFLATE",
- "IPCOMP_LZS",
- "IPCOMP_LZJH"
-);
-
/**
* See header
*/
diff --git a/src/libhydra/kernel/kernel_ipsec.h b/src/libhydra/kernel/kernel_ipsec.h
index ddb63283c..ee0ade2aa 100644
--- a/src/libhydra/kernel/kernel_ipsec.h
+++ b/src/libhydra/kernel/kernel_ipsec.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2011 Tobias Brunner
+ * Copyright (C) 2006-2012 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -24,152 +24,14 @@
#ifndef KERNEL_IPSEC_H_
#define KERNEL_IPSEC_H_
-typedef enum ipsec_mode_t ipsec_mode_t;
-typedef enum policy_dir_t policy_dir_t;
-typedef enum policy_type_t policy_type_t;
-typedef enum policy_priority_t policy_priority_t;
-typedef enum ipcomp_transform_t ipcomp_transform_t;
typedef struct kernel_ipsec_t kernel_ipsec_t;
-typedef struct ipsec_sa_cfg_t ipsec_sa_cfg_t;
-typedef struct lifetime_cfg_t lifetime_cfg_t;
-typedef struct mark_t mark_t;
#include <utils/host.h>
-#include <crypto/prf_plus.h>
+#include <ipsec/ipsec_types.h>
#include <selectors/traffic_selector.h>
#include <plugins/plugin.h>
/**
- * Mode of an IPsec SA.
- */
-enum ipsec_mode_t {
- /** transport mode, no inner address */
- MODE_TRANSPORT = 1,
- /** tunnel mode, inner and outer addresses */
- MODE_TUNNEL,
- /** BEET mode, tunnel mode but fixed, bound inner addresses */
- MODE_BEET,
- /** passthrough policy for traffic without an IPsec SA */
- MODE_PASS,
- /** drop policy discarding traffic */
- MODE_DROP
-};
-
-/**
- * enum names for ipsec_mode_t.
- */
-extern enum_name_t *ipsec_mode_names;
-
-/**
- * Direction of a policy. These are equal to those
- * defined in xfrm.h, but we want to stay implementation
- * neutral here.
- */
-enum policy_dir_t {
- /** Policy for inbound traffic */
- POLICY_IN = 0,
- /** Policy for outbound traffic */
- POLICY_OUT = 1,
- /** Policy for forwarded traffic */
- POLICY_FWD = 2,
-};
-
-/**
- * enum names for policy_dir_t.
- */
-extern enum_name_t *policy_dir_names;
-
-/**
- * Type of a policy.
- */
-enum policy_type_t {
- /** Normal IPsec policy */
- POLICY_IPSEC = 1,
- /** Passthrough policy (traffic is ignored by IPsec) */
- POLICY_PASS,
- /** Drop policy (traffic is discarded) */
- POLICY_DROP,
-};
-
-/**
- * High-level priority of a policy.
- */
-enum policy_priority_t {
- /** Default priority */
- POLICY_PRIORITY_DEFAULT,
- /** Priority for trap policies */
- POLICY_PRIORITY_ROUTED,
- /** Priority for fallback drop policies */
- POLICY_PRIORITY_FALLBACK,
-};
-
-/**
- * IPComp transform IDs, as in RFC 4306
- */
-enum ipcomp_transform_t {
- IPCOMP_NONE = 0,
- IPCOMP_OUI = 1,
- IPCOMP_DEFLATE = 2,
- IPCOMP_LZS = 3,
- IPCOMP_LZJH = 4,
-};
-
-/**
- * enum strings for ipcomp_transform_t.
- */
-extern enum_name_t *ipcomp_transform_names;
-
-/**
- * This struct contains details about IPsec SA(s) tied to a policy.
- */
-struct ipsec_sa_cfg_t {
- /** mode of SA (tunnel, transport) */
- ipsec_mode_t mode;
- /** unique ID */
- u_int32_t reqid;
- /** details about ESP/AH */
- struct {
- /** TRUE if this protocol is used */
- bool use;
- /** SPI for ESP/AH */
- u_int32_t spi;
- } esp, ah;
- /** details about IPComp */
- struct {
- /** the IPComp transform used */
- u_int16_t transform;
- /** CPI for IPComp */
- u_int16_t cpi;
- } ipcomp;
-};
-
-/**
- * A lifetime_cfg_t defines the lifetime limits of an SA.
- *
- * Set any of these values to 0 to ignore.
- */
-struct lifetime_cfg_t {
- struct {
- /** Limit before the SA gets invalid. */
- u_int64_t life;
- /** Limit before the SA gets rekeyed. */
- u_int64_t rekey;
- /** The range of a random value subtracted from rekey. */
- u_int64_t jitter;
- } time, bytes, packets;
-};
-
-/**
- * A mark_t defines an optional mark in an IPsec SA.
- */
-struct mark_t {
- /** Mark value */
- u_int32_t value;
- /** Mark mask */
- u_int32_t mask;
-};
-
-/**
* Interface to the ipsec subsystem of the kernel.
*
* The kernel ipsec interface handles the communication with the kernel
@@ -396,6 +258,17 @@ struct kernel_ipsec_t {
bool (*bypass_socket)(kernel_ipsec_t *this, int fd, int family);
/**
+ * Enable decapsulation of ESP-in-UDP packets for the given port/socket.
+ *
+ * @param fd socket file descriptor
+ * @param family protocol family of the socket
+ * @param port the UDP port
+ * @return TRUE if UDP decapsulation was enabled successfully
+ */
+ bool (*enable_udp_decap)(kernel_ipsec_t *this, int fd, int family,
+ u_int16_t port);
+
+ /**
* Destroy the implementation.
*/
void (*destroy) (kernel_ipsec_t *this);
diff --git a/src/libhydra/kernel/kernel_net.h b/src/libhydra/kernel/kernel_net.h
index a89e76804..10350d644 100644
--- a/src/libhydra/kernel/kernel_net.h
+++ b/src/libhydra/kernel/kernel_net.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2008-2012 Tobias Brunner
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -23,12 +23,31 @@
#define KERNEL_NET_H_
typedef struct kernel_net_t kernel_net_t;
+typedef enum kernel_address_type_t kernel_address_type_t;
#include <utils/enumerator.h>
#include <utils/host.h>
#include <plugins/plugin.h>
/**
+ * Type of addresses (e.g. when enumerating them)
+ */
+enum kernel_address_type_t {
+ /** normal addresses (on regular, up, non-ignored) interfaces */
+ ADDR_TYPE_REGULAR = 0,
+ /** addresses on down interfaces */
+ ADDR_TYPE_DOWN = (1 << 0),
+ /** addresses on ignored interfaces */
+ ADDR_TYPE_IGNORED = (1 << 1),
+ /** addresses on loopback interfaces */
+ ADDR_TYPE_LOOPBACK = (1 << 2),
+ /** virtual IP addresses */
+ ADDR_TYPE_VIRTUAL = (1 << 3),
+ /** to enumerate all available addresses */
+ ADDR_TYPE_ALL = (1 << 4) - 1,
+};
+
+/**
* Interface to the network subsystem of the kernel.
*
* The kernel network interface handles the communication with the kernel
@@ -42,7 +61,7 @@ struct kernel_net_t {
* Does a route lookup to get the source address used to reach dest.
* The returned host is allocated and must be destroyed.
* An optional src address can be used to check if a route is available
- * for given source to dest.
+ * for the given source to dest.
*
* @param dest target destination address
* @param src source address to check, or NULL
@@ -55,19 +74,24 @@ struct kernel_net_t {
*
* Does a route lookup to get the next hop used to reach dest.
* The returned host is allocated and must be destroyed.
+ * An optional src address can be used to check if a route is available
+ * for the given source to dest.
*
* @param dest target destination address
+ * @param src source address to check, or NULL
* @return next hop address, NULL if unreachable
*/
- host_t* (*get_nexthop)(kernel_net_t *this, host_t *dest);
+ host_t* (*get_nexthop)(kernel_net_t *this, host_t *dest, host_t *src);
/**
- * Get the interface name of a local address.
+ * Get the interface name of a local address. Interfaces that are down or
+ * ignored by config are not considered.
*
* @param host address to get interface name from
- * @return allocated interface name, or NULL if not found
+ * @param name allocated interface name (optional)
+ * @return TRUE if interface found and usable
*/
- char* (*get_interface) (kernel_net_t *this, host_t *host);
+ bool (*get_interface) (kernel_net_t *this, host_t *host, char **name);
/**
* Creates an enumerator over all local addresses.
@@ -76,12 +100,11 @@ struct kernel_net_t {
* enumerator gets destroyed.
* The hosts are read-only, do not modify of free.
*
- * @param include_down_ifaces TRUE to enumerate addresses from down interfaces
- * @param include_virtual_ips TRUE to enumerate virtual ip addresses
- * @return enumerator over host_t's
+ * @param which a combination of address types to enumerate
+ * @return enumerator over host_t's
*/
enumerator_t *(*create_address_enumerator) (kernel_net_t *this,
- bool include_down_ifaces, bool include_virtual_ips);
+ kernel_address_type_t which);
/**
* Add a virtual IP to an interface.
diff --git a/src/libhydra/plugins/attr/Makefile.in b/src/libhydra/plugins/attr/Makefile.in
index 1ceb93ef3..831adf9d6 100644
--- a/src/libhydra/plugins/attr/Makefile.in
+++ b/src/libhydra/plugins/attr/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -82,7 +83,7 @@ libstrongswan_attr_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(libstrongswan_attr_la_LDFLAGS) $(LDFLAGS) -o $@
@MONOLITHIC_FALSE@am_libstrongswan_attr_la_rpath = -rpath $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_attr_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -108,6 +109,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -202,11 +204,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -223,11 +228,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -243,6 +249,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -252,7 +259,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libhydra/plugins/attr/attr_provider.c b/src/libhydra/plugins/attr/attr_provider.c
index 44242c259..c1c3cd895 100644
--- a/src/libhydra/plugins/attr/attr_provider.c
+++ b/src/libhydra/plugins/attr/attr_provider.c
@@ -77,10 +77,10 @@ static bool attr_enum_filter(void *null, attribute_entry_t **in,
}
METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
- private_attr_provider_t *this, char *pool,
- identification_t *id, host_t *vip)
+ private_attr_provider_t *this, linked_list_t *pools,
+ identification_t *id, linked_list_t *vips)
{
- if (vip)
+ if (vips->get_count(vips))
{
this->lock->read_lock(this->lock);
return enumerator_create_filter(
@@ -145,18 +145,22 @@ static void add_legacy_entry(private_attr_provider_t *this, char *key, int nr,
/**
* Key to attribute type mappings, for v4 and v6 attributes
*/
-static struct {
+typedef struct {
char *name;
configuration_attribute_type_t v4;
configuration_attribute_type_t v6;
-} keys[] = {
- {"address", INTERNAL_IP4_ADDRESS, INTERNAL_IP6_ADDRESS},
- {"dns", INTERNAL_IP4_DNS, INTERNAL_IP6_DNS},
- {"nbns", INTERNAL_IP4_NBNS, INTERNAL_IP6_NBNS},
- {"dhcp", INTERNAL_IP4_DHCP, INTERNAL_IP6_DHCP},
- {"netmask", INTERNAL_IP4_NETMASK, INTERNAL_IP6_NETMASK},
- {"server", INTERNAL_IP4_SERVER, INTERNAL_IP6_SERVER},
- {"subnet", INTERNAL_IP4_SUBNET, INTERNAL_IP6_SUBNET},
+} attribute_type_key_t;
+
+static attribute_type_key_t keys[] = {
+ {"address", INTERNAL_IP4_ADDRESS, INTERNAL_IP6_ADDRESS},
+ {"dns", INTERNAL_IP4_DNS, INTERNAL_IP6_DNS},
+ {"nbns", INTERNAL_IP4_NBNS, INTERNAL_IP6_NBNS},
+ {"dhcp", INTERNAL_IP4_DHCP, INTERNAL_IP6_DHCP},
+ {"netmask", INTERNAL_IP4_NETMASK, INTERNAL_IP6_NETMASK},
+ {"server", INTERNAL_IP4_SERVER, INTERNAL_IP6_SERVER},
+ {"subnet", INTERNAL_IP4_SUBNET, INTERNAL_IP6_SUBNET},
+ {"split-include", UNITY_SPLIT_INCLUDE, UNITY_SPLIT_INCLUDE},
+ {"split-exclude", UNITY_LOCAL_LAN, UNITY_LOCAL_LAN},
};
/**
@@ -179,12 +183,29 @@ static void load_entries(private_attr_provider_t *this)
while (enumerator->enumerate(enumerator, &key, &value))
{
configuration_attribute_type_t type;
+ attribute_type_key_t *mapped = NULL;
attribute_entry_t *entry;
host_t *host;
char *pos;
- int i, mask = -1;
+ int i, mask = -1, family;
type = atoi(key);
+ if (!type)
+ {
+ for (i = 0; i < countof(keys); i++)
+ {
+ if (streq(key, keys[i].name))
+ {
+ mapped = &keys[i];
+ break;
+ }
+ }
+ if (!mapped)
+ {
+ DBG1(DBG_CFG, "mapping attribute type %s failed", key);
+ continue;
+ }
+ }
tokens = enumerator_create_token(value, ",", " ");
while (tokens->enumerate(tokens, &token))
{
@@ -200,37 +221,16 @@ static void load_entries(private_attr_provider_t *this)
DBG1(DBG_CFG, "invalid host in key %s: %s", key, token);
continue;
}
- if (!type)
- {
- for (i = 0; i < countof(keys); i++)
- {
- if (streq(key, keys[i].name))
- {
- if (host->get_family(host) == AF_INET)
- {
- type = keys[i].v4;
- }
- else
- {
- type = keys[i].v6;
- }
- }
- }
- if (!type)
- {
- DBG1(DBG_CFG, "mapping attribute type %s failed", key);
- break;
- }
- }
+ family = host->get_family(host);
entry = malloc_thing(attribute_entry_t);
- entry->type = type;
+ entry->type = type ?: (family == AF_INET ? mapped->v4 : mapped->v6);
if (mask == -1)
{
entry->value = chunk_clone(host->get_address(host));
}
else
{
- if (host->get_family(host) == AF_INET)
+ if (family == AF_INET)
{ /* IPv4 attributes contain a subnet mask */
u_int32_t netmask;
diff --git a/src/libhydra/plugins/attr_sql/Makefile.in b/src/libhydra/plugins/attr_sql/Makefile.in
index 4fe577f3b..71810ae5e 100644
--- a/src/libhydra/plugins/attr_sql/Makefile.in
+++ b/src/libhydra/plugins/attr_sql/Makefile.in
@@ -51,6 +51,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -95,7 +96,7 @@ pool_OBJECTS = $(am_pool_OBJECTS)
pool_DEPENDENCIES = \
$(top_builddir)/src/libstrongswan/libstrongswan.la \
$(top_builddir)/src/libhydra/libhydra.la
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -121,6 +122,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -215,11 +217,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -236,11 +241,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -256,6 +262,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -265,7 +272,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libhydra/plugins/attr_sql/pool_attributes.c b/src/libhydra/plugins/attr_sql/pool_attributes.c
index 5c7397476..d3fc06eeb 100644
--- a/src/libhydra/plugins/attr_sql/pool_attributes.c
+++ b/src/libhydra/plugins/attr_sql/pool_attributes.c
@@ -492,7 +492,7 @@ void del_attr(char *name, char *pool, char *identity,
{
fprintf(stderr, "deleting %s attribute (%N) with value '%.*s'%s failed.\n",
name, configuration_attribute_type_names, type,
- blob_db.len, blob_db.ptr, id_pool_str);
+ (int)blob_db.len, blob_db.ptr, id_pool_str);
}
else
@@ -514,7 +514,7 @@ void del_attr(char *name, char *pool, char *identity,
{
printf("deleted %s attribute (%N) with value '%.*s'%s.\n",
name, configuration_attribute_type_names, type,
- blob_db.len, blob_db.ptr, id_pool_str);
+ (int)blob_db.len, blob_db.ptr, id_pool_str);
}
else
{
@@ -555,7 +555,7 @@ void del_attr(char *name, char *pool, char *identity,
fprintf(stderr, "the %s attribute (%N) with value '%.*s'%s "
"was not found.\n", name,
configuration_attribute_type_names, type,
- blob.len, blob.ptr, id_pool_str);
+ (int)blob.len, blob.ptr, id_pool_str);
}
}
}
diff --git a/src/libhydra/plugins/attr_sql/sql_attribute.c b/src/libhydra/plugins/attr_sql/sql_attribute.c
index 714bbcd72..a7d90e728 100644
--- a/src/libhydra/plugins/attr_sql/sql_attribute.c
+++ b/src/libhydra/plugins/attr_sql/sql_attribute.c
@@ -233,54 +233,37 @@ static host_t* get_lease(private_sql_attribute_t *this, char *name,
}
METHOD(attribute_provider_t, acquire_address, host_t*,
- private_sql_attribute_t *this, char *names, identification_t *id,
+ private_sql_attribute_t *this, linked_list_t *pools, identification_t *id,
host_t *requested)
{
+ enumerator_t *enumerator;
host_t *address = NULL;
u_int identity, pool, timeout;
+ char *name;
identity = get_identity(this, id);
if (identity)
{
- /* check for a single pool first (no concatenation and enumeration) */
- if (strchr(names, ',') == NULL)
+ /* check for an existing lease in all pools */
+ enumerator = pools->create_enumerator(pools);
+ while (enumerator->enumerate(enumerator, &name))
{
- pool = get_pool(this, names, &timeout);
+ pool = get_pool(this, name, &timeout);
if (pool)
{
- /* check for an existing lease */
- address = check_lease(this, names, pool, identity);
- if (address == NULL)
+ address = check_lease(this, name, pool, identity);
+ if (address)
{
- /* get an unallocated address or expired lease */
- address = get_lease(this, names, pool, timeout, identity);
+ break;
}
}
}
- else
- {
- enumerator_t *enumerator;
- char *name;
+ enumerator->destroy(enumerator);
- /* in a first step check for an existing lease over all pools */
- enumerator = enumerator_create_token(names, ",", " ");
- while (enumerator->enumerate(enumerator, &name))
- {
- pool = get_pool(this, name, &timeout);
- if (pool)
- {
- address = check_lease(this, name, pool, identity);
- if (address)
- {
- enumerator->destroy(enumerator);
- return address;
- }
- }
- }
- enumerator->destroy(enumerator);
-
- /* in a second step get an unallocated address or expired lease */
- enumerator = enumerator_create_token(names, ",", " ");
+ if (!address)
+ {
+ /* get an unallocated address or expired lease */
+ enumerator = pools->create_enumerator(pools);
while (enumerator->enumerate(enumerator, &name))
{
pool = get_pool(this, name, &timeout);
@@ -300,20 +283,27 @@ METHOD(attribute_provider_t, acquire_address, host_t*,
}
METHOD(attribute_provider_t, release_address, bool,
- private_sql_attribute_t *this, char *name, host_t *address,
+ private_sql_attribute_t *this, linked_list_t *pools, host_t *address,
identification_t *id)
{
enumerator_t *enumerator;
- bool found = FALSE;
+ u_int pool, timeout;
time_t now = time(NULL);
+ bool found = FALSE;
+ char *name;
- enumerator = enumerator_create_token(name, ",", " ");
+ enumerator = pools->create_enumerator(pools);
while (enumerator->enumerate(enumerator, &name))
{
- u_int pool, timeout;
-
pool = get_pool(this, name, &timeout);
- if (pool)
+ if (!pool)
+ {
+ continue;
+ }
+ if (this->db->execute(this->db, NULL,
+ "UPDATE addresses SET released = ? WHERE "
+ "pool = ? AND address = ?", DB_UINT, time(NULL),
+ DB_UINT, pool, DB_BLOB, address->get_address(address)) > 0)
{
if (this->history)
{
@@ -324,29 +314,24 @@ METHOD(attribute_provider_t, release_address, bool,
DB_UINT, now, DB_UINT, pool,
DB_BLOB, address->get_address(address));
}
- if (this->db->execute(this->db, NULL,
- "UPDATE addresses SET released = ? WHERE "
- "pool = ? AND address = ?", DB_UINT, time(NULL),
- DB_UINT, pool, DB_BLOB, address->get_address(address)) > 0)
- {
- found = TRUE;
- break;
- }
+ found = TRUE;
+ break;
}
}
enumerator->destroy(enumerator);
+
return found;
}
METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
- private_sql_attribute_t *this, char *names, identification_t *id,
- host_t *vip)
+ private_sql_attribute_t *this, linked_list_t *pools, identification_t *id,
+ linked_list_t *vips)
{
enumerator_t *attr_enumerator = NULL;
- if (vip)
+ if (vips->get_count(vips))
{
- enumerator_t *names_enumerator;
+ enumerator_t *pool_enumerator;
u_int count;
char *name;
@@ -357,8 +342,8 @@ METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
{
u_int identity = get_identity(this, id);
- names_enumerator = enumerator_create_token(names, ",", " ");
- while (names_enumerator->enumerate(names_enumerator, &name))
+ pool_enumerator = pools->create_enumerator(pools);
+ while (pool_enumerator->enumerate(pool_enumerator, &name))
{
u_int attr_pool = get_attr_pool(this, name);
if (!attr_pool)
@@ -385,14 +370,14 @@ METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
DESTROY_IF(attr_enumerator);
attr_enumerator = NULL;
}
- names_enumerator->destroy(names_enumerator);
+ pool_enumerator->destroy(pool_enumerator);
}
/* in a second step check for attributes that match name */
if (!attr_enumerator)
{
- names_enumerator = enumerator_create_token(names, ",", " ");
- while (names_enumerator->enumerate(names_enumerator, &name))
+ pool_enumerator = pools->create_enumerator(pools);
+ while (pool_enumerator->enumerate(pool_enumerator, &name))
{
u_int attr_pool = get_attr_pool(this, name);
if (!attr_pool)
@@ -419,7 +404,7 @@ METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
DESTROY_IF(attr_enumerator);
attr_enumerator = NULL;
}
- names_enumerator->destroy(names_enumerator);
+ pool_enumerator->destroy(pool_enumerator);
}
this->db->execute(this->db, NULL, "END TRANSACTION");
diff --git a/src/libhydra/plugins/kernel_klips/Makefile.in b/src/libhydra/plugins/kernel_klips/Makefile.in
index 63f3e045b..1dd633ee2 100644
--- a/src/libhydra/plugins/kernel_klips/Makefile.in
+++ b/src/libhydra/plugins/kernel_klips/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -86,7 +87,7 @@ libstrongswan_kernel_klips_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_kernel_klips_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_kernel_klips_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -112,6 +113,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -206,11 +208,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -227,11 +232,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -247,6 +253,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -256,7 +263,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c b/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c
index ceff8cdc9..d875dab04 100644
--- a/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c
+++ b/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c
@@ -138,11 +138,6 @@ struct private_kernel_klips_ipsec_t
linked_list_t *ipsec_devices;
/**
- * job receiving PF_KEY events
- */
- callback_job_t *job;
-
- /**
* mutex to lock access to the PF_KEY socket
*/
mutex_t *mutex_pfkey;
@@ -825,8 +820,22 @@ static kernel_algorithm_t compression_algs[] = {
/**
* Look up a kernel algorithm ID and its key size
*/
-static int lookup_algorithm(kernel_algorithm_t *list, int ikev2)
+static int lookup_algorithm(transform_type_t type, int ikev2)
{
+ kernel_algorithm_t *list;
+ int alg = 0;
+
+ switch (type)
+ {
+ case ENCRYPTION_ALGORITHM:
+ list = encryption_algs;
+ break;
+ case INTEGRITY_ALGORITHM:
+ list = integrity_algs;
+ break;
+ default:
+ return 0;
+ }
while (list->ikev2 != END_OF_LIST)
{
if (ikev2 == list->ikev2)
@@ -835,7 +844,9 @@ static int lookup_algorithm(kernel_algorithm_t *list, int ikev2)
}
list++;
}
- return 0;
+ hydra->kernel_interface->lookup_algorithm(hydra->kernel_interface, ikev2,
+ type, &alg, NULL);
+ return alg;
}
/**
@@ -1525,12 +1536,12 @@ METHOD(kernel_ipsec_t, get_spi, status_t,
u_int32_t spi_gen;
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
- if (!rng)
+ if (!rng || !rng->get_bytes(rng, sizeof(spi_gen), (void*)&spi_gen))
{
- DBG1(DBG_KNL, "allocating SPI failed: no RNG");
+ DBG1(DBG_KNL, "allocating SPI failed");
+ DESTROY_IF(rng);
return FAILED;
}
- rng->get_bytes(rng, sizeof(spi_gen), (void*)&spi_gen);
rng->destroy(rng);
/* allocated SPIs lie within the range from 0xc0000000 to 0xcFFFFFFF */
@@ -1718,8 +1729,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
sa->sadb_sa_spi = spi;
sa->sadb_sa_state = SADB_SASTATE_MATURE;
sa->sadb_sa_replay = (protocol == IPPROTO_COMP) ? 0 : 32;
- sa->sadb_sa_auth = lookup_algorithm(integrity_algs, int_alg);
- sa->sadb_sa_encrypt = lookup_algorithm(encryption_algs, enc_alg);
+ sa->sadb_sa_auth = lookup_algorithm(INTEGRITY_ALGORITHM, int_alg);
+ sa->sadb_sa_encrypt = lookup_algorithm(ENCRYPTION_ALGORITHM, enc_alg);
PFKEY_EXT_ADD(msg, sa);
add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC);
@@ -2097,7 +2108,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
*/
if (policy->route == NULL && direction == POLICY_OUT)
{
- char *iface;
+ char *iface = NULL;
ipsec_dev_t *dev;
route_entry_t *route = malloc_thing(route_entry_t);
route->src_ip = NULL;
@@ -2115,8 +2126,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
}
/* find the virtual interface */
- iface = hydra->kernel_interface->get_interface(hydra->kernel_interface,
- src);
+ hydra->kernel_interface->get_interface(hydra->kernel_interface,
+ src, &iface);
if (find_ipsec_dev(this, iface, &dev) == SUCCESS)
{
/* above, we got either the name of a virtual or a physical
@@ -2163,7 +2174,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
/* get the nexthop to dst */
route->gateway = hydra->kernel_interface->get_nexthop(
- hydra->kernel_interface, dst);
+ hydra->kernel_interface, dst, route->src_ip);
route->dst_net = chunk_clone(policy->dst.net->get_address(policy->dst.net));
route->prefixlen = policy->dst.mask;
@@ -2542,20 +2553,9 @@ static status_t register_pfkey_socket(private_kernel_klips_ipsec_t *this, u_int8
return SUCCESS;
}
-METHOD(kernel_ipsec_t, bypass_socket, bool,
- private_kernel_klips_ipsec_t *this, int fd, int family)
-{
- /* KLIPS does not need a bypass policy for IKE */
- return TRUE;
-}
-
METHOD(kernel_ipsec_t, destroy, void,
private_kernel_klips_ipsec_t *this)
{
- if (this->job)
- {
- this->job->cancel(this->job);
- }
if (this->socket > 0)
{
close(this->socket);
@@ -2594,7 +2594,10 @@ kernel_klips_ipsec_t *kernel_klips_ipsec_create()
.query_policy = _query_policy,
.del_policy = _del_policy,
.flush_policies = (void*)return_failed,
- .bypass_socket = _bypass_socket,
+ /* KLIPS does not need a bypass policy for IKE */
+ .bypass_socket = (void*)return_true,
+ /* KLIPS does not need enabling UDP decap explicitly */
+ .enable_udp_decap = (void*)return_true,
.destroy = _destroy,
},
},
@@ -2639,9 +2642,9 @@ kernel_klips_ipsec_t *kernel_klips_ipsec_create()
return NULL;
}
- this->job = callback_job_create_with_prio((callback_job_cb_t)receive_events,
- this, NULL, NULL, JOB_PRIO_CRITICAL);
- lib->processor->queue_job(lib->processor, (job_t*)this->job);
+ lib->processor->queue_job(lib->processor,
+ (job_t*)callback_job_create_with_prio((callback_job_cb_t)receive_events,
+ this, NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
return &this->public;
}
diff --git a/src/libhydra/plugins/kernel_netlink/Makefile.in b/src/libhydra/plugins/kernel_netlink/Makefile.in
index 73dbdd0e3..d0adb3b1e 100644
--- a/src/libhydra/plugins/kernel_netlink/Makefile.in
+++ b/src/libhydra/plugins/kernel_netlink/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -87,7 +88,7 @@ libstrongswan_kernel_netlink_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_kernel_netlink_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_kernel_netlink_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -113,6 +114,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -207,11 +209,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -228,11 +233,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -248,6 +254,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -257,7 +264,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
index b2cf778be..4f5b6600d 100644
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
+++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2011 Tobias Brunner
+ * Copyright (C) 2006-2012 Tobias Brunner
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2008 Andreas Steffen
* Copyright (C) 2006-2007 Fabian Hartmann, Noah Heusser
@@ -58,6 +58,20 @@
#define IPV6_XFRM_POLICY 34
#endif /*IPV6_XFRM_POLICY*/
+/* from linux/udp.h */
+#ifndef UDP_ENCAP
+#define UDP_ENCAP 100
+#endif
+
+#ifndef UDP_ENCAP_ESPINUDP
+#define UDP_ENCAP_ESPINUDP 2
+#endif
+
+/* this is not defined on some platforms */
+#ifndef SOL_UDP
+#define SOL_UDP IPPROTO_UDP
+#endif
+
/** Default priority of installed policies */
#define PRIO_BASE 512
@@ -229,8 +243,25 @@ static kernel_algorithm_t compression_algs[] = {
/**
* Look up a kernel algorithm name and its key size
*/
-static char* lookup_algorithm(kernel_algorithm_t *list, int ikev2)
+static char* lookup_algorithm(transform_type_t type, int ikev2)
{
+ kernel_algorithm_t *list;
+ char *name = NULL;
+
+ switch (type)
+ {
+ case ENCRYPTION_ALGORITHM:
+ list = encryption_algs;
+ break;
+ case INTEGRITY_ALGORITHM:
+ list = integrity_algs;
+ break;
+ case COMPRESSION_ALGORITHM:
+ list = compression_algs;
+ break;
+ default:
+ return NULL;
+ }
while (list->ikev2 != END_OF_LIST)
{
if (list->ikev2 == ikev2)
@@ -239,7 +270,9 @@ static char* lookup_algorithm(kernel_algorithm_t *list, int ikev2)
}
list++;
}
- return NULL;
+ hydra->kernel_interface->lookup_algorithm(hydra->kernel_interface, ikev2,
+ type, NULL, &name);
+ return name;
}
typedef struct private_kernel_netlink_ipsec_t private_kernel_netlink_ipsec_t;
@@ -269,11 +302,6 @@ struct private_kernel_netlink_ipsec_t {
hashtable_t *sas;
/**
- * Job receiving netlink events
- */
- callback_job_t *job;
-
- /**
* Netlink xfrm socket (IPsec)
*/
netlink_socket_t *socket_xfrm;
@@ -294,12 +322,12 @@ struct private_kernel_netlink_ipsec_t {
bool policy_history;
/**
- * Size of the replay window, in packets
+ * Size of the replay window, in packets (= bits)
*/
u_int32_t replay_window;
/**
- * Size of the replay window bitmap, in bytes
+ * Size of the replay window bitmap, in number of __u32 blocks
*/
u_int32_t replay_bmp;
};
@@ -344,8 +372,8 @@ static void route_entry_destroy(route_entry_t *this)
static bool route_entry_equals(route_entry_t *a, route_entry_t *b)
{
return a->if_name && b->if_name && streq(a->if_name, b->if_name) &&
- a->src_ip->equals(a->src_ip, b->src_ip) &&
- a->gateway->equals(a->gateway, b->gateway) &&
+ a->src_ip->ip_equals(a->src_ip, b->src_ip) &&
+ a->gateway->ip_equals(a->gateway, b->gateway) &&
chunk_equals(a->dst_net, b->dst_net) && a->prefixlen == b->prefixlen;
}
@@ -562,9 +590,8 @@ static void policy_entry_destroy(private_kernel_netlink_ipsec_t *this,
*/
static u_int policy_hash(policy_entry_t *key)
{
- chunk_t chunk = chunk_create((void*)&key->sel,
- sizeof(struct xfrm_selector) + sizeof(u_int32_t));
- return chunk_hash(chunk);
+ chunk_t chunk = chunk_from_thing(key->sel);
+ return chunk_hash_inc(chunk, chunk_hash(chunk_from_thing(key->mark)));
}
/**
@@ -572,8 +599,8 @@ static u_int policy_hash(policy_entry_t *key)
*/
static bool policy_equals(policy_entry_t *key, policy_entry_t *other_key)
{
- return memeq(&key->sel, &other_key->sel,
- sizeof(struct xfrm_selector) + sizeof(u_int32_t)) &&
+ return memeq(&key->sel, &other_key->sel, sizeof(struct xfrm_selector)) &&
+ key->mark == other_key->mark &&
key->direction == other_key->direction;
}
@@ -1147,16 +1174,9 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
memset(&request, 0, sizeof(request));
- if (mark.value)
- {
- DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%u} (mark "
- "%u/0x%8x)", ntohl(spi), reqid, mark.value, mark.mask);
- }
- else
- {
- DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%u}",
- ntohl(spi), reqid);
- }
+ DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%u} (mark "
+ "%u/0x%08x)", ntohl(spi), reqid, mark.value, mark.mask);
+
hdr = (struct nlmsghdr*)request;
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
hdr->nlmsg_type = inbound ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA;
@@ -1220,12 +1240,12 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
{
struct xfrm_algo_aead *algo;
- alg_name = lookup_algorithm(encryption_algs, enc_alg);
+ alg_name = lookup_algorithm(ENCRYPTION_ALGORITHM, enc_alg);
if (alg_name == NULL)
{
DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
- encryption_algorithm_names, enc_alg);
- goto failed;
+ encryption_algorithm_names, enc_alg);
+ goto failed;
}
DBG2(DBG_KNL, " using encryption algorithm %N with key size %d",
encryption_algorithm_names, enc_alg, enc_key.len * 8);
@@ -1242,7 +1262,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
algo = (struct xfrm_algo_aead*)RTA_DATA(rthdr);
algo->alg_key_len = enc_key.len * 8;
algo->alg_icv_len = icv_size;
- strcpy(algo->alg_name, alg_name);
+ strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
+ algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
memcpy(algo->alg_key, enc_key.ptr, enc_key.len);
rthdr = XFRM_RTA_NEXT(rthdr);
@@ -1252,7 +1273,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
{
struct xfrm_algo *algo;
- alg_name = lookup_algorithm(encryption_algs, enc_alg);
+ alg_name = lookup_algorithm(ENCRYPTION_ALGORITHM, enc_alg);
if (alg_name == NULL)
{
DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
@@ -1272,7 +1293,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
algo = (struct xfrm_algo*)RTA_DATA(rthdr);
algo->alg_key_len = enc_key.len * 8;
- strcpy(algo->alg_name, alg_name);
+ strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
+ algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
memcpy(algo->alg_key, enc_key.ptr, enc_key.len);
rthdr = XFRM_RTA_NEXT(rthdr);
@@ -1283,7 +1305,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
{
u_int trunc_len = 0;
- alg_name = lookup_algorithm(integrity_algs, int_alg);
+ alg_name = lookup_algorithm(INTEGRITY_ALGORITHM, int_alg);
if (alg_name == NULL)
{
DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
@@ -1326,7 +1348,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
algo = (struct xfrm_algo_auth*)RTA_DATA(rthdr);
algo->alg_key_len = int_key.len * 8;
algo->alg_trunc_len = trunc_len;
- strcpy(algo->alg_name, alg_name);
+ strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
+ algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
memcpy(algo->alg_key, int_key.ptr, int_key.len);
}
else
@@ -1344,7 +1367,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
algo = (struct xfrm_algo*)RTA_DATA(rthdr);
algo->alg_key_len = int_key.len * 8;
- strcpy(algo->alg_name, alg_name);
+ strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
+ algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
memcpy(algo->alg_key, int_key.ptr, int_key.len);
}
rthdr = XFRM_RTA_NEXT(rthdr);
@@ -1353,7 +1377,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
if (ipcomp != IPCOMP_NONE)
{
rthdr->rta_type = XFRMA_ALG_COMP;
- alg_name = lookup_algorithm(compression_algs, ipcomp);
+ alg_name = lookup_algorithm(COMPRESSION_ALGORITHM, ipcomp);
if (alg_name == NULL)
{
DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
@@ -1372,7 +1396,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
struct xfrm_algo* algo = (struct xfrm_algo*)RTA_DATA(rthdr);
algo->alg_key_len = 0;
- strcpy(algo->alg_name, alg_name);
+ strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
+ algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
rthdr = XFRM_RTA_NEXT(rthdr);
}
@@ -1467,7 +1492,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
/* bmp_len contains number uf __u32's */
replay->bmp_len = this->replay_bmp;
replay->replay_window = this->replay_window;
- DBG2(DBG_KNL, " using replay window of %u bytes",
+ DBG2(DBG_KNL, " using replay window of %u packets",
this->replay_window);
rthdr = XFRM_RTA_NEXT(rthdr);
@@ -1479,7 +1504,9 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
}
else
{
- sa->replay_window = DEFAULT_REPLAY_WINDOW;
+ DBG2(DBG_KNL, " using replay window of %u packets",
+ this->replay_window);
+ sa->replay_window = this->replay_window;
}
}
@@ -1488,7 +1515,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
if (mark.value)
{
DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x "
- "(mark %u/0x%8x)", ntohl(spi), mark.value, mark.mask);
+ "(mark %u/0x%08x)", ntohl(spi), mark.value, mark.mask);
}
else
{
@@ -1608,15 +1635,9 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
memset(&request, 0, sizeof(request));
- if (mark.value)
- {
- DBG2(DBG_KNL, "querying SAD entry with SPI %.8x (mark %u/0x%8x)",
- ntohl(spi), mark.value, mark.mask);
- }
- else
- {
- DBG2(DBG_KNL, "querying SAD entry with SPI %.8x", ntohl(spi));
- }
+ DBG2(DBG_KNL, "querying SAD entry with SPI %.8x (mark %u/0x%08x)",
+ ntohl(spi), mark.value, mark.mask);
+
hdr = (struct nlmsghdr*)request;
hdr->nlmsg_flags = NLM_F_REQUEST;
hdr->nlmsg_type = XFRM_MSG_GETSA;
@@ -1665,7 +1686,7 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
if (mark.value)
{
DBG1(DBG_KNL, "querying SAD entry with SPI %.8x "
- "(mark %u/0x%8x) failed: %s (%d)",
+ "(mark %u/0x%08x) failed: %s (%d)",
ntohl(spi), mark.value, mark.mask,
strerror(-err->error), -err->error);
}
@@ -1717,15 +1738,9 @@ METHOD(kernel_ipsec_t, del_sa, status_t,
memset(&request, 0, sizeof(request));
- if (mark.value)
- {
- DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x (mark %u/0x%8x)",
- ntohl(spi), mark.value, mark.mask);
- }
- else
- {
- DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x", ntohl(spi));
- }
+ DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x (mark %u/0x%08x)",
+ ntohl(spi), mark.value, mark.mask);
+
hdr = (struct nlmsghdr*)request;
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
hdr->nlmsg_type = XFRM_MSG_DELSA;
@@ -1755,30 +1770,27 @@ METHOD(kernel_ipsec_t, del_sa, status_t,
mrk->m = mark.mask;
}
- if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
- {
- if (mark.value)
- {
- DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x "
- "(mark %u/0x%8x)", ntohl(spi), mark.value, mark.mask);
- }
- else
- {
- DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x",
- ntohl(spi));
- }
- return FAILED;
- }
- if (mark.value)
+ switch (this->socket_xfrm->send_ack(this->socket_xfrm, hdr))
{
- DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x (mark %u/0x%8x)",
- ntohl(spi), mark.value, mark.mask);
- }
- else
- {
- DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x", ntohl(spi));
+ case SUCCESS:
+ DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x (mark %u/0x%08x)",
+ ntohl(spi), mark.value, mark.mask);
+ return SUCCESS;
+ case NOT_FOUND:
+ return NOT_FOUND;
+ default:
+ if (mark.value)
+ {
+ DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x "
+ "(mark %u/0x%08x)", ntohl(spi), mark.value, mark.mask);
+ }
+ else
+ {
+ DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x",
+ ntohl(spi));
+ }
+ return FAILED;
}
- return SUCCESS;
}
METHOD(kernel_ipsec_t, update_sa, status_t,
@@ -1954,7 +1966,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
{
goto failed;
}
- memcpy(RTA_DATA(rta), replay, sizeof(replay));
+ memcpy(RTA_DATA(rta), replay, sizeof(struct xfrm_replay_state));
rta = XFRM_RTA_NEXT(rta);
}
@@ -2153,23 +2165,26 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this,
if (policy->direction == POLICY_FWD &&
ipsec->cfg.mode != MODE_TRANSPORT && this->install_routes)
{
- route_entry_t *route = malloc_thing(route_entry_t);
policy_sa_fwd_t *fwd = (policy_sa_fwd_t*)mapping;
+ route_entry_t *route;
+
+ INIT(route,
+ .prefixlen = policy->sel.prefixlen_s,
+ );
if (hydra->kernel_interface->get_address_by_ts(hydra->kernel_interface,
fwd->dst_ts, &route->src_ip) == SUCCESS)
{
/* get the nexthop to src (src as we are in POLICY_FWD) */
route->gateway = hydra->kernel_interface->get_nexthop(
- hydra->kernel_interface, ipsec->src);
- /* install route via outgoing interface */
- route->if_name = hydra->kernel_interface->get_interface(
- hydra->kernel_interface, ipsec->dst);
+ hydra->kernel_interface, ipsec->src,
+ ipsec->dst);
route->dst_net = chunk_alloc(policy->sel.family == AF_INET ? 4 : 16);
memcpy(route->dst_net.ptr, &policy->sel.saddr, route->dst_net.len);
- route->prefixlen = policy->sel.prefixlen_s;
- if (!route->if_name)
+ /* install route via outgoing interface */
+ if (!hydra->kernel_interface->get_interface(hydra->kernel_interface,
+ ipsec->dst, &route->if_name))
{
this->mutex->unlock(this->mutex);
route_entry_destroy(route);
@@ -2180,12 +2195,7 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this,
{
route_entry_t *old = policy->route;
if (route_entry_equals(old, route))
- { /* keep previously installed route. since it might have
- * still been removed by an address change, we install it
- * again but ignore the result */
- hydra->kernel_interface->add_route(hydra->kernel_interface,
- route->dst_net, route->prefixlen, route->gateway,
- route->src_ip, route->if_name);
+ {
this->mutex->unlock(this->mutex);
route_entry_destroy(route);
return SUCCESS;
@@ -2258,19 +2268,10 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
if (current)
{
/* use existing policy */
- if (mark.value)
- {
- DBG2(DBG_KNL, "policy %R === %R %N (mark %u/0x%8x) "
- "already exists, increasing refcount",
- src_ts, dst_ts, policy_dir_names, direction,
- mark.value, mark.mask);
- }
- else
- {
- DBG2(DBG_KNL, "policy %R === %R %N "
- "already exists, increasing refcount",
- src_ts, dst_ts, policy_dir_names, direction);
- }
+ DBG2(DBG_KNL, "policy %R === %R %N (mark %u/0x%08x) "
+ "already exists, increasing refcount",
+ src_ts, dst_ts, policy_dir_names, direction,
+ mark.value, mark.mask);
policy_entry_destroy(this, policy);
policy = current;
found = TRUE;
@@ -2314,18 +2315,9 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
return SUCCESS;
}
- if (mark.value)
- {
- DBG2(DBG_KNL, "%s policy %R === %R %N (mark %u/0x%8x)",
- found ? "updating" : "adding", src_ts, dst_ts,
- policy_dir_names, direction, mark.value, mark.mask);
- }
- else
- {
- DBG2(DBG_KNL, "%s policy %R === %R %N",
- found ? "updating" : "adding", src_ts, dst_ts,
- policy_dir_names, direction);
- }
+ DBG2(DBG_KNL, "%s policy %R === %R %N (mark %u/0x%08x)",
+ found ? "updating" : "adding", src_ts, dst_ts,
+ policy_dir_names, direction, mark.value, mark.mask);
if (add_policy_internal(this, policy, assigned_sa, found) != SUCCESS)
{
@@ -2350,17 +2342,10 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
memset(&request, 0, sizeof(request));
- if (mark.value)
- {
- DBG2(DBG_KNL, "querying policy %R === %R %N (mark %u/0x%8x)",
- src_ts, dst_ts, policy_dir_names, direction,
- mark.value, mark.mask);
- }
- else
- {
- DBG2(DBG_KNL, "querying policy %R === %R %N", src_ts, dst_ts,
- policy_dir_names, direction);
- }
+ DBG2(DBG_KNL, "querying policy %R === %R %N (mark %u/0x%08x)",
+ src_ts, dst_ts, policy_dir_names, direction,
+ mark.value, mark.mask);
+
hdr = (struct nlmsghdr*)request;
hdr->nlmsg_flags = NLM_F_REQUEST;
hdr->nlmsg_type = XFRM_MSG_GETPOLICY;
@@ -2454,17 +2439,9 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
bool is_installed = TRUE;
u_int32_t priority;
- if (mark.value)
- {
- DBG2(DBG_KNL, "deleting policy %R === %R %N (mark %u/0x%8x)",
- src_ts, dst_ts, policy_dir_names, direction,
- mark.value, mark.mask);
- }
- else
- {
- DBG2(DBG_KNL, "deleting policy %R === %R %N",
- src_ts, dst_ts, policy_dir_names, direction);
- }
+ DBG2(DBG_KNL, "deleting policy %R === %R %N (mark %u/0x%08x)",
+ src_ts, dst_ts, policy_dir_names, direction,
+ mark.value, mark.mask);
/* create a policy */
memset(&policy, 0, sizeof(policy_entry_t));
@@ -2479,7 +2456,7 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
{
if (mark.value)
{
- DBG1(DBG_KNL, "deleting policy %R === %R %N (mark %u/0x%8x) "
+ DBG1(DBG_KNL, "deleting policy %R === %R %N (mark %u/0x%08x) "
"failed, not found", src_ts, dst_ts, policy_dir_names,
direction, mark.value, mark.mask);
}
@@ -2525,17 +2502,9 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
return SUCCESS;
}
- if (mark.value)
- {
- DBG2(DBG_KNL, "updating policy %R === %R %N (mark %u/0x%8x)",
- src_ts, dst_ts, policy_dir_names, direction,
- mark.value, mark.mask);
- }
- else
- {
- DBG2(DBG_KNL, "updating policy %R === %R %N",
- src_ts, dst_ts, policy_dir_names, direction);
- }
+ DBG2(DBG_KNL, "updating policy %R === %R %N (mark %u/0x%08x)",
+ src_ts, dst_ts, policy_dir_names, direction,
+ mark.value, mark.mask);
current->used_by->get_first(current->used_by, (void**)&mapping);
if (add_policy_internal(this, current, mapping, TRUE) != SUCCESS)
@@ -2599,7 +2568,7 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
if (mark.value)
{
DBG1(DBG_KNL, "unable to delete policy %R === %R %N "
- "(mark %u/0x%8x)", src_ts, dst_ts, policy_dir_names,
+ "(mark %u/0x%08x)", src_ts, dst_ts, policy_dir_names,
direction, mark.value, mark.mask);
}
else
@@ -2680,16 +2649,25 @@ METHOD(kernel_ipsec_t, bypass_socket, bool,
return TRUE;
}
+METHOD(kernel_ipsec_t, enable_udp_decap, bool,
+ private_kernel_netlink_ipsec_t *this, int fd, int family, u_int16_t port)
+{
+ int type = UDP_ENCAP_ESPINUDP;
+
+ if (setsockopt(fd, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0)
+ {
+ DBG1(DBG_KNL, "unable to set UDP_ENCAP: %s", strerror(errno));
+ return FALSE;
+ }
+ return TRUE;
+}
+
METHOD(kernel_ipsec_t, destroy, void,
private_kernel_netlink_ipsec_t *this)
{
enumerator_t *enumerator;
policy_entry_t *policy;
- if (this->job)
- {
- this->job->cancel(this->job);
- }
if (this->socket_xfrm_events > 0)
{
close(this->socket_xfrm_events);
@@ -2713,7 +2691,7 @@ METHOD(kernel_ipsec_t, destroy, void,
kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
{
private_kernel_netlink_ipsec_t *this;
- struct sockaddr_nl addr;
+ bool register_for_events = TRUE;
int fd;
INIT(this,
@@ -2731,6 +2709,7 @@ kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
.del_policy = _del_policy,
.flush_policies = _flush_policies,
.bypass_socket = _bypass_socket,
+ .enable_udp_decap = _enable_udp_decap,
.destroy = _destroy,
},
},
@@ -2755,10 +2734,14 @@ kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
/* no policy history for pluto */
this->policy_history = FALSE;
}
+ else if (streq(hydra->daemon, "starter"))
+ { /* starter has no threads, so we do not register for kernel events */
+ register_for_events = FALSE;
+ }
/* disable lifetimes for allocated SPIs in kernel */
fd = open("/proc/sys/net/core/xfrm_acq_expires", O_WRONLY);
- if (fd)
+ if (fd > 0)
{
ignore_result(write(fd, "165", 3));
close(fd);
@@ -2771,28 +2754,34 @@ kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
return NULL;
}
- memset(&addr, 0, sizeof(addr));
- addr.nl_family = AF_NETLINK;
-
- /* create and bind XFRM socket for ACQUIRE, EXPIRE, MIGRATE & MAPPING */
- this->socket_xfrm_events = socket(AF_NETLINK, SOCK_RAW, NETLINK_XFRM);
- if (this->socket_xfrm_events <= 0)
+ if (register_for_events)
{
- DBG1(DBG_KNL, "unable to create XFRM event socket");
- destroy(this);
- return NULL;
- }
- addr.nl_groups = XFRMNLGRP(ACQUIRE) | XFRMNLGRP(EXPIRE) |
- XFRMNLGRP(MIGRATE) | XFRMNLGRP(MAPPING);
- if (bind(this->socket_xfrm_events, (struct sockaddr*)&addr, sizeof(addr)))
- {
- DBG1(DBG_KNL, "unable to bind XFRM event socket");
- destroy(this);
- return NULL;
+ struct sockaddr_nl addr;
+
+ memset(&addr, 0, sizeof(addr));
+ addr.nl_family = AF_NETLINK;
+
+ /* create and bind XFRM socket for ACQUIRE, EXPIRE, MIGRATE & MAPPING */
+ this->socket_xfrm_events = socket(AF_NETLINK, SOCK_RAW, NETLINK_XFRM);
+ if (this->socket_xfrm_events <= 0)
+ {
+ DBG1(DBG_KNL, "unable to create XFRM event socket");
+ destroy(this);
+ return NULL;
+ }
+ addr.nl_groups = XFRMNLGRP(ACQUIRE) | XFRMNLGRP(EXPIRE) |
+ XFRMNLGRP(MIGRATE) | XFRMNLGRP(MAPPING);
+ if (bind(this->socket_xfrm_events, (struct sockaddr*)&addr, sizeof(addr)))
+ {
+ DBG1(DBG_KNL, "unable to bind XFRM event socket");
+ destroy(this);
+ return NULL;
+ }
+ lib->processor->queue_job(lib->processor,
+ (job_t*)callback_job_create_with_prio(
+ (callback_job_cb_t)receive_events, this, NULL,
+ (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
}
- this->job = callback_job_create_with_prio((callback_job_cb_t)receive_events,
- this, NULL, NULL, JOB_PRIO_CRITICAL);
- lib->processor->queue_job(lib->processor, (job_t*)this->job);
return &this->public;
}
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c
index cce0ff402..3f63a8496 100644
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c
+++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2008-2012 Tobias Brunner
* Copyright (C) 2005-2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -38,6 +38,7 @@
*/
#include <sys/socket.h>
+#include <sys/utsname.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <unistd.h>
@@ -50,32 +51,38 @@
#include <hydra.h>
#include <debug.h>
#include <threading/thread.h>
-#include <threading/condvar.h>
#include <threading/mutex.h>
+#include <threading/rwlock.h>
+#include <threading/rwlock_condvar.h>
+#include <threading/spinlock.h>
+#include <utils/hashtable.h>
#include <utils/linked_list.h>
#include <processing/jobs/callback_job.h>
/** delay before firing roam events (ms) */
#define ROAM_DELAY 100
+/** delay before reinstalling routes (ms) */
+#define ROUTE_DELAY 100
+
typedef struct addr_entry_t addr_entry_t;
/**
- * IP address in an inface_entry_t
+ * IP address in an iface_entry_t
*/
struct addr_entry_t {
- /** The ip address */
+ /** the ip address */
host_t *ip;
- /** virtual IP managed by us */
- bool virtual;
-
/** scope of the address */
u_char scope;
- /** Number of times this IP is used, if virtual */
+ /** number of times this IP is used, if virtual (i.e. managed by us) */
u_int refcount;
+
+ /** TRUE once it is installed, if virtual */
+ bool installed;
};
/**
@@ -105,6 +112,9 @@ struct iface_entry_t {
/** list of addresses as host_t */
linked_list_t *addrs;
+
+ /** TRUE if usable by config */
+ bool usable;
};
/**
@@ -116,6 +126,208 @@ static void iface_entry_destroy(iface_entry_t *this)
free(this);
}
+/**
+ * find an interface entry by index
+ */
+static bool iface_entry_by_index(iface_entry_t *this, int *ifindex)
+{
+ return this->ifindex == *ifindex;
+}
+
+/**
+ * find an interface entry by name
+ */
+static bool iface_entry_by_name(iface_entry_t *this, char *ifname)
+{
+ return streq(this->ifname, ifname);
+}
+
+/**
+ * check if an interface is up
+ */
+static inline bool iface_entry_up(iface_entry_t *iface)
+{
+ return (iface->flags & IFF_UP) == IFF_UP;
+}
+
+/**
+ * check if an interface is up and usable
+ */
+static inline bool iface_entry_up_and_usable(iface_entry_t *iface)
+{
+ return iface->usable && iface_entry_up(iface);
+}
+
+typedef struct addr_map_entry_t addr_map_entry_t;
+
+/**
+ * Entry that maps an IP address to an interface entry
+ */
+struct addr_map_entry_t {
+ /** The IP address */
+ host_t *ip;
+
+ /** The address entry for this IP address */
+ addr_entry_t *addr;
+
+ /** The interface this address is installed on */
+ iface_entry_t *iface;
+};
+
+/**
+ * Hash a addr_map_entry_t object, all entries with the same IP address
+ * are stored in the same bucket
+ */
+static u_int addr_map_entry_hash(addr_map_entry_t *this)
+{
+ return chunk_hash(this->ip->get_address(this->ip));
+}
+
+/**
+ * Compare two addr_map_entry_t objects, two entries are equal if they are
+ * installed on the same interface
+ */
+static bool addr_map_entry_equals(addr_map_entry_t *a, addr_map_entry_t *b)
+{
+ return a->iface->ifindex == b->iface->ifindex &&
+ a->ip->ip_equals(a->ip, b->ip);
+}
+
+/**
+ * Used with get_match this finds an address entry if it is installed on
+ * an up and usable interface
+ */
+static bool addr_map_entry_match_up_and_usable(addr_map_entry_t *a,
+ addr_map_entry_t *b)
+{
+ return iface_entry_up_and_usable(b->iface) &&
+ a->ip->ip_equals(a->ip, b->ip);
+}
+
+/**
+ * Used with get_match this finds an address entry if it is installed on
+ * any active local interface
+ */
+static bool addr_map_entry_match_up(addr_map_entry_t *a, addr_map_entry_t *b)
+{
+ return iface_entry_up(b->iface) && a->ip->ip_equals(a->ip, b->ip);
+}
+
+/**
+ * Used with get_match this finds an address entry if it is installed on
+ * any local interface
+ */
+static bool addr_map_entry_match(addr_map_entry_t *a, addr_map_entry_t *b)
+{
+ return a->ip->ip_equals(a->ip, b->ip);
+}
+
+typedef struct route_entry_t route_entry_t;
+
+/**
+ * Installed routing entry
+ */
+struct route_entry_t {
+ /** Name of the interface the route is bound to */
+ char *if_name;
+
+ /** Source ip of the route */
+ host_t *src_ip;
+
+ /** Gateway for this route */
+ host_t *gateway;
+
+ /** Destination net */
+ chunk_t dst_net;
+
+ /** Destination net prefixlen */
+ u_int8_t prefixlen;
+};
+
+/**
+ * Clone a route_entry_t object.
+ */
+static route_entry_t *route_entry_clone(route_entry_t *this)
+{
+ route_entry_t *route;
+
+ INIT(route,
+ .if_name = strdup(this->if_name),
+ .src_ip = this->src_ip->clone(this->src_ip),
+ .gateway = this->gateway->clone(this->gateway),
+ .dst_net = chunk_clone(this->dst_net),
+ .prefixlen = this->prefixlen,
+ );
+ return route;
+}
+
+/**
+ * Destroy a route_entry_t object
+ */
+static void route_entry_destroy(route_entry_t *this)
+{
+ free(this->if_name);
+ DESTROY_IF(this->src_ip);
+ DESTROY_IF(this->gateway);
+ chunk_free(&this->dst_net);
+ free(this);
+}
+
+/**
+ * Hash a route_entry_t object
+ */
+static u_int route_entry_hash(route_entry_t *this)
+{
+ return chunk_hash_inc(chunk_from_thing(this->prefixlen),
+ chunk_hash(this->dst_net));
+}
+
+/**
+ * Compare two route_entry_t objects
+ */
+static bool route_entry_equals(route_entry_t *a, route_entry_t *b)
+{
+ return a->if_name && b->if_name && streq(a->if_name, b->if_name) &&
+ a->src_ip->ip_equals(a->src_ip, b->src_ip) &&
+ a->gateway->ip_equals(a->gateway, b->gateway) &&
+ chunk_equals(a->dst_net, b->dst_net) && a->prefixlen == b->prefixlen;
+}
+
+typedef struct net_change_t net_change_t;
+
+/**
+ * Queued network changes
+ */
+struct net_change_t {
+ /** Name of the interface that got activated (or an IP appeared on) */
+ char *if_name;
+};
+
+/**
+ * Destroy a net_change_t object
+ */
+static void net_change_destroy(net_change_t *this)
+{
+ free(this->if_name);
+ free(this);
+}
+
+/**
+ * Hash a net_change_t object
+ */
+static u_int net_change_hash(net_change_t *this)
+{
+ return chunk_hash(chunk_create(this->if_name, strlen(this->if_name)));
+}
+
+/**
+ * Compare two net_change_t objects
+ */
+static bool net_change_equals(net_change_t *a, net_change_t *b)
+{
+ return streq(a->if_name, b->if_name);
+}
+
typedef struct private_kernel_netlink_net_t private_kernel_netlink_net_t;
/**
@@ -128,14 +340,14 @@ struct private_kernel_netlink_net_t {
kernel_netlink_net_t public;
/**
- * mutex to lock access to various lists
+ * lock to access various lists and maps
*/
- mutex_t *mutex;
+ rwlock_t *lock;
/**
* condition variable to signal virtual IP add/removal
*/
- condvar_t *condvar;
+ rwlock_condvar_t *condvar;
/**
* Cached list of interfaces and its addresses (iface_entry_t)
@@ -143,9 +355,14 @@ struct private_kernel_netlink_net_t {
linked_list_t *ifaces;
/**
- * job receiving netlink events
+ * Map for IP addresses to iface_entry_t objects (addr_map_entry_t)
*/
- callback_job_t *job;
+ hashtable_t *addrs;
+
+ /**
+ * Map for virtual IP addresses to iface_entry_t objects (addr_map_entry_t)
+ */
+ hashtable_t *vips;
/**
* netlink rt socket (routing)
@@ -158,9 +375,14 @@ struct private_kernel_netlink_net_t {
int socket_events;
/**
- * time of the last roam event
+ * earliest time of the next roam event
+ */
+ timeval_t next_roam;
+
+ /**
+ * lock to check and update roam event time
*/
- timeval_t last_roam;
+ spinlock_t *roam_lock;
/**
* routing table to install routes
@@ -173,6 +395,31 @@ struct private_kernel_netlink_net_t {
int routing_table_prio;
/**
+ * installed routes
+ */
+ hashtable_t *routes;
+
+ /**
+ * mutex for routes
+ */
+ mutex_t *routes_lock;
+
+ /**
+ * interface changes which may trigger route reinstallation
+ */
+ hashtable_t *net_changes;
+
+ /**
+ * mutex for route reinstallation triggers
+ */
+ mutex_t *net_changes_lock;
+
+ /**
+ * time of last route reinstallation
+ */
+ timeval_t last_route_reinstall;
+
+ /**
* whether to react to RTM_NEWROUTE or RTM_DELROUTE events
*/
bool process_route;
@@ -183,79 +430,253 @@ struct private_kernel_netlink_net_t {
bool install_virtual_ip;
/**
+ * the name of the interface virtual IP addresses are installed on
+ */
+ char *install_virtual_ip_on;
+
+ /**
+ * whether preferred source addresses can be specified for IPv6 routes
+ */
+ bool rta_prefsrc_for_ipv6;
+
+ /**
* list with routing tables to be excluded from route lookup
*/
linked_list_t *rt_exclude;
};
/**
- * get the refcount of a virtual ip
+ * Forward declaration
+ */
+static status_t manage_srcroute(private_kernel_netlink_net_t *this,
+ int nlmsg_type, int flags, chunk_t dst_net,
+ u_int8_t prefixlen, host_t *gateway,
+ host_t *src_ip, char *if_name);
+
+/**
+ * Clear the queued network changes.
*/
-static int get_vip_refcount(private_kernel_netlink_net_t *this, host_t* ip)
+static void net_changes_clear(private_kernel_netlink_net_t *this)
{
- enumerator_t *ifaces, *addrs;
- iface_entry_t *iface;
- addr_entry_t *addr;
- int refcount = 0;
+ enumerator_t *enumerator;
+ net_change_t *change;
- ifaces = this->ifaces->create_enumerator(this->ifaces);
- while (ifaces->enumerate(ifaces, (void**)&iface))
+ enumerator = this->net_changes->create_enumerator(this->net_changes);
+ while (enumerator->enumerate(enumerator, NULL, (void**)&change))
{
- addrs = iface->addrs->create_enumerator(iface->addrs);
- while (addrs->enumerate(addrs, (void**)&addr))
- {
- if (addr->virtual && (iface->flags & IFF_UP) &&
- ip->ip_equals(ip, addr->ip))
+ this->net_changes->remove_at(this->net_changes, enumerator);
+ net_change_destroy(change);
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Act upon queued network changes.
+ */
+static job_requeue_t reinstall_routes(private_kernel_netlink_net_t *this)
+{
+ enumerator_t *enumerator;
+ route_entry_t *route;
+
+ this->net_changes_lock->lock(this->net_changes_lock);
+ this->routes_lock->lock(this->routes_lock);
+
+ enumerator = this->routes->create_enumerator(this->routes);
+ while (enumerator->enumerate(enumerator, NULL, (void**)&route))
+ {
+ net_change_t *change, lookup = {
+ .if_name = route->if_name,
+ };
+ /* check if a change for the outgoing interface is queued */
+ change = this->net_changes->get(this->net_changes, &lookup);
+ if (!change)
+ { /* in case src_ip is not on the outgoing interface */
+ if (this->public.interface.get_interface(&this->public.interface,
+ route->src_ip, &lookup.if_name))
{
- refcount = addr->refcount;
- break;
+ if (!streq(lookup.if_name, route->if_name))
+ {
+ change = this->net_changes->get(this->net_changes, &lookup);
+ }
+ free(lookup.if_name);
}
}
- addrs->destroy(addrs);
- if (refcount)
+ if (change)
{
- break;
+ manage_srcroute(this, RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL,
+ route->dst_net, route->prefixlen, route->gateway,
+ route->src_ip, route->if_name);
}
}
- ifaces->destroy(ifaces);
+ enumerator->destroy(enumerator);
+ this->routes_lock->unlock(this->routes_lock);
+
+ net_changes_clear(this);
+ this->net_changes_lock->unlock(this->net_changes_lock);
+ return JOB_REQUEUE_NONE;
+}
+
+/**
+ * Queue route reinstallation caused by network changes for a given interface.
+ *
+ * The route reinstallation is delayed for a while and only done once for
+ * several calls during this delay, in order to avoid doing it too often.
+ * The interface name is freed.
+ */
+static void queue_route_reinstall(private_kernel_netlink_net_t *this,
+ char *if_name)
+{
+ net_change_t *update, *found;
+ timeval_t now;
+ job_t *job;
+
+ INIT(update,
+ .if_name = if_name
+ );
+
+ this->net_changes_lock->lock(this->net_changes_lock);
+ found = this->net_changes->put(this->net_changes, update, update);
+ if (found)
+ {
+ net_change_destroy(found);
+ }
+ time_monotonic(&now);
+ if (timercmp(&now, &this->last_route_reinstall, >))
+ {
+ now.tv_usec += ROUTE_DELAY * 1000;
+ while (now.tv_usec > 1000000)
+ {
+ now.tv_sec++;
+ now.tv_usec -= 1000000;
+ }
+ this->last_route_reinstall = now;
+
+ job = (job_t*)callback_job_create((callback_job_cb_t)reinstall_routes,
+ this, NULL, NULL);
+ lib->scheduler->schedule_job_ms(lib->scheduler, job, ROUTE_DELAY);
+ }
+ this->net_changes_lock->unlock(this->net_changes_lock);
+}
- return refcount;
+/**
+ * check if the given IP is known as virtual IP and currently installed
+ *
+ * this function will also return TRUE if the virtual IP entry disappeared.
+ * in that case the returned entry will be NULL.
+ *
+ * this->lock must be held when calling this function
+ */
+static bool is_vip_installed_or_gone(private_kernel_netlink_net_t *this,
+ host_t *ip, addr_map_entry_t **entry)
+{
+ addr_map_entry_t lookup = {
+ .ip = ip,
+ };
+
+ *entry = this->vips->get_match(this->vips, &lookup,
+ (void*)addr_map_entry_match);
+ if (*entry == NULL)
+ { /* the virtual IP disappeared */
+ return TRUE;
+ }
+ return (*entry)->addr->installed;
+}
+
+/**
+ * check if the given IP is known as virtual IP
+ *
+ * this->lock must be held when calling this function
+ */
+static bool is_known_vip(private_kernel_netlink_net_t *this, host_t *ip)
+{
+ addr_map_entry_t lookup = {
+ .ip = ip,
+ };
+
+ return this->vips->get_match(this->vips, &lookup,
+ (void*)addr_map_entry_match) != NULL;
+}
+
+/**
+ * Add an address map entry
+ */
+static void addr_map_entry_add(hashtable_t *map, addr_entry_t *addr,
+ iface_entry_t *iface)
+{
+ addr_map_entry_t *entry;
+
+ INIT(entry,
+ .ip = addr->ip,
+ .addr = addr,
+ .iface = iface,
+ );
+ entry = map->put(map, entry, entry);
+ free(entry);
+}
+
+/**
+ * Remove an address map entry
+ */
+static void addr_map_entry_remove(hashtable_t *map, addr_entry_t *addr,
+ iface_entry_t *iface)
+{
+ addr_map_entry_t *entry, lookup = {
+ .ip = addr->ip,
+ .addr = addr,
+ .iface = iface,
+ };
+
+ entry = map->remove(map, &lookup);
+ free(entry);
}
/**
* get the first non-virtual ip address on the given interface.
+ * if a candidate address is given, we first search for that address and if not
+ * found return the address as above.
* returned host is a clone, has to be freed by caller.
+ *
+ * this->lock must be held when calling this function
*/
static host_t *get_interface_address(private_kernel_netlink_net_t *this,
- int ifindex, int family)
+ int ifindex, int family, host_t *candidate)
{
- enumerator_t *ifaces, *addrs;
iface_entry_t *iface;
+ enumerator_t *addrs;
addr_entry_t *addr;
host_t *ip = NULL;
- this->mutex->lock(this->mutex);
- ifaces = this->ifaces->create_enumerator(this->ifaces);
- while (ifaces->enumerate(ifaces, &iface))
+ if (this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_index,
+ (void**)&iface, &ifindex) == SUCCESS)
{
- if (iface->ifindex == ifindex)
- {
+ if (iface->usable)
+ { /* only use interfaces not excluded by config */
addrs = iface->addrs->create_enumerator(iface->addrs);
while (addrs->enumerate(addrs, &addr))
{
- if (!addr->virtual && addr->ip->get_family(addr->ip) == family)
+ if (addr->refcount)
+ { /* ignore virtual IP addresses */
+ continue;
+ }
+ if (addr->ip->get_family(addr->ip) == family)
{
- ip = addr->ip->clone(addr->ip);
- break;
+ if (!candidate || candidate->ip_equals(candidate, addr->ip))
+ { /* stop at the first address if we don't search for a
+ * candidate or if the candidate matches */
+ ip = addr->ip;
+ break;
+ }
+ else if (!ip)
+ { /* store the first address as fallback if candidate is
+ * not found */
+ ip = addr->ip;
+ }
}
}
addrs->destroy(addrs);
- break;
}
}
- ifaces->destroy(ifaces);
- this->mutex->unlock(this->mutex);
- return ip;
+ return ip ? ip->clone(ip) : NULL;
}
/**
@@ -277,21 +698,60 @@ static void fire_roam_event(private_kernel_netlink_net_t *this, bool address)
job_t *job;
time_monotonic(&now);
- if (timercmp(&now, &this->last_roam, >))
+ this->roam_lock->lock(this->roam_lock);
+ if (!timercmp(&now, &this->next_roam, >))
{
- now.tv_usec += ROAM_DELAY * 1000;
- while (now.tv_usec > 1000000)
- {
- now.tv_sec++;
- now.tv_usec -= 1000000;
- }
- this->last_roam = now;
+ this->roam_lock->unlock(this->roam_lock);
+ return;
+ }
+ now.tv_usec += ROAM_DELAY * 1000;
+ while (now.tv_usec > 1000000)
+ {
+ now.tv_sec++;
+ now.tv_usec -= 1000000;
+ }
+ this->next_roam = now;
+ this->roam_lock->unlock(this->roam_lock);
+
+ job = (job_t*)callback_job_create((callback_job_cb_t)roam_event,
+ (void*)(uintptr_t)(address ? 1 : 0),
+ NULL, NULL);
+ lib->scheduler->schedule_job_ms(lib->scheduler, job, ROAM_DELAY);
+}
- job = (job_t*)callback_job_create((callback_job_cb_t)roam_event,
- (void*)(uintptr_t)(address ? 1 : 0),
- NULL, NULL);
- lib->scheduler->schedule_job_ms(lib->scheduler, job, ROAM_DELAY);
+/**
+ * check if an interface with a given index is up and usable
+ *
+ * this->lock must be locked when calling this function
+ */
+static bool is_interface_up_and_usable(private_kernel_netlink_net_t *this,
+ int index)
+{
+ iface_entry_t *iface;
+
+ if (this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_index,
+ (void**)&iface, &index) == SUCCESS)
+ {
+ return iface_entry_up_and_usable(iface);
+ }
+ return FALSE;
+}
+
+/**
+ * unregister the current addr_entry_t from the hashtable it is stored in
+ *
+ * this->lock must be locked when calling this function
+ */
+static void addr_entry_unregister(addr_entry_t *addr, iface_entry_t *iface,
+ private_kernel_netlink_net_t *this)
+{
+ if (addr->refcount)
+ {
+ addr_map_entry_remove(this->vips, addr, iface);
+ this->condvar->broadcast(this->condvar);
+ return;
}
+ addr_map_entry_remove(this->addrs, addr, iface);
}
/**
@@ -306,9 +766,9 @@ static void process_link(private_kernel_netlink_net_t *this,
enumerator_t *enumerator;
iface_entry_t *current, *entry = NULL;
char *name = NULL;
- bool update = FALSE;
+ bool update = FALSE, update_routes = FALSE;
- while(RTA_OK(rta, rtasize))
+ while (RTA_OK(rta, rtasize))
{
switch (rta->rta_type)
{
@@ -323,40 +783,30 @@ static void process_link(private_kernel_netlink_net_t *this,
name = "(unknown)";
}
- this->mutex->lock(this->mutex);
+ this->lock->write_lock(this->lock);
switch (hdr->nlmsg_type)
{
case RTM_NEWLINK:
{
- if (msg->ifi_flags & IFF_LOOPBACK)
- { /* ignore loopback interfaces */
- break;
- }
- enumerator = this->ifaces->create_enumerator(this->ifaces);
- while (enumerator->enumerate(enumerator, &current))
- {
- if (current->ifindex == msg->ifi_index)
- {
- entry = current;
- break;
- }
- }
- enumerator->destroy(enumerator);
- if (!entry)
+ if (this->ifaces->find_first(this->ifaces,
+ (void*)iface_entry_by_index, (void**)&entry,
+ &msg->ifi_index) != SUCCESS)
{
- entry = malloc_thing(iface_entry_t);
- entry->ifindex = msg->ifi_index;
- entry->flags = 0;
- entry->addrs = linked_list_create();
+ INIT(entry,
+ .ifindex = msg->ifi_index,
+ .addrs = linked_list_create(),
+ .usable = hydra->kernel_interface->is_interface_usable(
+ hydra->kernel_interface, name),
+ );
this->ifaces->insert_last(this->ifaces, entry);
}
strncpy(entry->ifname, name, IFNAMSIZ);
entry->ifname[IFNAMSIZ-1] = '\0';
- if (event)
+ if (event && entry->usable)
{
if (!(entry->flags & IFF_UP) && (msg->ifi_flags & IFF_UP))
{
- update = TRUE;
+ update = update_routes = TRUE;
DBG1(DBG_KNL, "interface %s activated", name);
}
if ((entry->flags & IFF_UP) && !(msg->ifi_flags & IFF_UP))
@@ -375,12 +825,16 @@ static void process_link(private_kernel_netlink_net_t *this,
{
if (current->ifindex == msg->ifi_index)
{
- if (event)
+ if (event && current->usable)
{
update = TRUE;
DBG1(DBG_KNL, "interface %s deleted", current->ifname);
}
+ /* TODO: move virtual IPs installed on this interface to
+ * another interface? */
this->ifaces->remove_at(this->ifaces, enumerator);
+ current->addrs->invoke_function(current->addrs,
+ (void*)addr_entry_unregister, current, this);
iface_entry_destroy(current);
break;
}
@@ -389,9 +843,13 @@ static void process_link(private_kernel_netlink_net_t *this,
break;
}
}
- this->mutex->unlock(this->mutex);
+ this->lock->unlock(this->lock);
+
+ if (update_routes && event)
+ {
+ queue_route_reinstall(this, strdup(name));
+ }
- /* send an update to all IKE_SAs */
if (update && event)
{
fire_roam_event(this, TRUE);
@@ -408,13 +866,12 @@ static void process_addr(private_kernel_netlink_net_t *this,
struct rtattr *rta = IFA_RTA(msg);
size_t rtasize = IFA_PAYLOAD (hdr);
host_t *host = NULL;
- enumerator_t *ifaces, *addrs;
iface_entry_t *iface;
- addr_entry_t *addr;
chunk_t local = chunk_empty, address = chunk_empty;
+ char *route_ifname = NULL;
bool update = FALSE, found = FALSE, changed = FALSE;
- while(RTA_OK(rta, rtasize))
+ while (RTA_OK(rta, rtasize))
{
switch (rta->rta_type)
{
@@ -447,65 +904,92 @@ static void process_addr(private_kernel_netlink_net_t *this,
return;
}
- this->mutex->lock(this->mutex);
- ifaces = this->ifaces->create_enumerator(this->ifaces);
- while (ifaces->enumerate(ifaces, &iface))
+ this->lock->write_lock(this->lock);
+ if (this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_index,
+ (void**)&iface, &msg->ifa_index) == SUCCESS)
{
- if (iface->ifindex == msg->ifa_index)
+ addr_map_entry_t *entry, lookup = {
+ .ip = host,
+ .iface = iface,
+ };
+ addr_entry_t *addr;
+
+ entry = this->vips->get(this->vips, &lookup);
+ if (entry)
{
- addrs = iface->addrs->create_enumerator(iface->addrs);
- while (addrs->enumerate(addrs, &addr))
+ if (hdr->nlmsg_type == RTM_NEWADDR)
+ { /* mark as installed and signal waiting threads */
+ entry->addr->installed = TRUE;
+ }
+ else
+ { /* the address was already marked as uninstalled */
+ addr = entry->addr;
+ iface->addrs->remove(iface->addrs, addr, NULL);
+ addr_map_entry_remove(this->vips, addr, iface);
+ addr_entry_destroy(addr);
+ }
+ /* no roam events etc. for virtual IPs */
+ this->condvar->broadcast(this->condvar);
+ this->lock->unlock(this->lock);
+ host->destroy(host);
+ return;
+ }
+ entry = this->addrs->get(this->addrs, &lookup);
+ if (entry)
+ {
+ if (hdr->nlmsg_type == RTM_DELADDR)
{
- if (host->ip_equals(host, addr->ip))
+ found = TRUE;
+ addr = entry->addr;
+ iface->addrs->remove(iface->addrs, addr, NULL);
+ if (iface->usable)
{
- found = TRUE;
- if (hdr->nlmsg_type == RTM_DELADDR)
- {
- iface->addrs->remove_at(iface->addrs, addrs);
- if (!addr->virtual)
- {
- changed = TRUE;
- DBG1(DBG_KNL, "%H disappeared from %s",
- host, iface->ifname);
- }
- addr_entry_destroy(addr);
- }
- else if (hdr->nlmsg_type == RTM_NEWADDR && addr->virtual)
- {
- addr->refcount = 1;
- }
+ changed = TRUE;
+ DBG1(DBG_KNL, "%H disappeared from %s", host,
+ iface->ifname);
}
+ addr_map_entry_remove(this->addrs, addr, iface);
+ addr_entry_destroy(addr);
}
- addrs->destroy(addrs);
-
+ }
+ else
+ {
if (hdr->nlmsg_type == RTM_NEWADDR)
{
- if (!found)
+ found = TRUE;
+ changed = TRUE;
+ route_ifname = strdup(iface->ifname);
+ INIT(addr,
+ .ip = host->clone(host),
+ .scope = msg->ifa_scope,
+ );
+ iface->addrs->insert_last(iface->addrs, addr);
+ addr_map_entry_add(this->addrs, addr, iface);
+ if (event && iface->usable)
{
- found = TRUE;
- changed = TRUE;
- addr = malloc_thing(addr_entry_t);
- addr->ip = host->clone(host);
- addr->virtual = FALSE;
- addr->refcount = 1;
- addr->scope = msg->ifa_scope;
-
- iface->addrs->insert_last(iface->addrs, addr);
- if (event)
- {
- DBG1(DBG_KNL, "%H appeared on %s", host, iface->ifname);
- }
+ DBG1(DBG_KNL, "%H appeared on %s", host, iface->ifname);
}
}
- if (found && (iface->flags & IFF_UP))
- {
- update = TRUE;
- }
- break;
+ }
+ if (found && (iface->flags & IFF_UP))
+ {
+ update = TRUE;
+ }
+ if (!iface->usable)
+ { /* ignore events for interfaces excluded by config */
+ update = changed = FALSE;
}
}
- ifaces->destroy(ifaces);
- this->mutex->unlock(this->mutex);
+ this->lock->unlock(this->lock);
+
+ if (update && event && route_ifname)
+ {
+ queue_route_reinstall(this, route_ifname);
+ }
+ else
+ {
+ free(route_ifname);
+ }
host->destroy(host);
/* send an update to all IKE_SAs */
@@ -532,6 +1016,10 @@ static void process_route(private_kernel_netlink_net_t *this, struct nlmsghdr *h
{
return;
}
+ else if (msg->rtm_flags & RTM_F_CLONED)
+ { /* ignore cached routes, seem to be created a lot for IPv6 */
+ return;
+ }
while (RTA_OK(rta, rtasize))
{
@@ -551,20 +1039,26 @@ static void process_route(private_kernel_netlink_net_t *this, struct nlmsghdr *h
}
rta = RTA_NEXT(rta, rtasize);
}
+ this->lock->read_lock(this->lock);
+ if (rta_oif && !is_interface_up_and_usable(this, rta_oif))
+ { /* ignore route changes for interfaces that are ignored or down */
+ this->lock->unlock(this->lock);
+ DESTROY_IF(host);
+ return;
+ }
if (!host && rta_oif)
{
- host = get_interface_address(this, rta_oif, msg->rtm_family);
+ host = get_interface_address(this, rta_oif, msg->rtm_family, NULL);
}
- if (host)
- {
- this->mutex->lock(this->mutex);
- if (!get_vip_refcount(this, host))
- { /* ignore routes added for virtual IPs */
- fire_roam_event(this, FALSE);
- }
- this->mutex->unlock(this->mutex);
- host->destroy(host);
+ if (!host || is_known_vip(this, host))
+ { /* ignore routes added for virtual IPs */
+ this->lock->unlock(this->lock);
+ DESTROY_IF(host);
+ return;
}
+ this->lock->unlock(this->lock);
+ fire_roam_event(this, FALSE);
+ host->destroy(host);
}
/**
@@ -614,12 +1108,10 @@ static job_requeue_t receive_events(private_kernel_netlink_net_t *this)
case RTM_NEWADDR:
case RTM_DELADDR:
process_addr(this, hdr, TRUE);
- this->condvar->broadcast(this->condvar);
break;
case RTM_NEWLINK:
case RTM_DELLINK:
process_link(this, hdr, TRUE);
- this->condvar->broadcast(this->condvar);
break;
case RTM_NEWROUTE:
case RTM_DELROUTE:
@@ -639,10 +1131,8 @@ static job_requeue_t receive_events(private_kernel_netlink_net_t *this)
/** enumerator over addresses */
typedef struct {
private_kernel_netlink_net_t* this;
- /** whether to enumerate down interfaces */
- bool include_down_ifaces;
- /** whether to enumerate virtual ip addresses */
- bool include_virtual_ips;
+ /** which addresses to enumerate */
+ kernel_address_type_t which;
} address_enumerator_t;
/**
@@ -650,7 +1140,7 @@ typedef struct {
*/
static void address_enumerator_destroy(address_enumerator_t *data)
{
- data->this->mutex->unlock(data->this->mutex);
+ data->this->lock->unlock(data->this->lock);
free(data);
}
@@ -660,7 +1150,7 @@ static void address_enumerator_destroy(address_enumerator_t *data)
static bool filter_addresses(address_enumerator_t *data,
addr_entry_t** in, host_t** out)
{
- if (!data->include_virtual_ips && (*in)->virtual)
+ if (!(data->which & ADDR_TYPE_VIRTUAL) && (*in)->refcount)
{ /* skip virtual interfaces added by us */
return FALSE;
}
@@ -689,7 +1179,15 @@ static enumerator_t *create_iface_enumerator(iface_entry_t *iface,
static bool filter_interfaces(address_enumerator_t *data, iface_entry_t** in,
iface_entry_t** out)
{
- if (!data->include_down_ifaces && !((*in)->flags & IFF_UP))
+ if (!(data->which & ADDR_TYPE_IGNORED) && !(*in)->usable)
+ { /* skip interfaces excluded by config */
+ return FALSE;
+ }
+ if (!(data->which & ADDR_TYPE_LOOPBACK) && ((*in)->flags & IFF_LOOPBACK))
+ { /* ignore loopback devices */
+ return FALSE;
+ }
+ if (!(data->which & ADDR_TYPE_DOWN) && !((*in)->flags & IFF_UP))
{ /* skip interfaces not up */
return FALSE;
}
@@ -698,15 +1196,13 @@ static bool filter_interfaces(address_enumerator_t *data, iface_entry_t** in,
}
METHOD(kernel_net_t, create_address_enumerator, enumerator_t*,
- private_kernel_netlink_net_t *this,
- bool include_down_ifaces, bool include_virtual_ips)
+ private_kernel_netlink_net_t *this, kernel_address_type_t which)
{
address_enumerator_t *data = malloc_thing(address_enumerator_t);
data->this = this;
- data->include_down_ifaces = include_down_ifaces;
- data->include_virtual_ips = include_virtual_ips;
+ data->which = which;
- this->mutex->lock(this->mutex);
+ this->lock->read_lock(this->lock);
return enumerator_create_nested(
enumerator_create_filter(
this->ifaces->create_enumerator(this->ifaces),
@@ -715,47 +1211,40 @@ METHOD(kernel_net_t, create_address_enumerator, enumerator_t*,
(void*)address_enumerator_destroy);
}
-METHOD(kernel_net_t, get_interface_name, char*,
- private_kernel_netlink_net_t *this, host_t* ip)
+METHOD(kernel_net_t, get_interface_name, bool,
+ private_kernel_netlink_net_t *this, host_t* ip, char **name)
{
- enumerator_t *ifaces, *addrs;
- iface_entry_t *iface;
- addr_entry_t *addr;
- char *name = NULL;
+ addr_map_entry_t *entry, lookup = {
+ .ip = ip,
+ };
- DBG2(DBG_KNL, "getting interface name for %H", ip);
-
- this->mutex->lock(this->mutex);
- ifaces = this->ifaces->create_enumerator(this->ifaces);
- while (ifaces->enumerate(ifaces, &iface))
+ if (ip->is_anyaddr(ip))
+ {
+ return FALSE;
+ }
+ this->lock->read_lock(this->lock);
+ /* first try to find it on an up and usable interface */
+ entry = this->addrs->get_match(this->addrs, &lookup,
+ (void*)addr_map_entry_match_up_and_usable);
+ if (entry)
{
- addrs = iface->addrs->create_enumerator(iface->addrs);
- while (addrs->enumerate(addrs, &addr))
- {
- if (ip->ip_equals(ip, addr->ip))
- {
- name = strdup(iface->ifname);
- break;
- }
- }
- addrs->destroy(addrs);
if (name)
{
- break;
+ *name = strdup(entry->iface->ifname);
+ DBG2(DBG_KNL, "%H is on interface %s", ip, *name);
}
+ this->lock->unlock(this->lock);
+ return TRUE;
}
- ifaces->destroy(ifaces);
- this->mutex->unlock(this->mutex);
-
- if (name)
- {
- DBG2(DBG_KNL, "%H is on interface %s", ip, name);
- }
- else
+ /* maybe it is installed on an ignored interface */
+ entry = this->addrs->get_match(this->addrs, &lookup,
+ (void*)addr_map_entry_match_up);
+ if (!entry)
{
- DBG2(DBG_KNL, "%H is not a local address", ip);
+ DBG2(DBG_KNL, "%H is not a local address or the interface is down", ip);
}
- return name;
+ this->lock->unlock(this->lock);
+ return FALSE;
}
/**
@@ -763,24 +1252,18 @@ METHOD(kernel_net_t, get_interface_name, char*,
*/
static int get_interface_index(private_kernel_netlink_net_t *this, char* name)
{
- enumerator_t *ifaces;
iface_entry_t *iface;
int ifindex = 0;
DBG2(DBG_KNL, "getting iface index for %s", name);
- this->mutex->lock(this->mutex);
- ifaces = this->ifaces->create_enumerator(this->ifaces);
- while (ifaces->enumerate(ifaces, &iface))
+ this->lock->read_lock(this->lock);
+ if (this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_name,
+ (void**)&iface, name) == SUCCESS)
{
- if (streq(name, iface->ifname))
- {
- ifindex = iface->ifindex;
- break;
- }
+ ifindex = iface->ifindex;
}
- ifaces->destroy(ifaces);
- this->mutex->unlock(this->mutex);
+ this->lock->unlock(this->lock);
if (ifindex == 0)
{
@@ -790,29 +1273,6 @@ static int get_interface_index(private_kernel_netlink_net_t *this, char* name)
}
/**
- * Check if an interface with a given index is up
- */
-static bool is_interface_up(private_kernel_netlink_net_t *this, int index)
-{
- enumerator_t *ifaces;
- iface_entry_t *iface;
- /* default to TRUE for interface we do not monitor (e.g. lo) */
- bool up = TRUE;
-
- ifaces = this->ifaces->create_enumerator(this->ifaces);
- while (ifaces->enumerate(ifaces, &iface))
- {
- if (iface->ifindex == index)
- {
- up = iface->flags & IFF_UP;
- break;
- }
- }
- ifaces->destroy(ifaces);
- return up;
-}
-
-/**
* check if an address (chunk) addr is in subnet (net with net_len net bits)
*/
static bool addr_in_subnet(chunk_t addr, chunk_t net, int net_len)
@@ -849,6 +1309,94 @@ static bool addr_in_subnet(chunk_t addr, chunk_t net, int net_len)
}
/**
+ * Store information about a route retrieved via RTNETLINK
+ */
+typedef struct {
+ chunk_t gtw;
+ chunk_t src;
+ chunk_t dst;
+ host_t *src_host;
+ u_int8_t dst_len;
+ u_int32_t table;
+ u_int32_t oif;
+} rt_entry_t;
+
+/**
+ * Free a route entry
+ */
+static void rt_entry_destroy(rt_entry_t *this)
+{
+ DESTROY_IF(this->src_host);
+ free(this);
+}
+
+/**
+ * Parse route received with RTM_NEWROUTE. The given rt_entry_t object will be
+ * reused if not NULL.
+ *
+ * Returned chunks point to internal data of the Netlink message.
+ */
+static rt_entry_t *parse_route(struct nlmsghdr *hdr, rt_entry_t *route)
+{
+ struct rtattr *rta;
+ struct rtmsg *msg;
+ size_t rtasize;
+
+ msg = (struct rtmsg*)(NLMSG_DATA(hdr));
+ rta = RTM_RTA(msg);
+ rtasize = RTM_PAYLOAD(hdr);
+
+ if (route)
+ {
+ route->gtw = chunk_empty;
+ route->src = chunk_empty;
+ route->dst = chunk_empty;
+ route->dst_len = msg->rtm_dst_len;
+ route->table = msg->rtm_table;
+ route->oif = 0;
+ }
+ else
+ {
+ INIT(route,
+ .dst_len = msg->rtm_dst_len,
+ .table = msg->rtm_table,
+ );
+ }
+
+ while (RTA_OK(rta, rtasize))
+ {
+ switch (rta->rta_type)
+ {
+ case RTA_PREFSRC:
+ route->src = chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta));
+ break;
+ case RTA_GATEWAY:
+ route->gtw = chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta));
+ break;
+ case RTA_DST:
+ route->dst = chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta));
+ break;
+ case RTA_OIF:
+ if (RTA_PAYLOAD(rta) == sizeof(route->oif))
+ {
+ route->oif = *(u_int32_t*)RTA_DATA(rta);
+ }
+ break;
+#ifdef HAVE_RTA_TABLE
+ case RTA_TABLE:
+ if (RTA_PAYLOAD(rta) == sizeof(route->table))
+ {
+ route->table = *(u_int32_t*)RTA_DATA(rta);
+ }
+ break;
+#endif /* HAVE_RTA_TABLE*/
+ }
+ rta = RTA_NEXT(rta, rtasize);
+ }
+ return route;
+}
+
+/**
* Get a route: If "nexthop", the nexthop is returned. source addr otherwise.
*/
static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
@@ -859,22 +1407,21 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
struct rtmsg *msg;
chunk_t chunk;
size_t len;
- int best = -1;
+ linked_list_t *routes;
+ rt_entry_t *route = NULL, *best = NULL;
enumerator_t *enumerator;
- host_t *src = NULL, *gtw = NULL;
-
- DBG2(DBG_KNL, "getting address to reach %H", dest);
+ host_t *addr = NULL;
memset(&request, 0, sizeof(request));
hdr = (struct nlmsghdr*)request;
hdr->nlmsg_flags = NLM_F_REQUEST;
- if (dest->get_family(dest) == AF_INET)
- {
- /* We dump all addresses for IPv4, as we want to ignore IPsec specific
- * routes installed by us. But the kernel does not return source
- * addresses in a IPv6 dump, so fall back to get() for v6 routes. */
- hdr->nlmsg_flags |= NLM_F_ROOT | NLM_F_DUMP;
+ if (dest->get_family(dest) == AF_INET || this->rta_prefsrc_for_ipv6 ||
+ this->routing_table)
+ { /* 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));
@@ -891,10 +1438,12 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
if (this->socket->send(this->socket, hdr, &out, &len) != SUCCESS)
{
- DBG1(DBG_KNL, "getting address to %H failed", dest);
+ DBG2(DBG_KNL, "getting %s to reach %H failed",
+ nexthop ? "nexthop" : "address", dest);
return NULL;
}
- this->mutex->lock(this->mutex);
+ routes = linked_list_create();
+ this->lock->read_lock(this->lock);
for (current = out; NLMSG_OK(current, len);
current = NLMSG_NEXT(current, len))
@@ -905,132 +1454,53 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
break;
case RTM_NEWROUTE:
{
- struct rtattr *rta;
- size_t rtasize;
- chunk_t rta_gtw, rta_src, rta_dst;
- u_int32_t rta_oif = 0, rta_table;
- host_t *new_src, *new_gtw;
- bool cont = FALSE;
+ rt_entry_t *other;
uintptr_t table;
- rta_gtw = rta_src = rta_dst = chunk_empty;
- msg = (struct rtmsg*)(NLMSG_DATA(current));
- rta = RTM_RTA(msg);
- rtasize = RTM_PAYLOAD(current);
- rta_table = msg->rtm_table;
- while (RTA_OK(rta, rtasize))
- {
- switch (rta->rta_type)
- {
- case RTA_PREFSRC:
- rta_src = chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta));
- break;
- case RTA_GATEWAY:
- rta_gtw = chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta));
- break;
- case RTA_DST:
- rta_dst = chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta));
- break;
- case RTA_OIF:
- if (RTA_PAYLOAD(rta) == sizeof(rta_oif))
- {
- rta_oif = *(u_int32_t*)RTA_DATA(rta);
- }
- break;
-#ifdef HAVE_RTA_TABLE
- case RTA_TABLE:
- if (RTA_PAYLOAD(rta) == sizeof(rta_table))
- {
- rta_table = *(u_int32_t*)RTA_DATA(rta);
- }
- break;
-#endif /* HAVE_RTA_TABLE*/
- }
- rta = RTA_NEXT(rta, rtasize);
- }
- if (msg->rtm_dst_len <= best)
- { /* not better than a previous one */
- continue;
- }
- enumerator = this->rt_exclude->create_enumerator(this->rt_exclude);
- while (enumerator->enumerate(enumerator, &table))
- {
- if (table == rta_table)
- {
- cont = TRUE;
- break;
- }
- }
- enumerator->destroy(enumerator);
- if (cont)
- {
+ route = parse_route(current, route);
+
+ table = (uintptr_t)route->table;
+ if (this->rt_exclude->find_first(this->rt_exclude, NULL,
+ (void**)&table) == SUCCESS)
+ { /* route is from an excluded routing table */
continue;
}
if (this->routing_table != 0 &&
- rta_table == this->routing_table)
+ route->table == this->routing_table)
{ /* route is from our own ipsec routing table */
continue;
}
- if (rta_oif && !is_interface_up(this, rta_oif))
+ if (route->oif && !is_interface_up_and_usable(this, route->oif))
{ /* interface is down */
continue;
}
- if (!addr_in_subnet(chunk, rta_dst, msg->rtm_dst_len))
+ if (!addr_in_subnet(chunk, route->dst, route->dst_len))
{ /* route destination does not contain dest */
continue;
}
-
- if (nexthop)
- {
- /* nexthop lookup, return gateway if any */
- DESTROY_IF(gtw);
- gtw = host_create_from_chunk(msg->rtm_family, rta_gtw, 0);
- best = msg->rtm_dst_len;
- continue;
- }
- if (rta_src.ptr)
- { /* got a source address */
- new_src = host_create_from_chunk(msg->rtm_family, rta_src, 0);
- if (new_src)
- {
- if (get_vip_refcount(this, new_src))
- { /* skip source address if it is installed by us */
- new_src->destroy(new_src);
- }
- else
- {
- DESTROY_IF(src);
- src = new_src;
- best = msg->rtm_dst_len;
- }
- }
- continue;
- }
- if (rta_oif)
- { /* no src or gtw, but an interface. Get address from it. */
- new_src = get_interface_address(this, rta_oif,
- msg->rtm_family);
- if (new_src)
- {
- DESTROY_IF(src);
- src = new_src;
- best = msg->rtm_dst_len;
+ if (route->src.ptr)
+ { /* verify source address, if any */
+ host_t *src = host_create_from_chunk(msg->rtm_family,
+ route->src, 0);
+ if (src && is_known_vip(this, src))
+ { /* ignore routes installed by us */
+ src->destroy(src);
+ continue;
}
- continue;
+ route->src_host = src;
}
- if (rta_gtw.ptr)
- { /* no source, but a gateway. Lookup source to reach gtw. */
- new_gtw = host_create_from_chunk(msg->rtm_family, rta_gtw, 0);
- new_src = get_route(this, new_gtw, FALSE, candidate);
- new_gtw->destroy(new_gtw);
- if (new_src)
+ /* insert route, sorted by decreasing network prefix */
+ enumerator = routes->create_enumerator(routes);
+ while (enumerator->enumerate(enumerator, &other))
+ {
+ if (route->dst_len > other->dst_len)
{
- DESTROY_IF(src);
- src = new_src;
- best = msg->rtm_dst_len;
+ break;
}
- continue;
}
+ routes->insert_before(routes, enumerator, route);
+ enumerator->destroy(enumerator);
+ route = NULL;
continue;
}
default:
@@ -1038,18 +1508,111 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
}
break;
}
- free(out);
- this->mutex->unlock(this->mutex);
+ if (route)
+ {
+ rt_entry_destroy(route);
+ }
+
+ /* now we have a list of routes matching dest, sorted by net prefix.
+ * we will look for source addresses for these routes and select the one
+ * with the preferred source address, if possible */
+ enumerator = routes->create_enumerator(routes);
+ while (enumerator->enumerate(enumerator, &route))
+ {
+ if (route->src_host)
+ { /* got a source address with the route, if no preferred source
+ * is given or it matches we are done, as this is the best route */
+ if (!candidate || candidate->ip_equals(candidate, route->src_host))
+ {
+ best = route;
+ break;
+ }
+ else if (route->oif)
+ { /* no match yet, maybe it is assigned to the same interface */
+ host_t *src = get_interface_address(this, route->oif,
+ msg->rtm_family, candidate);
+ if (src && src->ip_equals(src, candidate))
+ {
+ route->src_host->destroy(route->src_host);
+ route->src_host = src;
+ best = route;
+ break;
+ }
+ DESTROY_IF(src);
+ }
+ /* no luck yet with the source address. if this is the best (first)
+ * route we store it as fallback in case we don't find a route with
+ * the preferred source */
+ best = best ?: route;
+ continue;
+ }
+ if (route->oif)
+ { /* no src, but an interface - get address from it */
+ route->src_host = get_interface_address(this, route->oif,
+ msg->rtm_family, candidate);
+ if (route->src_host)
+ { /* we handle this address the same as the one above */
+ if (!candidate ||
+ candidate->ip_equals(candidate, route->src_host))
+ {
+ best = route;
+ break;
+ }
+ best = best ?: route;
+ continue;
+ }
+ }
+ if (route->gtw.ptr)
+ { /* no src, no iface, but a gateway - lookup src to reach gtw */
+ host_t *gtw;
+
+ gtw = host_create_from_chunk(msg->rtm_family, route->gtw, 0);
+ route->src_host = get_route(this, gtw, FALSE, candidate);
+ gtw->destroy(gtw);
+ if (route->src_host)
+ { /* more of the same */
+ if (!candidate ||
+ candidate->ip_equals(candidate, route->src_host))
+ {
+ best = route;
+ break;
+ }
+ best = best ?: route;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
if (nexthop)
+ { /* nexthop lookup, return gateway if any */
+ if (best || routes->get_first(routes, (void**)&best) == SUCCESS)
+ {
+ addr = host_create_from_chunk(msg->rtm_family, best->gtw, 0);
+ }
+ addr = addr ?: dest->clone(dest);
+ }
+ else
{
- if (gtw)
+ if (best)
{
- return gtw;
+ addr = best->src_host->clone(best->src_host);
}
- return dest->clone(dest);
}
- return src;
+ this->lock->unlock(this->lock);
+ routes->destroy_function(routes, (void*)rt_entry_destroy);
+ free(out);
+
+ if (addr)
+ {
+ DBG2(DBG_KNL, "using %H as %s to reach %H", addr,
+ nexthop ? "nexthop" : "address", dest);
+ }
+ else
+ {
+ DBG2(DBG_KNL, "no %s found to reach %H",
+ nexthop ? "nexthop" : "address", dest);
+ }
+ return addr;
}
METHOD(kernel_net_t, get_source_addr, host_t*,
@@ -1059,9 +1622,9 @@ METHOD(kernel_net_t, get_source_addr, host_t*,
}
METHOD(kernel_net_t, get_nexthop, host_t*,
- private_kernel_netlink_net_t *this, host_t *dest)
+ private_kernel_netlink_net_t *this, host_t *dest, host_t *src)
{
- return get_route(this, dest, TRUE, NULL);
+ return get_route(this, dest, TRUE, src);
}
/**
@@ -1100,87 +1663,109 @@ static status_t manage_ipaddr(private_kernel_netlink_net_t *this, int nlmsg_type
METHOD(kernel_net_t, add_ip, status_t,
private_kernel_netlink_net_t *this, host_t *virtual_ip, host_t *iface_ip)
{
- iface_entry_t *iface;
- addr_entry_t *addr;
- enumerator_t *addrs, *ifaces;
- int ifindex;
+ addr_map_entry_t *entry, lookup = {
+ .ip = virtual_ip,
+ };
+ iface_entry_t *iface = NULL;
if (!this->install_virtual_ip)
{ /* disabled by config */
return SUCCESS;
}
- DBG2(DBG_KNL, "adding virtual IP %H", virtual_ip);
-
- this->mutex->lock(this->mutex);
- ifaces = this->ifaces->create_enumerator(this->ifaces);
- while (ifaces->enumerate(ifaces, &iface))
- {
- bool iface_found = FALSE;
-
- addrs = iface->addrs->create_enumerator(iface->addrs);
- while (addrs->enumerate(addrs, &addr))
- {
- if (iface_ip->ip_equals(iface_ip, addr->ip))
+ this->lock->write_lock(this->lock);
+ /* the virtual IP might actually be installed as regular IP, in which case
+ * we don't track it as virtual IP */
+ entry = this->addrs->get_match(this->addrs, &lookup,
+ (void*)addr_map_entry_match);
+ if (!entry)
+ { /* otherwise it might already be installed as virtual IP */
+ entry = this->vips->get_match(this->vips, &lookup,
+ (void*)addr_map_entry_match);
+ if (entry)
+ { /* the vip we found can be in one of three states: 1) installed and
+ * ready, 2) just added by another thread, but not yet confirmed to
+ * be installed by the kernel, 3) just deleted, but not yet gone.
+ * Then while we wait below, several things could happen (as we
+ * release the lock). For instance, the interface could disappear,
+ * or the IP is finally deleted, and it reappears on a different
+ * interface. All these cases are handled by the call below. */
+ while (!is_vip_installed_or_gone(this, virtual_ip, &entry))
{
- iface_found = TRUE;
+ this->condvar->wait(this->condvar, this->lock);
}
- else if (virtual_ip->ip_equals(virtual_ip, addr->ip))
+ if (entry)
{
- addr->refcount++;
- DBG2(DBG_KNL, "virtual IP %H already installed on %s",
- virtual_ip, iface->ifname);
- addrs->destroy(addrs);
- ifaces->destroy(ifaces);
- this->mutex->unlock(this->mutex);
- return SUCCESS;
+ entry->addr->refcount++;
}
}
- addrs->destroy(addrs);
-
- if (iface_found)
+ }
+ if (entry)
+ {
+ DBG2(DBG_KNL, "virtual IP %H is already installed on %s", virtual_ip,
+ entry->iface->ifname);
+ this->lock->unlock(this->lock);
+ return SUCCESS;
+ }
+ /* try to find the target interface, either by config or via src ip */
+ if (!this->install_virtual_ip_on ||
+ this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_name,
+ (void**)&iface, this->install_virtual_ip_on) != SUCCESS)
+ {
+ lookup.ip = iface_ip;
+ entry = this->addrs->get_match(this->addrs, &lookup,
+ (void*)addr_map_entry_match);
+ if (!entry)
+ { /* if we don't find the requested interface we just use the first */
+ this->ifaces->get_first(this->ifaces, (void**)&iface);
+ }
+ else
{
- ifindex = iface->ifindex;
- addr = malloc_thing(addr_entry_t);
- addr->ip = virtual_ip->clone(virtual_ip);
- addr->refcount = 0;
- addr->virtual = TRUE;
- addr->scope = RT_SCOPE_UNIVERSE;
- iface->addrs->insert_last(iface->addrs, addr);
-
- if (manage_ipaddr(this, RTM_NEWADDR, NLM_F_CREATE | NLM_F_EXCL,
- ifindex, virtual_ip) == SUCCESS)
- {
- while (get_vip_refcount(this, virtual_ip) == 0)
- { /* wait until address appears */
- this->condvar->wait(this->condvar, this->mutex);
- }
- ifaces->destroy(ifaces);
- this->mutex->unlock(this->mutex);
+ iface = entry->iface;
+ }
+ }
+ if (iface)
+ {
+ addr_entry_t *addr;
+
+ INIT(addr,
+ .ip = virtual_ip->clone(virtual_ip),
+ .refcount = 1,
+ .scope = RT_SCOPE_UNIVERSE,
+ );
+ iface->addrs->insert_last(iface->addrs, addr);
+ addr_map_entry_add(this->vips, addr, iface);
+ if (manage_ipaddr(this, RTM_NEWADDR, NLM_F_CREATE | NLM_F_EXCL,
+ iface->ifindex, virtual_ip) == SUCCESS)
+ {
+ while (!is_vip_installed_or_gone(this, virtual_ip, &entry))
+ { /* wait until address appears */
+ this->condvar->wait(this->condvar, this->lock);
+ }
+ if (entry)
+ { /* we fail if the interface got deleted in the meantime */
+ DBG2(DBG_KNL, "virtual IP %H installed on %s", virtual_ip,
+ entry->iface->ifname);
+ this->lock->unlock(this->lock);
return SUCCESS;
}
- ifaces->destroy(ifaces);
- this->mutex->unlock(this->mutex);
- DBG1(DBG_KNL, "adding virtual IP %H failed", virtual_ip);
- return FAILED;
}
+ this->lock->unlock(this->lock);
+ DBG1(DBG_KNL, "adding virtual IP %H failed", virtual_ip);
+ return FAILED;
}
- ifaces->destroy(ifaces);
- this->mutex->unlock(this->mutex);
-
- DBG1(DBG_KNL, "interface address %H not found, unable to install"
- "virtual IP %H", iface_ip, virtual_ip);
+ this->lock->unlock(this->lock);
+ DBG1(DBG_KNL, "no interface available, unable to install virtual IP %H",
+ virtual_ip);
return FAILED;
}
METHOD(kernel_net_t, del_ip, status_t,
private_kernel_netlink_net_t *this, host_t *virtual_ip)
{
- iface_entry_t *iface;
- addr_entry_t *addr;
- enumerator_t *addrs, *ifaces;
- status_t status;
- int ifindex;
+ addr_map_entry_t *entry, lookup = {
+ .ip = virtual_ip,
+ };
if (!this->install_virtual_ip)
{ /* disabled by config */
@@ -1189,60 +1774,61 @@ METHOD(kernel_net_t, del_ip, status_t,
DBG2(DBG_KNL, "deleting virtual IP %H", virtual_ip);
- this->mutex->lock(this->mutex);
- ifaces = this->ifaces->create_enumerator(this->ifaces);
- while (ifaces->enumerate(ifaces, &iface))
- {
- addrs = iface->addrs->create_enumerator(iface->addrs);
- while (addrs->enumerate(addrs, &addr))
+ this->lock->write_lock(this->lock);
+ entry = this->vips->get_match(this->vips, &lookup,
+ (void*)addr_map_entry_match);
+ if (!entry)
+ { /* we didn't install this IP as virtual IP */
+ entry = this->addrs->get_match(this->addrs, &lookup,
+ (void*)addr_map_entry_match);
+ if (entry)
{
- if (virtual_ip->ip_equals(virtual_ip, addr->ip))
+ DBG2(DBG_KNL, "not deleting existing IP %H on %s", virtual_ip,
+ entry->iface->ifname);
+ this->lock->unlock(this->lock);
+ return SUCCESS;
+ }
+ DBG2(DBG_KNL, "virtual IP %H not cached, unable to delete", virtual_ip);
+ this->lock->unlock(this->lock);
+ return FAILED;
+ }
+ if (entry->addr->refcount == 1)
+ {
+ status_t status;
+
+ /* we set this flag so that threads calling add_ip will block and wait
+ * until the entry is gone, also so we can wait below */
+ entry->addr->installed = FALSE;
+ status = manage_ipaddr(this, RTM_DELADDR, 0, entry->iface->ifindex,
+ virtual_ip);
+ if (status == SUCCESS)
+ { /* wait until the address is really gone */
+ while (is_known_vip(this, virtual_ip))
{
- ifindex = iface->ifindex;
- if (addr->refcount == 1)
- {
- status = manage_ipaddr(this, RTM_DELADDR, 0,
- ifindex, virtual_ip);
- if (status == SUCCESS)
- { /* wait until the address is really gone */
- while (get_vip_refcount(this, virtual_ip) > 0)
- {
- this->condvar->wait(this->condvar, this->mutex);
- }
- }
- addrs->destroy(addrs);
- ifaces->destroy(ifaces);
- this->mutex->unlock(this->mutex);
- return status;
- }
- else
- {
- addr->refcount--;
- }
- DBG2(DBG_KNL, "virtual IP %H used by other SAs, not deleting",
- virtual_ip);
- addrs->destroy(addrs);
- ifaces->destroy(ifaces);
- this->mutex->unlock(this->mutex);
- return SUCCESS;
+ this->condvar->wait(this->condvar, this->lock);
}
}
- addrs->destroy(addrs);
+ this->lock->unlock(this->lock);
+ return status;
}
- ifaces->destroy(ifaces);
- this->mutex->unlock(this->mutex);
-
- DBG2(DBG_KNL, "virtual IP %H not cached, unable to delete", virtual_ip);
- return FAILED;
+ else
+ {
+ entry->addr->refcount--;
+ }
+ DBG2(DBG_KNL, "virtual IP %H used by other SAs, not deleting",
+ virtual_ip);
+ this->lock->unlock(this->lock);
+ return SUCCESS;
}
/**
* Manages source routes in the routing table.
* By setting the appropriate nlmsg_type, the route gets added or removed.
*/
-static status_t manage_srcroute(private_kernel_netlink_net_t *this, int nlmsg_type,
- int flags, chunk_t dst_net, u_int8_t prefixlen,
- host_t *gateway, host_t *src_ip, char *if_name)
+static status_t manage_srcroute(private_kernel_netlink_net_t *this,
+ int nlmsg_type, int flags, chunk_t dst_net,
+ u_int8_t prefixlen, host_t *gateway,
+ host_t *src_ip, char *if_name)
{
netlink_buf_t request;
struct nlmsghdr *hdr;
@@ -1306,16 +1892,56 @@ METHOD(kernel_net_t, add_route, status_t,
private_kernel_netlink_net_t *this, chunk_t dst_net, u_int8_t prefixlen,
host_t *gateway, host_t *src_ip, char *if_name)
{
- return manage_srcroute(this, RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL,
- dst_net, prefixlen, gateway, src_ip, if_name);
+ status_t status;
+ route_entry_t *found, route = {
+ .dst_net = dst_net,
+ .prefixlen = prefixlen,
+ .gateway = gateway,
+ .src_ip = src_ip,
+ .if_name = if_name,
+ };
+
+ this->routes_lock->lock(this->routes_lock);
+ found = this->routes->get(this->routes, &route);
+ if (found)
+ {
+ this->routes_lock->unlock(this->routes_lock);
+ return ALREADY_DONE;
+ }
+ found = route_entry_clone(&route);
+ this->routes->put(this->routes, found, found);
+ status = manage_srcroute(this, RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL,
+ dst_net, prefixlen, gateway, src_ip, if_name);
+ this->routes_lock->unlock(this->routes_lock);
+ return status;
}
METHOD(kernel_net_t, del_route, status_t,
private_kernel_netlink_net_t *this, chunk_t dst_net, u_int8_t prefixlen,
host_t *gateway, host_t *src_ip, char *if_name)
{
- return manage_srcroute(this, RTM_DELROUTE, 0, dst_net, prefixlen,
- gateway, src_ip, if_name);
+ status_t status;
+ route_entry_t *found, route = {
+ .dst_net = dst_net,
+ .prefixlen = prefixlen,
+ .gateway = gateway,
+ .src_ip = src_ip,
+ .if_name = if_name,
+ };
+
+ this->routes_lock->lock(this->routes_lock);
+ found = this->routes->get(this->routes, &route);
+ if (!found)
+ {
+ this->routes_lock->unlock(this->routes_lock);
+ return NOT_FOUND;
+ }
+ this->routes->remove(this->routes, found);
+ route_entry_destroy(found);
+ status = manage_srcroute(this, RTM_DELROUTE, 0, dst_net, prefixlen,
+ gateway, src_ip, if_name);
+ this->routes_lock->unlock(this->routes_lock);
+ return status;
}
/**
@@ -1331,7 +1957,7 @@ static status_t init_address_list(private_kernel_netlink_net_t *this)
iface_entry_t *iface;
addr_entry_t *addr;
- DBG1(DBG_KNL, "listening on interfaces:");
+ DBG2(DBG_KNL, "known interfaces and IP addresses:");
memset(&request, 0, sizeof(request));
@@ -1389,23 +2015,23 @@ static status_t init_address_list(private_kernel_netlink_net_t *this)
}
free(out);
- this->mutex->lock(this->mutex);
+ this->lock->read_lock(this->lock);
ifaces = this->ifaces->create_enumerator(this->ifaces);
while (ifaces->enumerate(ifaces, &iface))
{
- if (iface->flags & IFF_UP)
+ if (iface_entry_up_and_usable(iface))
{
- DBG1(DBG_KNL, " %s", iface->ifname);
+ DBG2(DBG_KNL, " %s", iface->ifname);
addrs = iface->addrs->create_enumerator(iface->addrs);
while (addrs->enumerate(addrs, (void**)&addr))
{
- DBG1(DBG_KNL, " %H", addr->ip);
+ DBG2(DBG_KNL, " %H", addr->ip);
}
addrs->destroy(addrs);
}
}
ifaces->destroy(ifaces);
- this->mutex->unlock(this->mutex);
+ this->lock->unlock(this->lock);
return SUCCESS;
}
@@ -1443,9 +2069,59 @@ static status_t manage_rule(private_kernel_netlink_net_t *this, int nlmsg_type,
return this->socket->send_ack(this->socket, hdr);
}
+/**
+ * check for kernel features (currently only via version number)
+ */
+static void check_kernel_features(private_kernel_netlink_net_t *this)
+{
+ struct utsname utsname;
+ int a, b, c;
+
+ if (uname(&utsname) == 0)
+ {
+ switch(sscanf(utsname.release, "%d.%d.%d", &a, &b, &c))
+ {
+ case 3:
+ if (a == 2)
+ {
+ DBG2(DBG_KNL, "detected Linux %d.%d.%d, no support for "
+ "RTA_PREFSRC for IPv6 routes", a, b, c);
+ break;
+ }
+ /* fall-through */
+ case 2:
+ /* only 3.x+ uses two part version numbers */
+ this->rta_prefsrc_for_ipv6 = TRUE;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+/**
+ * Destroy an address to iface map
+ */
+static void addr_map_destroy(hashtable_t *map)
+{
+ enumerator_t *enumerator;
+ addr_map_entry_t *addr;
+
+ enumerator = map->create_enumerator(map);
+ while (enumerator->enumerate(enumerator, NULL, (void**)&addr))
+ {
+ free(addr);
+ }
+ enumerator->destroy(enumerator);
+ map->destroy(map);
+}
+
METHOD(kernel_net_t, destroy, void,
private_kernel_netlink_net_t *this)
{
+ enumerator_t *enumerator;
+ route_entry_t *route;
+
if (this->routing_table)
{
manage_rule(this, RTM_DELRULE, AF_INET, this->routing_table,
@@ -1453,19 +2129,34 @@ METHOD(kernel_net_t, destroy, void,
manage_rule(this, RTM_DELRULE, AF_INET6, this->routing_table,
this->routing_table_prio);
}
- if (this->job)
- {
- this->job->cancel(this->job);
- }
if (this->socket_events > 0)
{
close(this->socket_events);
}
+ enumerator = this->routes->create_enumerator(this->routes);
+ while (enumerator->enumerate(enumerator, NULL, (void**)&route))
+ {
+ manage_srcroute(this, RTM_DELROUTE, 0, route->dst_net, route->prefixlen,
+ route->gateway, route->src_ip, route->if_name);
+ route_entry_destroy(route);
+ }
+ enumerator->destroy(enumerator);
+ this->routes->destroy(this->routes);
+ this->routes_lock->destroy(this->routes_lock);
DESTROY_IF(this->socket);
+
+ net_changes_clear(this);
+ this->net_changes->destroy(this->net_changes);
+ this->net_changes_lock->destroy(this->net_changes_lock);
+
+ addr_map_destroy(this->addrs);
+ addr_map_destroy(this->vips);
+
this->ifaces->destroy_function(this->ifaces, (void*)iface_entry_destroy);
this->rt_exclude->destroy(this->rt_exclude);
+ this->roam_lock->destroy(this->roam_lock);
this->condvar->destroy(this->condvar);
- this->mutex->destroy(this->mutex);
+ this->lock->destroy(this->lock);
free(this);
}
@@ -1475,8 +2166,8 @@ METHOD(kernel_net_t, destroy, void,
kernel_netlink_net_t *kernel_netlink_net_create()
{
private_kernel_netlink_net_t *this;
- struct sockaddr_nl addr;
enumerator_t *enumerator;
+ bool register_for_events = TRUE;
char *exclude;
INIT(this,
@@ -1495,9 +2186,22 @@ kernel_netlink_net_t *kernel_netlink_net_create()
},
.socket = netlink_socket_create(NETLINK_ROUTE),
.rt_exclude = linked_list_create(),
+ .routes = hashtable_create((hashtable_hash_t)route_entry_hash,
+ (hashtable_equals_t)route_entry_equals, 16),
+ .net_changes = hashtable_create(
+ (hashtable_hash_t)net_change_hash,
+ (hashtable_equals_t)net_change_equals, 16),
+ .addrs = hashtable_create(
+ (hashtable_hash_t)addr_map_entry_hash,
+ (hashtable_equals_t)addr_map_entry_equals, 16),
+ .vips = hashtable_create((hashtable_hash_t)addr_map_entry_hash,
+ (hashtable_equals_t)addr_map_entry_equals, 16),
+ .routes_lock = mutex_create(MUTEX_TYPE_DEFAULT),
+ .net_changes_lock = mutex_create(MUTEX_TYPE_DEFAULT),
.ifaces = linked_list_create(),
- .mutex = mutex_create(MUTEX_TYPE_RECURSIVE),
- .condvar = condvar_create(CONDVAR_TYPE_DEFAULT),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ .condvar = rwlock_condvar_create(),
+ .roam_lock = spinlock_create(),
.routing_table = lib->settings->get_int(lib->settings,
"%s.routing_table", ROUTING_TABLE, hydra->daemon),
.routing_table_prio = lib->settings->get_int(lib->settings,
@@ -1506,8 +2210,18 @@ kernel_netlink_net_t *kernel_netlink_net_create()
"%s.process_route", TRUE, hydra->daemon),
.install_virtual_ip = lib->settings->get_bool(lib->settings,
"%s.install_virtual_ip", TRUE, hydra->daemon),
+ .install_virtual_ip_on = lib->settings->get_str(lib->settings,
+ "%s.install_virtual_ip_on", NULL, hydra->daemon),
);
- timerclear(&this->last_roam);
+ timerclear(&this->last_route_reinstall);
+ timerclear(&this->next_roam);
+
+ check_kernel_features(this);
+
+ if (streq(hydra->daemon, "starter"))
+ { /* starter has no threads, so we do not register for kernel events */
+ register_for_events = FALSE;
+ }
exclude = lib->settings->get_str(lib->settings,
"%s.ignore_routing_tables", NULL, hydra->daemon);
@@ -1530,29 +2244,35 @@ kernel_netlink_net_t *kernel_netlink_net_create()
enumerator->destroy(enumerator);
}
- memset(&addr, 0, sizeof(addr));
- addr.nl_family = AF_NETLINK;
-
- /* create and bind RT socket for events (address/interface/route changes) */
- this->socket_events = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
- if (this->socket_events < 0)
+ if (register_for_events)
{
- DBG1(DBG_KNL, "unable to create RT event socket");
- destroy(this);
- return NULL;
- }
- addr.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR |
- RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE | RTMGRP_LINK;
- if (bind(this->socket_events, (struct sockaddr*)&addr, sizeof(addr)))
- {
- DBG1(DBG_KNL, "unable to bind RT event socket");
- destroy(this);
- return NULL;
- }
+ struct sockaddr_nl addr;
+
+ memset(&addr, 0, sizeof(addr));
+ addr.nl_family = AF_NETLINK;
- this->job = callback_job_create_with_prio((callback_job_cb_t)receive_events,
- this, NULL, NULL, JOB_PRIO_CRITICAL);
- lib->processor->queue_job(lib->processor, (job_t*)this->job);
+ /* create and bind RT socket for events (address/interface/route changes) */
+ this->socket_events = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ if (this->socket_events < 0)
+ {
+ DBG1(DBG_KNL, "unable to create RT event socket");
+ destroy(this);
+ return NULL;
+ }
+ addr.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR |
+ RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE | RTMGRP_LINK;
+ if (bind(this->socket_events, (struct sockaddr*)&addr, sizeof(addr)))
+ {
+ DBG1(DBG_KNL, "unable to bind RT event socket");
+ destroy(this);
+ return NULL;
+ }
+
+ lib->processor->queue_job(lib->processor,
+ (job_t*)callback_job_create_with_prio(
+ (callback_job_cb_t)receive_events, this, NULL,
+ (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
+ }
if (init_address_list(this) != SUCCESS)
{
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.c
index dad3fb68e..285f6c8b2 100644
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.c
+++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.c
@@ -206,6 +206,11 @@ METHOD(netlink_socket_t, netlink_send_ack, status_t,
free(out);
return ALREADY_DONE;
}
+ if (-err->error == ESRCH)
+ { /* do not report missing entries */
+ free(out);
+ return NOT_FOUND;
+ }
DBG1(DBG_KNL, "received netlink error: %s (%d)",
strerror(-err->error), -err->error);
free(out);
diff --git a/src/libhydra/plugins/kernel_pfkey/Makefile.in b/src/libhydra/plugins/kernel_pfkey/Makefile.in
index 14c924b6f..aac85a4e6 100644
--- a/src/libhydra/plugins/kernel_pfkey/Makefile.in
+++ b/src/libhydra/plugins/kernel_pfkey/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -86,7 +87,7 @@ libstrongswan_kernel_pfkey_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_kernel_pfkey_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_kernel_pfkey_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -112,6 +113,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -206,11 +208,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -227,11 +232,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -247,6 +253,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -256,7 +263,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
index da10edffe..b099bc714 100644
--- a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
+++ b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2011 Tobias Brunner
+ * Copyright (C) 2008-2012 Tobias Brunner
* Copyright (C) 2008 Andreas Steffen
* Hochschule fuer Technik Rapperswil
*
@@ -51,6 +51,9 @@
#include <unistd.h>
#include <time.h>
#include <errno.h>
+#ifdef __APPLE__
+#include <sys/sysctl.h>
+#endif
#include "kernel_pfkey_ipsec.h"
@@ -99,6 +102,20 @@
#define IPV6_IPSEC_POLICY 34
#endif
+/* from linux/udp.h */
+#ifndef UDP_ENCAP
+#define UDP_ENCAP 100
+#endif
+
+#ifndef UDP_ENCAP_ESPINUDP
+#define UDP_ENCAP_ESPINUDP 2
+#endif
+
+/* this is not defined on some platforms */
+#ifndef SOL_UDP
+#define SOL_UDP IPPROTO_UDP
+#endif
+
/** default priority of installed policies */
#define PRIO_BASE 512
@@ -173,11 +190,6 @@ struct private_kernel_pfkey_ipsec_t
bool install_routes;
/**
- * job receiving PF_KEY events
- */
- callback_job_t *job;
-
- /**
* mutex to lock access to the PF_KEY socket
*/
mutex_t *mutex_pfkey;
@@ -238,8 +250,8 @@ static void route_entry_destroy(route_entry_t *this)
static bool route_entry_equals(route_entry_t *a, route_entry_t *b)
{
return a->if_name && b->if_name && streq(a->if_name, b->if_name) &&
- a->src_ip->equals(a->src_ip, b->src_ip) &&
- a->gateway->equals(a->gateway, b->gateway) &&
+ a->src_ip->ip_equals(a->src_ip, b->src_ip) &&
+ a->gateway->ip_equals(a->gateway, b->gateway) &&
chunk_equals(a->dst_net, b->dst_net) && a->prefixlen == b->prefixlen;
}
@@ -795,8 +807,22 @@ static kernel_algorithm_t compression_algs[] = {
/**
* Look up a kernel algorithm ID and its key size
*/
-static int lookup_algorithm(kernel_algorithm_t *list, int ikev2)
+static int lookup_algorithm(transform_type_t type, int ikev2)
{
+ kernel_algorithm_t *list;
+ int alg = 0;
+
+ switch (type)
+ {
+ case ENCRYPTION_ALGORITHM:
+ list = encryption_algs;
+ break;
+ case INTEGRITY_ALGORITHM:
+ list = integrity_algs;
+ break;
+ default:
+ return 0;
+ }
while (list->ikev2 != END_OF_LIST)
{
if (ikev2 == list->ikev2)
@@ -805,18 +831,21 @@ static int lookup_algorithm(kernel_algorithm_t *list, int ikev2)
}
list++;
}
- return 0;
+ hydra->kernel_interface->lookup_algorithm(hydra->kernel_interface, ikev2,
+ type, &alg, NULL);
+ return alg;
}
/**
- * Copy a host_t as sockaddr_t to the given memory location. Ports are
- * reset to zero as per RFC 2367.
+ * Copy a host_t as sockaddr_t to the given memory location.
* @return the number of bytes copied
*/
-static size_t hostcpy(void *dest, host_t *host)
+static size_t hostcpy(void *dest, host_t *host, bool include_port)
{
sockaddr_t *addr = host->get_sockaddr(host), *dest_addr = dest;
socklen_t *len = host->get_sockaddr_len(host);
+ u_int16_t port = htons(host->get_port(host));
+
memcpy(dest, addr, *len);
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
dest_addr->sa_len = *len;
@@ -826,13 +855,13 @@ static size_t hostcpy(void *dest, host_t *host)
case AF_INET:
{
struct sockaddr_in *sin = dest;
- sin->sin_port = 0;
+ sin->sin_port = include_port ? port : 0;
break;
}
case AF_INET6:
{
struct sockaddr_in6 *sin6 = dest;
- sin6->sin6_port = 0;
+ sin6->sin6_port = include_port ? port : 0;
break;
}
}
@@ -842,9 +871,9 @@ static size_t hostcpy(void *dest, host_t *host)
/**
* add a host behind an sadb_address extension
*/
-static void host2ext(host_t *host, struct sadb_address *ext)
+static void host2ext(host_t *host, struct sadb_address *ext, bool include_port)
{
- size_t len = hostcpy(ext + 1, host);
+ size_t len = hostcpy(ext + 1, host, include_port);
ext->sadb_address_len = PFKEY_LEN(sizeof(*ext) + len);
}
@@ -852,13 +881,13 @@ static void host2ext(host_t *host, struct sadb_address *ext)
* add a host to the given sadb_msg
*/
static void add_addr_ext(struct sadb_msg *msg, host_t *host, u_int16_t type,
- u_int8_t proto, u_int8_t prefixlen)
+ u_int8_t proto, u_int8_t prefixlen, bool include_port)
{
struct sadb_address *addr = (struct sadb_address*)PFKEY_EXT_ADD_NEXT(msg);
addr->sadb_address_exttype = type;
addr->sadb_address_proto = proto;
addr->sadb_address_prefixlen = prefixlen;
- host2ext(host, addr);
+ host2ext(host, addr, include_port);
PFKEY_EXT_ADD(msg, addr);
}
@@ -1292,11 +1321,13 @@ static void process_mapping(private_kernel_pfkey_ipsec_t *this,
{
struct sockaddr_in *sin = (struct sockaddr_in*)sa;
sin->sin_port = htons(response.x_natt_dport->sadb_x_nat_t_port_port);
+ break;
}
case AF_INET6:
{
struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)sa;
sin6->sin6_port = htons(response.x_natt_dport->sadb_x_nat_t_port_port);
+ break;
}
default:
break;
@@ -1410,8 +1441,8 @@ METHOD(kernel_ipsec_t, get_spi, status_t,
sa2->sadb_x_sa2_reqid = reqid;
PFKEY_EXT_ADD(msg, sa2);
- add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0);
- add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0);
+ add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0, FALSE);
+ add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
range = (struct sadb_spirange*)PFKEY_EXT_ADD_NEXT(msg);
range->sadb_spirange_exttype = SADB_EXT_SPIRANGE;
@@ -1497,8 +1528,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
sa->sadb_sa_len = PFKEY_LEN(len);
sa->sadb_sa_spi = spi;
sa->sadb_sa_replay = (protocol == IPPROTO_COMP) ? 0 : 32;
- sa->sadb_sa_auth = lookup_algorithm(integrity_algs, int_alg);
- sa->sadb_sa_encrypt = lookup_algorithm(encryption_algs, enc_alg);
+ sa->sadb_sa_auth = lookup_algorithm(INTEGRITY_ALGORITHM, int_alg);
+ sa->sadb_sa_encrypt = lookup_algorithm(ENCRYPTION_ALGORITHM, enc_alg);
PFKEY_EXT_ADD(msg, sa);
sa2 = (struct sadb_x_sa2*)PFKEY_EXT_ADD_NEXT(msg);
@@ -1508,8 +1539,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
sa2->sadb_x_sa2_reqid = reqid;
PFKEY_EXT_ADD(msg, sa2);
- add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0);
- add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0);
+ add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0, FALSE);
+ add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
lft = (struct sadb_lifetime*)PFKEY_EXT_ADD_NEXT(msg);
lft->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
@@ -1639,7 +1670,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
/* the kernel wants a SADB_EXT_ADDRESS_SRC to be present even though
* it is not used for anything. */
add_anyaddr_ext(msg, dst->get_family(dst), SADB_EXT_ADDRESS_SRC);
- add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0);
+ add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
if (pfkey_send(this, msg, &out, &len) != SUCCESS)
{
@@ -1762,8 +1793,8 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
/* the Linux Kernel doesn't care for the src address, but other systems do
* (e.g. FreeBSD)
*/
- add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0);
- add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0);
+ add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0, FALSE);
+ add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
if (pfkey_send(this, msg, &out, &len) != SUCCESS)
{
@@ -1818,8 +1849,8 @@ METHOD(kernel_ipsec_t, del_sa, status_t,
/* the Linux Kernel doesn't care for the src address, but other systems do
* (e.g. FreeBSD)
*/
- add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0);
- add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0);
+ add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0, FALSE);
+ add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
if (pfkey_send(this, msg, &out, &len) != SUCCESS)
{
@@ -1919,9 +1950,9 @@ static status_t add_policy_internal(private_kernel_pfkey_ipsec_t *this,
req->sadb_x_ipsecrequest_level = IPSEC_LEVEL_UNIQUE;
if (ipsec->cfg.mode == MODE_TUNNEL)
{
- len = hostcpy(req + 1, ipsec->src);
+ len = hostcpy(req + 1, ipsec->src, FALSE);
req->sadb_x_ipsecrequest_len += len;
- len = hostcpy((char*)(req + 1) + len, ipsec->dst);
+ len = hostcpy((char*)(req + 1) + len, ipsec->dst, FALSE);
req->sadb_x_ipsecrequest_len += len;
}
@@ -1929,9 +1960,9 @@ static status_t add_policy_internal(private_kernel_pfkey_ipsec_t *this,
PFKEY_EXT_ADD(msg, pol);
add_addr_ext(msg, policy->src.net, SADB_EXT_ADDRESS_SRC, policy->src.proto,
- policy->src.mask);
+ policy->src.mask, TRUE);
add_addr_ext(msg, policy->dst.net, SADB_EXT_ADDRESS_DST, policy->dst.proto,
- policy->dst.mask);
+ policy->dst.mask, TRUE);
#ifdef __FreeBSD__
{ /* on FreeBSD a lifetime has to be defined to be able to later query
@@ -1989,23 +2020,26 @@ static status_t add_policy_internal(private_kernel_pfkey_ipsec_t *this,
if (policy->direction == POLICY_FWD &&
ipsec->cfg.mode != MODE_TRANSPORT && this->install_routes)
{
- route_entry_t *route = malloc_thing(route_entry_t);
policy_sa_fwd_t *fwd = (policy_sa_fwd_t*)mapping;
+ route_entry_t *route;
+
+ INIT(route,
+ .prefixlen = policy->src.mask,
+ );
if (hydra->kernel_interface->get_address_by_ts(hydra->kernel_interface,
fwd->dst_ts, &route->src_ip) == SUCCESS)
{
/* get the nexthop to src (src as we are in POLICY_FWD).*/
route->gateway = hydra->kernel_interface->get_nexthop(
- hydra->kernel_interface, ipsec->src);
- /* install route via outgoing interface */
- route->if_name = hydra->kernel_interface->get_interface(
- hydra->kernel_interface, ipsec->dst);
+ hydra->kernel_interface, ipsec->src,
+ ipsec->dst);
route->dst_net = chunk_clone(policy->src.net->get_address(
policy->src.net));
- route->prefixlen = policy->src.mask;
- if (!route->if_name)
+ /* install route via outgoing interface */
+ if (!hydra->kernel_interface->get_interface(hydra->kernel_interface,
+ ipsec->dst, &route->if_name))
{
this->mutex->unlock(this->mutex);
route_entry_destroy(route);
@@ -2016,12 +2050,7 @@ static status_t add_policy_internal(private_kernel_pfkey_ipsec_t *this,
{
route_entry_t *old = policy->route;
if (route_entry_equals(old, route))
- { /* keep previously installed route. since it might have
- * still been removed by an address change, we install it
- * again but ignore the result */
- hydra->kernel_interface->add_route(hydra->kernel_interface,
- route->dst_net, route->prefixlen, route->gateway,
- route->src_ip, route->if_name);
+ {
this->mutex->unlock(this->mutex);
route_entry_destroy(route);
return SUCCESS;
@@ -2200,9 +2229,9 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
PFKEY_EXT_ADD(msg, pol);
add_addr_ext(msg, policy->src.net, SADB_EXT_ADDRESS_SRC, policy->src.proto,
- policy->src.mask);
+ policy->src.mask, TRUE);
add_addr_ext(msg, policy->dst.net, SADB_EXT_ADDRESS_DST, policy->dst.proto,
- policy->dst.mask);
+ policy->dst.mask, TRUE);
this->mutex->unlock(this->mutex);
@@ -2344,9 +2373,9 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
PFKEY_EXT_ADD(msg, pol);
add_addr_ext(msg, policy->src.net, SADB_EXT_ADDRESS_SRC, policy->src.proto,
- policy->src.mask);
+ policy->src.mask, TRUE);
add_addr_ext(msg, policy->dst.net, SADB_EXT_ADDRESS_DST, policy->dst.proto,
- policy->dst.mask);
+ policy->dst.mask, TRUE);
if (policy->route)
{
@@ -2497,13 +2526,33 @@ METHOD(kernel_ipsec_t, bypass_socket, bool,
return TRUE;
}
-METHOD(kernel_ipsec_t, destroy, void,
- private_kernel_pfkey_ipsec_t *this)
+METHOD(kernel_ipsec_t, enable_udp_decap, bool,
+ private_kernel_pfkey_ipsec_t *this, int fd, int family, u_int16_t port)
{
- if (this->job)
+#ifndef __APPLE__
+ int type = UDP_ENCAP_ESPINUDP;
+
+ if (setsockopt(fd, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0)
{
- this->job->cancel(this->job);
+ DBG1(DBG_KNL, "unable to set UDP_ENCAP: %s", strerror(errno));
+ return FALSE;
}
+#else /* __APPLE__ */
+ if (sysctlbyname("net.inet.ipsec.esp_port", NULL, NULL, &port,
+ sizeof(port)) != 0)
+ {
+ DBG1(DBG_KNL, "could not set net.inet.ipsec.esp_port to %d: %s",
+ port, strerror(errno));
+ return FALSE;
+ }
+#endif /* __APPLE__ */
+
+ return TRUE;
+}
+
+METHOD(kernel_ipsec_t, destroy, void,
+ private_kernel_pfkey_ipsec_t *this)
+{
if (this->socket > 0)
{
close(this->socket);
@@ -2528,6 +2577,7 @@ METHOD(kernel_ipsec_t, destroy, void,
kernel_pfkey_ipsec_t *kernel_pfkey_ipsec_create()
{
private_kernel_pfkey_ipsec_t *this;
+ bool register_for_events = TRUE;
INIT(this,
.public = {
@@ -2544,6 +2594,7 @@ kernel_pfkey_ipsec_t *kernel_pfkey_ipsec_create()
.del_policy = _del_policy,
.flush_policies = _flush_policies,
.bypass_socket = _bypass_socket,
+ .enable_udp_decap = _enable_udp_decap,
.destroy = _destroy,
},
},
@@ -2561,6 +2612,10 @@ kernel_pfkey_ipsec_t *kernel_pfkey_ipsec_create()
{ /* no routes for pluto, they are installed via updown script */
this->install_routes = FALSE;
}
+ else if (streq(hydra->daemon, "starter"))
+ { /* starter has no threads, so we do not register for kernel events */
+ register_for_events = FALSE;
+ }
/* create a PF_KEY socket to communicate with the kernel */
this->socket = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
@@ -2571,27 +2626,31 @@ kernel_pfkey_ipsec_t *kernel_pfkey_ipsec_create()
return NULL;
}
- /* create a PF_KEY socket for ACQUIRE & EXPIRE */
- this->socket_events = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
- if (this->socket_events <= 0)
+ if (register_for_events)
{
- DBG1(DBG_KNL, "unable to create PF_KEY event socket");
- destroy(this);
- return NULL;
- }
+ /* create a PF_KEY socket for ACQUIRE & EXPIRE */
+ this->socket_events = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
+ if (this->socket_events <= 0)
+ {
+ DBG1(DBG_KNL, "unable to create PF_KEY event socket");
+ destroy(this);
+ return NULL;
+ }
- /* register the event socket */
- if (register_pfkey_socket(this, SADB_SATYPE_ESP) != SUCCESS ||
- register_pfkey_socket(this, SADB_SATYPE_AH) != SUCCESS)
- {
- DBG1(DBG_KNL, "unable to register PF_KEY event socket");
- destroy(this);
- return NULL;
- }
+ /* register the event socket */
+ if (register_pfkey_socket(this, SADB_SATYPE_ESP) != SUCCESS ||
+ register_pfkey_socket(this, SADB_SATYPE_AH) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to register PF_KEY event socket");
+ destroy(this);
+ return NULL;
+ }
- this->job = callback_job_create_with_prio((callback_job_cb_t)receive_events,
- this, NULL, NULL, JOB_PRIO_CRITICAL);
- lib->processor->queue_job(lib->processor, (job_t*)this->job);
+ lib->processor->queue_job(lib->processor,
+ (job_t*)callback_job_create_with_prio(
+ (callback_job_cb_t)receive_events, this, NULL,
+ (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
+ }
return &this->public;
}
diff --git a/src/libhydra/plugins/kernel_pfroute/Makefile.in b/src/libhydra/plugins/kernel_pfroute/Makefile.in
index 1412db0ec..6fa2fc9c1 100644
--- a/src/libhydra/plugins/kernel_pfroute/Makefile.in
+++ b/src/libhydra/plugins/kernel_pfroute/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -86,7 +87,7 @@ libstrongswan_kernel_pfroute_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_kernel_pfroute_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_kernel_pfroute_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -112,6 +113,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -206,11 +208,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -227,11 +232,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -247,6 +253,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -256,7 +263,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c b/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c
index 5464568df..16a46bb56 100644
--- a/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c
+++ b/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Tobias Brunner
+ * Copyright (C) 2009-2012 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -28,6 +28,8 @@
#include <utils/host.h>
#include <threading/thread.h>
#include <threading/mutex.h>
+#include <threading/rwlock.h>
+#include <utils/hashtable.h>
#include <utils/linked_list.h>
#include <processing/jobs/callback_job.h>
@@ -85,6 +87,9 @@ struct iface_entry_t {
/** list of addresses as host_t */
linked_list_t *addrs;
+
+ /** TRUE if usable by config */
+ bool usable;
};
/**
@@ -96,6 +101,73 @@ static void iface_entry_destroy(iface_entry_t *this)
free(this);
}
+/**
+ * check if an interface is up
+ */
+static inline bool iface_entry_up(iface_entry_t *iface)
+{
+ return (iface->flags & IFF_UP) == IFF_UP;
+}
+
+/**
+ * check if an interface is up and usable
+ */
+static inline bool iface_entry_up_and_usable(iface_entry_t *iface)
+{
+ return iface->usable && iface_entry_up(iface);
+}
+
+typedef struct addr_map_entry_t addr_map_entry_t;
+
+/**
+ * Entry that maps an IP address to an interface entry
+ */
+struct addr_map_entry_t {
+ /** The IP address */
+ host_t *ip;
+
+ /** The interface this address is installed on */
+ iface_entry_t *iface;
+};
+
+/**
+ * Hash a addr_map_entry_t object, all entries with the same IP address
+ * are stored in the same bucket
+ */
+static u_int addr_map_entry_hash(addr_map_entry_t *this)
+{
+ return chunk_hash(this->ip->get_address(this->ip));
+}
+
+/**
+ * Compare two addr_map_entry_t objects, two entries are equal if they are
+ * installed on the same interface
+ */
+static bool addr_map_entry_equals(addr_map_entry_t *a, addr_map_entry_t *b)
+{
+ return a->iface->ifindex == b->iface->ifindex &&
+ a->ip->ip_equals(a->ip, b->ip);
+}
+
+/**
+ * Used with get_match this finds an address entry if it is installed on
+ * an up and usable interface
+ */
+static bool addr_map_entry_match_up_and_usable(addr_map_entry_t *a,
+ addr_map_entry_t *b)
+{
+ return iface_entry_up_and_usable(b->iface) &&
+ a->ip->ip_equals(a->ip, b->ip);
+}
+
+/**
+ * Used with get_match this finds an address entry if it is installed on
+ * any active local interface
+ */
+static bool addr_map_entry_match_up(addr_map_entry_t *a, addr_map_entry_t *b)
+{
+ return iface_entry_up(b->iface) && a->ip->ip_equals(a->ip, b->ip);
+}
typedef struct private_kernel_pfroute_net_t private_kernel_pfroute_net_t;
@@ -110,9 +182,9 @@ struct private_kernel_pfroute_net_t
kernel_pfroute_net_t public;
/**
- * mutex to lock access to various lists
+ * lock to access lists and maps
*/
- mutex_t *mutex;
+ rwlock_t *lock;
/**
* Cached list of interfaces and their addresses (iface_entry_t)
@@ -120,9 +192,9 @@ struct private_kernel_pfroute_net_t
linked_list_t *ifaces;
/**
- * job receiving PF_ROUTE events
+ * Map for IP addresses to iface_entry_t objects (addr_map_entry_t)
*/
- callback_job_t *job;
+ hashtable_t *addrs;
/**
* mutex to lock access to the PF_ROUTE socket
@@ -151,6 +223,48 @@ struct private_kernel_pfroute_net_t
};
/**
+ * Add an address map entry
+ */
+static void addr_map_entry_add(private_kernel_pfroute_net_t *this,
+ addr_entry_t *addr, iface_entry_t *iface)
+{
+ addr_map_entry_t *entry;
+
+ if (addr->virtual)
+ { /* don't map virtual IPs */
+ return;
+ }
+
+ INIT(entry,
+ .ip = addr->ip,
+ .iface = iface,
+ );
+ entry = this->addrs->put(this->addrs, entry, entry);
+ free(entry);
+}
+
+/**
+ * Remove an address map entry (the argument order is a bit strange because
+ * it is also used with linked_list_t.invoke_function)
+ */
+static void addr_map_entry_remove(addr_entry_t *addr, iface_entry_t *iface,
+ private_kernel_pfroute_net_t *this)
+{
+ addr_map_entry_t *entry, lookup = {
+ .ip = addr->ip,
+ .iface = iface,
+ };
+
+ if (addr->virtual)
+ { /* these are never mapped, but this check avoid problems if a virtual IP
+ * equals a regular one */
+ return;
+ }
+ entry = this->addrs->remove(this->addrs, &lookup);
+ free(entry);
+}
+
+/**
* callback function that raises the delayed roam event
*/
static job_requeue_t roam_event(uintptr_t address)
@@ -219,7 +333,7 @@ static void process_addr(private_kernel_pfroute_net_t *this,
return;
}
- this->mutex->lock(this->mutex);
+ this->lock->write_lock(this->lock);
ifaces = this->ifaces->create_enumerator(this->ifaces);
while (ifaces->enumerate(ifaces, &iface))
{
@@ -234,12 +348,13 @@ static void process_addr(private_kernel_pfroute_net_t *this,
if (ifa->ifam_type == RTM_DELADDR)
{
iface->addrs->remove_at(iface->addrs, addrs);
- if (!addr->virtual)
+ if (!addr->virtual && iface->usable)
{
changed = TRUE;
DBG1(DBG_KNL, "%H disappeared from %s",
host, iface->ifname);
}
+ addr_map_entry_remove(addr, iface, this);
addr_entry_destroy(addr);
}
else if (ifa->ifam_type == RTM_NEWADDR && addr->virtual)
@@ -258,10 +373,14 @@ static void process_addr(private_kernel_pfroute_net_t *this,
addr->virtual = FALSE;
addr->refcount = 1;
iface->addrs->insert_last(iface->addrs, addr);
- DBG1(DBG_KNL, "%H appeared on %s", host, iface->ifname);
+ addr_map_entry_add(this, addr, iface);
+ if (iface->usable)
+ {
+ DBG1(DBG_KNL, "%H appeared on %s", host, iface->ifname);
+ }
}
- if (changed && (iface->flags & IFF_UP))
+ if (changed && iface_entry_up_and_usable(iface))
{
roam = TRUE;
}
@@ -269,7 +388,7 @@ static void process_addr(private_kernel_pfroute_net_t *this,
}
}
ifaces->destroy(ifaces);
- this->mutex->unlock(this->mutex);
+ this->lock->unlock(this->lock);
host->destroy(host);
if (roam)
@@ -289,33 +408,31 @@ static void process_link(private_kernel_pfroute_net_t *this,
iface_entry_t *iface;
bool roam = FALSE;
- if (msg->ifm_flags & IFF_LOOPBACK)
- { /* ignore loopback interfaces */
- return;
- }
-
- this->mutex->lock(this->mutex);
+ this->lock->write_lock(this->lock);
enumerator = this->ifaces->create_enumerator(this->ifaces);
while (enumerator->enumerate(enumerator, &iface))
{
if (iface->ifindex == msg->ifm_index)
{
- if (!(iface->flags & IFF_UP) && (msg->ifm_flags & IFF_UP))
- {
- roam = TRUE;
- DBG1(DBG_KNL, "interface %s activated", iface->ifname);
- }
- else if ((iface->flags & IFF_UP) && !(msg->ifm_flags & IFF_UP))
+ if (iface->usable)
{
- roam = TRUE;
- DBG1(DBG_KNL, "interface %s deactivated", iface->ifname);
+ if (!(iface->flags & IFF_UP) && (msg->ifm_flags & IFF_UP))
+ {
+ roam = TRUE;
+ DBG1(DBG_KNL, "interface %s activated", iface->ifname);
+ }
+ else if ((iface->flags & IFF_UP) && !(msg->ifm_flags & IFF_UP))
+ {
+ roam = TRUE;
+ DBG1(DBG_KNL, "interface %s deactivated", iface->ifname);
+ }
}
iface->flags = msg->ifm_flags;
break;
}
}
enumerator->destroy(enumerator);
- this->mutex->unlock(this->mutex);
+ this->lock->unlock(this->lock);
if (roam)
{
@@ -394,10 +511,8 @@ static job_requeue_t receive_events(private_kernel_pfroute_net_t *this)
/** enumerator over addresses */
typedef struct {
private_kernel_pfroute_net_t* this;
- /** whether to enumerate down interfaces */
- bool include_down_ifaces;
- /** whether to enumerate virtual ip addresses */
- bool include_virtual_ips;
+ /** which addresses to enumerate */
+ kernel_address_type_t which;
} address_enumerator_t;
/**
@@ -405,7 +520,7 @@ typedef struct {
*/
static void address_enumerator_destroy(address_enumerator_t *data)
{
- data->this->mutex->unlock(data->this->mutex);
+ data->this->lock->unlock(data->this->lock);
free(data);
}
@@ -416,7 +531,7 @@ static bool filter_addresses(address_enumerator_t *data,
addr_entry_t** in, host_t** out)
{
host_t *ip;
- if (!data->include_virtual_ips && (*in)->virtual)
+ if (!(data->which & ADDR_TYPE_VIRTUAL) && (*in)->virtual)
{ /* skip virtual interfaces added by us */
return FALSE;
}
@@ -449,8 +564,16 @@ static enumerator_t *create_iface_enumerator(iface_entry_t *iface,
static bool filter_interfaces(address_enumerator_t *data, iface_entry_t** in,
iface_entry_t** out)
{
- if (!data->include_down_ifaces && !((*in)->flags & IFF_UP))
- { /* skip interfaces not up */
+ if (!(data->which & ADDR_TYPE_IGNORED) && !(*in)->usable)
+ { /* skip interfaces excluded by config */
+ return FALSE;
+ }
+ if (!(data->which & ADDR_TYPE_LOOPBACK) && ((*in)->flags & IFF_LOOPBACK))
+ { /* ignore loopback devices */
+ return FALSE;
+ }
+ if (!(data->which & ADDR_TYPE_DOWN) && !((*in)->flags & IFF_UP))
+ { /* skip interfaces not up */
return FALSE;
}
*out = *in;
@@ -458,15 +581,13 @@ static bool filter_interfaces(address_enumerator_t *data, iface_entry_t** in,
}
METHOD(kernel_net_t, create_address_enumerator, enumerator_t*,
- private_kernel_pfroute_net_t *this,
- bool include_down_ifaces, bool include_virtual_ips)
+ private_kernel_pfroute_net_t *this, kernel_address_type_t which)
{
address_enumerator_t *data = malloc_thing(address_enumerator_t);
data->this = this;
- data->include_down_ifaces = include_down_ifaces;
- data->include_virtual_ips = include_virtual_ips;
+ data->which = which;
- this->mutex->lock(this->mutex);
+ this->lock->read_lock(this->lock);
return enumerator_create_nested(
enumerator_create_filter(
this->ifaces->create_enumerator(this->ifaces),
@@ -475,47 +596,40 @@ METHOD(kernel_net_t, create_address_enumerator, enumerator_t*,
(void*)address_enumerator_destroy);
}
-METHOD(kernel_net_t, get_interface_name, char*,
- private_kernel_pfroute_net_t *this, host_t* ip)
+METHOD(kernel_net_t, get_interface_name, bool,
+ private_kernel_pfroute_net_t *this, host_t* ip, char **name)
{
- enumerator_t *ifaces, *addrs;
- iface_entry_t *iface;
- addr_entry_t *addr;
- char *name = NULL;
-
- DBG2(DBG_KNL, "getting interface name for %H", ip);
+ addr_map_entry_t *entry, lookup = {
+ .ip = ip,
+ };
- this->mutex->lock(this->mutex);
- ifaces = this->ifaces->create_enumerator(this->ifaces);
- while (ifaces->enumerate(ifaces, &iface))
+ if (ip->is_anyaddr(ip))
+ {
+ return FALSE;
+ }
+ this->lock->read_lock(this->lock);
+ /* first try to find it on an up and usable interface */
+ entry = this->addrs->get_match(this->addrs, &lookup,
+ (void*)addr_map_entry_match_up_and_usable);
+ if (entry)
{
- addrs = iface->addrs->create_enumerator(iface->addrs);
- while (addrs->enumerate(addrs, &addr))
- {
- if (ip->ip_equals(ip, addr->ip))
- {
- name = strdup(iface->ifname);
- break;
- }
- }
- addrs->destroy(addrs);
if (name)
{
- break;
+ *name = strdup(entry->iface->ifname);
+ DBG2(DBG_KNL, "%H is on interface %s", ip, *name);
}
+ this->lock->unlock(this->lock);
+ return TRUE;
}
- ifaces->destroy(ifaces);
- this->mutex->unlock(this->mutex);
-
- if (name)
- {
- DBG2(DBG_KNL, "%H is on interface %s", ip, name);
- }
- else
- {
- DBG2(DBG_KNL, "%H is not a local address", ip);
+ /* maybe it is installed on an ignored interface */
+ entry = this->addrs->get_match(this->addrs, &lookup,
+ (void*)addr_map_entry_match_up);
+ if (!entry)
+ { /* the address does not exist, is on a down interface */
+ DBG2(DBG_KNL, "%H is not a local address or the interface is down", ip);
}
- return name;
+ this->lock->unlock(this->lock);
+ return FALSE;
}
METHOD(kernel_net_t, get_source_addr, host_t*,
@@ -525,7 +639,7 @@ METHOD(kernel_net_t, get_source_addr, host_t*,
}
METHOD(kernel_net_t, get_nexthop, host_t*,
- private_kernel_pfroute_net_t *this, host_t *dest)
+ private_kernel_pfroute_net_t *this, host_t *dest, host_t *src)
{
return NULL;
}
@@ -566,7 +680,7 @@ static status_t init_address_list(private_kernel_pfroute_net_t *this)
addr_entry_t *addr;
enumerator_t *ifaces, *addrs;
- DBG1(DBG_KNL, "listening on interfaces:");
+ DBG2(DBG_KNL, "known interfaces and IP addresses:");
if (getifaddrs(&ifap) < 0)
{
@@ -586,11 +700,6 @@ static status_t init_address_list(private_kernel_pfroute_net_t *this)
case AF_INET:
case AF_INET6:
{
- if (ifa->ifa_flags & IFF_LOOPBACK)
- { /* ignore loopback interfaces */
- continue;
- }
-
iface = NULL;
ifaces = this->ifaces->create_enumerator(this->ifaces);
while (ifaces->enumerate(ifaces, &current))
@@ -610,6 +719,8 @@ static status_t init_address_list(private_kernel_pfroute_net_t *this)
iface->ifindex = if_nametoindex(ifa->ifa_name);
iface->flags = ifa->ifa_flags;
iface->addrs = linked_list_create();
+ iface->usable = hydra->kernel_interface->is_interface_usable(
+ hydra->kernel_interface, ifa->ifa_name);
this->ifaces->insert_last(this->ifaces, iface);
}
@@ -620,6 +731,7 @@ static status_t init_address_list(private_kernel_pfroute_net_t *this)
addr->virtual = FALSE;
addr->refcount = 1;
iface->addrs->insert_last(iface->addrs, addr);
+ addr_map_entry_add(this, addr, iface);
}
}
}
@@ -629,13 +741,13 @@ static status_t init_address_list(private_kernel_pfroute_net_t *this)
ifaces = this->ifaces->create_enumerator(this->ifaces);
while (ifaces->enumerate(ifaces, &iface))
{
- if (iface->flags & IFF_UP)
+ if (iface->usable && iface->flags & IFF_UP)
{
- DBG1(DBG_KNL, " %s", iface->ifname);
+ DBG2(DBG_KNL, " %s", iface->ifname);
addrs = iface->addrs->create_enumerator(iface->addrs);
while (addrs->enumerate(addrs, (void**)&addr))
{
- DBG1(DBG_KNL, " %H", addr->ip);
+ DBG2(DBG_KNL, " %H", addr->ip);
}
addrs->destroy(addrs);
}
@@ -648,10 +760,9 @@ static status_t init_address_list(private_kernel_pfroute_net_t *this)
METHOD(kernel_net_t, destroy, void,
private_kernel_pfroute_net_t *this)
{
- if (this->job)
- {
- this->job->cancel(this->job);
- }
+ enumerator_t *enumerator;
+ addr_entry_t *addr;
+
if (this->socket > 0)
{
close(this->socket);
@@ -660,8 +771,15 @@ METHOD(kernel_net_t, destroy, void,
{
close(this->socket_events);
}
+ enumerator = this->addrs->create_enumerator(this->addrs);
+ while (enumerator->enumerate(enumerator, NULL, (void**)&addr))
+ {
+ free(addr);
+ }
+ enumerator->destroy(enumerator);
+ this->addrs->destroy(this->addrs);
this->ifaces->destroy_function(this->ifaces, (void*)iface_entry_destroy);
- this->mutex->destroy(this->mutex);
+ this->lock->destroy(this->lock);
this->mutex_pfroute->destroy(this->mutex_pfroute);
free(this);
}
@@ -672,6 +790,7 @@ METHOD(kernel_net_t, destroy, void,
kernel_pfroute_net_t *kernel_pfroute_net_create()
{
private_kernel_pfroute_net_t *this;
+ bool register_for_events = TRUE;
INIT(this,
.public = {
@@ -688,10 +807,18 @@ kernel_pfroute_net_t *kernel_pfroute_net_create()
},
},
.ifaces = linked_list_create(),
- .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ .addrs = hashtable_create(
+ (hashtable_hash_t)addr_map_entry_hash,
+ (hashtable_equals_t)addr_map_entry_equals, 16),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
.mutex_pfroute = mutex_create(MUTEX_TYPE_DEFAULT),
);
+ if (streq(hydra->daemon, "starter"))
+ { /* starter has no threads, so we do not register for kernel events */
+ register_for_events = FALSE;
+ }
+
/* create a PF_ROUTE socket to communicate with the kernel */
this->socket = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
if (this->socket < 0)
@@ -701,18 +828,22 @@ kernel_pfroute_net_t *kernel_pfroute_net_create()
return NULL;
}
- /* create a PF_ROUTE socket to receive events */
- this->socket_events = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
- if (this->socket_events < 0)
+ if (register_for_events)
{
- DBG1(DBG_KNL, "unable to create PF_ROUTE event socket");
- destroy(this);
- return NULL;
- }
+ /* create a PF_ROUTE socket to receive events */
+ this->socket_events = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
+ if (this->socket_events < 0)
+ {
+ DBG1(DBG_KNL, "unable to create PF_ROUTE event socket");
+ destroy(this);
+ return NULL;
+ }
- this->job = callback_job_create_with_prio((callback_job_cb_t)receive_events,
- this, NULL, NULL, JOB_PRIO_CRITICAL);
- lib->processor->queue_job(lib->processor, (job_t*)this->job);
+ lib->processor->queue_job(lib->processor,
+ (job_t*)callback_job_create_with_prio(
+ (callback_job_cb_t)receive_events, this, NULL,
+ (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
+ }
if (init_address_list(this) != SUCCESS)
{
diff --git a/src/libhydra/plugins/resolve/Makefile.in b/src/libhydra/plugins/resolve/Makefile.in
index 41846ffe0..aed5ee19d 100644
--- a/src/libhydra/plugins/resolve/Makefile.in
+++ b/src/libhydra/plugins/resolve/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -85,7 +86,7 @@ libstrongswan_resolve_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@MONOLITHIC_FALSE@am_libstrongswan_resolve_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_resolve_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -111,6 +112,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -205,11 +207,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -226,11 +231,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -246,6 +252,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -255,7 +262,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libhydra/plugins/resolve/resolve_handler.c b/src/libhydra/plugins/resolve/resolve_handler.c
index 011ebbaaf..0a3094fd7 100644
--- a/src/libhydra/plugins/resolve/resolve_handler.c
+++ b/src/libhydra/plugins/resolve/resolve_handler.c
@@ -150,6 +150,7 @@ static bool invoke_resolvconf(private_resolve_handler_t *this,
bool install)
{
char cmd[128];
+ bool success = TRUE;
/* we use the nameserver's IP address as part of the interface name to
* make them unique */
@@ -171,7 +172,8 @@ static bool invoke_resolvconf(private_resolve_handler_t *this,
DBG1(DBG_IKE, "installing DNS server %H via resolvconf", addr);
fprintf(out, "nameserver %H # by strongSwan, from %Y\n", addr,
server);
- if (ferror(out) || pclose(out))
+ success = !ferror(out);
+ if (pclose(out))
{
return FALSE;
}
@@ -180,7 +182,7 @@ static bool invoke_resolvconf(private_resolve_handler_t *this,
{
ignore_result(system(cmd));
}
- return TRUE;
+ return success;
}
METHOD(attribute_handler_t, handle, bool,
@@ -267,46 +269,71 @@ METHOD(attribute_handler_t, release, void,
typedef struct {
/** implements enumerator_t interface */
enumerator_t public;
- /** virtual IP we are requesting */
- host_t *vip;
+ /** request IPv4 DNS? */
+ bool v4;
+ /** request IPv6 DNS? */
+ bool v6;
} attribute_enumerator_t;
static bool attribute_enumerate(attribute_enumerator_t *this,
configuration_attribute_type_t *type,
chunk_t *data)
{
- switch (this->vip->get_family(this->vip))
+ if (this->v4)
{
- case AF_INET:
- *type = INTERNAL_IP4_DNS;
- break;
- case AF_INET6:
- *type = INTERNAL_IP6_DNS;
- break;
- default:
- return FALSE;
+ *type = INTERNAL_IP4_DNS;
+ *data = chunk_empty;
+ this->v4 = FALSE;
+ return TRUE;
+ }
+ if (this->v6)
+ {
+ *type = INTERNAL_IP6_DNS;
+ *data = chunk_empty;
+ this->v6 = FALSE;
+ return TRUE;
}
- *data = chunk_empty;
- /* enumerate only once */
- this->public.enumerate = (void*)return_false;
- return TRUE;
+ return FALSE;
}
-METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*,
- private_resolve_handler_t *this, identification_t *server, host_t *vip)
+/**
+ * Check if a list has a host of given family
+ */
+static bool has_host_family(linked_list_t *list, int family)
{
- if (vip)
+ enumerator_t *enumerator;
+ host_t *host;
+ bool found = FALSE;
+
+ enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, &host))
{
- attribute_enumerator_t *enumerator;
+ if (host->get_family(host) == family)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
- enumerator = malloc_thing(attribute_enumerator_t);
- enumerator->public.enumerate = (void*)attribute_enumerate;
- enumerator->public.destroy = (void*)free;
- enumerator->vip = vip;
+ return found;
+}
- return &enumerator->public;
- }
- return enumerator_create_empty();
+METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*,
+ private_resolve_handler_t *this, identification_t *server,
+ linked_list_t *vips)
+{
+ attribute_enumerator_t *enumerator;
+
+ INIT(enumerator,
+ .public = {
+ .enumerate = (void*)attribute_enumerate,
+ .destroy = (void*)free,
+ },
+ .v4 = has_host_family(vips, AF_INET),
+ .v6 = has_host_family(vips, AF_INET6),
+ );
+ return &enumerator->public;
}
METHOD(resolve_handler_t, destroy, void,
diff --git a/src/libimcv/Makefile.am b/src/libimcv/Makefile.am
index fae9fd662..e0e8f1017 100644
--- a/src/libimcv/Makefile.am
+++ b/src/libimcv/Makefile.am
@@ -13,8 +13,11 @@ libimcv_la_SOURCES = \
ietf/ietf_attr_pa_tnc_error.h ietf/ietf_attr_pa_tnc_error.c \
ietf/ietf_attr_port_filter.h ietf/ietf_attr_port_filter.c \
ietf/ietf_attr_product_info.h ietf/ietf_attr_product_info.c \
+ ietf/ietf_attr_attr_request.h ietf/ietf_attr_attr_request.c \
+ ietf/ietf_attr_assess_result.h ietf/ietf_attr_assess_result.c \
ita/ita_attr.h ita/ita_attr.c \
ita/ita_attr_command.h ita/ita_attr_command.c \
+ ita/ita_attr_dummy.h ita/ita_attr_dummy.c \
pa_tnc/pa_tnc_attr.h \
pa_tnc/pa_tnc_msg.h pa_tnc/pa_tnc_msg.c \
pa_tnc/pa_tnc_attr_manager.h pa_tnc/pa_tnc_attr_manager.c
diff --git a/src/libimcv/Makefile.in b/src/libimcv/Makefile.in
index 7e90a7aca..d1a1373af 100644
--- a/src/libimcv/Makefile.in
+++ b/src/libimcv/Makefile.in
@@ -53,6 +53,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -81,10 +82,11 @@ LTLIBRARIES = $(ipseclib_LTLIBRARIES)
libimcv_la_DEPENDENCIES = $(top_builddir)/src/libtncif/libtncif.la
am_libimcv_la_OBJECTS = imcv.lo imc_agent.lo imv_agent.lo ietf_attr.lo \
ietf_attr_pa_tnc_error.lo ietf_attr_port_filter.lo \
- ietf_attr_product_info.lo ita_attr.lo ita_attr_command.lo \
- pa_tnc_msg.lo pa_tnc_attr_manager.lo
+ ietf_attr_product_info.lo ietf_attr_attr_request.lo \
+ ietf_attr_assess_result.lo ita_attr.lo ita_attr_command.lo \
+ ita_attr_dummy.lo pa_tnc_msg.lo pa_tnc_attr_manager.lo
libimcv_la_OBJECTS = $(am_libimcv_la_OBJECTS)
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -149,6 +151,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -243,11 +246,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -264,11 +270,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -284,6 +291,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -293,7 +301,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -332,8 +339,11 @@ libimcv_la_SOURCES = \
ietf/ietf_attr_pa_tnc_error.h ietf/ietf_attr_pa_tnc_error.c \
ietf/ietf_attr_port_filter.h ietf/ietf_attr_port_filter.c \
ietf/ietf_attr_product_info.h ietf/ietf_attr_product_info.c \
+ ietf/ietf_attr_attr_request.h ietf/ietf_attr_attr_request.c \
+ ietf/ietf_attr_assess_result.h ietf/ietf_attr_assess_result.c \
ita/ita_attr.h ita/ita_attr.c \
ita/ita_attr_command.h ita/ita_attr_command.c \
+ ita/ita_attr_dummy.h ita/ita_attr_dummy.c \
pa_tnc/pa_tnc_attr.h \
pa_tnc/pa_tnc_msg.h pa_tnc/pa_tnc_msg.c \
pa_tnc/pa_tnc_attr_manager.h pa_tnc/pa_tnc_attr_manager.c
@@ -415,6 +425,8 @@ distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ietf_attr.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ietf_attr_assess_result.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ietf_attr_attr_request.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ietf_attr_pa_tnc_error.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ietf_attr_port_filter.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ietf_attr_product_info.Plo@am__quote@
@@ -423,6 +435,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imv_agent.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ita_attr.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ita_attr_command.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ita_attr_dummy.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pa_tnc_attr_manager.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pa_tnc_msg.Plo@am__quote@
@@ -489,6 +502,20 @@ ietf_attr_product_info.lo: ietf/ietf_attr_product_info.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ietf_attr_product_info.lo `test -f 'ietf/ietf_attr_product_info.c' || echo '$(srcdir)/'`ietf/ietf_attr_product_info.c
+ietf_attr_attr_request.lo: ietf/ietf_attr_attr_request.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ietf_attr_attr_request.lo -MD -MP -MF $(DEPDIR)/ietf_attr_attr_request.Tpo -c -o ietf_attr_attr_request.lo `test -f 'ietf/ietf_attr_attr_request.c' || echo '$(srcdir)/'`ietf/ietf_attr_attr_request.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ietf_attr_attr_request.Tpo $(DEPDIR)/ietf_attr_attr_request.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ietf/ietf_attr_attr_request.c' object='ietf_attr_attr_request.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ietf_attr_attr_request.lo `test -f 'ietf/ietf_attr_attr_request.c' || echo '$(srcdir)/'`ietf/ietf_attr_attr_request.c
+
+ietf_attr_assess_result.lo: ietf/ietf_attr_assess_result.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ietf_attr_assess_result.lo -MD -MP -MF $(DEPDIR)/ietf_attr_assess_result.Tpo -c -o ietf_attr_assess_result.lo `test -f 'ietf/ietf_attr_assess_result.c' || echo '$(srcdir)/'`ietf/ietf_attr_assess_result.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ietf_attr_assess_result.Tpo $(DEPDIR)/ietf_attr_assess_result.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ietf/ietf_attr_assess_result.c' object='ietf_attr_assess_result.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ietf_attr_assess_result.lo `test -f 'ietf/ietf_attr_assess_result.c' || echo '$(srcdir)/'`ietf/ietf_attr_assess_result.c
+
ita_attr.lo: ita/ita_attr.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ita_attr.lo -MD -MP -MF $(DEPDIR)/ita_attr.Tpo -c -o ita_attr.lo `test -f 'ita/ita_attr.c' || echo '$(srcdir)/'`ita/ita_attr.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ita_attr.Tpo $(DEPDIR)/ita_attr.Plo
@@ -503,6 +530,13 @@ ita_attr_command.lo: ita/ita_attr_command.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ita_attr_command.lo `test -f 'ita/ita_attr_command.c' || echo '$(srcdir)/'`ita/ita_attr_command.c
+ita_attr_dummy.lo: ita/ita_attr_dummy.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ita_attr_dummy.lo -MD -MP -MF $(DEPDIR)/ita_attr_dummy.Tpo -c -o ita_attr_dummy.lo `test -f 'ita/ita_attr_dummy.c' || echo '$(srcdir)/'`ita/ita_attr_dummy.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ita_attr_dummy.Tpo $(DEPDIR)/ita_attr_dummy.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ita/ita_attr_dummy.c' object='ita_attr_dummy.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ita_attr_dummy.lo `test -f 'ita/ita_attr_dummy.c' || echo '$(srcdir)/'`ita/ita_attr_dummy.c
+
pa_tnc_msg.lo: pa_tnc/pa_tnc_msg.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pa_tnc_msg.lo -MD -MP -MF $(DEPDIR)/pa_tnc_msg.Tpo -c -o pa_tnc_msg.lo `test -f 'pa_tnc/pa_tnc_msg.c' || echo '$(srcdir)/'`pa_tnc/pa_tnc_msg.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pa_tnc_msg.Tpo $(DEPDIR)/pa_tnc_msg.Plo
diff --git a/src/libimcv/ietf/ietf_attr.c b/src/libimcv/ietf/ietf_attr.c
index 89c6fc8db..fc89c5716 100644
--- a/src/libimcv/ietf/ietf_attr.c
+++ b/src/libimcv/ietf/ietf_attr.c
@@ -16,6 +16,8 @@
#include "ietf/ietf_attr_pa_tnc_error.h"
#include "ietf/ietf_attr_port_filter.h"
#include "ietf/ietf_attr_product_info.h"
+#include "ietf/ietf_attr_attr_request.h"
+#include "ietf/ietf_attr_assess_result.h"
ENUM(ietf_attr_names, IETF_ATTR_TESTING, IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED,
"Testing",
@@ -40,19 +42,21 @@ pa_tnc_attr_t* ietf_attr_create_from_data(u_int32_t type, chunk_t value)
{
switch (type)
{
+ case IETF_ATTR_ATTRIBUTE_REQUEST:
+ return ietf_attr_attr_request_create_from_data(value);
+ case IETF_ATTR_PRODUCT_INFORMATION:
+ return ietf_attr_product_info_create_from_data(value);
case IETF_ATTR_PORT_FILTER:
return ietf_attr_port_filter_create_from_data(value);
case IETF_ATTR_PA_TNC_ERROR:
return ietf_attr_pa_tnc_error_create_from_data(value);
- case IETF_ATTR_PRODUCT_INFORMATION:
- return ietf_attr_product_info_create_from_data(value);
+ case IETF_ATTR_ASSESSMENT_RESULT:
+ return ietf_attr_assess_result_create_from_data(value);
case IETF_ATTR_TESTING:
- case IETF_ATTR_ATTRIBUTE_REQUEST:
case IETF_ATTR_NUMERIC_VERSION:
case IETF_ATTR_STRING_VERSION:
case IETF_ATTR_OPERATIONAL_STATUS:
case IETF_ATTR_INSTALLED_PACKAGES:
- case IETF_ATTR_ASSESSMENT_RESULT:
case IETF_ATTR_REMEDIATION_INSTRUCTIONS:
case IETF_ATTR_FORWARDING_ENABLED:
case IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED:
diff --git a/src/libimcv/ietf/ietf_attr_assess_result.c b/src/libimcv/ietf/ietf_attr_assess_result.c
new file mode 100644
index 000000000..6893730bf
--- /dev/null
+++ b/src/libimcv/ietf/ietf_attr_assess_result.c
@@ -0,0 +1,209 @@
+/*
+ * 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.
+ */
+
+#include "ietf_attr_assess_result.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <debug.h>
+
+typedef struct private_ietf_attr_assess_result_t private_ietf_attr_assess_result_t;
+
+/**
+ * PA-TNC Product Information type (see section 4.2.2 of RFC 5792)
+ *
+ * 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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Assessment Result |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define ASSESS_RESULT_SIZE 4
+
+/**
+ * Private data of an ietf_attr_assess_result_t object.
+ */
+struct private_ietf_attr_assess_result_t {
+
+ /**
+ * Public members of ietf_attr_assess_result_t
+ */
+ ietf_attr_assess_result_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Attribute value
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * Assessment Result
+ */
+ u_int32_t result;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_ietf_attr_assess_result_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_ietf_attr_assess_result_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_ietf_attr_assess_result_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_ietf_attr_assess_result_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_ietf_attr_assess_result_t *this)
+{
+ bio_writer_t *writer;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+
+ writer = bio_writer_create(ASSESS_RESULT_SIZE);
+ writer->write_uint32(writer, this->result);
+ this->value = chunk_clone(writer->get_buf(writer));
+ writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_ietf_attr_assess_result_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+
+ if (this->value.len < ASSESS_RESULT_SIZE)
+ {
+ DBG1(DBG_TNC, "insufficient data for IETF assessment result");
+ *offset = 0;
+ return FAILED;
+ }
+ reader = bio_reader_create(this->value);
+ reader->read_uint32(reader, &this->result);
+ reader->destroy(reader);
+
+ return SUCCESS;
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_ietf_attr_assess_result_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_ietf_attr_assess_result_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->value.ptr);
+ free(this);
+ }
+}
+
+METHOD(ietf_attr_assess_result_t, get_result, u_int32_t,
+ private_ietf_attr_assess_result_t *this)
+{
+ return this->result;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *ietf_attr_assess_result_create(u_int32_t result)
+{
+ private_ietf_attr_assess_result_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,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_result = _get_result,
+ },
+ .type = { PEN_IETF, IETF_ATTR_ASSESSMENT_RESULT },
+ .result = result,
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *ietf_attr_assess_result_create_from_data(chunk_t data)
+{
+ private_ietf_attr_assess_result_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .build = _build,
+ .process = _process,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_result = _get_result,
+ },
+ .type = { PEN_IETF, IETF_ATTR_ASSESSMENT_RESULT },
+ .value = chunk_clone(data),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
diff --git a/src/libimcv/ietf/ietf_attr_assess_result.h b/src/libimcv/ietf/ietf_attr_assess_result.h
new file mode 100644
index 000000000..fab8bc3f0
--- /dev/null
+++ b/src/libimcv/ietf/ietf_attr_assess_result.h
@@ -0,0 +1,63 @@
+/*
+ * 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_assess_resultt ietf_attr_assess_result
+ * @{ @ingroup ietf
+ */
+
+#ifndef IETF_ATTR_ASSESS_RESULT_H_
+#define IETF_ATTR_ASSESS_RESULT_H_
+
+typedef struct ietf_attr_assess_result_t ietf_attr_assess_result_t;
+
+#include "ietf_attr.h"
+#include "pa_tnc/pa_tnc_attr.h"
+
+
+/**
+ * Class implementing the IETF PA-TNC Assessment Result attribute.
+ *
+ */
+struct ietf_attr_assess_result_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+
+ /**
+ * Get the assessment result
+ *
+ * @return Assessment Result
+ */
+ u_int32_t (*get_result)(ietf_attr_assess_result_t *this);
+
+};
+
+/**
+ * Creates an ietf_attr_assess_result_t object
+ *
+ */
+pa_tnc_attr_t* ietf_attr_assess_result_create(u_int32_t result);
+
+/**
+ * Creates an ietf_attr_assess_result_t object from received data
+ *
+ * @param value unparsed attribute value
+ */
+pa_tnc_attr_t* ietf_attr_assess_result_create_from_data(chunk_t value);
+
+#endif /** IETF_ATTR_ASSESS_RESULT_H_ @}*/
diff --git a/src/libimcv/ietf/ietf_attr_attr_request.c b/src/libimcv/ietf/ietf_attr_attr_request.c
new file mode 100644
index 000000000..c0dcd0983
--- /dev/null
+++ b/src/libimcv/ietf/ietf_attr_attr_request.c
@@ -0,0 +1,270 @@
+/*
+ * 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.
+ */
+
+#include "imcv.h"
+#include "ietf_attr_attr_request.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/linked_list.h>
+
+#include <debug.h>
+
+typedef struct private_ietf_attr_attr_request_t private_ietf_attr_attr_request_t;
+
+/**
+ * PA-TNC Attribute Request type (see section 4.2.1 of RFC 5792)
+ *
+ * 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 | PA-TNC Attribute Vendor ID |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | PA-TNC Attribute Type |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Reserved | PA-TNC Attribute Vendor ID |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | PA-TNC Attribute Type |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define ATTR_REQUEST_ENTRY_SIZE 8
+
+/**
+ * Private data of an ietf_attr_attr_request_t object.
+ */
+struct private_ietf_attr_attr_request_t {
+
+ /**
+ * Public members of ietf_attr_attr_request_t
+ */
+ ietf_attr_attr_request_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Attribute value
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * List of requested attribute types
+ */
+ linked_list_t *list;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_ietf_attr_attr_request_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_ietf_attr_attr_request_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_ietf_attr_attr_request_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_ietf_attr_attr_request_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_ietf_attr_attr_request_t *this)
+{
+ bio_writer_t *writer;
+ enumerator_t *enumerator;
+ pen_type_t *entry;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+ writer = bio_writer_create(ATTR_REQUEST_ENTRY_SIZE *
+ this->list->get_count(this->list));
+
+ enumerator = this->list->create_enumerator(this->list);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ writer->write_uint32(writer, entry->vendor_id);
+ writer->write_uint32(writer, entry->type);
+ }
+ enumerator->destroy(enumerator);
+
+ this->value = chunk_clone(writer->get_buf(writer));
+ writer->destroy(writer);
+}
+
+METHOD(ietf_attr_attr_request_t, add, void,
+ private_ietf_attr_attr_request_t *this, pen_t vendor_id, u_int32_t type)
+{
+ pen_type_t *entry;
+
+ entry = malloc_thing(pen_type_t);
+ entry->vendor_id = vendor_id;
+ entry->type = type;
+ this->list->insert_last(this->list, entry);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_ietf_attr_attr_request_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+ enum_name_t *pa_attr_names;
+ pen_t vendor_id;
+ u_int32_t type;
+ u_int8_t reserved;
+ int count;
+
+ count = this->value.len / ATTR_REQUEST_ENTRY_SIZE;
+ if (this->value.len != ATTR_REQUEST_ENTRY_SIZE * count)
+ {
+ DBG1(DBG_TNC, "incorrect attribute length for IETF attribute request");
+ *offset = 0;
+ return FAILED;
+ }
+
+ reader = bio_reader_create(this->value);
+ while (count--)
+ {
+ reader->read_uint8 (reader, &reserved);
+ reader->read_uint24(reader, &vendor_id);
+ reader->read_uint32(reader, &type);
+
+ pa_attr_names = imcv_pa_tnc_attributes->get_names(imcv_pa_tnc_attributes,
+ vendor_id);
+ if (pa_attr_names)
+ {
+ DBG2(DBG_TNC, " 0x%06x/0x%08x '%N/%N'", vendor_id, type,
+ pen_names, vendor_id, pa_attr_names, type);
+ }
+ else
+ {
+ DBG2(DBG_TNC, " 0x%06x/0x%08x '%N'", vendor_id, type,
+ pen_names, vendor_id);
+ }
+ add(this, vendor_id, type);
+ }
+ reader->destroy(reader);
+
+ return SUCCESS;
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_ietf_attr_attr_request_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_ietf_attr_attr_request_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ this->list->destroy_function(this->list, free);
+ free(this->value.ptr);
+ free(this);
+ }
+}
+
+METHOD(ietf_attr_attr_request_t, create_enumerator, enumerator_t*,
+ private_ietf_attr_attr_request_t *this)
+{
+ return this->list->create_enumerator(this->list);
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *ietf_attr_attr_request_create(pen_t vendor_id, u_int32_t type)
+{
+ private_ietf_attr_attr_request_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,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .add = _add,
+ .create_enumerator = _create_enumerator,
+ },
+ .type = { PEN_IETF, IETF_ATTR_ATTRIBUTE_REQUEST },
+ .list = linked_list_create(),
+ .ref = 1,
+ );
+ add(this, vendor_id, type);
+
+ return &this->public.pa_tnc_attribute;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *ietf_attr_attr_request_create_from_data(chunk_t data)
+{
+ private_ietf_attr_attr_request_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .build = _build,
+ .process = _process,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .add = _add,
+ .create_enumerator = _create_enumerator,
+ },
+ .type = { PEN_IETF,IETF_ATTR_ATTRIBUTE_REQUEST },
+ .value = chunk_clone(data),
+ .list = linked_list_create(),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
diff --git a/src/libimcv/ietf/ietf_attr_attr_request.h b/src/libimcv/ietf/ietf_attr_attr_request.h
new file mode 100644
index 000000000..22c5be0a0
--- /dev/null
+++ b/src/libimcv/ietf/ietf_attr_attr_request.h
@@ -0,0 +1,71 @@
+/*
+ * 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_attr_requestt ietf_attr_attr_request
+ * @{ @ingroup ietf
+ */
+
+#ifndef IETF_ATTR_ATTR_REQUEST_H_
+#define IETF_ATTR_ATTR_REQUEST_H_
+
+typedef struct ietf_attr_attr_request_t ietf_attr_attr_request_t;
+
+#include "ietf_attr.h"
+#include "pa_tnc/pa_tnc_attr.h"
+
+
+/**
+ * Class implementing the IETF PA-TNC Attribute Request attribute.
+ *
+ */
+struct ietf_attr_attr_request_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+
+ /**
+ * Adds another attribute type to the attribute request
+ *
+ * @param vendor_id Attribute Vendor ID
+ * @param type Attribute Type
+ */
+ void (*add)(ietf_attr_attr_request_t *this, pen_t vendor_id, u_int32_t type);
+
+ /**
+ * Creates an enumerator over all attribute types contained
+ * in the attribute request
+ *
+ * @return Attribute Type enumerator returns (vendor ID, type)
+ */
+ enumerator_t* (*create_enumerator)(ietf_attr_attr_request_t *this);
+};
+
+/**
+ * Creates an ietf_attr_attr_request_t object
+ *
+ */
+pa_tnc_attr_t* ietf_attr_attr_request_create(pen_t vendor_id, u_int32_t type);
+
+/**
+ * Creates an ietf_attr_attr_request_t object from received data
+ *
+ * @param value unparsed attribute value
+ */
+pa_tnc_attr_t* ietf_attr_attr_request_create_from_data(chunk_t value);
+
+#endif /** IETF_ATTR_ATTR_REQUEST_H_ @}*/
diff --git a/src/libimcv/ietf/ietf_attr_pa_tnc_error.c b/src/libimcv/ietf/ietf_attr_pa_tnc_error.c
index 6daee1a77..46f5d6716 100644
--- a/src/libimcv/ietf/ietf_attr_pa_tnc_error.c
+++ b/src/libimcv/ietf/ietf_attr_pa_tnc_error.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2011-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
@@ -107,14 +108,9 @@ struct private_ietf_attr_pa_tnc_error_t {
ietf_attr_pa_tnc_error_t public;
/**
- * Attribute vendor ID
+ * Vendor-specific attribute type
*/
- pen_t vendor_id;
-
- /**
- * Attribute type
- */
- u_int32_t type;
+ pen_type_t type;
/**
* Attribute value
@@ -127,14 +123,9 @@ struct private_ietf_attr_pa_tnc_error_t {
bool noskip_flag;
/**
- * Error code vendor ID
- */
- pen_t error_vendor_id;
-
- /**
- * Error code
+ * Vendor-specific error code
*/
- u_int32_t error_code;
+ pen_type_t error_code;
/**
* First 8 bytes of erroneous PA-TNC message
@@ -157,13 +148,7 @@ struct private_ietf_attr_pa_tnc_error_t {
refcount_t ref;
};
-METHOD(pa_tnc_attr_t, get_vendor_id, pen_t,
- private_ietf_attr_pa_tnc_error_t *this)
-{
- return this->vendor_id;
-}
-
-METHOD(pa_tnc_attr_t, get_type, u_int32_t,
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
private_ietf_attr_pa_tnc_error_t *this)
{
return this->type;
@@ -192,15 +177,19 @@ METHOD(pa_tnc_attr_t, build, void,
{
bio_writer_t *writer;
+ if (this->value.ptr)
+ {
+ return;
+ }
writer = bio_writer_create(PA_ERROR_HEADER_SIZE + PA_ERROR_MSG_INFO_SIZE);
writer->write_uint8 (writer, PA_ERROR_RESERVED);
- writer->write_uint24(writer, this->error_vendor_id);
- writer->write_uint32(writer, this->error_code);
+ writer->write_uint24(writer, this->error_code.vendor_id);
+ writer->write_uint32(writer, this->error_code.type);
writer->write_data (writer, this->msg_info);
- if (this->error_vendor_id == PEN_IETF)
+ if (this->error_code.vendor_id == PEN_IETF)
{
- switch (this->error_code)
+ switch (this->error_code.type)
{
case PA_ERROR_INVALID_PARAMETER:
writer->write_uint32(writer, this->error_offset);
@@ -235,10 +224,10 @@ METHOD(pa_tnc_attr_t, process, status_t,
}
reader = bio_reader_create(this->value);
reader->read_uint8 (reader, &reserved);
- reader->read_uint24(reader, &this->error_vendor_id);
- reader->read_uint32(reader, &this->error_code);
+ reader->read_uint24(reader, &this->error_code.vendor_id);
+ reader->read_uint32(reader, &this->error_code.type);
- if (this->error_vendor_id == PEN_IETF)
+ if (this->error_code.vendor_id == PEN_IETF)
{
if (!reader->read_data(reader, PA_ERROR_MSG_INFO_SIZE, &this->msg_info))
{
@@ -249,7 +238,7 @@ METHOD(pa_tnc_attr_t, process, status_t,
}
this->msg_info = chunk_clone(this->msg_info);
- switch (this->error_code)
+ switch (this->error_code.type)
{
case PA_ERROR_INVALID_PARAMETER:
if (!reader->read_uint32(reader, &this->error_offset))
@@ -305,13 +294,7 @@ METHOD(pa_tnc_attr_t, destroy, void,
}
}
-METHOD(ietf_attr_pa_tnc_error_t, get_error_vendor_id, pen_t,
- private_ietf_attr_pa_tnc_error_t *this)
-{
- return this->error_vendor_id;
-}
-
-METHOD(ietf_attr_pa_tnc_error_t, get_error_code, u_int32_t,
+METHOD(ietf_attr_pa_tnc_error_t, get_error_code, pen_type_t,
private_ietf_attr_pa_tnc_error_t *this)
{
return this->error_code;
@@ -344,13 +327,12 @@ METHOD(ietf_attr_pa_tnc_error_t, get_offset, u_int32_t,
/**
* Described in header.
*/
-pa_tnc_attr_t *ietf_attr_pa_tnc_error_create(pen_t vendor_id,
- u_int32_t error_code,
+pa_tnc_attr_t *ietf_attr_pa_tnc_error_create(pen_type_t error_code,
chunk_t msg_info)
{
private_ietf_attr_pa_tnc_error_t *this;
- if (vendor_id == PEN_IETF)
+ if (error_code.vendor_id == PEN_IETF)
{
msg_info.len = PA_ERROR_MSG_INFO_SIZE;
}
@@ -362,7 +344,6 @@ pa_tnc_attr_t *ietf_attr_pa_tnc_error_create(pen_t vendor_id,
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -372,16 +353,13 @@ pa_tnc_attr_t *ietf_attr_pa_tnc_error_create(pen_t vendor_id,
.get_ref = _get_ref,
.destroy = _destroy,
},
- .get_vendor_id = _get_error_vendor_id,
.get_error_code = _get_error_code,
.get_msg_info = _get_msg_info,
.get_attr_info = _get_attr_info,
.set_attr_info = _set_attr_info,
.get_offset = _get_offset,
},
- .vendor_id = PEN_IETF,
- .type = IETF_ATTR_PA_TNC_ERROR,
- .error_vendor_id = vendor_id,
+ .type = { PEN_IETF, IETF_ATTR_PA_TNC_ERROR },
.error_code = error_code,
.msg_info = chunk_clone(msg_info),
.ref = 1,
@@ -393,8 +371,7 @@ pa_tnc_attr_t *ietf_attr_pa_tnc_error_create(pen_t vendor_id,
/**
* Described in header.
*/
-pa_tnc_attr_t *ietf_attr_pa_tnc_error_create_with_offset(pen_t vendor_id,
- u_int32_t error_code,
+pa_tnc_attr_t *ietf_attr_pa_tnc_error_create_with_offset(pen_type_t error_code,
chunk_t msg_info,
u_int32_t error_offset)
{
@@ -406,7 +383,6 @@ pa_tnc_attr_t *ietf_attr_pa_tnc_error_create_with_offset(pen_t vendor_id,
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -416,16 +392,13 @@ pa_tnc_attr_t *ietf_attr_pa_tnc_error_create_with_offset(pen_t vendor_id,
.get_ref = _get_ref,
.destroy = _destroy,
},
- .get_vendor_id = _get_error_vendor_id,
.get_error_code = _get_error_code,
.get_msg_info = _get_msg_info,
.get_attr_info = _get_attr_info,
.set_attr_info = _set_attr_info,
.get_offset = _get_offset,
},
- .vendor_id = PEN_IETF,
- .type = IETF_ATTR_PA_TNC_ERROR,
- .error_vendor_id = vendor_id,
+ .type = { PEN_IETF, IETF_ATTR_PA_TNC_ERROR },
.error_code = error_code,
.msg_info = chunk_clone(msg_info),
.error_offset = error_offset,
@@ -445,7 +418,6 @@ pa_tnc_attr_t *ietf_attr_pa_tnc_error_create_from_data(chunk_t data)
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.build = _build,
@@ -453,15 +425,13 @@ pa_tnc_attr_t *ietf_attr_pa_tnc_error_create_from_data(chunk_t data)
.get_ref = _get_ref,
.destroy = _destroy,
},
- .get_vendor_id = _get_error_vendor_id,
.get_error_code = _get_error_code,
.get_msg_info = _get_msg_info,
.get_attr_info = _get_attr_info,
.set_attr_info = _set_attr_info,
.get_offset = _get_offset,
},
- .vendor_id = PEN_IETF,
- .type = IETF_ATTR_PA_TNC_ERROR,
+ .type = { PEN_IETF, IETF_ATTR_PA_TNC_ERROR },
.value = chunk_clone(data),
.ref = 1,
);
diff --git a/src/libimcv/ietf/ietf_attr_pa_tnc_error.h b/src/libimcv/ietf/ietf_attr_pa_tnc_error.h
index 945e06c62..d28c524aa 100644
--- a/src/libimcv/ietf/ietf_attr_pa_tnc_error.h
+++ b/src/libimcv/ietf/ietf_attr_pa_tnc_error.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
+ * Copyright (C) 2011-2012 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -62,11 +62,11 @@ struct ietf_attr_pa_tnc_error_t {
pen_t (*get_vendor_id)(ietf_attr_pa_tnc_error_t *this);
/**
- * Get PA-TNC error code
+ * Get Vendor-specific PA-TNC error code
*
* @return error code
*/
- pa_tnc_error_code_t (*get_error_code)(ietf_attr_pa_tnc_error_t *this);
+ pen_type_t (*get_error_code)(ietf_attr_pa_tnc_error_t *this);
/**
* Get first 8 bytes of erroneous PA-TNC message
@@ -101,26 +101,22 @@ struct ietf_attr_pa_tnc_error_t {
/**
* Creates an ietf_attr_pa_tnc_error_t object from an error code
*
- * @param vendor_id PA-TNC error code vendor ID
- * @param error_code PA-TNC error code
+ * @param error_code Vendor-specific PA-TNC error code
* @param header PA-TNC message header (first 8 bytes)
*
*/
-pa_tnc_attr_t* ietf_attr_pa_tnc_error_create(pen_t vendor_id,
- u_int32_t error_code,
+pa_tnc_attr_t* ietf_attr_pa_tnc_error_create(pen_type_t error_code,
chunk_t header);
/**
* Creates an ietf_attr_pa_tnc_error_t object from an error code with offset
*
- * @param vendor_id PA-TNC error code vendor ID
- * @param error_code PA-TNC error code
+ * @param error_code Vendor-specifica PA-TNC error code
* @param header PA-TNC message header (first 8 bytes)
* @param error_offset PA-TNC error offset in bytes
*
*/
-pa_tnc_attr_t* ietf_attr_pa_tnc_error_create_with_offset(pen_t vendor_id,
- u_int32_t error_code,
+pa_tnc_attr_t* ietf_attr_pa_tnc_error_create_with_offset(pen_type_t error_code,
chunk_t header,
u_int32_t error_offset);
diff --git a/src/libimcv/ietf/ietf_attr_port_filter.c b/src/libimcv/ietf/ietf_attr_port_filter.c
index b53019657..5ea52256b 100644
--- a/src/libimcv/ietf/ietf_attr_port_filter.c
+++ b/src/libimcv/ietf/ietf_attr_port_filter.c
@@ -58,14 +58,9 @@ struct private_ietf_attr_port_filter_t {
ietf_attr_port_filter_t public;
/**
- * Attribute vendor ID
+ * Vendor-specific attribute type
*/
- pen_t vendor_id;
-
- /**
- * Attribute type
- */
- u_int32_t type;
+ pen_type_t type;
/**
* Attribute value
@@ -88,13 +83,7 @@ struct private_ietf_attr_port_filter_t {
refcount_t ref;
};
-METHOD(pa_tnc_attr_t, get_vendor_id, pen_t,
- private_ietf_attr_port_filter_t *this)
-{
- return this->vendor_id;
-}
-
-METHOD(pa_tnc_attr_t, get_type, u_int32_t,
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
private_ietf_attr_port_filter_t *this)
{
return this->type;
@@ -125,6 +114,10 @@ METHOD(pa_tnc_attr_t, build, void,
enumerator_t *enumerator;
port_entry_t *entry;
+ if (this->value.ptr)
+ {
+ return;
+ }
writer = bio_writer_create(this->ports->get_count(this->ports) *
PORT_FILTER_ENTRY_SIZE);
@@ -232,7 +225,6 @@ pa_tnc_attr_t *ietf_attr_port_filter_create(void)
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -245,8 +237,7 @@ pa_tnc_attr_t *ietf_attr_port_filter_create(void)
.add_port = _add_port,
.create_port_enumerator = _create_port_enumerator,
},
- .vendor_id = PEN_IETF,
- .type = IETF_ATTR_PORT_FILTER,
+ .type = { PEN_IETF, IETF_ATTR_PORT_FILTER },
.ports = linked_list_create(),
.ref = 1,
);
@@ -264,7 +255,6 @@ pa_tnc_attr_t *ietf_attr_port_filter_create_from_data(chunk_t data)
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.build = _build,
@@ -275,8 +265,7 @@ pa_tnc_attr_t *ietf_attr_port_filter_create_from_data(chunk_t data)
.add_port = _add_port,
.create_port_enumerator = _create_port_enumerator,
},
- .vendor_id = PEN_IETF,
- .type = IETF_ATTR_PORT_FILTER,
+ .type = {PEN_IETF, IETF_ATTR_PORT_FILTER },
.value = chunk_clone(data),
.ports = linked_list_create(),
.ref = 1,
diff --git a/src/libimcv/ietf/ietf_attr_product_info.c b/src/libimcv/ietf/ietf_attr_product_info.c
index 548793547..dcc0e0294 100644
--- a/src/libimcv/ietf/ietf_attr_product_info.c
+++ b/src/libimcv/ietf/ietf_attr_product_info.c
@@ -46,14 +46,9 @@ struct private_ietf_attr_product_info_t {
ietf_attr_product_info_t public;
/**
- * Attribute vendor ID
+ * Vendor-specific attribute type
*/
- pen_t vendor_id;
-
- /**
- * Attribute type
- */
- u_int32_t type;
+ pen_type_t type;
/**
* Attribute value
@@ -86,13 +81,7 @@ struct private_ietf_attr_product_info_t {
refcount_t ref;
};
-METHOD(pa_tnc_attr_t, get_vendor_id, pen_t,
- private_ietf_attr_product_info_t *this)
-{
- return this->vendor_id;
-}
-
-METHOD(pa_tnc_attr_t, get_type, u_int32_t,
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
private_ietf_attr_product_info_t *this)
{
return this->type;
@@ -122,6 +111,10 @@ METHOD(pa_tnc_attr_t, build, void,
bio_writer_t *writer;
chunk_t product_name;
+ if (this->value.ptr)
+ {
+ return;
+ }
product_name = chunk_create(this->product_name, strlen(this->product_name));
writer = bio_writer_create(PRODUCT_INFO_MIN_SIZE);
@@ -201,7 +194,6 @@ pa_tnc_attr_t *ietf_attr_product_info_create(pen_t vendor_id, u_int16_t id,
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -213,8 +205,7 @@ pa_tnc_attr_t *ietf_attr_product_info_create(pen_t vendor_id, u_int16_t id,
},
.get_info = _get_info,
},
- .vendor_id = PEN_IETF,
- .type = IETF_ATTR_PRODUCT_INFORMATION,
+ .type = { PEN_IETF, IETF_ATTR_PRODUCT_INFORMATION },
.product_vendor_id = vendor_id,
.product_id = id,
.product_name = strdup(name),
@@ -234,7 +225,6 @@ pa_tnc_attr_t *ietf_attr_product_info_create_from_data(chunk_t data)
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.build = _build,
@@ -244,8 +234,7 @@ pa_tnc_attr_t *ietf_attr_product_info_create_from_data(chunk_t data)
},
.get_info = _get_info,
},
- .vendor_id = PEN_IETF,
- .type = IETF_ATTR_PRODUCT_INFORMATION,
+ .type = { PEN_IETF, IETF_ATTR_PRODUCT_INFORMATION },
.value = chunk_clone(data),
.ref = 1,
);
diff --git a/src/libimcv/imc/imc_agent.c b/src/libimcv/imc/imc_agent.c
index de2f959a4..8d1e70716 100644
--- a/src/libimcv/imc/imc_agent.c
+++ b/src/libimcv/imc/imc_agent.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2011-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
@@ -18,7 +19,6 @@
#include <tncif_names.h>
#include <debug.h>
-#include <utils/linked_list.h>
#include <threading/rwlock.h>
typedef struct private_imc_agent_t private_imc_agent_t;
@@ -333,12 +333,31 @@ static char* get_str_attribute(private_imc_agent_t *this, TNC_ConnectionID id,
return NULL;
}
+/**
+ * Read an UInt32 attribute
+ */
+static u_int32_t get_uint_attribute(private_imc_agent_t *this, TNC_ConnectionID id,
+ TNC_AttributeID attribute_id)
+{
+ TNC_UInt32 len;
+ char buf[4];
+
+ if (this->get_attribute &&
+ this->get_attribute(this->id, id, attribute_id, 4, buf, &len) ==
+ TNC_RESULT_SUCCESS && len == 4)
+ {
+ return untoh32(buf);
+ }
+ return 0;
+ }
+
METHOD(imc_agent_t, create_state, TNC_Result,
private_imc_agent_t *this, imc_state_t *state)
{
TNC_ConnectionID conn_id;
char *tnccs_p = NULL, *tnccs_v = NULL, *t_p = NULL, *t_v = NULL;
bool has_long = FALSE, has_excl = FALSE, has_soh = FALSE;
+ u_int32_t max_msg_len;
conn_id = state->get_connection_id(state);
if (find_connection(this, conn_id))
@@ -357,14 +376,18 @@ METHOD(imc_agent_t, create_state, TNC_Result,
tnccs_v = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFTNCCS_VERSION);
t_p = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFT_PROTOCOL);
t_v = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFT_VERSION);
+ max_msg_len = get_uint_attribute(this, conn_id, TNC_ATTRIBUTEID_MAX_MESSAGE_SIZE);
state->set_flags(state, has_long, has_excl);
+ state->set_max_msg_len(state, max_msg_len);
+
+ DBG2(DBG_IMC, "IMC %u \"%s\" created a state for %s %s Connection ID %u: "
+ "%slong %sexcl %ssoh", this->id, this->name,
+ tnccs_p ? tnccs_p:"?", tnccs_v ? tnccs_v:"?", conn_id,
+ has_long ? "+":"-", has_excl ? "+":"-", has_soh ? "+":"-");
+ DBG2(DBG_IMC, " over %s %s with maximum PA-TNC message size of %u bytes",
+ t_p ? t_p:"?", t_v ? t_v :"?", max_msg_len);
- DBG2(DBG_IMC, "IMC %u \"%s\" created a state for Connection ID %u: "
- "%s %s with %slong %sexcl %ssoh over %s %s",
- this->id, this->name, conn_id, tnccs_p ? tnccs_p:"?",
- tnccs_v ? tnccs_v:"?", has_long ? "+":"-", has_excl ? "+":"-",
- has_soh ? "+":"-", t_p ? t_p:"?", t_v ? t_v :"?");
free(tnccs_p);
free(tnccs_v);
free(t_p);
@@ -453,11 +476,17 @@ METHOD(imc_agent_t, get_state, bool,
METHOD(imc_agent_t, send_message, TNC_Result,
private_imc_agent_t *this, TNC_ConnectionID connection_id, bool excl,
- TNC_UInt32 src_imc_id, TNC_UInt32 dst_imv_id, chunk_t msg)
+ TNC_UInt32 src_imc_id, TNC_UInt32 dst_imv_id, linked_list_t *attr_list)
{
TNC_MessageType type;
TNC_UInt32 msg_flags;
+ TNC_Result result = TNC_RESULT_FATAL;
imc_state_t *state;
+ pa_tnc_attr_t *attr;
+ pa_tnc_msg_t *pa_tnc_msg;
+ chunk_t msg;
+ enumerator_t *enumerator;
+ bool attr_added;
state = find_connection(this, connection_id);
if (!state)
@@ -467,26 +496,70 @@ METHOD(imc_agent_t, send_message, TNC_Result,
return TNC_RESULT_FATAL;
}
- if (state->has_long(state) && this->send_message_long)
+ while (attr_list->get_count(attr_list))
{
- if (!src_imc_id)
+ pa_tnc_msg = pa_tnc_msg_create(state->get_max_msg_len(state));
+ attr_added = FALSE;
+
+ enumerator = attr_list->create_enumerator(attr_list);
+ while (enumerator->enumerate(enumerator, &attr))
{
- src_imc_id = this->id;
+ if (pa_tnc_msg->add_attribute(pa_tnc_msg, attr))
+ {
+ attr_added = TRUE;
+ }
+ else
+ {
+ if (attr_added)
+ {
+ break;
+ }
+ else
+ {
+ DBG1(DBG_IMC, "PA-TNC attribute too large to send, deleted");
+ attr->destroy(attr);
+ }
+ }
+ attr_list->remove_at(attr_list, enumerator);
}
- msg_flags = excl ? TNC_MESSAGE_FLAGS_EXCLUSIVE : 0;
+ enumerator->destroy(enumerator);
- return this->send_message_long(src_imc_id, connection_id, msg_flags,
- msg.ptr, msg.len, this->vendor_id,
- this->subtype, dst_imv_id);
- }
- if (this->send_message)
- {
- type = (this->vendor_id << 8) | this->subtype;
+ /* build and send the PA-TNC message via the IF-IMC interface */
+ if (!pa_tnc_msg->build(pa_tnc_msg))
+ {
+ pa_tnc_msg->destroy(pa_tnc_msg);
+ return TNC_RESULT_FATAL;
+ }
+ msg = pa_tnc_msg->get_encoding(pa_tnc_msg);
+
+ if (state->has_long(state) && this->send_message_long)
+ {
+ if (!src_imc_id)
+ {
+ src_imc_id = this->id;
+ }
+ msg_flags = excl ? TNC_MESSAGE_FLAGS_EXCLUSIVE : 0;
+
+ result = this->send_message_long(src_imc_id, connection_id,
+ msg_flags, msg.ptr, msg.len, this->vendor_id,
+ this->subtype, dst_imv_id);
+ }
+ else if (this->send_message)
+ {
+ type = (this->vendor_id << 8) | this->subtype;
- return this->send_message(this->id, connection_id, msg.ptr, msg.len,
- type);
+ result = this->send_message(this->id, connection_id, msg.ptr,
+ msg.len, type);
+ }
+
+ pa_tnc_msg->destroy(pa_tnc_msg);
+
+ if (result != TNC_RESULT_SUCCESS)
+ {
+ break;
+ }
}
- return TNC_RESULT_FATAL;
+ return result;
}
METHOD(imc_agent_t, receive_message, TNC_Result,
@@ -494,11 +567,11 @@ METHOD(imc_agent_t, receive_message, TNC_Result,
TNC_VendorID msg_vid, TNC_MessageSubtype msg_subtype,
TNC_UInt32 src_imv_id, TNC_UInt32 dst_imc_id, pa_tnc_msg_t **pa_tnc_msg)
{
- pa_tnc_msg_t *pa_msg, *error_msg;
+ pa_tnc_msg_t *pa_msg;
pa_tnc_attr_t *error_attr;
+ linked_list_t *error_attr_list;
enumerator_t *enumerator;
- TNC_MessageType msg_type;
- TNC_UInt32 msg_flags, src_imc_id, dst_imv_id;
+ TNC_UInt32 src_imc_id, dst_imv_id;
TNC_ConnectionID connection_id;
TNC_Result result;
@@ -534,51 +607,24 @@ METHOD(imc_agent_t, receive_message, TNC_Result,
*pa_tnc_msg = pa_msg;
break;
case VERIFY_ERROR:
- /* build error message */
- error_msg = pa_tnc_msg_create();
+ /* extract and copy by refence all error attributes */
+ error_attr_list = linked_list_create();
+
enumerator = pa_msg->create_error_enumerator(pa_msg);
while (enumerator->enumerate(enumerator, &error_attr))
{
- error_msg->add_attribute(error_msg,
- error_attr->get_ref(error_attr));
+ error_attr_list->insert_last(error_attr_list,
+ error_attr->get_ref(error_attr));
}
enumerator->destroy(enumerator);
- error_msg->build(error_msg);
-
- /* send error message */
- if (state->has_long(state) && this->send_message_long)
- {
- if (state->has_excl(state))
- {
- msg_flags = TNC_MESSAGE_FLAGS_EXCLUSIVE;
- dst_imv_id = src_imv_id;
- }
- else
- {
- msg_flags = 0;
- dst_imv_id = TNC_IMVID_ANY;
- }
- src_imc_id = (dst_imc_id == TNC_IMCID_ANY) ? this->id
- : dst_imc_id;
- result = this->send_message_long(src_imc_id, connection_id,
- msg_flags, msg.ptr, msg.len, msg_vid,
- msg_subtype, dst_imv_id);
- }
- else if (this->send_message)
- {
- msg_type = (msg_vid << 8) | msg_subtype;
+ src_imc_id = (dst_imc_id == TNC_IMCID_ANY) ? this->id : dst_imc_id;
+ dst_imv_id = state->has_excl(state) ? src_imv_id : TNC_IMVID_ANY;
- result = this->send_message(this->id, connection_id,
- msg.ptr, msg.len, msg_type);
- }
- else
- {
- result = TNC_RESULT_FATAL;
- }
+ result = send_message(this, connection_id, state->has_excl(state),
+ src_imc_id, dst_imv_id, error_attr_list);
- /* clean up */
- error_msg->destroy(error_msg);
+ error_attr_list->destroy(error_attr_list);
pa_msg->destroy(pa_msg);
return result;
case FAILED:
diff --git a/src/libimcv/imc/imc_agent.h b/src/libimcv/imc/imc_agent.h
index d1fef4d8d..e87450aa6 100644
--- a/src/libimcv/imc/imc_agent.h
+++ b/src/libimcv/imc/imc_agent.h
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2011-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
@@ -26,6 +27,7 @@
#include <tncifimc.h>
#include <pen/pen.h>
+#include <utils/linked_list.h>
#include <library.h>
@@ -104,13 +106,13 @@ struct imc_agent_t {
* @param excl exclusive flag
* @param src_imc_id IMC ID to be set as source
* @param dst_imv_id IMV ID to be set as destination
- * @param msg message to send
+ * @param attr_list list of PA-TNC attributes to send
* @return TNC result code
*/
TNC_Result (*send_message)(imc_agent_t *this,
TNC_ConnectionID connection_id, bool excl,
TNC_UInt32 src_imc_id, TNC_UInt32 dst_imv_id,
- chunk_t msg);
+ linked_list_t *attr_list);
/**
* Call when a PA-TNC message was received
diff --git a/src/libimcv/imc/imc_state.h b/src/libimcv/imc/imc_state.h
index f1b0358c9..c34441f0f 100644
--- a/src/libimcv/imc/imc_state.h
+++ b/src/libimcv/imc/imc_state.h
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2011-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
@@ -22,6 +23,8 @@
#define IMC_STATE_H_
#include <tncif.h>
+#include <tncifimv.h>
+#include <tncifimc.h>
#include <library.h>
@@ -33,8 +36,7 @@ typedef struct imc_state_t imc_state_t;
struct imc_state_t {
/**
- * Get the TNCS connection I
-D attached to the state
+ * Get the TNCS connection ID attached to the state
*
* @return TNCS connection ID of the state
*/
@@ -64,6 +66,20 @@ D attached to the state
void (*set_flags)(imc_state_t *this, bool has_long, bool has_excl);
/**
+ * Set the maximum size of a PA-TNC message for this TNCCS connection
+ *
+ * @max_msg_len maximum size of a PA-TNC message
+ */
+ void (*set_max_msg_len)(imc_state_t *this, u_int32_t max_msg_len);
+
+ /**
+ * Get the maximum size of a PA-TNC message for this TNCCS connection
+ *
+ * @return maximum size of a PA-TNC message
+ */
+ u_int32_t (*get_max_msg_len)(imc_state_t *this);
+
+ /**
* Change the connection state
*
* @param new_state new connection state
@@ -71,6 +87,25 @@ D attached to the state
void (*change_state)(imc_state_t *this, TNC_ConnectionState new_state);
/**
+ * Set the Assessment/Evaluation Result
+ *
+ * @param id IMC ID
+ * @param result Assessment/Evaluation Result
+ */
+ void (*set_result)(imc_state_t *this, TNC_IMCID id,
+ TNC_IMV_Evaluation_Result result);
+
+ /**
+ * Get the Assessment/Evaluation Result
+ *
+ * @param id IMC ID
+ * @param result Assessment/Evaluation Result
+ * @return TRUE if result is known
+ */
+ bool (*get_result)(imc_state_t *this, TNC_IMCID id,
+ TNC_IMV_Evaluation_Result *result);
+
+ /**
* Destroys an imc_state_t object
*/
void (*destroy)(imc_state_t *this);
diff --git a/src/libimcv/imcv.c b/src/libimcv/imcv.c
index a8c0af47b..b84548f9b 100644
--- a/src/libimcv/imcv.c
+++ b/src/libimcv/imcv.c
@@ -108,7 +108,7 @@ bool libimcv_init(void)
}
if (!lib->plugins->load(lib->plugins, NULL,
- "sha1 sha2 random gmp pubkey x509"))
+ "sha1 sha2 random nonce gmp pubkey x509"))
{
library_deinit();
return FALSE;
diff --git a/src/libimcv/imv/imv_agent.c b/src/libimcv/imv/imv_agent.c
index 56131c547..fa04e0237 100644
--- a/src/libimcv/imv/imv_agent.c
+++ b/src/libimcv/imv/imv_agent.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2011-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
@@ -14,11 +15,11 @@
#include "imcv.h"
#include "imv_agent.h"
+#include "ietf/ietf_attr_assess_result.h"
#include <tncif_names.h>
#include <debug.h>
-#include <utils/linked_list.h>
#include <threading/rwlock.h>
typedef struct private_imv_agent_t private_imv_agent_t;
@@ -49,6 +50,11 @@ struct private_imv_agent_t {
TNC_MessageSubtype subtype;
/**
+ * Maximum PA-TNC Message size
+ */
+ size_t max_msg_len;
+
+ /**
* ID of IMV as assigned by TNCS
*/
TNC_IMVID id;
@@ -351,12 +357,31 @@ static char* get_str_attribute(private_imv_agent_t *this, TNC_ConnectionID id,
return NULL;
}
+/**
+ * Read an UInt32 attribute
+ */
+static u_int32_t get_uint_attribute(private_imv_agent_t *this, TNC_ConnectionID id,
+ TNC_AttributeID attribute_id)
+{
+ TNC_UInt32 len;
+ char buf[4];
+
+ if (this->get_attribute &&
+ this->get_attribute(this->id, id, attribute_id, 4, buf, &len) ==
+ TNC_RESULT_SUCCESS && len == 4)
+ {
+ return untoh32(buf);
+ }
+ return 0;
+ }
+
METHOD(imv_agent_t, create_state, TNC_Result,
private_imv_agent_t *this, imv_state_t *state)
{
TNC_ConnectionID conn_id;
char *tnccs_p = NULL, *tnccs_v = NULL, *t_p = NULL, *t_v = NULL;
bool has_long = FALSE, has_excl = FALSE, has_soh = FALSE;
+ u_int32_t max_msg_len;
conn_id = state->get_connection_id(state);
if (find_connection(this, conn_id))
@@ -371,18 +396,22 @@ METHOD(imv_agent_t, create_state, TNC_Result,
has_long = get_bool_attribute(this, conn_id, TNC_ATTRIBUTEID_HAS_LONG_TYPES);
has_excl = get_bool_attribute(this, conn_id, TNC_ATTRIBUTEID_HAS_EXCLUSIVE);
has_soh = get_bool_attribute(this, conn_id, TNC_ATTRIBUTEID_HAS_SOH);
- tnccs_p = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFTNCCS_PROTOCOL);
+ tnccs_p = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFTNCCS_PROTOCOL);
tnccs_v = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFTNCCS_VERSION);
t_p = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFT_PROTOCOL);
t_v = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFT_VERSION);
+ max_msg_len = get_uint_attribute(this, conn_id, TNC_ATTRIBUTEID_MAX_MESSAGE_SIZE);
state->set_flags(state, has_long, has_excl);
+ state->set_max_msg_len(state, max_msg_len);
+
+ DBG2(DBG_IMV, "IMV %u \"%s\" created a state for %s %s Connection ID %u: "
+ "%slong %sexcl %ssoh", this->id, this->name,
+ tnccs_p ? tnccs_p:"?", tnccs_v ? tnccs_v:"?", conn_id,
+ has_long ? "+":"-", has_excl ? "+":"-", has_soh ? "+":"-");
+ DBG2(DBG_IMV, " over %s %s with maximum PA-TNC message size of %u bytes",
+ t_p ? t_p:"?", t_v ? t_v :"?", max_msg_len);
- DBG2(DBG_IMV, "IMV %u \"%s\" created a state for Connection ID %u: "
- "%s %s with %slong %sexcl %ssoh over %s %s",
- this->id, this->name, conn_id, tnccs_p ? tnccs_p:"?",
- tnccs_v ? tnccs_v:"?", has_long ? "+":"-", has_excl ? "+":"-",
- has_soh ? "+":"-", t_p ? t_p:"?", t_v ? t_v :"?");
free(tnccs_p);
free(tnccs_v);
free(t_p);
@@ -449,7 +478,7 @@ METHOD(imv_agent_t, change_state, TNC_Result,
DBG1(DBG_IMV, "IMV %u \"%s\" was notified of unknown state %u "
"for Connection ID %u",
this->id, this->name, new_state, connection_id);
- return TNC_RESULT_INVALID_PARAMETER;
+ return TNC_RESULT_INVALID_PARAMETER;
}
return TNC_RESULT_SUCCESS;
}
@@ -470,11 +499,17 @@ METHOD(imv_agent_t, get_state, bool,
METHOD(imv_agent_t, send_message, TNC_Result,
private_imv_agent_t *this, TNC_ConnectionID connection_id, bool excl,
- TNC_UInt32 src_imv_id, TNC_UInt32 dst_imc_id, chunk_t msg)
+ TNC_UInt32 src_imv_id, TNC_UInt32 dst_imc_id, linked_list_t *attr_list)
{
TNC_MessageType type;
TNC_UInt32 msg_flags;
+ TNC_Result result = TNC_RESULT_FATAL;
imv_state_t *state;
+ pa_tnc_attr_t *attr;
+ pa_tnc_msg_t *pa_tnc_msg;
+ chunk_t msg;
+ enumerator_t *enumerator;
+ bool attr_added;
state = find_connection(this, connection_id);
if (!state)
@@ -484,26 +519,70 @@ METHOD(imv_agent_t, send_message, TNC_Result,
return TNC_RESULT_FATAL;
}
- if (state->has_long(state) && this->send_message_long)
+ while (attr_list->get_count(attr_list))
{
- if (!src_imv_id)
+ pa_tnc_msg = pa_tnc_msg_create(this->max_msg_len);
+ attr_added = FALSE;
+
+ enumerator = attr_list->create_enumerator(attr_list);
+ while (enumerator->enumerate(enumerator, &attr))
+ {
+ if (pa_tnc_msg->add_attribute(pa_tnc_msg, attr))
+ {
+ attr_added = TRUE;
+ }
+ else
+ {
+ if (attr_added)
+ {
+ break;
+ }
+ else
+ {
+ DBG1(DBG_IMV, "PA-TNC attribute too large to send, deleted");
+ attr->destroy(attr);
+ }
+ }
+ attr_list->remove_at(attr_list, enumerator);
+ }
+ enumerator->destroy(enumerator);
+
+ /* build and send the PA-TNC message via the IF-IMV interface */
+ if (!pa_tnc_msg->build(pa_tnc_msg))
{
- src_imv_id = this->id;
+ pa_tnc_msg->destroy(pa_tnc_msg);
+ return TNC_RESULT_FATAL;
}
- msg_flags = excl ? TNC_MESSAGE_FLAGS_EXCLUSIVE : 0;
+ msg = pa_tnc_msg->get_encoding(pa_tnc_msg);
- return this->send_message_long(src_imv_id, connection_id, msg_flags,
- msg.ptr, msg.len, this->vendor_id,
- this->subtype, dst_imc_id);
- }
- if (this->send_message)
- {
- type = (this->vendor_id << 8) | this->subtype;
+ if (state->has_long(state) && this->send_message_long)
+ {
+ if (!src_imv_id)
+ {
+ src_imv_id = this->id;
+ }
+ msg_flags = excl ? TNC_MESSAGE_FLAGS_EXCLUSIVE : 0;
- return this->send_message(this->id, connection_id, msg.ptr, msg.len,
- type);
+ result = this->send_message_long(src_imv_id, connection_id,
+ msg_flags, msg.ptr, msg.len, this->vendor_id,
+ this->subtype, dst_imc_id);
+ }
+ else if (this->send_message)
+ {
+ type = (this->vendor_id << 8) | this->subtype;
+
+ result = this->send_message(this->id, connection_id, msg.ptr,
+ msg.len, type);
+ }
+
+ pa_tnc_msg->destroy(pa_tnc_msg);
+
+ if (result != TNC_RESULT_SUCCESS)
+ {
+ break;
+ }
}
- return TNC_RESULT_FATAL;
+ return result;
}
METHOD(imv_agent_t, set_recommendation, TNC_Result,
@@ -530,11 +609,11 @@ METHOD(imv_agent_t, receive_message, TNC_Result,
TNC_VendorID msg_vid, TNC_MessageSubtype msg_subtype,
TNC_UInt32 src_imc_id, TNC_UInt32 dst_imv_id, pa_tnc_msg_t **pa_tnc_msg)
{
- pa_tnc_msg_t *pa_msg, *error_msg;
+ pa_tnc_msg_t *pa_msg;
pa_tnc_attr_t *error_attr;
+ linked_list_t *error_attr_list;
enumerator_t *enumerator;
- TNC_MessageType msg_type;
- TNC_UInt32 msg_flags, src_imv_id, dst_imc_id;
+ TNC_UInt32 src_imv_id, dst_imc_id;
TNC_ConnectionID connection_id;
TNC_Result result;
@@ -570,53 +649,24 @@ METHOD(imv_agent_t, receive_message, TNC_Result,
*pa_tnc_msg = pa_msg;
break;
case VERIFY_ERROR:
- /* build error message */
- error_msg = pa_tnc_msg_create();
+ /* extract and copy by refence all error attributes */
+ error_attr_list = linked_list_create();
+
enumerator = pa_msg->create_error_enumerator(pa_msg);
while (enumerator->enumerate(enumerator, &error_attr))
{
- error_msg->add_attribute(error_msg,
- error_attr->get_ref(error_attr));
+ error_attr_list->insert_last(error_attr_list,
+ error_attr->get_ref(error_attr));
}
enumerator->destroy(enumerator);
- error_msg->build(error_msg);
- /* send error message */
- msg = error_msg->get_encoding(error_msg);
+ src_imv_id = (dst_imv_id == TNC_IMVID_ANY) ? this->id : dst_imv_id;
+ dst_imc_id = state->has_excl(state) ? src_imc_id : TNC_IMCID_ANY;
- if (state->has_long(state) && this->send_message_long)
- {
- if (state->has_excl(state))
- {
- msg_flags = TNC_MESSAGE_FLAGS_EXCLUSIVE;
- dst_imc_id = src_imc_id;
- }
- else
- {
- msg_flags = 0;
- dst_imc_id = TNC_IMCID_ANY;
- }
- src_imv_id = (dst_imv_id == TNC_IMVID_ANY) ? this->id
- : dst_imv_id;
-
- result = this->send_message_long(src_imv_id, connection_id,
- msg_flags, msg.ptr, msg.len, msg_vid,
- msg_subtype, dst_imc_id);
- }
- else if (this->send_message)
- {
- msg_type = (msg_vid << 8) | msg_subtype;
+ result = send_message(this, connection_id, state->has_excl(state),
+ src_imv_id, dst_imc_id, error_attr_list);
- result = this->send_message(this->id, connection_id,
- msg.ptr, msg.len, msg_type);
- }
- else
- {
- result = TNC_RESULT_FATAL;
- }
-
- /* clean up */
- error_msg->destroy(error_msg);
+ error_attr_list->destroy(error_attr_list);
pa_msg->destroy(pa_msg);
return result;
case FAILED:
@@ -633,9 +683,13 @@ METHOD(imv_agent_t, receive_message, TNC_Result,
}
METHOD(imv_agent_t, provide_recommendation, TNC_Result,
- private_imv_agent_t *this, TNC_ConnectionID connection_id)
+ private_imv_agent_t *this, TNC_ConnectionID connection_id,
+ TNC_UInt32 dst_imc_id)
{
imv_state_t *state;
+ linked_list_t *attr_list;
+ pa_tnc_attr_t *attr;
+ TNC_Result result;
TNC_IMV_Action_Recommendation rec;
TNC_IMV_Evaluation_Result eval;
TNC_UInt32 lang_len;
@@ -651,7 +705,6 @@ METHOD(imv_agent_t, provide_recommendation, TNC_Result,
}
state->get_recommendation(state, &rec, &eval);
-
/* send a reason string if action recommendation is not allow */
if (rec != TNC_IMV_ACTION_RECOMMENDATION_ALLOW)
{
@@ -663,8 +716,8 @@ METHOD(imv_agent_t, provide_recommendation, TNC_Result,
lang_len <= BUF_LEN)
{
pref_lang.len = lang_len;
- DBG2(DBG_IMV, "preferred language is '%.*s'",
- pref_lang.len, pref_lang.ptr);
+ DBG2(DBG_IMV, "preferred language is '%.*s'", (int)pref_lang.len,
+ pref_lang.ptr);
}
/* find a reason string for the preferred or default language and set it */
@@ -680,7 +733,21 @@ METHOD(imv_agent_t, provide_recommendation, TNC_Result,
reason_lang.len, reason_lang.ptr);
}
}
-
+
+ /* Send an IETF Assessment Result attribute if enabled */
+ if (lib->settings->get_bool(lib->settings, "libimcv.assessment_result", TRUE))
+ {
+ attr = ietf_attr_assess_result_create(eval);
+ attr_list = linked_list_create();
+ attr_list->insert_last(attr_list, attr);
+ result = send_message(this, connection_id, FALSE, this->id, dst_imc_id,
+ attr_list);
+ attr_list->destroy(attr_list);
+ if (result != TNC_RESULT_SUCCESS)
+ {
+ return result;
+ }
+ }
return this->provide_recommendation(this->id, connection_id, rec, eval);
}
@@ -777,6 +844,7 @@ imv_agent_t *imv_agent_create(const char *name,
.name = name,
.vendor_id = vendor_id,
.subtype = subtype,
+ .max_msg_len = 65490,
.id = id,
.additional_ids = linked_list_create(),
.connections = linked_list_create(),
diff --git a/src/libimcv/imv/imv_agent.h b/src/libimcv/imv/imv_agent.h
index de70f3bc1..34ac3c109 100644
--- a/src/libimcv/imv/imv_agent.h
+++ b/src/libimcv/imv/imv_agent.h
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2011-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
@@ -26,6 +27,7 @@
#include <tncifimv.h>
#include <pen/pen.h>
+#include <utils/linked_list.h>
#include <library.h>
@@ -104,13 +106,13 @@ struct imv_agent_t {
* @param excl exclusive flag
* @param src_imv_id IMV ID to be set as source
* @param dst_imc_id IMD ID to be set as destination
- * @param msg message to send
+ * @param attr_list list of PA-TNC attributes to send
* @return TNC result code
*/
TNC_Result (*send_message)(imv_agent_t *this,
TNC_ConnectionID connection_id, bool excl,
TNC_UInt32 src_imv_id, TNC_UInt32 dst_imc_id,
- chunk_t msg);
+ linked_list_t *attr_list);
/**
* Call when a PA-TNC message was received
@@ -149,10 +151,12 @@ struct imv_agent_t {
* Deliver IMV Action Recommendation and IMV Evaluation Result to the TNCS
*
* @param connection_id network connection ID assigned by TNCS
+ * @param dst_imc_id IMD ID to be set as destination
* @return TNC result code
*/
TNC_Result (*provide_recommendation)(imv_agent_t *this,
- TNC_ConnectionID connection_id);
+ TNC_ConnectionID connection_id,
+ TNC_UInt32 dst_imc_id);
/**
* Reserve additional IMV IDs from TNCS
diff --git a/src/libimcv/imv/imv_state.h b/src/libimcv/imv/imv_state.h
index 9e7a29a9f..1b0845b84 100644
--- a/src/libimcv/imv/imv_state.h
+++ b/src/libimcv/imv/imv_state.h
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2011-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
@@ -63,6 +64,20 @@ struct imv_state_t {
void (*set_flags)(imv_state_t *this, bool has_long, bool has_excl);
/**
+ * Set the maximum size of a PA-TNC message for this TNCCS connection
+ *
+ * @max_msg_len maximum size of a PA-TNC message
+ */
+ void (*set_max_msg_len)(imv_state_t *this, u_int32_t max_msg_len);
+
+ /**
+ * Get the maximum size of a PA-TNC message for this TNCCS connection
+ *
+ * @return maximum size of a PA-TNC message
+ */
+ u_int32_t (*get_max_msg_len)(imv_state_t *this);
+
+ /**
* Change the connection state
*
* @param new_state new connection state
diff --git a/src/libimcv/ita/ita_attr.c b/src/libimcv/ita/ita_attr.c
index ec23c11ea..0ea799c3a 100644
--- a/src/libimcv/ita/ita_attr.c
+++ b/src/libimcv/ita/ita_attr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
+ * Copyright (C) 2011-2012 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -15,9 +15,11 @@
#include "ita_attr.h"
#include "ita/ita_attr_command.h"
+#include "ita/ita_attr_dummy.h"
-ENUM(ita_attr_names, ITA_ATTR_COMMAND, ITA_ATTR_COMMAND,
+ENUM(ita_attr_names, ITA_ATTR_COMMAND, ITA_ATTR_DUMMY,
"Command",
+ "Dummy",
);
/**
@@ -29,6 +31,8 @@ pa_tnc_attr_t* ita_attr_create_from_data(u_int32_t type, chunk_t value)
{
case ITA_ATTR_COMMAND:
return ita_attr_command_create_from_data(value);
+ case ITA_ATTR_DUMMY:
+ return ita_attr_dummy_create_from_data(value);
default:
return NULL;
}
diff --git a/src/libimcv/ita/ita_attr.h b/src/libimcv/ita/ita_attr.h
index 82debdd1e..3baf0e3b8 100644
--- a/src/libimcv/ita/ita_attr.h
+++ b/src/libimcv/ita/ita_attr.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
+ * Copyright (C) 2011-2012 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -32,6 +32,7 @@ typedef enum ita_attr_t ita_attr_t;
*/
enum ita_attr_t {
ITA_ATTR_COMMAND = 1,
+ ITA_ATTR_DUMMY = 2,
};
/**
diff --git a/src/libimcv/ita/ita_attr_command.c b/src/libimcv/ita/ita_attr_command.c
index 5c1577a7c..d43e4777b 100644
--- a/src/libimcv/ita/ita_attr_command.c
+++ b/src/libimcv/ita/ita_attr_command.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2011-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
@@ -32,14 +33,9 @@ struct private_ita_attr_command_t {
ita_attr_command_t public;
/**
- * Attribute vendor ID
+ * Vendor-specific attribute type
*/
- pen_t vendor_id;
-
- /**
- * Attribute type
- */
- u_int32_t type;
+ pen_type_t type;
/**
* Attribute value
@@ -62,13 +58,7 @@ struct private_ita_attr_command_t {
refcount_t ref;
};
-METHOD(pa_tnc_attr_t, get_vendor_id, pen_t,
- private_ita_attr_command_t *this)
-{
- return this->vendor_id;
-}
-
-METHOD(pa_tnc_attr_t, get_type, u_int32_t,
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
private_ita_attr_command_t *this)
{
return this->type;
@@ -95,6 +85,10 @@ METHOD(pa_tnc_attr_t, set_noskip_flag,void,
METHOD(pa_tnc_attr_t, build, void,
private_ita_attr_command_t *this)
{
+ if (this->value.ptr)
+ {
+ return;
+ }
this->value = chunk_create(this->command, strlen(this->command));
this->value = chunk_clone(this->value);
}
@@ -143,7 +137,6 @@ pa_tnc_attr_t *ita_attr_command_create(char *command)
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -155,8 +148,7 @@ pa_tnc_attr_t *ita_attr_command_create(char *command)
},
.get_command = _get_command,
},
- .vendor_id = PEN_ITA,
- .type = ITA_ATTR_COMMAND,
+ .type = { PEN_ITA, ITA_ATTR_COMMAND },
.command = strdup(command),
.ref = 1,
);
@@ -174,7 +166,6 @@ pa_tnc_attr_t *ita_attr_command_create_from_data(chunk_t data)
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.build = _build,
@@ -184,8 +175,7 @@ pa_tnc_attr_t *ita_attr_command_create_from_data(chunk_t data)
},
.get_command = _get_command,
},
- .vendor_id = PEN_ITA,
- .type = ITA_ATTR_COMMAND,
+ .type = {PEN_ITA, ITA_ATTR_COMMAND },
.value = chunk_clone(data),
.ref = 1,
);
diff --git a/src/libimcv/ita/ita_attr_dummy.c b/src/libimcv/ita/ita_attr_dummy.c
new file mode 100644
index 000000000..f122256a1
--- /dev/null
+++ b/src/libimcv/ita/ita_attr_dummy.c
@@ -0,0 +1,183 @@
+/*
+ * 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.
+ */
+
+#include "ita_attr.h"
+#include "ita_attr_dummy.h"
+
+#include <pen/pen.h>
+
+#include <debug.h>
+
+typedef struct private_ita_attr_dummy_t private_ita_attr_dummy_t;
+
+/**
+ * Private data of an ita_attr_dummy_t object.
+ */
+struct private_ita_attr_dummy_t {
+
+ /**
+ * Public members of ita_attr_dummy_t
+ */
+ ita_attr_dummy_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Attribute value
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * Size of the attribute value
+ */
+ int size;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_ita_attr_dummy_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_ita_attr_dummy_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_ita_attr_dummy_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_ita_attr_dummy_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_ita_attr_dummy_t *this)
+{
+ if (this->value.ptr)
+ {
+ return;
+ }
+ this->value = chunk_alloc(this->size);
+ memset(this->value.ptr, 0xdd, this->value.len);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_ita_attr_dummy_t *this, u_int32_t *offset)
+{
+ this->size = this->value.len;
+
+ return SUCCESS;
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_ita_attr_dummy_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_ita_attr_dummy_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->value.ptr);
+ free(this);
+ }
+}
+
+METHOD(ita_attr_dummy_t, get_size, int,
+ private_ita_attr_dummy_t *this)
+{
+ return this->size;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *ita_attr_dummy_create(int size)
+{
+ private_ita_attr_dummy_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,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_size = _get_size,
+ },
+ .type = { PEN_ITA, ITA_ATTR_DUMMY },
+ .size = size,
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *ita_attr_dummy_create_from_data(chunk_t data)
+{
+ private_ita_attr_dummy_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .build = _build,
+ .process = _process,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_size = _get_size,
+ },
+ .type = { PEN_ITA, ITA_ATTR_DUMMY },
+ .value = chunk_clone(data),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+
diff --git a/src/libimcv/ita/ita_attr_dummy.h b/src/libimcv/ita/ita_attr_dummy.h
new file mode 100644
index 000000000..afd543b52
--- /dev/null
+++ b/src/libimcv/ita/ita_attr_dummy.h
@@ -0,0 +1,61 @@
+/*
+ * 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 ita_attr_dummyt ita_attr_dummy
+ * @{ @ingroup ita_attr_dummy
+ */
+
+#ifndef ITA_ATTR_DUMMY_H_
+#define ITA_ATTR_DUMMY_H_
+
+typedef struct ita_attr_dummy_t ita_attr_dummy_t;
+
+#include "pa_tnc/pa_tnc_attr.h"
+
+/**
+ * Class implementing the ITA Dummy PA-TNC attribute.
+ *
+ */
+struct ita_attr_dummy_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+
+ /**
+ * Get the size the ITA Dummy attribute value
+ *
+ * @return size of dummy attribute value
+ */
+ int (*get_size)(ita_attr_dummy_t *this);
+};
+
+/**
+ * Creates an ita_attr_dummy_t object with a given size
+ *
+ * @param size size of dummy attribute value
+ */
+pa_tnc_attr_t* ita_attr_dummy_create(int size);
+
+/**
+ * Creates an ita_attr_dummy_t object from received data
+ *
+ * @param command ITA command string
+ */
+pa_tnc_attr_t* ita_attr_dummy_create_from_data(chunk_t value);
+
+#endif /** ITA_ATTR_DUMMY_H_ @}*/
diff --git a/src/libimcv/pa_tnc/pa_tnc_attr.h b/src/libimcv/pa_tnc/pa_tnc_attr.h
index b6057a70b..9abdba78c 100644
--- a/src/libimcv/pa_tnc/pa_tnc_attr.h
+++ b/src/libimcv/pa_tnc/pa_tnc_attr.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
+ * Copyright (C) 2011-2012 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -33,18 +33,11 @@ typedef struct pa_tnc_attr_t pa_tnc_attr_t;
struct pa_tnc_attr_t {
/**
- * Get the vendor ID of an PA-TNC attribute
+ * Get the vendor ID/type of an PA-TNC attribute
*
- * @return attribute vendor ID
+ * @return vendor-specific attribute type
*/
- u_int32_t (*get_vendor_id)(pa_tnc_attr_t *this);
-
- /**
- * Get the type of an PA-TNC attribute
- *
- * @return attribute type
- */
- u_int32_t (*get_type)(pa_tnc_attr_t *this);
+ pen_type_t (*get_type)(pa_tnc_attr_t *this);
/**
* Get the value of an PA-TNC attribute
diff --git a/src/libimcv/pa_tnc/pa_tnc_msg.c b/src/libimcv/pa_tnc/pa_tnc_msg.c
index b5df0a5b5..b1476fc7f 100644
--- a/src/libimcv/pa_tnc/pa_tnc_msg.c
+++ b/src/libimcv/pa_tnc/pa_tnc_msg.c
@@ -1,6 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
- *
+ * Copyright (C) 2011-2012 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -90,6 +89,16 @@ struct private_pa_tnc_msg_t {
u_int32_t identifier;
/**
+ * Current PA-TNC Message size
+ */
+ size_t msg_len;
+
+ /**
+ * Maximum PA-TNC Message size
+ */
+ size_t max_msg_len;
+
+ /**
* Encoded message
*/
chunk_t encoding;
@@ -101,67 +110,84 @@ METHOD(pa_tnc_msg_t, get_encoding, chunk_t,
return this->encoding;
}
-METHOD(pa_tnc_msg_t, add_attribute, void,
+METHOD(pa_tnc_msg_t, add_attribute, bool,
private_pa_tnc_msg_t *this, pa_tnc_attr_t *attr)
{
+ chunk_t attr_value;
+ size_t attr_len;
+
+ attr->build(attr);
+ attr_value = attr->get_value(attr);
+ attr_len = PA_TNC_ATTR_HEADER_SIZE + attr_value.len;
+
+ if (this->max_msg_len && this->msg_len + attr_len > this->max_msg_len)
+ {
+ /* attribute just does not fit into this message */
+ return FALSE;
+ }
+ this->msg_len += attr_len;
+
this->attributes->insert_last(this->attributes, attr);
+ return TRUE;
}
-METHOD(pa_tnc_msg_t, build, void,
+METHOD(pa_tnc_msg_t, build, bool,
private_pa_tnc_msg_t *this)
{
bio_writer_t *writer;
enumerator_t *enumerator;
pa_tnc_attr_t *attr;
enum_name_t *pa_attr_names;
- pen_t vendor_id;
- u_int32_t type;
+ pen_type_t type;
u_int8_t flags;
chunk_t value;
- rng_t *rng;
+ nonce_gen_t *ng;
- /* create a random message identifier */
- rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
- rng->get_bytes(rng, sizeof(this->identifier), (u_int8_t*)&this->identifier);
- rng->destroy(rng);
- DBG2(DBG_TNC, "creating PA-TNC message with ID 0x%08x", this->identifier);
+ /* generate a nonce as a message identifier */
+ ng = lib->crypto->create_nonce_gen(lib->crypto);
+ if (!ng || !ng->get_nonce(ng, 4, (u_int8_t*)&this->identifier))
+ {
+ DBG1(DBG_TNC, "failed to generate random PA-TNC message identifier");
+ DESTROY_IF(ng);
+ return FALSE;
+ }
+ ng->destroy(ng);
+ DBG1(DBG_TNC, "creating PA-TNC message with ID 0x%08x", this->identifier);
/* build message header */
- writer = bio_writer_create(PA_TNC_HEADER_SIZE);
+ writer = bio_writer_create(this->msg_len);
writer->write_uint8 (writer, PA_TNC_VERSION);
writer->write_uint24(writer, PA_TNC_RESERVED);
writer->write_uint32(writer, this->identifier);
- /* build and append encoding of PA-TNC attributes */
+ /* append encoded value of PA-TNC attributes */
enumerator = this->attributes->create_enumerator(this->attributes);
while (enumerator->enumerate(enumerator, &attr))
{
- attr->build(attr);
- vendor_id = attr->get_vendor_id(attr);
- type = attr->get_type(attr);
+ type = attr->get_type(attr);
value = attr->get_value(attr);
flags = attr->get_noskip_flag(attr) ? PA_TNC_ATTR_FLAG_NOSKIP :
PA_TNC_ATTR_FLAG_NONE;
pa_attr_names = imcv_pa_tnc_attributes->get_names(imcv_pa_tnc_attributes,
- vendor_id);
+ type.vendor_id);
if (pa_attr_names)
{
DBG2(DBG_TNC, "creating PA-TNC attribute type '%N/%N' "
- "0x%06x/0x%08x", pen_names, vendor_id,
- pa_attr_names, type, vendor_id, type);
+ "0x%06x/0x%08x", pen_names, type.vendor_id,
+ pa_attr_names, type.type, type.vendor_id, type.type);
}
else
{
DBG2(DBG_TNC, "creating PA-TNC attribute type '%N' "
- "0x%06x/0x%08x", pen_names, vendor_id,
- vendor_id, type);
+ "0x%06x/0x%08x", pen_names, type.vendor_id,
+ type.vendor_id, type.type);
}
DBG3(DBG_TNC, "%B", &value);
writer->write_uint8 (writer, flags);
- writer->write_uint24(writer, vendor_id);
- writer->write_uint32(writer, type);
+ writer->write_uint24(writer, type.vendor_id);
+ writer->write_uint32(writer, type.type);
writer->write_uint32(writer, PA_TNC_ATTR_HEADER_SIZE + value.len);
writer->write_data (writer, value);
}
@@ -170,6 +196,8 @@ METHOD(pa_tnc_msg_t, build, void,
free(this->encoding.ptr);
this->encoding = chunk_clone(writer->get_buf(writer));
writer->destroy(writer);
+
+ return TRUE;
}
METHOD(pa_tnc_msg_t, process, status_t,
@@ -179,6 +207,7 @@ METHOD(pa_tnc_msg_t, process, status_t,
pa_tnc_attr_t *error;
u_int8_t version;
u_int32_t reserved, offset, attr_offset;
+ pen_type_t error_code;
/* process message header */
if (this->encoding.len < PA_TNC_HEADER_SIZE)
@@ -191,13 +220,14 @@ METHOD(pa_tnc_msg_t, process, status_t,
reader->read_uint8 (reader, &version);
reader->read_uint24(reader, &reserved);
reader->read_uint32(reader, &this->identifier);
- DBG2(DBG_TNC, "processing PA-TNC message with ID 0x%08x", this->identifier);
+ DBG1(DBG_TNC, "processing PA-TNC message with ID 0x%08x", this->identifier);
if (version != PA_TNC_VERSION)
{
+ pen_type_t error_code = { PEN_IETF, PA_ERROR_VERSION_NOT_SUPPORTED };
+
DBG1(DBG_TNC, "PA-TNC version %u not supported", version);
- error = ietf_attr_pa_tnc_error_create(PEN_IETF,
- PA_ERROR_VERSION_NOT_SUPPORTED, this->encoding);
+ error = ietf_attr_pa_tnc_error_create(error_code, this->encoding);
goto err;
}
@@ -214,6 +244,7 @@ METHOD(pa_tnc_msg_t, process, status_t,
pa_tnc_attr_t *attr;
enum_name_t *pa_attr_names;
ietf_attr_pa_tnc_error_t *error_attr;
+ pen_type_t error_code;
attr_info = reader->peek(reader);
attr_info.len = PA_TNC_ATTR_INFO_SIZE;
@@ -241,18 +272,18 @@ METHOD(pa_tnc_msg_t, process, status_t,
{
DBG1(DBG_TNC, "%u bytes too small for PA-TNC attribute length",
length);
- error = ietf_attr_pa_tnc_error_create_with_offset(PEN_IETF,
- PA_ERROR_INVALID_PARAMETER, this->encoding,
- offset + PA_TNC_ATTR_INFO_SIZE);
+ error_code = pen_type_create(PEN_IETF, PA_ERROR_INVALID_PARAMETER);
+ error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
+ this->encoding, offset + PA_TNC_ATTR_INFO_SIZE);
goto err;
}
if (!reader->read_data(reader, length - PA_TNC_ATTR_HEADER_SIZE, &value))
{
DBG1(DBG_TNC, "insufficient bytes for PA-TNC attribute value");
- error = ietf_attr_pa_tnc_error_create_with_offset(PEN_IETF,
- PA_ERROR_INVALID_PARAMETER, this->encoding,
- offset + PA_TNC_ATTR_INFO_SIZE);
+ error_code = pen_type_create(PEN_IETF, PA_ERROR_INVALID_PARAMETER);
+ error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
+ this->encoding, offset + PA_TNC_ATTR_INFO_SIZE);
goto err;
}
DBG3(DBG_TNC, "%B", &value);
@@ -264,8 +295,10 @@ METHOD(pa_tnc_msg_t, process, status_t,
if (flags & PA_TNC_ATTR_FLAG_NOSKIP)
{
DBG1(DBG_TNC, "unsupported PA-TNC attribute with NOSKIP flag");
- error = ietf_attr_pa_tnc_error_create(PEN_IETF,
- PA_ERROR_ATTR_TYPE_NOT_SUPPORTED, this->encoding);
+ error_code = pen_type_create(PEN_IETF,
+ PA_ERROR_ATTR_TYPE_NOT_SUPPORTED);
+ error = ietf_attr_pa_tnc_error_create(error_code,
+ this->encoding);
error_attr = (ietf_attr_pa_tnc_error_t*)error;
error_attr->set_attr_info(error_attr, attr_info);
goto err;
@@ -281,18 +314,21 @@ METHOD(pa_tnc_msg_t, process, status_t,
if (attr->process(attr, &attr_offset) != SUCCESS)
{
attr->destroy(attr);
- if (vendor_id == PEN_IETF && type == IETF_ATTR_PA_TNC_ERROR)
+ if (error_code.vendor_id == PEN_IETF &&
+ error_code.type == IETF_ATTR_PA_TNC_ERROR)
{
/* error while processing a PA-TNC error attribute - abort */
reader->destroy(reader);
return FAILED;
}
- error = ietf_attr_pa_tnc_error_create_with_offset(PEN_IETF,
- PA_ERROR_INVALID_PARAMETER, this->encoding,
+ error_code = pen_type_create(PEN_IETF,
+ PA_ERROR_ATTR_TYPE_NOT_SUPPORTED);
+ error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
+ this->encoding,
offset + PA_TNC_ATTR_HEADER_SIZE + attr_offset);
goto err;
}
- add_attribute(this, attr);
+ this->attributes->insert_last(this->attributes, attr);
offset += length;
}
@@ -302,8 +338,9 @@ METHOD(pa_tnc_msg_t, process, status_t,
return SUCCESS;
}
DBG1(DBG_TNC, "insufficient bytes for PA-TNC attribute header");
- error = ietf_attr_pa_tnc_error_create_with_offset(PEN_IETF,
- PA_ERROR_INVALID_PARAMETER, this->encoding, offset);
+ error_code = pen_type_create(PEN_IETF, PA_ERROR_INVALID_PARAMETER);
+ error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
+ this->encoding, offset);
err:
reader->destroy(reader);
@@ -316,35 +353,35 @@ METHOD(pa_tnc_msg_t, process_ietf_std_errors, bool,
{
enumerator_t *enumerator;
pa_tnc_attr_t *attr;
+ pen_type_t type;
bool fatal_error = FALSE;
enumerator = this->attributes->create_enumerator(this->attributes);
while (enumerator->enumerate(enumerator, &attr))
{
- if (attr->get_vendor_id(attr) == PEN_IETF &&
- attr->get_type(attr) == IETF_ATTR_PA_TNC_ERROR)
+ type = attr->get_type(attr);
+
+ if (type.vendor_id == PEN_IETF && type.type == IETF_ATTR_PA_TNC_ERROR)
{
ietf_attr_pa_tnc_error_t *error_attr;
- pen_t error_vendor_id;
- pa_tnc_error_code_t error_code;
+ pen_type_t error_code;
chunk_t msg_info, attr_info;
u_int32_t offset;
error_attr = (ietf_attr_pa_tnc_error_t*)attr;
- error_vendor_id = error_attr->get_vendor_id(error_attr);
error_code = error_attr->get_error_code(error_attr);
msg_info = error_attr->get_msg_info(error_attr);
/* skip errors from non-IETF namespaces */
- if (error_vendor_id != PEN_IETF)
+ if (error_code.vendor_id != PEN_IETF)
{
continue;
}
DBG1(DBG_IMC, "received PA-TNC error '%N' concerning message "
- "0x%08x/0x%08x", pa_tnc_error_code_names, error_code,
+ "0x%08x/0x%08x", pa_tnc_error_code_names, error_code.type,
untoh32(msg_info.ptr), untoh32(msg_info.ptr + 4));
- switch (error_code)
+ switch (error_code.type)
{
case PA_ERROR_INVALID_PARAMETER:
offset = error_attr->get_offset(error_attr);
@@ -358,8 +395,9 @@ METHOD(pa_tnc_msg_t, process_ietf_std_errors, bool,
break;
}
- /* remove the processed IETF standard error attribute */
+ /* remove and delete the processed IETF standard error attribute */
this->attributes->remove_at(this->attributes, enumerator);
+ attr->destroy(attr);
fatal_error = TRUE;
}
}
@@ -394,7 +432,7 @@ METHOD(pa_tnc_msg_t, destroy, void,
/**
* See header
*/
-pa_tnc_msg_t *pa_tnc_msg_create_from_data(chunk_t data)
+pa_tnc_msg_t *pa_tnc_msg_create(size_t max_msg_len)
{
private_pa_tnc_msg_t *this;
@@ -409,9 +447,10 @@ pa_tnc_msg_t *pa_tnc_msg_create_from_data(chunk_t data)
.create_error_enumerator = _create_error_enumerator,
.destroy = _destroy,
},
- .encoding = chunk_clone(data),
.attributes = linked_list_create(),
.errors = linked_list_create(),
+ .msg_len = PA_TNC_HEADER_SIZE,
+ .max_msg_len = max_msg_len,
);
return &this->public;
@@ -420,8 +459,26 @@ pa_tnc_msg_t *pa_tnc_msg_create_from_data(chunk_t data)
/**
* See header
*/
-pa_tnc_msg_t *pa_tnc_msg_create(void)
+pa_tnc_msg_t *pa_tnc_msg_create_from_data(chunk_t data)
{
- return pa_tnc_msg_create_from_data(chunk_empty);
+ private_pa_tnc_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .get_encoding = _get_encoding,
+ .add_attribute = _add_attribute,
+ .build = _build,
+ .process = _process,
+ .process_ietf_std_errors = _process_ietf_std_errors,
+ .create_attribute_enumerator = _create_attribute_enumerator,
+ .create_error_enumerator = _create_error_enumerator,
+ .destroy = _destroy,
+ },
+ .encoding = chunk_clone(data),
+ .attributes = linked_list_create(),
+ .errors = linked_list_create(),
+ );
+
+ return &this->public;
}
diff --git a/src/libimcv/pa_tnc/pa_tnc_msg.h b/src/libimcv/pa_tnc/pa_tnc_msg.h
index c3ce829d5..80016fecd 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 Andreas Steffen
+ * Copyright (C) 2011-2012 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -46,13 +46,16 @@ struct pa_tnc_msg_t {
* Add a PA-TNC attribute
*
* @param attr PA-TNC attribute to be addedd
+ * @return TRUE if attribute fit into message and was added
*/
- void (*add_attribute)(pa_tnc_msg_t *this, pa_tnc_attr_t* attr);
+ bool (*add_attribute)(pa_tnc_msg_t *this, pa_tnc_attr_t* attr);
/**
* Build the PA-TNC message
+ *
+ * @return TRUE if PA-TNC message was built successfully
*/
- void (*build)(pa_tnc_msg_t *this);
+ bool (*build)(pa_tnc_msg_t *this);
/**
* Process the PA-TNC message
@@ -91,7 +94,7 @@ struct pa_tnc_msg_t {
/**
* Create an empty PA-TNC message
*/
-pa_tnc_msg_t* pa_tnc_msg_create(void);
+pa_tnc_msg_t* pa_tnc_msg_create(size_t max_msg_len);
/**
* Create an unprocessed PA-TNC message from received data
diff --git a/src/libimcv/plugins/imc_scanner/Makefile.in b/src/libimcv/plugins/imc_scanner/Makefile.in
index 497d317d5..d06798170 100644
--- a/src/libimcv/plugins/imc_scanner/Makefile.in
+++ b/src/libimcv/plugins/imc_scanner/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -81,7 +82,7 @@ imc_scanner_la_OBJECTS = $(am_imc_scanner_la_OBJECTS)
imc_scanner_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(imc_scanner_la_LDFLAGS) $(LDFLAGS) -o $@
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -107,6 +108,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -201,11 +203,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -222,11 +227,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -242,6 +248,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -251,7 +258,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libimcv/plugins/imc_scanner/imc_scanner.c b/src/libimcv/plugins/imc_scanner/imc_scanner.c
index b24c39c3a..34c9359fe 100644
--- a/src/libimcv/plugins/imc_scanner/imc_scanner.c
+++ b/src/libimcv/plugins/imc_scanner/imc_scanner.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2011-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
@@ -19,8 +20,8 @@
#include <ietf/ietf_attr.h>
#include <ietf/ietf_attr_pa_tnc_error.h>
#include <ietf/ietf_attr_port_filter.h>
+#include <ietf/ietf_attr_assess_result.h>
-#include <tncif_names.h>
#include <tncif_pa_subtypes.h>
#include <pen/pen.h>
@@ -37,7 +38,7 @@ static const char imc_name[] = "Scanner";
#define IMC_SUBTYPE PA_SUBTYPE_ITA_SCANNER
static imc_agent_t *imc_scanner;
-
+
/**
* see section 3.8.1 of TCG TNC IF-IMC Specification 1.3
*/
@@ -84,6 +85,15 @@ TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id,
case TNC_CONNECTION_STATE_CREATE:
state = imc_scanner_state_create(connection_id);
return imc_scanner->create_state(imc_scanner, state);
+ case TNC_CONNECTION_STATE_HANDSHAKE:
+ if (imc_scanner->change_state(imc_scanner, 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_scanner->delete_state(imc_scanner, connection_id);
default:
@@ -123,7 +133,7 @@ static bool do_netstat(ietf_attr_port_filter_t *attr)
enumerator_t *enumerator;
bool allowed, found = FALSE;
- DBG2(DBG_IMC, "%.*s", strlen(buf)-1, buf);
+ DBG2(DBG_IMC, "%.*s", (int)(strlen(buf)-1), buf);
if (n++ < 2)
{
@@ -199,7 +209,7 @@ static bool do_netstat(ietf_attr_port_filter_t *attr)
}
}
enumerator->destroy(enumerator);
-
+
/* Skip the duplicate port entry */
if (found)
{
@@ -221,7 +231,7 @@ end:
static TNC_Result send_message(TNC_ConnectionID connection_id)
{
- pa_tnc_msg_t *msg;
+ linked_list_t *attr_list;
pa_tnc_attr_t *attr;
ietf_attr_port_filter_t *attr_port_filter;
TNC_Result result;
@@ -234,12 +244,11 @@ static TNC_Result send_message(TNC_ConnectionID connection_id)
attr->destroy(attr);
return TNC_RESULT_FATAL;
}
- msg = pa_tnc_msg_create();
- msg->add_attribute(msg, attr);
- msg->build(msg);
+ attr_list = linked_list_create();
+ attr_list->insert_last(attr_list, attr);
result = imc_scanner->send_message(imc_scanner, connection_id, FALSE, 0,
- TNC_IMVID_ANY, msg->get_encoding(msg));
- msg->destroy(msg);
+ TNC_IMVID_ANY, attr_list);
+ attr_list->destroy(attr_list);
return result;
}
@@ -268,8 +277,12 @@ static TNC_Result receive_message(TNC_IMCID imc_id,
TNC_UInt32 dst_imc_id)
{
pa_tnc_msg_t *pa_tnc_msg;
+ pa_tnc_attr_t *attr;
+ pen_type_t attr_type;
imc_state_t *state;
+ enumerator_t *enumerator;
TNC_Result result;
+ TNC_UInt32 target_imc_id;
bool fatal_error;
if (!imc_scanner)
@@ -284,7 +297,7 @@ static TNC_Result receive_message(TNC_IMCID imc_id,
return TNC_RESULT_FATAL;
}
- /* parse received PA-TNC message and automatically handle any errors */
+ /* parse received PA-TNC message and automatically handle any errors */
result = imc_scanner->receive_message(imc_scanner, state, msg, msg_vid,
msg_subtype, src_imv_id, dst_imc_id, &pa_tnc_msg);
@@ -293,17 +306,43 @@ static TNC_Result receive_message(TNC_IMCID imc_id,
{
return result;
}
+ target_imc_id = (dst_imc_id == TNC_IMCID_ANY) ? imc_id : dst_imc_id;
/* preprocess any IETF standard error attributes */
fatal_error = pa_tnc_msg->process_ietf_std_errors(pa_tnc_msg);
+
+ /* analyze PA-TNC attributes */
+ enumerator = pa_tnc_msg->create_attribute_enumerator(pa_tnc_msg);
+ while (enumerator->enumerate(enumerator, &attr))
+ {
+ attr_type = attr->get_type(attr);
+
+ if (attr_type.vendor_id == PEN_IETF &&
+ attr_type.type == IETF_ATTR_ASSESSMENT_RESULT)
+ {
+ ietf_attr_assess_result_t *ietf_attr;
+
+ ietf_attr = (ietf_attr_assess_result_t*)attr;
+ state->set_result(state, target_imc_id,
+ ietf_attr->get_result(ietf_attr));
+ }
+ }
+ enumerator->destroy(enumerator);
pa_tnc_msg->destroy(pa_tnc_msg);
- /* if no error occurred then always return the same response */
- return fatal_error ? TNC_RESULT_FATAL : send_message(connection_id);
+ if (fatal_error)
+ {
+ return TNC_RESULT_FATAL;
+ }
+
+ /* if no assessment result is known then repeat the measurement */
+ return state->get_result(state, target_imc_id, NULL) ?
+ TNC_RESULT_SUCCESS : send_message(connection_id);
}
/**
* see section 3.8.4 of TCG TNC IF-IMC Specification 1.3
+
*/
TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
TNC_ConnectionID connection_id,
diff --git a/src/libimcv/plugins/imc_scanner/imc_scanner_state.c b/src/libimcv/plugins/imc_scanner/imc_scanner_state.c
index 563105548..991b24a73 100644
--- a/src/libimcv/plugins/imc_scanner/imc_scanner_state.c
+++ b/src/libimcv/plugins/imc_scanner/imc_scanner_state.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2011-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
@@ -14,6 +15,8 @@
#include "imc_scanner_state.h"
+#include <tncif_names.h>
+
#include <debug.h>
typedef struct private_imc_scanner_state_t private_imc_scanner_state_t;
@@ -39,6 +42,11 @@ struct private_imc_scanner_state_t {
TNC_ConnectionState state;
/**
+ * Assessment/Evaluation Result
+ */
+ TNC_IMV_Evaluation_Result result;
+
+ /**
* Does the TNCCS connection support long message types?
*/
bool has_long;
@@ -48,6 +56,10 @@ struct private_imc_scanner_state_t {
*/
bool has_excl;
+ /**
+ * Maximum PA-TNC message size for this TNCCS connection
+ */
+ u_int32_t max_msg_len;
};
METHOD(imc_state_t, get_connection_id, TNC_ConnectionID,
@@ -75,12 +87,44 @@ METHOD(imc_state_t, set_flags, void,
this->has_excl = has_excl;
}
+METHOD(imc_state_t, set_max_msg_len, void,
+ private_imc_scanner_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_scanner_state_t *this)
+{
+ return this->max_msg_len;
+}
+
METHOD(imc_state_t, change_state, void,
private_imc_scanner_state_t *this, TNC_ConnectionState new_state)
{
this->state = new_state;
}
+METHOD(imc_state_t, set_result, void,
+ private_imc_scanner_state_t *this, TNC_IMCID id,
+ TNC_IMV_Evaluation_Result result)
+{
+ DBG1(DBG_IMC, "set assessment result for IMC %u to '%N'",
+ id, TNC_IMV_Evaluation_Result_names, result);
+ this->result = result;
+}
+
+METHOD(imc_state_t, get_result, bool,
+ private_imc_scanner_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_scanner_state_t *this)
{
@@ -101,11 +145,16 @@ imc_state_t *imc_scanner_state_create(TNC_ConnectionID 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,
.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,
);
diff --git a/src/libimcv/plugins/imc_test/Makefile.in b/src/libimcv/plugins/imc_test/Makefile.in
index b4e3f8ae0..8e37e7e9e 100644
--- a/src/libimcv/plugins/imc_test/Makefile.in
+++ b/src/libimcv/plugins/imc_test/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -81,7 +82,7 @@ imc_test_la_OBJECTS = $(am_imc_test_la_OBJECTS)
imc_test_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(imc_test_la_LDFLAGS) $(LDFLAGS) -o $@
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -107,6 +108,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -201,11 +203,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -222,11 +227,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -242,6 +248,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -251,7 +258,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libimcv/plugins/imc_test/imc_test.c b/src/libimcv/plugins/imc_test/imc_test.c
index fe005ed4a..ee8e5b206 100644
--- a/src/libimcv/plugins/imc_test/imc_test.c
+++ b/src/libimcv/plugins/imc_test/imc_test.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2011-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
@@ -18,10 +19,11 @@
#include <pa_tnc/pa_tnc_msg.h>
#include <ietf/ietf_attr.h>
#include <ietf/ietf_attr_pa_tnc_error.h>
+#include <ietf/ietf_attr_assess_result.h>
#include <ita/ita_attr.h>
#include <ita/ita_attr_command.h>
+#include <ita/ita_attr_dummy.h>
-#include <tncif_names.h>
#include <tncif_pa_subtypes.h>
#include <pen/pen.h>
@@ -73,9 +75,12 @@ TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id,
imc_state_t *state;
imc_test_state_t *test_state;
TNC_Result result;
+ TNC_UInt32 additional_id;
char *command;
bool retry;
- int additional_ids;
+ void *pointer;
+ enumerator_t *enumerator;
+ int dummy_size, additional_ids;
if (!imc_test)
{
@@ -88,9 +93,12 @@ TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id,
case TNC_CONNECTION_STATE_CREATE:
command = lib->settings->get_str(lib->settings,
"libimcv.plugins.imc-test.command", "none");
+ dummy_size = lib->settings->get_int(lib->settings,
+ "libimcv.plugins.imc-test.dummy_size", 0);
retry = lib->settings->get_bool(lib->settings,
"libimcv.plugins.imc-test.retry", FALSE);
- state = imc_test_state_create(connection_id, command, retry);
+ state = imc_test_state_create(connection_id, command, dummy_size,
+ retry);
result = imc_test->create_state(imc_test, state);
if (result != TNC_RESULT_SUCCESS)
@@ -124,6 +132,26 @@ TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id,
test_state->get_command(test_state));
test_state->set_command(test_state, command);
}
+
+ state->set_result(state, imc_id, TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
+
+ /* Exit if there are no additional IMC IDs */
+ if (!imc_test->count_additional_ids(imc_test))
+ {
+ return result;
+ }
+
+ enumerator = imc_test->create_id_enumerator(imc_test);
+ while (enumerator->enumerate(enumerator, &pointer))
+ {
+ /* interpret pointer as scalar value */
+ additional_id = (TNC_UInt32)pointer;
+
+ state->set_result(state, additional_id,
+ TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
+ }
+ enumerator->destroy(enumerator);
+
return TNC_RESULT_SUCCESS;
case TNC_CONNECTION_STATE_DELETE:
@@ -158,23 +186,30 @@ static TNC_Result send_message(imc_state_t *state, TNC_UInt32 src_imc_id,
TNC_UInt32 dst_imv_id)
{
imc_test_state_t *test_state;
- pa_tnc_msg_t *msg;
+ linked_list_t *attr_list;
pa_tnc_attr_t *attr;
bool excl;
TNC_ConnectionID connection_id;
TNC_Result result;
+ attr_list = linked_list_create();
connection_id = state->get_connection_id(state);
test_state = (imc_test_state_t*)state;
+
+ if (test_state->get_dummy_size(test_state))
+ {
+ attr = ita_attr_dummy_create(test_state->get_dummy_size(test_state));
+ attr->set_noskip_flag(attr, TRUE);
+ attr_list->insert_last(attr_list, attr);
+ }
attr = ita_attr_command_create(test_state->get_command(test_state));
attr->set_noskip_flag(attr, TRUE);
- msg = pa_tnc_msg_create();
- msg->add_attribute(msg, attr);
- msg->build(msg);
+ attr_list->insert_last(attr_list, attr);
+
excl = dst_imv_id != TNC_IMVID_ANY;
result = imc_test->send_message(imc_test, connection_id, excl, src_imc_id,
- dst_imv_id, msg->get_encoding(msg));
- msg->destroy(msg);
+ dst_imv_id, attr_list);
+ attr_list->destroy(attr_list);
return result;
}
@@ -245,9 +280,11 @@ static TNC_Result receive_message(TNC_IMCID imc_id,
{
pa_tnc_msg_t *pa_tnc_msg;
pa_tnc_attr_t *attr;
+ pen_type_t attr_type;
imc_state_t *state;
enumerator_t *enumerator;
TNC_Result result;
+ TNC_UInt32 target_imc_id;
bool fatal_error = FALSE;
if (!imc_test)
@@ -271,6 +308,7 @@ static TNC_Result receive_message(TNC_IMCID imc_id,
{
return result;
}
+ target_imc_id = (dst_imc_id == TNC_IMCID_ANY) ? imc_id : dst_imc_id;
/* preprocess any IETF standard error attributes */
fatal_error = pa_tnc_msg->process_ietf_std_errors(pa_tnc_msg);
@@ -279,22 +317,47 @@ static TNC_Result receive_message(TNC_IMCID imc_id,
enumerator = pa_tnc_msg->create_attribute_enumerator(pa_tnc_msg);
while (enumerator->enumerate(enumerator, &attr))
{
- if (attr->get_vendor_id(attr) == PEN_ITA &&
- attr->get_type(attr) == ITA_ATTR_COMMAND)
+ attr_type = attr->get_type(attr);
+
+ if (attr_type.vendor_id == PEN_IETF)
{
- ita_attr_command_t *ita_attr;
- char *command;
-
- ita_attr = (ita_attr_command_t*)attr;
- command = ita_attr->get_command(ita_attr);
+ ietf_attr_assess_result_t *ietf_attr;
+
+ ietf_attr = (ietf_attr_assess_result_t*)attr;
+ state->set_result(state, target_imc_id,
+ ietf_attr->get_result(ietf_attr));
+ }
+ else if (attr_type.vendor_id == PEN_ITA)
+ {
+ if (attr_type.type == ITA_ATTR_COMMAND)
+ {
+ ita_attr_command_t *ita_attr;
+
+ ita_attr = (ita_attr_command_t*)attr;
+ DBG1(DBG_IMC, "received command '%s'",
+ ita_attr->get_command(ita_attr));
+ }
+ else if (attr_type.type == ITA_ATTR_DUMMY)
+ {
+ ita_attr_dummy_t *ita_attr;
+
+ ita_attr = (ita_attr_dummy_t*)attr;
+ DBG1(DBG_IMC, "received dummy attribute value (%d bytes)",
+ ita_attr->get_size(ita_attr));
+ }
}
}
enumerator->destroy(enumerator);
pa_tnc_msg->destroy(pa_tnc_msg);
- /* if no error occurred then always return the same response */
- return fatal_error ? TNC_RESULT_FATAL :
- send_message(state, dst_imc_id, src_imv_id);
+ if (fatal_error)
+ {
+ return TNC_RESULT_FATAL;
+ }
+
+ /* if no assessment result is known then repeat the measurement */
+ return state->get_result(state, target_imc_id, NULL) ?
+ TNC_RESULT_SUCCESS : send_message(state, dst_imc_id, src_imv_id);
}
/**
diff --git a/src/libimcv/plugins/imc_test/imc_test_state.c b/src/libimcv/plugins/imc_test/imc_test_state.c
index 2adfd7d64..e70eb1492 100644
--- a/src/libimcv/plugins/imc_test/imc_test_state.c
+++ b/src/libimcv/plugins/imc_test/imc_test_state.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2011-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
@@ -14,10 +15,13 @@
#include "imc_test_state.h"
+#include <tncif_names.h>
+
#include <debug.h>
#include <utils/linked_list.h>
typedef struct private_imc_test_state_t private_imc_test_state_t;
+typedef struct entry_t entry_t;
/**
* Private data of an imc_test_state_t object.
@@ -40,6 +44,11 @@ struct private_imc_test_state_t {
TNC_ConnectionState state;
/**
+ * Assessment/Evaluation Results for all IMC IDs
+ */
+ linked_list_t *results;
+
+ /**
* Does the TNCCS connection support long message types?
*/
bool has_long;
@@ -50,11 +59,21 @@ struct private_imc_test_state_t {
bool has_excl;
/**
+ * Maximum PA-TNC message size for this TNCCS connection
+ */
+ u_int32_t max_msg_len;
+
+ /**
* Command to transmit to IMV
*/
char *command;
/**
+ * Size of the dummy attribute value to transmit to IMV
+ */
+ int dummy_size;
+
+ /**
* Is it the first handshake?
*/
bool first_handshake;
@@ -66,6 +85,14 @@ struct private_imc_test_state_t {
};
+/**
+ * Stores the Assessment/Evaluation Result for a given IMC ID
+ */
+struct entry_t {
+ TNC_IMCID id;
+ TNC_IMV_Evaluation_Result result;
+};
+
METHOD(imc_state_t, get_connection_id, TNC_ConnectionID,
private_imc_test_state_t *this)
{
@@ -91,15 +118,86 @@ METHOD(imc_state_t, set_flags, void,
this->has_excl = has_excl;
}
+METHOD(imc_state_t, set_max_msg_len, void,
+ private_imc_test_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_test_state_t *this)
+{
+ return this->max_msg_len;
+}
+
METHOD(imc_state_t, change_state, void,
private_imc_test_state_t *this, TNC_ConnectionState new_state)
{
this->state = new_state;
}
+METHOD(imc_state_t, set_result, void,
+ private_imc_test_state_t *this, TNC_IMCID id,
+ TNC_IMV_Evaluation_Result result)
+{
+ enumerator_t *enumerator;
+ entry_t *entry;
+ bool found = FALSE;
+
+ DBG1(DBG_IMC, "set assessment result for IMC %u to '%N'",
+ id, TNC_IMV_Evaluation_Result_names, result);
+
+ enumerator = this->results->create_enumerator(this->results);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->id == id)
+ {
+ entry->result = result;
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!found)
+ {
+ entry = malloc_thing(entry_t);
+ entry->id = id;
+ entry->result = result;
+ this->results->insert_last(this->results, entry);
+ }
+}
+
+METHOD(imc_state_t, get_result, bool,
+ private_imc_test_state_t *this, TNC_IMCID id,
+ TNC_IMV_Evaluation_Result *result)
+{
+ enumerator_t *enumerator;
+ entry_t *entry;
+ TNC_IMV_Evaluation_Result eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
+
+ enumerator = this->results->create_enumerator(this->results);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->id == id)
+ {
+ eval = entry->result;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (result)
+ {
+ *result = eval;
+ }
+ return eval != TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
+}
+
METHOD(imc_state_t, destroy, void,
private_imc_test_state_t *this)
{
+ this->results->destroy_function(this->results, free);
free(this->command);
free(this);
}
@@ -120,6 +218,13 @@ METHOD(imc_test_state_t, set_command, void,
free(old_command);
}
+METHOD(imc_test_state_t, get_dummy_size, int,
+ private_imc_test_state_t *this)
+{
+ return this->dummy_size;
+}
+
+
METHOD(imc_test_state_t, is_first_handshake, bool,
private_imc_test_state_t *this)
{
@@ -146,7 +251,7 @@ METHOD(imc_test_state_t, do_handshake_retry, bool,
* Described in header.
*/
imc_state_t *imc_test_state_create(TNC_ConnectionID connection_id,
- char *command, bool retry)
+ char *command, int dummy_size, bool retry)
{
private_imc_test_state_t *this;
@@ -157,17 +262,24 @@ imc_state_t *imc_test_state_create(TNC_ConnectionID 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,
.change_state = _change_state,
+ .set_result = _set_result,
+ .get_result = _get_result,
.destroy = _destroy,
},
.get_command = _get_command,
.set_command = _set_command,
+ .get_dummy_size = _get_dummy_size,
.is_first_handshake = _is_first_handshake,
.do_handshake_retry = _do_handshake_retry,
},
.state = TNC_CONNECTION_STATE_CREATE,
+ .results = linked_list_create(),
.connection_id = connection_id,
.command = strdup(command),
+ .dummy_size = dummy_size,
.first_handshake = TRUE,
.handshake_retry = retry,
);
@@ -175,4 +287,3 @@ imc_state_t *imc_test_state_create(TNC_ConnectionID connection_id,
return &this->public.interface;
}
-
diff --git a/src/libimcv/plugins/imc_test/imc_test_state.h b/src/libimcv/plugins/imc_test/imc_test_state.h
index d9160df94..402fd14b3 100644
--- a/src/libimcv/plugins/imc_test/imc_test_state.h
+++ b/src/libimcv/plugins/imc_test/imc_test_state.h
@@ -52,6 +52,13 @@ struct imc_test_state_t {
void (*set_command)(imc_test_state_t *this, char *command);
/**
+ * get the value size of a dummy attribute to send to IMV
+ *
+ * @return size of the dummy attribute value to send to IMV
+ */
+ int (*get_dummy_size)(imc_test_state_t *this);
+
+ /**
* Test and reset the first handshake flag
*
* @return TRUE if first handshake
@@ -70,11 +77,12 @@ struct imc_test_state_t {
/**
* Create an imc_test_state_t instance
*
- * @param id connection ID
- * @param command command to send to IMV
- * @param retry TRUE if a handshake retry should be done
+ * @param id connection ID
+ * @param command command to send to IMV
+ * @param dummy_size size of the dummy attribute to send (only if > 0)
+ * @param retry TRUE if a handshake retry should be done
*/
imc_state_t* imc_test_state_create(TNC_ConnectionID id, char* command,
- bool retry);
+ int dummy_size, bool retry);
#endif /** IMC_TEST_STATE_H_ @}*/
diff --git a/src/libimcv/plugins/imv_scanner/Makefile.in b/src/libimcv/plugins/imv_scanner/Makefile.in
index 63602c707..126a42c93 100644
--- a/src/libimcv/plugins/imv_scanner/Makefile.in
+++ b/src/libimcv/plugins/imv_scanner/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -81,7 +82,7 @@ imv_scanner_la_OBJECTS = $(am_imv_scanner_la_OBJECTS)
imv_scanner_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(imv_scanner_la_LDFLAGS) $(LDFLAGS) -o $@
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -107,6 +108,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -201,11 +203,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -222,11 +227,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -242,6 +248,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -251,7 +258,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libimcv/plugins/imv_scanner/imv_scanner.c b/src/libimcv/plugins/imv_scanner/imv_scanner.c
index dba3fd632..1352397c6 100644
--- a/src/libimcv/plugins/imv_scanner/imv_scanner.c
+++ b/src/libimcv/plugins/imv_scanner/imv_scanner.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2011-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
@@ -186,6 +187,7 @@ static TNC_Result receive_message(TNC_IMVID imv_id,
{
pa_tnc_msg_t *pa_tnc_msg;
pa_tnc_attr_t *attr;
+ pen_type_t type;
imv_state_t *state;
enumerator_t *enumerator;
TNC_Result result;
@@ -220,8 +222,9 @@ static TNC_Result receive_message(TNC_IMVID imv_id,
enumerator = pa_tnc_msg->create_attribute_enumerator(pa_tnc_msg);
while (enumerator->enumerate(enumerator, &attr))
{
- if (attr->get_vendor_id(attr) == PEN_IETF &&
- attr->get_type(attr) == IETF_ATTR_PORT_FILTER)
+ type = attr->get_type(attr);
+
+ if (type.vendor_id == PEN_IETF && type.type == IETF_ATTR_PORT_FILTER)
{
ietf_attr_port_filter_t *attr_port_filter;
enumerator_t *enumerator;
@@ -305,10 +308,9 @@ static TNC_Result receive_message(TNC_IMVID imv_id,
state->set_recommendation(state,
TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
TNC_IMV_EVALUATION_RESULT_ERROR);
- return imv_scanner->provide_recommendation(imv_scanner, connection_id);
}
-
- return imv_scanner->provide_recommendation(imv_scanner, connection_id);
+ return imv_scanner->provide_recommendation(imv_scanner, connection_id,
+ src_imc_id);
}
/**
@@ -359,7 +361,8 @@ TNC_Result TNC_IMV_SolicitRecommendation(TNC_IMVID imv_id,
DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
return TNC_RESULT_NOT_INITIALIZED;
}
- return imv_scanner->provide_recommendation(imv_scanner, connection_id);
+ return imv_scanner->provide_recommendation(imv_scanner, connection_id,
+ TNC_IMCID_ANY);
}
/**
diff --git a/src/libimcv/plugins/imv_scanner/imv_scanner_state.c b/src/libimcv/plugins/imv_scanner/imv_scanner_state.c
index 422cb980d..fecc84e70 100644
--- a/src/libimcv/plugins/imv_scanner/imv_scanner_state.c
+++ b/src/libimcv/plugins/imv_scanner/imv_scanner_state.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2011-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
@@ -50,6 +51,11 @@ struct private_imv_scanner_state_t {
bool has_excl;
/**
+ * Maximum PA-TNC message size for this TNCCS connection
+ */
+ u_int32_t max_msg_len;
+
+ /**
* IMV action recommendation
*/
TNC_IMV_Action_Recommendation rec;
@@ -115,6 +121,18 @@ METHOD(imv_state_t, set_flags, void,
this->has_excl = has_excl;
}
+METHOD(imv_state_t, set_max_msg_len, void,
+ private_imv_scanner_state_t *this, u_int32_t max_msg_len)
+{
+ this->max_msg_len = max_msg_len;
+}
+
+METHOD(imv_state_t, get_max_msg_len, u_int32_t,
+ private_imv_scanner_state_t *this)
+{
+ return this->max_msg_len;
+}
+
METHOD(imv_state_t, change_state, void,
private_imv_scanner_state_t *this, TNC_ConnectionState new_state)
{
@@ -223,6 +241,8 @@ imv_state_t *imv_scanner_state_create(TNC_ConnectionID 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,
.change_state = _change_state,
.get_recommendation = _get_recommendation,
.set_recommendation = _set_recommendation,
diff --git a/src/libimcv/plugins/imv_test/Makefile.in b/src/libimcv/plugins/imv_test/Makefile.in
index e51ad9afd..e395f8187 100644
--- a/src/libimcv/plugins/imv_test/Makefile.in
+++ b/src/libimcv/plugins/imv_test/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -81,7 +82,7 @@ imv_test_la_OBJECTS = $(am_imv_test_la_OBJECTS)
imv_test_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(imv_test_la_LDFLAGS) $(LDFLAGS) -o $@
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -107,6 +108,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -201,11 +203,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -222,11 +227,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -242,6 +248,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -251,7 +258,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libimcv/plugins/imv_test/imv_test.c b/src/libimcv/plugins/imv_test/imv_test.c
index 0afd81aec..5ea82e97c 100644
--- a/src/libimcv/plugins/imv_test/imv_test.c
+++ b/src/libimcv/plugins/imv_test/imv_test.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2011-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
@@ -20,6 +21,7 @@
#include <ietf/ietf_attr_pa_tnc_error.h>
#include <ita/ita_attr.h>
#include <ita/ita_attr_command.h>
+#include <ita/ita_attr_dummy.h>
#include <tncif_names.h>
#include <tncif_pa_subtypes.h>
@@ -101,12 +103,14 @@ static TNC_Result receive_message(TNC_IMVID imv_id,
{
pa_tnc_msg_t *pa_tnc_msg;
pa_tnc_attr_t *attr;
+ pen_type_t attr_type;
+ linked_list_t *attr_list;
imv_state_t *state;
imv_test_state_t *test_state;
enumerator_t *enumerator;
TNC_Result result;
int rounds;
- bool fatal_error, retry = FALSE;
+ bool fatal_error, received_command = FALSE, retry = FALSE;
if (!imv_test)
{
@@ -143,12 +147,18 @@ static TNC_Result receive_message(TNC_IMVID imv_id,
enumerator = pa_tnc_msg->create_attribute_enumerator(pa_tnc_msg);
while (enumerator->enumerate(enumerator, &attr))
{
- if (attr->get_vendor_id(attr) == PEN_ITA &&
- attr->get_type(attr) == ITA_ATTR_COMMAND)
+ attr_type = attr->get_type(attr);
+
+ if (attr_type.vendor_id != PEN_ITA)
+ {
+ continue;
+ }
+ if (attr_type.type == ITA_ATTR_COMMAND)
{
ita_attr_command_t *ita_attr;
char *command;
+ received_command = TRUE;
ita_attr = (ita_attr_command_t*)attr;
command = ita_attr->get_command(ita_attr);
@@ -181,7 +191,15 @@ static TNC_Result receive_message(TNC_IMVID imv_id,
TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
TNC_IMV_EVALUATION_RESULT_ERROR);
}
- }
+ }
+ else if (attr_type.type == ITA_ATTR_DUMMY)
+ {
+ ita_attr_dummy_t *ita_attr;
+
+ ita_attr = (ita_attr_dummy_t*)attr;
+ DBG1(DBG_IMV, "received dummy attribute value (%d bytes)",
+ ita_attr->get_size(ita_attr));
+ }
}
enumerator->destroy(enumerator);
pa_tnc_msg->destroy(pa_tnc_msg);
@@ -191,7 +209,8 @@ static TNC_Result receive_message(TNC_IMVID imv_id,
state->set_recommendation(state,
TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
TNC_IMV_EVALUATION_RESULT_ERROR);
- return imv_test->provide_recommendation(imv_test, connection_id);
+ return imv_test->provide_recommendation(imv_test, connection_id,
+ src_imc_id);
}
/* request a handshake retry ? */
@@ -205,18 +224,18 @@ static TNC_Result receive_message(TNC_IMVID imv_id,
/* repeat the measurement ? */
if (test_state->another_round(test_state, src_imc_id))
{
+ attr_list = linked_list_create();
attr = ita_attr_command_create("repeat");
- pa_tnc_msg = pa_tnc_msg_create();
- pa_tnc_msg->add_attribute(pa_tnc_msg, attr);
- pa_tnc_msg->build(pa_tnc_msg);
+ attr_list->insert_last(attr_list, attr);
result = imv_test->send_message(imv_test, connection_id, TRUE, imv_id,
- src_imc_id, pa_tnc_msg->get_encoding(pa_tnc_msg));
- pa_tnc_msg->destroy(pa_tnc_msg);
+ src_imc_id, attr_list);
+ attr_list->destroy(attr_list);
return result;
}
- return imv_test->provide_recommendation(imv_test, connection_id);
+ return received_command ? imv_test->provide_recommendation(imv_test,
+ connection_id, src_imc_id) : TNC_RESULT_SUCCESS;
}
/**
@@ -267,7 +286,8 @@ TNC_Result TNC_IMV_SolicitRecommendation(TNC_IMVID imv_id,
DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
return TNC_RESULT_NOT_INITIALIZED;
}
- return imv_test->provide_recommendation(imv_test, connection_id);
+ return imv_test->provide_recommendation(imv_test, connection_id,
+ TNC_IMCID_ANY);
}
/**
diff --git a/src/libimcv/plugins/imv_test/imv_test_state.c b/src/libimcv/plugins/imv_test/imv_test_state.c
index 530090af7..67f22c062 100644
--- a/src/libimcv/plugins/imv_test/imv_test_state.c
+++ b/src/libimcv/plugins/imv_test/imv_test_state.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2011-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
@@ -51,6 +52,11 @@ struct private_imv_test_state_t {
bool has_excl;
/**
+ * Maximum PA-TNC message size for this TNCCS connection
+ */
+ u_int32_t max_msg_len;
+
+ /**
* IMV action recommendation
*/
TNC_IMV_Action_Recommendation rec;
@@ -122,6 +128,18 @@ METHOD(imv_state_t, set_flags, void,
this->has_excl = has_excl;
}
+METHOD(imv_state_t, set_max_msg_len, void,
+ private_imv_test_state_t *this, u_int32_t max_msg_len)
+{
+ this->max_msg_len = max_msg_len;
+}
+
+METHOD(imv_state_t, get_max_msg_len, u_int32_t,
+ private_imv_test_state_t *this)
+{
+ return this->max_msg_len;
+}
+
METHOD(imv_state_t, change_state, void,
private_imv_test_state_t *this, TNC_ConnectionState new_state)
{
@@ -274,6 +292,8 @@ imv_state_t *imv_test_state_create(TNC_ConnectionID 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,
.change_state = _change_state,
.get_recommendation = _get_recommendation,
.set_recommendation = _set_recommendation,
diff --git a/src/libipsec/Android.mk b/src/libipsec/Android.mk
new file mode 100644
index 000000000..81f4632ef
--- /dev/null
+++ b/src/libipsec/Android.mk
@@ -0,0 +1,38 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+# copy-n-paste from Makefile.am
+LOCAL_SRC_FILES := \
+ipsec.c ipsec.h \
+esp_context.c esp_context.h \
+esp_packet.c esp_packet.h \
+ip_packet.c ip_packet.h \
+ipsec_event_listener.h \
+ipsec_event_relay.c ipsec_event_relay.h \
+ipsec_policy.c ipsec_policy.h \
+ipsec_policy_mgr.c ipsec_policy_mgr.h \
+ipsec_processor.c ipsec_processor.h \
+ipsec_sa.c ipsec_sa.h \
+ipsec_sa_mgr.c ipsec_sa_mgr.h
+
+# build libipsec ---------------------------------------------------------------
+
+LOCAL_C_INCLUDES += \
+ $(libvstr_PATH) \
+ $(strongswan_PATH)/src/include \
+ $(strongswan_PATH)/src/libstrongswan
+
+LOCAL_CFLAGS := $(strongswan_CFLAGS)
+
+LOCAL_MODULE := libipsec
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_SHARED_LIBRARIES += libstrongswan
+
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/src/libipsec/Makefile.am b/src/libipsec/Makefile.am
new file mode 100644
index 000000000..35b8d7916
--- /dev/null
+++ b/src/libipsec/Makefile.am
@@ -0,0 +1,31 @@
+ipseclib_LTLIBRARIES = libipsec.la
+
+libipsec_la_SOURCES = \
+ipsec.c ipsec.h \
+esp_context.c esp_context.h \
+esp_packet.c esp_packet.h \
+ip_packet.c ip_packet.h \
+ipsec_event_listener.h \
+ipsec_event_relay.c ipsec_event_relay.h \
+ipsec_policy.c ipsec_policy.h \
+ipsec_policy_mgr.c ipsec_policy_mgr.h \
+ipsec_processor.c ipsec_processor.h \
+ipsec_sa.c ipsec_sa.h \
+ipsec_sa_mgr.c ipsec_sa_mgr.h
+
+libipsec_la_LIBADD =
+
+INCLUDES = \
+ -I$(top_srcdir)/src/libstrongswan
+
+EXTRA_DIST = Android.mk
+
+# build optional plugins
+########################
+
+if MONOLITHIC
+SUBDIRS =
+else
+SUBDIRS = .
+endif
+
diff --git a/src/libfreeswan/Makefile.in b/src/libipsec/Makefile.in
index b6ee06630..6d984d8ab 100644
--- a/src/libfreeswan/Makefile.in
+++ b/src/libipsec/Makefile.in
@@ -34,9 +34,8 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-subdir = src/libfreeswan
-DIST_COMMON = $(dist_man3_MANS) $(srcdir)/Makefile.am \
- $(srcdir)/Makefile.in
+subdir = src/libipsec
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
$(top_srcdir)/m4/config/ltoptions.m4 \
@@ -50,41 +49,9 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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 =
-LIBRARIES = $(noinst_LIBRARIES)
-ARFLAGS = cru
-libfreeswan_a_AR = $(AR) $(ARFLAGS)
-libfreeswan_a_LIBADD =
-am_libfreeswan_a_OBJECTS = addrtoa.$(OBJEXT) addrtot.$(OBJEXT) \
- addrtypeof.$(OBJEXT) anyaddr.$(OBJEXT) atoaddr.$(OBJEXT) \
- atoasr.$(OBJEXT) atosubnet.$(OBJEXT) atoul.$(OBJEXT) \
- copyright.$(OBJEXT) datatot.$(OBJEXT) goodmask.$(OBJEXT) \
- initaddr.$(OBJEXT) initsaid.$(OBJEXT) initsubnet.$(OBJEXT) \
- pfkey_v2_build.$(OBJEXT) pfkey_v2_debug.$(OBJEXT) \
- pfkey_v2_ext_bits.$(OBJEXT) pfkey_v2_parse.$(OBJEXT) \
- portof.$(OBJEXT) rangetoa.$(OBJEXT) rangetosubnet.$(OBJEXT) \
- sameaddr.$(OBJEXT) satot.$(OBJEXT) subnetof.$(OBJEXT) \
- subnettoa.$(OBJEXT) subnettot.$(OBJEXT) subnettypeof.$(OBJEXT) \
- ttoaddr.$(OBJEXT) ttodata.$(OBJEXT) ttoprotoport.$(OBJEXT) \
- ttosa.$(OBJEXT) ttosubnet.$(OBJEXT) ttoul.$(OBJEXT) \
- ultoa.$(OBJEXT) ultot.$(OBJEXT)
-libfreeswan_a_OBJECTS = $(am_libfreeswan_a_OBJECTS)
-DEFAULT_INCLUDES = -I.@am__isrc@
-depcomp = $(SHELL) $(top_srcdir)/depcomp
-am__depfiles_maybe = depfiles
-am__mv = mv -f
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
- --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
- $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-CCLD = $(CC)
-LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
- --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
- $(LDFLAGS) -o $@
-SOURCES = $(libfreeswan_a_SOURCES)
-DIST_SOURCES = $(libfreeswan_a_SOURCES)
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
@@ -106,13 +73,70 @@ am__nobase_list = $(am__nobase_strip_setup); \
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
-man3dir = $(mandir)/man3
-am__installdirs = "$(DESTDIR)$(man3dir)"
-NROFF = nroff
-MANS = $(dist_man3_MANS)
+am__installdirs = "$(DESTDIR)$(ipseclibdir)"
+LTLIBRARIES = $(ipseclib_LTLIBRARIES)
+libipsec_la_DEPENDENCIES =
+am_libipsec_la_OBJECTS = ipsec.lo esp_context.lo esp_packet.lo \
+ ip_packet.lo ipsec_event_relay.lo ipsec_policy.lo \
+ ipsec_policy_mgr.lo ipsec_processor.lo ipsec_sa.lo \
+ ipsec_sa_mgr.lo
+libipsec_la_OBJECTS = $(am_libipsec_la_OBJECTS)
+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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libipsec_la_SOURCES)
+DIST_SOURCES = $(libipsec_la_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir
ETAGS = etags
CTAGS = ctags
+DIST_SUBDIRS = .
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
ACLOCAL = @ACLOCAL@
ALLOCA = @ALLOCA@
AMTAR = @AMTAR@
@@ -121,6 +145,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -215,11 +240,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -236,11 +264,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -256,6 +285,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -265,7 +295,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -293,29 +322,31 @@ top_srcdir = @top_srcdir@
urandom_device = @urandom_device@
xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
-noinst_LIBRARIES = libfreeswan.a
-libfreeswan_a_SOURCES = \
-addrtoa.c addrtot.c addrtypeof.c anyaddr.c atoaddr.c atoasr.c \
-atosubnet.c atoul.c copyright.c datatot.c freeswan.h \
-goodmask.c initaddr.c initsaid.c initsubnet.c internal.h ipsec_param.h \
-pfkey_v2_build.c pfkey_v2_debug.c \
-pfkey_v2_ext_bits.c pfkey_v2_parse.c portof.c rangetoa.c \
-pfkey.h pfkeyv2.h rangetosubnet.c sameaddr.c \
-satot.c subnetof.c subnettoa.c subnettot.c \
-subnettypeof.c ttoaddr.c ttodata.c ttoprotoport.c ttosa.c ttosubnet.c ttoul.c \
-ultoa.c ultot.c
-
+ipseclib_LTLIBRARIES = libipsec.la
+libipsec_la_SOURCES = \
+ipsec.c ipsec.h \
+esp_context.c esp_context.h \
+esp_packet.c esp_packet.h \
+ip_packet.c ip_packet.h \
+ipsec_event_listener.h \
+ipsec_event_relay.c ipsec_event_relay.h \
+ipsec_policy.c ipsec_policy.h \
+ipsec_policy_mgr.c ipsec_policy_mgr.h \
+ipsec_processor.c ipsec_processor.h \
+ipsec_sa.c ipsec_sa.h \
+ipsec_sa_mgr.c ipsec_sa_mgr.h
+
+libipsec_la_LIBADD =
INCLUDES = \
--I$(top_srcdir)/src/libstrongswan \
--I$(top_srcdir)/src/libhydra \
--I$(top_srcdir)/src/pluto
-
-dist_man3_MANS = anyaddr.3 atoaddr.3 atoasr.3 atoul.3 goodmask.3 initaddr.3 initsubnet.3 \
- portof.3 rangetosubnet.3 sameaddr.3 subnetof.3 \
- ttoaddr.3 ttodata.3 ttosa.3 ttoul.3
+ -I$(top_srcdir)/src/libstrongswan
EXTRA_DIST = Android.mk
-all: all-am
+@MONOLITHIC_FALSE@SUBDIRS = .
+
+# build optional plugins
+########################
+@MONOLITHIC_TRUE@SUBDIRS =
+all: all-recursive
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
@@ -328,9 +359,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libfreeswan/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libipsec/Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --gnu src/libfreeswan/Makefile
+ $(AUTOMAKE) --gnu src/libipsec/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
@@ -349,13 +380,39 @@ $(top_srcdir)/configure: $(am__configure_deps)
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
+install-ipseclibLTLIBRARIES: $(ipseclib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(ipseclibdir)" || $(MKDIR_P) "$(DESTDIR)$(ipseclibdir)"
+ @list='$(ipseclib_LTLIBRARIES)'; test -n "$(ipseclibdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(ipseclibdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(ipseclibdir)"; \
+ }
-clean-noinstLIBRARIES:
- -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
-libfreeswan.a: $(libfreeswan_a_OBJECTS) $(libfreeswan_a_DEPENDENCIES)
- -rm -f libfreeswan.a
- $(libfreeswan_a_AR) libfreeswan.a $(libfreeswan_a_OBJECTS) $(libfreeswan_a_LIBADD)
- $(RANLIB) libfreeswan.a
+uninstall-ipseclibLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(ipseclib_LTLIBRARIES)'; test -n "$(ipseclibdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(ipseclibdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(ipseclibdir)/$$f"; \
+ done
+
+clean-ipseclibLTLIBRARIES:
+ -test -z "$(ipseclib_LTLIBRARIES)" || rm -f $(ipseclib_LTLIBRARIES)
+ @list='$(ipseclib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libipsec.la: $(libipsec_la_OBJECTS) $(libipsec_la_DEPENDENCIES)
+ $(LINK) -rpath $(ipseclibdir) $(libipsec_la_OBJECTS) $(libipsec_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -363,41 +420,16 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/addrtoa.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/addrtot.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/addrtypeof.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/anyaddr.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atoaddr.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atoasr.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atosubnet.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atoul.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/copyright.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/datatot.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/goodmask.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/initaddr.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/initsaid.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/initsubnet.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pfkey_v2_build.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pfkey_v2_debug.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pfkey_v2_ext_bits.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pfkey_v2_parse.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/portof.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rangetoa.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rangetosubnet.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sameaddr.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/satot.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subnetof.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subnettoa.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subnettot.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subnettypeof.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ttoaddr.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ttodata.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ttoprotoport.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ttosa.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ttosubnet.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ttoul.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ultoa.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ultot.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/esp_context.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/esp_packet.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ip_packet.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipsec.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipsec_event_relay.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipsec_policy.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipsec_policy_mgr.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipsec_processor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipsec_sa.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipsec_sa_mgr.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@@ -425,40 +457,76 @@ mostlyclean-libtool:
clean-libtool:
-rm -rf .libs _libs
-install-man3: $(dist_man3_MANS)
- @$(NORMAL_INSTALL)
- test -z "$(man3dir)" || $(MKDIR_P) "$(DESTDIR)$(man3dir)"
- @list='$(dist_man3_MANS)'; test -n "$(man3dir)" || exit 0; \
- { for i in $$list; do echo "$$i"; done; \
- } | while read p; do \
- if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
- echo "$$d$$p"; echo "$$p"; \
- done | \
- sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \
- -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
- sed 'N;N;s,\n, ,g' | { \
- list=; while read file base inst; do \
- if test "$$base" = "$$inst"; then list="$$list $$file"; else \
- echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \
- $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst" || exit $$?; \
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
done; \
- for i in $$list; do echo "$$i"; done | $(am__base_list) | \
- while read files; do \
- test -z "$$files" || { \
- echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man3dir)'"; \
- $(INSTALL_DATA) $$files "$(DESTDIR)$(man3dir)" || exit $$?; }; \
- done; }
-
-uninstall-man3:
- @$(NORMAL_UNINSTALL)
- @list='$(dist_man3_MANS)'; test -n "$(man3dir)" || exit 0; \
- files=`{ for i in $$list; do echo "$$i"; done; \
- } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \
- -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
- test -z "$$files" || { \
- echo " ( cd '$(DESTDIR)$(man3dir)' && rm -f" $$files ")"; \
- cd "$(DESTDIR)$(man3dir)" && rm -f $$files; }
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
@@ -470,10 +538,23 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
mkid -fID $$unique
tags: TAGS
-TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
set x; \
here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
@@ -492,7 +573,7 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
fi; \
fi
ctags: CTAGS
-CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
@@ -513,19 +594,6 @@ distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
- @list='$(MANS)'; if test -n "$$list"; then \
- list=`for p in $$list; do \
- if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
- if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \
- if test -n "$$list" && \
- grep 'ab help2man is required to generate this page' $$list >/dev/null; then \
- echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \
- grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \
- echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \
- echo " typically \`make maintainer-clean' will remove them" >&2; \
- exit 1; \
- else :; fi; \
- else :; fi
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
@@ -555,22 +623,51 @@ distdir: $(DISTFILES)
|| exit 1; \
fi; \
done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
check-am: all-am
-check: check-am
-all-am: Makefile $(LIBRARIES) $(MANS)
-installdirs:
- for dir in "$(DESTDIR)$(man3dir)"; do \
+check: check-recursive
+all-am: Makefile $(LTLIBRARIES)
+installdirs: installdirs-recursive
+installdirs-am:
+ for dir in "$(DESTDIR)$(ipseclibdir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
-install: install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-installcheck: installcheck-am
+installcheck: installcheck-recursive
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
@@ -587,94 +684,95 @@ distclean-generic:
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
-clean: clean-am
+clean: clean-recursive
-clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \
+clean-am: clean-generic clean-ipseclibLTLIBRARIES clean-libtool \
mostlyclean-am
-distclean: distclean-am
+distclean: distclean-recursive
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
-dvi: dvi-am
+dvi: dvi-recursive
dvi-am:
-html: html-am
+html: html-recursive
html-am:
-info: info-am
+info: info-recursive
info-am:
-install-data-am: install-man
+install-data-am: install-ipseclibLTLIBRARIES
-install-dvi: install-dvi-am
+install-dvi: install-dvi-recursive
install-dvi-am:
install-exec-am:
-install-html: install-html-am
+install-html: install-html-recursive
install-html-am:
-install-info: install-info-am
+install-info: install-info-recursive
install-info-am:
-install-man: install-man3
+install-man:
-install-pdf: install-pdf-am
+install-pdf: install-pdf-recursive
install-pdf-am:
-install-ps: install-ps-am
+install-ps: install-ps-recursive
install-ps-am:
installcheck-am:
-maintainer-clean: maintainer-clean-am
+maintainer-clean: maintainer-clean-recursive
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
-mostlyclean: mostlyclean-am
+mostlyclean: mostlyclean-recursive
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
-pdf: pdf-am
+pdf: pdf-recursive
pdf-am:
-ps: ps-am
+ps: ps-recursive
ps-am:
-uninstall-am: uninstall-man
-
-uninstall-man: uninstall-man3
-
-.MAKE: install-am install-strip
-
-.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libtool clean-noinstLIBRARIES ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-man3 install-pdf install-pdf-am install-ps \
- install-ps-am install-strip installcheck installcheck-am \
- installdirs maintainer-clean maintainer-clean-generic \
+uninstall-am: uninstall-ipseclibLTLIBRARIES
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+ install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-am clean clean-generic \
+ clean-ipseclibLTLIBRARIES clean-libtool ctags ctags-recursive \
+ distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-ipseclibLTLIBRARIES install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ installdirs-am maintainer-clean maintainer-clean-generic \
mostlyclean mostlyclean-compile mostlyclean-generic \
- mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
- uninstall-am uninstall-man uninstall-man3
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \
+ uninstall uninstall-am uninstall-ipseclibLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libipsec/esp_context.c b/src/libipsec/esp_context.c
new file mode 100644
index 000000000..dc3ad3f8b
--- /dev/null
+++ b/src/libipsec/esp_context.c
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012 Giuliano Grassi
+ * Copyright (C) 2012 Ralf Sager
+ * 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 <limits.h>
+#include <stdint.h>
+
+#include "esp_context.h"
+
+#include <library.h>
+#include <debug.h>
+#include <crypto/crypters/crypter.h>
+#include <crypto/signers/signer.h>
+
+/**
+ * Should be a multiple of 8
+ */
+#define ESP_DEFAULT_WINDOW_SIZE 128
+
+typedef struct private_esp_context_t private_esp_context_t;
+
+/**
+ * Private additions to esp_context_t.
+ */
+struct private_esp_context_t {
+
+ /**
+ * Public members
+ */
+ esp_context_t public;
+
+ /**
+ * Crypter used to encrypt/decrypt ESP packets
+ */
+ crypter_t *crypter;
+
+ /**
+ * Signer to authenticate ESP packets
+ */
+ signer_t *signer;
+
+ /**
+ * The highest sequence number that was successfully verified
+ * and authenticated, or assigned in an outbound context
+ */
+ u_int32_t last_seqno;
+
+ /**
+ * The bit in the window of the highest authenticated sequence number
+ */
+ u_int seqno_index;
+
+ /**
+ * The size of the anti-replay window (in bits)
+ */
+ u_int window_size;
+
+ /**
+ * The anti-replay window buffer
+ */
+ chunk_t window;
+
+ /**
+ * TRUE in case of an inbound ESP context
+ */
+ bool inbound;
+};
+
+/**
+ * Set or unset a bit in the window.
+ */
+static inline void set_window_bit(private_esp_context_t *this,
+ u_int index, bool set)
+{
+ u_int i = index / CHAR_BIT;
+
+ if (set)
+ {
+ this->window.ptr[i] |= 1 << (index % CHAR_BIT);
+ }
+ else
+ {
+ this->window.ptr[i] &= ~(1 << (index % CHAR_BIT));
+ }
+}
+
+/**
+ * Get a bit from the window.
+ */
+static inline bool get_window_bit(private_esp_context_t *this, u_int index)
+{
+ u_int i = index / CHAR_BIT;
+
+ return this->window.ptr[i] & (1 << index % CHAR_BIT);
+}
+
+/**
+ * Returns TRUE if the supplied seqno is not already marked in the window
+ */
+static bool check_window(private_esp_context_t *this, u_int32_t seqno)
+{
+ u_int offset;
+
+ offset = this->last_seqno - seqno;
+ offset = (this->seqno_index - offset) % this->window_size;
+ return !get_window_bit(this, offset);
+}
+
+METHOD(esp_context_t, verify_seqno, bool,
+ private_esp_context_t *this, u_int32_t seqno)
+{
+ if (!this->inbound)
+ {
+ return FALSE;
+ }
+
+ if (seqno > this->last_seqno)
+ { /* |----------------------------------------|
+ * <---------^ ^ or <---------^ ^
+ * WIN H S WIN H S
+ */
+ return TRUE;
+ }
+ else if (seqno > 0 && this->window_size > this->last_seqno - seqno)
+ { /* |----------------------------------------|
+ * <---------^ or <---------^
+ * WIN ^ H WIN ^ H
+ * S S
+ */
+ return check_window(this, seqno);
+ }
+ else
+ { /* |----------------------------------------|
+ * ^ <---------^
+ * S WIN H
+ */
+ return FALSE;
+ }
+}
+
+METHOD(esp_context_t, set_authenticated_seqno, void,
+ private_esp_context_t *this, u_int32_t seqno)
+{
+ u_int i, shift;
+
+ if (!this->inbound)
+ {
+ return;
+ }
+
+ if (seqno > this->last_seqno)
+ { /* shift the window to the new highest authenticated seqno */
+ shift = seqno - this->last_seqno;
+ shift = shift < this->window_size ? shift : this->window_size;
+ for (i = 0; i < shift; ++i)
+ {
+ this->seqno_index = (this->seqno_index + 1) % this->window_size;
+ set_window_bit(this, this->seqno_index, FALSE);
+ }
+ set_window_bit(this, this->seqno_index, TRUE);
+ this->last_seqno = seqno;
+ }
+ else
+ { /* seqno is inside the window, set the corresponding window bit */
+ i = this->last_seqno - seqno;
+ set_window_bit(this, (this->seqno_index - i) % this->window_size, TRUE);
+ }
+}
+
+METHOD(esp_context_t, get_seqno, u_int32_t,
+ private_esp_context_t *this)
+{
+ return this->last_seqno;
+}
+
+METHOD(esp_context_t, next_seqno, bool,
+ private_esp_context_t *this, u_int32_t *seqno)
+{
+ if (this->inbound || this->last_seqno == UINT32_MAX)
+ { /* inbound or segno would cycle */
+ return FALSE;
+ }
+ *seqno = ++this->last_seqno;
+ return TRUE;
+}
+
+METHOD(esp_context_t, get_signer, signer_t *,
+ private_esp_context_t *this)
+{
+ return this->signer;
+}
+
+METHOD(esp_context_t, get_crypter, crypter_t *,
+ private_esp_context_t *this)
+{
+ return this->crypter;
+}
+
+METHOD(esp_context_t, destroy, void,
+ private_esp_context_t *this)
+{
+ chunk_free(&this->window);
+ DESTROY_IF(this->crypter);
+ DESTROY_IF(this->signer);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+esp_context_t *esp_context_create(int enc_alg, chunk_t enc_key,
+ int int_alg, chunk_t int_key, bool inbound)
+{
+ private_esp_context_t *this;
+
+ INIT(this,
+ .public = {
+ .get_crypter = _get_crypter,
+ .get_signer = _get_signer,
+ .get_seqno = _get_seqno,
+ .next_seqno = _next_seqno,
+ .verify_seqno = _verify_seqno,
+ .set_authenticated_seqno = _set_authenticated_seqno,
+ .destroy = _destroy,
+ },
+ .inbound = inbound,
+ .window_size = ESP_DEFAULT_WINDOW_SIZE,
+ );
+
+ switch(enc_alg)
+ {
+ case ENCR_AES_CBC:
+ this->crypter = lib->crypto->create_crypter(lib->crypto, enc_alg,
+ enc_key.len);
+ break;
+ default:
+ break;
+ }
+ if (!this->crypter)
+ {
+ DBG1(DBG_ESP, "failed to create ESP context: unsupported encryption "
+ "algorithm");
+ destroy(this);
+ return NULL;
+ }
+ if (!this->crypter->set_key(this->crypter, enc_key))
+ {
+ DBG1(DBG_ESP, "failed to create ESP context: setting encryption key "
+ "failed");
+ destroy(this);
+ return NULL;
+ }
+
+ switch(int_alg)
+ {
+ case AUTH_HMAC_SHA1_96:
+ case AUTH_HMAC_SHA2_256_128:
+ case AUTH_HMAC_SHA2_384_192:
+ case AUTH_HMAC_SHA2_512_256:
+ this->signer = lib->crypto->create_signer(lib->crypto, int_alg);
+ break;
+ default:
+ break;
+ }
+ if (!this->signer)
+ {
+ DBG1(DBG_ESP, "failed to create ESP context: unsupported integrity "
+ "algorithm");
+ destroy(this);
+ return NULL;
+ }
+ if (!this->signer->set_key(this->signer, int_key))
+ {
+ DBG1(DBG_ESP, "failed to create ESP context: setting signature key "
+ "failed");
+ destroy(this);
+ return NULL;
+ }
+
+ if (inbound)
+ {
+ this->window = chunk_alloc(this->window_size / CHAR_BIT + 1);
+ memset(this->window.ptr, 0, this->window.len);
+ }
+ return &this->public;
+}
+
+
diff --git a/src/libipsec/esp_context.h b/src/libipsec/esp_context.h
new file mode 100644
index 000000000..db247dced
--- /dev/null
+++ b/src/libipsec/esp_context.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012 Giuliano Grassi
+ * Copyright (C) 2012 Ralf Sager
+ * 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 esp_context esp_context
+ * @{ @ingroup libipsec
+ */
+
+#ifndef ESP_CONTEXT_H_
+#define ESP_CONTEXT_H_
+
+#include <library.h>
+#include <crypto/crypters/crypter.h>
+#include <crypto/signers/signer.h>
+
+typedef struct esp_context_t esp_context_t;
+
+/**
+ * ESP context, handles sequence numbers and maintains cryptographic primitives
+ */
+struct esp_context_t {
+
+ /**
+ * Get the crypter.
+ *
+ * @return crypter
+ */
+ crypter_t *(*get_crypter)(esp_context_t *this);
+
+ /**
+ * Get the signer.
+ *
+ * @return signer
+ */
+ signer_t *(*get_signer)(esp_context_t *this);
+
+ /**
+ * Get the current outbound ESP sequence number or the highest authenticated
+ * inbound sequence number.
+ *
+ * @return current sequence number, in host byte order
+ */
+ u_int32_t (*get_seqno)(esp_context_t *this);
+
+ /**
+ * Allocate the next outbound ESP sequence number.
+ *
+ * @param seqno the sequence number, in host byte order
+ * @return FALSE if the sequence number cycled or inbound context
+ */
+ bool (*next_seqno)(esp_context_t *this, u_int32_t *seqno);
+
+ /**
+ * Verify an ESP sequence number. Checks whether a packet with this
+ * sequence number was already received, using the anti-replay window.
+ * This operation does not modify the internal state. After the sequence
+ * number is successfully verified and the ESP packet is authenticated,
+ * set_authenticated_seqno() should be called.
+ *
+ * @param seqno the sequence number to verify, in host byte order
+ * @return TRUE when sequence number is valid
+ */
+ bool (*verify_seqno)(esp_context_t *this, u_int32_t seqno);
+
+ /**
+ * Adds a sequence number that was successfully verified and
+ * authenticated. A user MUST call verify_seqno() immediately before
+ * calling this method.
+ *
+ * @param seqno verified and authenticated seq number in host byte order
+ */
+ void (*set_authenticated_seqno)(esp_context_t *this,
+ u_int32_t seqno);
+
+ /**
+ * Destroy an esp_context_t
+ */
+ void (*destroy)(esp_context_t *this);
+
+};
+
+/**
+ * Create an esp_context_t instance
+ *
+ * @param enc_alg encryption algorithm
+ * @param enc_key encryption key
+ * @param int_alg integrity protection algorithm
+ * @param int_key integrity protection key
+ * @param inbound TRUE to create an inbound ESP context
+ * @return ESP context instance, or NULL if creation fails
+ */
+esp_context_t *esp_context_create(int enc_alg, chunk_t enc_key, int int_alg,
+ chunk_t int_key, bool inbound);
+
+#endif /** ESP_CONTEXT_H_ @}*/
+
diff --git a/src/libipsec/esp_packet.c b/src/libipsec/esp_packet.c
new file mode 100644
index 000000000..bfcab95eb
--- /dev/null
+++ b/src/libipsec/esp_packet.c
@@ -0,0 +1,468 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012 Giuliano Grassi
+ * Copyright (C) 2012 Ralf Sager
+ * 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 "esp_packet.h"
+
+#include <library.h>
+#include <debug.h>
+#include <crypto/crypters/crypter.h>
+#include <crypto/signers/signer.h>
+#include <bio/bio_reader.h>
+#include <bio/bio_writer.h>
+
+#include <netinet/in.h>
+
+typedef struct private_esp_packet_t private_esp_packet_t;
+
+/**
+ * Private additions to esp_packet_t.
+ */
+struct private_esp_packet_t {
+
+ /**
+ * Public members
+ */
+ esp_packet_t public;
+
+ /**
+ * Raw ESP packet
+ */
+ packet_t *packet;
+
+ /**
+ * Payload of this packet
+ */
+ ip_packet_t *payload;
+
+ /**
+ * Next Header info (e.g. IPPROTO_IPIP)
+ */
+ u_int8_t next_header;
+
+};
+
+/**
+ * Forward declaration for clone()
+ */
+static private_esp_packet_t *esp_packet_create_internal(packet_t *packet);
+
+METHOD(packet_t, set_source, void,
+ private_esp_packet_t *this, host_t *src)
+{
+ return this->packet->set_source(this->packet, src);
+}
+
+METHOD2(esp_packet_t, packet_t, get_source, host_t*,
+ private_esp_packet_t *this)
+{
+ return this->packet->get_source(this->packet);
+}
+
+METHOD(packet_t, set_destination, void,
+ private_esp_packet_t *this, host_t *dst)
+{
+ return this->packet->set_destination(this->packet, dst);
+}
+
+METHOD2(esp_packet_t, packet_t, get_destination, host_t*,
+ private_esp_packet_t *this)
+{
+ return this->packet->get_destination(this->packet);
+}
+
+METHOD(packet_t, get_data, chunk_t,
+ private_esp_packet_t *this)
+{
+ return this->packet->get_data(this->packet);
+}
+
+METHOD(packet_t, set_data, void,
+ private_esp_packet_t *this, chunk_t data)
+{
+ return this->packet->set_data(this->packet, data);
+}
+
+METHOD(packet_t, skip_bytes, void,
+ private_esp_packet_t *this, size_t bytes)
+{
+ return this->packet->skip_bytes(this->packet, bytes);
+}
+
+METHOD(packet_t, clone, packet_t*,
+ private_esp_packet_t *this)
+{
+ private_esp_packet_t *pkt;
+
+ pkt = esp_packet_create_internal(this->packet->clone(this->packet));
+ pkt->payload = this->payload ? this->payload->clone(this->payload) : NULL;
+ pkt->next_header = this->next_header;
+ return &pkt->public.packet;
+}
+
+METHOD(esp_packet_t, parse_header, bool,
+ private_esp_packet_t *this, u_int32_t *spi)
+{
+ bio_reader_t *reader;
+ u_int32_t seq;
+
+ reader = bio_reader_create(this->packet->get_data(this->packet));
+ if (!reader->read_uint32(reader, spi) ||
+ !reader->read_uint32(reader, &seq))
+ {
+ DBG1(DBG_ESP, "failed to parse ESP header: invalid length");
+ reader->destroy(reader);
+ return FALSE;
+ }
+ reader->destroy(reader);
+
+ DBG2(DBG_ESP, "parsed ESP header with SPI %.8x [seq %u]", *spi, seq);
+ *spi = htonl(*spi);
+ return TRUE;
+}
+
+/**
+ * Check padding as specified in RFC 4303
+ */
+static bool check_padding(chunk_t padding)
+{
+ size_t i;
+
+ for (i = 0; i < padding.len; ++i)
+ {
+ if (padding.ptr[i] != (u_int8_t)(i + 1))
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * Remove the padding from the payload and set the next header info
+ */
+static bool remove_padding(private_esp_packet_t *this, chunk_t plaintext)
+{
+ u_int8_t next_header, pad_length;
+ chunk_t padding, payload;
+ bio_reader_t *reader;
+
+ reader = bio_reader_create(plaintext);
+ if (!reader->read_uint8_end(reader, &next_header) ||
+ !reader->read_uint8_end(reader, &pad_length))
+ {
+ DBG1(DBG_ESP, "parsing ESP payload failed: invalid length");
+ goto failed;
+ }
+ if (!reader->read_data_end(reader, pad_length, &padding) ||
+ !check_padding(padding))
+ {
+ DBG1(DBG_ESP, "parsing ESP payload failed: invalid padding");
+ goto failed;
+ }
+ this->payload = ip_packet_create(reader->peek(reader));
+ reader->destroy(reader);
+ if (!this->payload)
+ {
+ DBG1(DBG_ESP, "parsing ESP payload failed: unsupported payload");
+ return FALSE;
+ }
+ this->next_header = next_header;
+ payload = this->payload->get_encoding(this->payload);
+
+ DBG3(DBG_ESP, "ESP payload:\n payload %B\n padding %B\n "
+ "padding length = %hhu, next header = %hhu", &payload, &padding,
+ pad_length, this->next_header);
+ return TRUE;
+
+failed:
+ reader->destroy(reader);
+ chunk_free(&plaintext);
+ return FALSE;
+}
+
+METHOD(esp_packet_t, decrypt, status_t,
+ private_esp_packet_t *this, esp_context_t *esp_context)
+{
+ bio_reader_t *reader;
+ u_int32_t spi, seq;
+ chunk_t data, iv, icv, ciphertext, plaintext;
+ crypter_t *crypter;
+ signer_t *signer;
+
+ DESTROY_IF(this->payload);
+ this->payload = NULL;
+
+ data = this->packet->get_data(this->packet);
+ crypter = esp_context->get_crypter(esp_context);
+ signer = esp_context->get_signer(esp_context);
+
+ reader = bio_reader_create(data);
+ if (!reader->read_uint32(reader, &spi) ||
+ !reader->read_uint32(reader, &seq) ||
+ !reader->read_data(reader, crypter->get_iv_size(crypter), &iv) ||
+ !reader->read_data_end(reader, signer->get_block_size(signer), &icv) ||
+ reader->remaining(reader) % crypter->get_block_size(crypter))
+ {
+ DBG1(DBG_ESP, "ESP decryption failed: invalid length");
+ return PARSE_ERROR;
+ }
+ ciphertext = reader->peek(reader);
+ reader->destroy(reader);
+
+ if (!esp_context->verify_seqno(esp_context, seq))
+ {
+ DBG1(DBG_ESP, "ESP sequence number verification failed:\n "
+ "src %H, dst %H, SPI %.8x [seq %u]",
+ get_source(this), get_destination(this), spi, seq);
+ return VERIFY_ERROR;
+ }
+ DBG3(DBG_ESP, "ESP decryption:\n SPI %.8x [seq %u]\n IV %B\n "
+ "encrypted %B\n ICV %B", spi, seq, &iv, &ciphertext, &icv);
+
+ if (!signer->get_signature(signer, chunk_create(data.ptr, 8), NULL) ||
+ !signer->get_signature(signer, iv, NULL) ||
+ !signer->verify_signature(signer, ciphertext, icv))
+ {
+ DBG1(DBG_ESP, "ICV verification failed!");
+ return FAILED;
+ }
+ esp_context->set_authenticated_seqno(esp_context, seq);
+
+ if (!crypter->decrypt(crypter, ciphertext, iv, &plaintext))
+ {
+ DBG1(DBG_ESP, "ESP decryption failed");
+ return FAILED;
+ }
+
+ if (!remove_padding(this, plaintext))
+ {
+ return PARSE_ERROR;
+ }
+ return SUCCESS;
+}
+
+/**
+ * Generate the padding as specified in RFC4303
+ */
+static void generate_padding(chunk_t padding)
+{
+ size_t i;
+
+ for (i = 0; i < padding.len; ++i)
+ {
+ padding.ptr[i] = (u_int8_t)(i + 1);
+ }
+}
+
+METHOD(esp_packet_t, encrypt, status_t,
+ private_esp_packet_t *this, esp_context_t *esp_context, u_int32_t spi)
+{
+ chunk_t iv, icv, padding, payload, ciphertext, auth_data;
+ bio_writer_t *writer;
+ u_int32_t next_seqno;
+ size_t blocksize, plainlen;
+ crypter_t *crypter;
+ signer_t *signer;
+ rng_t *rng;
+
+ this->packet->set_data(this->packet, chunk_empty);
+
+ if (!esp_context->next_seqno(esp_context, &next_seqno))
+ {
+ DBG1(DBG_ESP, "ESP encapsulation failed: sequence numbers cycled");
+ return FAILED;
+ }
+
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ if (!rng)
+ {
+ DBG1(DBG_ESP, "ESP encryption failed: could not find RNG");
+ return NOT_FOUND;
+ }
+ crypter = esp_context->get_crypter(esp_context);
+ signer = esp_context->get_signer(esp_context);
+
+ blocksize = crypter->get_block_size(crypter);
+ iv.len = crypter->get_iv_size(crypter);
+ icv.len = signer->get_block_size(signer);
+
+ /* plaintext = payload, padding, pad_length, next_header */
+ payload = this->payload ? this->payload->get_encoding(this->payload)
+ : chunk_empty;
+ plainlen = payload.len + 2;
+ padding.len = blocksize - (plainlen % blocksize);
+ plainlen += padding.len;
+
+ /* len = spi, seq, IV, plaintext, ICV */
+ writer = bio_writer_create(2 * sizeof(u_int32_t) + iv.len + plainlen +
+ icv.len);
+ writer->write_uint32(writer, ntohl(spi));
+ writer->write_uint32(writer, next_seqno);
+
+ iv = writer->skip(writer, iv.len);
+ if (!rng->get_bytes(rng, iv.len, iv.ptr))
+ {
+ DBG1(DBG_ESP, "ESP encryption failed: could not generate IV");
+ writer->destroy(writer);
+ rng->destroy(rng);
+ return FAILED;
+ }
+ rng->destroy(rng);
+
+ /* plain-/ciphertext will start here */
+ ciphertext = writer->get_buf(writer);
+ ciphertext.ptr += ciphertext.len;
+ ciphertext.len = plainlen;
+
+ writer->write_data(writer, payload);
+
+ padding = writer->skip(writer, padding.len);
+ generate_padding(padding);
+
+ writer->write_uint8(writer, padding.len);
+ writer->write_uint8(writer, this->next_header);
+
+ DBG3(DBG_ESP, "ESP before encryption:\n payload = %B\n padding = %B\n "
+ "padding length = %hhu, next header = %hhu", &payload, &padding,
+ (u_int8_t)padding.len, this->next_header);
+
+ /* encrypt the content inline */
+ if (!crypter->encrypt(crypter, ciphertext, iv, NULL))
+ {
+ DBG1(DBG_ESP, "ESP encryption failed");
+ writer->destroy(writer);
+ return FAILED;
+ }
+
+ /* calculate signature */
+ auth_data = writer->get_buf(writer);
+ icv = writer->skip(writer, icv.len);
+ if (!signer->get_signature(signer, auth_data, icv.ptr))
+ {
+ DBG1(DBG_ESP, "ESP encryption failed: signature generation failed");
+ writer->destroy(writer);
+ return FAILED;
+ }
+
+ DBG3(DBG_ESP, "ESP packet:\n SPI %.8x [seq %u]\n IV %B\n "
+ "encrypted %B\n ICV %B", ntohl(spi), next_seqno, &iv,
+ &ciphertext, &icv);
+
+ this->packet->set_data(this->packet, writer->extract_buf(writer));
+ writer->destroy(writer);
+ return SUCCESS;
+}
+
+METHOD(esp_packet_t, get_next_header, u_int8_t,
+ private_esp_packet_t *this)
+{
+ return this->next_header;
+}
+
+METHOD(esp_packet_t, get_payload, ip_packet_t*,
+ private_esp_packet_t *this)
+{
+ return this->payload;
+}
+
+METHOD(esp_packet_t, extract_payload, ip_packet_t*,
+ private_esp_packet_t *this)
+{
+ ip_packet_t *payload;
+
+ payload = this->payload;
+ this->payload = NULL;
+ return payload;
+}
+
+METHOD2(esp_packet_t, packet_t, destroy, void,
+ private_esp_packet_t *this)
+{
+ DESTROY_IF(this->payload);
+ this->packet->destroy(this->packet);
+ free(this);
+}
+
+static private_esp_packet_t *esp_packet_create_internal(packet_t *packet)
+{
+ private_esp_packet_t *this;
+
+ INIT(this,
+ .public = {
+ .packet = {
+ .set_source = _set_source,
+ .get_source = _get_source,
+ .set_destination = _set_destination,
+ .get_destination = _get_destination,
+ .get_data = _get_data,
+ .set_data = _set_data,
+ .skip_bytes = _skip_bytes,
+ .clone = _clone,
+ .destroy = _destroy,
+ },
+ .get_source = _get_source,
+ .get_destination = _get_destination,
+ .get_next_header = _get_next_header,
+ .parse_header = _parse_header,
+ .decrypt = _decrypt,
+ .encrypt = _encrypt,
+ .get_payload = _get_payload,
+ .extract_payload = _extract_payload,
+ .destroy = _destroy,
+ },
+ .packet = packet,
+ .next_header = IPPROTO_NONE,
+ );
+ return this;
+}
+
+/**
+ * Described in header.
+ */
+esp_packet_t *esp_packet_create_from_packet(packet_t *packet)
+{
+ private_esp_packet_t *this;
+
+ this = esp_packet_create_internal(packet);
+
+ return &this->public;
+}
+
+/**
+ * Described in header.
+ */
+esp_packet_t *esp_packet_create_from_payload(host_t *src, host_t *dst,
+ ip_packet_t *payload)
+{
+ private_esp_packet_t *this;
+ packet_t *packet;
+
+ packet = packet_create_from_data(src, dst, chunk_empty);
+ this = esp_packet_create_internal(packet);
+ this->payload = payload;
+ if (payload)
+ {
+ this->next_header = payload->get_version(payload) == 4 ? IPPROTO_IPIP
+ : IPPROTO_IPV6;
+ }
+ else
+ {
+ this->next_header = IPPROTO_NONE;
+ }
+ return &this->public;
+}
diff --git a/src/libipsec/esp_packet.h b/src/libipsec/esp_packet.h
new file mode 100644
index 000000000..a1d1602c1
--- /dev/null
+++ b/src/libipsec/esp_packet.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012 Giuliano Grassi
+ * Copyright (C) 2012 Ralf Sager
+ * 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 esp_packet esp_packet
+ * @{ @ingroup libipsec
+ */
+
+#ifndef ESP_PACKET_H_
+#define ESP_PACKET_H_
+
+#include "ip_packet.h"
+#include "esp_context.h"
+
+#include <library.h>
+#include <utils/host.h>
+#include <utils/packet.h>
+
+typedef struct esp_packet_t esp_packet_t;
+
+/**
+ * ESP packet
+ */
+struct esp_packet_t {
+
+ /**
+ * Implements packet_t interface to access the raw ESP packet
+ */
+ packet_t packet;
+
+ /**
+ * Get the source address of this packet
+ *
+ * @return source host
+ */
+ host_t *(*get_source)(esp_packet_t *this);
+
+ /**
+ * Get the destination address of this packet
+ *
+ * @return destination host
+ */
+ host_t *(*get_destination)(esp_packet_t *this);
+
+ /**
+ * Parse the packet header before decryption. Tries to read the SPI
+ * from the packet to find a corresponding SA.
+ *
+ * @param spi parsed SPI, in network byte order
+ * @return TRUE when successful, FALSE otherwise (e.g. when the
+ * length of the packet is invalid)
+ */
+ bool (*parse_header)(esp_packet_t *this, u_int32_t *spi);
+
+ /**
+ * Authenticate and decrypt the packet. Also verifies the sequence number
+ * using the supplied ESP context and updates the anti-replay window.
+ *
+ * @param esp_context ESP context of corresponding inbound IPsec SA
+ * @return - SUCCESS if successfully authenticated,
+ * decrypted and parsed
+ * - PARSE_ERROR if the length of the packet or the
+ * padding is invalid
+ * - VERIFY_ERROR if the sequence number
+ * verification failed
+ * - FAILED if the ICV (MAC) check or the actual
+ * decryption failed
+ */
+ status_t (*decrypt)(esp_packet_t *this, esp_context_t *esp_context);
+
+ /**
+ * Encapsulate and encrypt the packet. The sequence number will be generated
+ * using the supplied ESP context.
+ *
+ * @param esp_context ESP context of corresponding outbound IPsec SA
+ * @param spi SPI value to use, in network byte order
+ * @return - SUCCESS if encrypted
+ * - FAILED if sequence number cycled or any of the
+ * cryptographic functions failed
+ * - NOT_FOUND if no suitable RNG could be found
+ */
+ status_t (*encrypt)(esp_packet_t *this, esp_context_t *esp_context,
+ u_int32_t spi);
+
+ /**
+ * Get the next header field of a packet.
+ *
+ * @note Packet has to be in the decrypted state.
+ *
+ * @return next header field
+ */
+ u_int8_t (*get_next_header)(esp_packet_t *this);
+
+ /**
+ * Get the plaintext payload of this packet.
+ *
+ * @return plaintext payload (internal data),
+ * NULL if not decrypted
+ */
+ ip_packet_t *(*get_payload)(esp_packet_t *this);
+
+ /**
+ * Extract the plaintext payload from this packet.
+ *
+ * @return plaintext payload (has to be destroyed),
+ * NULL if not decrypted
+ */
+ ip_packet_t *(*extract_payload)(esp_packet_t *this);
+
+ /**
+ * Destroy an esp_packet_t
+ */
+ void (*destroy)(esp_packet_t *this);
+
+};
+
+/**
+ * Create an ESP packet out of data from the wire.
+ *
+ * @param packet the packet data as received, gets owned
+ * @return esp_packet_t instance
+ */
+esp_packet_t *esp_packet_create_from_packet(packet_t *packet);
+
+/**
+ * Create an ESP packet from a plaintext payload
+ *
+ * @param src source address
+ * @param dst destination address
+ * @param payload plaintext payload, gets owned
+ * @return esp_packet_t instance
+ */
+esp_packet_t *esp_packet_create_from_payload(host_t *src, host_t *dst,
+ ip_packet_t *payload);
+
+#endif /** ESP_PACKET_H_ @}*/
+
diff --git a/src/libipsec/ip_packet.c b/src/libipsec/ip_packet.c
new file mode 100644
index 000000000..096ca33a8
--- /dev/null
+++ b/src/libipsec/ip_packet.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2012 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 "ip_packet.h"
+
+#include <library.h>
+#include <debug.h>
+
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#ifdef HAVE_NETINET_IP6_H
+#include <netinet/ip6.h>
+#endif
+
+typedef struct private_ip_packet_t private_ip_packet_t;
+
+/**
+ * Private additions to ip_packet_t.
+ */
+struct private_ip_packet_t {
+
+ /**
+ * Public members
+ */
+ ip_packet_t public;
+
+ /**
+ * Source address
+ */
+ host_t *src;
+
+ /**
+ * Destination address
+ */
+ host_t *dst;
+
+ /**
+ * IP packet
+ */
+ chunk_t packet;
+
+ /**
+ * IP version
+ */
+ u_int8_t version;
+
+ /**
+ * Protocol|Next Header field
+ */
+ u_int8_t next_header;
+
+};
+
+METHOD(ip_packet_t, get_version, u_int8_t,
+ private_ip_packet_t *this)
+{
+ return this->version;
+}
+
+METHOD(ip_packet_t, get_source, host_t*,
+ private_ip_packet_t *this)
+{
+ return this->src;
+}
+
+METHOD(ip_packet_t, get_destination, host_t*,
+ private_ip_packet_t *this)
+{
+ return this->dst;
+}
+
+METHOD(ip_packet_t, get_encoding, chunk_t,
+ private_ip_packet_t *this)
+{
+ return this->packet;
+}
+
+METHOD(ip_packet_t, get_next_header, u_int8_t,
+ private_ip_packet_t *this)
+{
+ return this->next_header;
+}
+
+METHOD(ip_packet_t, clone, ip_packet_t*,
+ private_ip_packet_t *this)
+{
+ return ip_packet_create(this->packet);
+}
+
+METHOD(ip_packet_t, destroy, void,
+ private_ip_packet_t *this)
+{
+ this->src->destroy(this->src);
+ this->dst->destroy(this->dst);
+ chunk_free(&this->packet);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+ip_packet_t *ip_packet_create(chunk_t packet)
+{
+ private_ip_packet_t *this;
+ u_int8_t version, next_header;
+ host_t *src, *dst;
+
+ if (packet.len < 1)
+ {
+ DBG1(DBG_ESP, "IP packet too short");
+ goto failed;
+ }
+
+ version = (packet.ptr[0] & 0xf0) >> 4;
+
+ switch (version)
+ {
+ case 4:
+ {
+ struct ip *ip;
+
+ if (packet.len < sizeof(struct ip))
+ {
+ DBG1(DBG_ESP, "IPv4 packet too short");
+ goto failed;
+ }
+ ip = (struct ip*)packet.ptr;
+ src = host_create_from_chunk(AF_INET,
+ chunk_from_thing(ip->ip_src), 0);
+ dst = host_create_from_chunk(AF_INET,
+ chunk_from_thing(ip->ip_dst), 0);
+ next_header = ip->ip_p;
+ break;
+ }
+#ifdef HAVE_NETINET_IP6_H
+ case 6:
+ {
+ struct ip6_hdr *ip;
+
+ if (packet.len < sizeof(struct ip6_hdr))
+ {
+ DBG1(DBG_ESP, "IPv6 packet too short");
+ goto failed;
+ }
+ ip = (struct ip6_hdr*)packet.ptr;
+ src = host_create_from_chunk(AF_INET6,
+ chunk_from_thing(ip->ip6_src), 0);
+ dst = host_create_from_chunk(AF_INET6,
+ chunk_from_thing(ip->ip6_dst), 0);
+ next_header = ip->ip6_nxt;
+ break;
+ }
+#endif /* HAVE_NETINET_IP6_H */
+ default:
+ DBG1(DBG_ESP, "unsupported IP version");
+ goto failed;
+ }
+
+ INIT(this,
+ .public = {
+ .get_version = _get_version,
+ .get_source = _get_source,
+ .get_destination = _get_destination,
+ .get_next_header = _get_next_header,
+ .get_encoding = _get_encoding,
+ .clone = _clone,
+ .destroy = _destroy,
+ },
+ .src = src,
+ .dst = dst,
+ .packet = packet,
+ .version = version,
+ .next_header = next_header,
+ );
+ return &this->public;
+
+failed:
+ chunk_free(&packet);
+ return NULL;
+}
diff --git a/src/libipsec/ip_packet.h b/src/libipsec/ip_packet.h
new file mode 100644
index 000000000..b4fc298ff
--- /dev/null
+++ b/src/libipsec/ip_packet.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup ip_packet ip_packet
+ * @{ @ingroup libipsec
+ */
+
+#ifndef IP_PACKET_H_
+#define IP_PACKET_H_
+
+#include <library.h>
+#include <utils/host.h>
+#include <utils/packet.h>
+
+typedef struct ip_packet_t ip_packet_t;
+
+/**
+ * IP packet
+ */
+struct ip_packet_t {
+
+ /**
+ * IP version of this packet
+ *
+ * @return ip version
+ */
+ u_int8_t (*get_version)(ip_packet_t *this);
+
+ /**
+ * Get the source address of this packet
+ *
+ * @return source host
+ */
+ host_t *(*get_source)(ip_packet_t *this);
+
+ /**
+ * Get the destination address of this packet
+ *
+ * @return destination host
+ */
+ host_t *(*get_destination)(ip_packet_t *this);
+
+ /**
+ * Get the protocol (IPv4) or next header (IPv6) field of this packet.
+ *
+ * @return protocol|next header field
+ */
+ u_int8_t (*get_next_header)(ip_packet_t *this);
+
+ /**
+ * Get the complete IP packet (including the header)
+ *
+ * @return IP packet (internal data)
+ */
+ chunk_t (*get_encoding)(ip_packet_t *this);
+
+ /**
+ * Clone the IP packet
+ *
+ * @return clone of the packet
+ */
+ ip_packet_t *(*clone)(ip_packet_t *this);
+
+ /**
+ * Destroy an ip_packet_t
+ */
+ void (*destroy)(ip_packet_t *this);
+
+};
+
+/**
+ * Create an IP packet out of data from the wire (or decapsulated from another
+ * packet).
+ *
+ * @note The raw IP packet gets either owned by the new object, or destroyed,
+ * if the data is invalid.
+ *
+ * @param packet the IP packet (including header), gets owned
+ * @return ip_packet_t instance, or NULL if invalid
+ */
+ip_packet_t *ip_packet_create(chunk_t packet);
+
+#endif /** IP_PACKET_H_ @}*/
diff --git a/src/libipsec/ipsec.c b/src/libipsec/ipsec.c
new file mode 100644
index 000000000..50d9163ea
--- /dev/null
+++ b/src/libipsec/ipsec.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2012 Giuliano Grassi
+ * Copyright (C) 2012 Ralf Sager
+ * Copyright (C) 2012 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 "ipsec.h"
+
+#include <debug.h>
+
+typedef struct private_ipsec_t private_ipsec_t;
+
+/**
+ * Private additions to ipsec_t.
+ */
+struct private_ipsec_t {
+
+ /**
+ * Public members of ipsec_t.
+ */
+ ipsec_t public;
+};
+
+/**
+ * Single instance of ipsec_t.
+ */
+ipsec_t *ipsec;
+
+/**
+ * Described in header.
+ */
+void libipsec_deinit()
+{
+ private_ipsec_t *this = (private_ipsec_t*)ipsec;
+ DESTROY_IF(this->public.processor);
+ DESTROY_IF(this->public.events);
+ DESTROY_IF(this->public.policies);
+ DESTROY_IF(this->public.sas);
+ free(this);
+ ipsec = NULL;
+}
+
+/**
+ * Described in header.
+ */
+bool libipsec_init()
+{
+ private_ipsec_t *this;
+
+ INIT(this);
+ ipsec = &this->public;
+
+ if (lib->integrity &&
+ !lib->integrity->check(lib->integrity, "libipsec", libipsec_init))
+ {
+ DBG1(DBG_LIB, "integrity check of libipsec failed");
+ return FALSE;
+ }
+
+ this->public.sas = ipsec_sa_mgr_create();
+ this->public.policies = ipsec_policy_mgr_create();
+ this->public.events = ipsec_event_relay_create();
+ this->public.processor = ipsec_processor_create();
+ return TRUE;
+}
+
diff --git a/src/libipsec/ipsec.h b/src/libipsec/ipsec.h
new file mode 100644
index 000000000..7ee49432a
--- /dev/null
+++ b/src/libipsec/ipsec.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2012 Giuliano Grassi
+ * Copyright (C) 2012 Ralf Sager
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup libipsec libipsec
+ *
+ * @addtogroup libipsec
+ * @{
+ */
+
+#ifndef IPSEC_H_
+#define IPSEC_H_
+
+#include "ipsec_sa_mgr.h"
+#include "ipsec_policy_mgr.h"
+#include "ipsec_event_relay.h"
+#include "ipsec_processor.h"
+
+#include <library.h>
+
+typedef struct ipsec_t ipsec_t;
+
+/**
+ * User space IPsec implementation.
+ */
+struct ipsec_t {
+
+ /**
+ * IPsec SA manager instance
+ */
+ ipsec_sa_mgr_t *sas;
+
+ /**
+ * IPsec policy manager instance
+ */
+ ipsec_policy_mgr_t *policies;
+
+ /**
+ * Event relay instance
+ */
+ ipsec_event_relay_t *events;
+
+ /**
+ * IPsec processor instance
+ */
+ ipsec_processor_t *processor;
+
+};
+
+/**
+ * The single instance of ipsec_t.
+ *
+ * Set between calls to libipsec_init() and libipsec_deinit() calls.
+ */
+extern ipsec_t *ipsec;
+
+/**
+ * Initialize libipsec.
+ *
+ * @return FALSE if integrity check failed
+ */
+bool libipsec_init();
+
+/**
+ * Deinitialize libipsec.
+ */
+void libipsec_deinit();
+
+#endif /** IPSEC_H_ @}*/
diff --git a/src/libipsec/ipsec_event_listener.h b/src/libipsec/ipsec_event_listener.h
new file mode 100644
index 000000000..c5c39b0f1
--- /dev/null
+++ b/src/libipsec/ipsec_event_listener.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup ipsec_event_listener ipsec_event_listener
+ * @{ @ingroup libipsec
+ */
+
+#ifndef IPSEC_EVENT_LISTENER_H_
+#define IPSEC_EVENT_LISTENER_H_
+
+typedef struct ipsec_event_listener_t ipsec_event_listener_t;
+
+#include <library.h>
+
+/**
+ * Listener interface for IPsec events
+ *
+ * All methods are optional.
+ */
+struct ipsec_event_listener_t {
+
+ /**
+ * Called when the lifetime of an IPsec SA expired
+ *
+ * @param reqid reqid of the expired SA
+ * @param protocol protocol of the expired SA
+ * @param spi spi of the expired SA
+ * @param hard TRUE if this is a hard expire, FALSE otherwise
+ */
+ void (*expire)(u_int32_t reqid, u_int8_t protocol, u_int32_t spi,
+ bool hard);
+
+};
+
+#endif /** IPSEC_EVENT_LISTENER_H_ @}*/
diff --git a/src/libipsec/ipsec_event_relay.c b/src/libipsec/ipsec_event_relay.c
new file mode 100644
index 000000000..34222258c
--- /dev/null
+++ b/src/libipsec/ipsec_event_relay.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012 Giuliano Grassi
+ * Copyright (C) 2012 Ralf Sager
+ * 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 "ipsec_event_relay.h"
+
+#include <library.h>
+#include <debug.h>
+#include <threading/rwlock.h>
+#include <utils/linked_list.h>
+#include <utils/blocking_queue.h>
+#include <processing/jobs/callback_job.h>
+
+typedef struct private_ipsec_event_relay_t private_ipsec_event_relay_t;
+
+/**
+ * Private additions to ipsec_event_relay_t.
+ */
+struct private_ipsec_event_relay_t {
+
+ /**
+ * Public members
+ */
+ ipsec_event_relay_t public;
+
+ /**
+ * Registered listeners
+ */
+ linked_list_t *listeners;
+
+ /**
+ * Lock to safely access the list of listeners
+ */
+ rwlock_t *lock;
+
+ /**
+ * Blocking queue for events
+ */
+ blocking_queue_t *queue;
+};
+
+/**
+ * Helper struct used to manage events in a queue
+ */
+typedef struct {
+
+ /**
+ * Type of the event
+ */
+ enum {
+ IPSEC_EVENT_EXPIRE,
+ } type;
+
+ /**
+ * Reqid of the SA, if any
+ */
+ u_int32_t reqid;
+
+ /**
+ * SPI of the SA, if any
+ */
+ u_int32_t spi;
+
+ /**
+ * Additional data for specific event types
+ */
+ union {
+
+ struct {
+ /** Protocol of the SA */
+ u_int8_t protocol;
+ /** TRUE in case of a hard expire */
+ bool hard;
+ } expire;
+
+ } data;
+
+} ipsec_event_t;
+
+/**
+ * Dequeue events and relay them to listeners
+ */
+static job_requeue_t handle_events(private_ipsec_event_relay_t *this)
+{
+ enumerator_t *enumerator;
+ ipsec_event_listener_t *current;
+ ipsec_event_t *event;
+
+ event = this->queue->dequeue(this->queue);
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->listeners->create_enumerator(this->listeners);
+ while (enumerator->enumerate(enumerator, (void**)&current))
+ {
+ switch (event->type)
+ {
+ case IPSEC_EVENT_EXPIRE:
+ if (current->expire)
+ {
+ current->expire(event->reqid, event->data.expire.protocol,
+ event->spi, event->data.expire.hard);
+ }
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+ return JOB_REQUEUE_DIRECT;
+}
+
+METHOD(ipsec_event_relay_t, expire, void,
+ private_ipsec_event_relay_t *this, u_int32_t reqid, u_int8_t protocol,
+ u_int32_t spi, bool hard)
+{
+ ipsec_event_t *event;
+
+ INIT(event,
+ .type = IPSEC_EVENT_EXPIRE,
+ .reqid = reqid,
+ .spi = spi,
+ .data = {
+ .expire = {
+ .protocol = protocol,
+ .hard = hard,
+ },
+ },
+ );
+ this->queue->enqueue(this->queue, event);
+}
+
+METHOD(ipsec_event_relay_t, register_listener, void,
+ private_ipsec_event_relay_t *this, ipsec_event_listener_t *listener)
+{
+ this->lock->write_lock(this->lock);
+ this->listeners->insert_last(this->listeners, listener);
+ this->lock->unlock(this->lock);
+}
+
+METHOD(ipsec_event_relay_t, unregister_listener, void,
+ private_ipsec_event_relay_t *this, ipsec_event_listener_t *listener)
+{
+ this->lock->write_lock(this->lock);
+ this->listeners->remove(this->listeners, listener, NULL);
+ this->lock->unlock(this->lock);
+}
+
+METHOD(ipsec_event_relay_t, destroy, void,
+ private_ipsec_event_relay_t *this)
+{
+ this->queue->destroy_function(this->queue, free);
+ this->listeners->destroy(this->listeners);
+ this->lock->destroy(this->lock);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+ipsec_event_relay_t *ipsec_event_relay_create()
+{
+ private_ipsec_event_relay_t *this;
+
+ INIT(this,
+ .public = {
+ .expire = _expire,
+ .register_listener = _register_listener,
+ .unregister_listener = _unregister_listener,
+ .destroy = _destroy,
+ },
+ .listeners = linked_list_create(),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ .queue = blocking_queue_create(),
+ );
+
+ lib->processor->queue_job(lib->processor,
+ (job_t*)callback_job_create((callback_job_cb_t)handle_events, this,
+ NULL, (callback_job_cancel_t)return_false));
+
+ return &this->public;
+}
diff --git a/src/libipsec/ipsec_event_relay.h b/src/libipsec/ipsec_event_relay.h
new file mode 100644
index 000000000..c6935d546
--- /dev/null
+++ b/src/libipsec/ipsec_event_relay.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2012 Giuliano Grassi
+ * Copyright (C) 2012 Ralf Sager
+ * 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 ipsec_event_relay ipsec_event_relay
+ * @{ @ingroup libipsec
+ */
+
+#ifndef IPSEC_EVENT_RELAY_H_
+#define IPSEC_EVENT_RELAY_H_
+
+#include "ipsec_event_listener.h"
+
+#include <library.h>
+
+typedef struct ipsec_event_relay_t ipsec_event_relay_t;
+
+/**
+ * Event relay manager.
+ *
+ * Used to notify upper layers about changes
+ */
+struct ipsec_event_relay_t {
+
+ /**
+ * Raise an expire event.
+ *
+ * @param reqid reqid of the expired IPsec SA
+ * @param protocol protocol (e.g ESP) of the expired SA
+ * @param spi SPI of the expired SA
+ * @param hard TRUE for a hard expire, FALSE otherwise
+ */
+ void (*expire)(ipsec_event_relay_t *this, u_int32_t reqid,
+ u_int8_t protocol, u_int32_t spi, bool hard);
+
+ /**
+ * Register a listener to events raised by this manager
+ *
+ * @param listener the listener to register
+ */
+ void (*register_listener)(ipsec_event_relay_t *this,
+ ipsec_event_listener_t *listener);
+
+ /**
+ * Unregister a listener
+ *
+ * @param listener the listener to unregister
+ */
+ void (*unregister_listener)(ipsec_event_relay_t *this,
+ ipsec_event_listener_t *listener);
+
+ /**
+ * Destroy an ipsec_event_relay_t
+ */
+ void (*destroy)(ipsec_event_relay_t *this);
+
+};
+
+/**
+ * Create an ipsec_event_relay_t instance
+ *
+ * @return IPsec event relay instance
+ */
+ipsec_event_relay_t *ipsec_event_relay_create();
+
+#endif /** IPSEC_EVENT_RELAY_H_ @}*/
diff --git a/src/libipsec/ipsec_policy.c b/src/libipsec/ipsec_policy.c
new file mode 100644
index 000000000..af8ea9f9d
--- /dev/null
+++ b/src/libipsec/ipsec_policy.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012 Giuliano Grassi
+ * Copyright (C) 2012 Ralf Sager
+ * 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 "ipsec_policy.h"
+
+#include <debug.h>
+
+typedef struct private_ipsec_policy_t private_ipsec_policy_t;
+
+/**
+ * Private additions to ipsec_policy_t.
+ */
+struct private_ipsec_policy_t {
+
+ /**
+ * Public members
+ */
+ ipsec_policy_t public;
+
+ /**
+ * SA source address
+ */
+ host_t *src;
+
+ /**
+ * SA destination address
+ */
+ host_t *dst;
+
+ /**
+ * Source traffic selector
+ */
+ traffic_selector_t *src_ts;
+
+ /**
+ * Destination traffic selector
+ */
+ traffic_selector_t *dst_ts;
+
+ /**
+ * If any of the two TS has a protocol selector we cache it here
+ */
+ u_int8_t protocol;
+
+ /**
+ * Traffic direction
+ */
+ policy_dir_t direction;
+
+ /**
+ * Policy type
+ */
+ policy_type_t type;
+
+ /**
+ * SA configuration
+ */
+ ipsec_sa_cfg_t sa;
+
+ /**
+ * Mark
+ */
+ mark_t mark;
+
+ /**
+ * Policy priority
+ */
+ policy_priority_t priority;
+
+ /**
+ * Reference counter
+ */
+ refcount_t refcount;
+
+};
+
+METHOD(ipsec_policy_t, match, bool,
+ private_ipsec_policy_t *this, traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t reqid,
+ mark_t mark, policy_priority_t priority)
+{
+ return (this->direction == direction &&
+ this->priority == priority &&
+ this->sa.reqid == reqid &&
+ memeq(&this->mark, &mark, sizeof(mark_t)) &&
+ this->src_ts->equals(this->src_ts, src_ts) &&
+ this->dst_ts->equals(this->dst_ts, dst_ts));
+}
+
+METHOD(ipsec_policy_t, match_packet, bool,
+ private_ipsec_policy_t *this, ip_packet_t *packet)
+{
+ u_int8_t proto = packet->get_next_header(packet);
+ host_t *src = packet->get_source(packet),
+ *dst = packet->get_destination(packet);
+
+ return (!this->protocol || this->protocol == proto) &&
+ this->src_ts->includes(this->src_ts, src) &&
+ this->dst_ts->includes(this->dst_ts, dst);
+}
+
+METHOD(ipsec_policy_t, get_source_ts, traffic_selector_t*,
+ private_ipsec_policy_t *this)
+{
+ return this->src_ts;
+}
+
+METHOD(ipsec_policy_t, get_destination_ts, traffic_selector_t*,
+ private_ipsec_policy_t *this)
+{
+ return this->dst_ts;
+}
+
+METHOD(ipsec_policy_t, get_reqid, u_int32_t,
+ private_ipsec_policy_t *this)
+{
+ return this->sa.reqid;
+}
+
+METHOD(ipsec_policy_t, get_direction, policy_dir_t,
+ private_ipsec_policy_t *this)
+{
+ return this->direction;
+}
+
+METHOD(ipsec_policy_t, get_priority, policy_priority_t,
+ private_ipsec_policy_t *this)
+{
+ return this->priority;
+}
+
+METHOD(ipsec_policy_t, get_type, policy_type_t,
+ private_ipsec_policy_t *this)
+{
+ return this->type;
+}
+
+METHOD(ipsec_policy_t, get_ref, ipsec_policy_t*,
+ private_ipsec_policy_t *this)
+{
+ ref_get(&this->refcount);
+ return &this->public;
+}
+
+METHOD(ipsec_policy_t, destroy, void,
+ private_ipsec_policy_t *this)
+{
+ if (ref_put(&this->refcount))
+ {
+ this->src->destroy(this->src);
+ this->dst->destroy(this->dst);
+ this->src_ts->destroy(this->src_ts);
+ this->dst_ts->destroy(this->dst_ts);
+ free(this);
+ }
+}
+
+/**
+ * Described in header.
+ */
+ipsec_policy_t *ipsec_policy_create(host_t *src, host_t *dst,
+ traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts,
+ policy_dir_t direction, policy_type_t type,
+ ipsec_sa_cfg_t *sa, mark_t mark,
+ policy_priority_t priority)
+{
+ private_ipsec_policy_t *this;
+
+ INIT(this,
+ .public = {
+ .match = _match,
+ .match_packet = _match_packet,
+ .get_source_ts = _get_source_ts,
+ .get_destination_ts = _get_destination_ts,
+ .get_direction = _get_direction,
+ .get_priority = _get_priority,
+ .get_reqid = _get_reqid,
+ .get_type = _get_type,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .src = src->clone(src),
+ .dst = dst->clone(dst),
+ .src_ts = src_ts->clone(src_ts),
+ .dst_ts = dst_ts->clone(dst_ts),
+ .protocol = max(src_ts->get_protocol(src_ts),
+ dst_ts->get_protocol(dst_ts)),
+ .direction = direction,
+ .type = type,
+ .sa = *sa,
+ .mark = mark,
+ .priority = priority,
+ .refcount = 1,
+ );
+
+ return &this->public;
+}
diff --git a/src/libipsec/ipsec_policy.h b/src/libipsec/ipsec_policy.h
new file mode 100644
index 000000000..67ad0b0ed
--- /dev/null
+++ b/src/libipsec/ipsec_policy.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012 Giuliano Grassi
+ * Copyright (C) 2012 Ralf Sager
+ * 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 ipsec_policy ipsec_policy
+ * @{ @ingroup libipsec
+ */
+
+#ifndef IPSEC_POLICY_H
+#define IPSEC_POLICY_H
+
+#include "ip_packet.h"
+
+#include <library.h>
+#include <utils/host.h>
+#include <ipsec/ipsec_types.h>
+#include <selectors/traffic_selector.h>
+
+typedef struct ipsec_policy_t ipsec_policy_t;
+
+/**
+ * IPsec Policy
+ */
+struct ipsec_policy_t {
+
+ /**
+ * Get the source traffic selector of this policy
+ *
+ * @return the source traffic selector
+ */
+ traffic_selector_t *(*get_source_ts)(ipsec_policy_t *this);
+
+ /**
+ * Get the destination traffic selector of this policy
+ *
+ * @return the destination traffic selector
+ */
+ traffic_selector_t *(*get_destination_ts)(ipsec_policy_t *this);
+
+ /**
+ * Get the direction of this policy
+ *
+ * @return direction
+ */
+ policy_dir_t (*get_direction)(ipsec_policy_t *this);
+
+ /**
+ * Get the priority of this policy
+ *
+ * @return priority
+ */
+ policy_priority_t (*get_priority)(ipsec_policy_t *this);
+
+ /**
+ * Get the type of this policy (e.g. IPsec)
+ *
+ * @return the policy type
+ */
+ policy_type_t (*get_type)(ipsec_policy_t *this);
+
+ /**
+ * Get the reqid associated to this policy
+ *
+ * @return the reqid
+ */
+ u_int32_t (*get_reqid)(ipsec_policy_t *this);
+
+ /**
+ * Get another reference to this policy
+ *
+ * @return additional reference to the policy
+ */
+ ipsec_policy_t *(*get_ref)(ipsec_policy_t *this);
+
+ /**
+ * Check if this policy matches all given parameters
+ *
+ * @param src_ts source traffic selector
+ * @param dst_ts destination traffic selector
+ * @param direction traffic direction
+ * @param reqid reqid of the policy
+ * @param mark mark for this policy
+ * @param prioirty policy priority
+ * @return TRUE if policy matches all parameters
+ */
+ bool (*match)(ipsec_policy_t *this, traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts, policy_dir_t direction,
+ u_int32_t reqid, mark_t mark, policy_priority_t priority);
+
+ /**
+ * Check if this policy matches the given IP packet
+ *
+ * @param packet IP packet
+ * @return TRUE if policy matches the packet
+ */
+ bool (*match_packet)(ipsec_policy_t *this, ip_packet_t *packet);
+
+ /**
+ * Destroy an ipsec_policy_t
+ */
+ void (*destroy)(ipsec_policy_t *this);
+
+};
+
+/**
+ * Create an ipsec_policy_t instance
+ *
+ * @param src source address of SA
+ * @param dst dest address of SA
+ * @param src_ts traffic selector to match traffic source
+ * @param dst_ts traffic selector to match traffic dest
+ * @param direction direction of traffic, POLICY_(IN|OUT|FWD)
+ * @param type type of policy, POLICY_(IPSEC|PASS|DROP)
+ * @param sa details about the SA(s) tied to this policy
+ * @param mark mark for this policy
+ * @param priority priority of this policy
+ * @return ipsec policy instance
+ */
+ipsec_policy_t *ipsec_policy_create(host_t *src, host_t *dst,
+ traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts,
+ policy_dir_t direction, policy_type_t type,
+ ipsec_sa_cfg_t *sa, mark_t mark,
+ policy_priority_t priority);
+
+#endif /** IPSEC_POLICY_H @}*/
diff --git a/src/libipsec/ipsec_policy_mgr.c b/src/libipsec/ipsec_policy_mgr.c
new file mode 100644
index 000000000..41ba792c3
--- /dev/null
+++ b/src/libipsec/ipsec_policy_mgr.c
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012 Giuliano Grassi
+ * Copyright (C) 2012 Ralf Sager
+ * 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 "ipsec_policy_mgr.h"
+
+#include <debug.h>
+#include <threading/rwlock.h>
+#include <utils/linked_list.h>
+
+/** Base priority for installed policies */
+#define PRIO_BASE 512
+
+typedef struct private_ipsec_policy_mgr_t private_ipsec_policy_mgr_t;
+
+/**
+ * Private additions to ipsec_policy_mgr_t.
+ */
+struct private_ipsec_policy_mgr_t {
+
+ /**
+ * Public members of ipsec_policy_mgr_t.
+ */
+ ipsec_policy_mgr_t public;
+
+ /**
+ * Installed policies (ipsec_policy_entry_t*)
+ */
+ linked_list_t *policies;
+
+ /**
+ * Lock to safely access the list of policies
+ */
+ rwlock_t *lock;
+
+};
+
+/**
+ * Helper struct to store policies in a list sorted by the same pseudo-priority
+ * used by the NETLINK kernel interface.
+ */
+typedef struct {
+
+ /**
+ * Priority used to sort policies
+ */
+ u_int32_t priority;
+
+ /**
+ * The policy
+ */
+ ipsec_policy_t *policy;
+
+} ipsec_policy_entry_t;
+
+/**
+ * Calculate the pseudo-priority to sort policies. This is the same algorithm
+ * used by the NETLINK kernel interface (i.e. high priority -> low value).
+ */
+static u_int32_t calculate_priority(policy_priority_t policy_priority,
+ traffic_selector_t *src,
+ traffic_selector_t *dst)
+{
+ u_int32_t priority = PRIO_BASE;
+ u_int16_t port;
+ u_int8_t mask, proto;
+ host_t *net;
+
+ switch (policy_priority)
+ {
+ case POLICY_PRIORITY_FALLBACK:
+ priority <<= 1;
+ /* fall-through */
+ case POLICY_PRIORITY_ROUTED:
+ priority <<= 1;
+ /* fall-through */
+ case POLICY_PRIORITY_DEFAULT:
+ break;
+ }
+ /* calculate priority based on selector size, small size = high prio */
+ src->to_subnet(src, &net, &mask);
+ priority -= mask;
+ proto = src->get_protocol(src);
+ port = net->get_port(net);
+ net->destroy(net);
+
+ dst->to_subnet(dst, &net, &mask);
+ priority -= mask;
+ proto = max(proto, dst->get_protocol(dst));
+ port = max(port, net->get_port(net));
+ net->destroy(net);
+
+ priority <<= 2; /* make some room for the two flags */
+ priority += port ? 0 : 2;
+ priority += proto ? 0 : 1;
+ return priority;
+}
+
+/**
+ * Create a policy entry
+ */
+static ipsec_policy_entry_t *policy_entry_create(ipsec_policy_t *policy)
+{
+ ipsec_policy_entry_t *this;
+
+ INIT(this,
+ .policy = policy,
+ .priority = calculate_priority(policy->get_priority(policy),
+ policy->get_source_ts(policy),
+ policy->get_destination_ts(policy)),
+ );
+ return this;
+}
+
+/**
+ * Destroy a policy entry
+ */
+static void policy_entry_destroy(ipsec_policy_entry_t *this)
+{
+ this->policy->destroy(this->policy);
+ free(this);
+}
+
+METHOD(ipsec_policy_mgr_t, add_policy, status_t,
+ private_ipsec_policy_mgr_t *this, host_t *src, host_t *dst,
+ traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
+ policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa, mark_t mark,
+ policy_priority_t priority)
+{
+ enumerator_t *enumerator;
+ ipsec_policy_entry_t *entry, *current;
+ ipsec_policy_t *policy;
+
+ if (type != POLICY_IPSEC || direction == POLICY_FWD)
+ { /* we ignore these policies as we currently have no use for them */
+ return SUCCESS;
+ }
+
+ DBG2(DBG_ESP, "adding policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+
+ policy = ipsec_policy_create(src, dst, src_ts, dst_ts, direction, type, sa,
+ mark, priority);
+ entry = policy_entry_create(policy);
+
+ this->lock->write_lock(this->lock);
+ enumerator = this->policies->create_enumerator(this->policies);
+ while (enumerator->enumerate(enumerator, (void**)&current))
+ {
+ if (current->priority >= entry->priority)
+ {
+ break;
+ }
+ }
+ this->policies->insert_before(this->policies, enumerator, entry);
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+ return SUCCESS;
+}
+
+METHOD(ipsec_policy_mgr_t, del_policy, status_t,
+ private_ipsec_policy_mgr_t *this, traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t reqid,
+ mark_t mark, policy_priority_t policy_priority)
+{
+ enumerator_t *enumerator;
+ ipsec_policy_entry_t *current, *found = NULL;
+ u_int32_t priority;
+
+ if (direction == POLICY_FWD)
+ { /* we ignore these policies as we currently have no use for them */
+ return SUCCESS;
+ }
+ DBG2(DBG_ESP, "deleting policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+
+ priority = calculate_priority(policy_priority, src_ts, dst_ts);
+
+ this->lock->write_lock(this->lock);
+ enumerator = this->policies->create_enumerator(this->policies);
+ while (enumerator->enumerate(enumerator, (void**)&current))
+ {
+ if (current->priority == priority &&
+ current->policy->match(current->policy, src_ts, dst_ts, direction,
+ reqid, mark, policy_priority))
+ {
+ this->policies->remove_at(this->policies, enumerator);
+ found = current;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+ if (found)
+ {
+ policy_entry_destroy(found);
+ return SUCCESS;
+ }
+ return FAILED;
+}
+
+METHOD(ipsec_policy_mgr_t, flush_policies, status_t,
+ private_ipsec_policy_mgr_t *this)
+{
+ ipsec_policy_entry_t *entry;
+
+ DBG2(DBG_ESP, "flushing policies");
+
+ this->lock->write_lock(this->lock);
+ while (this->policies->remove_last(this->policies,
+ (void**)&entry) == SUCCESS)
+ {
+ policy_entry_destroy(entry);
+ }
+ this->lock->unlock(this->lock);
+ return SUCCESS;
+}
+
+METHOD(ipsec_policy_mgr_t, find_by_packet, ipsec_policy_t*,
+ private_ipsec_policy_mgr_t *this, ip_packet_t *packet, bool inbound)
+{
+ enumerator_t *enumerator;
+ ipsec_policy_entry_t *current;
+ ipsec_policy_t *found = NULL;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->policies->create_enumerator(this->policies);
+ while (enumerator->enumerate(enumerator, (void**)&current))
+ {
+ ipsec_policy_t *policy = current->policy;
+
+ if ((inbound == (policy->get_direction(policy) == POLICY_IN)) &&
+ policy->match_packet(policy, packet))
+ {
+ found = policy->get_ref(policy);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+ return found;
+}
+
+METHOD(ipsec_policy_mgr_t, destroy, void,
+ private_ipsec_policy_mgr_t *this)
+{
+ flush_policies(this);
+ this->policies->destroy(this->policies);
+ this->lock->destroy(this->lock);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+ipsec_policy_mgr_t *ipsec_policy_mgr_create()
+{
+ private_ipsec_policy_mgr_t *this;
+
+ INIT(this,
+ .public = {
+ .add_policy = _add_policy,
+ .del_policy = _del_policy,
+ .flush_policies = _flush_policies,
+ .find_by_packet = _find_by_packet,
+ .destroy = _destroy,
+ },
+ .policies = linked_list_create(),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ );
+
+ return &this->public;
+}
diff --git a/src/libipsec/ipsec_policy_mgr.h b/src/libipsec/ipsec_policy_mgr.h
new file mode 100644
index 000000000..d3ee1074f
--- /dev/null
+++ b/src/libipsec/ipsec_policy_mgr.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012 Giuliano Grassi
+ * Copyright (C) 2012 Ralf Sager
+ * 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 ipsec_policy_mgr ipsec_policy_mgr
+ * @{ @ingroup libipsec
+ */
+
+#ifndef IPSEC_POLICY_MGR_H_
+#define IPSEC_POLICY_MGR_H_
+
+#include "ipsec_policy.h"
+#include "ip_packet.h"
+
+#include <library.h>
+#include <utils/host.h>
+#include <utils/linked_list.h>
+#include <ipsec/ipsec_types.h>
+#include <selectors/traffic_selector.h>
+
+typedef struct ipsec_policy_mgr_t ipsec_policy_mgr_t;
+
+/**
+ * IPsec policy manager
+ *
+ * The first methods are modeled after those in kernel_ipsec_t.
+ *
+ * @note Only policies of type POLICY_IPSEC are currently used, also policies
+ * with direction POLICY_FWD are ignored. Any packets that do not match an
+ * installed policy will be dropped.
+ */
+struct ipsec_policy_mgr_t {
+
+ /**
+ * Add a policy
+ *
+ * A policy is always associated to an SA. Traffic which matches a
+ * policy is handled by the SA with the same reqid.
+ *
+ * @param src source address of SA
+ * @param dst dest address of SA
+ * @param src_ts traffic selector to match traffic source
+ * @param dst_ts traffic selector to match traffic dest
+ * @param direction direction of traffic, POLICY_(IN|OUT|FWD)
+ * @param type type of policy, POLICY_(IPSEC|PASS|DROP)
+ * @param sa details about the SA(s) tied to this policy
+ * @param mark mark for this policy
+ * @param priority priority of this policy
+ * @return SUCCESS if operation completed
+ */
+ status_t (*add_policy)(ipsec_policy_mgr_t *this,
+ host_t *src, host_t *dst, traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts, policy_dir_t direction,
+ policy_type_t type, ipsec_sa_cfg_t *sa, mark_t mark,
+ policy_priority_t priority);
+
+ /**
+ * Remove a policy
+ *
+ * @param src_ts traffic selector to match traffic source
+ * @param dst_ts traffic selector to match traffic dest
+ * @param direction direction of traffic, POLICY_(IN|OUT|FWD)
+ * @param reqid unique ID of the associated SA
+ * @param mark optional mark
+ * @param priority priority of the policy
+ * @return SUCCESS if operation completed
+ */
+ status_t (*del_policy)(ipsec_policy_mgr_t *this,
+ traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts,
+ policy_dir_t direction, u_int32_t reqid, mark_t mark,
+ policy_priority_t priority);
+
+ /**
+ * Flush all policies
+ *
+ * @return SUCCESS if operation completed
+ */
+ status_t (*flush_policies)(ipsec_policy_mgr_t *this);
+
+ /**
+ * Find the policy that matches the given IP packet best
+ *
+ * @param packet IP packet to match
+ * @param inbound TRUE for an inbound packet
+ * @return reference to the policy, or NULL if none found
+ */
+ ipsec_policy_t *(*find_by_packet)(ipsec_policy_mgr_t *this,
+ ip_packet_t *packet, bool inbound);
+
+ /**
+ * Destroy an ipsec_policy_mgr_t
+ */
+ void (*destroy)(ipsec_policy_mgr_t *this);
+
+};
+
+/**
+ * Create an ipsec_policy_mgr instance
+ *
+ * @return ipsec_policy_mgr
+ */
+ipsec_policy_mgr_t *ipsec_policy_mgr_create();
+
+#endif /** IPSEC_POLICY_MGR_H_ @}*/
diff --git a/src/libipsec/ipsec_processor.c b/src/libipsec/ipsec_processor.c
new file mode 100644
index 000000000..a91d9e074
--- /dev/null
+++ b/src/libipsec/ipsec_processor.c
@@ -0,0 +1,324 @@
+/*
+ * Copyright (C) 2012 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 "ipsec.h"
+#include "ipsec_processor.h"
+
+#include <debug.h>
+#include <library.h>
+#include <threading/rwlock.h>
+#include <utils/blocking_queue.h>
+#include <processing/jobs/callback_job.h>
+
+typedef struct private_ipsec_processor_t private_ipsec_processor_t;
+
+/**
+ * Private additions to ipsec_processor_t.
+ */
+struct private_ipsec_processor_t {
+
+ /**
+ * Public members
+ */
+ ipsec_processor_t public;
+
+ /**
+ * Queue for inbound packets (esp_packet_t*)
+ */
+ blocking_queue_t *inbound_queue;
+
+ /**
+ * Queue for outbound packets (ip_packet_t*)
+ */
+ blocking_queue_t *outbound_queue;
+
+ /**
+ * Registered inbound callback
+ */
+ struct {
+ ipsec_inbound_cb_t cb;
+ void *data;
+ } inbound;
+
+ /**
+ * Registered outbound callback
+ */
+ struct {
+ ipsec_outbound_cb_t cb;
+ void *data;
+ } outbound;
+
+ /**
+ * Lock used to synchronize access to the callbacks
+ */
+ rwlock_t *lock;
+};
+
+/**
+ * Deliver an inbound IP packet to the registered listener
+ */
+static void deliver_inbound(private_ipsec_processor_t *this,
+ esp_packet_t *packet)
+{
+ this->lock->read_lock(this->lock);
+ if (this->inbound.cb)
+ {
+ this->inbound.cb(this->inbound.data, packet->extract_payload(packet));
+ }
+ else
+ {
+ DBG2(DBG_ESP, "no inbound callback registered, dropping packet");
+ }
+ packet->destroy(packet);
+ this->lock->unlock(this->lock);
+}
+
+/**
+ * Processes inbound packets
+ */
+static job_requeue_t process_inbound(private_ipsec_processor_t *this)
+{
+ esp_packet_t *packet;
+ ipsec_sa_t *sa;
+ u_int8_t next_header;
+ u_int32_t spi;
+
+ packet = (esp_packet_t*)this->inbound_queue->dequeue(this->inbound_queue);
+
+ if (!packet->parse_header(packet, &spi))
+ {
+ packet->destroy(packet);
+ return JOB_REQUEUE_DIRECT;
+ }
+
+ sa = ipsec->sas->checkout_by_spi(ipsec->sas, spi,
+ packet->get_destination(packet));
+ if (!sa)
+ {
+ DBG2(DBG_ESP, "inbound ESP packet does not belong to an installed SA");
+ packet->destroy(packet);
+ return JOB_REQUEUE_DIRECT;
+ }
+
+ if (!sa->is_inbound(sa))
+ {
+ DBG1(DBG_ESP, "error: IPsec SA is not inbound");
+ packet->destroy(packet);
+ ipsec->sas->checkin(ipsec->sas, sa);
+ return JOB_REQUEUE_DIRECT;
+ }
+
+ if (packet->decrypt(packet, sa->get_esp_context(sa)) != SUCCESS)
+ {
+ ipsec->sas->checkin(ipsec->sas, sa);
+ packet->destroy(packet);
+ return JOB_REQUEUE_DIRECT;
+ }
+ ipsec->sas->checkin(ipsec->sas, sa);
+
+ next_header = packet->get_next_header(packet);
+ switch (next_header)
+ {
+ case IPPROTO_IPIP:
+ case IPPROTO_IPV6:
+ {
+ ipsec_policy_t *policy;
+ ip_packet_t *ip_packet;
+
+ ip_packet = packet->get_payload(packet);
+ policy = ipsec->policies->find_by_packet(ipsec->policies,
+ ip_packet, TRUE);
+ if (policy)
+ { /* TODO-IPSEC: update policy/sa stats? */
+ deliver_inbound(this, packet);
+ policy->destroy(policy);
+ break;
+ }
+ DBG1(DBG_ESP, "discarding inbound IP packet due to policy");
+ /* no matching policy found, fall-through */
+ }
+ case IPPROTO_NONE:
+ /* discard dummy packets */
+ /* fall-through */
+ default:
+ packet->destroy(packet);
+ break;
+ }
+ return JOB_REQUEUE_DIRECT;
+}
+
+/**
+ * Send an ESP packet using the registered outbound callback
+ */
+static void send_outbound(private_ipsec_processor_t *this,
+ esp_packet_t *packet)
+{
+ this->lock->read_lock(this->lock);
+ if (this->outbound.cb)
+ {
+ this->outbound.cb(this->outbound.data, packet);
+ }
+ else
+ {
+ DBG2(DBG_ESP, "no outbound callback registered, dropping packet");
+ packet->destroy(packet);
+ }
+ this->lock->unlock(this->lock);
+}
+
+/**
+ * Processes outbound packets
+ */
+static job_requeue_t process_outbound(private_ipsec_processor_t *this)
+{
+ ipsec_policy_t *policy;
+ esp_packet_t *esp_packet;
+ ip_packet_t *packet;
+ ipsec_sa_t *sa;
+ host_t *src, *dst;
+
+ packet = (ip_packet_t*)this->outbound_queue->dequeue(this->outbound_queue);
+
+ policy = ipsec->policies->find_by_packet(ipsec->policies, packet, FALSE);
+ if (!policy)
+ {
+ DBG1(DBG_ESP, "no matching outbound IPsec policy for %H == %H",
+ packet->get_source(packet), packet->get_destination(packet));
+ packet->destroy(packet);
+ return JOB_REQUEUE_DIRECT;
+ }
+
+ sa = ipsec->sas->checkout_by_reqid(ipsec->sas, policy->get_reqid(policy),
+ FALSE);
+ if (!sa)
+ { /* TODO-IPSEC: send an acquire to uppper layer */
+ DBG1(DBG_ESP, "could not find an outbound IPsec SA for reqid {%u}, "
+ "dropping packet", policy->get_reqid(policy));
+ packet->destroy(packet);
+ policy->destroy(policy);
+ return JOB_REQUEUE_DIRECT;
+ }
+ src = sa->get_source(sa);
+ dst = sa->get_destination(sa);
+ esp_packet = esp_packet_create_from_payload(src->clone(src),
+ dst->clone(dst), packet);
+ if (esp_packet->encrypt(esp_packet, sa->get_esp_context(sa),
+ sa->get_spi(sa)) != SUCCESS)
+ {
+ ipsec->sas->checkin(ipsec->sas, sa);
+ esp_packet->destroy(esp_packet);
+ policy->destroy(policy);
+ return JOB_REQUEUE_DIRECT;
+ }
+ /* TODO-IPSEC: update policy/sa counters? */
+ ipsec->sas->checkin(ipsec->sas, sa);
+ policy->destroy(policy);
+ send_outbound(this, esp_packet);
+ return JOB_REQUEUE_DIRECT;
+}
+
+METHOD(ipsec_processor_t, queue_inbound, void,
+ private_ipsec_processor_t *this, esp_packet_t *packet)
+{
+ this->inbound_queue->enqueue(this->inbound_queue, packet);
+}
+
+METHOD(ipsec_processor_t, queue_outbound, void,
+ private_ipsec_processor_t *this, ip_packet_t *packet)
+{
+ this->outbound_queue->enqueue(this->outbound_queue, packet);
+}
+
+METHOD(ipsec_processor_t, register_inbound, void,
+ private_ipsec_processor_t *this, ipsec_inbound_cb_t cb, void *data)
+{
+ this->lock->write_lock(this->lock);
+ this->inbound.cb = cb;
+ this->inbound.data = data;
+ this->lock->unlock(this->lock);
+}
+
+METHOD(ipsec_processor_t, unregister_inbound, void,
+ private_ipsec_processor_t *this, ipsec_inbound_cb_t cb)
+{
+ this->lock->write_lock(this->lock);
+ if (this->inbound.cb == cb)
+ {
+ this->inbound.cb = NULL;
+ }
+ this->lock->unlock(this->lock);
+}
+
+METHOD(ipsec_processor_t, register_outbound, void,
+ private_ipsec_processor_t *this, ipsec_outbound_cb_t cb, void *data)
+{
+ this->lock->write_lock(this->lock);
+ this->outbound.cb = cb;
+ this->outbound.data = data;
+ this->lock->unlock(this->lock);
+}
+
+METHOD(ipsec_processor_t, unregister_outbound, void,
+ private_ipsec_processor_t *this, ipsec_outbound_cb_t cb)
+{
+ this->lock->write_lock(this->lock);
+ if (this->outbound.cb == cb)
+ {
+ this->outbound.cb = NULL;
+ }
+ this->lock->unlock(this->lock);
+}
+
+METHOD(ipsec_processor_t, destroy, void,
+ private_ipsec_processor_t *this)
+{
+ this->inbound_queue->destroy_offset(this->inbound_queue,
+ offsetof(esp_packet_t, destroy));
+ this->outbound_queue->destroy_offset(this->outbound_queue,
+ offsetof(ip_packet_t, destroy));
+ this->lock->destroy(this->lock);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+ipsec_processor_t *ipsec_processor_create()
+{
+ private_ipsec_processor_t *this;
+
+ INIT(this,
+ .public = {
+ .queue_inbound = _queue_inbound,
+ .queue_outbound = _queue_outbound,
+ .register_inbound = _register_inbound,
+ .unregister_inbound = _unregister_inbound,
+ .register_outbound = _register_outbound,
+ .unregister_outbound = _unregister_outbound,
+ .destroy = _destroy,
+ },
+ .inbound_queue = blocking_queue_create(),
+ .outbound_queue = blocking_queue_create(),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ );
+
+ lib->processor->queue_job(lib->processor,
+ (job_t*)callback_job_create((callback_job_cb_t)process_inbound, this,
+ NULL, (callback_job_cancel_t)return_false));
+ lib->processor->queue_job(lib->processor,
+ (job_t*)callback_job_create((callback_job_cb_t)process_outbound, this,
+ NULL, (callback_job_cancel_t)return_false));
+ return &this->public;
+}
diff --git a/src/libipsec/ipsec_processor.h b/src/libipsec/ipsec_processor.h
new file mode 100644
index 000000000..0a409828b
--- /dev/null
+++ b/src/libipsec/ipsec_processor.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup ipsec_processor ipsec_processor
+ * @{ @ingroup libipsec
+ */
+
+#ifndef IPSEC_PROCESSOR_H_
+#define IPSEC_PROCESSOR_H_
+
+#include "ip_packet.h"
+#include "esp_packet.h"
+
+typedef struct ipsec_processor_t ipsec_processor_t;
+
+/**
+ * Callback called to deliver an inbound plaintext packet.
+ *
+ * @param data data supplied during registration of the callback
+ * @param packet plaintext IP packet to deliver
+ */
+typedef void (*ipsec_inbound_cb_t)(void *data, ip_packet_t *packet);
+
+/**
+ * Callback called to send an ESP packet.
+ *
+ * @note The ESP packet currently comes without IP header (and without UDP
+ * header in case of UDP encapsulation)
+ *
+ * @param data data supplied during registration of the callback
+ * @param packet ESP packet to send
+ */
+typedef void (*ipsec_outbound_cb_t)(void *data, esp_packet_t *packet);
+
+/**
+ * IPsec processor
+ */
+struct ipsec_processor_t {
+
+ /**
+ * Queue an inbound ESP packet for processing.
+ *
+ * @param packet the ESP packet to process
+ */
+ void (*queue_inbound)(ipsec_processor_t *this, esp_packet_t *packet);
+
+ /**
+ * Queue an outbound plaintext IP packet for processing.
+ *
+ * @param packet the plaintext IP packet
+ */
+ void (*queue_outbound)(ipsec_processor_t *this, ip_packet_t *packet);
+
+ /**
+ * Register the callback used to deliver inbound plaintext packets.
+ *
+ * @param cb the inbound callback function
+ * @param data optional data provided to callback
+ */
+ void (*register_inbound)(ipsec_processor_t *this, ipsec_inbound_cb_t cb,
+ void *data);
+
+ /**
+ * Unregister a previously registered inbound callback.
+ *
+ * @param cb previously registered callback function
+ */
+ void (*unregister_inbound)(ipsec_processor_t *this,
+ ipsec_inbound_cb_t cb);
+
+ /**
+ * Register the callback used to send outbound ESP packets.
+ *
+ * @param cb the outbound callback function
+ * @param data optional data provided to callback
+ */
+ void (*register_outbound)(ipsec_processor_t *this, ipsec_outbound_cb_t cb,
+ void *data);
+
+ /**
+ * Unregister a previously registered outbound callback.
+ *
+ * @param cb previously registered callback function
+ */
+ void (*unregister_outbound)(ipsec_processor_t *this,
+ ipsec_outbound_cb_t cb);
+
+ /**
+ * Destroy an ipsec_processor_t.
+ */
+ void (*destroy)(ipsec_processor_t *this);
+
+};
+
+/**
+ * Create an ipsec_processor_t instance
+ *
+ * @return IPsec processor instance
+ */
+ipsec_processor_t *ipsec_processor_create();
+
+#endif /** IPSEC_PROCESSOR_H_ @}*/
diff --git a/src/libipsec/ipsec_sa.c b/src/libipsec/ipsec_sa.c
new file mode 100644
index 000000000..cccd16404
--- /dev/null
+++ b/src/libipsec/ipsec_sa.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012 Giuliano Grassi
+ * Copyright (C) 2012 Ralf Sager
+ * 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 "ipsec_sa.h"
+
+#include <library.h>
+#include <debug.h>
+
+typedef struct private_ipsec_sa_t private_ipsec_sa_t;
+
+/**
+ * Private additions to ipsec_sa_t.
+ */
+struct private_ipsec_sa_t {
+
+ /**
+ * Public members
+ */
+ ipsec_sa_t public;
+
+ /**
+ * SPI of this SA
+ */
+ u_int32_t spi;
+
+ /**
+ * Source address
+ */
+ host_t *src;
+
+ /**
+ * Destination address
+ */
+ host_t *dst;
+
+ /**
+ * Protocol
+ */
+ u_int8_t protocol;
+
+ /**
+ * Reqid of this SA
+ */
+ u_int32_t reqid;
+
+ /**
+ * Lifetime configuration
+ */
+ lifetime_cfg_t lifetime;
+
+ /**
+ * IPsec mode
+ */
+ ipsec_mode_t mode;
+
+ /**
+ * TRUE if extended sequence numbers are used
+ */
+ bool esn;
+
+ /**
+ * TRUE if this is an inbound SA
+ */
+ bool inbound;
+
+ /**
+ * ESP context
+ */
+ esp_context_t *esp_context;
+};
+
+METHOD(ipsec_sa_t, get_source, host_t*,
+ private_ipsec_sa_t *this)
+{
+ return this->src;
+}
+
+METHOD(ipsec_sa_t, get_destination, host_t*,
+ private_ipsec_sa_t *this)
+{
+ return this->dst;
+}
+
+METHOD(ipsec_sa_t, get_spi, u_int32_t,
+ private_ipsec_sa_t *this)
+{
+ return this->spi;
+}
+
+METHOD(ipsec_sa_t, get_reqid, u_int32_t,
+ private_ipsec_sa_t *this)
+{
+ return this->reqid;
+}
+
+METHOD(ipsec_sa_t, get_protocol, u_int8_t,
+ private_ipsec_sa_t *this)
+{
+ return this->protocol;
+}
+
+METHOD(ipsec_sa_t, get_lifetime, lifetime_cfg_t*,
+ private_ipsec_sa_t *this)
+{
+ return &this->lifetime;
+}
+
+METHOD(ipsec_sa_t, is_inbound, bool,
+ private_ipsec_sa_t *this)
+{
+ return this->inbound;
+}
+
+METHOD(ipsec_sa_t, get_esp_context, esp_context_t*,
+ private_ipsec_sa_t *this)
+{
+ return this->esp_context;
+}
+
+METHOD(ipsec_sa_t, match_by_spi_dst, bool,
+ private_ipsec_sa_t *this, u_int32_t spi, host_t *dst)
+{
+ return this->spi == spi && this->dst->ip_equals(this->dst, dst);
+}
+
+METHOD(ipsec_sa_t, match_by_spi_src_dst, bool,
+ private_ipsec_sa_t *this, u_int32_t spi, host_t *src, host_t *dst)
+{
+ return this->spi == spi && this->src->ip_equals(this->src, src) &&
+ this->dst->ip_equals(this->dst, dst);
+}
+
+METHOD(ipsec_sa_t, match_by_reqid, bool,
+ private_ipsec_sa_t *this, u_int32_t reqid, bool inbound)
+{
+ return this->reqid == reqid && this->inbound == inbound;
+}
+
+METHOD(ipsec_sa_t, destroy, void,
+ private_ipsec_sa_t *this)
+{
+ this->src->destroy(this->src);
+ this->dst->destroy(this->dst);
+ DESTROY_IF(this->esp_context);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+ipsec_sa_t *ipsec_sa_create(u_int32_t spi, host_t *src, host_t *dst,
+ u_int8_t protocol, u_int32_t reqid, mark_t mark, u_int32_t tfc,
+ lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
+ u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode,
+ u_int16_t ipcomp, u_int16_t cpi, bool encap, bool esn, bool inbound,
+ traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
+{
+ private_ipsec_sa_t *this;
+
+ if (protocol != IPPROTO_ESP)
+ {
+ DBG1(DBG_ESP, " IPsec SA: protocol not supported");
+ return NULL;
+ }
+ if (!encap)
+ {
+ DBG1(DBG_ESP, " IPsec SA: only UDP encapsulation is supported");
+ return NULL;
+ }
+ if (esn)
+ {
+ DBG1(DBG_ESP, " IPsec SA: ESN not supported");
+ return NULL;
+ }
+ if (ipcomp != IPCOMP_NONE)
+ {
+ DBG1(DBG_ESP, " IPsec SA: compression not supported");
+ return NULL;
+ }
+ if (mode != MODE_TUNNEL)
+ {
+ DBG1(DBG_ESP, " IPsec SA: unsupported mode");
+ return NULL;
+ }
+
+ INIT(this,
+ .public = {
+ .destroy = _destroy,
+ .get_source = _get_source,
+ .get_destination = _get_destination,
+ .get_spi = _get_spi,
+ .get_reqid = _get_reqid,
+ .get_protocol = _get_protocol,
+ .get_lifetime = _get_lifetime,
+ .is_inbound = _is_inbound,
+ .match_by_spi_dst = _match_by_spi_dst,
+ .match_by_spi_src_dst = _match_by_spi_src_dst,
+ .match_by_reqid = _match_by_reqid,
+ .get_esp_context = _get_esp_context,
+ },
+ .spi = spi,
+ .src = src->clone(src),
+ .dst = dst->clone(dst),
+ .lifetime = *lifetime,
+ .protocol = protocol,
+ .reqid = reqid,
+ .mode = mode,
+ .esn = esn,
+ .inbound = inbound,
+ );
+
+ this->esp_context = esp_context_create(enc_alg, enc_key, int_alg, int_key,
+ inbound);
+ if (!this->esp_context)
+ {
+ destroy(this);
+ return NULL;
+ }
+ return &this->public;
+}
diff --git a/src/libipsec/ipsec_sa.h b/src/libipsec/ipsec_sa.h
new file mode 100644
index 000000000..5fd03b6e4
--- /dev/null
+++ b/src/libipsec/ipsec_sa.h
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012 Giuliano Grassi
+ * Copyright (C) 2012 Ralf Sager
+ * 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 ipsec_sa ipsec_sa
+ * @{ @ingroup libipsec
+ */
+
+#ifndef IPSEC_SA_H_
+#define IPSEC_SA_H_
+
+#include "esp_context.h"
+
+#include <library.h>
+#include <utils/host.h>
+#include <selectors/traffic_selector.h>
+#include <ipsec/ipsec_types.h>
+
+typedef struct ipsec_sa_t ipsec_sa_t;
+
+/**
+ * IPsec Security Association (SA)
+ */
+struct ipsec_sa_t {
+
+ /**
+ * Get the source address for this SA
+ *
+ * @return source address of this SA
+ */
+ host_t *(*get_source)(ipsec_sa_t *this);
+
+ /**
+ * Get the destination address for this SA
+ *
+ * @return destination address of this SA
+ */
+ host_t *(*get_destination)(ipsec_sa_t *this);
+
+ /**
+ * Get the SPI for this SA
+ *
+ * @return SPI of this SA
+ */
+ u_int32_t (*get_spi)(ipsec_sa_t *this);
+
+ /**
+ * Get the reqid of this SA
+ *
+ * @return reqid of this SA
+ */
+ u_int32_t (*get_reqid)(ipsec_sa_t *this);
+
+ /**
+ * Get the protocol (e.g. IPPROTO_ESP) of this SA
+ *
+ * @return protocol of this SA
+ */
+ u_int8_t (*get_protocol)(ipsec_sa_t *this);
+
+ /**
+ * Returns whether this SA is inbound or outbound
+ *
+ * @return TRUE if inbound, FALSE if outbound
+ */
+ bool (*is_inbound)(ipsec_sa_t *this);
+
+ /**
+ * Get the lifetime information for this SA
+ * Note that this information is always relative to the time when the
+ * SA was installed (i.e. it is not adjusted over time)
+ *
+ * @return lifetime of this SA
+ */
+ lifetime_cfg_t *(*get_lifetime)(ipsec_sa_t *this);
+
+ /**
+ * Get the ESP context for this SA
+ *
+ * @return ESP context of this SA
+ */
+ esp_context_t *(*get_esp_context)(ipsec_sa_t *this);
+
+ /**
+ * Check if this SA matches all given parameters
+ *
+ * @param spi SPI
+ * @param dst destination address
+ * @return TRUE if this SA matches all parameters, FALSE otherwise
+ */
+ bool (*match_by_spi_dst)(ipsec_sa_t *this, u_int32_t spi, host_t *dst);
+
+ /**
+ * Check if this SA matches all given parameters
+ *
+ * @param spi SPI
+ * @param src source address
+ * @param dst destination address
+ * @return TRUE if this SA matches all parameters, FALSE otherwise
+ */
+ bool (*match_by_spi_src_dst)(ipsec_sa_t *this, u_int32_t spi, host_t *src,
+ host_t *dst);
+
+ /**
+ * Check if this SA matches all given parameters
+ *
+ * @param reqid reqid
+ * @param inbound TRUE for inbound SA, FALSE for outbound
+ * @return TRUE if this SA matches all parameters, FALSE otherwise
+ */
+ bool (*match_by_reqid)(ipsec_sa_t *this, u_int32_t reqid, bool inbound);
+
+ /**
+ * Destroy an ipsec_sa_t
+ */
+ void (*destroy)(ipsec_sa_t *this);
+
+};
+
+/**
+ * Create an ipsec_sa_t instance
+ *
+ * @param spi SPI for this SA
+ * @param src source address for this SA (gets cloned)
+ * @param dst destination address for this SA (gets cloned)
+ * @param protocol protocol for this SA (only ESP is supported)
+ * @param reqid reqid for this SA
+ * @param mark mark for this SA (ignored)
+ * @param tfc Traffic Flow Confidentiality (currently not supported)
+ * @param lifetime lifetime for this SA
+ * @param enc_alg encryption algorithm for this SA
+ * @param enc_key encryption key for this SA
+ * @param int_alg integrity protection algorithm
+ * @param int_key integrity protection key
+ * @param mode mode for this SA (only tunnel mode is supported)
+ * @param ipcomp IPcomp transform (not supported, use IPCOMP_NONE)
+ * @param cpi CPI for IPcomp (ignored)
+ * @param encap enable UDP encapsulation (must be TRUE)
+ * @param esn Extended Sequence Numbers (currently not supported)
+ * @param inbound TRUE if this is an inbound SA, FALSE otherwise
+ * @param src_ts source traffic selector
+ * @param dst_ts destination traffic selector
+ * @return the IPsec SA, or NULL if the creation failed
+ */
+ipsec_sa_t *ipsec_sa_create(u_int32_t spi, host_t *src, host_t *dst,
+ u_int8_t protocol, u_int32_t reqid, mark_t mark,
+ u_int32_t tfc, lifetime_cfg_t *lifetime,
+ u_int16_t enc_alg, chunk_t enc_key,
+ u_int16_t int_alg, chunk_t int_key,
+ ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
+ bool encap, bool esn, bool inbound,
+ traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts);
+
+#endif /** IPSEC_SA_H_ @}*/
diff --git a/src/libipsec/ipsec_sa_mgr.c b/src/libipsec/ipsec_sa_mgr.c
new file mode 100644
index 000000000..e42c77aa5
--- /dev/null
+++ b/src/libipsec/ipsec_sa_mgr.c
@@ -0,0 +1,626 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012 Giuliano Grassi
+ * Copyright (C) 2012 Ralf Sager
+ * 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 "ipsec.h"
+#include "ipsec_sa_mgr.h"
+
+#include <debug.h>
+#include <library.h>
+#include <processing/jobs/callback_job.h>
+#include <threading/condvar.h>
+#include <threading/mutex.h>
+#include <utils/hashtable.h>
+#include <utils/linked_list.h>
+
+typedef struct private_ipsec_sa_mgr_t private_ipsec_sa_mgr_t;
+
+/**
+ * Private additions to ipsec_sa_mgr_t.
+ */
+struct private_ipsec_sa_mgr_t {
+
+ /**
+ * Public members of ipsec_sa_mgr_t.
+ */
+ ipsec_sa_mgr_t public;
+
+ /**
+ * Installed SAs
+ */
+ linked_list_t *sas;
+
+ /**
+ * SPIs allocated using get_spi()
+ */
+ hashtable_t *allocated_spis;
+
+ /**
+ * Mutex used to synchronize access to the SA manager
+ */
+ mutex_t *mutex;
+
+ /**
+ * RNG used to generate SPIs
+ */
+ rng_t *rng;
+};
+
+/**
+ * Struct to keep track of locked IPsec SAs
+ */
+typedef struct {
+
+ /**
+ * IPsec SA
+ */
+ ipsec_sa_t *sa;
+
+ /**
+ * Set if this SA is currently in use by a thread
+ */
+ bool locked;
+
+ /**
+ * Condvar used by threads to wait for this entry
+ */
+ condvar_t *condvar;
+
+ /**
+ * Number of threads waiting for this entry
+ */
+ u_int waiting_threads;
+
+ /**
+ * Set if this entry is awaiting deletion
+ */
+ bool awaits_deletion;
+
+} ipsec_sa_entry_t;
+
+/**
+ * Helper struct for expiration events
+ */
+typedef struct {
+
+ /**
+ * IPsec SA manager
+ */
+ private_ipsec_sa_mgr_t *manager;
+
+ /**
+ * Entry that expired
+ */
+ ipsec_sa_entry_t *entry;
+
+ /**
+ * 0 if this is a hard expire, otherwise the offset in s (soft->hard)
+ */
+ u_int32_t hard_offset;
+
+} ipsec_sa_expired_t;
+
+/*
+ * Used for the hash table of allocated SPIs
+ */
+static bool spi_equals(u_int32_t *spi, u_int32_t *other_spi)
+{
+ return *spi == *other_spi;
+}
+
+static u_int spi_hash(u_int32_t *spi)
+{
+ return chunk_hash(chunk_from_thing(*spi));
+}
+
+/**
+ * Create an SA entry
+ */
+static ipsec_sa_entry_t *create_entry(ipsec_sa_t *sa)
+{
+ ipsec_sa_entry_t *this;
+
+ INIT(this,
+ .condvar = condvar_create(CONDVAR_TYPE_DEFAULT),
+ .sa = sa,
+ );
+ return this;
+}
+
+/**
+ * Destroy an SA entry
+ */
+static void destroy_entry(ipsec_sa_entry_t *entry)
+{
+ entry->condvar->destroy(entry->condvar);
+ entry->sa->destroy(entry->sa);
+ free(entry);
+}
+
+/**
+ * Makes sure an entry is safe to remove
+ * Must be called with this->mutex held.
+ *
+ * @return TRUE if entry can be removed, FALSE if entry is already
+* being removed by another thread
+ */
+static bool wait_remove_entry(private_ipsec_sa_mgr_t *this,
+ ipsec_sa_entry_t *entry)
+{
+ if (entry->awaits_deletion)
+ {
+ /* this will be deleted by another thread already */
+ return FALSE;
+ }
+ entry->awaits_deletion = TRUE;
+ while (entry->locked)
+ {
+ entry->condvar->wait(entry->condvar, this->mutex);
+ }
+ while (entry->waiting_threads > 0)
+ {
+ entry->condvar->broadcast(entry->condvar);
+ entry->condvar->wait(entry->condvar, this->mutex);
+ }
+ return TRUE;
+}
+
+/**
+ * Waits until an is available and then locks it.
+ * Must only be called with this->mutex held
+ */
+static bool wait_for_entry(private_ipsec_sa_mgr_t *this,
+ ipsec_sa_entry_t *entry)
+{
+ while (entry->locked && !entry->awaits_deletion)
+ {
+ entry->waiting_threads++;
+ entry->condvar->wait(entry->condvar, this->mutex);
+ entry->waiting_threads--;
+ }
+ if (entry->awaits_deletion)
+ {
+ /* others may still be waiting, */
+ entry->condvar->signal(entry->condvar);
+ return FALSE;
+ }
+ entry->locked = TRUE;
+ return TRUE;
+}
+
+/**
+ * Flushes all entries
+ * Must be called with this->mutex held.
+ */
+static void flush_entries(private_ipsec_sa_mgr_t *this)
+{
+ ipsec_sa_entry_t *current;
+ enumerator_t *enumerator;
+
+ DBG2(DBG_ESP, "flushing SAD");
+
+ enumerator = this->sas->create_enumerator(this->sas);
+ while (enumerator->enumerate(enumerator, (void**)&current))
+ {
+ if (wait_remove_entry(this, current))
+ {
+ this->sas->remove_at(this->sas, enumerator);
+ destroy_entry(current);
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/*
+ * Different match functions to find SAs in the linked list
+ */
+static bool match_entry_by_ptr(ipsec_sa_entry_t *item, ipsec_sa_entry_t *entry)
+{
+ return item == entry;
+}
+
+static bool match_entry_by_sa_ptr(ipsec_sa_entry_t *item, ipsec_sa_t *sa)
+{
+ return item->sa == sa;
+}
+
+static bool match_entry_by_spi_inbound(ipsec_sa_entry_t *item, u_int32_t spi,
+ bool inbound)
+{
+ return item->sa->get_spi(item->sa) == spi &&
+ item->sa->is_inbound(item->sa) == inbound;
+}
+
+static bool match_entry_by_spi_src_dst(ipsec_sa_entry_t *item, u_int32_t spi,
+ host_t *src, host_t *dst)
+{
+ return item->sa->match_by_spi_src_dst(item->sa, spi, src, dst);
+}
+
+static bool match_entry_by_reqid_inbound(ipsec_sa_entry_t *item,
+ u_int32_t reqid, bool inbound)
+{
+ return item->sa->match_by_reqid(item->sa, reqid, inbound);
+}
+
+static bool match_entry_by_spi_dst(ipsec_sa_entry_t *item, u_int32_t spi,
+ host_t *dst)
+{
+ return item->sa->match_by_spi_dst(item->sa, spi, dst);
+}
+
+/**
+ * Remove an entry
+ */
+static bool remove_entry(private_ipsec_sa_mgr_t *this, ipsec_sa_entry_t *entry)
+{
+ ipsec_sa_entry_t *current;
+ enumerator_t *enumerator;
+ bool removed = FALSE;
+
+ enumerator = this->sas->create_enumerator(this->sas);
+ while (enumerator->enumerate(enumerator, (void**)&current))
+ {
+ if (current == entry)
+ {
+ if (wait_remove_entry(this, current))
+ {
+ this->sas->remove_at(this->sas, enumerator);
+ removed = TRUE;
+ }
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return removed;
+}
+
+/**
+ * Callback for expiration events
+ */
+static job_requeue_t sa_expired(ipsec_sa_expired_t *expired)
+{
+ private_ipsec_sa_mgr_t *this = expired->manager;
+
+ this->mutex->lock(this->mutex);
+ if (this->sas->find_first(this->sas, (void*)match_entry_by_ptr,
+ NULL, expired->entry) == SUCCESS)
+ {
+ u_int32_t hard_offset = expired->hard_offset;
+ ipsec_sa_t *sa = expired->entry->sa;
+
+ ipsec->events->expire(ipsec->events, sa->get_reqid(sa),
+ sa->get_protocol(sa), sa->get_spi(sa),
+ hard_offset == 0);
+ if (hard_offset)
+ { /* soft limit reached, schedule hard expire */
+ expired->hard_offset = 0;
+ this->mutex->unlock(this->mutex);
+ return JOB_RESCHEDULE(hard_offset);
+ }
+ /* hard limit reached */
+ if (remove_entry(this, expired->entry))
+ {
+ destroy_entry(expired->entry);
+ }
+ }
+ this->mutex->unlock(this->mutex);
+ return JOB_REQUEUE_NONE;
+}
+
+/**
+ * Schedule a job to handle IPsec SA expiration
+ */
+static void schedule_expiration(private_ipsec_sa_mgr_t *this,
+ ipsec_sa_entry_t *entry)
+{
+ lifetime_cfg_t *lifetime = entry->sa->get_lifetime(entry->sa);
+ ipsec_sa_expired_t *expired;
+ callback_job_t *job;
+ u_int32_t timeout;
+
+ INIT(expired,
+ .manager = this,
+ .entry = entry,
+ );
+
+ /* schedule a rekey first, a hard timeout will be scheduled then, if any */
+ expired->hard_offset = lifetime->time.life - lifetime->time.rekey;
+ timeout = lifetime->time.rekey;
+
+ if (lifetime->time.life <= lifetime->time.rekey ||
+ lifetime->time.rekey == 0)
+ { /* no rekey, schedule hard timeout */
+ expired->hard_offset = 0;
+ timeout = lifetime->time.life;
+ }
+
+ job = callback_job_create((callback_job_cb_t)sa_expired, expired,
+ (callback_job_cleanup_t)free, NULL);
+ lib->scheduler->schedule_job(lib->scheduler, (job_t*)job, timeout);
+}
+
+/**
+ * Remove all allocated SPIs
+ */
+static void flush_allocated_spis(private_ipsec_sa_mgr_t *this)
+{
+ enumerator_t *enumerator;
+ u_int32_t *current;
+
+ DBG2(DBG_ESP, "flushing allocated SPIs");
+ enumerator = this->allocated_spis->create_enumerator(this->allocated_spis);
+ while (enumerator->enumerate(enumerator, NULL, (void**)&current))
+ {
+ this->allocated_spis->remove_at(this->allocated_spis, enumerator);
+ DBG2(DBG_ESP, " removed allocated SPI %.8x", ntohl(*current));
+ free(current);
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Pre-allocate an SPI for an inbound SA
+ */
+static bool allocate_spi(private_ipsec_sa_mgr_t *this, u_int32_t spi)
+{
+ u_int32_t *spi_alloc;
+
+ if (this->allocated_spis->get(this->allocated_spis, &spi) ||
+ this->sas->find_first(this->sas, (void*)match_entry_by_spi_inbound,
+ NULL, spi, TRUE) == SUCCESS)
+ {
+ return FALSE;
+ }
+ spi_alloc = malloc_thing(u_int32_t);
+ *spi_alloc = spi;
+ this->allocated_spis->put(this->allocated_spis, spi_alloc, spi_alloc);
+ return TRUE;
+}
+
+METHOD(ipsec_sa_mgr_t, get_spi, status_t,
+ private_ipsec_sa_mgr_t *this, host_t *src, host_t *dst, u_int8_t protocol,
+ u_int32_t reqid, u_int32_t *spi)
+{
+ u_int32_t spi_new;
+
+ DBG2(DBG_ESP, "allocating SPI for reqid {%u}", reqid);
+
+ this->mutex->lock(this->mutex);
+ if (!this->rng)
+ {
+ this->rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ if (!this->rng)
+ {
+ this->mutex->unlock(this->mutex);
+ DBG1(DBG_ESP, "failed to create RNG for SPI generation");
+ return FAILED;
+ }
+ }
+
+ do
+ {
+ if (!this->rng->get_bytes(this->rng, sizeof(spi_new),
+ (u_int8_t*)&spi_new))
+ {
+ this->mutex->unlock(this->mutex);
+ DBG1(DBG_ESP, "failed to allocate SPI for reqid {%u}", reqid);
+ return FAILED;
+ }
+ /* make sure the SPI is valid (not in range 0-255) */
+ spi_new |= 0x00000100;
+ spi_new = htonl(spi_new);
+ }
+ while (!allocate_spi(this, spi_new));
+ this->mutex->unlock(this->mutex);
+
+ *spi = spi_new;
+
+ DBG2(DBG_ESP, "allocated SPI %.8x for reqid {%u}", ntohl(*spi), reqid);
+ return SUCCESS;
+}
+
+METHOD(ipsec_sa_mgr_t, add_sa, status_t,
+ private_ipsec_sa_mgr_t *this, host_t *src, host_t *dst, u_int32_t spi,
+ u_int8_t protocol, u_int32_t reqid, mark_t mark, u_int32_t tfc,
+ lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
+ u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp,
+ u_int16_t cpi, bool encap, bool esn, bool inbound,
+ traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
+{
+ ipsec_sa_entry_t *entry;
+ ipsec_sa_t *sa_new;
+
+ DBG2(DBG_ESP, "adding SAD entry with SPI %.8x and reqid {%u}",
+ ntohl(spi), reqid);
+ DBG2(DBG_ESP, " using encryption algorithm %N with key size %d",
+ encryption_algorithm_names, enc_alg, enc_key.len * 8);
+ DBG2(DBG_ESP, " using integrity algorithm %N with key size %d",
+ integrity_algorithm_names, int_alg, int_key.len * 8);
+
+ sa_new = ipsec_sa_create(spi, src, dst, protocol, reqid, mark, tfc,
+ lifetime, enc_alg, enc_key, int_alg, int_key, mode,
+ ipcomp, cpi, encap, esn, inbound, src_ts, dst_ts);
+ if (!sa_new)
+ {
+ DBG1(DBG_ESP, "failed to create SAD entry");
+ return FAILED;
+ }
+
+ this->mutex->lock(this->mutex);
+
+ if (inbound)
+ { /* remove any pre-allocated SPIs */
+ u_int32_t *spi_alloc;
+
+ spi_alloc = this->allocated_spis->remove(this->allocated_spis, &spi);
+ free(spi_alloc);
+ }
+
+ if (this->sas->find_first(this->sas, (void*)match_entry_by_spi_src_dst,
+ NULL, spi, src, dst) == SUCCESS)
+ {
+ this->mutex->unlock(this->mutex);
+ DBG1(DBG_ESP, "failed to install SAD entry: already installed");
+ sa_new->destroy(sa_new);
+ return FAILED;
+ }
+
+ entry = create_entry(sa_new);
+ schedule_expiration(this, entry);
+ this->sas->insert_last(this->sas, entry);
+
+ this->mutex->unlock(this->mutex);
+ return SUCCESS;
+}
+
+METHOD(ipsec_sa_mgr_t, del_sa, status_t,
+ private_ipsec_sa_mgr_t *this, host_t *src, host_t *dst, u_int32_t spi,
+ u_int8_t protocol, u_int16_t cpi, mark_t mark)
+{
+ ipsec_sa_entry_t *current, *found = NULL;
+ enumerator_t *enumerator;
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->sas->create_enumerator(this->sas);
+ while (enumerator->enumerate(enumerator, (void**)&current))
+ {
+ if (match_entry_by_spi_src_dst(current, spi, src, dst))
+ {
+ if (wait_remove_entry(this, current))
+ {
+ this->sas->remove_at(this->sas, enumerator);
+ found = current;
+ }
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+
+ if (found)
+ {
+ DBG2(DBG_ESP, "deleted %sbound SAD entry with SPI %.8x",
+ found->sa->is_inbound(found->sa) ? "in" : "out", ntohl(spi));
+ destroy_entry(found);
+ return SUCCESS;
+ }
+ return FAILED;
+}
+
+METHOD(ipsec_sa_mgr_t, checkout_by_reqid, ipsec_sa_t*,
+ private_ipsec_sa_mgr_t *this, u_int32_t reqid, bool inbound)
+{
+ ipsec_sa_entry_t *entry;
+ ipsec_sa_t *sa = NULL;
+
+ this->mutex->lock(this->mutex);
+ if (this->sas->find_first(this->sas, (void*)match_entry_by_reqid_inbound,
+ (void**)&entry, reqid, inbound) == SUCCESS &&
+ wait_for_entry(this, entry))
+ {
+ sa = entry->sa;
+ }
+ this->mutex->unlock(this->mutex);
+ return sa;
+}
+
+METHOD(ipsec_sa_mgr_t, checkout_by_spi, ipsec_sa_t*,
+ private_ipsec_sa_mgr_t *this, u_int32_t spi, host_t *dst)
+{
+ ipsec_sa_entry_t *entry;
+ ipsec_sa_t *sa = NULL;
+
+ this->mutex->lock(this->mutex);
+ if (this->sas->find_first(this->sas, (void*)match_entry_by_spi_dst,
+ (void**)&entry, spi, dst) == SUCCESS &&
+ wait_for_entry(this, entry))
+ {
+ sa = entry->sa;
+ }
+ this->mutex->unlock(this->mutex);
+ return sa;
+}
+
+METHOD(ipsec_sa_mgr_t, checkin, void,
+ private_ipsec_sa_mgr_t *this, ipsec_sa_t *sa)
+{
+ ipsec_sa_entry_t *entry;
+
+ this->mutex->lock(this->mutex);
+ if (this->sas->find_first(this->sas, (void*)match_entry_by_sa_ptr,
+ (void**)&entry, sa) == SUCCESS)
+ {
+ if (entry->locked)
+ {
+ entry->locked = FALSE;
+ entry->condvar->signal(entry->condvar);
+ }
+ }
+ this->mutex->unlock(this->mutex);
+}
+
+METHOD(ipsec_sa_mgr_t, flush_sas, status_t,
+ private_ipsec_sa_mgr_t *this)
+{
+ this->mutex->lock(this->mutex);
+ flush_entries(this);
+ this->mutex->unlock(this->mutex);
+ return SUCCESS;
+}
+
+METHOD(ipsec_sa_mgr_t, destroy, void,
+ private_ipsec_sa_mgr_t *this)
+{
+ this->mutex->lock(this->mutex);
+ flush_entries(this);
+ flush_allocated_spis(this);
+ this->mutex->unlock(this->mutex);
+
+ this->allocated_spis->destroy(this->allocated_spis);
+ this->sas->destroy(this->sas);
+
+ this->mutex->destroy(this->mutex);
+ DESTROY_IF(this->rng);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+ipsec_sa_mgr_t *ipsec_sa_mgr_create()
+{
+ private_ipsec_sa_mgr_t *this;
+
+ INIT(this,
+ .public = {
+ .get_spi = _get_spi,
+ .add_sa = _add_sa,
+ .del_sa = _del_sa,
+ .checkout_by_spi = _checkout_by_spi,
+ .checkout_by_reqid = _checkout_by_reqid,
+ .checkin = _checkin,
+ .flush_sas = _flush_sas,
+ .destroy = _destroy,
+ },
+ .sas = linked_list_create(),
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ .allocated_spis = hashtable_create((hashtable_hash_t)spi_hash,
+ (hashtable_equals_t)spi_equals, 16),
+ );
+
+ return &this->public;
+}
diff --git a/src/libipsec/ipsec_sa_mgr.h b/src/libipsec/ipsec_sa_mgr.h
new file mode 100644
index 000000000..303b36f0e
--- /dev/null
+++ b/src/libipsec/ipsec_sa_mgr.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012 Giuliano Grassi
+ * Copyright (C) 2012 Ralf Sager
+ * 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 ipsec_sa_mgr ipsec_sa_mgr
+ * @{ @ingroup libipsec
+ */
+
+#ifndef IPSEC_SA_MGR_H_
+#define IPSEC_SA_MGR_H_
+
+#include "ipsec_sa.h"
+
+#include <library.h>
+#include <ipsec/ipsec_types.h>
+#include <selectors/traffic_selector.h>
+#include <utils/host.h>
+
+typedef struct ipsec_sa_mgr_t ipsec_sa_mgr_t;
+
+/**
+ * IPsec SA manager
+ *
+ * The first methods are modeled after those in kernel_ipsec_t.
+ */
+struct ipsec_sa_mgr_t {
+
+ /**
+ * Allocate an SPI for an inbound IPsec SA
+ *
+ * @param src source address of the SA
+ * @param dst destination address of the SA
+ * @param protocol protocol of the SA (only ESP supported)
+ * @param reqid reqid for the SA
+ * @param spi the allocated SPI
+ * @return SUCCESS of operation successful
+ */
+ status_t (*get_spi)(ipsec_sa_mgr_t *this, host_t *src, host_t *dst,
+ u_int8_t protocol, u_int32_t reqid, u_int32_t *spi);
+
+ /**
+ * Add a new SA
+ *
+ * @param src source address for this SA (gets cloned)
+ * @param dst destination address for this SA (gets cloned)
+ * @param spi SPI for this SA
+ * @param protocol protocol for this SA (only ESP is supported)
+ * @param reqid reqid for this SA
+ * @param mark mark for this SA (ignored)
+ * @param tfc Traffic Flow Confidentiality (not yet supported)
+ * @param lifetime lifetime for this SA
+ * @param enc_alg encryption algorithm for this SA
+ * @param enc_key encryption key for this SA
+ * @param int_alg integrity protection algorithm
+ * @param int_key integrity protection key
+ * @param mode mode for this SA (only tunnel mode is supported)
+ * @param ipcomp IPcomp transform (not supported, use IPCOMP_NONE)
+ * @param cpi CPI for IPcomp (ignored)
+ * @param encap enable UDP encapsulation (must be TRUE)
+ * @param esn Extended Sequence Numbers (currently not supported)
+ * @param inbound TRUE if this is an inbound SA, FALSE otherwise
+ * @param src_ts source traffic selector
+ * @param dst_ts destination traffic selector
+ * @return SUCCESS if operation completed
+ */
+ status_t (*add_sa)(ipsec_sa_mgr_t *this, host_t *src, host_t *dst,
+ u_int32_t spi, u_int8_t protocol, u_int32_t reqid,
+ mark_t mark, u_int32_t tfc, lifetime_cfg_t *lifetime,
+ u_int16_t enc_alg, chunk_t enc_key, u_int16_t int_alg,
+ chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp,
+ u_int16_t cpi, bool encap, bool esn, bool inbound,
+ traffic_selector_t *src_ts, traffic_selector_t *dst_ts);
+
+ /**
+ * Delete a previously added SA
+ *
+ * @param spi SPI of the SA
+ * @param src source address of the SA
+ * @param dst destination address of the SA
+ * @param protocol protocol of the SA
+ * @param cpi CPI for IPcomp
+ * @param mark optional mark
+ * @return SUCCESS if operation completed
+ */
+ status_t (*del_sa)(ipsec_sa_mgr_t *this, host_t *src, host_t *dst,
+ u_int32_t spi, u_int8_t protocol, u_int16_t cpi,
+ mark_t mark);
+
+ /**
+ * Flush all SAs
+ *
+ * @return SUCCESS if operation completed
+ */
+ status_t (*flush_sas)(ipsec_sa_mgr_t *this);
+
+ /**
+ * Checkout an installed IPsec SA by SPI and destination address
+ * Can be used to find the correct SA for an inbound packet.
+ *
+ * The matching SA is locked until it is checked in using checkin().
+ * If the matching SA is already checked out, this call blocks until the
+ * SA is checked in.
+ *
+ * Since other threads may be waiting for the checked out SA, it should be
+ * checked in as soon as possible after use.
+ *
+ * @param spi SPI (e.g. of an inbound packet)
+ * @param dst destination address (e.g. of an inbound packet)
+ * @return the matching IPsec SA, or NULL if none is found
+ */
+ ipsec_sa_t *(*checkout_by_spi)(ipsec_sa_mgr_t *this, u_int32_t spi,
+ host_t *dst);
+
+ /**
+ * Checkout an installed IPsec SA by its reqid and inbound/outbound flag.
+ * Can be used to find the correct SA for an outbound packet.
+ *
+ * The matching SA is locked until it is checked in using checkin().
+ * If the matching SA is already checked out, this call blocks until the
+ * SA is checked in.
+ *
+ * Since other threads may be waiting for a checked out SA, it should be
+ * checked in as soon as possible after use.
+ *
+ * @param reqid reqid of the SA
+ * @param inbound TRUE for an inbound SA, FALSE for an outbound SA
+ * @return the matching IPsec SA, or NULL if none is found
+ */
+ ipsec_sa_t *(*checkout_by_reqid)(ipsec_sa_mgr_t *this, u_int32_t reqid,
+ bool inbound);
+
+ /**
+ * Checkin an SA after use.
+ *
+ * @param sa checked out SA
+ */
+ void (*checkin)(ipsec_sa_mgr_t *this, ipsec_sa_t *sa);
+
+ /**
+ * Destroy an ipsec_sa_mgr_t
+ */
+ void (*destroy)(ipsec_sa_mgr_t *this);
+
+};
+
+/**
+ * Create an ipsec_sa_mgr instance
+ *
+ * @return IPsec SA manager instance
+ */
+ipsec_sa_mgr_t *ipsec_sa_mgr_create();
+
+#endif /** IPSEC_SA_MGR_H_ @}*/
diff --git a/src/libpts/Makefile.am b/src/libpts/Makefile.am
index 3ff941794..8137493ab 100644
--- a/src/libpts/Makefile.am
+++ b/src/libpts/Makefile.am
@@ -9,6 +9,7 @@ libpts_la_SOURCES = \
libpts.h libpts.c \
pts/pts.h pts/pts.c \
pts/pts_error.h pts/pts_error.c \
+ pts/pts_pcr.h pts/pts_pcr.c \
pts/pts_proto_caps.h \
pts/pts_req_func_comp_evid.h \
pts/pts_simple_evid_final.h \
diff --git a/src/libpts/Makefile.in b/src/libpts/Makefile.in
index d317cfea1..0b6451bcc 100644
--- a/src/libpts/Makefile.in
+++ b/src/libpts/Makefile.in
@@ -51,6 +51,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -77,8 +78,8 @@ am__base_list = \
am__installdirs = "$(DESTDIR)$(ipseclibdir)"
LTLIBRARIES = $(ipseclib_LTLIBRARIES)
libpts_la_DEPENDENCIES = $(top_builddir)/src/libimcv/libimcv.la
-am_libpts_la_OBJECTS = libpts.lo pts.lo pts_error.lo pts_creds.lo \
- pts_database.lo pts_dh_group.lo pts_file_meas.lo \
+am_libpts_la_OBJECTS = libpts.lo pts.lo pts_error.lo pts_pcr.lo \
+ pts_creds.lo pts_database.lo pts_dh_group.lo pts_file_meas.lo \
pts_file_meta.lo pts_file_type.lo pts_meas_algo.lo \
pts_component_manager.lo pts_comp_evidence.lo \
pts_comp_func_name.lo ita_comp_func_name.lo ita_comp_ima.lo \
@@ -96,7 +97,7 @@ am_libpts_la_OBJECTS = libpts.lo pts.lo pts_error.lo pts_creds.lo \
tcg_pts_attr_req_file_meas.lo tcg_pts_attr_file_meas.lo \
tcg_pts_attr_req_file_meta.lo tcg_pts_attr_unix_file_meta.lo
libpts_la_OBJECTS = $(am_libpts_la_OBJECTS)
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -160,6 +161,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -254,11 +256,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -275,11 +280,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -295,6 +301,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -304,7 +311,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -339,6 +345,7 @@ libpts_la_SOURCES = \
libpts.h libpts.c \
pts/pts.h pts/pts.c \
pts/pts_error.h pts/pts_error.c \
+ pts/pts_pcr.h pts/pts_pcr.c \
pts/pts_proto_caps.h \
pts/pts_req_func_comp_evid.h \
pts/pts_simple_evid_final.h \
@@ -469,6 +476,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pts_file_meta.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pts_file_type.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pts_meas_algo.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pts_pcr.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcg_attr.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcg_comp_func_name.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcg_pts_attr_aik.Plo@am__quote@
@@ -524,6 +532,13 @@ pts_error.lo: pts/pts_error.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pts_error.lo `test -f 'pts/pts_error.c' || echo '$(srcdir)/'`pts/pts_error.c
+pts_pcr.lo: pts/pts_pcr.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pts_pcr.lo -MD -MP -MF $(DEPDIR)/pts_pcr.Tpo -c -o pts_pcr.lo `test -f 'pts/pts_pcr.c' || echo '$(srcdir)/'`pts/pts_pcr.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pts_pcr.Tpo $(DEPDIR)/pts_pcr.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pts/pts_pcr.c' object='pts_pcr.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pts_pcr.lo `test -f 'pts/pts_pcr.c' || echo '$(srcdir)/'`pts/pts_pcr.c
+
pts_creds.lo: pts/pts_creds.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pts_creds.lo -MD -MP -MF $(DEPDIR)/pts_creds.Tpo -c -o pts_creds.lo `test -f 'pts/pts_creds.c' || echo '$(srcdir)/'`pts/pts_creds.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pts_creds.Tpo $(DEPDIR)/pts_creds.Plo
diff --git a/src/libpts/plugins/imc_attestation/Makefile.in b/src/libpts/plugins/imc_attestation/Makefile.in
index 583d2dfee..4734379bf 100644
--- a/src/libpts/plugins/imc_attestation/Makefile.in
+++ b/src/libpts/plugins/imc_attestation/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -84,7 +85,7 @@ imc_attestation_la_OBJECTS = $(am_imc_attestation_la_OBJECTS)
imc_attestation_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(imc_attestation_la_LDFLAGS) $(LDFLAGS) -o $@
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -110,6 +111,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -204,11 +206,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -225,11 +230,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -245,6 +251,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -254,7 +261,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libpts/plugins/imc_attestation/imc_attestation.c b/src/libpts/plugins/imc_attestation/imc_attestation.c
index 4f77ba093..7cb2a0671 100644
--- a/src/libpts/plugins/imc_attestation/imc_attestation.c
+++ b/src/libpts/plugins/imc_attestation/imc_attestation.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -21,6 +21,7 @@
#include <ietf/ietf_attr.h>
#include <ietf/ietf_attr_pa_tnc_error.h>
#include <ietf/ietf_attr_product_info.h>
+#include <ietf/ietf_attr_assess_result.h>
#include <libpts.h>
@@ -108,9 +109,17 @@ TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id,
case TNC_CONNECTION_STATE_CREATE:
state = imc_attestation_state_create(connection_id);
return imc_attestation->create_state(imc_attestation, state);
+ case TNC_CONNECTION_STATE_HANDSHAKE:
+ if (imc_attestation->change_state(imc_attestation, 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_attestation->delete_state(imc_attestation, connection_id);
- case TNC_CONNECTION_STATE_HANDSHAKE:
case TNC_CONNECTION_STATE_ACCESS_ISOLATED:
case TNC_CONNECTION_STATE_ACCESS_NONE:
default:
@@ -149,17 +158,15 @@ TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id,
platform_info = pts->get_platform_info(pts);
if (platform_info)
{
- pa_tnc_msg_t *pa_tnc_msg;
+ linked_list_t *attr_list;
pa_tnc_attr_t *attr;
- pa_tnc_msg = pa_tnc_msg_create();
+ attr_list = linked_list_create();
attr = ietf_attr_product_info_create(0, 0, platform_info);
- pa_tnc_msg->add_attribute(pa_tnc_msg, attr);
- pa_tnc_msg->build(pa_tnc_msg);
+ attr_list->insert_last(attr_list, attr);
result = imc_attestation->send_message(imc_attestation, connection_id,
- FALSE, 0, TNC_IMVID_ANY,
- pa_tnc_msg->get_encoding(pa_tnc_msg));
- pa_tnc_msg->destroy(pa_tnc_msg);
+ FALSE, 0, TNC_IMVID_ANY, attr_list);
+ attr_list->destroy(attr_list);
}
return result;
@@ -176,11 +183,13 @@ static TNC_Result receive_message(TNC_IMCID imc_id,
{
pa_tnc_msg_t *pa_tnc_msg;
pa_tnc_attr_t *attr;
+ pen_type_t type;
linked_list_t *attr_list;
imc_state_t *state;
imc_attestation_state_t *attestation_state;
enumerator_t *enumerator;
TNC_Result result;
+ TNC_UInt32 target_imc_id;
if (!imc_attestation)
{
@@ -204,6 +213,7 @@ static TNC_Result receive_message(TNC_IMCID imc_id,
{
return result;
}
+ target_imc_id = (dst_imc_id == TNC_IMCID_ANY) ? imc_id : dst_imc_id;
/* preprocess any IETF standard error attributes */
result = pa_tnc_msg->process_ietf_std_errors(pa_tnc_msg) ?
@@ -215,30 +225,40 @@ static TNC_Result receive_message(TNC_IMCID imc_id,
enumerator = pa_tnc_msg->create_attribute_enumerator(pa_tnc_msg);
while (enumerator->enumerate(enumerator, &attr))
{
- if (attr->get_vendor_id(attr) == PEN_IETF &&
- attr->get_type(attr) == IETF_ATTR_PA_TNC_ERROR)
- {
- ietf_attr_pa_tnc_error_t *error_attr;
- pen_t error_vendor_id;
- pa_tnc_error_code_t error_code;
- chunk_t msg_info;
+ type = attr->get_type(attr);
- error_attr = (ietf_attr_pa_tnc_error_t*)attr;
- error_vendor_id = error_attr->get_vendor_id(error_attr);
-
- if (error_vendor_id == PEN_TCG)
+ if (type.vendor_id == PEN_IETF)
+ {
+ if (type.type == IETF_ATTR_PA_TNC_ERROR)
{
+ ietf_attr_pa_tnc_error_t *error_attr;
+ pen_type_t error_code;
+ chunk_t msg_info;
+
+ error_attr = (ietf_attr_pa_tnc_error_t*)attr;
error_code = error_attr->get_error_code(error_attr);
- msg_info = error_attr->get_msg_info(error_attr);
- DBG1(DBG_IMC, "received TCG-PTS error '%N'",
- pts_error_code_names, error_code);
- DBG1(DBG_IMC, "error information: %B", &msg_info);
+ if (error_code.vendor_id == PEN_TCG)
+ {
+ msg_info = error_attr->get_msg_info(error_attr);
- result = TNC_RESULT_FATAL;
+ DBG1(DBG_IMC, "received TCG-PTS error '%N'",
+ pts_error_code_names, error_code.type);
+ DBG1(DBG_IMC, "error information: %B", &msg_info);
+
+ result = TNC_RESULT_FATAL;
+ }
+ }
+ else if (type.type == IETF_ATTR_ASSESSMENT_RESULT)
+ {
+ ietf_attr_assess_result_t *ietf_attr;
+
+ ietf_attr = (ietf_attr_assess_result_t*)attr;
+ state->set_result(state, target_imc_id,
+ ietf_attr->get_result(ietf_attr));
}
}
- else if (attr->get_vendor_id(attr) == PEN_TCG)
+ else if (type.vendor_id == PEN_TCG)
{
if (!imc_attestation_process(attr, attr_list, attestation_state,
supported_algorithms, supported_dh_groups))
@@ -253,23 +273,11 @@ static TNC_Result receive_message(TNC_IMCID imc_id,
if (result == TNC_RESULT_SUCCESS && attr_list->get_count(attr_list))
{
- pa_tnc_msg = pa_tnc_msg_create();
-
- enumerator = attr_list->create_enumerator(attr_list);
- while (enumerator->enumerate(enumerator, &attr))
- {
- pa_tnc_msg->add_attribute(pa_tnc_msg, attr);
- }
- enumerator->destroy(enumerator);
-
- pa_tnc_msg->build(pa_tnc_msg);
result = imc_attestation->send_message(imc_attestation, connection_id,
- FALSE, 0, TNC_IMVID_ANY,
- pa_tnc_msg->get_encoding(pa_tnc_msg));
- pa_tnc_msg->destroy(pa_tnc_msg);
+ FALSE, 0, TNC_IMVID_ANY, attr_list);
}
-
attr_list->destroy(attr_list);
+
return result;
}
diff --git a/src/libpts/plugins/imc_attestation/imc_attestation_process.c b/src/libpts/plugins/imc_attestation/imc_attestation_process.c
index b70c05370..bd2fa649d 100644
--- a/src/libpts/plugins/imc_attestation/imc_attestation_process.c
+++ b/src/libpts/plugins/imc_attestation/imc_attestation_process.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -23,7 +23,6 @@
#include <ietf/ietf_attr_pa_tnc_error.h>
-#include <libpts.h>
#include <pts/pts.h>
#include <tcg/tcg_pts_attr_proto_caps.h>
@@ -57,10 +56,13 @@ bool imc_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
chunk_t attr_info;
pts_t *pts;
pts_error_code_t pts_error;
+ pen_type_t attr_type;
bool valid_path;
pts = attestation_state->get_pts(attestation_state);
- switch (attr->get_type(attr))
+ attr_type = attr->get_type(attr);
+
+ switch (attr_type.type)
{
case TCG_PTS_REQ_PROTO_CAPS:
{
@@ -182,12 +184,12 @@ bool imc_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
case TCG_PTS_GET_TPM_VERSION_INFO:
{
chunk_t tpm_version_info, attr_info;
+ pen_type_t error_code = { PEN_TCG, TCG_PTS_TPM_VERS_NOT_SUPPORTED };
if (!pts->get_tpm_version_info(pts, &tpm_version_info))
{
attr_info = attr->get_value(attr);
- attr = ietf_attr_pa_tnc_error_create(PEN_TCG,
- TCG_PTS_TPM_VERS_NOT_SUPPORTED, attr_info);
+ attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
attr_list->insert_last(attr_list, attr);
break;
}
@@ -221,6 +223,7 @@ bool imc_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
bool is_directory;
u_int32_t delimiter;
pts_file_meas_t *measurements;
+ pen_type_t error_code;
attr_info = attr->get_value(attr);
attr_cast = (tcg_pts_attr_req_file_meas_t*)attr;
@@ -232,8 +235,8 @@ bool imc_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
if (valid_path && pts_error)
{
- attr = ietf_attr_pa_tnc_error_create(PEN_TCG,
- pts_error, attr_info);
+ error_code = pen_type_create(PEN_TCG, pts_error);
+ attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
attr_list->insert_last(attr_list, attr);
break;
}
@@ -244,8 +247,9 @@ bool imc_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
if (delimiter != SOLIDUS_UTF && delimiter != REVERSE_SOLIDUS_UTF)
{
- attr = ietf_attr_pa_tnc_error_create(PEN_TCG,
- TCG_PTS_INVALID_DELIMITER, attr_info);
+ error_code = pen_type_create(PEN_TCG,
+ TCG_PTS_INVALID_DELIMITER);
+ attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
attr_list->insert_last(attr_list, attr);
break;
}
@@ -254,8 +258,9 @@ bool imc_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
DBG2(DBG_IMC, "measurement request %d for %s '%s'",
request_id, is_directory ? "directory" : "file",
pathname);
- measurements = pts->do_measurements(pts, request_id,
- pathname, is_directory);
+ measurements = pts_file_meas_create_from_path(request_id,
+ pathname, is_directory, TRUE,
+ pts->get_meas_algorithm(pts));
if (!measurements)
{
/* TODO handle error codes from measurements */
@@ -273,6 +278,7 @@ bool imc_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
bool is_directory;
u_int8_t delimiter;
pts_file_meta_t *metadata;
+ pen_type_t error_code;
attr_info = attr->get_value(attr);
attr_cast = (tcg_pts_attr_req_file_meta_t*)attr;
@@ -283,8 +289,8 @@ bool imc_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
valid_path = pts->is_path_valid(pts, pathname, &pts_error);
if (valid_path && pts_error)
{
- attr = ietf_attr_pa_tnc_error_create(PEN_TCG,
- pts_error, attr_info);
+ error_code = pen_type_create(PEN_TCG, pts_error);
+ attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
attr_list->insert_last(attr_list, attr);
break;
}
@@ -294,8 +300,9 @@ bool imc_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
}
if (delimiter != SOLIDUS_UTF && delimiter != REVERSE_SOLIDUS_UTF)
{
- attr = ietf_attr_pa_tnc_error_create(PEN_TCG,
- TCG_PTS_INVALID_DELIMITER, attr_info);
+ error_code = pen_type_create(PEN_TCG,
+ TCG_PTS_INVALID_DELIMITER);
+ attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
attr_list->insert_last(attr_list, attr);
break;
}
@@ -323,6 +330,7 @@ bool imc_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
pts_comp_func_name_t *name;
pts_comp_evidence_t *evid;
pts_component_t *comp;
+ pen_type_t error_code;
u_int32_t depth;
u_int8_t flags;
status_t status;
@@ -342,32 +350,36 @@ bool imc_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
if (flags & PTS_REQ_FUNC_COMP_EVID_TTC)
{
- attr = ietf_attr_pa_tnc_error_create(PEN_TCG,
- TCG_PTS_UNABLE_DET_TTC, attr_info);
+ error_code = pen_type_create(PEN_TCG,
+ TCG_PTS_UNABLE_DET_TTC);
+ attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
attr_list->insert_last(attr_list, attr);
break;
}
if (flags & PTS_REQ_FUNC_COMP_EVID_VER &&
!(negotiated_caps & PTS_PROTO_CAPS_V))
{
- attr = ietf_attr_pa_tnc_error_create(PEN_TCG,
- TCG_PTS_UNABLE_LOCAL_VAL, attr_info);
+ error_code = pen_type_create(PEN_TCG,
+ TCG_PTS_UNABLE_LOCAL_VAL);
+ attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
attr_list->insert_last(attr_list, attr);
break;
}
if (flags & PTS_REQ_FUNC_COMP_EVID_CURR &&
!(negotiated_caps & PTS_PROTO_CAPS_C))
{
- attr = ietf_attr_pa_tnc_error_create(PEN_TCG,
- TCG_PTS_UNABLE_CUR_EVID, attr_info);
+ error_code = pen_type_create(PEN_TCG,
+ TCG_PTS_UNABLE_CUR_EVID);
+ attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
attr_list->insert_last(attr_list, attr);
break;
}
if (flags & PTS_REQ_FUNC_COMP_EVID_PCR &&
!(negotiated_caps & PTS_PROTO_CAPS_T))
{
- attr = ietf_attr_pa_tnc_error_create(PEN_TCG,
- TCG_PTS_UNABLE_DET_PCR, attr_info);
+ error_code = pen_type_create(PEN_TCG,
+ TCG_PTS_UNABLE_DET_PCR);
+ attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
attr_list->insert_last(attr_list, attr);
break;
}
@@ -377,17 +389,19 @@ bool imc_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
"support sub component measurements");
return FALSE;
}
- comp = pts_components->create(pts_components, name, depth, NULL);
+ comp = attestation_state->create_component(attestation_state,
+ name, depth);
if (!comp)
{
DBG2(DBG_IMC, " not registered: no evidence provided");
continue;
}
- /* do the component evidence measurement[s] */
+ /* do the component evidence measurement[s] and cache them */
do
{
- status = comp->measure(comp, pts, &evid);
+ status = comp->measure(comp, name->get_qualifier(name),
+ pts, &evid);
if (status == FAILED)
{
break;
@@ -395,7 +409,6 @@ bool imc_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
attestation_state->add_evidence(attestation_state, evid);
}
while (status == NEED_MORE);
- comp->destroy(comp);
}
e->destroy(e);
break;
@@ -408,12 +421,9 @@ bool imc_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
chunk_t pcr_composite, quote_sig;
bool use_quote2;
- /* Send buffered Simple Component Evidences */
+ /* Send cached Component Evidence entries */
while (attestation_state->next_evidence(attestation_state, &evid))
{
- pts->select_pcr(pts, evid->get_extended_pcr(evid));
-
- /* Send Simple Component Evidence */
attr = tcg_pts_attr_simple_comp_evid_create(evid);
attr_list->insert_last(attr_list, attr);
}
diff --git a/src/libpts/plugins/imc_attestation/imc_attestation_state.c b/src/libpts/plugins/imc_attestation/imc_attestation_state.c
index 72a55f60e..8ebabafa2 100644
--- a/src/libpts/plugins/imc_attestation/imc_attestation_state.c
+++ b/src/libpts/plugins/imc_attestation/imc_attestation_state.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -15,10 +15,15 @@
#include "imc_attestation_state.h"
+#include <libpts.h>
+
+#include <tncif_names.h>
+
#include <utils/linked_list.h>
#include <debug.h>
typedef struct private_imc_attestation_state_t private_imc_attestation_state_t;
+typedef struct func_comp_t func_comp_t;
/**
* Private data of an imc_attestation_state_t object.
@@ -41,6 +46,11 @@ struct private_imc_attestation_state_t {
TNC_ConnectionState state;
/**
+ * Assessment/Evaluation Result
+ */
+ TNC_IMV_Evaluation_Result result;
+
+ /**
* Does the TNCCS connection support long message types?
*/
bool has_long;
@@ -51,12 +61,22 @@ struct private_imc_attestation_state_t {
bool has_excl;
/**
+ * Maximum PA-TNC message size for this TNCCS connection
+ */
+ u_int32_t max_msg_len;
+
+ /**
* PTS object
*/
pts_t *pts;
/**
- * PTS Component Evidence list
+ * List of Functional Components
+ */
+ linked_list_t *components;
+
+ /**
+ * Functional Component Evidence cache list
*/
linked_list_t *list;
@@ -87,18 +107,52 @@ METHOD(imc_state_t, set_flags, void,
this->has_excl = has_excl;
}
+METHOD(imc_state_t, set_max_msg_len, void,
+ private_imc_attestation_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_attestation_state_t *this)
+{
+ return this->max_msg_len;
+}
+
METHOD(imc_state_t, change_state, void,
private_imc_attestation_state_t *this, TNC_ConnectionState new_state)
{
this->state = new_state;
}
+METHOD(imc_state_t, set_result, void,
+ private_imc_attestation_state_t *this, TNC_IMCID id,
+ TNC_IMV_Evaluation_Result result)
+{
+ DBG1(DBG_IMC, "set assessment result for IMC %u to '%N'",
+ id, TNC_IMV_Evaluation_Result_names, result);
+ this->result = result;
+}
+
+METHOD(imc_state_t, get_result, bool,
+ private_imc_attestation_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_attestation_state_t *this)
{
this->pts->destroy(this->pts);
- this->list->destroy_offset(this->list, offsetof(pts_comp_evidence_t, destroy));
+ this->components->destroy_offset(this->components,
+ offsetof(pts_component_t, destroy));
+ this->list->destroy_offset(this->list,
+ offsetof(pts_comp_evidence_t, destroy));
free(this);
}
@@ -108,10 +162,42 @@ METHOD(imc_attestation_state_t, get_pts, pts_t*,
return this->pts;
}
+METHOD(imc_attestation_state_t, create_component, pts_component_t*,
+ private_imc_attestation_state_t *this, pts_comp_func_name_t *name,
+ u_int32_t depth)
+{
+ enumerator_t *enumerator;
+ pts_component_t *component;
+ bool found = FALSE;
+
+ enumerator = this->components->create_enumerator(this->components);
+ while (enumerator->enumerate(enumerator, &component))
+ {
+ if (name->equals(name, component->get_comp_func_name(component)))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!found)
+ {
+ component = pts_components->create(pts_components, name, depth, NULL);
+ if (!component)
+ {
+ return NULL;
+ }
+ this->components->insert_last(this->components, component);
+
+ }
+ return component;
+}
+
METHOD(imc_attestation_state_t, add_evidence, void,
- private_imc_attestation_state_t *this, pts_comp_evidence_t *evidence)
+ private_imc_attestation_state_t *this, pts_comp_evidence_t *evid)
{
- this->list->insert_last(this->list, evidence);
+ this->list->insert_last(this->list, evid);
}
METHOD(imc_attestation_state_t, next_evidence, bool,
@@ -135,16 +221,23 @@ imc_state_t *imc_attestation_state_create(TNC_ConnectionID 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,
.change_state = _change_state,
+ .set_result = _set_result,
+ .get_result = _get_result,
.destroy = _destroy,
},
.get_pts = _get_pts,
+ .create_component = _create_component,
.add_evidence = _add_evidence,
.next_evidence = _next_evidence,
},
.connection_id = connection_id,
.state = TNC_CONNECTION_STATE_CREATE,
+ .result = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
.pts = pts_create(TRUE),
+ .components = linked_list_create(),
.list = linked_list_create(),
);
diff --git a/src/libpts/plugins/imc_attestation/imc_attestation_state.h b/src/libpts/plugins/imc_attestation/imc_attestation_state.h
index 22b0bba23..e4fca71bb 100644
--- a/src/libpts/plugins/imc_attestation/imc_attestation_state.h
+++ b/src/libpts/plugins/imc_attestation/imc_attestation_state.h
@@ -24,6 +24,7 @@
#include <imc/imc_state.h>
#include <pts/pts.h>
+#include <pts/components/pts_component.h>
#include <pts/components/pts_comp_evidence.h>
#include <library.h>
@@ -47,14 +48,24 @@ struct imc_attestation_state_t {
pts_t* (*get_pts)(imc_attestation_state_t *this);
/**
- * Add an entry to the Component Evidence list
+ * Create and add an entry to the list of Functional Components
*
- * @param entry Component Evidence entry
+ * @param name Component Functional Name
+ * @param depth Sub-component Depth
+ * @return created functional component instance or NULL
*/
- void (*add_evidence)(imc_attestation_state_t *this, pts_comp_evidence_t *entry);
+ pts_component_t* (*create_component)(imc_attestation_state_t *this,
+ pts_comp_func_name_t *name, u_int32_t depth);
/**
- * Removes next Component Evidence entry from list and returns it
+ * Add an entry to the Component Evidence cache list
+ *
+ * @param evid Component Evidence entry
+ */
+ void (*add_evidence)(imc_attestation_state_t *this, pts_comp_evidence_t *evid);
+
+ /**
+ * Removes next entry from the Component Evidence cache list and returns it
*
* @param evid Next Component Evidence entry
* @return TRUE if next entry is available
diff --git a/src/libpts/plugins/imv_attestation/Makefile.am b/src/libpts/plugins/imv_attestation/Makefile.am
index a550a3552..5e7465195 100644
--- a/src/libpts/plugins/imv_attestation/Makefile.am
+++ b/src/libpts/plugins/imv_attestation/Makefile.am
@@ -31,3 +31,5 @@ attest_LDADD = \
$(top_builddir)/src/libpts/libpts.la \
$(top_builddir)/src/libstrongswan/libstrongswan.la
attest.o : $(top_builddir)/config.status
+
+EXTRA_DIST = build-database.sh
diff --git a/src/libpts/plugins/imv_attestation/Makefile.in b/src/libpts/plugins/imv_attestation/Makefile.in
index 989a173b5..afb4abed7 100644
--- a/src/libpts/plugins/imv_attestation/Makefile.in
+++ b/src/libpts/plugins/imv_attestation/Makefile.in
@@ -51,6 +51,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -94,7 +95,7 @@ attest_OBJECTS = $(am_attest_OBJECTS)
attest_DEPENDENCIES = $(top_builddir)/src/libimcv/libimcv.la \
$(top_builddir)/src/libpts/libpts.la \
$(top_builddir)/src/libstrongswan/libstrongswan.la
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -120,6 +121,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -214,11 +216,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -235,11 +240,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -255,6 +261,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -264,7 +271,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -321,6 +327,7 @@ attest_LDADD = \
$(top_builddir)/src/libpts/libpts.la \
$(top_builddir)/src/libstrongswan/libstrongswan.la
+EXTRA_DIST = build-database.sh
all: all-am
.SUFFIXES:
diff --git a/src/libpts/plugins/imv_attestation/attest.c b/src/libpts/plugins/imv_attestation/attest.c
index 9200820e8..a202d128f 100644
--- a/src/libpts/plugins/imv_attestation/attest.c
+++ b/src/libpts/plugins/imv_attestation/attest.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
+ * Copyright (C) 2011-2012 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -34,7 +34,7 @@
/**
* global debug output variables
*/
-static int debug_level = 2;
+static int debug_level = 1;
static bool stderr_quiet = TRUE;
/**
@@ -131,9 +131,14 @@ static void do_args(int argc, char *argv[])
{ "directory", required_argument, NULL, 'D' },
{ "dir", required_argument, NULL, 'D' },
{ "file", required_argument, NULL, 'F' },
+ { "sha1-ima", no_argument, NULL, 'I' },
{ "key", required_argument, NULL, 'K' },
{ "owner", required_argument, NULL, 'O' },
{ "product", required_argument, NULL, 'P' },
+ { "relative", no_argument, NULL, 'R' },
+ { "rel", no_argument, NULL, 'R' },
+ { "sequence", required_argument, NULL, 'S' },
+ { "seq", required_argument, NULL, 'S' },
{ "sha1", no_argument, NULL, '1' },
{ "sha256", no_argument, NULL, '2' },
{ "sha384", no_argument, NULL, '3' },
@@ -232,6 +237,9 @@ static void do_args(int argc, char *argv[])
exit(EXIT_FAILURE);
}
continue;
+ case 'I':
+ attest->set_algo(attest, PTS_MEAS_ALGO_SHA1_IMA);
+ continue;
case 'K':
{
chunk_t aik;
@@ -252,6 +260,12 @@ static void do_args(int argc, char *argv[])
exit(EXIT_FAILURE);
}
continue;
+ case 'R':
+ attest->set_relative(attest);
+ continue;
+ case 'S':
+ attest->set_sequence(attest, atoi(optarg));
+ continue;
case '1':
attest->set_algo(attest, PTS_MEAS_ALGO_SHA1);
continue;
diff --git a/src/libpts/plugins/imv_attestation/attest_db.c b/src/libpts/plugins/imv_attestation/attest_db.c
index 88d19eee1..55afbf701 100644
--- a/src/libpts/plugins/imv_attestation/attest_db.c
+++ b/src/libpts/plugins/imv_attestation/attest_db.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
+ * Copyright (C) 2011-2012 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -16,8 +16,14 @@
#include "attest_db.h"
#include "libpts.h"
+#include "pts/pts_meas_algo.h"
+#include "pts/pts_file_meas.h"
#include "pts/components/pts_comp_func_name.h"
+#include <libgen.h>
+
+#define IMA_MAX_NAME_LEN 255
+
typedef struct private_attest_db_t private_attest_db_t;
/**
@@ -106,6 +112,16 @@ struct private_attest_db_t {
bool product_set;
/**
+ * TRUE if relative filenames are to be used
+ */
+ bool relative;
+
+ /**
+ * Sequence number for ordering entries
+ */
+ int seq_no;
+
+ /**
* File measurement hash algorithm
*/
pts_meas_algorithms_t algo;
@@ -175,7 +191,7 @@ METHOD(attest_db_t, set_component, bool,
e = this->db->query(this->db,
"SELECT id FROM components "
"WHERE vendor_id = ? AND name = ? AND qualifier = ?",
- DB_INT, vid, DB_INT, name, DB_INT, qualifier, DB_INT);
+ DB_UINT, vid, DB_INT, name, DB_INT, qualifier, DB_INT);
if (e)
{
if (e->enumerate(e, &this->cid))
@@ -231,7 +247,7 @@ METHOD(attest_db_t, set_cid, bool,
e = this->db->query(this->db, "SELECT vendor_id, name, qualifier "
"FROM components WHERE id = ?",
- DB_INT, cid, DB_INT, DB_INT, DB_INT);
+ DB_UINT, cid, DB_INT, DB_INT, DB_INT);
if (e)
{
if (e->enumerate(e, &vid, &name, &qualifier))
@@ -252,6 +268,7 @@ METHOD(attest_db_t, set_directory, bool,
private_attest_db_t *this, char *dir, bool create)
{
enumerator_t *e;
+ size_t len;
if (this->dir_set)
{
@@ -259,6 +276,13 @@ METHOD(attest_db_t, set_directory, bool,
return FALSE;
}
free(this->dir);
+
+ /* remove trailing '/' character */
+ len = strlen(dir);
+ if (len && dir[len-1] == '/')
+ {
+ dir[len-1] = '\0';
+ }
this->dir = strdup(dir);
e = this->db->query(this->db,
@@ -308,7 +332,7 @@ METHOD(attest_db_t, set_did, bool,
this->did = did;
e = this->db->query(this->db, "SELECT path FROM files WHERE id = ?",
- DB_INT, did, DB_TEXT);
+ DB_UINT, did, DB_TEXT);
if (e)
{
if (e->enumerate(e, &dir))
@@ -330,6 +354,7 @@ METHOD(attest_db_t, set_file, bool,
private_attest_db_t *this, char *file, bool create)
{
enumerator_t *e;
+ char *filename;
if (this->file_set)
{
@@ -337,9 +362,10 @@ METHOD(attest_db_t, set_file, bool,
return FALSE;
}
this->file = strdup(file);
+ filename = this->relative ? basename(file) : file;
e = this->db->query(this->db, "SELECT id FROM files WHERE path = ?",
- DB_TEXT, file, DB_INT);
+ DB_TEXT, filename, DB_INT);
if (e)
{
if (e->enumerate(e, &this->fid))
@@ -362,9 +388,9 @@ METHOD(attest_db_t, set_file, bool,
/* Add a new database entry */
this->file_set = this->db->execute(this->db, &this->fid,
"INSERT INTO files (type, path) VALUES (0, ?)",
- DB_TEXT, file) == 1;
+ DB_TEXT, filename) == 1;
- printf("file '%s' %sinserted into database\n", file,
+ printf("file '%s' %sinserted into database\n", filename,
this->file_set ? "" : "could not be ");
return this->file_set;
@@ -384,7 +410,7 @@ METHOD(attest_db_t, set_fid, bool,
this->fid = fid;
e = this->db->query(this->db, "SELECT path FROM files WHERE id = ?",
- DB_INT, fid, DB_TEXT);
+ DB_UINT, fid, DB_TEXT);
if (e)
{
if (e->enumerate(e, &file))
@@ -468,7 +494,7 @@ METHOD(attest_db_t, set_kid, bool,
this->kid = kid;
e = this->db->query(this->db, "SELECT keyid, owner FROM keys WHERE id = ?",
- DB_INT, kid, DB_BLOB, DB_TEXT);
+ DB_UINT, kid, DB_BLOB, DB_TEXT);
if (e)
{
if (e->enumerate(e, &key, &owner))
@@ -545,7 +571,7 @@ METHOD(attest_db_t, set_pid, bool,
this->pid = pid;
e = this->db->query(this->db, "SELECT name FROM products WHERE id = ?",
- DB_INT, pid, DB_TEXT);
+ DB_UINT, pid, DB_TEXT);
if (e)
{
if (e->enumerate(e, &product))
@@ -568,6 +594,18 @@ METHOD(attest_db_t, set_algo, void,
this->algo = algo;
}
+METHOD(attest_db_t, set_relative, void,
+ private_attest_db_t *this)
+{
+ this->relative = TRUE;
+}
+
+METHOD(attest_db_t, set_sequence, void,
+ private_attest_db_t *this, int seq_no)
+{
+ this->seq_no = seq_no;
+}
+
METHOD(attest_db_t, set_owner, void,
private_attest_db_t *this, char *owner)
{
@@ -580,16 +618,29 @@ METHOD(attest_db_t, list_components, void,
{
enumerator_t *e;
pts_comp_func_name_t *cfn;
- int cid, vid, name, qualifier, count = 0;
+ int seq_no, cid, vid, name, qualifier, count = 0;
if (this->kid)
{
e = this->db->query(this->db,
- "SELECT c.id, c.vendor_id, c.name, c.qualifier "
+ "SELECT kc.seq_no, c.id, c.vendor_id, c.name, c.qualifier "
"FROM components AS c "
"JOIN key_component AS kc ON c.id = kc.component "
- "WHERE kc.key = ? ORDER BY c.vendor_id, c.name, c.qualifier",
- DB_INT, this->kid, DB_INT, DB_INT, DB_INT, DB_INT);
+ "WHERE kc.key = ? ORDER BY kc.seq_no",
+ DB_UINT, this->kid, DB_INT, DB_INT, DB_INT, DB_INT, DB_INT);
+ if (e)
+ {
+ while (e->enumerate(e, &cid, &seq_no, &vid, &name, &qualifier))
+ {
+ cfn = pts_comp_func_name_create(vid, name, qualifier);
+ printf("%4d: #%-2d %s\n", seq_no, cid, print_cfn(cfn));
+ cfn->destroy(cfn);
+ count++;
+ }
+ e->destroy(e);
+ printf("%d component%s found for key %#B\n", count,
+ (count == 1) ? "" : "s", &this->key);
+ }
}
else
{
@@ -597,24 +648,18 @@ METHOD(attest_db_t, list_components, void,
"SELECT id, vendor_id, name, qualifier FROM components "
"ORDER BY vendor_id, name, qualifier",
DB_INT, DB_INT, DB_INT, DB_INT);
- }
- if (e)
- {
- while (e->enumerate(e, &cid, &vid, &name, &qualifier))
- {
- cfn = pts_comp_func_name_create(vid, name, qualifier);
- printf("%3d: %s\n", cid, print_cfn(cfn));
- cfn->destroy(cfn);
- count++;
- }
- e->destroy(e);
-
- printf("%d component%s found", count, (count == 1) ? "" : "s");
- if (this->key_set)
+ if (e)
{
- printf(" for key %#B", &this->key);
+ while (e->enumerate(e, &cid, &vid, &name, &qualifier))
+ {
+ cfn = pts_comp_func_name_create(vid, name, qualifier);
+ printf("%4d: %s\n", cid, print_cfn(cfn));
+ cfn->destroy(cfn);
+ count++;
+ }
+ e->destroy(e);
+ printf("%d component%s found\n", count, (count == 1) ? "" : "s");
}
- printf("\n");
}
}
@@ -632,12 +677,12 @@ METHOD(attest_db_t, list_keys, void,
"SELECT k.id, k.keyid, k.owner FROM keys AS k "
"JOIN key_component AS kc ON k.id = kc.key "
"WHERE kc.component = ? ORDER BY k.keyid",
- DB_INT, this->cid, DB_INT, DB_BLOB, DB_TEXT);
+ DB_UINT, this->cid, DB_INT, DB_BLOB, DB_TEXT);
if (e)
{
while (e->enumerate(e, &kid, &keyid, &owner))
{
- printf("%3d: %#B '%s'\n", kid, &keyid, owner);
+ printf("%4d: %#B '%s'\n", kid, &keyid, owner);
count++;
}
e->destroy(e);
@@ -652,7 +697,7 @@ METHOD(attest_db_t, list_keys, void,
{
while (e->enumerate(e, &kid, &keyid, &owner))
{
- printf("%3d: %#B '%s'\n", kid, &keyid, owner);
+ printf("%4d: %#B '%s'\n", kid, &keyid, owner);
count++;
}
e->destroy(e);
@@ -681,13 +726,13 @@ METHOD(attest_db_t, list_files, void,
"FROM files AS f "
"JOIN product_file AS pf ON f.id = pf.file "
"WHERE pf.product = ? ORDER BY f.path",
- DB_INT, this->pid, DB_INT, DB_INT, DB_TEXT, DB_INT, DB_INT);
+ DB_UINT, this->pid, DB_INT, DB_INT, DB_TEXT, DB_INT, DB_INT);
if (e)
{
while (e->enumerate(e, &fid, &type, &file, &meas, &meta))
{
type = (type < 0 || type > 2) ? 0 : type;
- printf("%3d: |%s%s| %s %s\n", fid, meas ? "M":" ", meta ? "T":" ",
+ printf("%4d: |%s%s| %s %s\n", fid, meas ? "M":" ", meta ? "T":" ",
file_type[type], file);
count++;
}
@@ -705,7 +750,7 @@ METHOD(attest_db_t, list_files, void,
while (e->enumerate(e, &fid, &type, &file))
{
type = (type < 0 || type > 2) ? 0 : type;
- printf("%3d: %s %s\n", fid, file_type[type], file);
+ printf("%4d: %s %s\n", fid, file_type[type], file);
count++;
}
e->destroy(e);
@@ -734,12 +779,12 @@ METHOD(attest_db_t, list_products, void,
"FROM products AS p "
"JOIN product_file AS pf ON p.id = pf.product "
"WHERE pf.file = ? ORDER BY p.name",
- DB_INT, this->fid, DB_INT, DB_TEXT, DB_INT, DB_INT);
+ DB_UINT, this->fid, DB_INT, DB_TEXT, DB_INT, DB_INT);
if (e)
{
while (e->enumerate(e, &pid, &product, &meas, &meta))
{
- printf("%3d: |%s%s| %s\n", pid, meas ? "M":" ", meta ? "T":" ",
+ printf("%4d: |%s%s| %s\n", pid, meas ? "M":" ", meta ? "T":" ",
product);
count++;
}
@@ -755,7 +800,7 @@ METHOD(attest_db_t, list_products, void,
{
while (e->enumerate(e, &pid, &product))
{
- printf("%3d: %s\n", pid, product);
+ printf("%4d: %s\n", pid, product);
count++;
}
e->destroy(e);
@@ -785,7 +830,7 @@ static void get_directory(private_attest_db_t *this, int did, char **directory)
{
e = this->db->query(this->db,
"SELECT path from files WHERE id = ?",
- DB_INT, did, DB_TEXT);
+ DB_UINT, did, DB_TEXT);
if (e)
{
if (e->enumerate(e, &dir))
@@ -826,17 +871,17 @@ METHOD(attest_db_t, list_hashes, void,
{
if (this->fid != fid_old)
{
- printf("%3d: %s%s%s\n", this->fid, this->dir,
+ printf("%4d: %s%s%s\n", this->fid, this->dir,
slash(this->dir, this->file) ? "/" : "", this->file);
fid_old = this->fid;
}
- printf(" %#B\n", &hash);
+ printf(" %#B\n", &hash);
count++;
}
e->destroy(e);
printf("%d %N value%s found for product '%s'\n", count,
- hash_algorithm_names, pts_meas_algo_to_hash(this->algo),
+ pts_meas_algorithm_names, this->algo,
(count == 1) ? "" : "s", this->product);
}
}
@@ -848,7 +893,7 @@ METHOD(attest_db_t, list_hashes, void,
"JOIN files AS f ON f.id = fh.file "
"WHERE fh.algo = ? AND fh.product = ? "
"ORDER BY fh.directory, f.path",
- DB_INT, this->algo, DB_INT, this->pid,
+ DB_INT, this->algo, DB_UINT, this->pid,
DB_INT, DB_TEXT, DB_BLOB, DB_INT);
if (e)
{
@@ -860,18 +905,18 @@ METHOD(attest_db_t, list_hashes, void,
{
get_directory(this, did, &dir);
}
- printf("%3d: %s%s%s\n", fid,
+ printf("%4d: %s%s%s\n", fid,
dir, slash(dir, file) ? "/" : "", file);
fid_old = fid;
did_old = did;
}
- printf(" %#B\n", &hash);
+ printf(" %#B\n", &hash);
count++;
}
e->destroy(e);
printf("%d %N value%s found for product '%s'\n", count,
- hash_algorithm_names, pts_meas_algo_to_hash(this->algo),
+ pts_meas_algorithm_names, this->algo,
(count == 1) ? "" : "s", this->product);
}
}
@@ -883,7 +928,7 @@ METHOD(attest_db_t, list_hashes, void,
"JOIN products AS p ON p.id = fh.product "
"WHERE fh.algo = ? AND fh.file = ? AND fh.directory = ?"
"ORDER BY p.name",
- DB_INT, this->algo, DB_INT, this->fid, DB_INT, this->did,
+ DB_INT, this->algo, DB_UINT, this->fid, DB_UINT, this->did,
DB_TEXT, DB_BLOB, DB_INT);
if (e)
{
@@ -895,7 +940,7 @@ METHOD(attest_db_t, list_hashes, void,
e->destroy(e);
printf("%d %N value%s found for file '%s%s%s'\n",
- count, hash_algorithm_names, pts_meas_algo_to_hash(this->algo),
+ count, pts_meas_algorithm_names, this->algo,
(count == 1) ? "" : "s", this->dir,
slash(this->dir, this->file) ? "/" : "", this->file);
}
@@ -922,17 +967,17 @@ METHOD(attest_db_t, list_hashes, void,
get_directory(this, did, &dir);
did_old = did;
}
- printf("%3d: %s%s%s\n", fid,
+ printf("%4d: %s%s%s\n", fid,
dir, slash(dir, file) ? "/" : "", file);
fid_old = fid;
}
- printf(" %#B '%s'\n", &hash, product);
+ printf(" %#B '%s'\n", &hash, product);
count++;
}
e->destroy(e);
- printf("%d %N value%s found\n", count, hash_algorithm_names,
- pts_meas_algo_to_hash(this->algo), (count == 1) ? "" : "s");
+ printf("%d %N value%s found\n", count, pts_meas_algorithm_names,
+ this->algo, (count == 1) ? "" : "s");
}
}
free(dir);
@@ -956,7 +1001,7 @@ METHOD(attest_db_t, list_measurements, void,
"JOIN keys AS k ON k.id = ch.key "
"WHERE ch.algo = ? AND ch.key = ? AND ch.component = ? "
"ORDER BY seq_no",
- DB_INT, this->algo, DB_INT, this->kid, DB_INT, this->cid,
+ DB_INT, this->algo, DB_UINT, this->kid, DB_UINT, this->cid,
DB_INT, DB_INT, DB_BLOB, DB_TEXT);
if (e)
{
@@ -964,16 +1009,16 @@ METHOD(attest_db_t, list_measurements, void,
{
if (this->kid != kid_old)
{
- printf("%3d: %#B '%s'\n", this->kid, &this->key, owner);
+ printf("%4d: %#B '%s'\n", this->kid, &this->key, owner);
kid_old = this->kid;
}
- printf("%5d %02d %#B\n", seq_no, pcr, &hash);
+ printf("%7d %02d %#B\n", seq_no, pcr, &hash);
count++;
}
e->destroy(e);
printf("%d %N value%s found for component '%s'\n", count,
- hash_algorithm_names, pts_meas_algo_to_hash(this->algo),
+ pts_meas_algorithm_names, this->algo,
(count == 1) ? "" : "s", print_cfn(this->cfn));
}
}
@@ -985,7 +1030,7 @@ METHOD(attest_db_t, list_measurements, void,
"JOIN keys AS k ON k.id = ch.key "
"WHERE ch.algo = ? AND ch.component = ? "
"ORDER BY keyid, seq_no",
- DB_INT, this->algo, DB_INT, this->cid,
+ DB_INT, this->algo, DB_UINT, this->cid,
DB_INT, DB_INT, DB_BLOB, DB_INT, DB_BLOB, DB_TEXT);
if (e)
{
@@ -993,16 +1038,16 @@ METHOD(attest_db_t, list_measurements, void,
{
if (kid != kid_old)
{
- printf("%3d: %#B '%s'\n", kid, &keyid, owner);
+ printf("%4d: %#B '%s'\n", kid, &keyid, owner);
kid_old = kid;
}
- printf("%5d %02d %#B\n", seq_no, pcr, &hash);
+ printf("%7d %02d %#B\n", seq_no, pcr, &hash);
count++;
}
e->destroy(e);
printf("%d %N value%s found for component '%s'\n", count,
- hash_algorithm_names, pts_meas_algo_to_hash(this->algo),
+ pts_meas_algorithm_names, this->algo,
(count == 1) ? "" : "s", print_cfn(this->cfn));
}
@@ -1016,7 +1061,7 @@ METHOD(attest_db_t, list_measurements, void,
"JOIN components AS c ON c.id = ch.component "
"WHERE ch.algo = ? AND ch.key = ? "
"ORDER BY vendor_id, name, qualifier, seq_no",
- DB_INT, this->algo, DB_INT, this->kid, DB_INT, DB_INT, DB_BLOB,
+ DB_INT, this->algo, DB_UINT, this->kid, DB_INT, DB_INT, DB_BLOB,
DB_INT, DB_INT, DB_INT, DB_INT);
if (e)
{
@@ -1026,7 +1071,7 @@ METHOD(attest_db_t, list_measurements, void,
if (cid != cid_old)
{
cfn = pts_comp_func_name_create(vid, name, qualifier);
- printf("%3d: %s\n", cid, print_cfn(cfn));
+ printf("%4d: %s\n", cid, print_cfn(cfn));
cfn->destroy(cfn);
cid_old = cid;
}
@@ -1036,25 +1081,189 @@ METHOD(attest_db_t, list_measurements, void,
e->destroy(e);
printf("%d %N value%s found for key %#B '%s'\n", count,
- hash_algorithm_names, pts_meas_algo_to_hash(this->algo),
+ pts_meas_algorithm_names, this->algo,
(count == 1) ? "" : "s", &this->key, this->owner);
}
}
}
+bool insert_file_hash(private_attest_db_t *this, pts_meas_algorithms_t algo,
+ chunk_t measurement, int fid, int did, bool ima,
+ int *hashes_added)
+{
+ enumerator_t *e;
+ chunk_t hash;
+ char *label;
+
+ label = "could not be created";
+
+ e = this->db->query(this->db,
+ "SELECT hash FROM file_hashes WHERE algo = ? "
+ "AND file = ? AND directory = ? AND product = ? and key = 0",
+ DB_INT, algo, DB_UINT, fid, DB_UINT, did, DB_UINT, this->pid, DB_BLOB);
+ if (!e)
+ {
+ printf("file_hashes query failed\n");
+ return FALSE;
+ }
+ if (e->enumerate(e, &hash))
+ {
+ label = chunk_equals(measurement, hash) ?
+ "exists and equals" : "exists and differs";
+ }
+ else
+ {
+ if (this->db->execute(this->db, NULL,
+ "INSERT INTO file_hashes "
+ "(file, directory, product, key, algo, hash) "
+ "VALUES (?, ?, ?, 0, ?, ?)",
+ DB_UINT, fid, DB_UINT, did, DB_UINT, this->pid,
+ DB_INT, algo, DB_BLOB, measurement) == 1)
+ {
+ label = "created";
+ (*hashes_added)++;
+ }
+ }
+ e->destroy(e);
+
+ printf(" %#B - %s%s\n", &measurement, ima ? "ima - " : "", label);
+ return TRUE;
+}
+
METHOD(attest_db_t, add, bool,
private_attest_db_t *this)
{
bool success = FALSE;
+ /* add key/component pair */
if (this->kid && this->cid)
{
success = this->db->execute(this->db, NULL,
- "INSERT INTO key_component (key, component) VALUES (?, ?)",
- DB_UINT, this->kid, DB_UINT, this->cid) == 1;
+ "INSERT INTO key_component (key, component, seq_no) "
+ "VALUES (?, ?, ?)",
+ DB_UINT, this->kid, DB_UINT, this->cid,
+ DB_UINT, this->seq_no) == 1;
- printf("key/component pair (%d/%d) %sinserted into database\n",
- this->kid, this->cid, success ? "" : "could not be ");
+ printf("key/component pair (%d/%d) %sinserted into database at "
+ "position %d\n", this->kid, this->cid,
+ success ? "" : "could not be ", this->seq_no);
+
+ return success;
+ }
+
+ /* add directory or file measurement for a given product */
+ if ((this->did || this->fid) && this->pid)
+ {
+ char *pathname, *filename, *label;
+ char ima_buffer[IMA_MAX_NAME_LEN + 1];
+ chunk_t measurement, ima_template;
+ pts_file_meas_t *measurements;
+ hasher_t *hasher = NULL;
+ bool ima = FALSE;
+ int fid, did;
+ int files_added = 0, hashes_added = 0, ima_hashes_added = 0;
+ enumerator_t *enumerator, *e;
+
+ if (this->algo == PTS_MEAS_ALGO_SHA1_IMA)
+ {
+ ima = TRUE;
+ this->algo = PTS_MEAS_ALGO_SHA1;
+ hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+ if (!hasher)
+ {
+ printf("could not create hasher\n");
+ return FALSE;
+ }
+ }
+
+ pathname = this->did ? this->dir : this->file;
+ measurements = pts_file_meas_create_from_path(0, pathname, this->did,
+ this->relative, this->algo);
+ if (!measurements)
+ {
+ printf("file measurement failed\n");
+ DESTROY_IF(hasher);
+ return FALSE;
+ }
+ if (this->fid && this->relative)
+ {
+ set_directory(this, dirname(pathname), TRUE);
+ }
+ did = this->relative ? this->did : 0;
+
+ enumerator = measurements->create_enumerator(measurements);
+ while (enumerator->enumerate(enumerator, &filename, &measurement))
+ {
+ /* retrieve or create filename */
+ label = "could not be created";
+
+ e = this->db->query(this->db,
+ "SELECT id FROM files WHERE path = ?",
+ DB_TEXT, filename, DB_INT);
+ if (!e)
+ {
+ printf("files query failed\n");
+ break;
+ }
+ if (e->enumerate(e, &fid))
+ {
+ label = "exists";
+ }
+ else
+ {
+ if (this->db->execute(this->db, &fid,
+ "INSERT INTO files (type, path) VALUES (0, ?)",
+ DB_TEXT, filename) == 1)
+ {
+ label = "created";
+ files_added++;
+ }
+ }
+ e->destroy(e);
+
+ printf("%4d: %s - %s\n", fid, filename, label);
+
+ /* compute file measurement hash */
+ if (!insert_file_hash(this, this->algo, measurement,
+ fid, did, FALSE, &hashes_added))
+ {
+ break;
+ }
+
+ if (!ima)
+ {
+ continue;
+ }
+
+ /* compute IMA template hash */
+ strncpy(ima_buffer, filename, IMA_MAX_NAME_LEN);
+ ima_buffer[IMA_MAX_NAME_LEN] = '\0';
+ ima_template = chunk_create(ima_buffer, sizeof(ima_buffer));
+ if (!hasher->get_hash(hasher, measurement, NULL) ||
+ !hasher->get_hash(hasher, ima_template, measurement.ptr))
+ {
+ printf("could not compute IMA template hash\n");
+ break;
+ }
+ if (!insert_file_hash(this, PTS_MEAS_ALGO_SHA1_IMA, measurement,
+ fid, did, TRUE, &ima_hashes_added))
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ printf("%d measurements, added %d new files, %d new file hashes",
+ measurements->get_file_count(measurements),
+ files_added, hashes_added);
+ if (ima)
+ {
+ printf(" , %d new ima hashes", ima_hashes_added);
+ hasher->destroy(hasher);
+ }
+ printf("\n");
+ measurements->destroy(measurements);
+ success = TRUE;
}
return success;
}
@@ -1064,12 +1273,42 @@ METHOD(attest_db_t, delete, bool,
{
bool success;
+ /* delete a file measurement hash for a given product */
+ if (this->algo && this->pid && this->fid)
+ {
+ success = this->db->execute(this->db, NULL,
+ "DELETE FROM file_hashes "
+ "WHERE algo = ? AND product = ? "
+ "AND file = ? AND directory = ?",
+ DB_UINT, this->algo, DB_UINT, this->pid,
+ DB_UINT, this->fid, DB_UINT, this->did) > 0;
+
+ printf("%4d: %s%s%s\n", this->fid, this->dir, this->did ? "/":"",
+ this->file);
+ printf("%N value for product '%s' %sdeleted from database\n",
+ pts_meas_algorithm_names, this->algo, this->product,
+ success ? "" : "could not be ");
+
+ return success;
+ }
+
+ /* delete product/file entries */
if (this->pid && (this->fid || this->did))
{
- printf("deletion of product/file entries not supported yet\n");
- return FALSE;
+ success = this->db->execute(this->db, NULL,
+ "DELETE FROM product_file "
+ "WHERE product = ? AND file = ?",
+ DB_UINT, this->pid,
+ DB_UINT, this->fid ? this->fid : this->did) > 0;
+
+ printf("product/file pair (%d/%d) %sdeleted from database\n",
+ this->pid, this->fid ? this->fid : this->did,
+ success ? "" : "could not be ");
+
+ return success;
}
+ /* delete key/component pair */
if (this->kid && this->cid)
{
success = this->db->execute(this->db, NULL,
@@ -1173,6 +1412,8 @@ attest_db_t *attest_db_create(char *uri)
.set_product = _set_product,
.set_pid = _set_pid,
.set_algo = _set_algo,
+ .set_relative = _set_relative,
+ .set_sequence = _set_sequence,
.set_owner = _set_owner,
.list_products = _list_products,
.list_files = _list_files,
@@ -1185,7 +1426,6 @@ attest_db_t *attest_db_create(char *uri)
.destroy = _destroy,
},
.dir = strdup(""),
- .algo = PTS_MEAS_ALGO_SHA256,
.db = lib->db->create(lib->db, uri),
);
diff --git a/src/libpts/plugins/imv_attestation/attest_db.h b/src/libpts/plugins/imv_attestation/attest_db.h
index 9c9a9dcba..e32a368d8 100644
--- a/src/libpts/plugins/imv_attestation/attest_db.h
+++ b/src/libpts/plugins/imv_attestation/attest_db.h
@@ -126,6 +126,21 @@ struct attest_db_t {
void (*set_algo)(attest_db_t *this, pts_meas_algorithms_t algo);
/**
+ * Set that the IMA-specific SHA-1 template hash be computed
+ */
+ void (*set_ima)(attest_db_t *this);
+
+ /**
+ * Set that relative filenames are to be used
+ */
+ void (*set_relative)(attest_db_t *this);
+
+ /**
+ * Set the sequence number
+ */
+ void (*set_sequence)(attest_db_t *this, int seq_no);
+
+ /**
* Set owner [user/host] of an AIK
*
* @param owner user/host name
diff --git a/src/libpts/plugins/imv_attestation/attest_usage.c b/src/libpts/plugins/imv_attestation/attest_usage.c
index e58f821e0..f7040f7ad 100644
--- a/src/libpts/plugins/imv_attestation/attest_usage.c
+++ b/src/libpts/plugins/imv_attestation/attest_usage.c
@@ -40,7 +40,7 @@ Usage:\n\
Show a list of measurement hashes for a given software product or\n\
its primary key as an optional selector.\n\
\n\
- ipsec attest --hashes [--sha1|--sha256|--sha384] [--file <path>|--fid <id>]\n\
+ ipsec attest --hashes [--sha1|--sha1-ima|--sha256|--sha384] [--file <path>|--fid <id>]\n\
Show a list of measurement hashes for a given file or\n\
its primary key as an optional selector.\n\
\n\
@@ -52,11 +52,11 @@ Usage:\n\
Show a list of AIK key digests with a component or\n\
its primary key as an optional selector.\n\
\n\
- ipsec attest --measurements [--sha1|--sha256|--sha384] [--component <cfn>|--cid <id>]\n\
+ ipsec attest --measurements --sha1|--sha256|--sha384 [--component <cfn>|--cid <id>]\n\
Show a list of component measurements for a given component or\n\
its primary key as an optional selector.\n\
\n\
- ipsec attest --measurements [--sha1|--sha256|--sha384] [--key <digest>|--kid <id>|--aik <path>]\n\
+ ipsec attest --measurements --sha1|--sha256|--sha384 [--key <digest>|--kid <id>|--aik <path>]\n\
Show a list of component measurements for a given AIK or\n\
its primary key as an optional selector.\n\
\n\
@@ -67,14 +67,31 @@ Usage:\n\
ipsec attest --add [--owner <name>] --key <digest>|--aik <path>\n\
Add an AIK public key digest entry preceded by an optional owner name\n\
\n\
+ ipsec attest --add --product <name>|--pid <id> --sha1|--sha1-ima|--sha256|--sha384\n\
+ [--relative|--rel] --dir <path>|--file <path>\n\
+ Add hashes of a single file or all files in a directory under absolute or relative filenames\n\
+ \n\
+ ipsec attest --add --key <digest|--kid <id> --component <cfn>|--cid <id> --sequence <no>|--seq <no>\n\
+ Add an ordered key/component entry\n\
+ \n\
ipsec attest --del --file <path>|--fid <id>|--dir <path>|--did <id>\n\
Delete a file or directory entry referenced either by value or primary key\n\
\n\
ipsec attest --del --product <name>|--pid <id>|--component <cfn>|--cid <id>\n\
Delete a product or component entry referenced either by value or primary key\n\
\n\
+ ipsec attest --del --product <name>|--pid <id> --file <path>|--fid <id>|--dir <path>|--did <id>\n\
+ Delete a product/file entry referenced either by value or primary key\n\
+ \n\
ipsec attest --del --key <digest>|--kid <id>|--aik <path>\n\
Delete an AIK entry referenced either by value or primary key\n\
+ \n\
+ ipsec attest --del --key <digest|--kid <id> --component <cfn>|--cid <id>\n\
+ Delete a key/component entry\n\
+ \n\
+ ipsec attest --del --product <name>|--pid <id> --sha1|--sha1-ima|--sha256|--sha384\n\
+ [--dir <path>|--did <id>] --file <path>|--fid <id>\n\
+ Delete a file hash given an absolute or relative filename\n\
\n");
}
diff --git a/src/libpts/plugins/imv_attestation/build-database.sh b/src/libpts/plugins/imv_attestation/build-database.sh
new file mode 100755
index 000000000..a89258e1d
--- /dev/null
+++ b/src/libpts/plugins/imv_attestation/build-database.sh
@@ -0,0 +1,221 @@
+#!/bin/sh
+
+p="Ubuntu 12.04.1 LTS i686"
+
+ipsec attest --add --product "$p" --sha1-ima --dir /sbin
+ipsec attest --add --product "$p" --sha1-ima --dir /usr/sbin
+ipsec attest --add --product "$p" --sha1-ima --dir /bin
+ipsec attest --add --product "$p" --sha1-ima --dir /usr/bin
+ipsec attest --add --product "$p" --sha1-ima --dir /etc/acpi
+ipsec attest --add --product "$p" --sha1-ima --file /etc/init.d/rc
+ipsec attest --add --product "$p" --sha1-ima --file /etc/init.d/rcS
+ipsec attest --add --product "$p" --sha1-ima --dir /etc/network/if-post-down.d
+ipsec attest --add --product "$p" --sha1-ima --dir /etc/network/if-pre-up.d
+ipsec attest --add --product "$p" --sha1-ima --dir /etc/network/if-up.d
+ipsec attest --add --product "$p" --sha1-ima --file /etc/NetworkManager/dispatcher.d/01ifupdown
+ipsec attest --add --product "$p" --sha1-ima --dir /etc/ppp/ip-down.d
+ipsec attest --add --product "$p" --sha1-ima --dir /etc/rc2.d
+ipsec attest --add --product "$p" --sha1-ima --dir /etc/rcS.d
+ipsec attest --add --product "$p" --sha1-ima --file /etc/rc.local
+ipsec attest --add --product "$p" --sha1-ima --dir /etc/resolvconf/update.d
+ipsec attest --add --product "$p" --sha1-ima --file /etc/resolvconf/update-libc.d/avahi-daemon
+ipsec attest --add --product "$p" --sha1-ima --dir /etc/update-motd.d
+ipsec attest --add --product "$p" --sha1-ima --file /lib/crda/setregdomain
+ipsec attest --add --product "$p" --sha1-ima --file /lib/init/apparmor-profile-load
+ipsec attest --add --product "$p" --sha1-ima --file /lib/resolvconf/list-records
+ipsec attest --add --product "$p" --sha1-ima --dir /lib/udev
+ipsec attest --add --product "$p" --sha1-ima --file /lib/ufw/ufw-init
+ipsec attest --add --product "$p" --sha1-ima --file /opt/Adobe/Reader9/Reader/intellinux/bin/acroread
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/accountsservice/accounts-daemon
+ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/apt/methods
+ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/at-spi2-core
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/avahi/avahi-daemon-check-dns.sh
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/bamf/bamfdaemon
+ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/ConsoleKit
+ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/ConsoleKit/run-seat.d
+ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/ConsoleKit/run-session.d
+ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/cups/notifier
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/dconf/dconf-service
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/dbus-1.0/dbus-daemon-launch-helper
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/deja-dup/deja-dup/deja-dup-monitor
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/evolution/3.2/evolution-alarm-notify
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/firefox/firefox
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/firefox/plugin-container
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/gcc/i686-linux-gnu/4.6/cc1
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/gcc/i686-linux-gnu/4.6/collect2
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/geoclue/geoclue-master
+ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/git-core
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/gnome-desktop3/check_gl_texture_size
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/gnome-disk-utility/gdu-notification-daemon
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/gnome-online-accounts/goa-daemon
+ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/gnome-settings-daemon
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/gnome-user-share/gnome-user-share
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/gnome-screensaver/gnome-screensaver-dialog
+ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/gvfs
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/gvfs//gvfs-fuse-daemon
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/i386-linux-gnu/colord/colord
+ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/i386-linux-gnu/gconf
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/indicator-application/indicator-application-service
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/indicator-appmenu/hud-service
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/indicator-datetime/indicator-datetime-service
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/indicator-messages/indicator-messages-service
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/indicator-printers/indicator-printers-service
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/indicator-session/indicator-session-service
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/indicator-sound/indicator-sound-service
+ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/lightdm
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/NetworkManager/nm-dhcp-client.action
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/NetworkManager/nm-dispatcher.action
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/notify-osd/notify-osd
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/nux/unity_support_test
+ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/pm-utils/power.d
+ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/pm-utils/sleep.d
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/policykit-1/polkitd
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/policykit-1-gnome/polkit-gnome-authentication-agent-1
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/pulseaudio/pulse/gconf-helper
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/rtkit/rtkit-daemon
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/system-service/system-service-d
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/telepathy/mission-control-5
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/thunderbird/thunderbird
+ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/ubuntuone-client
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/ubuntu-geoip/ubuntu-geoip-provider
+ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/ubuntu-sso-client
+ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/udisks
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/unity/unity-panel-service
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/unity-lens-applications/unity-applications-daemon
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/unity-lens-files/unity-files-daemon
+ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/unity-lens-music
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/unity-lens-video/unity-lens-video
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/unity-scope-video-remote/unity-scope-video-remote
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/update-manager/release-upgrade-motd
+ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/update-notifier
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/upower/upowerd
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/libvte-2.90-9/gnome-pty-helper
+ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/zeitgeist/zeitgeist-fts
+ipsec attest --add --product "$p" --sha1-ima --file /usr/share/apport/apport
+ipsec attest --add --product "$p" --sha1-ima --file /usr/share/apport/apport-checkreports
+ipsec attest --add --product "$p" --sha1-ima --file /usr/share/apport/apport-gtk
+ipsec attest --add --product "$p" --sha1-ima --dir /usr/share/language-tools
+ipsec attest --add --product "$p" --sha1-ima --file /usr/share/virtualbox/VBoxCreateUSBNode.sh
+ipsec attest --add --product "$p" --sha1-ima --relative --file /etc/ld.so.cache
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /lib
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /lib/i386-linux-gnu
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /lib/i386-linux-gnu/security
+for file in `find /lib/modules/3.2.21ima/kernel -name *.ko`
+do
+ipsec attest --add --product "$p" --sha1-ima --relative --file $file
+done
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /lib/plymouth
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /lib/plymouth/renderers
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /lib/security
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /opt/Adobe/Reader9/Reader/intellinux/lib
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/apache2/modules
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/compiz
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/compizconfig/backends/
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/enchant
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/evolution/3.2/libemiscwidgets.so.0.0.0
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/evolution/3.2/libeutil.so.0.0.0
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/evolution/3.2/libgnomecanvas.so.0.0.0
+for file in /usr/lib/firefox/*.so
+do
+ipsec attest --add --product "$p" --sha1-ima --relative --file $file
+done
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/firefox/components/libbrowsercomps.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/firefox/components/libdbusservice.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/firefox/components/libmozgnome.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/firefox-addons/extensions/globalmenu@ubuntu.com/components/libglobalmenu.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/firefox-addons/plugins/nppdf.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/flashplugin-installer/libflashplayer.so
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/gedit/plugins
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/gnome-bluetooth
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/gnome-settings-daemon-3.0
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/gtk-2.0/2.10.0/menuproxies
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/gtk-3.0/3.0.0/menuproxies
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/gtk-3.0/3.0.0/theming-engines
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/alsa-lib
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/dri
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/gconf/2
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/gconv
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/gio/modules
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/gtk-2.0/modules
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/gtk-2.0/2.10.0/engines
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/gtk-2.0/2.10.0/immodules
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/gtk-3.0/modules
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/gtk-3.0/3.0.0/immodules
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/gvfs
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/libcanberra-0.28
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/mesa
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/mit-krb5
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/openssl-1.0.0/engines
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/pango/1.6.0/modules
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/pkcs11
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/polkit-1/extensions
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/nss
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/sane
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/sse2
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/indicators3/7
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/indicator-messages/status-providers/1
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/libpeas-1.0/loaders
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/man-db/libman-2.6.1.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/man-db/libmandb-2.6.1.so
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/mission-control-plugins.0
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/ModemManager
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/nautilus/extensions-3.0
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/NetworkManager/libnm-settings-plugin-ifupdown.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/perl/5.14.2/auto/File/Glob/Glob.so
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/pulse-1.1/modules
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/python2.7/lib-dynload
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/apt_inst.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/apt_pkg.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/cairo/_cairo.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/dbus/mainloop/qt.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/_dbus_bindings.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/_dbus_glib_bindings.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/duplicity/_librsync.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gi/_gi.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gi/_gobject/_gobject.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gi/_glib/_glib.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/glib/_glib.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gobject/_gobject.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gtk-2.0/atk.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gtk-2.0/gtk/_gtk.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gtk-2.0/gio/_gio.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gtk-2.0/gio/unix.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gtk-2.0/pango.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gtk-2.0/pangocairo.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gtk-2.0/pynotify/_pynotify.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/OpenSSL/crypto.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/OpenSSL/rand.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/OpenSSL/SSL.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/PyQt4/QtCore.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/simplejson/_speedups.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/sip.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/twisted/internet/_sigchld.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/twisted/python/_initgroups.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/xapian/_xapian.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/zope/interface/_zope_interface_coptimizations.so
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/rsyslog
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/sane
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/sse2
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/sudo
+for file in /usr/lib/thunderbird/*.so
+do
+ipsec attest --add --product "$p" --sha1-ima --relative --file $file
+done
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/thunderbird/components/libdbusservice.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/thunderbird/components/libmozgnome.so
+ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/thunderbird-addons/extensions/globalmenu@ubuntu.com/components/libglobalmenu.so
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/xorg/modules
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/xorg/modules/drivers
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/xorg/modules/extensions
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/xorg/modules/input
+ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/share/fonts/truetype/ubuntu-font-family
+ipsec attest --del --product "$p" --sha1 --file /lib/resolvconf/list-records
+ipsec attest --del --product "$p" --sha1-ima --file /lib/resolvconf/list-records
+ipsec attest --del --product "$p" --sha1 --file /usr/bin/lsb_release
+ipsec attest --del --product "$p" --sha1-ima --file /usr/bin/lsb_release
+ipsec attest --del --product "$p" --sha1 --file /usr/share/language-tools/language-options
+ipsec attest --del --product "$p" --sha1-ima --file /usr/share/language-tools/language-options
+
diff --git a/src/libpts/plugins/imv_attestation/data.sql b/src/libpts/plugins/imv_attestation/data.sql
index e6e03627a..b1646b724 100644
--- a/src/libpts/plugins/imv_attestation/data.sql
+++ b/src/libpts/plugins/imv_attestation/data.sql
@@ -42,6 +42,18 @@ INSERT INTO products (
'Ubuntu 11.10 i686'
);
+INSERT INTO products (
+ name
+) VALUES (
+ 'Ubuntu 12.04 LTS i686'
+);
+
+INSERT INTO products (
+ name
+) VALUES (
+ 'Ubuntu 12.04.1 LTS i686'
+);
+
/* Files */
INSERT INTO files ( /* 1 */
@@ -83,7 +95,7 @@ INSERT INTO files (
INSERT INTO files (
type, path
) VALUES (
- 1, '/lib/xtables/'
+ 1, '/lib/xtables'
);
INSERT INTO files (
@@ -176,6 +188,19 @@ INSERT INTO files (
0, '/etc/tnc_config'
);
+INSERT INTO files (
+ type, path
+) VALUES (
+ 0, '/lib/libxtables.so.7'
+);
+
+INSERT INTO files (
+ type, path
+) VALUES (
+ 0, '/sbin/xtables-multi'
+);
+
+
/* Product-File */
INSERT INTO product_file (
@@ -388,6 +413,48 @@ INSERT INTO product_file (
7, 22, 1
);
+INSERT INTO product_file (
+ product, file, measurement
+) VALUES (
+ 8, 1, 1
+);
+
+INSERT INTO product_file (
+ product, file, measurement
+) VALUES (
+ 8, 7, 1
+);
+
+INSERT INTO product_file (
+ product, file, metadata
+) VALUES (
+ 8, 22, 1
+);
+
+INSERT INTO product_file (
+ product, file, measurement
+) VALUES (
+ 8, 23, 1
+);
+
+INSERT INTO product_file (
+ product, file, measurement
+) VALUES (
+ 8, 24, 1
+);
+
+INSERT INTO product_file (
+ product, file, measurement
+) VALUES (
+ 9, 1, 1
+);
+
+INSERT INTO product_file (
+ product, file, metadata
+) VALUES (
+ 9, 22, 1
+);
+
/* File Hashes */
INSERT INTO file_hashes (
@@ -429,6 +496,42 @@ INSERT INTO file_hashes (
INSERT INTO file_hashes (
file, product, algo, hash
) VALUES (
+ 1, 8, 32768, X'9c3ed3179990c0ffb3a65b75a09b61faa4aca907'
+);
+
+INSERT INTO file_hashes (
+ file, product, algo, hash
+) VALUES (
+ 1, 8, 16384, X'af474dd532c9f2d85c12368334eda3609a7c6287e08940f078547ab0f2871c94'
+);
+
+INSERT INTO file_hashes (
+ file, product, algo, hash
+) VALUES (
+ 1, 8, 8192, X'a23fa7034dabdce2d10f2893d52b21d14fe24c6ae4c8570fb6c7190228046e4c064c4d29d736cd84ca42a3d9abf9bfde'
+);
+
+INSERT INTO file_hashes (
+ file, product, algo, hash
+) VALUES (
+ 1, 9, 32768, X'9c3ed3179990c0ffb3a65b75a09b61faa4aca907'
+);
+
+INSERT INTO file_hashes (
+ file, product, algo, hash
+) VALUES (
+ 1, 9, 16384, X'af474dd532c9f2d85c12368334eda3609a7c6287e08940f078547ab0f2871c94'
+);
+
+INSERT INTO file_hashes (
+ file, product, algo, hash
+) VALUES (
+ 1, 9, 8192, X'a23fa7034dabdce2d10f2893d52b21d14fe24c6ae4c8570fb6c7190228046e4c064c4d29d736cd84ca42a3d9abf9bfde'
+);
+
+INSERT INTO file_hashes (
+ file, product, algo, hash
+) VALUES (
2, 2, 32768, X'2a4047437e6fb346e2d854fc415e16b80e75bf6b'
);
@@ -736,6 +839,24 @@ INSERT INTO file_hashes (
INSERT INTO file_hashes (
file, directory, product, algo, hash
) VALUES (
+ 8, 7, 8, 32768, X'a93f870078b69ba530e6335eaee698908b12078f'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
+ 8, 7, 8, 16384, X'0c31c1f41a57f4b15fafeb541de475e6da88380c911bb606b35413fda8428006'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
+ 8, 7, 8, 8192, X'bb8fc7073691910d315621de176be64316923782df8d836b384414fd9a3d293be5bea51811ee6ef68a497f12384bba42'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
8, 21, 6, 32768, X'010873de0d682a26e1c6795dd4992248cc47cdd1'
);
@@ -808,6 +929,24 @@ INSERT INTO file_hashes (
INSERT INTO file_hashes (
file, directory, product, algo, hash
) VALUES (
+ 9, 7, 8, 32768, X'225836cb243c3502d90c92c3eb54310403303270'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
+ 9, 7, 8, 16384, X'7862ed16eeb35d2f10e6d416a6fcbe8000ba1bbc2daddd15f43b375686308d7d'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
+ 9, 7, 8, 8192, X'd4b6b939d0fdcd84bbc66fbf9bd044a61de823b4acb52e0ead7ae7f955d9b2d6399da1f673eadbb4792b819923e5e845'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
9, 21, 6, 32768, X'e1df4f3949b09c25e15b9c9b7088a60d683903a8'
);
@@ -862,6 +1001,24 @@ INSERT INTO file_hashes (
INSERT INTO file_hashes (
file, directory, product, algo, hash
) VALUES (
+ 10, 7, 8, 32768, X'008374e704c81351c333a214f4ee2d89e996f344'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
+ 10, 7, 8, 16384, X'0e28034f99a3e0cdffa64bf126858afb48ee25b5cbfc70bbcd997bab7ef1e056'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
+ 10, 7, 8, 8192, X'b6e01ba0706e48ce37abef3fbc59a45fd50c7abd3bb7950b1d892bc4a0db3f9784f573d74ef51376267183d26513d1d0'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
10, 21, 6, 32768, X'87df2d01b85d8354819b431bae0a0a65bfc5d2db'
);
@@ -916,6 +1073,24 @@ INSERT INTO file_hashes (
INSERT INTO file_hashes (
file, directory, product, algo, hash
) VALUES (
+ 11, 7, 8, 32768, X'105fc70c5ecde30ebe841ac0a229b77b6d5f3d8a'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
+ 11, 7, 8, 16384, X'e4cdc17b835eabe06d719bccada0e59d3ee5eb3759ca75eb9c037166e8dafd30'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
+ 11, 7, 8, 8192, X'a9f6a18ff6f85208583e0b3fdd2fdafc4575baf5d973c7a831ce74d8bb5a24b8ae8e4504ddefa4a2c2b91f31cd68edea'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
12, 7, 1, 32768, X'6c0b2df4fc4c9122b5762ae140d53fdd1cf9e89b'
);
@@ -952,6 +1127,24 @@ INSERT INTO file_hashes (
INSERT INTO file_hashes (
file, directory, product, algo, hash
) VALUES (
+ 12, 7, 8, 32768, X'a9d8ea0203810d269b3ef3d974fed2ac4d486bae'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
+ 12, 7, 8, 16384, X'c071aedaa6f66f8ab45ce037d72bbc42fb1894ac69ab689ad21ce6ff0c1c5d6a'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
+ 12, 7, 8, 8192, X'1612eb51a3be3fcba24808326e29967b6f798c5140aefc8279601c5f5600030148fd01e8fbe737fba9c3972832e67601'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
13, 7, 1, 32768, X'e2f7b92abda769f82796f57a29801870585dcea3'
);
@@ -988,6 +1181,24 @@ INSERT INTO file_hashes (
INSERT INTO file_hashes (
file, directory, product, algo, hash
) VALUES (
+ 13, 7, 8, 32768, X'da655441bf10f7dc32978474c77903f2f9120cc4'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
+ 13, 7, 8, 16384, X'ec6a4bb332af51cf60cc30ce95197a8c89d42e6135d6e0d4e1d9e4bcc88e838c'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
+ 13, 7, 8, 8192, X'135a84e988f219d5bcd7cb4e7ada6f9239c0164a0021262be0c4f9c00d8bece341aa88e0e35011b195c737e438225f4b'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
14, 7, 1, 32768, X'160d2b04d11eb225fb148615b699081869e15b6c'
);
@@ -1024,6 +1235,24 @@ INSERT INTO file_hashes (
INSERT INTO file_hashes (
file, directory, product, algo, hash
) VALUES (
+ 14, 7, 8, 32768, X'7b401b741cc32bcc86c3eac43059c9dd26e99a40'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
+ 14, 7, 8, 16384, X'9a7cf37befecc40b494f9176bb887dd478e72c750fed8d540e5d7bbf4b5f2765'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
+ 14, 7, 8, 8192, X'161c2f502f10a72ef159b6308219c38cb13387e21645e4357e6934d7afc62727cd76fd518dc6f676e2db47125eb9a2f6'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
15, 7, 1, 32768, X'5a0d07ab036603a76759e5f61f7d04f2d3c056cc'
);
@@ -1060,6 +1289,24 @@ INSERT INTO file_hashes (
INSERT INTO file_hashes (
file, directory, product, algo, hash
) VALUES (
+ 15, 7, 8, 32768, X'129f6ecfb596fd751e33209b2ad2a28f2d243fdc'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
+ 15, 7, 8, 16384, X'2fd1e8874b2faf18973881af54bd3e1fd21aaa8ee181313919569715885e69bc'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
+ 15, 7, 8, 8192, X'3862f52ec823474ccfffeb6ead7c6a18b132057018704cb2fa05b08aaee3a1abfaf0eb4c826348f427dfbbb5b3e56647'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
16, 7, 1, 32768, X'd6c8dfbaae7ab28b5cef2626a2af3f99a6ea4365'
);
@@ -1094,6 +1341,24 @@ INSERT INTO file_hashes (
);
INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
+ 16, 7, 8, 32768, X'2b686cd8359dea842cfdcacf39d22f5e0e6d06f2'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
+ 16, 7, 8, 16384, X'e14fb3f87b9539108e023660f2d7b4fc728b0622a85de89bdc1fe20162f200a3'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
+ 16, 7, 8, 8192, X'6f55292ad4061b0575dca0a3e6abe5f86d5288e0b860e6f76715bd5c9df8b5f751bc547d3147e9da12593b56a3f83252'
+);
+
+INSERT INTO file_hashes (
file, product, algo, hash
) VALUES (
17, 1, 32768, X'8a7c41167bc0fcc1dec8329a868ba265c23857f5'
@@ -1186,6 +1451,24 @@ INSERT INTO file_hashes (
INSERT INTO file_hashes (
file, directory, product, algo, hash
) VALUES (
+ 18, 7, 8, 32768, X'9ff04217b3b40cb328440e40b6dc1c283f9f71ec'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
+ 18, 7, 8, 16384, X'76de3b5b8df6d685e522aeea01d79ac457808437c02d40eb2e6ff06098057d41'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
+ 18, 7, 8, 8192, X'ca1c0f6e3516f82a40cbaaea84dd42a8c97cea6b729dc07343f18a5d1b898a94e861b0dfb574c3efad64c363bb07ebf5'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
19, 7, 1, 32768, X'd537d437f058136eb3d7be517dbe7647b623c619'
);
@@ -1222,6 +1505,24 @@ INSERT INTO file_hashes (
INSERT INTO file_hashes (
file, directory, product, algo, hash
) VALUES (
+ 19, 7, 8, 32768, X'b3d6df204cc27f59704c19ab501172892a9c7c5d'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
+ 19, 7, 8, 16384, X'9168ba26a67a3daf0ad3ea956d88358235ebb968b95f91bd110eab34ba75e4f8'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
+ 19, 7, 8, 8192, X'e3a69702f9d07ea6e1f7cb85157f3d76d7e7dc577fd48ca7f6cf8f917ca7e5015e0f7dd463e1229aebf18aabcfd39cc3'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
20, 7, 1, 32768, X'f9e3531abb67a020cf667d46ca823675dd0a0dd4'
);
@@ -1255,6 +1556,60 @@ INSERT INTO file_hashes (
20, 7, 7, 8192, X'84200bd318bb022915150842ddf4002e061ef593604ad0d07021dc662cc40bfa749cce084ddf25d0e5137f6380f613d8'
);
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
+ 20, 7, 8, 32768, X'8696176c12bf8291b6b9989ec5c94c3fdf26b14f'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
+ 20, 7, 8, 16384, X'e7b5896d1dbe17f501f20424e8ed7d2de14d79e984e0c0a032ea70ca2f44e83a'
+);
+
+INSERT INTO file_hashes (
+ file, directory, product, algo, hash
+) VALUES (
+ 20, 7, 8, 8192, X'0d87fb31cf84b57b5b872af0b5e65610df929e48877f5ea199c073da6087c7a0e4b4c186545f654bb5db94284fde6274'
+);
+
+INSERT INTO file_hashes (
+ file, product, algo, hash
+) VALUES (
+ 23, 8, 32768, X'a67433717c2b9e2a9293f15a88456efbf7998a84'
+);
+
+INSERT INTO file_hashes (
+ file, product, algo, hash
+) VALUES (
+ 23, 8, 16384, X'1453d3ceaea4043cecd34f1eb24e0fbbe9fe04978077d06a0f728de849e71365'
+);
+
+INSERT INTO file_hashes (
+ file, product, algo, hash
+) VALUES (
+ 23, 8, 8192, X'abd1134f68a2daf92183aeae372f970cb076164468d4df08b8cb53743cae0867c17231e8f087e3367b6ec6905eb03c16'
+);
+
+INSERT INTO file_hashes (
+ file, product, algo, hash
+) VALUES (
+ 24, 8, 32768, X'bc3f9d1edeb00192c5c040a53823b58642ed8f41'
+);
+
+INSERT INTO file_hashes (
+ file, product, algo, hash
+) VALUES (
+ 24, 8, 16384, X'78f76b5c274705d09cd73cfad04791b8009c56d00849a00613909a659dc9ac63'
+);
+
+INSERT INTO file_hashes (
+ file, product, algo, hash
+) VALUES (
+ 24, 8, 8192, X'52cea5a859d0a1e06ffa8c1fc4f7b8dffde2de99915d660b2d3756315efdd873bee67ba3732f2c1ec692c38a8780cd72'
+);
+
/* AIKs */
INSERT INTO keys (
@@ -1280,7 +1635,13 @@ INSERT INTO components (
INSERT INTO components (
vendor_id, name, qualifier
) VALUES (
- 36906, 3, 33 /* ITA IMA */
+ 36906, 3, 33 /* ITA IMA - Trusted Platform */
+);
+
+INSERT INTO components (
+ vendor_id, name, qualifier
+) VALUES (
+ 36906, 3, 34 /* ITA IMA - Operating System */
);
/* AIK Component */
@@ -1288,18 +1649,18 @@ INSERT INTO components (
INSERT INTO key_component (
key, component, depth, seq_no
) VALUES (
- 2, 2, 0, 1
+ 1, 3, 0, 1
);
INSERT INTO key_component (
key, component, depth, seq_no
) VALUES (
- 1, 3, 0, 1
+ 1, 2, 0, 2
);
INSERT INTO key_component (
key, component, depth, seq_no
) VALUES (
- 1, 2, 0, 2
+ 1, 4, 0, 3
);
diff --git a/src/libpts/plugins/imv_attestation/imv_attestation.c b/src/libpts/plugins/imv_attestation/imv_attestation.c
index 51069b02d..201496e8a 100644
--- a/src/libpts/plugins/imv_attestation/imv_attestation.c
+++ b/src/libpts/plugins/imv_attestation/imv_attestation.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -168,13 +168,10 @@ TNC_Result TNC_IMV_NotifyConnectionChange(TNC_IMVID imv_id,
static TNC_Result send_message(TNC_ConnectionID connection_id)
{
- pa_tnc_msg_t *msg;
- pa_tnc_attr_t *attr;
+ linked_list_t *attr_list;
imv_state_t *state;
imv_attestation_state_t *attestation_state;
TNC_Result result;
- linked_list_t *attr_list;
- enumerator_t *enumerator;
if (!imv_attestation->get_state(imv_attestation, connection_id, &state))
{
@@ -188,21 +185,8 @@ static TNC_Result send_message(TNC_ConnectionID connection_id)
{
if (attr_list->get_count(attr_list))
{
- msg = pa_tnc_msg_create();
-
- /* move PA-TNC attributes to PA-TNC message */
- enumerator = attr_list->create_enumerator(attr_list);
- while (enumerator->enumerate(enumerator, &attr))
- {
- msg->add_attribute(msg, attr);
- }
- enumerator->destroy(enumerator);
-
- msg->build(msg);
result = imv_attestation->send_message(imv_attestation,
- connection_id, FALSE, 0, TNC_IMCID_ANY,
- msg->get_encoding(msg));
- msg->destroy(msg);
+ connection_id, FALSE, 0, TNC_IMCID_ANY, attr_list);
}
else
{
@@ -230,6 +214,7 @@ static TNC_Result receive_message(TNC_IMVID imv_id,
{
pa_tnc_msg_t *pa_tnc_msg;
pa_tnc_attr_t *attr;
+ pen_type_t type;
linked_list_t *attr_list;
imv_state_t *state;
imv_attestation_state_t *attestation_state;
@@ -271,31 +256,31 @@ static TNC_Result receive_message(TNC_IMVID imv_id,
enumerator = pa_tnc_msg->create_attribute_enumerator(pa_tnc_msg);
while (enumerator->enumerate(enumerator, &attr))
{
- if (attr->get_vendor_id(attr) == PEN_IETF)
+ type = attr->get_type(attr);
+
+ if (type.vendor_id == PEN_IETF)
{
- if (attr->get_type(attr) == IETF_ATTR_PA_TNC_ERROR)
+ if (type.type == IETF_ATTR_PA_TNC_ERROR)
{
ietf_attr_pa_tnc_error_t *error_attr;
- pen_t error_vendor_id;
- pa_tnc_error_code_t error_code;
+ pen_type_t error_code;
chunk_t msg_info;
error_attr = (ietf_attr_pa_tnc_error_t*)attr;
- error_vendor_id = error_attr->get_vendor_id(error_attr);
+ error_code = error_attr->get_error_code(error_attr);
- if (error_vendor_id == PEN_TCG)
+ if (error_code.vendor_id == PEN_TCG)
{
- error_code = error_attr->get_error_code(error_attr);
msg_info = error_attr->get_msg_info(error_attr);
DBG1(DBG_IMV, "received TCG-PTS error '%N'",
- pts_error_code_names, error_code);
+ pts_error_code_names, error_code.type);
DBG1(DBG_IMV, "error information: %B", &msg_info);
result = TNC_RESULT_FATAL;
}
}
- else if (attr->get_type(attr) == IETF_ATTR_PRODUCT_INFORMATION)
+ else if (type.type == IETF_ATTR_PRODUCT_INFORMATION)
{
ietf_attr_product_info_t *attr_cast;
char *platform_info;
@@ -305,7 +290,7 @@ static TNC_Result receive_message(TNC_IMVID imv_id,
pts->set_platform_info(pts, platform_info);
}
}
- else if (attr->get_vendor_id(attr) == PEN_TCG)
+ else if (type.vendor_id == PEN_TCG)
{
if (!imv_attestation_process(attr, attr_list, attestation_state,
supported_algorithms,supported_dh_groups, pts_db, pts_credmgr))
@@ -325,29 +310,14 @@ static TNC_Result receive_message(TNC_IMVID imv_id,
TNC_IMV_ACTION_RECOMMENDATION_ISOLATE,
TNC_IMV_EVALUATION_RESULT_ERROR);
return imv_attestation->provide_recommendation(imv_attestation,
- connection_id);
+ connection_id, src_imc_id);
}
if (attr_list->get_count(attr_list))
{
- pa_tnc_msg = pa_tnc_msg_create();
-
- /* move PA-TNC attributes to PA-TNC message */
- enumerator = attr_list->create_enumerator(attr_list);
- while (enumerator->enumerate(enumerator, &attr))
- {
- pa_tnc_msg->add_attribute(pa_tnc_msg, attr);
- }
- enumerator->destroy(enumerator);
-
- pa_tnc_msg->build(pa_tnc_msg);
result = imv_attestation->send_message(imv_attestation, connection_id,
- FALSE, 0, TNC_IMCID_ANY,
- pa_tnc_msg->get_encoding(pa_tnc_msg));
-
- pa_tnc_msg->destroy(pa_tnc_msg);
+ FALSE, 0, TNC_IMCID_ANY, attr_list);
attr_list->destroy(attr_list);
-
return result;
}
attr_list->destroy(attr_list);
@@ -360,7 +330,7 @@ static TNC_Result receive_message(TNC_IMVID imv_id,
TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
TNC_IMV_EVALUATION_RESULT_ERROR);
return imv_attestation->provide_recommendation(imv_attestation,
- connection_id);
+ connection_id, src_imc_id);
}
if (attestation_state->get_handshake_state(attestation_state) ==
@@ -372,12 +342,6 @@ static TNC_Result receive_message(TNC_IMVID imv_id,
attestation_state->get_file_meas_request_count(attestation_state));
attestation_state->set_measurement_error(attestation_state);
}
- if (attestation_state->get_component_count(attestation_state))
- {
- DBG1(DBG_IMV, "failure due to %d components waiting for evidence",
- attestation_state->get_component_count(attestation_state));
- attestation_state->set_measurement_error(attestation_state);
- }
if (attestation_state->get_measurement_error(attestation_state))
{
state->set_recommendation(state,
@@ -391,7 +355,7 @@ static TNC_Result receive_message(TNC_IMVID imv_id,
TNC_IMV_EVALUATION_RESULT_COMPLIANT);
}
return imv_attestation->provide_recommendation(imv_attestation,
- connection_id);
+ connection_id, src_imc_id);
}
return result;
@@ -446,7 +410,7 @@ TNC_Result TNC_IMV_SolicitRecommendation(TNC_IMVID imv_id,
return TNC_RESULT_NOT_INITIALIZED;
}
return imv_attestation->provide_recommendation(imv_attestation,
- connection_id);
+ connection_id, TNC_IMCID_ANY);
}
/**
diff --git a/src/libpts/plugins/imv_attestation/imv_attestation_build.c b/src/libpts/plugins/imv_attestation/imv_attestation_build.c
index 4f2cc1e95..23195d6e3 100644
--- a/src/libpts/plugins/imv_attestation/imv_attestation_build.c
+++ b/src/libpts/plugins/imv_attestation/imv_attestation_build.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -16,7 +16,6 @@
#include "imv_attestation_build.h"
#include "imv_attestation_state.h"
-#include <libpts.h>
#include <tcg/tcg_pts_attr_proto_caps.h>
#include <tcg/tcg_pts_attr_meas_algo.h>
#include <tcg/tcg_pts_attr_dh_nonce_params_req.h>
@@ -198,7 +197,13 @@ bool imv_attestation_build(linked_list_t *attr_list,
attr_list->insert_last(attr_list, attr);
}
enumerator->destroy(enumerator);
- break;
+
+ /* do we have any file metadata or measurement requests? */
+ if (attr_list->get_count(attr_list))
+ {
+ break;
+ }
+ /* fall through to next state */
}
case IMV_ATTESTATION_STATE_COMP_EVID:
{
@@ -252,15 +257,15 @@ bool imv_attestation_build(linked_list_t *attr_list,
comp_name = pts_comp_func_name_create(vid, name, qualifier);
comp_name->log(comp_name, " ");
- comp = pts_components->create(pts_components, comp_name,
- depth, pts_db);
+ comp = attestation_state->create_component(attestation_state,
+ comp_name, depth, pts_db);
if (!comp)
{
- DBG2(DBG_IMV, " not registered: removed from request");
+ DBG2(DBG_IMV, " not registered or duplicate"
+ " - removed from request");
comp_name->destroy(comp_name);
continue;
}
- attestation_state->add_component(attestation_state, comp);
if (first_component)
{
attr = tcg_pts_attr_req_func_comp_evid_create();
@@ -290,8 +295,11 @@ bool imv_attestation_build(linked_list_t *attr_list,
break;
}
case IMV_ATTESTATION_STATE_EVID_FINAL:
- attestation_state->set_handshake_state(attestation_state,
+ if (attestation_state->components_finalized(attestation_state))
+ {
+ attestation_state->set_handshake_state(attestation_state,
IMV_ATTESTATION_STATE_END);
+ }
break;
case IMV_ATTESTATION_STATE_END:
break;
diff --git a/src/libpts/plugins/imv_attestation/imv_attestation_process.c b/src/libpts/plugins/imv_attestation/imv_attestation_process.c
index a742b6697..37e9ac77a 100644
--- a/src/libpts/plugins/imv_attestation/imv_attestation_process.c
+++ b/src/libpts/plugins/imv_attestation/imv_attestation_process.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -41,11 +41,13 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
pts_database_t *pts_db,
credential_manager_t *pts_credmgr)
{
+ pen_type_t attr_type;
pts_t *pts;
-
+
pts = attestation_state->get_pts(attestation_state);
-
- switch (attr->get_type(attr))
+ attr_type = attr->get_type(attr);
+
+ switch (attr_type.type)
{
case TCG_PTS_PROTO_CAPS:
{
@@ -169,7 +171,7 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
KEY_ANY, aik->get_issuer(aik), FALSE);
while (e->enumerate(e, &issuer))
{
- if (aik->issued_by(aik, issuer))
+ if (aik->issued_by(aik, issuer, NULL))
{
trusted = TRUE;
break;
@@ -216,22 +218,29 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
DBG1(DBG_IMV, "measurement request %d returned %d file%s:",
request_id, file_count, (file_count == 1) ? "":"s");
- if (!attestation_state->check_off_file_meas_request(attestation_state,
- request_id, &file_id, &is_dir))
+ if (request_id)
{
- DBG1(DBG_IMV, " no entry found for file measurement request %d",
- request_id);
- break;
- }
+ if (!attestation_state->check_off_file_meas_request(
+ attestation_state, request_id, &file_id, &is_dir))
+ {
+ DBG1(DBG_IMV, " no entry found for file measurement "
+ "request %d", request_id);
+ break;
+ }
- /* check hashes from database against measurements */
- e_hash = pts_db->create_file_hash_enumerator(pts_db,
- platform_info, algo, file_id, is_dir);
- if (!measurements->verify(measurements, e_hash, is_dir))
+ /* check hashes from database against measurements */
+ e_hash = pts_db->create_file_hash_enumerator(pts_db,
+ platform_info, algo, file_id, is_dir);
+ if (!measurements->verify(measurements, e_hash, is_dir))
+ {
+ attestation_state->set_measurement_error(attestation_state);
+ }
+ e_hash->destroy(e_hash);
+ }
+ else
{
- attestation_state->set_measurement_error(attestation_state);
+ measurements->check(measurements, pts_db, platform_info, algo);
}
- e_hash->destroy(e_hash);
break;
}
case TCG_PTS_UNIX_FILE_META:
@@ -276,34 +285,22 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
pts_comp_evidence_t *evidence;
pts_component_t *comp;
u_int32_t depth;
- status_t status;
attr_cast = (tcg_pts_attr_simple_comp_evid_t*)attr;
evidence = attr_cast->get_comp_evidence(attr_cast);
name = evidence->get_comp_func_name(evidence, &depth);
- comp = attestation_state->check_off_component(attestation_state, name);
+ comp = attestation_state->get_component(attestation_state, name);
if (!comp)
{
DBG1(DBG_IMV, " no entry found for component evidence request");
break;
}
- status = comp->verify(comp, pts, evidence);
-
- switch (status)
+ if (comp->verify(comp, name->get_qualifier(name), pts,
+ evidence) != SUCCESS)
{
- default:
- case FAILED:
- attestation_state->set_measurement_error(attestation_state);
- comp->destroy(comp);
- break;
- case SUCCESS:
- name->log(name, " successfully measured ");
- comp->destroy(comp);
- break;
- case NEED_MORE:
- /* re-enter component into list */
- attestation_state->add_component(attestation_state, comp);
+ attestation_state->set_measurement_error(attestation_state);
+ name->log(name, " measurement mismatch for ");
}
break;
}
@@ -353,8 +350,11 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
DBG2(DBG_IMV, "TPM Quote Info signature verification successful");
free(quote_info.ptr);
- /* Finalize any pending measurement registrations */
- attestation_state->check_off_registrations(attestation_state);
+ /**
+ * Finalize any pending measurement registrations and check
+ * if all expected component measurements were received
+ */
+ attestation_state->finalize_components(attestation_state);
}
if (attr_cast->get_evid_sig(attr_cast, &evid_sig))
diff --git a/src/libpts/plugins/imv_attestation/imv_attestation_state.c b/src/libpts/plugins/imv_attestation/imv_attestation_state.c
index a58fd3ec3..1dbc88309 100644
--- a/src/libpts/plugins/imv_attestation/imv_attestation_state.c
+++ b/src/libpts/plugins/imv_attestation/imv_attestation_state.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -15,21 +15,15 @@
#include "imv_attestation_state.h"
+#include <libpts.h>
+
#include <utils/lexparser.h>
#include <utils/linked_list.h>
#include <debug.h>
typedef struct private_imv_attestation_state_t private_imv_attestation_state_t;
typedef struct file_meas_request_t file_meas_request_t;
-
-/**
- * PTS File/Directory Measurement request entry
- */
-struct file_meas_request_t {
- u_int16_t id;
- int file_id;
- bool is_dir;
-};
+typedef struct func_comp_t func_comp_t;
/**
* Private data of an imv_attestation_state_t object.
@@ -62,6 +56,11 @@ struct private_imv_attestation_state_t {
bool has_excl;
/**
+ * Maximum PA-TNC message size for this TNCCS connection
+ */
+ u_int32_t max_msg_len;
+
+ /**
* IMV Attestation handshake state
*/
imv_attestation_handshake_state_t handshake_state;
@@ -103,6 +102,32 @@ struct private_imv_attestation_state_t {
};
+/**
+ * PTS File/Directory Measurement request entry
+ */
+struct file_meas_request_t {
+ u_int16_t id;
+ int file_id;
+ bool is_dir;
+};
+
+/**
+ * PTS Functional Component entry
+ */
+struct func_comp_t {
+ pts_component_t *comp;
+ u_int8_t qualifier;
+};
+
+/**
+ * Frees a func_comp_t object
+ */
+static void free_func_comp(func_comp_t *this)
+{
+ this->comp->destroy(this->comp);
+ free(this);
+}
+
typedef struct entry_t entry_t;
/**
@@ -150,6 +175,18 @@ METHOD(imv_state_t, set_flags, void,
this->has_excl = has_excl;
}
+METHOD(imv_state_t, set_max_msg_len, void,
+ private_imv_attestation_state_t *this, u_int32_t max_msg_len)
+{
+ this->max_msg_len = max_msg_len;
+}
+
+METHOD(imv_state_t, get_max_msg_len, u_int32_t,
+ private_imv_attestation_state_t *this)
+{
+ return this->max_msg_len;
+}
+
METHOD(imv_state_t, change_state, void,
private_imv_attestation_state_t *this, TNC_ConnectionState new_state)
{
@@ -220,8 +257,7 @@ METHOD(imv_state_t, destroy, void,
private_imv_attestation_state_t *this)
{
this->file_meas_requests->destroy_function(this->file_meas_requests, free);
- this->components->destroy_offset(this->components,
- offsetof(pts_component_t, destroy));
+ this->components->destroy_function(this->components, (void *)free_func_comp);
this->pts->destroy(this->pts);
free(this);
}
@@ -290,54 +326,74 @@ METHOD(imv_attestation_state_t, get_file_meas_request_count, int,
return this->file_meas_requests->get_count(this->file_meas_requests);
}
-METHOD(imv_attestation_state_t, add_component, void,
- private_imv_attestation_state_t *this, pts_component_t *entry)
-{
- this->components->insert_last(this->components, entry);
-}
-
-METHOD(imv_attestation_state_t, check_off_component, pts_component_t*,
- private_imv_attestation_state_t *this, pts_comp_func_name_t *name)
+METHOD(imv_attestation_state_t, create_component, pts_component_t*,
+ private_imv_attestation_state_t *this, pts_comp_func_name_t *name,
+ u_int32_t depth, pts_database_t *pts_db)
{
enumerator_t *enumerator;
- pts_component_t *entry, *found = NULL;
+ func_comp_t *entry, *new_entry;
+ pts_component_t *component;
+ bool found = FALSE;
enumerator = this->components->create_enumerator(this->components);
while (enumerator->enumerate(enumerator, &entry))
{
- if (name->equals(name, entry->get_comp_func_name(entry)))
+ if (name->equals(name, entry->comp->get_comp_func_name(entry->comp)))
{
- found = entry;
- this->components->remove_at(this->components, enumerator);
+ found = TRUE;
break;
}
}
enumerator->destroy(enumerator);
- return found;
+
+ if (found)
+ {
+ if (name->get_qualifier(name) == entry->qualifier)
+ {
+ /* duplicate entry */
+ return NULL;
+ }
+ new_entry = malloc_thing(func_comp_t);
+ new_entry->qualifier = name->get_qualifier(name);
+ new_entry->comp = entry->comp->get_ref(entry->comp);
+ this->components->insert_last(this->components, new_entry);
+ return entry->comp;
+ }
+ else
+ {
+ component = pts_components->create(pts_components, name, depth, pts_db);
+ if (!component)
+ {
+ /* unsupported component */
+ return NULL;
+ }
+ new_entry = malloc_thing(func_comp_t);
+ new_entry->qualifier = name->get_qualifier(name);
+ new_entry->comp = component;
+ this->components->insert_last(this->components, new_entry);
+ return component;
+ }
}
-METHOD(imv_attestation_state_t, check_off_registrations, void,
- private_imv_attestation_state_t *this)
+METHOD(imv_attestation_state_t, get_component, pts_component_t*,
+ private_imv_attestation_state_t *this, pts_comp_func_name_t *name)
{
enumerator_t *enumerator;
- pts_component_t *entry;
+ func_comp_t *entry;
+ pts_component_t *found = NULL;
enumerator = this->components->create_enumerator(this->components);
while (enumerator->enumerate(enumerator, &entry))
{
- if (entry->check_off_registrations(entry))
+ if (name->equals(name, entry->comp->get_comp_func_name(entry->comp)) &&
+ name->get_qualifier(name) == entry->qualifier)
{
- this->components->remove_at(this->components, enumerator);
- entry->destroy(entry);
+ found = entry->comp;
+ break;
}
}
enumerator->destroy(enumerator);
-}
-
-METHOD(imv_attestation_state_t, get_component_count, int,
- private_imv_attestation_state_t *this)
-{
- return this->components->get_count(this->components);
+ return found;
}
METHOD(imv_attestation_state_t, get_measurement_error, bool,
@@ -352,6 +408,28 @@ METHOD(imv_attestation_state_t, set_measurement_error, void,
this->measurement_error = TRUE;
}
+METHOD(imv_attestation_state_t, finalize_components, void,
+ private_imv_attestation_state_t *this)
+{
+ func_comp_t *entry;
+
+ while (this->components->remove_last(this->components,
+ (void**)&entry) == SUCCESS)
+ {
+ if (!entry->comp->finalize(entry->comp, entry->qualifier))
+ {
+ _set_measurement_error(this);
+ }
+ free_func_comp(entry);
+ }
+}
+
+METHOD(imv_attestation_state_t, components_finalized, bool,
+ private_imv_attestation_state_t *this)
+{
+ return this->components->get_count(this->components) == 0;
+}
+
/**
* Described in header.
*/
@@ -367,6 +445,8 @@ imv_state_t *imv_attestation_state_create(TNC_ConnectionID 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,
.change_state = _change_state,
.get_recommendation = _get_recommendation,
.set_recommendation = _set_recommendation,
@@ -379,10 +459,10 @@ imv_state_t *imv_attestation_state_create(TNC_ConnectionID connection_id)
.add_file_meas_request = _add_file_meas_request,
.check_off_file_meas_request = _check_off_file_meas_request,
.get_file_meas_request_count = _get_file_meas_request_count,
- .add_component = _add_component,
- .check_off_component = _check_off_component,
- .check_off_registrations = _check_off_registrations,
- .get_component_count = _get_component_count,
+ .create_component = _create_component,
+ .get_component = _get_component,
+ .finalize_components = _finalize_components,
+ .components_finalized = _components_finalized,
.get_measurement_error = _get_measurement_error,
.set_measurement_error = _set_measurement_error,
},
diff --git a/src/libpts/plugins/imv_attestation/imv_attestation_state.h b/src/libpts/plugins/imv_attestation/imv_attestation_state.h
index 0e2c04da4..901d4b19d 100644
--- a/src/libpts/plugins/imv_attestation/imv_attestation_state.h
+++ b/src/libpts/plugins/imv_attestation/imv_attestation_state.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
#include <imv/imv_state.h>
#include <pts/pts.h>
+#include <pts/pts_database.h>
#include <pts/components/pts_component.h>
#include <library.h>
@@ -105,32 +106,37 @@ struct imv_attestation_state_t {
u_int16_t id, int *file_id, bool *is_dir);
/**
- * Add an entry to the list of Functional Components waiting for evidence
+ * Create and add an entry to the list of Functional Components
*
- * @param entry Functional Component
+ * @param name Component Functional Name
+ * @param depth Sub-component Depth
+ * @param pts_db PTS measurement database
+ * @return created functional component instance or NULL
*/
- void (*add_component)(imv_attestation_state_t *this, pts_component_t *entry);
+ pts_component_t* (*create_component)(imv_attestation_state_t *this,
+ pts_comp_func_name_t *name,
+ u_int32_t depth,
+ pts_database_t *pts_db);
/**
- * Returns the number of Functional Component waiting for evidence
- *
- * @return Number of waiting Functional Components
- */
- int (*get_component_count)(imv_attestation_state_t *this);
-
- /**
- * Check for presence of Functional Component and remove and return it
+ * Get a Functional Component with a given name
*
* @param name Name of the requested Functional Component
* @return Functional Component if found, NULL otherwise
*/
- pts_component_t* (*check_off_component)(imv_attestation_state_t *this,
- pts_comp_func_name_t *name);
+ pts_component_t* (*get_component)(imv_attestation_state_t *this,
+ pts_comp_func_name_t *name);
/**
* Tell the Functional Components to finalize any measurement registrations
+ * and to check if all expected measurements were received
+ */
+ void (*finalize_components)(imv_attestation_state_t *this);
+
+ /**
+ * Have the Functional Component measurements been finalized?
*/
- void (*check_off_registrations)(imv_attestation_state_t *this);
+ bool (*components_finalized)(imv_attestation_state_t *this);
/**
* Indicates if a file measurement error occurred
diff --git a/src/libpts/plugins/imv_attestation/tables.sql b/src/libpts/plugins/imv_attestation/tables.sql
index 703557a07..42553bef0 100644
--- a/src/libpts/plugins/imv_attestation/tables.sql
+++ b/src/libpts/plugins/imv_attestation/tables.sql
@@ -6,6 +6,10 @@ CREATE TABLE files (
type INTEGER NOT NULL,
path TEXT NOT NULL
);
+DROP INDEX IF EXISTS files_path;
+CREATE INDEX files_path ON files (
+ path
+);
DROP TABLE IF EXISTS products;
CREATE TABLE products (
@@ -31,6 +35,7 @@ CREATE TABLE file_hashes (
file INTEGER NOT NULL,
directory INTEGER DEFAULT 0,
product INTEGER NOT NULL,
+ key INTEGER DEFAULT 0,
algo INTEGER NOT NULL,
hash BLOB NOT NULL,
PRIMARY KEY(file, directory, product, algo)
diff --git a/src/libpts/pts/components/ita/ita_comp_ima.c b/src/libpts/pts/components/ita/ita_comp_ima.c
index a7da76651..a59732428 100644
--- a/src/libpts/pts/components/ita/ita_comp_ima.c
+++ b/src/libpts/pts/components/ita/ita_comp_ima.c
@@ -1,6 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
- *
+ * Copyright (C) 2011-2012 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -18,6 +17,7 @@
#include "ita_comp_func_name.h"
#include "libpts.h"
+#include "pts/pts_pcr.h"
#include "pts/components/pts_component.h"
#include <debug.h>
@@ -29,11 +29,25 @@
#include <fcntl.h>
#include <errno.h>
-#define IMA_SECURITY_DIR "/sys/kernel/security/tpm0/"
-#define IMA_BIOS_MEASUREMENT_PATH IMA_SECURITY_DIR "binary_bios_measurements"
-#define IMA_PCR_MAX 16
+#define SECURITY_DIR "/sys/kernel/security/"
+#define IMA_BIOS_MEASUREMENTS SECURITY_DIR "tpm0/binary_bios_measurements"
+#define IMA_RUNTIME_MEASUREMENTS SECURITY_DIR "ima/binary_runtime_measurements"
+#define IMA_PCR 10
+#define IMA_TYPE_LEN 3
+#define IMA_FILENAME_LEN_MAX 255
typedef struct pts_ita_comp_ima_t pts_ita_comp_ima_t;
+typedef struct bios_entry_t bios_entry_t;
+typedef struct ima_entry_t ima_entry_t;
+typedef enum ima_state_t ima_state_t;
+
+enum ima_state_t {
+ IMA_STATE_INIT,
+ IMA_STATE_BIOS,
+ IMA_STATE_BOOT_AGGREGATE,
+ IMA_STATE_RUNTIME,
+ IMA_STATE_END
+};
/**
* Private data of a pts_ita_comp_ima_t object.
@@ -67,52 +81,101 @@ struct pts_ita_comp_ima_t {
pts_database_t *pts_db;
/**
- * Primary key for Component Functional Name database entry
+ * Primary key for AIK database entry
*/
- int cid;
+ int kid;
/**
- * Primary key for AIK database entry
+ * Primary key for IMA BIOS Component Functional Name database entry
*/
- int kid;
+ int bios_cid;
+
+ /**
+ * Primary key for IMA Runtime Component Functional Name database entry
+ */
+ int ima_cid;
/**
- * Component is registering measurements
+ * Component is registering IMA BIOS measurements
*/
- bool is_registering;
+ bool is_bios_registering;
+
+ /**
+ * Component is registering IMA boot aggregate measurement
+ */
+ bool is_ima_registering;
+
+ /**
+ * Measurement sequence number
+ */
+ int seq_no;
/**
- * IMA BIOS measurement time
+ * Expected IMA BIOS measurement count
*/
- time_t bios_measurement_time;
+ int bios_count;
/**
* IMA BIOS measurements
*/
- linked_list_t *list;
+ linked_list_t *bios_list;
/**
- * Expected measurement count
+ * IMA runtime file measurements
+ */
+ linked_list_t *ima_list;
+
+ /**
+ * Whether to send pcr_before and pcr_after info
+ */
+ bool pcr_info;
+
+ /**
+ * IMA measurement time
+ */
+ time_t measurement_time;
+
+ /**
+ * IMA state machine
+ */
+ ima_state_t state;
+
+ /**
+ * Total number of component measurements
*/
int count;
/**
- * Measurement sequence number
+ * Number of successful component measurements
*/
- int seq_no;
+ int count_ok;
/**
- * Shadow PCR registers
+ * Number of unknown component measurements
*/
- chunk_t pcrs[IMA_PCR_MAX];
-};
+ int count_unknown;
-typedef struct entry_t entry_t;
+ /**
+ * Number of differing component measurements
+ */
+ int count_differ;
+
+ /**
+ * Number of failed component measurements
+ */
+ int count_failed;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+
+};
/**
- * Linux IMA measurement entry
+ * Linux IMA BIOS measurement entry
*/
-struct entry_t {
+struct bios_entry_t {
/**
* PCR register
@@ -126,21 +189,48 @@ struct entry_t {
};
/**
- * Free an entry_t object
+ * Linux IMA runtime file measurement entry
+ */
+struct ima_entry_t {
+
+ /**
+ * SHA1 measurement hash
+ */
+ chunk_t measurement;
+
+ /**
+ * absolute path of executable files or basename of dynamic libraries
+ */
+ char *filename;
+};
+
+/**
+ * Free a bios_entry_t object
+ */
+static void free_bios_entry(bios_entry_t *this)
+{
+ free(this->measurement.ptr);
+ free(this);
+}
+
+/**
+ * Free an ima_entry_t object
*/
-static void free_entry(entry_t *this)
+static void free_ima_entry(ima_entry_t *this)
{
free(this->measurement.ptr);
+ free(this->filename);
free(this);
}
/**
* Load a PCR measurement file and determine the creation date
*/
-static bool load_measurements(char *file, linked_list_t *list, time_t *created)
+static bool load_bios_measurements(char *file, linked_list_t *list,
+ time_t *created)
{
u_int32_t pcr, num, len;
- entry_t *entry;
+ bios_entry_t *entry;
struct stat st;
ssize_t res;
int fd;
@@ -148,13 +238,13 @@ static bool load_measurements(char *file, linked_list_t *list, time_t *created)
fd = open(file, O_RDONLY);
if (fd == -1)
{
- DBG1(DBG_PTS, " opening '%s' failed: %s", file, strerror(errno));
+ DBG1(DBG_PTS, "opening '%s' failed: %s", file, strerror(errno));
return FALSE;
}
if (fstat(fd, &st) == -1)
{
- DBG1(DBG_PTS, " getting statistics of '%s' failed: %s", file,
+ DBG1(DBG_PTS, "getting statistics of '%s' failed: %s", file,
strerror(errno));
close(fd);
return FALSE;
@@ -167,12 +257,12 @@ static bool load_measurements(char *file, linked_list_t *list, time_t *created)
if (res == 0)
{
DBG2(DBG_PTS, "loaded bios measurements '%s' (%d entries)",
- file, list->get_count(list));
+ file, list->get_count(list));
close(fd);
return TRUE;
}
- entry = malloc_thing(entry_t);
+ entry = malloc_thing(bios_entry_t);
entry->pcr = pcr;
entry->measurement = chunk_alloc(HASH_SIZE_SHA1);
@@ -199,12 +289,188 @@ static bool load_measurements(char *file, linked_list_t *list, time_t *created)
list->insert_last(list, entry);
}
- DBG1(DBG_PTS, "loading bios measurements '%s' failed: %s",
- file, strerror(errno));
+ DBG1(DBG_PTS, "loading bios measurements '%s' failed: %s", file,
+ strerror(errno));
+ close(fd);
+ return FALSE;
+}
+
+/**
+ * Load an IMA runtime measurement file and determine the creation and
+ * update dates
+ */
+static bool load_runtime_measurements(char *file, linked_list_t *list,
+ time_t *created)
+{
+ u_int32_t pcr, len;
+ ima_entry_t *entry;
+ char type[IMA_TYPE_LEN];
+ struct stat st;
+ ssize_t res;
+ int fd;
+
+ fd = open(file, O_RDONLY);
+ if (fd == -1)
+ {
+ DBG1(DBG_PTS, "opening '%s' failed: %s", file, strerror(errno));
+ return TRUE;
+ }
+
+ if (fstat(fd, &st) == -1)
+ {
+ DBG1(DBG_PTS, "getting statistics of '%s' failed: %s", file,
+ strerror(errno));
+ close(fd);
+ return FALSE;
+ }
+ *created = st.st_ctime;
+
+ while (TRUE)
+ {
+ res = read(fd, &pcr, 4);
+ if (res == 0)
+ {
+ DBG2(DBG_PTS, "loaded ima measurements '%s' (%d entries)",
+ file, list->get_count(list));
+ close(fd);
+ return TRUE;
+ }
+
+ entry = malloc_thing(ima_entry_t);
+ entry->measurement = chunk_alloc(HASH_SIZE_SHA1);
+ entry->filename = NULL;
+
+ if (res != 4 || pcr != IMA_PCR)
+ {
+ break;
+ }
+ if (read(fd, entry->measurement.ptr, HASH_SIZE_SHA1) != HASH_SIZE_SHA1)
+ {
+ break;
+ }
+ if (read(fd, &len, 4) != 4 || len != IMA_TYPE_LEN)
+ {
+ break;
+ }
+ if (read(fd, type, IMA_TYPE_LEN) != IMA_TYPE_LEN ||
+ memcmp(type, "ima", IMA_TYPE_LEN))
+ {
+ break;
+ }
+ if (lseek(fd, HASH_SIZE_SHA1, SEEK_CUR) == -1)
+ {
+ break;
+ }
+ if (read(fd, &len, 4) != 4)
+ {
+ break;
+ }
+ entry->filename = malloc(len + 1);
+ if (read(fd, entry->filename, len) != len)
+ {
+ break;
+ }
+ entry->filename[len] = '\0';
+
+ list->insert_last(list, entry);
+ }
+
+ DBG1(DBG_PTS, "loading ima measurements '%s' failed: %s",
+ file, strerror(errno));
close(fd);
return FALSE;
}
+/**
+ * Extend measurement into PCR an create evidence
+ */
+static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this,
+ u_int8_t qualifier, pts_pcr_t *pcrs,
+ u_int32_t pcr, chunk_t measurement)
+{
+ size_t pcr_len;
+ pts_pcr_transform_t pcr_transform;
+ pts_meas_algorithms_t hash_algo;
+ pts_comp_func_name_t *name;
+ pts_comp_evidence_t *evidence;
+ chunk_t pcr_before = chunk_empty, pcr_after = chunk_empty;
+
+ hash_algo = PTS_MEAS_ALGO_SHA1;
+ pcr_len = HASH_SIZE_SHA1;
+ pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len);
+
+ if (this->pcr_info)
+ {
+ pcr_before = chunk_clone(pcrs->get(pcrs, pcr));
+ }
+ pcr_after = pcrs->extend(pcrs, pcr, measurement);
+ if (!pcr_after.ptr)
+ {
+ free(pcr_before.ptr);
+ return NULL;
+ }
+ name = this->name->clone(this->name);
+ name->set_qualifier(name, qualifier);
+ evidence = pts_comp_evidence_create(name, this->depth, pcr, hash_algo,
+ pcr_transform, this->measurement_time, measurement);
+ if (this->pcr_info)
+ {
+ pcr_after =chunk_clone(pcrs->get(pcrs, pcr));
+ evidence->set_pcr_info(evidence, pcr_before, pcr_after);
+ }
+ return evidence;
+}
+
+/**
+ * Compute and check boot aggregate value by hashing PCR0 to PCR7
+ */
+static bool check_boot_aggregate(pts_pcr_t *pcrs, chunk_t measurement)
+{
+ u_int32_t i;
+ u_char filename_buffer[IMA_FILENAME_LEN_MAX + 1];
+ u_char pcr_buffer[HASH_SIZE_SHA1];
+ chunk_t file_name, boot_aggregate;
+ hasher_t *hasher;
+ bool success, pcr_ok = TRUE;
+
+ hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+ if (!hasher)
+ {
+ DBG1(DBG_PTS, "%N hasher could not be created",
+ hash_algorithm_short_names, HASH_SHA1);
+ return FALSE;
+ }
+ for (i = 0; i < 8 && pcr_ok; i++)
+ {
+ pcr_ok = hasher->get_hash(hasher, pcrs->get(pcrs, i), NULL);
+ }
+ if (pcr_ok)
+ {
+ boot_aggregate = chunk_create(pcr_buffer, sizeof(pcr_buffer));
+ memset(filename_buffer, 0, sizeof(filename_buffer));
+ strcpy(filename_buffer, "boot_aggregate");
+ file_name = chunk_create (filename_buffer, sizeof(filename_buffer));
+
+ pcr_ok = hasher->get_hash(hasher, chunk_empty, pcr_buffer) &&
+ hasher->get_hash(hasher, boot_aggregate, NULL) &&
+ hasher->get_hash(hasher, file_name, boot_aggregate.ptr);
+ }
+ hasher->destroy(hasher);
+
+ if (pcr_ok)
+ {
+ success = chunk_equals(boot_aggregate, measurement);
+ DBG1(DBG_PTS, "boot aggregate value is %scorrect",
+ success ? "":"in");
+ return success;
+ }
+ else
+ {
+ DBG1(DBG_PTS, "failed to compute boot aggregate value");
+ return FALSE;
+ }
+}
+
METHOD(pts_component_t, get_comp_func_name, pts_comp_func_name_t*,
pts_ita_comp_ima_t *this)
{
@@ -224,193 +490,446 @@ METHOD(pts_component_t, get_depth, u_int32_t,
}
METHOD(pts_component_t, measure, status_t,
- pts_ita_comp_ima_t *this, pts_t *pts, pts_comp_evidence_t **evidence)
+ pts_ita_comp_ima_t *this, u_int8_t qualifier, pts_t *pts,
+ pts_comp_evidence_t **evidence)
{
- pts_comp_evidence_t *evid;
- chunk_t pcr_before, pcr_after;
- pts_pcr_transform_t pcr_transform;
- pts_meas_algorithms_t hash_algo;
- size_t pcr_len;
- entry_t *entry;
- hasher_t *hasher;
+ bios_entry_t *bios_entry;
+ ima_entry_t *ima_entry;
+ pts_pcr_t *pcrs;
+ pts_comp_evidence_t *evid = NULL;
+ status_t status;
- hash_algo = PTS_MEAS_ALGO_SHA1;
- pcr_len = pts->get_pcr_len(pts);
- pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len);
+ pcrs = pts->get_pcrs(pts);
- if (this->list->get_count(this->list) == 0)
+ if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_TRUSTED))
{
- if (!load_measurements(IMA_BIOS_MEASUREMENT_PATH, this->list,
- &this->bios_measurement_time))
+ switch (this->state)
{
- return FAILED;
+ case IMA_STATE_INIT:
+ if (!load_bios_measurements(IMA_BIOS_MEASUREMENTS,
+ this->bios_list, &this->measurement_time))
+ {
+ return FAILED;
+ }
+ this->bios_count = this->bios_list->get_count(this->bios_list);
+ this->state = IMA_STATE_BIOS;
+ /* fall through to next state */
+ case IMA_STATE_BIOS:
+ status = this->bios_list->remove_first(this->bios_list,
+ (void**)&bios_entry);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_PTS, "could not retrieve bios measurement entry");
+ return status;
+ }
+ evid = extend_pcr(this, qualifier, pcrs, bios_entry->pcr,
+ bios_entry->measurement);
+ free(bios_entry);
+
+ this->state = this->bios_list->get_count(this->bios_list) ?
+ IMA_STATE_BIOS : IMA_STATE_INIT;
+ break;
+ default:
+ return FAILED;
}
}
-
- if (this->list->remove_first(this->list, (void**)&entry) != SUCCESS)
+ else if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_OS))
+ {
+ switch (this->state)
+ {
+ case IMA_STATE_INIT:
+ if (!load_runtime_measurements(IMA_RUNTIME_MEASUREMENTS,
+ this->ima_list, &this->measurement_time))
+ {
+ return FAILED;
+ }
+ this->state = IMA_STATE_BOOT_AGGREGATE;
+ /* fall through to next state */
+ case IMA_STATE_BOOT_AGGREGATE:
+ case IMA_STATE_RUNTIME:
+ status = this->ima_list->remove_first(this->ima_list,
+ (void**)&ima_entry);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_PTS, "could not retrieve ima measurement entry");
+ return status;
+ }
+ if (this->state == IMA_STATE_BOOT_AGGREGATE && this->bios_count)
+ {
+ if (!check_boot_aggregate(pcrs, ima_entry->measurement))
+ {
+ return FAILED;
+ }
+ }
+ evid = extend_pcr(this, qualifier, pcrs, IMA_PCR,
+ ima_entry->measurement);
+ if (evid)
+ {
+ evid->set_validation(evid, PTS_COMP_EVID_VALIDATION_PASSED,
+ ima_entry->filename);
+ }
+ free(ima_entry->filename);
+ free(ima_entry);
+
+ this->state = this->ima_list->get_count(this->ima_list) ?
+ IMA_STATE_RUNTIME : IMA_STATE_END;
+ break;
+ default:
+ return FAILED;
+ }
+ }
+ else
{
- DBG1(DBG_PTS, "could not retrieve measurement entry");
+ DBG1(DBG_PTS, "unsupported functional component name qualifier");
return FAILED;
}
-
- pcr_before = chunk_clone(this->pcrs[entry->pcr]);
-
- hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
- hasher->get_hash(hasher, pcr_before, NULL);
- hasher->get_hash(hasher, entry->measurement, this->pcrs[entry->pcr].ptr);
- hasher->destroy(hasher);
-
- pcr_after = chunk_clone(this->pcrs[entry->pcr]);
- evid = *evidence = pts_comp_evidence_create(this->name->clone(this->name),
- this->depth, entry->pcr, hash_algo, pcr_transform,
- this->bios_measurement_time, entry->measurement);
- evid->set_pcr_info(evid, pcr_before, pcr_after);
-
- free(entry);
+ *evidence = evid;
+ if (!evid)
+ {
+ return FAILED;
+ }
- return (this->list->get_count(this->list)) ? NEED_MORE : SUCCESS;
+ return (this->state == IMA_STATE_INIT || this->state == IMA_STATE_END) ?
+ SUCCESS : NEED_MORE;
}
METHOD(pts_component_t, verify, status_t,
- pts_ita_comp_ima_t *this, pts_t *pts, pts_comp_evidence_t *evidence)
+ pts_ita_comp_ima_t *this, u_int8_t qualifier, pts_t *pts,
+ pts_comp_evidence_t *evidence)
{
bool has_pcr_info;
- u_int32_t extended_pcr, vid, name;
+ u_int32_t pcr, vid, name;
enum_name_t *names;
pts_meas_algorithms_t algo;
pts_pcr_transform_t transform;
+ pts_pcr_t *pcrs;
time_t measurement_time;
chunk_t measurement, pcr_before, pcr_after;
+ status_t status;
+ char *uri;
- measurement = evidence->get_measurement(evidence, &extended_pcr,
- &algo, &transform, &measurement_time);
-
+ /* some first time initializations */
if (!this->keyid.ptr)
{
if (!pts->get_aik_keyid(pts, &this->keyid))
{
+ DBG1(DBG_PTS, "AIK keyid not available");
return FAILED;
}
this->keyid = chunk_clone(this->keyid);
-
if (!this->pts_db)
{
DBG1(DBG_PTS, "pts database not available");
return FAILED;
}
- if (this->pts_db->get_comp_measurement_count(this->pts_db,
- this->name, this->keyid, algo,
- &this->cid, &this->kid, &this->count) != SUCCESS)
- {
- return FAILED;
- }
- vid = this->name->get_vendor_id(this->name);
- name = this->name->get_name(this->name);
- names = pts_components->get_comp_func_names(pts_components, vid);
+ }
- if (this->count)
- {
- DBG1(DBG_PTS, "checking %d %N '%N' functional component evidence "
- "measurements", this->count, pen_names, vid, names, name);
- }
- else
+ pcrs = pts->get_pcrs(pts);
+ measurement = evidence->get_measurement(evidence, &pcr, &algo, &transform,
+ &measurement_time);
+
+ if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_TRUSTED))
+ {
+ switch (this->state)
{
- DBG1(DBG_PTS, "registering %N '%N' functional component evidence "
- "measurements", pen_names, vid, names, name);
- this->is_registering = TRUE;
+ case IMA_STATE_INIT:
+ this->name->set_qualifier(this->name, qualifier);
+ status = this->pts_db->get_comp_measurement_count(this->pts_db,
+ this->name, this->keyid, algo, &this->bios_cid,
+ &this->kid, &this->bios_count);
+ this->name->set_qualifier(this->name, PTS_QUALIFIER_UNKNOWN);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ vid = this->name->get_vendor_id(this->name);
+ name = this->name->get_name(this->name);
+ names = pts_components->get_comp_func_names(pts_components, vid);
+
+ if (this->bios_count)
+ {
+ DBG1(DBG_PTS, "checking %d %N '%N' BIOS evidence measurements",
+ this->bios_count, pen_names, vid, names, name);
+ }
+ else
+ {
+ DBG1(DBG_PTS, "registering %N '%N' BIOS evidence measurements",
+ pen_names, vid, names, name);
+ this->is_bios_registering = TRUE;
+ }
+
+ this->state = IMA_STATE_BIOS;
+ /* fall through to next state */
+ case IMA_STATE_BIOS:
+ if (this->is_bios_registering)
+ {
+ status = this->pts_db->insert_comp_measurement(this->pts_db,
+ measurement, this->bios_cid, this->kid,
+ ++this->seq_no, pcr, algo);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ this->bios_count = this->seq_no + 1;
+ }
+ else
+ {
+ status = this->pts_db->check_comp_measurement(this->pts_db,
+ measurement, this->bios_cid, this->kid,
+ ++this->seq_no, pcr, algo);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ }
+ break;
+ default:
+ return FAILED;
}
}
-
- if (this->is_registering)
+ else if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_OS))
{
- if (this->pts_db->insert_comp_measurement(this->pts_db, measurement,
- this->cid, this->kid, ++this->seq_no,
- extended_pcr, algo) != SUCCESS)
+ int ima_count;
+
+ switch (this->state)
{
- return FAILED;
+ case IMA_STATE_BIOS:
+ if (!check_boot_aggregate(pcrs, measurement))
+ {
+ this->state = IMA_STATE_RUNTIME;
+ return FAILED;
+ }
+ this->state = IMA_STATE_INIT;
+ /* fall through to next state */
+ case IMA_STATE_INIT:
+ this->name->set_qualifier(this->name, qualifier);
+ status = this->pts_db->get_comp_measurement_count(this->pts_db,
+ this->name, this->keyid, algo,
+ &this->ima_cid, &this->kid, &ima_count);
+ this->name->set_qualifier(this->name, PTS_QUALIFIER_UNKNOWN);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ vid = this->name->get_vendor_id(this->name);
+ name = this->name->get_name(this->name);
+ names = pts_components->get_comp_func_names(pts_components, vid);
+
+ if (ima_count)
+ {
+ DBG1(DBG_PTS, "checking %N '%N' boot aggregate evidence "
+ "measurement", pen_names, vid, names, name);
+ status = this->pts_db->check_comp_measurement(this->pts_db,
+ measurement, this->ima_cid,
+ this->kid, 1, pcr, algo);
+ }
+ else
+ {
+ DBG1(DBG_PTS, "registering %N '%N' boot aggregate evidence "
+ "measurement", pen_names, vid, names, name);
+ this->is_ima_registering = TRUE;
+ status = this->pts_db->insert_comp_measurement(this->pts_db,
+ measurement, this->ima_cid,
+ this->kid, 1, pcr, algo);
+ }
+ this->state = IMA_STATE_RUNTIME;
+
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ break;
+ case IMA_STATE_RUNTIME:
+ this->count++;
+ if (evidence->get_validation(evidence, &uri) !=
+ PTS_COMP_EVID_VALIDATION_PASSED)
+ {
+ DBG1(DBG_PTS, "policy URI could no be retrieved");
+ this->count_failed++;
+ return FAILED;
+ }
+ status = this->pts_db->check_file_measurement(this->pts_db,
+ pts->get_platform_info(pts),
+ PTS_MEAS_ALGO_SHA1_IMA,
+ measurement, uri);
+ switch (status)
+ {
+ case SUCCESS:
+ DBG3(DBG_PTS, "%#B for '%s' is ok",
+ &measurement, uri);
+ this->count_ok++;
+ break;
+ case NOT_FOUND:
+ DBG2(DBG_PTS, "%#B for '%s' not found",
+ &measurement, uri);
+ this->count_unknown++;
+ break;
+ case VERIFY_ERROR:
+ DBG1(DBG_PTS, "%#B for '%s' differs",
+ &measurement, uri);
+ this->count_differ++;
+ break;
+ case FAILED:
+ default:
+ DBG1(DBG_PTS, "%#B for '%s' failed",
+ &measurement, uri);
+ this->count_failed++;
+ }
+ break;
+ default:
+ return FAILED;
}
- this->count = this->seq_no + 1;
}
else
{
- if (this->pts_db->check_comp_measurement(this->pts_db, measurement,
- this->cid, this->kid, ++this->seq_no,
- extended_pcr, algo) != SUCCESS)
- {
- return FAILED;
- }
+ DBG1(DBG_PTS, "unsupported functional component name qualifier");
+ return FAILED;
}
has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
if (has_pcr_info)
{
- if (!pts->add_pcr(pts, extended_pcr, pcr_before, pcr_after))
+ if (!chunk_equals(pcr_before, pcrs->get(pcrs, pcr)))
{
- return FAILED;
+ DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to register value",
+ pcr);
+ }
+ if (pcrs->set(pcrs, pcr, pcr_after))
+ {
+ return SUCCESS;
}
}
-
- return (this->seq_no < this->count) ? NEED_MORE : SUCCESS;
+ else
+ {
+ pcr_after = pcrs->extend(pcrs, pcr, measurement);
+ if (pcr_after.ptr)
+ {
+ return SUCCESS;
+ }
+ }
+ return FAILED;
}
-METHOD(pts_component_t, check_off_registrations, bool,
- pts_ita_comp_ima_t *this)
+METHOD(pts_component_t, finalize, bool,
+ pts_ita_comp_ima_t *this, u_int8_t qualifier)
{
u_int32_t vid, name;
enum_name_t *names;
+ bool success = TRUE;
- if (!this->is_registering)
+ this->name->set_qualifier(this->name, qualifier);
+ vid = this->name->get_vendor_id(this->name);
+ name = this->name->get_name(this->name);
+ names = pts_components->get_comp_func_names(pts_components, vid);
+
+ if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_TRUSTED))
{
- return FALSE;
+ /* finalize BIOS measurements */
+ if (this->is_bios_registering)
+ {
+ /* close registration */
+ this->is_bios_registering = FALSE;
+
+ DBG1(DBG_PTS, "registered %d %N '%N' BIOS evidence measurements",
+ this->seq_no, pen_names, vid, names, name);
+ }
+ else if (this->seq_no < this->bios_count)
+ {
+ DBG1(DBG_PTS, "%d of %d %N '%N' BIOS evidence measurements missing",
+ this->bios_count - this->seq_no, this->bios_count,
+ pen_names, vid, names, name);
+ success = FALSE;
+ }
}
+ else if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_OS))
+ {
+ /* finalize IMA file measurements */
+ if (this->is_ima_registering)
+ {
+ /* close registration */
+ this->is_ima_registering = FALSE;
- /* Finalize registration */
- this->is_registering = FALSE;
+ DBG1(DBG_PTS, "registered %N '%N' boot aggregate evidence "
+ "measurement", pen_names, vid, names, name);
+ }
+ if (this->count)
+ {
+ DBG1(DBG_PTS, "processed %d %N '%N' file evidence measurements: "
+ "%d ok, %d unknown, %d differ, %d failed",
+ this->count, pen_names, vid, names, name,
+ this->count_ok, this->count_unknown,
+ this->count_differ, this->count_failed);
+ success = !this->count_differ && !this->count_failed;
+ }
+ }
+ else
+ {
+ DBG1(DBG_PTS, "unsupported functional component name qualifier");
+ success = FALSE;
+ }
+ this->name->set_qualifier(this->name, PTS_QUALIFIER_UNKNOWN);
- vid = this->name->get_vendor_id(this->name);
- name = this->name->get_name(this->name);
- names = pts_components->get_comp_func_names(pts_components, vid);
- DBG1(DBG_PTS, "registered %d %N '%N' functional component evidence "
- "measurements", this->seq_no, pen_names, vid, names, name);
- return TRUE;
+ return success;
+}
+
+METHOD(pts_component_t, get_ref, pts_component_t*,
+ pts_ita_comp_ima_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public;
}
METHOD(pts_component_t, destroy, void,
pts_ita_comp_ima_t *this)
{
- int i, count;
+ int count;
u_int32_t vid, name;
enum_name_t *names;
- for (i = 0; i < IMA_PCR_MAX; i++)
- {
- free(this->pcrs[i].ptr);
- }
- if (this->is_registering)
+ if (ref_put(&this->ref))
{
- count = this->pts_db->delete_comp_measurements(this->pts_db,
- this->cid, this->kid);
vid = this->name->get_vendor_id(this->name);
name = this->name->get_name(this->name);
names = pts_components->get_comp_func_names(pts_components, vid);
- DBG1(DBG_PTS, "deleted %d registered %N '%N' functional component "
- "evidence measurements", count, pen_names, vid, names, name);
+
+ if (this->is_bios_registering)
+ {
+ count = this->pts_db->delete_comp_measurements(this->pts_db,
+ this->bios_cid, this->kid);
+ DBG1(DBG_PTS, "deleted %d registered %N '%N' BIOS evidence "
+ "measurements", count, pen_names, vid, names, name);
+ }
+ if (this->is_ima_registering)
+ {
+ count = this->pts_db->delete_comp_measurements(this->pts_db,
+ this->ima_cid, this->kid);
+ DBG1(DBG_PTS, "deleted registered %N '%N' boot aggregate evidence "
+ "measurement", pen_names, vid, names, name);
+ }
+ this->bios_list->destroy_function(this->bios_list,
+ (void *)free_bios_entry);
+ this->ima_list->destroy_function(this->ima_list,
+ (void *)free_ima_entry);
+ this->name->destroy(this->name);
+ free(this->keyid.ptr);
+ free(this);
}
- this->list->destroy_function(this->list, (void *)free_entry);
- this->name->destroy(this->name);
- free(this->keyid.ptr);
- free(this);
}
/**
* See header
*/
-pts_component_t *pts_ita_comp_ima_create(u_int8_t qualifier, u_int32_t depth,
+pts_component_t *pts_ita_comp_ima_create(u_int32_t depth,
pts_database_t *pts_db)
{
pts_ita_comp_ima_t *this;
- int i;
INIT(this,
.public = {
@@ -419,21 +938,21 @@ pts_component_t *pts_ita_comp_ima_create(u_int8_t qualifier, u_int32_t depth,
.get_depth = _get_depth,
.measure = _measure,
.verify = _verify,
- .check_off_registrations = _check_off_registrations,
+ .finalize = _finalize,
+ .get_ref = _get_ref,
.destroy = _destroy,
},
.name = pts_comp_func_name_create(PEN_ITA, PTS_ITA_COMP_FUNC_NAME_IMA,
- qualifier),
+ PTS_QUALIFIER_UNKNOWN),
.depth = depth,
.pts_db = pts_db,
- .list = linked_list_create(),
+ .bios_list = linked_list_create(),
+ .ima_list = linked_list_create(),
+ .pcr_info = lib->settings->get_bool(lib->settings,
+ "libimcv.plugins.imc-attestation.pcr_info", TRUE),
+ .ref = 1,
);
- for (i = 0; i < IMA_PCR_MAX; i++)
- {
- this->pcrs[i] = chunk_alloc(HASH_SIZE_SHA1);
- memset(this->pcrs[i].ptr, 0x00, HASH_SIZE_SHA1);
- }
return &this->public;
}
diff --git a/src/libpts/pts/components/ita/ita_comp_ima.h b/src/libpts/pts/components/ita/ita_comp_ima.h
index 1ca27e6f0..546d0a4b2 100644
--- a/src/libpts/pts/components/ita/ita_comp_ima.h
+++ b/src/libpts/pts/components/ita/ita_comp_ima.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
+ * Copyright (C) 2011-2012 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -26,11 +26,10 @@
/**
* Create a PTS ITS Functional Component object
*
- * @param qualifier PTS Component Functional Name Qualifier
* @param depth Sub-component depth
* @param pts_db PTS measurement database
*/
-pts_component_t* pts_ita_comp_ima_create(u_int8_t qualifier, u_int32_t depth,
+pts_component_t* pts_ita_comp_ima_create(u_int32_t depth,
pts_database_t *pts_db);
#endif /** PTS_ITA_COMP_IMA_H_ @}*/
diff --git a/src/libpts/pts/components/ita/ita_comp_tboot.c b/src/libpts/pts/components/ita/ita_comp_tboot.c
index a85de8cd8..9deeb19b5 100644
--- a/src/libpts/pts/components/ita/ita_comp_tboot.c
+++ b/src/libpts/pts/components/ita/ita_comp_tboot.c
@@ -1,6 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
- *
+ * Copyright (C) 2011-2012 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -86,6 +85,11 @@ struct pts_ita_comp_tboot_t {
*/
int seq_no;
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+
};
METHOD(pts_component_t, get_comp_func_name, pts_comp_func_name_t*,
@@ -107,15 +111,18 @@ METHOD(pts_component_t, get_depth, u_int32_t,
}
METHOD(pts_component_t, measure, status_t,
- pts_ita_comp_tboot_t *this, pts_t *pts, pts_comp_evidence_t **evidence)
+ pts_ita_comp_tboot_t *this, u_int8_t qualifier, pts_t *pts,
+ pts_comp_evidence_t **evidence)
+
{
+ size_t pcr_len;
+ pts_pcr_t *pcrs;
+ pts_pcr_transform_t pcr_transform;
+ pts_meas_algorithms_t hash_algo;
pts_comp_evidence_t *evid;
char *meas_hex, *pcr_before_hex, *pcr_after_hex;
chunk_t measurement, pcr_before, pcr_after;
- size_t hash_size, pcr_len;
u_int32_t extended_pcr;
- pts_pcr_transform_t pcr_transform;
- pts_meas_algorithms_t hash_algo;
switch (this->seq_no++)
{
@@ -149,9 +156,8 @@ METHOD(pts_component_t, measure, status_t,
return FAILED;
}
- hash_algo = pts->get_meas_algorithm(pts);
- hash_size = pts_meas_algo_hash_size(hash_algo);
- pcr_len = pts->get_pcr_len(pts);
+ hash_algo = PTS_MEAS_ALGO_SHA1;
+ pcr_len = HASH_SIZE_SHA1;
pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len);
/* get and check the measurement data */
@@ -162,35 +168,40 @@ METHOD(pts_component_t, measure, status_t,
pcr_after = chunk_from_hex(
chunk_create(pcr_after_hex, strlen(pcr_after_hex)), NULL);
if (pcr_before.len != pcr_len || pcr_after.len != pcr_len ||
- measurement.len != hash_size)
+ measurement.len != pcr_len)
{
- DBG1(DBG_PTS, "TBOOT measurement or pcr data have the wrong size");
+ DBG1(DBG_PTS, "TBOOT measurement or PCR data have the wrong size");
free(measurement.ptr);
free(pcr_before.ptr);
free(pcr_after.ptr);
return FAILED;
}
+ pcrs = pts->get_pcrs(pts);
+ pcrs->set(pcrs, extended_pcr, pcr_after);
evid = *evidence = pts_comp_evidence_create(this->name->clone(this->name),
- this->depth, extended_pcr,
- hash_algo, pcr_transform,
- this->measurement_time, measurement);
+ this->depth, extended_pcr, hash_algo, pcr_transform,
+ this->measurement_time, measurement);
evid->set_pcr_info(evid, pcr_before, pcr_after);
return (this->seq_no < 2) ? NEED_MORE : SUCCESS;
}
METHOD(pts_component_t, verify, status_t,
- pts_ita_comp_tboot_t *this, pts_t *pts, pts_comp_evidence_t *evidence)
+ pts_ita_comp_tboot_t *this, u_int8_t qualifier,pts_t *pts,
+ pts_comp_evidence_t *evidence)
{
bool has_pcr_info;
u_int32_t extended_pcr, vid, name;
enum_name_t *names;
pts_meas_algorithms_t algo;
pts_pcr_transform_t transform;
+ pts_pcr_t *pcrs;
time_t measurement_time;
chunk_t measurement, pcr_before, pcr_after;
+ status_t status;
+ pcrs = pts->get_pcrs(pts);
measurement = evidence->get_measurement(evidence, &extended_pcr,
&algo, &transform, &measurement_time);
@@ -207,11 +218,12 @@ METHOD(pts_component_t, verify, status_t,
DBG1(DBG_PTS, "pts database not available");
return FAILED;
}
- if (this->pts_db->get_comp_measurement_count(this->pts_db,
- this->name, this->keyid, algo,
- &this->cid, &this->kid, &this->count) != SUCCESS)
+ status = this->pts_db->get_comp_measurement_count(this->pts_db,
+ this->name, this->keyid, algo, &this->cid,
+ &this->kid, &this->count);
+ if (status != SUCCESS)
{
- return FAILED;
+ return status;
}
vid = this->name->get_vendor_id(this->name);
name = this->name->get_name(this->name);
@@ -232,58 +244,79 @@ METHOD(pts_component_t, verify, status_t,
if (this->is_registering)
{
- if (this->pts_db->insert_comp_measurement(this->pts_db, measurement,
- this->cid, this->kid, ++this->seq_no,
- extended_pcr, algo) != SUCCESS)
+ status = this->pts_db->insert_comp_measurement(this->pts_db,
+ measurement, this->cid, this->kid,
+ ++this->seq_no, extended_pcr, algo);
+ if (status != SUCCESS)
{
- return FAILED;
+ return status;
}
this->count = this->seq_no + 1;
}
else
{
- if (this->pts_db->check_comp_measurement(this->pts_db, measurement,
- this->cid, this->kid, ++this->seq_no,
- extended_pcr, algo) != SUCCESS)
+ status = this->pts_db->check_comp_measurement(this->pts_db,
+ measurement, this->cid, this->kid,
+ ++this->seq_no, extended_pcr, algo);
+ if (status != SUCCESS)
{
- return FAILED;
+ return status;
}
}
has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
if (has_pcr_info)
{
- if (!pts->add_pcr(pts, extended_pcr, pcr_before, pcr_after))
+ if (!chunk_equals(pcr_before, pcrs->get(pcrs, extended_pcr)))
{
- return FAILED;
+ DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to register value",
+ extended_pcr);
+ }
+ if (pcrs->set(pcrs, extended_pcr, pcr_after))
+ {
+ return SUCCESS;
}
}
- return (this->seq_no < this->count) ? NEED_MORE : SUCCESS;
+ return SUCCESS;
}
-METHOD(pts_component_t, check_off_registrations, bool,
- pts_ita_comp_tboot_t *this)
+METHOD(pts_component_t, finalize, bool,
+ pts_ita_comp_tboot_t *this, u_int8_t qualifier)
{
u_int32_t vid, name;
enum_name_t *names;
- if (!this->is_registering)
+ vid = this->name->get_vendor_id(this->name);
+ name = this->name->get_name(this->name);
+ names = pts_components->get_comp_func_names(pts_components, vid);
+
+ if (this->is_registering)
{
+ /* close registration */
+ this->is_registering = FALSE;
+
+ DBG1(DBG_PTS, "registered %d %N '%N' functional component evidence "
+ "measurements", this->seq_no, pen_names, vid, names, name);
+ }
+ else if (this->seq_no < this->count)
+ {
+ DBG1(DBG_PTS, "%d of %d %N '%N' functional component evidence "
+ "measurements missing", this->count - this->seq_no,
+ this->count, pen_names, vid, names, name);
return FALSE;
}
- /* Finalize registration */
- this->is_registering = FALSE;
-
- vid = this->name->get_vendor_id(this->name);
- name = this->name->get_name(this->name);
- names = pts_components->get_comp_func_names(pts_components, vid);
- DBG1(DBG_PTS, "registered %d %N '%N' functional component evidence "
- "measurements", this->seq_no, pen_names, vid, names, name);
return TRUE;
}
+METHOD(pts_component_t, get_ref, pts_component_t*,
+ pts_ita_comp_tboot_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public;
+}
+
METHOD(pts_component_t, destroy, void,
pts_ita_comp_tboot_t *this)
{
@@ -291,25 +324,28 @@ METHOD(pts_component_t, destroy, void,
u_int32_t vid, name;
enum_name_t *names;
- if (this->is_registering)
+ if (ref_put(&this->ref))
{
- count = this->pts_db->delete_comp_measurements(this->pts_db,
- this->cid, this->kid);
- vid = this->name->get_vendor_id(this->name);
- name = this->name->get_name(this->name);
- names = pts_components->get_comp_func_names(pts_components, vid);
- DBG1(DBG_PTS, "deleted %d registered %N '%N' functional component "
- "evidence measurements", count, pen_names, vid, names, name);
+ if (this->is_registering)
+ {
+ count = this->pts_db->delete_comp_measurements(this->pts_db,
+ this->cid, this->kid);
+ vid = this->name->get_vendor_id(this->name);
+ name = this->name->get_name(this->name);
+ names = pts_components->get_comp_func_names(pts_components, vid);
+ DBG1(DBG_PTS, "deleted %d registered %N '%N' functional component "
+ "evidence measurements", count, pen_names, vid, names, name);
+ }
+ this->name->destroy(this->name);
+ free(this->keyid.ptr);
+ free(this);
}
- this->name->destroy(this->name);
- free(this->keyid.ptr);
- free(this);
}
/**
* See header
*/
-pts_component_t *pts_ita_comp_tboot_create(u_int8_t qualifier, u_int32_t depth,
+pts_component_t *pts_ita_comp_tboot_create(u_int32_t depth,
pts_database_t *pts_db)
{
pts_ita_comp_tboot_t *this;
@@ -321,13 +357,16 @@ pts_component_t *pts_ita_comp_tboot_create(u_int8_t qualifier, u_int32_t depth,
.get_depth = _get_depth,
.measure = _measure,
.verify = _verify,
- .check_off_registrations = _check_off_registrations,
+ .finalize = _finalize,
+ .get_ref = _get_ref,
.destroy = _destroy,
},
.name = pts_comp_func_name_create(PEN_ITA, PTS_ITA_COMP_FUNC_NAME_TBOOT,
- qualifier),
+ PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_TRUSTED),
.depth = depth,
.pts_db = pts_db,
+ .ref = 1,
);
return &this->public;
diff --git a/src/libpts/pts/components/ita/ita_comp_tboot.h b/src/libpts/pts/components/ita/ita_comp_tboot.h
index 39554fbc7..1e1a14831 100644
--- a/src/libpts/pts/components/ita/ita_comp_tboot.h
+++ b/src/libpts/pts/components/ita/ita_comp_tboot.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -26,11 +26,10 @@
/**
* Create a PTS ITS Functional Component object
*
- * @param qualifier PTS Component Functional Name Qualifier
* @param depth Sub-component depth
* @param pts_db PTS measurement database
*/
-pts_component_t* pts_ita_comp_tboot_create(u_int8_t qualifier, u_int32_t depth,
+pts_component_t* pts_ita_comp_tboot_create(u_int32_t depth,
pts_database_t *pts_db);
#endif /** PTS_ITA_COMP_TBOOT_H_ @}*/
diff --git a/src/libpts/pts/components/ita/ita_comp_tgrub.c b/src/libpts/pts/components/ita/ita_comp_tgrub.c
index 0dfd5fd41..986f7ace2 100644
--- a/src/libpts/pts/components/ita/ita_comp_tgrub.c
+++ b/src/libpts/pts/components/ita/ita_comp_tgrub.c
@@ -1,6 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
- *
+ * Copyright (C) 2011-2012 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -50,6 +49,12 @@ struct pts_ita_comp_tgrub_t {
*/
pts_database_t *pts_db;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+
};
METHOD(pts_component_t, get_comp_func_name, pts_comp_func_name_t*,
@@ -71,15 +76,16 @@ METHOD(pts_component_t, get_depth, u_int32_t,
}
METHOD(pts_component_t, measure, status_t,
- pts_ita_comp_tgrub_t *this, pts_t *pts, pts_comp_evidence_t **evidence)
+ pts_ita_comp_tgrub_t *this, u_int8_t qualifier, pts_t *pts,
+ pts_comp_evidence_t **evidence)
{
+ size_t pcr_len;
+ pts_pcr_transform_t pcr_transform;
+ pts_meas_algorithms_t hash_algo;
pts_comp_evidence_t *evid;
u_int32_t extended_pcr;
time_t measurement_time;
chunk_t measurement, pcr_before, pcr_after;
- pts_pcr_transform_t pcr_transform;
- pts_meas_algorithms_t hash_algo;
- size_t hash_size, pcr_len;
/* Provisional implementation for TGRUB */
extended_pcr = PCR_DEBUG;
@@ -91,12 +97,11 @@ METHOD(pts_component_t, measure, status_t,
return FAILED;
}
- hash_algo = pts->get_meas_algorithm(pts);
- hash_size = pts_meas_algo_hash_size(hash_algo);
- pcr_len = pts->get_pcr_len(pts);
+ hash_algo = PTS_MEAS_ALGO_SHA1;
+ pcr_len = HASH_SIZE_SHA1;
pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len);
- measurement = chunk_alloc(hash_size);
+ measurement = chunk_alloc(pcr_len);
memset(measurement.ptr, 0x00, measurement.len);
pcr_before = chunk_alloc(pcr_len);
@@ -112,15 +117,18 @@ METHOD(pts_component_t, measure, status_t,
}
METHOD(pts_component_t, verify, status_t,
- pts_ita_comp_tgrub_t *this, pts_t *pts, pts_comp_evidence_t *evidence)
+ pts_ita_comp_tgrub_t *this, u_int8_t qualifier, pts_t *pts,
+ pts_comp_evidence_t *evidence)
{
bool has_pcr_info;
u_int32_t extended_pcr;
pts_meas_algorithms_t algo;
pts_pcr_transform_t transform;
+ pts_pcr_t *pcrs;
time_t measurement_time;
chunk_t measurement, pcr_before, pcr_after;
+ pcrs = pts->get_pcrs(pts);
measurement = evidence->get_measurement(evidence, &extended_pcr,
&algo, &transform, &measurement_time);
if (extended_pcr != PCR_DEBUG)
@@ -133,32 +141,46 @@ METHOD(pts_component_t, verify, status_t,
has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
if (has_pcr_info)
{
- if (!pts->add_pcr(pts, extended_pcr, pcr_before, pcr_after))
+ if (!chunk_equals(pcr_before, pcrs->get(pcrs, extended_pcr)))
{
- return FAILED;
+ DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to pcr value");
+ }
+ if (pcrs->set(pcrs, extended_pcr, pcr_after))
+ {
+ return SUCCESS;
}
}
return SUCCESS;
}
-METHOD(pts_component_t, check_off_registrations, bool,
- pts_ita_comp_tgrub_t *this)
+METHOD(pts_component_t, finalize, bool,
+ pts_ita_comp_tgrub_t *this, u_int8_t qualifier)
{
return FALSE;
}
+METHOD(pts_component_t, get_ref, pts_component_t*,
+ pts_ita_comp_tgrub_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public;
+}
+
METHOD(pts_component_t, destroy, void,
pts_ita_comp_tgrub_t *this)
{
- this->name->destroy(this->name);
- free(this);
+ if (ref_put(&this->ref))
+ {
+ this->name->destroy(this->name);
+ free(this);
+ }
}
/**
* See header
*/
-pts_component_t *pts_ita_comp_tgrub_create(u_int8_t qualifier, u_int32_t depth,
+pts_component_t *pts_ita_comp_tgrub_create(u_int32_t depth,
pts_database_t *pts_db)
{
pts_ita_comp_tgrub_t *this;
@@ -170,13 +192,16 @@ pts_component_t *pts_ita_comp_tgrub_create(u_int8_t qualifier, u_int32_t depth,
.get_depth = _get_depth,
.measure = _measure,
.verify = _verify,
- .check_off_registrations = _check_off_registrations,
+ .finalize = _finalize,
+ .get_ref = _get_ref,
.destroy = _destroy,
},
.name = pts_comp_func_name_create(PEN_ITA, PTS_ITA_COMP_FUNC_NAME_TGRUB,
- qualifier),
+ PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_TRUSTED),
.depth = depth,
.pts_db = pts_db,
+ .ref = 1,
);
return &this->public;
diff --git a/src/libpts/pts/components/ita/ita_comp_tgrub.h b/src/libpts/pts/components/ita/ita_comp_tgrub.h
index 52ecc325c..59913c82d 100644
--- a/src/libpts/pts/components/ita/ita_comp_tgrub.h
+++ b/src/libpts/pts/components/ita/ita_comp_tgrub.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -26,11 +26,10 @@
/**
* Create a PTS ITS Functional Component object
*
- * @param qualifier PTS Component Functional Name Qualifier
* @param depth Sub-component depth
* @param pts_db PTS measurement database
*/
-pts_component_t* pts_ita_comp_tgrub_create(u_int8_t qualifier, u_int32_t depth,
+pts_component_t* pts_ita_comp_tgrub_create(u_int32_t depth,
pts_database_t *pts_db);
#endif /** PTS_ITA_COMP_TGRUB_H_ @}*/
diff --git a/src/libpts/pts/components/pts_comp_evidence.c b/src/libpts/pts/components/pts_comp_evidence.c
index 9eb8dae75..050717472 100644
--- a/src/libpts/pts/components/pts_comp_evidence.c
+++ b/src/libpts/pts/components/pts_comp_evidence.c
@@ -87,7 +87,7 @@ struct private_pts_comp_evidence_t {
/**
* Verification Policy URI
*/
- chunk_t policy_uri;
+ char *policy_uri;
};
@@ -152,12 +152,12 @@ METHOD(pts_comp_evidence_t, set_pcr_info, void,
this->pcr_before = pcr_before;
this->pcr_after = pcr_after;
- DBG2(DBG_PTS, "PCR %2d before value : %#B", this->extended_pcr, &pcr_before);
- DBG2(DBG_PTS, "PCR %2d after value : %#B", this->extended_pcr, &pcr_after);
+ DBG3(DBG_PTS, "PCR %2d before value : %#B", this->extended_pcr, &pcr_before);
+ DBG3(DBG_PTS, "PCR %2d after value : %#B", this->extended_pcr, &pcr_after);
}
METHOD(pts_comp_evidence_t, get_validation, pts_comp_evid_validation_t,
- private_pts_comp_evidence_t *this, chunk_t *uri)
+ private_pts_comp_evidence_t *this, char **uri)
{
if (uri)
{
@@ -168,10 +168,14 @@ METHOD(pts_comp_evidence_t, get_validation, pts_comp_evid_validation_t,
METHOD(pts_comp_evidence_t, set_validation, void,
private_pts_comp_evidence_t *this, pts_comp_evid_validation_t validation,
- chunk_t uri)
+ char *uri)
{
this->validation = validation;
- this->policy_uri = chunk_clone(uri);
+ if (uri)
+ {
+ this->policy_uri = strdup(uri);
+ DBG3(DBG_PTS, "'%s'", uri);
+ }
}
METHOD(pts_comp_evidence_t, destroy, void,
@@ -181,7 +185,7 @@ METHOD(pts_comp_evidence_t, destroy, void,
free(this->measurement.ptr);
free(this->pcr_before.ptr);
free(this->pcr_after.ptr);
- free(this->policy_uri.ptr);
+ free(this->policy_uri);
free(this);
}
@@ -219,8 +223,8 @@ pts_comp_evidence_t *pts_comp_evidence_create(pts_comp_func_name_t *name,
);
name->log(name, "");
- DBG2(DBG_PTS, "measurement time: %T", &measurement_time, FALSE);
- DBG2(DBG_PTS, "PCR %2d extended with: %#B", extended_pcr, &measurement);
+ DBG3(DBG_PTS, "measurement time: %T", &measurement_time, FALSE);
+ DBG3(DBG_PTS, "PCR %2d extended with: %#B", extended_pcr, &measurement);
return &this->public;
}
diff --git a/src/libpts/pts/components/pts_comp_evidence.h b/src/libpts/pts/components/pts_comp_evidence.h
index fe86aa940..55776ce8b 100644
--- a/src/libpts/pts/components/pts_comp_evidence.h
+++ b/src/libpts/pts/components/pts_comp_evidence.h
@@ -120,7 +120,7 @@ struct pts_comp_evidence_t {
* @return validation Validation Result
*/
pts_comp_evid_validation_t (*get_validation)(pts_comp_evidence_t *this,
- chunk_t *uri);
+ char **uri);
/**
* Sets Validation Result if available
@@ -129,7 +129,7 @@ struct pts_comp_evidence_t {
* @param uri Verification Policy URI
*/
void (*set_validation)(pts_comp_evidence_t *this,
- pts_comp_evid_validation_t validation, chunk_t uri);
+ pts_comp_evid_validation_t validation, char* uri);
/**
* Destroys a pts_comp_evidence_t object.
diff --git a/src/libpts/pts/components/pts_comp_func_name.c b/src/libpts/pts/components/pts_comp_func_name.c
index d98850d78..7501be044 100644
--- a/src/libpts/pts/components/pts_comp_func_name.c
+++ b/src/libpts/pts/components/pts_comp_func_name.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
+ * Copyright (C) 2011-2012 Andreas Steffen
*
* HSR Hochschule fuer Technik Rapperswil
*
@@ -67,6 +67,12 @@ METHOD(pts_comp_func_name_t, get_qualifier, u_int8_t,
return this->qualifier;
}
+METHOD(pts_comp_func_name_t, set_qualifier, void,
+ private_pts_comp_func_name_t *this, u_int8_t qualifier)
+{
+ this->qualifier = qualifier;
+}
+
static bool equals(private_pts_comp_func_name_t *this,
private_pts_comp_func_name_t *other)
{
@@ -137,6 +143,7 @@ pts_comp_func_name_t* pts_comp_func_name_create(u_int32_t vid, u_int32_t name,
.get_vendor_id = _get_vendor_id,
.get_name = _get_name,
.get_qualifier = _get_qualifier,
+ .set_qualifier = _set_qualifier,
.equals = (bool(*)(pts_comp_func_name_t*,pts_comp_func_name_t*))equals,
.clone = _clone_,
.log = _log_,
diff --git a/src/libpts/pts/components/pts_comp_func_name.h b/src/libpts/pts/components/pts_comp_func_name.h
index 2c7a84177..a3ffa1ba9 100644
--- a/src/libpts/pts/components/pts_comp_func_name.h
+++ b/src/libpts/pts/components/pts_comp_func_name.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -55,6 +55,13 @@ struct pts_comp_func_name_t {
u_int8_t (*get_qualifier)(pts_comp_func_name_t *this);
/**
+ * Set the PTS Component Functional Name Qualifier
+ *
+ * @param qualifier PTS Component Functional Name Qualifier to be set
+ */
+ void (*set_qualifier)(pts_comp_func_name_t *this, u_int8_t qualifier);
+
+ /**
* Check to PTS Component Functional Names for equality
*
* @param other Other PTS Component Functional Name
diff --git a/src/libpts/pts/components/pts_component.h b/src/libpts/pts/components/pts_component.h
index 524ff332d..da339a55f 100644
--- a/src/libpts/pts/components/pts_component.h
+++ b/src/libpts/pts/components/pts_component.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
+ * Copyright (C) 2011-2012 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@ typedef struct pts_component_t pts_component_t;
#include "pts/pts.h"
#include "pts/pts_database.h"
+#include "pts/pts_file_meas.h"
#include "pts/components/pts_comp_func_name.h"
#include "pts/components/pts_comp_evidence.h"
@@ -59,30 +60,41 @@ struct pts_component_t {
/**
* Do evidence measurements on the PTS Functional Component
*
+ * @param qualifier PTS Component Functional Name Qualifier
* @param pts PTS interface
* @param evidence returns component evidence measureemt
+ * @param measurements additional file measurements (NULL if not present)
* @return status return code
*/
- status_t (*measure)(pts_component_t *this, pts_t *pts,
+ status_t (*measure)(pts_component_t *this, u_int8_t qualifier, pts_t *pts,
pts_comp_evidence_t** evidence);
/**
* Verify the evidence measurements of the PTS Functional Component
*
+ * @param qualifier PTS Component Functional Name Qualifier
* @param pts PTS interface
* @param evidence component evidence measurement to be verified
* @return status return code
*/
- status_t (*verify)(pts_component_t *this, pts_t *pts,
+ status_t (*verify)(pts_component_t *this, u_int8_t qualifier, pts_t *pts,
pts_comp_evidence_t *evidence);
-
/**
* Tell the PTS Functional Component to finalize pending registrations
+ * and check for missing measurements
+ *
+ * @param qualifier PTS Component Functional Name Qualifier
+ * @return TRUE if finalization successful
+ */
+ bool (*finalize)(pts_component_t *this, u_int8_t qualifier);
+
+ /**
+ * Get a new reference to the PTS Functional Component
*
- * @return TRUE if there are pending registrations
+ * @return this, with an increased refcount
*/
- bool (*check_off_registrations)(pts_component_t *this);
+ pts_component_t* (*get_ref)(pts_component_t *this);
/**
* Destroys a pts_component_t object.
diff --git a/src/libpts/pts/components/pts_component_manager.c b/src/libpts/pts/components/pts_component_manager.c
index 8ac4767bf..e330aeebf 100644
--- a/src/libpts/pts/components/pts_component_manager.c
+++ b/src/libpts/pts/components/pts_component_manager.c
@@ -1,6 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
- *
+ * Copyright (C) 2011-2012 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -270,8 +269,7 @@ METHOD(pts_component_manager_t, create, pts_component_t*,
{
if (entry2->name == name->get_name(name) && entry2->create)
{
- component = entry2->create(name->get_qualifier(name),
- depth, pts_db);
+ component = entry2->create(depth, pts_db);
break;
}
}
diff --git a/src/libpts/pts/components/pts_component_manager.h b/src/libpts/pts/components/pts_component_manager.h
index 0079d0e26..61055ec74 100644
--- a/src/libpts/pts/components/pts_component_manager.h
+++ b/src/libpts/pts/components/pts_component_manager.h
@@ -30,8 +30,7 @@ typedef struct pts_component_manager_t pts_component_manager_t;
#include <library.h>
#include <pen/pen.h>
-typedef pts_component_t* (*pts_component_create_t)(u_int8_t qualifier,
- u_int32_t depth,
+typedef pts_component_t* (*pts_component_create_t)(u_int32_t depth,
pts_database_t *pts_db);
/**
diff --git a/src/libpts/pts/pts.c b/src/libpts/pts/pts.c
index 65ae2b2d2..4c6c5bc22 100644
--- a/src/libpts/pts/pts.c
+++ b/src/libpts/pts/pts.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -23,22 +23,13 @@
#include <trousers/tss.h>
#include <trousers/trousers.h>
+#include <sys/types.h>
#include <sys/stat.h>
#include <sys/utsname.h>
+#include <libgen.h>
+#include <unistd.h>
#include <errno.h>
-#define PTS_BUF_SIZE 4096
-
-/**
- * Maximum number of PCR's of TPM, TPM Spec 1.2
- */
-#define PCR_MAX_NUM 24
-
-/**
- * Number of bytes that can be saved in a PCR of TPM, TPM Spec 1.2
- */
-#define PCR_LEN 20
-
typedef struct private_pts_t private_pts_t;
/**
@@ -118,29 +109,9 @@ struct private_pts_t {
certificate_t *aik;
/**
- * Table of extended PCRs with corresponding values
- */
- u_char* pcrs[PCR_MAX_NUM];
-
- /**
- * Length of PCR registers
- */
- size_t pcr_len;
-
- /**
- * Number of extended PCR registers
- */
- u_int32_t pcr_count;
-
- /**
- * Highest extended PCR register
- */
- u_int32_t pcr_max;
-
- /**
- * Bitmap of extended PCR registers
+ * Shadow PCR set
*/
- u_int8_t pcr_select[PCR_MAX_NUM / 8];
+ pts_pcr_t *pcrs;
};
@@ -225,9 +196,13 @@ METHOD(pts_t, create_dh_nonce, bool,
DBG2(DBG_PTS, "nonce length is %d", nonce_len);
nonce = this->is_imc ? &this->responder_nonce : &this->initiator_nonce;
chunk_free(nonce);
- rng->allocate_bytes(rng, nonce_len, nonce);
+ if (!rng->allocate_bytes(rng, nonce_len, nonce))
+ {
+ DBG1(DBG_PTS, "failed to allocate nonce");
+ rng->destroy(rng);
+ return FALSE;
+ }
rng->destroy(rng);
-
return TRUE;
}
@@ -282,10 +257,15 @@ METHOD(pts_t, calculate_secret, bool,
hash_alg = pts_meas_algo_to_hash(this->dh_hash_algorithm);
hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
- hasher->allocate_hash(hasher, chunk_from_chars('1'), NULL);
- hasher->allocate_hash(hasher, this->initiator_nonce, NULL);
- hasher->allocate_hash(hasher, this->responder_nonce, NULL);
- hasher->allocate_hash(hasher, shared_secret, &this->secret);
+ if (!hasher ||
+ !hasher->get_hash(hasher, chunk_from_chars('1'), NULL) ||
+ !hasher->get_hash(hasher, this->initiator_nonce, NULL) ||
+ !hasher->get_hash(hasher, this->responder_nonce, NULL) ||
+ !hasher->allocate_hash(hasher, shared_secret, &this->secret))
+ {
+ DESTROY_IF(hasher);
+ return FALSE;
+ }
hasher->destroy(hasher);
/* The DH secret must be destroyed */
@@ -359,12 +339,6 @@ METHOD(pts_t, set_tpm_version_info, void,
print_tpm_version_info(this);
}
-METHOD(pts_t, get_pcr_len, size_t,
- private_pts_t *this)
-{
- return this->pcr_len;
-}
-
/**
* Load an AIK Blob (TSS_TSPATTRIB_KEYBLOB_BLOB attribute)
*/
@@ -486,54 +460,6 @@ METHOD(pts_t, get_aik_keyid, bool,
return success;
}
-METHOD(pts_t, hash_file, bool,
- private_pts_t *this, hasher_t *hasher, char *pathname, u_char *hash)
-{
- u_char buffer[PTS_BUF_SIZE];
- FILE *file;
- int bytes_read;
-
- file = fopen(pathname, "rb");
- if (!file)
- {
- DBG1(DBG_PTS," file '%s' can not be opened, %s", pathname,
- strerror(errno));
- return FALSE;
- }
- while (TRUE)
- {
- bytes_read = fread(buffer, 1, sizeof(buffer), file);
- if (bytes_read > 0)
- {
- hasher->get_hash(hasher, chunk_create(buffer, bytes_read), NULL);
- }
- else
- {
- hasher->get_hash(hasher, chunk_empty, hash);
- break;
- }
- }
- fclose(file);
-
- return TRUE;
-}
-
-/**
- * Get the relative filename of a fully qualified file pathname
- */
-static char* get_filename(char *pathname)
-{
- char *pos, *filename;
-
- pos = filename = pathname;
- while (pos && *(++pos) != '\0')
- {
- filename = pos;
- pos = strchr(filename, '/');
- }
- return filename;
-}
-
METHOD(pts_t, is_path_valid, bool,
private_pts_t *this, char *path, pts_error_code_t *error_code)
{
@@ -565,82 +491,6 @@ METHOD(pts_t, is_path_valid, bool,
return TRUE;
}
-METHOD(pts_t, do_measurements, pts_file_meas_t*,
- private_pts_t *this, u_int16_t request_id, char *pathname, bool is_directory)
-{
- hasher_t *hasher;
- hash_algorithm_t hash_alg;
- u_char hash[HASH_SIZE_SHA384];
- chunk_t measurement;
- pts_file_meas_t *measurements;
-
- /* Create a hasher */
- hash_alg = pts_meas_algo_to_hash(this->algorithm);
- hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
- if (!hasher)
- {
- DBG1(DBG_PTS, "hasher %N not available", hash_algorithm_names, hash_alg);
- return NULL;
- }
-
- /* Create a measurement object */
- measurements = pts_file_meas_create(request_id);
-
- /* Link the hash to the measurement and set the measurement length */
- measurement = chunk_create(hash, hasher->get_hash_size(hasher));
-
- if (is_directory)
- {
- enumerator_t *enumerator;
- char *rel_name, *abs_name;
- struct stat st;
-
- enumerator = enumerator_create_directory(pathname);
- if (!enumerator)
- {
- DBG1(DBG_PTS," directory '%s' can not be opened, %s", pathname,
- strerror(errno));
- hasher->destroy(hasher);
- measurements->destroy(measurements);
- return NULL;
- }
- while (enumerator->enumerate(enumerator, &rel_name, &abs_name, &st))
- {
- /* measure regular files only */
- if (S_ISREG(st.st_mode) && *rel_name != '.')
- {
- if (!hash_file(this, hasher, abs_name, hash))
- {
- enumerator->destroy(enumerator);
- hasher->destroy(hasher);
- measurements->destroy(measurements);
- return NULL;
- }
- DBG2(DBG_PTS, " %#B for '%s'", &measurement, rel_name);
- measurements->add(measurements, rel_name, measurement);
- }
- }
- enumerator->destroy(enumerator);
- }
- else
- {
- char *filename;
-
- if (!hash_file(this, hasher, pathname, hash))
- {
- hasher->destroy(hasher);
- measurements->destroy(measurements);
- return NULL;
- }
- filename = get_filename(pathname);
- DBG2(DBG_PTS, " %#B for '%s'", &measurement, filename);
- measurements->add(measurements, filename, measurement);
- }
- hasher->destroy(hasher);
-
- return measurements;
-}
-
/**
* Obtain statistical information describing a file
*/
@@ -654,6 +504,7 @@ static bool file_metadata(char *pathname, pts_file_metadata_t **entry)
if (stat(pathname, &st))
{
DBG1(DBG_PTS, "unable to obtain statistics about '%s'", pathname);
+ free(this);
return FALSE;
}
@@ -748,7 +599,7 @@ METHOD(pts_t, get_metadata, pts_file_meta_t*,
metadata->destroy(metadata);
return NULL;
}
- entry->filename = strdup(get_filename(pathname));
+ entry->filename = strdup(basename(pathname));
metadata->add(metadata, entry);
}
@@ -809,7 +660,7 @@ METHOD(pts_t, extend_pcr, bool,
TSS_HTPM hTPM;
TSS_RESULT result;
u_int32_t pcr_length;
- chunk_t pcr_value;
+ chunk_t pcr_value = chunk_empty;
result = Tspi_Context_Create(&hContext);
if (result != TSS_SUCCESS)
@@ -829,8 +680,8 @@ METHOD(pts_t, extend_pcr, bool,
goto err;
}
- pcr_value = chunk_alloc(PCR_LEN);
- result = Tspi_TPM_PcrExtend(hTPM, pcr_num, PCR_LEN, input.ptr,
+ pcr_value = chunk_alloc(PTS_PCR_LEN);
+ result = Tspi_TPM_PcrExtend(hTPM, pcr_num, PTS_PCR_LEN, input.ptr,
NULL, &pcr_length, &pcr_value.ptr);
if (result != TSS_SUCCESS)
{
@@ -842,7 +693,7 @@ METHOD(pts_t, extend_pcr, bool,
DBG3(DBG_PTS, "PCR %d extended with: %B", pcr_num, &input);
DBG3(DBG_PTS, "PCR %d value after extend: %B", pcr_num, output);
-
+
chunk_clear(&pcr_value);
Tspi_Context_FreeMemory(hContext, NULL);
Tspi_Context_Close(hContext);
@@ -851,28 +702,12 @@ METHOD(pts_t, extend_pcr, bool,
err:
DBG1(DBG_PTS, "TPM not available: tss error 0x%x", result);
-
+
chunk_clear(&pcr_value);
Tspi_Context_FreeMemory(hContext, NULL);
Tspi_Context_Close(hContext);
-
- return FALSE;
-}
-
-
-static void clear_pcrs(private_pts_t *this)
-{
- int i;
- for (i = 0; i <= this->pcr_max; i++)
- {
- free(this->pcrs[i]);
- this->pcrs[i] = NULL;
- }
- this->pcr_count = 0;
- this->pcr_max = 0;
-
- memset(this->pcr_select, 0x00, sizeof(this->pcr_select));
+ return FALSE;
}
METHOD(pts_t, quote_tpm, bool,
@@ -890,7 +725,8 @@ METHOD(pts_t, quote_tpm, bool,
TSS_RESULT result;
chunk_t quote_info;
BYTE* versionInfo;
- u_int32_t versionInfoSize, pcr, i = 0, f = 1;
+ u_int32_t versionInfoSize, pcr;
+ enumerator_t *enumerator;
bool success = FALSE;
result = Tspi_Context_Create(&hContext);
@@ -943,32 +779,30 @@ METHOD(pts_t, quote_tpm, bool,
Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_PCRS,
TSS_PCRS_STRUCT_INFO_SHORT, &hPcrComposite) :
Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_PCRS,
- 0, &hPcrComposite);
+ TSS_PCRS_STRUCT_DEFAULT, &hPcrComposite);
if (result != TSS_SUCCESS)
{
goto err2;
}
/* Select PCRs */
- for (pcr = 0; pcr <= this->pcr_max ; pcr++)
- {
- if (f == 256)
+ enumerator = this->pcrs->create_enumerator(this->pcrs);
+ while (enumerator->enumerate(enumerator, &pcr))
+ {
+ result = use_quote2 ?
+ Tspi_PcrComposite_SelectPcrIndexEx(hPcrComposite, pcr,
+ TSS_PCRS_DIRECTION_RELEASE) :
+ Tspi_PcrComposite_SelectPcrIndex(hPcrComposite, pcr);
+ if (result != TSS_SUCCESS)
{
- i++;
- f = 1;
- }
- if (this->pcr_select[i] & f)
- {
- result = use_quote2 ?
- Tspi_PcrComposite_SelectPcrIndexEx(hPcrComposite, pcr,
- TSS_PCRS_DIRECTION_RELEASE) :
- Tspi_PcrComposite_SelectPcrIndex(hPcrComposite, pcr);
- if (result != TSS_SUCCESS)
- {
- goto err3;
- }
+ break;
}
- f <<= 1;
+ }
+ enumerator->destroy(enumerator);
+
+ if (result != TSS_SUCCESS)
+ {
+ goto err3;
}
/* Set the Validation Data */
@@ -1028,87 +862,14 @@ err1:
{
DBG1(DBG_PTS, "TPM not available: tss error 0x%x", result);
}
- clear_pcrs(this);
return success;
}
-METHOD(pts_t, select_pcr, bool,
- private_pts_t *this, u_int32_t pcr)
-{
- u_int32_t i, f;
-
- if (pcr >= PCR_MAX_NUM)
- {
- DBG1(DBG_PTS, "PCR %u: number is larger than maximum of %u",
- pcr, PCR_MAX_NUM-1);
- return FALSE;
- }
-
- /* Determine PCR selection flag */
- i = pcr / 8;
- f = 1 << (pcr - 8*i);
-
- /* Has this PCR already been selected? */
- if (!(this->pcr_select[i] & f))
- {
- this->pcr_select[i] |= f;
- this->pcr_max = max(this->pcr_max, pcr);
- this->pcr_count++;
- }
-
- return TRUE;
-}
-
-METHOD(pts_t, add_pcr, bool,
- private_pts_t *this, u_int32_t pcr, chunk_t pcr_before, chunk_t pcr_after)
+METHOD(pts_t, get_pcrs, pts_pcr_t*,
+ private_pts_t *this)
{
- if (pcr >= PCR_MAX_NUM)
- {
- DBG1(DBG_PTS, "PCR %u: number is larger than maximum of %u",
- pcr, PCR_MAX_NUM-1);
- return FALSE;
- }
-
- /* Is the length of the PCR registers already set? */
- if (this->pcr_len)
- {
- if (pcr_after.len != this->pcr_len)
- {
- DBG1(DBG_PTS, "PCR %02u: length is %d bytes but should be %d bytes",
- pcr_after.len, this->pcr_len);
- return FALSE;
- }
- }
- else
- {
- this->pcr_len = pcr_after.len;
- }
-
- /* Has the value of the PCR register already been assigned? */
- if (this->pcrs[pcr])
- {
- if (!memeq(this->pcrs[pcr], pcr_before.ptr, this->pcr_len))
- {
- DBG1(DBG_PTS, "PCR %02u: new pcr_before value does not equal "
- "old pcr_after value");
- }
- /* remove the old PCR value */
- free(this->pcrs[pcr]);
- }
- else
- {
- /* add extended PCR Register */
- this->pcr_select[pcr / 8] |= 1 << (pcr % 8);
- this->pcr_max = max(this->pcr_max, pcr);
- this->pcr_count++;
- }
-
- /* Duplicate and store current PCR value */
- pcr_after = chunk_clone(pcr_after);
- this->pcrs[pcr] = pcr_after.ptr;
-
- return TRUE;
+ return this->pcrs;
}
/**
@@ -1130,13 +891,11 @@ METHOD(pts_t, get_quote_info, bool,
pts_meas_algorithms_t comp_hash_algo,
chunk_t *out_pcr_comp, chunk_t *out_quote_info)
{
- u_int8_t size_of_select;
- int pcr_comp_len, i;
- chunk_t pcr_comp, hash_pcr_comp;
+ chunk_t selection, pcr_comp, hash_pcr_comp;
bio_writer_t *writer;
hasher_t *hasher;
- if (this->pcr_count == 0)
+ if (!this->pcrs->get_count(this->pcrs))
{
DBG1(DBG_PTS, "No extended PCR entries available, "
"unable to construct TPM Quote Info");
@@ -1154,34 +913,9 @@ METHOD(pts_t, get_quote_info, bool,
"unable to construct TPM Quote Info2");
return FALSE;
}
-
- /**
- * A TPM v1.2 has 24 PCR Registers
- * so the bitmask field length used by TrouSerS is at least 3 bytes
- */
- size_of_select = max(PCR_MAX_NUM / 8, 1 + this->pcr_max / 8);
- pcr_comp_len = 2 + size_of_select + 4 + this->pcr_count * this->pcr_len;
-
- writer = bio_writer_create(pcr_comp_len);
-
- writer->write_uint16(writer, size_of_select);
- for (i = 0; i < size_of_select; i++)
- {
- writer->write_uint8(writer, this->pcr_select[i]);
- }
- writer->write_uint32(writer, this->pcr_count * this->pcr_len);
- for (i = 0; i < 8 * size_of_select; i++)
- {
- if (this->pcrs[i])
- {
- writer->write_data(writer, chunk_create(this->pcrs[i], this->pcr_len));
- }
- }
- pcr_comp = chunk_clone(writer->get_buf(writer));
- DBG3(DBG_PTS, "constructed PCR Composite: %B", &pcr_comp);
+ pcr_comp = this->pcrs->get_composite(this->pcrs);
- writer->destroy(writer);
/* Output the TPM_PCR_COMPOSITE expected from IMC */
if (comp_hash_algo)
@@ -1192,7 +926,12 @@ METHOD(pts_t, get_quote_info, bool,
hasher = lib->crypto->create_hasher(lib->crypto, algo);
/* Hash the PCR Composite Structure */
- hasher->allocate_hash(hasher, pcr_comp, out_pcr_comp);
+ if (!hasher || !hasher->allocate_hash(hasher, pcr_comp, out_pcr_comp))
+ {
+ DESTROY_IF(hasher);
+ free(pcr_comp.ptr);
+ return FALSE;
+ }
DBG3(DBG_PTS, "constructed PCR Composite hash: %#B", out_pcr_comp);
hasher->destroy(hasher);
}
@@ -1203,7 +942,13 @@ METHOD(pts_t, get_quote_info, bool,
/* SHA1 hash of PCR Composite to construct TPM_QUOTE_INFO */
hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
- hasher->allocate_hash(hasher, pcr_comp, &hash_pcr_comp);
+ if (!hasher || !hasher->allocate_hash(hasher, pcr_comp, &hash_pcr_comp))
+ {
+ DESTROY_IF(hasher);
+ chunk_free(out_pcr_comp);
+ free(pcr_comp.ptr);
+ return FALSE;
+ }
hasher->destroy(hasher);
/* Construct TPM_QUOTE_INFO/TPM_QUOTE_INFO2 structure */
@@ -1220,15 +965,11 @@ METHOD(pts_t, get_quote_info, bool,
/* Secret assessment value 20 bytes (nonce) */
writer->write_data(writer, this->secret);
- /* Length of the PCR selection field */
- writer->write_uint16(writer, size_of_select);
-
/* PCR selection */
- for (i = 0; i < size_of_select ; i++)
- {
- writer->write_uint8(writer, this->pcr_select[i]);
- }
-
+ selection.ptr = pcr_comp.ptr;
+ selection.len = 2 + this->pcrs->get_selection_size(this->pcrs);
+ writer->write_data(writer, selection);
+
/* TPM Locality Selection */
writer->write_uint8(writer, TPM_LOC_ZERO);
@@ -1263,7 +1004,6 @@ METHOD(pts_t, get_quote_info, bool,
writer->destroy(writer);
free(pcr_comp.ptr);
free(hash_pcr_comp.ptr);
- clear_pcrs(this);
return TRUE;
}
@@ -1295,7 +1035,7 @@ METHOD(pts_t, verify_quote_signature, bool,
METHOD(pts_t, destroy, void,
private_pts_t *this)
{
- clear_pcrs(this);
+ DESTROY_IF(this->pcrs);
DESTROY_IF(this->aik);
DESTROY_IF(this->dh);
free(this->initiator_nonce.ptr);
@@ -1357,7 +1097,7 @@ static char* extract_platform_info(void)
{
strcpy(buf, str_debian);
pos += strlen(str_debian);
- len -= strlen(str_debian);
+ len -= strlen(str_debian);
}
fseek(file, 0, SEEK_END);
@@ -1477,6 +1217,14 @@ static bool has_tpm(private_pts_t *this)
pts_t *pts_create(bool is_imc)
{
private_pts_t *this;
+ pts_pcr_t *pcrs;
+
+ pcrs = pts_pcr_create();
+ if (!pcrs)
+ {
+ DBG1(DBG_PTS, "shadow PCR set could not be created");
+ return NULL;
+ }
INIT(this,
.public = {
@@ -1494,19 +1242,15 @@ pts_t *pts_create(bool is_imc)
.set_platform_info = _set_platform_info,
.get_tpm_version_info = _get_tpm_version_info,
.set_tpm_version_info = _set_tpm_version_info,
- .get_pcr_len = _get_pcr_len,
.get_aik = _get_aik,
.set_aik = _set_aik,
.get_aik_keyid = _get_aik_keyid,
.is_path_valid = _is_path_valid,
- .hash_file = _hash_file,
- .do_measurements = _do_measurements,
.get_metadata = _get_metadata,
.read_pcr = _read_pcr,
.extend_pcr = _extend_pcr,
.quote_tpm = _quote_tpm,
- .select_pcr = _select_pcr,
- .add_pcr = _add_pcr,
+ .get_pcrs = _get_pcrs,
.get_quote_info = _get_quote_info,
.verify_quote_signature = _verify_quote_signature,
.destroy = _destroy,
@@ -1515,6 +1259,7 @@ pts_t *pts_create(bool is_imc)
.proto_caps = PTS_PROTO_CAPS_V,
.algorithm = PTS_MEAS_ALGO_SHA256,
.dh_hash_algorithm = PTS_MEAS_ALGO_SHA256,
+ .pcrs = pcrs,
);
if (is_imc)
@@ -1524,7 +1269,6 @@ pts_t *pts_create(bool is_imc)
if (has_tpm(this))
{
this->has_tpm = TRUE;
- this->pcr_len = PCR_LEN;
this->proto_caps |= PTS_PROTO_CAPS_T | PTS_PROTO_CAPS_D;
load_aik(this);
load_aik_blob(this);
diff --git a/src/libpts/pts/pts.h b/src/libpts/pts/pts.h
index 212acb02a..5f88cd15c 100644
--- a/src/libpts/pts/pts.h
+++ b/src/libpts/pts/pts.h
@@ -29,6 +29,7 @@ typedef struct pts_t pts_t;
#include "pts_file_meas.h"
#include "pts_file_meta.h"
#include "pts_dh_group.h"
+#include "pts_pcr.h"
#include "pts_req_func_comp_evid.h"
#include "pts_simple_evid_final.h"
#include "components/pts_comp_func_name.h"
@@ -190,13 +191,6 @@ struct pts_t {
void (*set_tpm_version_info)(pts_t *this, chunk_t info);
/**
- * Get the length of the TPM PCR registers
- *
- * @return Length of PCR registers in bytes, 0 if undefined
- */
- size_t (*get_pcr_len)(pts_t *this);
-
- /**
* Get Attestation Identity Certificate or Public Key
*
* @return AIK Certificate or Public Key
@@ -230,34 +224,13 @@ struct pts_t {
bool (*is_path_valid)(pts_t *this, char *path, pts_error_code_t *error_code);
/**
- * Compute a hash over a file
- * @param hasher Hasher to be used
- * @param pathname Absolute path of a file
- * @param hash Buffer to keep hash output
- * @return TRUE if path is valid and hashing succeeded
- */
- bool (*hash_file)(pts_t *this, hasher_t *hasher, char *pathname, u_char *hash);
-
- /**
- * Do PTS File Measurements
- *
- * @param request_id ID of PTS File Measurement Request
- * @param pathname Absolute pathname of file to be measured
- * @param is_directory TRUE if directory contents are measured
- * @return PTS File Measurements of NULL if FAILED
- */
- pts_file_meas_t* (*do_measurements)(pts_t *this, u_int16_t request_id,
- char *pathname, bool is_directory);
-
- /**
* Obtain file metadata
*
* @param pathname Absolute pathname of file/directory
- * @param is_directory TRUE if directory contents are requested
+ * @param is_dir TRUE if directory contents are requested
* @return PTS File Metadata or NULL if FAILED
*/
- pts_file_meta_t* (*get_metadata)(pts_t *this, char *pathname,
- bool is_directory);
+ pts_file_meta_t* (*get_metadata)(pts_t *this, char *pathname, bool is_dir);
/**
* Reads given PCR value and returns it
@@ -294,24 +267,12 @@ struct pts_t {
bool (*quote_tpm)(pts_t *this, bool use_quote2, chunk_t *pcr_comp,
chunk_t *quote_sig);
- /**
- * Mark an extended PCR as selected
- *
- * @param pcr Number of the extended PCR
- * @return TRUE if PCR number is valid
- */
- bool (*select_pcr)(pts_t *this, u_int32_t pcr);
-
- /**
- * Add an extended PCR with its corresponding value
+ /**
+ * Get the shadow PCR set
*
- * @param pcr Number of the extended PCR
- * @param pcr_before PCR value before extension
- * @param pcr_after PCR value after extension
- * @return TRUE if PCR number and register length is valid
+ * @return shadow PCR set
*/
- bool (*add_pcr)(pts_t *this, u_int32_t pcr, chunk_t pcr_before,
- chunk_t pcr_after);
+ pts_pcr_t* (*get_pcrs)(pts_t *this);
/**
* Constructs and returns TPM Quote Info structure expected from IMC
diff --git a/src/libpts/pts/pts_database.c b/src/libpts/pts/pts_database.c
index 282755c0a..946f37e1e 100644
--- a/src/libpts/pts/pts_database.c
+++ b/src/libpts/pts/pts_database.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -121,6 +121,42 @@ METHOD(pts_database_t, check_aik_keyid, status_t,
return SUCCESS;
}
+METHOD(pts_database_t, check_file_measurement, status_t,
+ private_pts_database_t *this, char *product, pts_meas_algorithms_t algo,
+ chunk_t measurement, char *filename)
+{
+ enumerator_t *e;
+ chunk_t hash;
+ status_t status = NOT_FOUND;
+
+ e = this->db->query(this->db,
+ "SELECT fh.hash FROM file_hashes AS fh "
+ "JOIN files AS f ON f.id = fh.file "
+ "JOIN products AS p ON p.id = fh.product "
+ "WHERE p.name = ? AND f.path = ? AND fh.algo = ?",
+ DB_TEXT, product, DB_TEXT, filename, DB_INT, algo, DB_BLOB);
+ if (!e)
+ {
+ return FAILED;
+ }
+ while (e->enumerate(e, &hash))
+ {
+ /* with relative filenames there might be multiple entries */
+ if (chunk_equals(measurement, hash))
+ {
+ status = SUCCESS;
+ break;
+ }
+ else
+ {
+ status = VERIFY_ERROR;
+ }
+ }
+ e->destroy(e);
+
+ return status;
+}
+
METHOD(pts_database_t, create_comp_evid_enumerator, enumerator_t*,
private_pts_database_t *this, int kid)
{
@@ -169,7 +205,7 @@ METHOD(pts_database_t, check_comp_measurement, status_t,
"found in database", pcr, seq_no);
DBG1(DBG_PTS, " expected: %#B", &hash);
DBG1(DBG_PTS, " received: %#B", &measurement);
- status = FAILED;
+ status = VERIFY_ERROR;
break;
}
}
@@ -290,6 +326,7 @@ pts_database_t *pts_database_create(char *uri)
.create_comp_evid_enumerator = _create_comp_evid_enumerator,
.create_file_hash_enumerator = _create_file_hash_enumerator,
.check_aik_keyid = _check_aik_keyid,
+ .check_file_measurement = _check_file_measurement,
.check_comp_measurement = _check_comp_measurement,
.insert_comp_measurement = _insert_comp_measurement,
.delete_comp_measurements = _delete_comp_measurements,
diff --git a/src/libpts/pts/pts_database.h b/src/libpts/pts/pts_database.h
index a9a68ac76..649ef0e31 100644
--- a/src/libpts/pts/pts_database.h
+++ b/src/libpts/pts/pts_database.h
@@ -82,6 +82,19 @@ struct pts_database_t {
enumerator_t* (*create_comp_evid_enumerator)(pts_database_t *this, int kid);
/**
+ * Check PTS file measurement against reference stored in database
+ *
+ * @param product Software product (os, vpn client, etc.)
+ * @param algo File measurement hash algorithm used
+ * @param measurement File measurement hash
+ * @param filename Optional name of the file to be checked
+ * @return Status
+ */
+ status_t (*check_file_measurement)(pts_database_t *this, char *product,
+ pts_meas_algorithms_t algo,
+ chunk_t measurement, char *filename);
+
+ /**
* Check a functional component measurement against value stored in database
*
* @param measurement measurement hash
diff --git a/src/libpts/pts/pts_error.c b/src/libpts/pts/pts_error.c
index 6e914b2a9..1e79689f9 100644
--- a/src/libpts/pts/pts_error.c
+++ b/src/libpts/pts/pts_error.c
@@ -46,13 +46,13 @@ pa_tnc_attr_t* pts_hash_alg_error_create(pts_meas_algorithms_t algorithms)
bio_writer_t *writer;
chunk_t msg_info;
pa_tnc_attr_t *attr;
+ pen_type_t error_code = { PEN_TCG, TCG_PTS_HASH_ALG_NOT_SUPPORTED };
writer = bio_writer_create(4);
writer->write_uint16(writer, 0x0000);
writer->write_uint16(writer, algorithms);
msg_info = writer->get_buf(writer);
- attr = ietf_attr_pa_tnc_error_create(PEN_TCG, TCG_PTS_HASH_ALG_NOT_SUPPORTED,
- msg_info);
+ attr = ietf_attr_pa_tnc_error_create(error_code, msg_info);
writer->destroy(writer);
return attr;
@@ -66,13 +66,13 @@ pa_tnc_attr_t* pts_dh_group_error_create(pts_dh_group_t dh_groups)
bio_writer_t *writer;
chunk_t msg_info;
pa_tnc_attr_t *attr;
+ pen_type_t error_code = { PEN_TCG, TCG_PTS_DH_GRPS_NOT_SUPPORTED };
writer = bio_writer_create(4);
writer->write_uint16(writer, 0x0000);
writer->write_uint16(writer, dh_groups);
msg_info = writer->get_buf(writer);
- attr = ietf_attr_pa_tnc_error_create(PEN_TCG, TCG_PTS_DH_GRPS_NOT_SUPPORTED,
- msg_info);
+ attr = ietf_attr_pa_tnc_error_create(error_code, msg_info);
writer->destroy(writer);
return attr;
@@ -86,13 +86,13 @@ pa_tnc_attr_t* pts_dh_nonce_error_create(int min_nonce_len, int max_nonce_len)
bio_writer_t *writer;
chunk_t msg_info;
pa_tnc_attr_t *attr;
+ pen_type_t error_code = { PEN_TCG, TCG_PTS_BAD_NONCE_LENGTH };
writer = bio_writer_create(4);
writer->write_uint16(writer, min_nonce_len);
writer->write_uint16(writer, max_nonce_len);
msg_info = writer->get_buf(writer);
- attr = ietf_attr_pa_tnc_error_create(PEN_TCG, TCG_PTS_BAD_NONCE_LENGTH,
- msg_info);
+ attr = ietf_attr_pa_tnc_error_create(error_code, msg_info);
writer->destroy(writer);
return attr;
diff --git a/src/libpts/pts/pts_file_meas.c b/src/libpts/pts/pts_file_meas.c
index f0e0d4c0a..4fece6b3c 100644
--- a/src/libpts/pts/pts_file_meas.c
+++ b/src/libpts/pts/pts_file_meas.c
@@ -18,6 +18,10 @@
#include <utils/linked_list.h>
#include <debug.h>
+#include <sys/stat.h>
+#include <libgen.h>
+#include <errno.h>
+
typedef struct private_pts_file_meas_t private_pts_file_meas_t;
/**
@@ -107,6 +111,51 @@ METHOD(pts_file_meas_t, create_enumerator, enumerator_t*,
(void*)entry_filter, NULL, NULL);
}
+METHOD(pts_file_meas_t, check, bool,
+ private_pts_file_meas_t *this, pts_database_t *pts_db, char *product,
+ pts_meas_algorithms_t algo)
+{
+ enumerator_t *enumerator;
+ entry_t *entry;
+ int count_ok = 0, count_not_found = 0, count_differ = 0;
+ status_t status;
+
+ enumerator = this->list->create_enumerator(this->list);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ status = pts_db->check_file_measurement(pts_db, product, algo,
+ entry->measurement, entry->filename);
+ switch (status)
+ {
+ case SUCCESS:
+ DBG3(DBG_PTS, " %#B for '%s' is ok", &entry->measurement,
+ entry->filename);
+ count_ok++;
+ break;
+ case NOT_FOUND:
+ DBG2(DBG_PTS, " %#B for '%s' not found", &entry->measurement,
+ entry->filename);
+ count_not_found++;
+ break;
+ case VERIFY_ERROR:
+ DBG1(DBG_PTS, " %#B for '%s' differs", &entry->measurement,
+ entry->filename);
+ count_differ++;
+ break;
+ case FAILED:
+ default:
+ DBG1(DBG_PTS, " %#B for '%s' failed", &entry->measurement,
+ entry->filename);
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ DBG1(DBG_PTS, "%d measurements, %d ok, %d not found, %d differ",
+ this->list->get_count(this->list),
+ count_ok, count_not_found, count_differ);
+ return TRUE;
+}
+
METHOD(pts_file_meas_t, verify, bool,
private_pts_file_meas_t *this, enumerator_t *e_hash, bool is_dir)
{
@@ -174,6 +223,7 @@ pts_file_meas_t *pts_file_meas_create(u_int16_t request_id)
.get_file_count = _get_file_count,
.add = _add,
.create_enumerator = _create_enumerator,
+ .check = _check,
.verify = _verify,
.destroy = _destroy,
},
@@ -184,3 +234,141 @@ pts_file_meas_t *pts_file_meas_create(u_int16_t request_id)
return &this->public;
}
+/**
+ * Hash a file with a given absolute pathname
+ */
+static bool hash_file(hasher_t *hasher, char *pathname, u_char *hash)
+{
+ u_char buffer[4096];
+ size_t bytes_read;
+ bool success = TRUE;
+ FILE *file;
+
+ file = fopen(pathname, "rb");
+ if (!file)
+ {
+ DBG1(DBG_PTS," file '%s' can not be opened, %s", pathname,
+ strerror(errno));
+ return FALSE;
+ }
+ while (TRUE)
+ {
+ bytes_read = fread(buffer, 1, sizeof(buffer), file);
+ if (bytes_read > 0)
+ {
+ if (!hasher->get_hash(hasher, chunk_create(buffer, bytes_read), NULL))
+ {
+ DBG1(DBG_PTS, " hasher increment error");
+ success = FALSE;
+ break;
+ }
+ }
+ else
+ {
+ if (!hasher->get_hash(hasher, chunk_empty, hash))
+ {
+ DBG1(DBG_PTS, " hasher finalize error");
+ success = FALSE;
+ }
+ break;
+ }
+ }
+ fclose(file);
+
+ return success;
+}
+
+/**
+ * See header
+ */
+pts_file_meas_t *pts_file_meas_create_from_path(u_int16_t request_id,
+ char *pathname, bool is_dir, bool use_rel_name,
+ pts_meas_algorithms_t alg)
+{
+ private_pts_file_meas_t *this;
+ hash_algorithm_t hash_alg;
+ hasher_t *hasher;
+ u_char hash[HASH_SIZE_SHA384];
+ chunk_t measurement;
+ char* filename;
+ bool success = TRUE;
+
+ /* Create a hasher and a hash measurement buffer */
+ hash_alg = pts_meas_algo_to_hash(alg);
+ hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
+ if (!hasher)
+ {
+ DBG1(DBG_PTS, "hasher %N not available", hash_algorithm_names, hash_alg);
+ return NULL;
+ }
+ measurement = chunk_create(hash, hasher->get_hash_size(hasher));
+
+ INIT(this,
+ .public = {
+ .get_request_id = _get_request_id,
+ .get_file_count = _get_file_count,
+ .add = _add,
+ .create_enumerator = _create_enumerator,
+ .check = _check,
+ .verify = _verify,
+ .destroy = _destroy,
+ },
+ .request_id = request_id,
+ .list = linked_list_create(),
+ );
+
+ if (is_dir)
+ {
+ enumerator_t *enumerator;
+ char *rel_name, *abs_name;
+ struct stat st;
+
+ enumerator = enumerator_create_directory(pathname);
+ if (!enumerator)
+ {
+ DBG1(DBG_PTS, " directory '%s' can not be opened, %s", pathname,
+ strerror(errno));
+ success = FALSE;
+ goto end;
+ }
+ while (enumerator->enumerate(enumerator, &rel_name, &abs_name, &st))
+ {
+ /* measure regular files only */
+ if (S_ISREG(st.st_mode) && *rel_name != '.')
+ {
+ if (!hash_file(hasher, abs_name, hash))
+ {
+ success = FALSE;
+ break;
+ }
+ filename = use_rel_name ? rel_name : abs_name;
+ DBG2(DBG_PTS, " %#B for '%s'", &measurement, filename);
+ add(this, filename, measurement);
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ else
+ {
+ if (!hash_file(hasher, pathname, hash))
+ {
+ success = FALSE;
+ goto end;
+ }
+ filename = use_rel_name ? basename(pathname) : pathname;
+ DBG2(DBG_PTS, " %#B for '%s'", &measurement, filename);
+ add(this, filename, measurement);
+ }
+
+end:
+ hasher->destroy(hasher);
+ if (success)
+ {
+ return &this->public;
+ }
+ else
+ {
+ destroy(this);
+ return NULL;
+ }
+}
diff --git a/src/libpts/pts/pts_file_meas.h b/src/libpts/pts/pts_file_meas.h
index 3ebb5c2a0..71efd5026 100644
--- a/src/libpts/pts/pts_file_meas.h
+++ b/src/libpts/pts/pts_file_meas.h
@@ -21,6 +21,8 @@
#ifndef PTS_FILE_MEAS_H_
#define PTS_FILE_MEAS_H_
+#include "pts/pts_database.h"
+
#include <library.h>
typedef struct pts_file_meas_t pts_file_meas_t;
@@ -60,6 +62,17 @@ struct pts_file_meas_t {
enumerator_t* (*create_enumerator)(pts_file_meas_t *this);
/**
+ * Check PTS File Measurements against reference value in the database
+ *
+ * @param db PTS Measurement database
+ * @param product Software product (os, vpn client, etc.)
+ * @param algo PTS Measurement algorithm used
+ * @return TRUE if all measurements agreed
+ */
+ bool (*check)(pts_file_meas_t *this, pts_database_t *db, char* product,
+ pts_meas_algorithms_t algo);
+
+ /**
* Verify stored hashes against PTS File Measurements
*
* @param e_hash Hash enumerator
@@ -82,4 +95,17 @@ struct pts_file_meas_t {
*/
pts_file_meas_t* pts_file_meas_create(u_int16_t request_id);
+/**
+ * Creates a pts_file_meas_t object measuring a file/directory
+ *
+ * @param request_id ID of PTS File Measurement Request
+ * @param pathname Absolute file or directory pathname
+ * @param is_dir TRUE if directory path
+ * @param use_rel_name TRUE if relative filenames are to be used
+ * @param alg PTS hash measurement algorithm to be used
+ */
+pts_file_meas_t* pts_file_meas_create_from_path(u_int16_t request_id,
+ char* pathname, bool is_dir, bool use_rel_name,
+ pts_meas_algorithms_t alg);
+
#endif /** PTS_FILE_MEAS_H_ @}*/
diff --git a/src/libpts/pts/pts_meas_algo.c b/src/libpts/pts/pts_meas_algo.c
index 865857d3c..fbc9c6959 100644
--- a/src/libpts/pts/pts_meas_algo.c
+++ b/src/libpts/pts/pts_meas_algo.c
@@ -17,12 +17,21 @@
#include <debug.h>
-ENUM(pts_meas_algorithm_names, PTS_MEAS_ALGO_NONE, PTS_MEAS_ALGO_SHA384,
- "None",
- "SHA1",
- "SHA256",
- "SHA384"
-);
+ENUM_BEGIN(pts_meas_algorithm_names, PTS_MEAS_ALGO_NONE, PTS_MEAS_ALGO_NONE,
+ "None");
+ENUM_NEXT(pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA384, PTS_MEAS_ALGO_SHA384,
+ PTS_MEAS_ALGO_NONE,
+ "SHA384");
+ENUM_NEXT(pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA256, PTS_MEAS_ALGO_SHA256,
+ PTS_MEAS_ALGO_SHA384,
+ "SHA256");
+ENUM_NEXT(pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA1, PTS_MEAS_ALGO_SHA1,
+ PTS_MEAS_ALGO_SHA256,
+ "SHA1");
+ENUM_NEXT(pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA1_IMA, PTS_MEAS_ALGO_SHA1_IMA,
+ PTS_MEAS_ALGO_SHA1,
+ "SHA1-IMA");
+ENUM_END(pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA1_IMA);
/**
* Described in header.
diff --git a/src/libpts/pts/pts_meas_algo.h b/src/libpts/pts/pts_meas_algo.h
index 1d96a4946..27cdaea7e 100644
--- a/src/libpts/pts/pts_meas_algo.h
+++ b/src/libpts/pts/pts_meas_algo.h
@@ -30,10 +30,11 @@ typedef enum pts_meas_algorithms_t pts_meas_algorithms_t;
* PTS Measurement Algorithms
*/
enum pts_meas_algorithms_t {
- PTS_MEAS_ALGO_NONE = 0,
- PTS_MEAS_ALGO_SHA1 = (1<<15),
- PTS_MEAS_ALGO_SHA256 = (1<<14),
- PTS_MEAS_ALGO_SHA384 = (1<<13),
+ PTS_MEAS_ALGO_NONE = 0,
+ PTS_MEAS_ALGO_SHA384 = (1<<13),
+ PTS_MEAS_ALGO_SHA256 = (1<<14),
+ PTS_MEAS_ALGO_SHA1 = (1<<15),
+ PTS_MEAS_ALGO_SHA1_IMA = (1<<16), /* internal use only */
};
/**
diff --git a/src/libpts/pts/pts_pcr.c b/src/libpts/pts/pts_pcr.c
new file mode 100644
index 000000000..a7a2f5fae
--- /dev/null
+++ b/src/libpts/pts/pts_pcr.c
@@ -0,0 +1,289 @@
+/*
+ * 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.
+ */
+
+#include "pts_pcr.h"
+
+#include <debug.h>
+
+#include <stdarg.h>
+
+typedef struct private_pts_pcr_t private_pts_pcr_t;
+
+/**
+ * Private data of a pts_pcr_t object.
+ *
+ */
+struct private_pts_pcr_t {
+
+ /**
+ * Public pts_pcr_t interface.
+ */
+ pts_pcr_t public;
+
+ /**
+ * Shadow PCR registers
+ */
+ chunk_t pcrs[PTS_PCR_MAX_NUM];
+
+ /**
+ * Number of extended PCR registers
+ */
+ u_int32_t pcr_count;
+
+ /**
+ * Highest extended PCR register
+ */
+ u_int32_t pcr_max;
+
+ /**
+ * Bitmap of extended PCR registers
+ */
+ u_int8_t pcr_select[PTS_PCR_MAX_NUM / 8];
+
+ /**
+ * Hasher used to extend shadow PCRs
+ */
+ hasher_t *hasher;
+
+};
+
+METHOD(pts_pcr_t, get_count, u_int32_t,
+ private_pts_pcr_t *this)
+{
+ return this->pcr_count;
+}
+
+METHOD(pts_pcr_t, select_pcr, bool,
+ private_pts_pcr_t *this, u_int32_t pcr)
+{
+ u_int32_t i, f;
+
+ if (pcr >= PTS_PCR_MAX_NUM)
+ {
+ DBG1(DBG_PTS, "PCR %2u: number is larger than maximum of %u",
+ pcr, PTS_PCR_MAX_NUM-1);
+ return FALSE;
+ }
+
+ /* Determine PCR selection flag */
+ i = pcr / 8;
+ f = 1 << (pcr - 8*i);
+
+ /* Has this PCR already been selected? */
+ if (!(this->pcr_select[i] & f))
+ {
+ this->pcr_select[i] |= f;
+ this->pcr_max = max(this->pcr_max, pcr);
+ this->pcr_count++;
+ }
+ return TRUE;
+}
+
+METHOD(pts_pcr_t, get_selection_size, size_t,
+ private_pts_pcr_t *this)
+{
+
+ /**
+ * A TPM v1.2 has 24 PCR Registers so the bitmask field length
+ * used by TrouSerS is at least 3 bytes
+ */
+ return PTS_PCR_MAX_NUM / 8;
+}
+
+typedef struct {
+ /** implements enumerator_t */
+ enumerator_t public;
+ /** current PCR */
+ u_int32_t pcr;
+ /** back reference to parent */
+ private_pts_pcr_t *pcrs;
+} pcr_enumerator_t;
+
+/**
+ * Implementation of enumerator.enumerate
+ */
+static bool pcr_enumerator_enumerate(pcr_enumerator_t *this, ...)
+{
+ u_int32_t *pcr, i, f;
+ va_list args;
+
+ va_start(args, this);
+ pcr = va_arg(args, u_int32_t*);
+ va_end(args);
+
+ while (this->pcr <= this->pcrs->pcr_max)
+ {
+ /* Determine PCR selection flag */
+ i = this->pcr / 8;
+ f = 1 << (this->pcr - 8*i);
+
+ /* Assign current PCR to output argument and increase */
+ *pcr = this->pcr++;
+
+ /* return if PCR is selected */
+ if (this->pcrs->pcr_select[i] & f)
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+METHOD(pts_pcr_t, create_enumerator, enumerator_t*,
+ private_pts_pcr_t *this)
+{
+ pcr_enumerator_t *enumerator;
+
+ INIT(enumerator,
+ .public = {
+ .enumerate = (void*)pcr_enumerator_enumerate,
+ .destroy = (void*)free,
+ },
+ .pcrs = this,
+ );
+
+ return (enumerator_t*)enumerator;
+}
+
+METHOD(pts_pcr_t, get, chunk_t,
+ private_pts_pcr_t *this, u_int32_t pcr)
+{
+ return (pcr < PTS_PCR_MAX_NUM) ? this->pcrs[pcr] : chunk_empty;
+}
+
+METHOD(pts_pcr_t, set, bool,
+ private_pts_pcr_t *this, u_int32_t pcr, chunk_t value)
+{
+ if (value.len != PTS_PCR_LEN)
+ {
+ DBG1(DBG_PTS, "PCR %2u: value does not fit", pcr);
+ return FALSE;
+ }
+ if (select_pcr(this, pcr))
+ {
+ memcpy(this->pcrs[pcr].ptr, value.ptr, PTS_PCR_LEN);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+METHOD(pts_pcr_t, extend, chunk_t,
+ private_pts_pcr_t *this, u_int32_t pcr, chunk_t measurement)
+{
+ if (measurement.len != PTS_PCR_LEN)
+ {
+ DBG1(DBG_PTS, "PCR %2u: measurement does not fit", pcr);
+ return chunk_empty;
+ }
+ if (!select_pcr(this, pcr))
+ {
+ return chunk_empty;
+ }
+ if (!this->hasher->get_hash(this->hasher, this->pcrs[pcr] , NULL) ||
+ !this->hasher->get_hash(this->hasher, measurement, this->pcrs[pcr].ptr))
+ {
+ DBG1(DBG_PTS, "PCR %2u: not extended due to hasher problem", pcr);
+ return chunk_empty;
+ }
+ return this->pcrs[pcr];
+}
+
+METHOD(pts_pcr_t, get_composite, chunk_t,
+ private_pts_pcr_t *this)
+{
+ chunk_t composite;
+ enumerator_t *enumerator;
+ u_int16_t selection_size;
+ u_int32_t pcr_field_size, pcr;
+ u_char *pos;
+
+ selection_size = get_selection_size(this);
+ pcr_field_size = this->pcr_count * PTS_PCR_LEN;
+
+ composite = chunk_alloc(2 + selection_size + 4 + pcr_field_size);
+ pos = composite.ptr;
+ htoun16(pos, selection_size);
+ pos += 2;
+ memcpy(pos, this->pcr_select, selection_size);
+ pos += selection_size;
+ htoun32(pos, pcr_field_size);
+ pos += 4;
+
+ enumerator = create_enumerator(this);
+ while (enumerator->enumerate(enumerator, &pcr))
+ {
+ memcpy(pos, this->pcrs[pcr].ptr, PTS_PCR_LEN);
+ pos += PTS_PCR_LEN;
+ }
+ enumerator->destroy(enumerator);
+
+ DBG3(DBG_PTS, "constructed PCR Composite: %B", &composite);
+ return composite;
+}
+
+METHOD(pts_pcr_t, destroy, void,
+ private_pts_pcr_t *this)
+{
+ u_int32_t i;
+
+ for (i = 0; i < PTS_PCR_MAX_NUM; i++)
+ {
+ free(this->pcrs[i].ptr);
+ }
+ this->hasher->destroy(this->hasher);
+ free(this);
+}
+
+/**
+ * See header
+ */
+pts_pcr_t *pts_pcr_create(void)
+{
+ private_pts_pcr_t *this;
+ hasher_t *hasher;
+ u_int32_t i;
+
+ hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+ if (!hasher)
+ {
+ DBG1(DBG_PTS, "%N hasher could not be created",
+ hash_algorithm_short_names, HASH_SHA1);
+ return NULL;
+ }
+
+ INIT(this,
+ .public = {
+ .get_count = _get_count,
+ .select_pcr = _select_pcr,
+ .get_selection_size = _get_selection_size,
+ .create_enumerator = _create_enumerator,
+ .get = _get,
+ .set = _set,
+ .extend = _extend,
+ .get_composite = _get_composite,
+ .destroy = _destroy,
+ },
+ .hasher = hasher,
+ );
+
+ for (i = 0; i < PTS_PCR_MAX_NUM; i++)
+ {
+ this->pcrs[i] = chunk_alloc(PTS_PCR_LEN);
+ memset(this->pcrs[i].ptr, 0x00, PTS_PCR_LEN);
+ }
+
+ return &this->public;
+}
+
diff --git a/src/libpts/pts/pts_pcr.h b/src/libpts/pts/pts_pcr.h
new file mode 100644
index 000000000..f638b5ee4
--- /dev/null
+++ b/src/libpts/pts/pts_pcr.h
@@ -0,0 +1,118 @@
+/*
+ * 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 pts_pcr pts_pcr
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_PCR_H_
+#define PTS_PCR_H_
+
+typedef struct pts_pcr_t pts_pcr_t;
+
+#include <library.h>
+
+/**
+ * Maximum number of PCR's of TPM, TPM Spec 1.2
+ */
+#define PTS_PCR_MAX_NUM 24
+
+/**
+ * Number of bytes that can be saved in a PCR of TPM, TPM Spec 1.2
+ */
+#define PTS_PCR_LEN 20
+
+/**
+ * Class implementing a shadow PCR register set
+ */
+struct pts_pcr_t {
+
+ /**
+ * Get the number of selected PCRs
+ *
+ * @return number of selected PCRs
+ */
+ u_int32_t (*get_count)(pts_pcr_t *this);
+
+ /**
+ * Mark a PCR as selected
+ *
+ * @param pcr index of PCR
+ * @return TRUE if PCR index exists
+ */
+ bool (*select_pcr)(pts_pcr_t *this, u_int32_t pcr);
+
+ /**
+ * Get the size of the selection field in bytes
+ *
+ * @return number of bytes written
+ */
+ size_t (*get_selection_size)(pts_pcr_t *this);
+
+ /**
+ * Create an enumerator over all selected PCR indexes
+ *
+ * @return enumerator
+ */
+ enumerator_t* (*create_enumerator)(pts_pcr_t *this);
+
+ /**
+ * Get the current content of a PCR
+ *
+ * @param pcr index of PCR
+ * @return content of PCR
+ */
+ chunk_t (*get)(pts_pcr_t *this, u_int32_t pcr);
+
+ /**
+ * Set the content of a PCR
+ *
+ * @param pcr index of PCR
+ * @param value new value of PCR
+ * @return TRUE if value could be set
+ */
+ bool (*set)(pts_pcr_t *this, u_int32_t pcr, chunk_t value);
+
+ /**
+ * Extend the content of a PCR
+ *
+ * @param pcr index of PCR
+ * @param measurement measurment value to be extended into PCR
+ * @return new content of PCR
+ */
+ chunk_t (*extend)(pts_pcr_t *this, u_int32_t pcr, chunk_t measurement);
+
+ /**
+ * Create a PCR Composite object over all selected PCRs
+ *
+ * @return PCR Composite object (must be freed)
+ */
+ chunk_t (*get_composite)(pts_pcr_t *this);
+
+ /**
+
+ * Destroys a pts_pcr_t object.
+ */
+ void (*destroy)(pts_pcr_t *this);
+
+};
+
+/**
+ * Creates an pts_pcr_t object
+ */
+pts_pcr_t* pts_pcr_create(void);
+
+#endif /** PTS_PCR_H_ @}*/
diff --git a/src/libpts/tcg/tcg_pts_attr_aik.c b/src/libpts/tcg/tcg_pts_attr_aik.c
index 9be3794b6..75f3f179c 100644
--- a/src/libpts/tcg/tcg_pts_attr_aik.c
+++ b/src/libpts/tcg/tcg_pts_attr_aik.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -49,14 +49,9 @@ struct private_tcg_pts_attr_aik_t {
tcg_pts_attr_aik_t public;
/**
- * Attribute vendor ID
+ * Vendor-specific attribute type
*/
- pen_t vendor_id;
-
- /**
- * Attribute type
- */
- u_int32_t type;
+ pen_type_t type;
/**
* Attribute value
@@ -79,13 +74,7 @@ struct private_tcg_pts_attr_aik_t {
refcount_t ref;
};
-METHOD(pa_tnc_attr_t, get_vendor_id, pen_t,
- private_tcg_pts_attr_aik_t *this)
-{
- return this->vendor_id;
-}
-
-METHOD(pa_tnc_attr_t, get_type, u_int32_t,
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
private_tcg_pts_attr_aik_t *this)
{
return this->type;
@@ -117,6 +106,10 @@ METHOD(pa_tnc_attr_t, build, void,
cred_encoding_type_t encoding_type = CERT_ASN1_DER;
chunk_t aik_blob;
+ if (this->value.ptr)
+ {
+ return;
+ }
if (this->aik->get_type(this->aik) == CERT_TRUSTED_PUBKEY)
{
flags |= PTS_AIK_FLAGS_NAKED_KEY;
@@ -202,7 +195,6 @@ pa_tnc_attr_t *tcg_pts_attr_aik_create(certificate_t *aik)
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -214,8 +206,7 @@ pa_tnc_attr_t *tcg_pts_attr_aik_create(certificate_t *aik)
},
.get_aik = _get_aik,
},
- .vendor_id = PEN_TCG,
- .type = TCG_PTS_AIK,
+ .type = { PEN_TCG, TCG_PTS_AIK },
.aik = aik->get_ref(aik),
.ref = 1,
);
@@ -234,7 +225,6 @@ pa_tnc_attr_t *tcg_pts_attr_aik_create_from_data(chunk_t data)
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -246,8 +236,7 @@ pa_tnc_attr_t *tcg_pts_attr_aik_create_from_data(chunk_t data)
},
.get_aik = _get_aik,
},
- .vendor_id = PEN_TCG,
- .type = TCG_PTS_AIK,
+ .type = { PEN_TCG, TCG_PTS_AIK },
.value = chunk_clone(data),
.ref = 1,
);
diff --git a/src/libpts/tcg/tcg_pts_attr_dh_nonce_finish.c b/src/libpts/tcg/tcg_pts_attr_dh_nonce_finish.c
index dce98e87d..3ca255cba 100644
--- a/src/libpts/tcg/tcg_pts_attr_dh_nonce_finish.c
+++ b/src/libpts/tcg/tcg_pts_attr_dh_nonce_finish.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -53,14 +53,9 @@ struct private_tcg_pts_attr_dh_nonce_finish_t {
tcg_pts_attr_dh_nonce_finish_t public;
/**
- * Attribute vendor ID
+ * Vendor-specific attribute type
*/
- pen_t vendor_id;
-
- /**
- * Attribute type
- */
- u_int32_t type;
+ pen_type_t type;
/**
* Attribute value
@@ -93,13 +88,7 @@ struct private_tcg_pts_attr_dh_nonce_finish_t {
refcount_t ref;
};
-METHOD(pa_tnc_attr_t, get_vendor_id, pen_t,
- private_tcg_pts_attr_dh_nonce_finish_t *this)
-{
- return this->vendor_id;
-}
-
-METHOD(pa_tnc_attr_t, get_type, u_int32_t,
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
private_tcg_pts_attr_dh_nonce_finish_t *this)
{
return this->type;
@@ -128,6 +117,10 @@ METHOD(pa_tnc_attr_t, build, void,
{
bio_writer_t *writer;
+ if (this->value.ptr)
+ {
+ return;
+ }
writer = bio_writer_create(PTS_DH_NONCE_FINISH_SIZE);
writer->write_uint8 (writer, PTS_DH_NONCE_FINISH_RESERVED);
writer->write_uint8 (writer, this->initiator_nonce.len);
@@ -217,7 +210,6 @@ pa_tnc_attr_t *tcg_pts_attr_dh_nonce_finish_create(
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -231,8 +223,7 @@ pa_tnc_attr_t *tcg_pts_attr_dh_nonce_finish_create(
.get_initiator_nonce = _get_initiator_nonce,
.get_initiator_value = _get_initiator_value,
},
- .vendor_id = PEN_TCG,
- .type = TCG_PTS_DH_NONCE_FINISH,
+ .type = { PEN_TCG, TCG_PTS_DH_NONCE_FINISH },
.hash_algo = hash_algo,
.initiator_value = initiator_value,
.initiator_nonce = chunk_clone(initiator_nonce),
@@ -252,7 +243,6 @@ pa_tnc_attr_t *tcg_pts_attr_dh_nonce_finish_create_from_data(chunk_t value)
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -266,8 +256,7 @@ pa_tnc_attr_t *tcg_pts_attr_dh_nonce_finish_create_from_data(chunk_t value)
.get_initiator_nonce = _get_initiator_nonce,
.get_initiator_value = _get_initiator_value,
},
- .vendor_id = PEN_TCG,
- .type = TCG_PTS_DH_NONCE_FINISH,
+ .type = { PEN_TCG, TCG_PTS_DH_NONCE_FINISH },
.value = chunk_clone(value),
.ref = 1,
);
diff --git a/src/libpts/tcg/tcg_pts_attr_dh_nonce_params_req.c b/src/libpts/tcg/tcg_pts_attr_dh_nonce_params_req.c
index 36266fe12..828c09605 100644
--- a/src/libpts/tcg/tcg_pts_attr_dh_nonce_params_req.c
+++ b/src/libpts/tcg/tcg_pts_attr_dh_nonce_params_req.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -49,14 +49,9 @@ struct private_tcg_pts_attr_dh_nonce_params_req_t {
tcg_pts_attr_dh_nonce_params_req_t public;
/**
- * Attribute vendor ID
+ * Vendor-specific attribute type
*/
- pen_t vendor_id;
-
- /**
- * Attribute type
- */
- u_int32_t type;
+ pen_type_t type;
/**
* Attribute value
@@ -84,13 +79,7 @@ struct private_tcg_pts_attr_dh_nonce_params_req_t {
refcount_t ref;
};
-METHOD(pa_tnc_attr_t, get_vendor_id, pen_t,
- private_tcg_pts_attr_dh_nonce_params_req_t *this)
-{
- return this->vendor_id;
-}
-
-METHOD(pa_tnc_attr_t, get_type, u_int32_t,
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
private_tcg_pts_attr_dh_nonce_params_req_t *this)
{
return this->type;
@@ -119,6 +108,10 @@ METHOD(pa_tnc_attr_t, build, void,
{
bio_writer_t *writer;
+ if (this->value.ptr)
+ {
+ return;
+ }
writer = bio_writer_create(PTS_DH_NONCE_PARAMS_REQ_SIZE);
writer->write_uint8 (writer, PTS_DH_NONCE_PARAMS_REQ_RESERVED);
writer->write_uint8 (writer, this->min_nonce_len);
@@ -191,7 +184,6 @@ pa_tnc_attr_t *tcg_pts_attr_dh_nonce_params_req_create(u_int8_t min_nonce_len,
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -204,8 +196,7 @@ pa_tnc_attr_t *tcg_pts_attr_dh_nonce_params_req_create(u_int8_t min_nonce_len,
.get_min_nonce_len = _get_min_nonce_len,
.get_dh_groups = _get_dh_groups,
},
- .vendor_id = PEN_TCG,
- .type = TCG_PTS_DH_NONCE_PARAMS_REQ,
+ .type = { PEN_TCG, TCG_PTS_DH_NONCE_PARAMS_REQ },
.min_nonce_len = min_nonce_len,
.dh_groups = dh_groups,
.ref = 1,
@@ -224,7 +215,6 @@ pa_tnc_attr_t *tcg_pts_attr_dh_nonce_params_req_create_from_data(chunk_t value)
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -237,8 +227,7 @@ pa_tnc_attr_t *tcg_pts_attr_dh_nonce_params_req_create_from_data(chunk_t value)
.get_min_nonce_len = _get_min_nonce_len,
.get_dh_groups = _get_dh_groups,
},
- .vendor_id = PEN_TCG,
- .type = TCG_PTS_DH_NONCE_PARAMS_REQ,
+ .type = { PEN_TCG, TCG_PTS_DH_NONCE_PARAMS_REQ },
.value = chunk_clone(value),
.ref = 1,
);
diff --git a/src/libpts/tcg/tcg_pts_attr_dh_nonce_params_resp.c b/src/libpts/tcg/tcg_pts_attr_dh_nonce_params_resp.c
index 09bfa3aac..66ac185b3 100644
--- a/src/libpts/tcg/tcg_pts_attr_dh_nonce_params_resp.c
+++ b/src/libpts/tcg/tcg_pts_attr_dh_nonce_params_resp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -55,14 +55,9 @@ struct private_tcg_pts_attr_dh_nonce_params_resp_t {
tcg_pts_attr_dh_nonce_params_resp_t public;
/**
- * Attribute vendor ID
+ * Vendor-specific attribute type
*/
- pen_t vendor_id;
-
- /**
- * Attribute type
- */
- u_int32_t type;
+ pen_type_t type;
/**
* Attribute value
@@ -100,13 +95,7 @@ struct private_tcg_pts_attr_dh_nonce_params_resp_t {
refcount_t ref;
};
-METHOD(pa_tnc_attr_t, get_vendor_id, pen_t,
- private_tcg_pts_attr_dh_nonce_params_resp_t *this)
-{
- return this->vendor_id;
-}
-
-METHOD(pa_tnc_attr_t, get_type, u_int32_t,
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
private_tcg_pts_attr_dh_nonce_params_resp_t *this)
{
return this->type;
@@ -135,6 +124,10 @@ METHOD(pa_tnc_attr_t, build, void,
{
bio_writer_t *writer;
+ if (this->value.ptr)
+ {
+ return;
+ }
writer = bio_writer_create(PTS_DH_NONCE_PARAMS_RESP_SIZE);
writer->write_uint24(writer, PTS_DH_NONCE_PARAMS_RESP_RESERVED);
writer->write_uint8 (writer, this->responder_nonce.len);
@@ -233,7 +226,6 @@ pa_tnc_attr_t *tcg_pts_attr_dh_nonce_params_resp_create(pts_dh_group_t dh_group,
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -248,8 +240,7 @@ pa_tnc_attr_t *tcg_pts_attr_dh_nonce_params_resp_create(pts_dh_group_t dh_group,
.get_responder_nonce = _get_responder_nonce,
.get_responder_value = _get_responder_value,
},
- .vendor_id = PEN_TCG,
- .type = TCG_PTS_DH_NONCE_PARAMS_RESP,
+ .type = { PEN_TCG, TCG_PTS_DH_NONCE_PARAMS_RESP },
.dh_group = dh_group,
.hash_algo_set = hash_algo_set,
.responder_nonce = chunk_clone(responder_nonce),
@@ -270,7 +261,6 @@ pa_tnc_attr_t *tcg_pts_attr_dh_nonce_params_resp_create_from_data(chunk_t value)
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -285,8 +275,7 @@ pa_tnc_attr_t *tcg_pts_attr_dh_nonce_params_resp_create_from_data(chunk_t value)
.get_responder_nonce = _get_responder_nonce,
.get_responder_value = _get_responder_value,
},
- .vendor_id = PEN_TCG,
- .type = TCG_PTS_DH_NONCE_PARAMS_RESP,
+ .type = { PEN_TCG, TCG_PTS_DH_NONCE_PARAMS_RESP },
.value = chunk_clone(value),
.ref = 1,
);
diff --git a/src/libpts/tcg/tcg_pts_attr_file_meas.c b/src/libpts/tcg/tcg_pts_attr_file_meas.c
index 737da65c1..01c4361e1 100644
--- a/src/libpts/tcg/tcg_pts_attr_file_meas.c
+++ b/src/libpts/tcg/tcg_pts_attr_file_meas.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -64,14 +64,9 @@ struct private_tcg_pts_attr_file_meas_t {
tcg_pts_attr_file_meas_t public;
/**
- * Attribute vendor ID
+ * Vendor-specific attribute type
*/
- pen_t vendor_id;
-
- /**
- * Attribute type
- */
- u_int32_t type;
+ pen_type_t type;
/**
* Attribute value
@@ -94,13 +89,7 @@ struct private_tcg_pts_attr_file_meas_t {
refcount_t ref;
};
-METHOD(pa_tnc_attr_t, get_vendor_id, pen_t,
- private_tcg_pts_attr_file_meas_t *this)
-{
- return this->vendor_id;
-}
-
-METHOD(pa_tnc_attr_t, get_type, u_int32_t,
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
private_tcg_pts_attr_file_meas_t *this)
{
return this->type;
@@ -135,6 +124,10 @@ METHOD(pa_tnc_attr_t, build, void,
chunk_t measurement;
bool first = TRUE;
+ if (this->value.ptr)
+ {
+ return;
+ }
number_of_files = this->measurements->get_file_count(this->measurements);
request_id = this->measurements->get_request_id(this->measurements);
@@ -254,7 +247,6 @@ pa_tnc_attr_t *tcg_pts_attr_file_meas_create(pts_file_meas_t *measurements)
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -266,8 +258,7 @@ pa_tnc_attr_t *tcg_pts_attr_file_meas_create(pts_file_meas_t *measurements)
},
.get_measurements = _get_measurements,
},
- .vendor_id = PEN_TCG,
- .type = TCG_PTS_FILE_MEAS,
+ .type = { PEN_TCG, TCG_PTS_FILE_MEAS },
.measurements = measurements,
.ref = 1,
);
@@ -286,7 +277,6 @@ pa_tnc_attr_t *tcg_pts_attr_file_meas_create_from_data(chunk_t data)
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -298,8 +288,7 @@ pa_tnc_attr_t *tcg_pts_attr_file_meas_create_from_data(chunk_t data)
},
.get_measurements = _get_measurements,
},
- .vendor_id = PEN_TCG,
- .type = TCG_PTS_FILE_MEAS,
+ .type = { PEN_TCG, TCG_PTS_FILE_MEAS },
.value = chunk_clone(data),
.ref = 1,
);
diff --git a/src/libpts/tcg/tcg_pts_attr_gen_attest_evid.c b/src/libpts/tcg/tcg_pts_attr_gen_attest_evid.c
index 054285c4e..5eac5ecae 100644
--- a/src/libpts/tcg/tcg_pts_attr_gen_attest_evid.c
+++ b/src/libpts/tcg/tcg_pts_attr_gen_attest_evid.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -50,14 +50,9 @@ struct private_tcg_pts_attr_gen_attest_evid_t {
tcg_pts_attr_gen_attest_evid_t public;
/**
- * Attribute vendor ID
+ * Vendor-specific attribute type
*/
- pen_t vendor_id;
-
- /**
- * Attribute type
- */
- u_int32_t type;
+ pen_type_t type;
/**
* Attribute value
@@ -75,13 +70,7 @@ struct private_tcg_pts_attr_gen_attest_evid_t {
refcount_t ref;
};
-METHOD(pa_tnc_attr_t, get_vendor_id, pen_t,
- private_tcg_pts_attr_gen_attest_evid_t *this)
-{
- return this->vendor_id;
-}
-
-METHOD(pa_tnc_attr_t, get_type, u_int32_t,
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
private_tcg_pts_attr_gen_attest_evid_t *this)
{
return this->type;
@@ -110,6 +99,10 @@ METHOD(pa_tnc_attr_t, build, void,
{
bio_writer_t *writer;
+ if (this->value.ptr)
+ {
+ return;
+ }
writer = bio_writer_create(PTS_GEN_ATTEST_EVID_SIZE);
writer->write_uint32 (writer, PTS_GEN_ATTEST_EVID_RESERVED);
@@ -163,7 +156,6 @@ pa_tnc_attr_t *tcg_pts_attr_gen_attest_evid_create()
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -174,8 +166,7 @@ pa_tnc_attr_t *tcg_pts_attr_gen_attest_evid_create()
.destroy = _destroy,
},
},
- .vendor_id = PEN_TCG,
- .type = TCG_PTS_GEN_ATTEST_EVID,
+ .type = { PEN_TCG, TCG_PTS_GEN_ATTEST_EVID },
.ref = 1,
);
@@ -193,7 +184,6 @@ pa_tnc_attr_t *tcg_pts_attr_gen_attest_evid_create_from_data(chunk_t data)
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -204,8 +194,7 @@ pa_tnc_attr_t *tcg_pts_attr_gen_attest_evid_create_from_data(chunk_t data)
.destroy = _destroy,
},
},
- .vendor_id = PEN_TCG,
- .type = TCG_PTS_GEN_ATTEST_EVID,
+ .type = { PEN_TCG, TCG_PTS_GEN_ATTEST_EVID },
.value = chunk_clone(data),
.ref = 1,
);
diff --git a/src/libpts/tcg/tcg_pts_attr_get_aik.c b/src/libpts/tcg/tcg_pts_attr_get_aik.c
index 1875375a4..4b5eae7a7 100644
--- a/src/libpts/tcg/tcg_pts_attr_get_aik.c
+++ b/src/libpts/tcg/tcg_pts_attr_get_aik.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -47,14 +47,9 @@ struct private_tcg_pts_attr_get_aik_t {
tcg_pts_attr_get_aik_t public;
/**
- * Attribute vendor ID
+ * Vendor-specific attribute type
*/
- pen_t vendor_id;
-
- /**
- * Attribute type
- */
- u_int32_t type;
+ pen_type_t type;
/**
* Attribute value
@@ -72,13 +67,7 @@ struct private_tcg_pts_attr_get_aik_t {
refcount_t ref;
};
-METHOD(pa_tnc_attr_t, get_vendor_id, pen_t,
- private_tcg_pts_attr_get_aik_t *this)
-{
- return this->vendor_id;
-}
-
-METHOD(pa_tnc_attr_t, get_type, u_int32_t,
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
private_tcg_pts_attr_get_aik_t *this)
{
return this->type;
@@ -107,6 +96,10 @@ METHOD(pa_tnc_attr_t, build, void,
{
bio_writer_t *writer;
+ if (this->value.ptr)
+ {
+ return;
+ }
writer = bio_writer_create(PTS_GET_AIK_SIZE);
writer->write_uint32 (writer, PTS_GET_AIK_RESERVED);
@@ -160,7 +153,6 @@ pa_tnc_attr_t *tcg_pts_attr_get_aik_create()
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -171,8 +163,7 @@ pa_tnc_attr_t *tcg_pts_attr_get_aik_create()
.destroy = _destroy,
},
},
- .vendor_id = PEN_TCG,
- .type = TCG_PTS_GET_AIK,
+ .type = { PEN_TCG, TCG_PTS_GET_AIK },
.ref = 1,
);
@@ -190,7 +181,6 @@ pa_tnc_attr_t *tcg_pts_attr_get_aik_create_from_data(chunk_t data)
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -201,8 +191,7 @@ pa_tnc_attr_t *tcg_pts_attr_get_aik_create_from_data(chunk_t data)
.destroy = _destroy,
},
},
- .vendor_id = PEN_TCG,
- .type = TCG_PTS_GET_AIK,
+ .type = { PEN_TCG, TCG_PTS_GET_AIK },
.value = chunk_clone(data),
.ref = 1,
);
diff --git a/src/libpts/tcg/tcg_pts_attr_get_tpm_version_info.c b/src/libpts/tcg/tcg_pts_attr_get_tpm_version_info.c
index cb6834ca5..0cfc7efa9 100644
--- a/src/libpts/tcg/tcg_pts_attr_get_tpm_version_info.c
+++ b/src/libpts/tcg/tcg_pts_attr_get_tpm_version_info.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -50,14 +50,9 @@ struct private_tcg_pts_attr_get_tpm_version_info_t {
tcg_pts_attr_get_tpm_version_info_t public;
/**
- * Attribute vendor ID
+ * Vendor-specific attribute type
*/
- pen_t vendor_id;
-
- /**
- * Attribute type
- */
- u_int32_t type;
+ pen_type_t type;
/**
* Attribute value
@@ -75,13 +70,7 @@ struct private_tcg_pts_attr_get_tpm_version_info_t {
refcount_t ref;
};
-METHOD(pa_tnc_attr_t, get_vendor_id, pen_t,
- private_tcg_pts_attr_get_tpm_version_info_t *this)
-{
- return this->vendor_id;
-}
-
-METHOD(pa_tnc_attr_t, get_type, u_int32_t,
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
private_tcg_pts_attr_get_tpm_version_info_t *this)
{
return this->type;
@@ -110,6 +99,10 @@ METHOD(pa_tnc_attr_t, build, void,
{
bio_writer_t *writer;
+ if (this->value.ptr)
+ {
+ return;
+ }
writer = bio_writer_create(PTS_GET_TPM_VER_INFO_SIZE);
writer->write_uint32 (writer, PTS_GET_TPM_VER_INFO_RESERVED);
@@ -163,7 +156,6 @@ pa_tnc_attr_t *tcg_pts_attr_get_tpm_version_info_create()
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -174,8 +166,7 @@ pa_tnc_attr_t *tcg_pts_attr_get_tpm_version_info_create()
.destroy = _destroy,
},
},
- .vendor_id = PEN_TCG,
- .type = TCG_PTS_GET_TPM_VERSION_INFO,
+ .type = { PEN_TCG, TCG_PTS_GET_TPM_VERSION_INFO },
.ref = 1,
);
@@ -193,7 +184,6 @@ pa_tnc_attr_t *tcg_pts_attr_get_tpm_version_info_create_from_data(chunk_t data)
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -204,8 +194,7 @@ pa_tnc_attr_t *tcg_pts_attr_get_tpm_version_info_create_from_data(chunk_t data)
.destroy = _destroy,
},
},
- .vendor_id = PEN_TCG,
- .type = TCG_PTS_GET_TPM_VERSION_INFO,
+ .type = { PEN_TCG, TCG_PTS_GET_TPM_VERSION_INFO },
.value = chunk_clone(data),
.ref = 1,
);
diff --git a/src/libpts/tcg/tcg_pts_attr_meas_algo.c b/src/libpts/tcg/tcg_pts_attr_meas_algo.c
index ed520e3cd..bb95adc9e 100644
--- a/src/libpts/tcg/tcg_pts_attr_meas_algo.c
+++ b/src/libpts/tcg/tcg_pts_attr_meas_algo.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -48,14 +48,9 @@ struct private_tcg_pts_attr_meas_algo_t {
tcg_pts_attr_meas_algo_t public;
/**
- * Attribute vendor ID
+ * Vendor-specific attribute type
*/
- pen_t vendor_id;
-
- /**
- * Attribute type
- */
- u_int32_t type;
+ pen_type_t type;
/**
* Attribute value
@@ -78,13 +73,7 @@ struct private_tcg_pts_attr_meas_algo_t {
refcount_t ref;
};
-METHOD(pa_tnc_attr_t, get_vendor_id, pen_t,
- private_tcg_pts_attr_meas_algo_t *this)
-{
- return this->vendor_id;
-}
-
-METHOD(pa_tnc_attr_t, get_type, u_int32_t,
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
private_tcg_pts_attr_meas_algo_t *this)
{
return this->type;
@@ -113,6 +102,10 @@ METHOD(pa_tnc_attr_t, build, void,
{
bio_writer_t *writer;
+ if (this->value.ptr)
+ {
+ return;
+ }
writer = bio_writer_create(PTS_MEAS_ALGO_SIZE);
writer->write_uint16(writer, PTS_MEAS_ALGO_RESERVED);
writer->write_uint16(writer, this->algorithms);
@@ -175,7 +168,6 @@ pa_tnc_attr_t *tcg_pts_attr_meas_algo_create(pts_meas_algorithms_t algorithms,
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -187,8 +179,8 @@ pa_tnc_attr_t *tcg_pts_attr_meas_algo_create(pts_meas_algorithms_t algorithms,
},
.get_algorithms = _get_algorithms,
},
- .vendor_id = PEN_TCG,
- .type = selection ? TCG_PTS_MEAS_ALGO_SELECTION : TCG_PTS_MEAS_ALGO,
+ .type = { PEN_TCG,
+ selection ? TCG_PTS_MEAS_ALGO_SELECTION : TCG_PTS_MEAS_ALGO },
.algorithms = algorithms,
.ref = 1,
);
@@ -208,7 +200,6 @@ pa_tnc_attr_t *tcg_pts_attr_meas_algo_create_from_data(chunk_t data,
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -220,8 +211,8 @@ pa_tnc_attr_t *tcg_pts_attr_meas_algo_create_from_data(chunk_t data,
},
.get_algorithms = _get_algorithms,
},
- .vendor_id = PEN_TCG,
- .type = selection ? TCG_PTS_MEAS_ALGO_SELECTION : TCG_PTS_MEAS_ALGO,
+ .type = { PEN_TCG,
+ selection ? TCG_PTS_MEAS_ALGO_SELECTION : TCG_PTS_MEAS_ALGO },
.value = chunk_clone(data),
.ref = 1,
);
diff --git a/src/libpts/tcg/tcg_pts_attr_proto_caps.c b/src/libpts/tcg/tcg_pts_attr_proto_caps.c
index 055c750ff..83665ff69 100644
--- a/src/libpts/tcg/tcg_pts_attr_proto_caps.c
+++ b/src/libpts/tcg/tcg_pts_attr_proto_caps.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -48,14 +48,9 @@ struct private_tcg_pts_attr_proto_caps_t {
tcg_pts_attr_proto_caps_t public;
/**
- * Attribute vendor ID
+ * Vendor-specific attribute type
*/
- pen_t vendor_id;
-
- /**
- * Attribute type
- */
- u_int32_t type;
+ pen_type_t type;
/**
* Attribute value
@@ -78,13 +73,7 @@ struct private_tcg_pts_attr_proto_caps_t {
refcount_t ref;
};
-METHOD(pa_tnc_attr_t, get_vendor_id, pen_t,
- private_tcg_pts_attr_proto_caps_t *this)
-{
- return this->vendor_id;
-}
-
-METHOD(pa_tnc_attr_t, get_type, u_int32_t,
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
private_tcg_pts_attr_proto_caps_t *this)
{
return this->type;
@@ -113,6 +102,10 @@ METHOD(pa_tnc_attr_t, build, void,
{
bio_writer_t *writer;
+ if (this->value.ptr)
+ {
+ return;
+ }
writer = bio_writer_create(PTS_PROTO_CAPS_SIZE);
writer->write_uint16(writer, PTS_PROTO_CAPS_RESERVED);
writer->write_uint16(writer, this->flags);
@@ -176,7 +169,6 @@ pa_tnc_attr_t *tcg_pts_attr_proto_caps_create(pts_proto_caps_flag_t flags,
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -188,8 +180,8 @@ pa_tnc_attr_t *tcg_pts_attr_proto_caps_create(pts_proto_caps_flag_t flags,
},
.get_flags = _get_flags,
},
- .vendor_id = PEN_TCG,
- .type = request ? TCG_PTS_REQ_PROTO_CAPS : TCG_PTS_PROTO_CAPS,
+ .type = { PEN_TCG,
+ request ? TCG_PTS_REQ_PROTO_CAPS : TCG_PTS_PROTO_CAPS },
.flags = flags,
.ref = 1,
);
@@ -208,7 +200,6 @@ pa_tnc_attr_t *tcg_pts_attr_proto_caps_create_from_data(chunk_t data,
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -220,8 +211,8 @@ pa_tnc_attr_t *tcg_pts_attr_proto_caps_create_from_data(chunk_t data,
},
.get_flags = _get_flags,
},
- .vendor_id = PEN_TCG,
- .type = request ? TCG_PTS_REQ_PROTO_CAPS : TCG_PTS_PROTO_CAPS,
+ .type = { PEN_TCG,
+ request ? TCG_PTS_REQ_PROTO_CAPS : TCG_PTS_PROTO_CAPS },
.value = chunk_clone(data),
.ref = 1,
);
diff --git a/src/libpts/tcg/tcg_pts_attr_req_file_meas.c b/src/libpts/tcg/tcg_pts_attr_req_file_meas.c
index 17781f745..65bdff579 100644
--- a/src/libpts/tcg/tcg_pts_attr_req_file_meas.c
+++ b/src/libpts/tcg/tcg_pts_attr_req_file_meas.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -54,14 +54,9 @@ struct private_tcg_pts_attr_req_file_meas_t {
tcg_pts_attr_req_file_meas_t public;
/**
- * Attribute vendor ID
+ * Vendor-specific attribute type
*/
- pen_t vendor_id;
-
- /**
- * Attribute type
- */
- u_int32_t type;
+ pen_type_t type;
/**
* Attribute value
@@ -99,13 +94,7 @@ struct private_tcg_pts_attr_req_file_meas_t {
refcount_t ref;
};
-METHOD(pa_tnc_attr_t, get_vendor_id, pen_t,
- private_tcg_pts_attr_req_file_meas_t *this)
-{
- return this->vendor_id;
-}
-
-METHOD(pa_tnc_attr_t, get_type, u_int32_t,
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
private_tcg_pts_attr_req_file_meas_t *this)
{
return this->type;
@@ -136,6 +125,10 @@ METHOD(pa_tnc_attr_t, build, void,
chunk_t pathname;
bio_writer_t *writer;
+ if (this->value.ptr)
+ {
+ return;
+ }
if (this->directory_flag)
{
flags |= DIRECTORY_CONTENTS_FLAG;
@@ -240,7 +233,6 @@ pa_tnc_attr_t *tcg_pts_attr_req_file_meas_create(bool directory_flag,
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -255,8 +247,7 @@ pa_tnc_attr_t *tcg_pts_attr_req_file_meas_create(bool directory_flag,
.get_delimiter = _get_delimiter,
.get_pathname = _get_pathname,
},
- .vendor_id = PEN_TCG,
- .type = TCG_PTS_REQ_FILE_MEAS,
+ .type = { PEN_TCG, TCG_PTS_REQ_FILE_MEAS },
.directory_flag = directory_flag,
.request_id = request_id,
.delimiter = delimiter,
@@ -278,7 +269,6 @@ pa_tnc_attr_t *tcg_pts_attr_req_file_meas_create_from_data(chunk_t data)
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -293,8 +283,7 @@ pa_tnc_attr_t *tcg_pts_attr_req_file_meas_create_from_data(chunk_t data)
.get_delimiter = _get_delimiter,
.get_pathname = _get_pathname,
},
- .vendor_id = PEN_TCG,
- .type = TCG_PTS_REQ_FILE_MEAS,
+ .type = { PEN_TCG, TCG_PTS_REQ_FILE_MEAS },
.value = chunk_clone(data),
.ref = 1,
);
diff --git a/src/libpts/tcg/tcg_pts_attr_req_file_meta.c b/src/libpts/tcg/tcg_pts_attr_req_file_meta.c
index bef6b5db6..eb5114172 100644
--- a/src/libpts/tcg/tcg_pts_attr_req_file_meta.c
+++ b/src/libpts/tcg/tcg_pts_attr_req_file_meta.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -52,14 +52,9 @@ struct private_tcg_pts_attr_req_file_meta_t {
tcg_pts_attr_req_file_meta_t public;
/**
- * Attribute vendor ID
+ * Vendor-specific attribute type
*/
- pen_t vendor_id;
-
- /**
- * Attribute type
- */
- u_int32_t type;
+ pen_type_t type;
/**
* Attribute value
@@ -92,13 +87,7 @@ struct private_tcg_pts_attr_req_file_meta_t {
refcount_t ref;
};
-METHOD(pa_tnc_attr_t, get_vendor_id, pen_t,
- private_tcg_pts_attr_req_file_meta_t *this)
-{
- return this->vendor_id;
-}
-
-METHOD(pa_tnc_attr_t, get_type, u_int32_t,
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
private_tcg_pts_attr_req_file_meta_t *this)
{
return this->type;
@@ -129,6 +118,10 @@ METHOD(pa_tnc_attr_t, build, void,
chunk_t pathname;
bio_writer_t *writer;
+ if (this->value.ptr)
+ {
+ return;
+ }
if (this->directory_flag)
{
flags |= DIRECTORY_CONTENTS_FLAG;
@@ -226,7 +219,6 @@ pa_tnc_attr_t *tcg_pts_attr_req_file_meta_create(bool directory_flag,
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -240,8 +232,7 @@ pa_tnc_attr_t *tcg_pts_attr_req_file_meta_create(bool directory_flag,
.get_delimiter = _get_delimiter,
.get_pathname = _get_pathname,
},
- .vendor_id = PEN_TCG,
- .type = TCG_PTS_REQ_FILE_META,
+ .type = { PEN_TCG, TCG_PTS_REQ_FILE_META },
.directory_flag = directory_flag,
.delimiter = delimiter,
.pathname = strdup(pathname),
@@ -262,7 +253,6 @@ pa_tnc_attr_t *tcg_pts_attr_req_file_meta_create_from_data(chunk_t data)
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -276,8 +266,7 @@ pa_tnc_attr_t *tcg_pts_attr_req_file_meta_create_from_data(chunk_t data)
.get_delimiter = _get_delimiter,
.get_pathname = _get_pathname,
},
- .vendor_id = PEN_TCG,
- .type = TCG_PTS_REQ_FILE_META,
+ .type = { PEN_TCG, TCG_PTS_REQ_FILE_META },
.value = chunk_clone(data),
.ref = 1,
);
diff --git a/src/libpts/tcg/tcg_pts_attr_req_func_comp_evid.c b/src/libpts/tcg/tcg_pts_attr_req_func_comp_evid.c
index bfd108b9f..a631e9891 100644
--- a/src/libpts/tcg/tcg_pts_attr_req_func_comp_evid.c
+++ b/src/libpts/tcg/tcg_pts_attr_req_func_comp_evid.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -73,14 +73,9 @@ struct private_tcg_pts_attr_req_func_comp_evid_t {
tcg_pts_attr_req_func_comp_evid_t public;
/**
- * Attribute vendor ID
+ * Vendor-specific attribute type
*/
- pen_t vendor_id;
-
- /**
- * Attribute type
- */
- u_int32_t type;
+ pen_type_t type;
/**
* Attribute value
@@ -140,13 +135,7 @@ static void free_entry(entry_t *this)
}
}
-METHOD(pa_tnc_attr_t, get_vendor_id, pen_t,
- private_tcg_pts_attr_req_func_comp_evid_t *this)
-{
- return this->vendor_id;
-}
-
-METHOD(pa_tnc_attr_t, get_type, u_int32_t,
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
private_tcg_pts_attr_req_func_comp_evid_t *this)
{
return this->type;
@@ -177,6 +166,10 @@ METHOD(pa_tnc_attr_t, build, void,
enumerator_t *enumerator;
entry_t *entry;
+ if (this->value.ptr)
+ {
+ return;
+ }
writer = bio_writer_create(PTS_REQ_FUNC_COMP_EVID_SIZE);
enumerator = this->list->create_enumerator(this->list);
@@ -320,7 +313,6 @@ pa_tnc_attr_t *tcg_pts_attr_req_func_comp_evid_create(void)
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -334,8 +326,7 @@ pa_tnc_attr_t *tcg_pts_attr_req_func_comp_evid_create(void)
.get_count = _get_count,
.create_enumerator = _create_enumerator,
},
- .vendor_id = PEN_TCG,
- .type = TCG_PTS_REQ_FUNC_COMP_EVID,
+ .type = { PEN_TCG, TCG_PTS_REQ_FUNC_COMP_EVID },
.list = linked_list_create(),
.ref = 1,
);
@@ -353,7 +344,6 @@ pa_tnc_attr_t *tcg_pts_attr_req_func_comp_evid_create_from_data(chunk_t data)
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -367,8 +357,7 @@ pa_tnc_attr_t *tcg_pts_attr_req_func_comp_evid_create_from_data(chunk_t data)
.get_count = _get_count,
.create_enumerator = _create_enumerator,
},
- .vendor_id = PEN_TCG,
- .type = TCG_PTS_REQ_FUNC_COMP_EVID,
+ .type = { PEN_TCG, TCG_PTS_REQ_FUNC_COMP_EVID },
.list = linked_list_create(),
.value = chunk_clone(data),
.ref = 1,
diff --git a/src/libpts/tcg/tcg_pts_attr_simple_comp_evid.c b/src/libpts/tcg/tcg_pts_attr_simple_comp_evid.c
index d2c197ac4..387f4a115 100644
--- a/src/libpts/tcg/tcg_pts_attr_simple_comp_evid.c
+++ b/src/libpts/tcg/tcg_pts_attr_simple_comp_evid.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -100,14 +100,9 @@ struct private_tcg_pts_attr_simple_comp_evid_t {
tcg_pts_attr_simple_comp_evid_t public;
/**
- * Attribute vendor ID
+ * Vendor-specific attribute type
*/
- pen_t vendor_id;
-
- /**
- * Attribute type
- */
- u_int32_t type;
+ pen_type_t type;
/**
* Attribute value
@@ -130,13 +125,7 @@ struct private_tcg_pts_attr_simple_comp_evid_t {
refcount_t ref;
};
-METHOD(pa_tnc_attr_t, get_vendor_id, pen_t,
- private_tcg_pts_attr_simple_comp_evid_t *this)
-{
- return this->vendor_id;
-}
-
-METHOD(pa_tnc_attr_t, get_type, u_int32_t,
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
private_tcg_pts_attr_simple_comp_evid_t *this)
{
return this->type;
@@ -185,16 +174,22 @@ METHOD(pa_tnc_attr_t, build, void,
{
bio_writer_t *writer;
bool has_pcr_info;
- char utc_time_buf[25];
+ char utc_time_buf[25], *policy_uri;
u_int8_t flags;
+ u_int16_t len;
u_int32_t depth, extended_pcr;
pts_comp_func_name_t *name;
pts_meas_algorithms_t hash_algorithm;
pts_pcr_transform_t transform;
pts_comp_evid_validation_t validation;
time_t measurement_time;
- chunk_t measurement, utc_time, pcr_before, pcr_after, policy_uri;
+ chunk_t measurement, utc_time, pcr_before, pcr_after;
+ if (this->value.ptr)
+ {
+ return;
+ }
+
/* Extract parameters from comp_evidence_t object */
name = this->evidence->get_comp_func_name(this->evidence,
&depth);
@@ -234,8 +229,9 @@ METHOD(pa_tnc_attr_t, build, void,
if (validation == PTS_COMP_EVID_VALIDATION_FAILED ||
validation == PTS_COMP_EVID_VALIDATION_PASSED)
{
- writer->write_uint16(writer, policy_uri.len);
- writer->write_data (writer, policy_uri);
+ len = strlen(policy_uri);
+ writer->write_uint16(writer, len);
+ writer->write_data (writer, chunk_create(policy_uri, len));
}
if (has_pcr_info)
{
@@ -409,8 +405,13 @@ METHOD(pa_tnc_attr_t, process, status_t,
/* Add options */
if (has_validation)
{
- policy_uri = chunk_clone(policy_uri);
- this->evidence->set_validation(this->evidence, validation, policy_uri);
+ char buf[BUF_LEN];
+ size_t len;
+
+ len = min(policy_uri.len, BUF_LEN-1);
+ memcpy(buf, policy_uri.ptr, len);
+ buf[len] = '\0';
+ this->evidence->set_validation(this->evidence, validation, buf);
}
if (has_pcr_info)
{
@@ -460,7 +461,6 @@ pa_tnc_attr_t *tcg_pts_attr_simple_comp_evid_create(pts_comp_evidence_t *evid)
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -472,8 +472,7 @@ pa_tnc_attr_t *tcg_pts_attr_simple_comp_evid_create(pts_comp_evidence_t *evid)
},
.get_comp_evidence = _get_comp_evidence,
},
- .vendor_id = PEN_TCG,
- .type = TCG_PTS_SIMPLE_COMP_EVID,
+ .type = { PEN_TCG, TCG_PTS_SIMPLE_COMP_EVID },
.evidence = evid,
.ref = 1,
);
@@ -492,7 +491,6 @@ pa_tnc_attr_t *tcg_pts_attr_simple_comp_evid_create_from_data(chunk_t data)
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -504,8 +502,7 @@ pa_tnc_attr_t *tcg_pts_attr_simple_comp_evid_create_from_data(chunk_t data)
},
.get_comp_evidence = _get_comp_evidence,
},
- .vendor_id = PEN_TCG,
- .type = TCG_PTS_SIMPLE_COMP_EVID,
+ .type = { PEN_TCG, TCG_PTS_SIMPLE_COMP_EVID },
.value = chunk_clone(data),
.ref = 1,
);
diff --git a/src/libpts/tcg/tcg_pts_attr_simple_evid_final.c b/src/libpts/tcg/tcg_pts_attr_simple_evid_final.c
index 27720d509..8d2d4f82d 100644
--- a/src/libpts/tcg/tcg_pts_attr_simple_evid_final.c
+++ b/src/libpts/tcg/tcg_pts_attr_simple_evid_final.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -58,14 +58,9 @@ struct private_tcg_pts_attr_simple_evid_final_t {
tcg_pts_attr_simple_evid_final_t public;
/**
- * Attribute vendor ID
+ * Vendor-specific attribute type
*/
- pen_t vendor_id;
-
- /**
- * Attribute type
- */
- u_int32_t type;
+ pen_type_t type;
/**
* Attribute value
@@ -113,13 +108,7 @@ struct private_tcg_pts_attr_simple_evid_final_t {
refcount_t ref;
};
-METHOD(pa_tnc_attr_t, get_vendor_id, pen_t,
- private_tcg_pts_attr_simple_evid_final_t *this)
-{
- return this->vendor_id;
-}
-
-METHOD(pa_tnc_attr_t, get_type, u_int32_t,
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
private_tcg_pts_attr_simple_evid_final_t *this)
{
return this->type;
@@ -169,6 +158,10 @@ METHOD(pa_tnc_attr_t, build, void,
bio_writer_t *writer;
u_int8_t flags;
+ if (this->value.ptr)
+ {
+ return;
+ }
flags = this->flags & PTS_SIMPLE_EVID_FINAL_FLAG_MASK;
if (this->has_evid_sig)
@@ -333,7 +326,6 @@ pa_tnc_attr_t *tcg_pts_attr_simple_evid_final_create(u_int8_t flags,
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -347,8 +339,7 @@ pa_tnc_attr_t *tcg_pts_attr_simple_evid_final_create(u_int8_t flags,
.get_evid_sig = _get_evid_sig,
.set_evid_sig = _set_evid_sig,
},
- .vendor_id = PEN_TCG,
- .type = TCG_PTS_SIMPLE_EVID_FINAL,
+ .type = { PEN_TCG, TCG_PTS_SIMPLE_EVID_FINAL },
.flags = flags,
.comp_hash_algorithm = comp_hash_algorithm,
.pcr_comp = pcr_comp,
@@ -370,7 +361,6 @@ pa_tnc_attr_t *tcg_pts_attr_simple_evid_final_create_from_data(chunk_t data)
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -384,8 +374,7 @@ pa_tnc_attr_t *tcg_pts_attr_simple_evid_final_create_from_data(chunk_t data)
.get_evid_sig = _get_evid_sig,
.set_evid_sig = _set_evid_sig,
},
- .vendor_id = PEN_TCG,
- .type = TCG_PTS_SIMPLE_EVID_FINAL,
+ .type = { PEN_TCG, TCG_PTS_SIMPLE_EVID_FINAL },
.value = chunk_clone(data),
.ref = 1,
);
diff --git a/src/libpts/tcg/tcg_pts_attr_tpm_version_info.c b/src/libpts/tcg/tcg_pts_attr_tpm_version_info.c
index 944a12cc9..8d1e78f18 100644
--- a/src/libpts/tcg/tcg_pts_attr_tpm_version_info.c
+++ b/src/libpts/tcg/tcg_pts_attr_tpm_version_info.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -49,14 +49,9 @@ struct private_tcg_pts_attr_tpm_version_info_t {
tcg_pts_attr_tpm_version_info_t public;
/**
- * Attribute vendor ID
+ * Vendor-specific attribute type
*/
- pen_t vendor_id;
-
- /**
- * Attribute type
- */
- u_int32_t type;
+ pen_type_t type;
/**
* Attribute value
@@ -79,13 +74,7 @@ struct private_tcg_pts_attr_tpm_version_info_t {
refcount_t ref;
};
-METHOD(pa_tnc_attr_t, get_vendor_id, pen_t,
- private_tcg_pts_attr_tpm_version_info_t *this)
-{
- return this->vendor_id;
-}
-
-METHOD(pa_tnc_attr_t, get_type, u_int32_t,
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
private_tcg_pts_attr_tpm_version_info_t *this)
{
return this->type;
@@ -114,6 +103,10 @@ METHOD(pa_tnc_attr_t, build, void,
{
bio_writer_t *writer;
+ if (this->value.ptr)
+ {
+ return;
+ }
writer = bio_writer_create(PTS_TPM_VER_INFO_SIZE);
writer->write_data(writer, this->tpm_version_info);
@@ -181,7 +174,6 @@ pa_tnc_attr_t *tcg_pts_attr_tpm_version_info_create(chunk_t tpm_version_info)
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -194,8 +186,7 @@ pa_tnc_attr_t *tcg_pts_attr_tpm_version_info_create(chunk_t tpm_version_info)
.get_tpm_version_info = _get_tpm_version_info,
.set_tpm_version_info = _set_tpm_version_info,
},
- .vendor_id = PEN_TCG,
- .type = TCG_PTS_TPM_VERSION_INFO,
+ .type = { PEN_TCG, TCG_PTS_TPM_VERSION_INFO },
.tpm_version_info = chunk_clone(tpm_version_info),
.ref = 1,
);
@@ -214,7 +205,6 @@ pa_tnc_attr_t *tcg_pts_attr_tpm_version_info_create_from_data(chunk_t data)
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -227,8 +217,7 @@ pa_tnc_attr_t *tcg_pts_attr_tpm_version_info_create_from_data(chunk_t data)
.get_tpm_version_info = _get_tpm_version_info,
.set_tpm_version_info = _set_tpm_version_info,
},
- .vendor_id = PEN_TCG,
- .type = TCG_PTS_TPM_VERSION_INFO,
+ .type = { PEN_TCG, TCG_PTS_TPM_VERSION_INFO },
.value = chunk_clone(data),
.ref = 1,
);
diff --git a/src/libpts/tcg/tcg_pts_attr_unix_file_meta.c b/src/libpts/tcg/tcg_pts_attr_unix_file_meta.c
index a9f4a115d..4f93ee885 100644
--- a/src/libpts/tcg/tcg_pts_attr_unix_file_meta.c
+++ b/src/libpts/tcg/tcg_pts_attr_unix_file_meta.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -80,14 +80,9 @@ struct private_tcg_pts_attr_file_meta_t {
tcg_pts_attr_file_meta_t public;
/**
- * Attribute vendor ID
+ * Vendor-specific attribute type
*/
- pen_t vendor_id;
-
- /**
- * Attribute type
- */
- u_int32_t type;
+ pen_type_t type;
/**
* Attribute value
@@ -110,13 +105,7 @@ struct private_tcg_pts_attr_file_meta_t {
refcount_t ref;
};
-METHOD(pa_tnc_attr_t, get_vendor_id, pen_t,
- private_tcg_pts_attr_file_meta_t *this)
-{
- return this->vendor_id;
-}
-
-METHOD(pa_tnc_attr_t, get_type, u_int32_t,
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
private_tcg_pts_attr_file_meta_t *this)
{
return this->type;
@@ -148,6 +137,10 @@ METHOD(pa_tnc_attr_t, build, void,
pts_file_metadata_t *entry;
u_int64_t number_of_files;
+ if (this->value.ptr)
+ {
+ return;
+ }
number_of_files = this->metadata->get_file_count(this->metadata);
writer = bio_writer_create(PTS_FILE_META_SIZE);
@@ -306,7 +299,6 @@ pa_tnc_attr_t *tcg_pts_attr_unix_file_meta_create(pts_file_meta_t *metadata)
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -318,8 +310,7 @@ pa_tnc_attr_t *tcg_pts_attr_unix_file_meta_create(pts_file_meta_t *metadata)
},
.get_metadata = _get_metadata,
},
- .vendor_id = PEN_TCG,
- .type = TCG_PTS_UNIX_FILE_META,
+ .type = { PEN_TCG, TCG_PTS_UNIX_FILE_META },
.metadata = metadata,
.ref = 1,
);
@@ -338,7 +329,6 @@ pa_tnc_attr_t *tcg_pts_attr_unix_file_meta_create_from_data(chunk_t data)
INIT(this,
.public = {
.pa_tnc_attribute = {
- .get_vendor_id = _get_vendor_id,
.get_type = _get_type,
.get_value = _get_value,
.get_noskip_flag = _get_noskip_flag,
@@ -350,8 +340,7 @@ pa_tnc_attr_t *tcg_pts_attr_unix_file_meta_create_from_data(chunk_t data)
},
.get_metadata = _get_metadata,
},
- .vendor_id = PEN_TCG,
- .type = TCG_PTS_UNIX_FILE_META,
+ .type = { PEN_TCG, TCG_PTS_UNIX_FILE_META },
.value = chunk_clone(data),
.ref = 1,
);
diff --git a/src/libradius/Makefile.in b/src/libradius/Makefile.in
index bcc38792a..15642db64 100644
--- a/src/libradius/Makefile.in
+++ b/src/libradius/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -78,7 +79,7 @@ libradius_la_LIBADD =
am_libradius_la_OBJECTS = radius_message.lo radius_socket.lo \
radius_client.lo radius_config.lo
libradius_la_OBJECTS = $(am_libradius_la_OBJECTS)
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -104,6 +105,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -198,11 +200,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -219,11 +224,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -239,6 +245,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -248,7 +255,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libradius/radius_message.c b/src/libradius/radius_message.c
index 17fa7357b..77f9b0398 100644
--- a/src/libradius/radius_message.c
+++ b/src/libradius/radius_message.c
@@ -286,14 +286,17 @@ METHOD(radius_message_t, add, void,
this->msg->length = htons(ntohs(this->msg->length) + attribute->length);
}
-METHOD(radius_message_t, sign, void,
+METHOD(radius_message_t, sign, bool,
private_radius_message_t *this, u_int8_t *req_auth, chunk_t secret,
hasher_t *hasher, signer_t *signer, rng_t *rng, bool msg_auth)
{
if (rng)
{
/* build Request-Authenticator */
- rng->get_bytes(rng, HASH_SIZE_MD5, this->msg->authenticator);
+ if (!rng->get_bytes(rng, HASH_SIZE_MD5, this->msg->authenticator))
+ {
+ return FALSE;
+ }
}
else
{
@@ -315,9 +318,12 @@ METHOD(radius_message_t, sign, void,
/* build Message-Authenticator attribute, using 16 null bytes */
memset(buf, 0, sizeof(buf));
add(this, RAT_MESSAGE_AUTHENTICATOR, chunk_create(buf, sizeof(buf)));
- signer->get_signature(signer,
+ if (!signer->get_signature(signer,
chunk_create((u_char*)this->msg, ntohs(this->msg->length)),
- ((u_char*)this->msg) + ntohs(this->msg->length) - HASH_SIZE_MD5);
+ ((u_char*)this->msg) + ntohs(this->msg->length) - HASH_SIZE_MD5))
+ {
+ return FALSE;
+ }
}
if (!rng)
@@ -326,9 +332,13 @@ METHOD(radius_message_t, sign, void,
/* build Response-Authenticator */
msg = chunk_create((u_char*)this->msg, ntohs(this->msg->length));
- hasher->get_hash(hasher, msg, NULL);
- hasher->get_hash(hasher, secret, this->msg->authenticator);
+ if (!hasher->get_hash(hasher, msg, NULL) ||
+ !hasher->get_hash(hasher, secret, this->msg->authenticator))
+ {
+ return FALSE;
+ }
}
+ return TRUE;
}
METHOD(radius_message_t, verify, bool,
@@ -357,9 +367,9 @@ METHOD(radius_message_t, verify, bool,
}
/* verify Response-Authenticator */
- hasher->get_hash(hasher, msg, NULL);
- hasher->get_hash(hasher, secret, buf);
- if (!memeq(buf, res_auth, HASH_SIZE_MD5))
+ if (!hasher->get_hash(hasher, msg, NULL) ||
+ !hasher->get_hash(hasher, secret, buf) ||
+ !memeq(buf, res_auth, HASH_SIZE_MD5))
{
DBG1(DBG_CFG, "RADIUS Response-Authenticator verification failed");
return FALSE;
diff --git a/src/libradius/radius_message.h b/src/libradius/radius_message.h
index 6d0df53c3..f9c57c5ef 100644
--- a/src/libradius/radius_message.h
+++ b/src/libradius/radius_message.h
@@ -257,8 +257,9 @@ struct radius_message_t {
* @param hasher MD5 hasher
* @param rng RNG to create Request-Authenticator, NULL to omit
* @param msg_auth calculate and add Message-Authenticator
+ * @return TRUE if signed successfully
*/
- void (*sign)(radius_message_t *this, u_int8_t *req_auth, chunk_t secret,
+ bool (*sign)(radius_message_t *this, u_int8_t *req_auth, chunk_t secret,
hasher_t *hasher, signer_t *signer, rng_t *rng, bool msg_auth);
/**
diff --git a/src/libradius/radius_socket.c b/src/libradius/radius_socket.c
index 048c8814e..ba7cb14b0 100644
--- a/src/libradius/radius_socket.c
+++ b/src/libradius/radius_socket.c
@@ -148,8 +148,11 @@ METHOD(radius_socket_t, request, radius_message_t*,
/* set Message Identifier */
request->set_identifier(request, this->identifier++);
/* sign the request */
- request->sign(request, NULL, this->secret, this->hasher, this->signer,
- rng, rng != NULL);
+ if (!request->sign(request, NULL, this->secret, this->hasher, this->signer,
+ rng, rng != NULL))
+ {
+ return NULL;
+ }
if (!check_connection(this, fd, port))
{
@@ -257,8 +260,11 @@ static chunk_t decrypt_mppe_key(private_radius_socket_t *this, u_int16_t salt,
while (c < C.ptr + C.len)
{
/* b(i) = MD5(S + c(i-1)) */
- this->hasher->get_hash(this->hasher, this->secret, NULL);
- this->hasher->get_hash(this->hasher, seed, p);
+ if (!this->hasher->get_hash(this->hasher, this->secret, NULL) ||
+ !this->hasher->get_hash(this->hasher, seed, p))
+ {
+ return chunk_empty;
+ }
/* p(i) = b(i) xor c(1) */
memxor(p, c, HASH_SIZE_MD5);
@@ -358,14 +364,14 @@ radius_socket_t *radius_socket_create(char *address, u_int16_t auth_port,
.rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK),
);
- if (!this->hasher || !this->signer || !this->rng)
+ if (!this->hasher || !this->signer || !this->rng ||
+ !this->signer->set_key(this->signer, secret))
{
DBG1(DBG_CFG, "RADIUS initialization failed, HMAC/MD5/RNG required");
destroy(this);
return NULL;
}
this->secret = secret;
- this->signer->set_key(this->signer, secret);
/* we use a random identifier, helps if we restart often */
this->identifier = random();
diff --git a/src/libsimaka/Makefile.in b/src/libsimaka/Makefile.in
index 59919e559..cdc7799ae 100644
--- a/src/libsimaka/Makefile.in
+++ b/src/libsimaka/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -78,7 +79,7 @@ libsimaka_la_LIBADD =
am_libsimaka_la_OBJECTS = simaka_message.lo simaka_crypto.lo \
simaka_manager.lo
libsimaka_la_OBJECTS = $(am_libsimaka_la_OBJECTS)
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -104,6 +105,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -198,11 +200,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -219,11 +224,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -239,6 +245,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -248,7 +255,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libsimaka/simaka_crypto.c b/src/libsimaka/simaka_crypto.c
index 4819d1b99..92db19317 100644
--- a/src/libsimaka/simaka_crypto.c
+++ b/src/libsimaka/simaka_crypto.c
@@ -115,90 +115,128 @@ static void call_hook(private_simaka_crypto_t *this, chunk_t encr, chunk_t auth)
mgr->key_hook(mgr, encr, auth);
}
-METHOD(simaka_crypto_t, derive_keys_full, chunk_t,
+METHOD(simaka_crypto_t, derive_keys_full, bool,
private_simaka_crypto_t *this, identification_t *id,
- chunk_t data, chunk_t *mk)
+ chunk_t data, chunk_t *mk, chunk_t *msk)
{
- chunk_t str, msk, k_encr, k_auth;
+ chunk_t str, k_encr, k_auth;
int i;
/* For SIM: MK = SHA1(Identity|n*Kc|NONCE_MT|Version List|Selected Version)
* For AKA: MK = SHA1(Identity|IK|CK) */
- this->hasher->get_hash(this->hasher, id->get_encoding(id), NULL);
- this->hasher->allocate_hash(this->hasher, data, mk);
+ if (!this->hasher->get_hash(this->hasher, id->get_encoding(id), NULL) ||
+ !this->hasher->allocate_hash(this->hasher, data, mk))
+ {
+ return FALSE;
+ }
DBG3(DBG_LIB, "MK %B", mk);
/* K_encr | K_auth | MSK | EMSK = prf() | prf() | prf() | prf() */
- this->prf->set_key(this->prf, *mk);
+ if (!this->prf->set_key(this->prf, *mk))
+ {
+ chunk_clear(mk);
+ return FALSE;
+ }
str = chunk_alloca(this->prf->get_block_size(this->prf) * 3);
for (i = 0; i < 3; i++)
{
- this->prf->get_bytes(this->prf, chunk_empty, str.ptr + str.len / 3 * i);
+ if (!this->prf->get_bytes(this->prf, chunk_empty,
+ str.ptr + str.len / 3 * i))
+ {
+ chunk_clear(mk);
+ return FALSE;
+ }
}
k_encr = chunk_create(str.ptr, KENCR_LEN);
k_auth = chunk_create(str.ptr + KENCR_LEN, KAUTH_LEN);
- msk = chunk_create(str.ptr + KENCR_LEN + KAUTH_LEN, MSK_LEN);
DBG3(DBG_LIB, "K_encr %B\nK_auth %B\nMSK %B", &k_encr, &k_auth, &msk);
- this->signer->set_key(this->signer, k_auth);
- this->crypter->set_key(this->crypter, k_encr);
+ if (!this->signer->set_key(this->signer, k_auth) ||
+ !this->crypter->set_key(this->crypter, k_encr))
+ {
+ chunk_clear(mk);
+ return FALSE;
+ }
+
+ *msk = chunk_clone(chunk_create(str.ptr + KENCR_LEN + KAUTH_LEN, MSK_LEN));
call_hook(this, k_encr, k_auth);
this->derived = TRUE;
- return chunk_clone(msk);
+ return TRUE;
}
-METHOD(simaka_crypto_t, derive_keys_reauth, void,
+METHOD(simaka_crypto_t, derive_keys_reauth, bool,
private_simaka_crypto_t *this, chunk_t mk)
{
chunk_t str, k_encr, k_auth;
int i;
/* K_encr | K_auth = prf() | prf() */
- this->prf->set_key(this->prf, mk);
+ if (!this->prf->set_key(this->prf, mk))
+ {
+ return FALSE;
+ }
str = chunk_alloca(this->prf->get_block_size(this->prf) * 2);
for (i = 0; i < 2; i++)
{
- this->prf->get_bytes(this->prf, chunk_empty, str.ptr + str.len / 2 * i);
+ if (!this->prf->get_bytes(this->prf, chunk_empty,
+ str.ptr + str.len / 2 * i))
+ {
+ return FALSE;
+ }
}
k_encr = chunk_create(str.ptr, KENCR_LEN);
k_auth = chunk_create(str.ptr + KENCR_LEN, KAUTH_LEN);
DBG3(DBG_LIB, "K_encr %B\nK_auth %B", &k_encr, &k_auth);
- this->signer->set_key(this->signer, k_auth);
- this->crypter->set_key(this->crypter, k_encr);
+ if (!this->signer->set_key(this->signer, k_auth) ||
+ !this->crypter->set_key(this->crypter, k_encr))
+ {
+ return FALSE;
+ }
call_hook(this, k_encr, k_auth);
this->derived = TRUE;
+ return TRUE;
}
-METHOD(simaka_crypto_t, derive_keys_reauth_msk, chunk_t,
+METHOD(simaka_crypto_t, derive_keys_reauth_msk, bool,
private_simaka_crypto_t *this, identification_t *id, chunk_t counter,
- chunk_t nonce_s, chunk_t mk)
+ chunk_t nonce_s, chunk_t mk, chunk_t *msk)
{
char xkey[HASH_SIZE_SHA1];
- chunk_t str, msk;
+ chunk_t str;
int i;
- this->hasher->get_hash(this->hasher, id->get_encoding(id), NULL);
- this->hasher->get_hash(this->hasher, counter, NULL);
- this->hasher->get_hash(this->hasher, nonce_s, NULL);
- this->hasher->get_hash(this->hasher, mk, xkey);
+ if (!this->hasher->get_hash(this->hasher, id->get_encoding(id), NULL) ||
+ !this->hasher->get_hash(this->hasher, counter, NULL) ||
+ !this->hasher->get_hash(this->hasher, nonce_s, NULL) ||
+ !this->hasher->get_hash(this->hasher, mk, xkey))
+ {
+ return FALSE;
+ }
/* MSK | EMSK = prf() | prf() | prf() | prf() */
- this->prf->set_key(this->prf, chunk_create(xkey, sizeof(xkey)));
+ if (!this->prf->set_key(this->prf, chunk_create(xkey, sizeof(xkey))))
+ {
+ return FALSE;
+ }
str = chunk_alloca(this->prf->get_block_size(this->prf) * 2);
for (i = 0; i < 2; i++)
{
- this->prf->get_bytes(this->prf, chunk_empty, str.ptr + str.len / 2 * i);
+ if (!this->prf->get_bytes(this->prf, chunk_empty,
+ str.ptr + str.len / 2 * i))
+ {
+ return FALSE;
+ }
}
- msk = chunk_create(str.ptr, MSK_LEN);
- DBG3(DBG_LIB, "MSK %B", &msk);
+ *msk = chunk_clone(chunk_create(str.ptr, MSK_LEN));
+ DBG3(DBG_LIB, "MSK %B", msk);
- return chunk_clone(msk);
+ return TRUE;
}
METHOD(simaka_crypto_t, clear_keys, void,
diff --git a/src/libsimaka/simaka_crypto.h b/src/libsimaka/simaka_crypto.h
index d1830e658..c07755865 100644
--- a/src/libsimaka/simaka_crypto.h
+++ b/src/libsimaka/simaka_crypto.h
@@ -62,10 +62,11 @@ struct simaka_crypto_t {
* @param id peer identity
* @param data method specific data
* @param mk chunk receiving allocated master key MK
- * @return allocated MSK value
+ * @param msk chunk receiving allocated MSK
+ * @return TRUE if keys allocated and derived successfully
*/
- chunk_t (*derive_keys_full)(simaka_crypto_t *this, identification_t *id,
- chunk_t data, chunk_t *mk);
+ bool (*derive_keys_full)(simaka_crypto_t *this, identification_t *id,
+ chunk_t data, chunk_t *mk, chunk_t *msk);
/**
* Derive k_encr/k_auth keys from MK using fast reauthentication.
@@ -74,8 +75,9 @@ struct simaka_crypto_t {
* internal crypter/signer instances.
*
* @param mk master key
+ * @return TRUE if keys derived successfully
*/
- void (*derive_keys_reauth)(simaka_crypto_t *this, chunk_t mk);
+ bool (*derive_keys_reauth)(simaka_crypto_t *this, chunk_t mk);
/**
* Derive MSK using fast reauthentication.
@@ -84,10 +86,12 @@ struct simaka_crypto_t {
* @param counter fast reauthentication counter value, network order
* @param nonce_s server generated NONCE_S value
* @param mk master key of last full authentication
+ * @param msk chunk receiving allocated MSK
+ * @return TRUE if MSK allocated and derived successfully
*/
- chunk_t (*derive_keys_reauth_msk)(simaka_crypto_t *this,
- identification_t *id, chunk_t counter,
- chunk_t nonce_s, chunk_t mk);
+ bool (*derive_keys_reauth_msk)(simaka_crypto_t *this,
+ identification_t *id, chunk_t counter,
+ chunk_t nonce_s, chunk_t mk, chunk_t *msk);
/**
* Clear keys (partially) derived.
diff --git a/src/libsimaka/simaka_message.c b/src/libsimaka/simaka_message.c
index a5754b985..aa36a0974 100644
--- a/src/libsimaka/simaka_message.c
+++ b/src/libsimaka/simaka_message.c
@@ -499,8 +499,10 @@ static bool decrypt(private_simaka_message_t *this)
eap_type_names, this->hdr->type);
return FALSE;
}
-
- crypter->decrypt(crypter, this->encr, this->iv, &plain);
+ if (!crypter->decrypt(crypter, this->encr, this->iv, &plain))
+ {
+ return FALSE;
+ }
this->encrypted = TRUE;
success = parse_attributes(this, plain);
@@ -599,8 +601,8 @@ METHOD(simaka_message_t, verify, bool,
return TRUE;
}
-METHOD(simaka_message_t, generate, chunk_t,
- private_simaka_message_t *this, chunk_t sigdata)
+METHOD(simaka_message_t, generate, bool,
+ private_simaka_message_t *this, chunk_t sigdata, chunk_t *gen)
{
/* buffers large enough for messages we generate */
char out_buf[1024], encr_buf[512];
@@ -771,13 +773,19 @@ METHOD(simaka_message_t, generate, chunk_t,
out = chunk_skip(out, 4);
rng = this->crypto->get_rng(this->crypto);
- rng->get_bytes(rng, iv.len, out.ptr);
+ if (!rng->get_bytes(rng, iv.len, out.ptr))
+ {
+ return FALSE;
+ }
iv = chunk_clonea(chunk_create(out.ptr, iv.len));
out = chunk_skip(out, iv.len);
/* inline encryption */
- crypter->encrypt(crypter, encr, iv, NULL);
+ if (!crypter->encrypt(crypter, encr, iv, NULL))
+ {
+ return FALSE;
+ }
/* add ENCR_DATA attribute */
hdr = (attr_hdr_t*)out.ptr;
@@ -822,12 +830,16 @@ METHOD(simaka_message_t, generate, chunk_t,
if (mac.len)
{
data = chunk_cata("cc", out, sigdata);
- signer->get_signature(signer, data, mac.ptr);
+ if (!signer->get_signature(signer, data, mac.ptr))
+ {
+ return FALSE;
+ }
}
call_hook(this, FALSE, FALSE);
- return chunk_clone(out);
+ *gen = chunk_clone(out);
+ return TRUE;
}
METHOD(simaka_message_t, destroy, void,
diff --git a/src/libsimaka/simaka_message.h b/src/libsimaka/simaka_message.h
index 28fe21823..209067c70 100644
--- a/src/libsimaka/simaka_message.h
+++ b/src/libsimaka/simaka_message.h
@@ -236,9 +236,10 @@ struct simaka_message_t {
* Generate a message, optionally encrypt attributes and create a MAC.
*
* @param sigdata additional data to include in signature, if any
- * @return allocated data of generated message
+ * @param gen allocated generated data, if successful
+ * @return TRUE if successful
*/
- chunk_t (*generate)(simaka_message_t *this, chunk_t sigdata);
+ bool (*generate)(simaka_message_t *this, chunk_t sigdata, chunk_t *gen);
/**
* Destroy a simaka_message_t.
diff --git a/src/libstrongswan/Android.mk b/src/libstrongswan/Android.mk
index d33bee6c7..4912576df 100644
--- a/src/libstrongswan/Android.mk
+++ b/src/libstrongswan/Android.mk
@@ -3,81 +3,43 @@ include $(CLEAR_VARS)
# copy-n-paste from Makefile.am
LOCAL_SRC_FILES := \
-library.c library.h \
-chunk.c chunk.h \
-debug.c debug.h \
-enum.c enum.h \
-settings.h settings.c \
-printf_hook.c printf_hook.h \
-asn1/asn1.c asn1/asn1.h \
-asn1/asn1_parser.c asn1/asn1_parser.h \
-asn1/oid.c asn1/oid.h \
-bio/bio_reader.h bio/bio_reader.c bio/bio_writer.h bio/bio_writer.c \
-crypto/crypters/crypter.c crypto/crypters/crypter.h \
-crypto/hashers/hasher.h crypto/hashers/hasher.c \
-crypto/pkcs9.c crypto/pkcs9.h \
-crypto/proposal/proposal_keywords.c crypto/proposal/proposal_keywords.h \
-crypto/prfs/prf.c crypto/prfs/prf.h \
-crypto/rngs/rng.c crypto/rngs/rng.h \
-crypto/prf_plus.h crypto/prf_plus.c \
-crypto/signers/signer.c crypto/signers/signer.h \
-crypto/crypto_factory.c crypto/crypto_factory.h \
-crypto/crypto_tester.c crypto/crypto_tester.h \
-crypto/diffie_hellman.c crypto/diffie_hellman.h \
-crypto/aead.c crypto/aead.h \
-crypto/transform.c crypto/transform.h \
-credentials/credential_factory.c credentials/credential_factory.h \
-credentials/builder.c credentials/builder.h \
-credentials/cred_encoding.c credentials/cred_encoding.h \
-credentials/keys/private_key.c credentials/keys/private_key.h \
-credentials/keys/public_key.c credentials/keys/public_key.h \
-credentials/keys/shared_key.c credentials/keys/shared_key.h \
-credentials/certificates/certificate.c credentials/certificates/certificate.h \
-credentials/certificates/x509.h credentials/certificates/ac.h \
-credentials/certificates/crl.h credentials/certificates/crl.c \
-credentials/certificates/pkcs10.h \
-credentials/certificates/ocsp_request.h \
-credentials/certificates/ocsp_response.h credentials/certificates/ocsp_response.c \
-credentials/certificates/pgp_certificate.h \
-credentials/ietf_attributes/ietf_attributes.c credentials/ietf_attributes/ietf_attributes.h \
-credentials/credential_manager.c credentials/credential_manager.h \
-credentials/sets/auth_cfg_wrapper.c credentials/sets/auth_cfg_wrapper.h \
-credentials/sets/ocsp_response_wrapper.c credentials/sets/ocsp_response_wrapper.h \
-credentials/sets/cert_cache.c credentials/sets/cert_cache.h \
-credentials/sets/mem_cred.c credentials/sets/mem_cred.h \
-credentials/sets/callback_cred.c credentials/sets/callback_cred.h \
-credentials/auth_cfg.c credentials/auth_cfg.h credentials/credential_set.h \
-credentials/cert_validator.h database/database.h database/database.c \
-database/database_factory.h database/database_factory.c \
-fetcher/fetcher.h fetcher/fetcher.c fetcher/fetcher_manager.h fetcher/fetcher_manager.c \
-eap/eap.h eap/eap.c \
-pen/pen.h pen/pen.c \
-plugins/plugin_loader.c plugins/plugin_loader.h plugins/plugin.h \
-plugins/plugin_feature.c plugins/plugin_feature.h \
-processing/jobs/job.h processing/jobs/job.c \
-processing/jobs/callback_job.c processing/jobs/callback_job.h \
-processing/processor.c processing/processor.h \
-processing/scheduler.c processing/scheduler.h \
-selectors/traffic_selector.c selectors/traffic_selector.h \
-threading/thread.h threading/thread.c \
-threading/thread_value.h threading/thread_value.c \
-threading/mutex.h threading/mutex.c threading/condvar.h \
-threading/rwlock.h threading/rwlock.c \
-threading/lock_profiler.h \
-utils.h utils.c \
-utils/host.c utils/host.h \
-utils/identification.c utils/identification.h \
-utils/lexparser.c utils/lexparser.h \
-utils/linked_list.c utils/linked_list.h \
-utils/hashtable.c utils/hashtable.h \
-utils/enumerator.c utils/enumerator.h \
-utils/optionsfrom.c utils/optionsfrom.h \
-utils/backtrace.c utils/backtrace.h
+library.c chunk.c debug.c enum.c settings.c printf_hook.c asn1/asn1.c \
+asn1/asn1_parser.c asn1/oid.c bio/bio_reader.c bio/bio_writer.c \
+crypto/crypters/crypter.c crypto/hashers/hasher.c crypto/pkcs7.c crypto/pkcs9.c \
+crypto/proposal/proposal_keywords.c crypto/proposal/proposal_keywords_static.c \
+crypto/prfs/prf.c crypto/prfs/mac_prf.c \
+crypto/rngs/rng.c crypto/prf_plus.c crypto/signers/signer.c \
+crypto/signers/mac_signer.c crypto/crypto_factory.c crypto/crypto_tester.c \
+crypto/diffie_hellman.c crypto/aead.c crypto/transform.c \
+credentials/credential_factory.c credentials/builder.c \
+credentials/cred_encoding.c credentials/keys/private_key.c \
+credentials/keys/public_key.c credentials/keys/shared_key.c \
+credentials/certificates/certificate.c credentials/certificates/crl.c \
+credentials/certificates/ocsp_response.c \
+credentials/ietf_attributes/ietf_attributes.c credentials/credential_manager.c \
+credentials/sets/auth_cfg_wrapper.c credentials/sets/ocsp_response_wrapper.c \
+credentials/sets/cert_cache.c credentials/sets/mem_cred.c \
+credentials/sets/callback_cred.c credentials/auth_cfg.c database/database.c \
+database/database_factory.c fetcher/fetcher.c fetcher/fetcher_manager.c eap/eap.c \
+ipsec/ipsec_types.c \
+pen/pen.c plugins/plugin_loader.c plugins/plugin_feature.c processing/jobs/job.c \
+processing/jobs/callback_job.c processing/processor.c processing/scheduler.c \
+selectors/traffic_selector.c threading/thread.c threading/thread_value.c \
+threading/mutex.c threading/semaphore.c threading/rwlock.c threading/spinlock.c \
+utils.c utils/host.c utils/packet.c utils/identification.c utils/lexparser.c \
+utils/linked_list.c utils/blocking_queue.c utils/hashtable.c utils/enumerator.c \
+utils/optionsfrom.c utils/capabilities.c utils/backtrace.c utils/tun_device.c
# adding the plugin source files
LOCAL_SRC_FILES += $(call add_plugin, aes)
+LOCAL_SRC_FILES += $(call add_plugin, curl)
+ifneq ($(call plugin_enabled, curl),)
+LOCAL_C_INCLUDES += $(libcurl_PATH)
+LOCAL_SHARED_LIBRARIES += libcurl
+endif
+
LOCAL_SRC_FILES += $(call add_plugin, des)
LOCAL_SRC_FILES += $(call add_plugin, fips-prf)
@@ -94,9 +56,11 @@ LOCAL_SRC_FILES += $(call add_plugin, md4)
LOCAL_SRC_FILES += $(call add_plugin, md5)
+LOCAL_SRC_FILES += $(call add_plugin, nonce)
+
LOCAL_SRC_FILES += $(call add_plugin, openssl)
ifneq ($(call plugin_enabled, openssl),)
-LOCAL_C_INCLUDES += external/openssl/include
+LOCAL_C_INCLUDES += $(openssl_PATH)
LOCAL_SHARED_LIBRARIES += libcrypto
endif
@@ -104,6 +68,8 @@ LOCAL_SRC_FILES += $(call add_plugin, pem)
LOCAL_SRC_FILES += $(call add_plugin, pkcs1)
+LOCAL_SRC_FILES += $(call add_plugin, pkcs8)
+
LOCAL_SRC_FILES += $(call add_plugin, pkcs11)
LOCAL_SRC_FILES += $(call add_plugin, pubkey)
diff --git a/src/libstrongswan/AndroidConfigLocal.h b/src/libstrongswan/AndroidConfigLocal.h
index a6da3276a..ee29c1693 100644
--- a/src/libstrongswan/AndroidConfigLocal.h
+++ b/src/libstrongswan/AndroidConfigLocal.h
@@ -1,3 +1,18 @@
+/*
+ * Copyright (C) 2010 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
/* stuff defined in AndroidConfig.h, which is included using the -include
* command-line option, thus cannot be undefined using -U CFLAGS options.
* the reason we have to undefine these flags in the first place, is that
diff --git a/src/libstrongswan/Makefile.am b/src/libstrongswan/Makefile.am
index 7bb0812bd..463d57d95 100644
--- a/src/libstrongswan/Makefile.am
+++ b/src/libstrongswan/Makefile.am
@@ -1,81 +1,75 @@
ipseclib_LTLIBRARIES = libstrongswan.la
libstrongswan_la_SOURCES = \
-library.c library.h \
-chunk.c chunk.h \
-debug.c debug.h \
-enum.c enum.h \
-settings.h settings.c \
-printf_hook.c printf_hook.h \
-asn1/asn1.c asn1/asn1.h \
-asn1/asn1_parser.c asn1/asn1_parser.h \
-asn1/oid.c asn1/oid.h \
-bio/bio_reader.h bio/bio_reader.c bio/bio_writer.h bio/bio_writer.c \
-crypto/crypters/crypter.c crypto/crypters/crypter.h \
-crypto/hashers/hasher.h crypto/hashers/hasher.c \
-crypto/pkcs9.c crypto/pkcs9.h \
-crypto/proposal/proposal_keywords.c crypto/proposal/proposal_keywords.h \
-crypto/prfs/prf.c crypto/prfs/prf.h \
-crypto/rngs/rng.c crypto/rngs/rng.h \
-crypto/prf_plus.h crypto/prf_plus.c \
-crypto/signers/signer.c crypto/signers/signer.h \
-crypto/crypto_factory.c crypto/crypto_factory.h \
-crypto/crypto_tester.c crypto/crypto_tester.h \
-crypto/diffie_hellman.c crypto/diffie_hellman.h \
-crypto/aead.c crypto/aead.h \
-crypto/transform.c crypto/transform.h \
-credentials/credential_factory.c credentials/credential_factory.h \
-credentials/builder.c credentials/builder.h \
-credentials/cred_encoding.c credentials/cred_encoding.h \
-credentials/keys/private_key.c credentials/keys/private_key.h \
-credentials/keys/public_key.c credentials/keys/public_key.h \
-credentials/keys/shared_key.c credentials/keys/shared_key.h \
-credentials/certificates/certificate.c credentials/certificates/certificate.h \
-credentials/certificates/x509.h credentials/certificates/ac.h \
-credentials/certificates/crl.h credentials/certificates/crl.c \
-credentials/certificates/pkcs10.h \
-credentials/certificates/ocsp_request.h \
-credentials/certificates/ocsp_response.h credentials/certificates/ocsp_response.c \
+library.c chunk.c debug.c enum.c settings.c printf_hook.c asn1/asn1.c \
+asn1/asn1_parser.c asn1/oid.c bio/bio_reader.c bio/bio_writer.c \
+crypto/crypters/crypter.c crypto/hashers/hasher.c crypto/pkcs7.c crypto/pkcs9.c \
+crypto/proposal/proposal_keywords.c crypto/proposal/proposal_keywords_static.c \
+crypto/prfs/prf.c crypto/prfs/mac_prf.c \
+crypto/rngs/rng.c crypto/prf_plus.c crypto/signers/signer.c \
+crypto/signers/mac_signer.c crypto/crypto_factory.c crypto/crypto_tester.c \
+crypto/diffie_hellman.c crypto/aead.c crypto/transform.c \
+credentials/credential_factory.c credentials/builder.c \
+credentials/cred_encoding.c credentials/keys/private_key.c \
+credentials/keys/public_key.c credentials/keys/shared_key.c \
+credentials/certificates/certificate.c credentials/certificates/crl.c \
+credentials/certificates/ocsp_response.c \
+credentials/ietf_attributes/ietf_attributes.c credentials/credential_manager.c \
+credentials/sets/auth_cfg_wrapper.c credentials/sets/ocsp_response_wrapper.c \
+credentials/sets/cert_cache.c credentials/sets/mem_cred.c \
+credentials/sets/callback_cred.c credentials/auth_cfg.c database/database.c \
+database/database_factory.c fetcher/fetcher.c fetcher/fetcher_manager.c eap/eap.c \
+ipsec/ipsec_types.c \
+pen/pen.c plugins/plugin_loader.c plugins/plugin_feature.c processing/jobs/job.c \
+processing/jobs/callback_job.c processing/processor.c processing/scheduler.c \
+selectors/traffic_selector.c threading/thread.c threading/thread_value.c \
+threading/mutex.c threading/semaphore.c threading/rwlock.c threading/spinlock.c \
+utils.c utils/host.c utils/packet.c utils/identification.c utils/lexparser.c \
+utils/linked_list.c utils/blocking_queue.c utils/hashtable.c utils/enumerator.c \
+utils/optionsfrom.c utils/capabilities.c utils/backtrace.c utils/tun_device.c
+
+if USE_DEV_HEADERS
+strongswan_includedir = ${dev_headers}
+nobase_strongswan_include_HEADERS = \
+library.h chunk.h debug.h enum.h settings.h printf_hook.h \
+asn1/asn1.h asn1/asn1_parser.h asn1/oid.h bio/bio_reader.h bio/bio_writer.h \
+crypto/crypters/crypter.h crypto/hashers/hasher.h crypto/mac.h \
+crypto/pkcs7.h crypto/pkcs9.h crypto/proposal/proposal_keywords.h \
+crypto/proposal/proposal_keywords_static.h \
+crypto/prfs/prf.h crypto/prfs/mac_prf.h crypto/rngs/rng.h crypto/nonce_gen.h \
+crypto/prf_plus.h crypto/signers/signer.h crypto/signers/mac_signer.h \
+crypto/crypto_factory.h crypto/crypto_tester.h crypto/diffie_hellman.h \
+crypto/aead.h crypto/transform.h \
+credentials/credential_factory.h credentials/builder.h \
+credentials/cred_encoding.h credentials/keys/private_key.h \
+credentials/keys/public_key.h credentials/keys/shared_key.h \
+credentials/certificates/certificate.h credentials/certificates/x509.h \
+credentials/certificates/ac.h credentials/certificates/crl.h \
+credentials/certificates/pkcs10.h credentials/certificates/ocsp_request.h \
+credentials/certificates/ocsp_response.h \
credentials/certificates/pgp_certificate.h \
-credentials/ietf_attributes/ietf_attributes.c credentials/ietf_attributes/ietf_attributes.h \
-credentials/credential_manager.c credentials/credential_manager.h \
-credentials/sets/auth_cfg_wrapper.c credentials/sets/auth_cfg_wrapper.h \
-credentials/sets/ocsp_response_wrapper.c credentials/sets/ocsp_response_wrapper.h \
-credentials/sets/cert_cache.c credentials/sets/cert_cache.h \
-credentials/sets/mem_cred.c credentials/sets/mem_cred.h \
-credentials/sets/callback_cred.c credentials/sets/callback_cred.h \
-credentials/auth_cfg.c credentials/auth_cfg.h credentials/credential_set.h \
-credentials/cert_validator.h database/database.h database/database.c \
-database/database_factory.h database/database_factory.c \
-fetcher/fetcher.h fetcher/fetcher.c fetcher/fetcher_manager.h fetcher/fetcher_manager.c \
-eap/eap.h eap/eap.c \
-pen/pen.h pen/pen.c \
-plugins/plugin_loader.c plugins/plugin_loader.h plugins/plugin.h \
-plugins/plugin_feature.c plugins/plugin_feature.h \
-processing/jobs/job.h processing/jobs/job.c \
-processing/jobs/callback_job.c processing/jobs/callback_job.h \
-processing/processor.c processing/processor.h \
-processing/scheduler.c processing/scheduler.h \
-selectors/traffic_selector.c selectors/traffic_selector.h \
-threading/thread.h threading/thread.c \
-threading/thread_value.h threading/thread_value.c \
-threading/mutex.h threading/mutex.c threading/condvar.h \
-threading/rwlock.h threading/rwlock.c \
-threading/lock_profiler.h \
-utils.h utils.c \
-utils/host.c utils/host.h \
-utils/identification.c utils/identification.h \
-utils/lexparser.c utils/lexparser.h \
-utils/linked_list.c utils/linked_list.h \
-utils/hashtable.c utils/hashtable.h \
-utils/enumerator.c utils/enumerator.h \
-utils/optionsfrom.c utils/optionsfrom.h \
-utils/backtrace.c utils/backtrace.h
-
+credentials/ietf_attributes/ietf_attributes.h \
+credentials/credential_manager.h credentials/sets/auth_cfg_wrapper.h \
+credentials/sets/ocsp_response_wrapper.h credentials/sets/cert_cache.h \
+credentials/sets/mem_cred.h credentials/sets/callback_cred.h \
+credentials/auth_cfg.h credentials/credential_set.h credentials/cert_validator.h \
+database/database.h database/database_factory.h fetcher/fetcher.h \
+fetcher/fetcher_manager.h eap/eap.h pen/pen.h ipsec/ipsec_types.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 selectors/traffic_selector.h \
+threading/thread.h threading/thread_value.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.h utils/host.h utils/packet.h utils/identification.h utils/lexparser.h \
+utils/linked_list.h utils/blocking_queue.h utils/hashtable.h utils/enumerator.h \
+utils/optionsfrom.h utils/capabilities.h utils/backtrace.h utils/tun_device.h \
+utils/leak_detective.h integrity_checker.h
+endif
library.lo : $(top_builddir)/config.status
-libstrongswan_la_LIBADD = $(PTHREADLIB) $(DLLIB) $(BTLIB) $(SOCKLIB) $(RTLIB)
+libstrongswan_la_LIBADD = $(PTHREADLIB) $(DLLIB) $(BTLIB) $(SOCKLIB) $(RTLIB) $(BFDLIB)
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = \
@@ -86,8 +80,7 @@ AM_CFLAGS = \
if USE_LEAK_DETECTIVE
AM_CFLAGS += -DLEAK_DETECTIVE
- libstrongswan_la_SOURCES += \
- utils/leak_detective.c utils/leak_detective.h
+ libstrongswan_la_SOURCES += utils/leak_detective.c
endif
if USE_LOCK_PROFILER
@@ -96,26 +89,29 @@ endif
if USE_INTEGRITY_TEST
AM_CFLAGS += -DINTEGRITY_TEST
- libstrongswan_la_SOURCES += \
- integrity_checker.c integrity_checker.h
+ libstrongswan_la_SOURCES += integrity_checker.c
endif
if USE_VSTR
libstrongswan_la_LIBADD += -lvstr
endif
+if USE_LIBCAP
+ libstrongswan_la_LIBADD += -lcap
+endif
+
EXTRA_DIST = \
asn1/oid.txt asn1/oid.pl \
-crypto/proposal/proposal_keywords.txt \
+crypto/proposal/proposal_keywords_static.txt \
Android.mk AndroidConfigLocal.h
BUILT_SOURCES = \
$(srcdir)/asn1/oid.c $(srcdir)/asn1/oid.h \
-$(srcdir)/crypto/proposal/proposal_keywords.c
+$(srcdir)/crypto/proposal/proposal_keywords_static.c
MAINTAINERCLEANFILES = \
$(srcdir)/asn1/oid.c $(srcdir)/asn1/oid.h \
-$(srcdir)/crypto/proposal/proposal_keywords.c
+$(srcdir)/crypto/proposal/proposal_keywords_static.c
$(srcdir)/asn1/oid.c : $(srcdir)/asn1/oid.pl $(srcdir)/asn1/oid.txt
(cd $(srcdir)/asn1/ && $(PERL) oid.pl)
@@ -123,10 +119,10 @@ $(srcdir)/asn1/oid.c : $(srcdir)/asn1/oid.pl $(srcdir)/asn1/oid.txt
$(srcdir)/asn1/oid.h : $(srcdir)/asn1/oid.pl $(srcdir)/asn1/oid.txt
(cd $(srcdir)/asn1/ && $(PERL) oid.pl)
-$(srcdir)/crypto/proposal/proposal_keywords.c: $(srcdir)/crypto/proposal/proposal_keywords.txt \
- $(srcdir)/crypto/proposal/proposal_keywords.h
- $(GPERF) -N proposal_get_token -m 10 -C -G -c -t -D < \
- $(srcdir)/crypto/proposal/proposal_keywords.txt > $@
+$(srcdir)/crypto/proposal/proposal_keywords_static.c: $(srcdir)/crypto/proposal/proposal_keywords_static.txt \
+ $(srcdir)/crypto/proposal/proposal_keywords_static.h
+ $(GPERF) -N proposal_get_token_static -m 10 -C -G -c -t -D < \
+ $(srcdir)/crypto/proposal/proposal_keywords_static.txt > $@
# build plugins with their own Makefile
@@ -208,6 +204,13 @@ if MONOLITHIC
endif
endif
+if USE_NONCE
+ SUBDIRS += plugins/nonce
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/nonce/libstrongswan-nonce.la
+endif
+endif
+
if USE_HMAC
SUBDIRS += plugins/hmac
if MONOLITHIC
diff --git a/src/libstrongswan/Makefile.in b/src/libstrongswan/Makefile.in
index 68c83a5aa..aeebb25c0 100644
--- a/src/libstrongswan/Makefile.in
+++ b/src/libstrongswan/Makefile.in
@@ -15,6 +15,7 @@
@SET_MAKE@
+
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
@@ -35,91 +36,91 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
@USE_LEAK_DETECTIVE_TRUE@am__append_1 = -DLEAK_DETECTIVE
-@USE_LEAK_DETECTIVE_TRUE@am__append_2 = \
-@USE_LEAK_DETECTIVE_TRUE@ utils/leak_detective.c utils/leak_detective.h
-
+@USE_LEAK_DETECTIVE_TRUE@am__append_2 = utils/leak_detective.c
@USE_LOCK_PROFILER_TRUE@am__append_3 = -DLOCK_PROFILER
@USE_INTEGRITY_TEST_TRUE@am__append_4 = -DINTEGRITY_TEST
-@USE_INTEGRITY_TEST_TRUE@am__append_5 = \
-@USE_INTEGRITY_TEST_TRUE@ integrity_checker.c integrity_checker.h
-
+@USE_INTEGRITY_TEST_TRUE@am__append_5 = integrity_checker.c
@USE_VSTR_TRUE@am__append_6 = -lvstr
-@USE_AF_ALG_TRUE@am__append_7 = plugins/af_alg
-@MONOLITHIC_TRUE@@USE_AF_ALG_TRUE@am__append_8 = plugins/af_alg/libstrongswan-af-alg.la
-@USE_AES_TRUE@am__append_9 = plugins/aes
-@MONOLITHIC_TRUE@@USE_AES_TRUE@am__append_10 = plugins/aes/libstrongswan-aes.la
-@USE_DES_TRUE@am__append_11 = plugins/des
-@MONOLITHIC_TRUE@@USE_DES_TRUE@am__append_12 = plugins/des/libstrongswan-des.la
-@USE_BLOWFISH_TRUE@am__append_13 = plugins/blowfish
-@MONOLITHIC_TRUE@@USE_BLOWFISH_TRUE@am__append_14 = plugins/blowfish/libstrongswan-blowfish.la
-@USE_MD4_TRUE@am__append_15 = plugins/md4
-@MONOLITHIC_TRUE@@USE_MD4_TRUE@am__append_16 = plugins/md4/libstrongswan-md4.la
-@USE_MD5_TRUE@am__append_17 = plugins/md5
-@MONOLITHIC_TRUE@@USE_MD5_TRUE@am__append_18 = plugins/md5/libstrongswan-md5.la
-@USE_SHA1_TRUE@am__append_19 = plugins/sha1
-@MONOLITHIC_TRUE@@USE_SHA1_TRUE@am__append_20 = plugins/sha1/libstrongswan-sha1.la
-@USE_SHA2_TRUE@am__append_21 = plugins/sha2
-@MONOLITHIC_TRUE@@USE_SHA2_TRUE@am__append_22 = plugins/sha2/libstrongswan-sha2.la
-@USE_GMP_TRUE@am__append_23 = plugins/gmp
-@MONOLITHIC_TRUE@@USE_GMP_TRUE@am__append_24 = plugins/gmp/libstrongswan-gmp.la
-@USE_RANDOM_TRUE@am__append_25 = plugins/random
-@MONOLITHIC_TRUE@@USE_RANDOM_TRUE@am__append_26 = plugins/random/libstrongswan-random.la
-@USE_HMAC_TRUE@am__append_27 = plugins/hmac
-@MONOLITHIC_TRUE@@USE_HMAC_TRUE@am__append_28 = plugins/hmac/libstrongswan-hmac.la
-@USE_CMAC_TRUE@am__append_29 = plugins/cmac
-@MONOLITHIC_TRUE@@USE_CMAC_TRUE@am__append_30 = plugins/cmac/libstrongswan-cmac.la
-@USE_XCBC_TRUE@am__append_31 = plugins/xcbc
-@MONOLITHIC_TRUE@@USE_XCBC_TRUE@am__append_32 = plugins/xcbc/libstrongswan-xcbc.la
-@USE_X509_TRUE@am__append_33 = plugins/x509
-@MONOLITHIC_TRUE@@USE_X509_TRUE@am__append_34 = plugins/x509/libstrongswan-x509.la
-@USE_REVOCATION_TRUE@am__append_35 = plugins/revocation
-@MONOLITHIC_TRUE@@USE_REVOCATION_TRUE@am__append_36 = plugins/revocation/libstrongswan-revocation.la
-@USE_CONSTRAINTS_TRUE@am__append_37 = plugins/constraints
-@MONOLITHIC_TRUE@@USE_CONSTRAINTS_TRUE@am__append_38 = plugins/constraints/libstrongswan-constraints.la
-@USE_PUBKEY_TRUE@am__append_39 = plugins/pubkey
-@MONOLITHIC_TRUE@@USE_PUBKEY_TRUE@am__append_40 = plugins/pubkey/libstrongswan-pubkey.la
-@USE_PKCS1_TRUE@am__append_41 = plugins/pkcs1
-@MONOLITHIC_TRUE@@USE_PKCS1_TRUE@am__append_42 = plugins/pkcs1/libstrongswan-pkcs1.la
-@USE_PKCS8_TRUE@am__append_43 = plugins/pkcs8
-@MONOLITHIC_TRUE@@USE_PKCS8_TRUE@am__append_44 = plugins/pkcs8/libstrongswan-pkcs8.la
-@USE_PGP_TRUE@am__append_45 = plugins/pgp
-@MONOLITHIC_TRUE@@USE_PGP_TRUE@am__append_46 = plugins/pgp/libstrongswan-pgp.la
-@USE_DNSKEY_TRUE@am__append_47 = plugins/dnskey
-@MONOLITHIC_TRUE@@USE_DNSKEY_TRUE@am__append_48 = plugins/dnskey/libstrongswan-dnskey.la
-@USE_PEM_TRUE@am__append_49 = plugins/pem
-@MONOLITHIC_TRUE@@USE_PEM_TRUE@am__append_50 = plugins/pem/libstrongswan-pem.la
-@USE_CURL_TRUE@am__append_51 = plugins/curl
-@MONOLITHIC_TRUE@@USE_CURL_TRUE@am__append_52 = plugins/curl/libstrongswan-curl.la
-@USE_SOUP_TRUE@am__append_53 = plugins/soup
-@MONOLITHIC_TRUE@@USE_SOUP_TRUE@am__append_54 = plugins/soup/libstrongswan-soup.la
-@USE_LDAP_TRUE@am__append_55 = plugins/ldap
-@MONOLITHIC_TRUE@@USE_LDAP_TRUE@am__append_56 = plugins/ldap/libstrongswan-ldap.la
-@USE_MYSQL_TRUE@am__append_57 = plugins/mysql
-@MONOLITHIC_TRUE@@USE_MYSQL_TRUE@am__append_58 = plugins/mysql/libstrongswan-mysql.la
-@USE_SQLITE_TRUE@am__append_59 = plugins/sqlite
-@MONOLITHIC_TRUE@@USE_SQLITE_TRUE@am__append_60 = plugins/sqlite/libstrongswan-sqlite.la
-@USE_PADLOCK_TRUE@am__append_61 = plugins/padlock
-@MONOLITHIC_TRUE@@USE_PADLOCK_TRUE@am__append_62 = plugins/padlock/libstrongswan-padlock.la
-@USE_OPENSSL_TRUE@am__append_63 = plugins/openssl
-@MONOLITHIC_TRUE@@USE_OPENSSL_TRUE@am__append_64 = plugins/openssl/libstrongswan-openssl.la
-@USE_GCRYPT_TRUE@am__append_65 = plugins/gcrypt
-@MONOLITHIC_TRUE@@USE_GCRYPT_TRUE@am__append_66 = plugins/gcrypt/libstrongswan-gcrypt.la
-@USE_FIPS_PRF_TRUE@am__append_67 = plugins/fips_prf
-@MONOLITHIC_TRUE@@USE_FIPS_PRF_TRUE@am__append_68 = plugins/fips_prf/libstrongswan-fips-prf.la
-@USE_AGENT_TRUE@am__append_69 = plugins/agent
-@MONOLITHIC_TRUE@@USE_AGENT_TRUE@am__append_70 = plugins/agent/libstrongswan-agent.la
-@USE_PKCS11_TRUE@am__append_71 = plugins/pkcs11
-@MONOLITHIC_TRUE@@USE_PKCS11_TRUE@am__append_72 = plugins/pkcs11/libstrongswan-pkcs11.la
-@USE_CTR_TRUE@am__append_73 = plugins/ctr
-@MONOLITHIC_TRUE@@USE_CTR_TRUE@am__append_74 = plugins/ctr/libstrongswan-ctr.la
-@USE_CCM_TRUE@am__append_75 = plugins/ccm
-@MONOLITHIC_TRUE@@USE_CCM_TRUE@am__append_76 = plugins/ccm/libstrongswan-ccm.la
-@USE_GCM_TRUE@am__append_77 = plugins/gcm
-@MONOLITHIC_TRUE@@USE_GCM_TRUE@am__append_78 = plugins/gcm/libstrongswan-gcm.la
-@USE_TEST_VECTORS_TRUE@am__append_79 = plugins/test_vectors
-@MONOLITHIC_TRUE@@USE_TEST_VECTORS_TRUE@am__append_80 = plugins/test_vectors/libstrongswan-test-vectors.la
+@USE_LIBCAP_TRUE@am__append_7 = -lcap
+@USE_AF_ALG_TRUE@am__append_8 = plugins/af_alg
+@MONOLITHIC_TRUE@@USE_AF_ALG_TRUE@am__append_9 = plugins/af_alg/libstrongswan-af-alg.la
+@USE_AES_TRUE@am__append_10 = plugins/aes
+@MONOLITHIC_TRUE@@USE_AES_TRUE@am__append_11 = plugins/aes/libstrongswan-aes.la
+@USE_DES_TRUE@am__append_12 = plugins/des
+@MONOLITHIC_TRUE@@USE_DES_TRUE@am__append_13 = plugins/des/libstrongswan-des.la
+@USE_BLOWFISH_TRUE@am__append_14 = plugins/blowfish
+@MONOLITHIC_TRUE@@USE_BLOWFISH_TRUE@am__append_15 = plugins/blowfish/libstrongswan-blowfish.la
+@USE_MD4_TRUE@am__append_16 = plugins/md4
+@MONOLITHIC_TRUE@@USE_MD4_TRUE@am__append_17 = plugins/md4/libstrongswan-md4.la
+@USE_MD5_TRUE@am__append_18 = plugins/md5
+@MONOLITHIC_TRUE@@USE_MD5_TRUE@am__append_19 = plugins/md5/libstrongswan-md5.la
+@USE_SHA1_TRUE@am__append_20 = plugins/sha1
+@MONOLITHIC_TRUE@@USE_SHA1_TRUE@am__append_21 = plugins/sha1/libstrongswan-sha1.la
+@USE_SHA2_TRUE@am__append_22 = plugins/sha2
+@MONOLITHIC_TRUE@@USE_SHA2_TRUE@am__append_23 = plugins/sha2/libstrongswan-sha2.la
+@USE_GMP_TRUE@am__append_24 = plugins/gmp
+@MONOLITHIC_TRUE@@USE_GMP_TRUE@am__append_25 = plugins/gmp/libstrongswan-gmp.la
+@USE_RANDOM_TRUE@am__append_26 = plugins/random
+@MONOLITHIC_TRUE@@USE_RANDOM_TRUE@am__append_27 = plugins/random/libstrongswan-random.la
+@USE_NONCE_TRUE@am__append_28 = plugins/nonce
+@MONOLITHIC_TRUE@@USE_NONCE_TRUE@am__append_29 = plugins/nonce/libstrongswan-nonce.la
+@USE_HMAC_TRUE@am__append_30 = plugins/hmac
+@MONOLITHIC_TRUE@@USE_HMAC_TRUE@am__append_31 = plugins/hmac/libstrongswan-hmac.la
+@USE_CMAC_TRUE@am__append_32 = plugins/cmac
+@MONOLITHIC_TRUE@@USE_CMAC_TRUE@am__append_33 = plugins/cmac/libstrongswan-cmac.la
+@USE_XCBC_TRUE@am__append_34 = plugins/xcbc
+@MONOLITHIC_TRUE@@USE_XCBC_TRUE@am__append_35 = plugins/xcbc/libstrongswan-xcbc.la
+@USE_X509_TRUE@am__append_36 = plugins/x509
+@MONOLITHIC_TRUE@@USE_X509_TRUE@am__append_37 = plugins/x509/libstrongswan-x509.la
+@USE_REVOCATION_TRUE@am__append_38 = plugins/revocation
+@MONOLITHIC_TRUE@@USE_REVOCATION_TRUE@am__append_39 = plugins/revocation/libstrongswan-revocation.la
+@USE_CONSTRAINTS_TRUE@am__append_40 = plugins/constraints
+@MONOLITHIC_TRUE@@USE_CONSTRAINTS_TRUE@am__append_41 = plugins/constraints/libstrongswan-constraints.la
+@USE_PUBKEY_TRUE@am__append_42 = plugins/pubkey
+@MONOLITHIC_TRUE@@USE_PUBKEY_TRUE@am__append_43 = plugins/pubkey/libstrongswan-pubkey.la
+@USE_PKCS1_TRUE@am__append_44 = plugins/pkcs1
+@MONOLITHIC_TRUE@@USE_PKCS1_TRUE@am__append_45 = plugins/pkcs1/libstrongswan-pkcs1.la
+@USE_PKCS8_TRUE@am__append_46 = plugins/pkcs8
+@MONOLITHIC_TRUE@@USE_PKCS8_TRUE@am__append_47 = plugins/pkcs8/libstrongswan-pkcs8.la
+@USE_PGP_TRUE@am__append_48 = plugins/pgp
+@MONOLITHIC_TRUE@@USE_PGP_TRUE@am__append_49 = plugins/pgp/libstrongswan-pgp.la
+@USE_DNSKEY_TRUE@am__append_50 = plugins/dnskey
+@MONOLITHIC_TRUE@@USE_DNSKEY_TRUE@am__append_51 = plugins/dnskey/libstrongswan-dnskey.la
+@USE_PEM_TRUE@am__append_52 = plugins/pem
+@MONOLITHIC_TRUE@@USE_PEM_TRUE@am__append_53 = plugins/pem/libstrongswan-pem.la
+@USE_CURL_TRUE@am__append_54 = plugins/curl
+@MONOLITHIC_TRUE@@USE_CURL_TRUE@am__append_55 = plugins/curl/libstrongswan-curl.la
+@USE_SOUP_TRUE@am__append_56 = plugins/soup
+@MONOLITHIC_TRUE@@USE_SOUP_TRUE@am__append_57 = plugins/soup/libstrongswan-soup.la
+@USE_LDAP_TRUE@am__append_58 = plugins/ldap
+@MONOLITHIC_TRUE@@USE_LDAP_TRUE@am__append_59 = plugins/ldap/libstrongswan-ldap.la
+@USE_MYSQL_TRUE@am__append_60 = plugins/mysql
+@MONOLITHIC_TRUE@@USE_MYSQL_TRUE@am__append_61 = plugins/mysql/libstrongswan-mysql.la
+@USE_SQLITE_TRUE@am__append_62 = plugins/sqlite
+@MONOLITHIC_TRUE@@USE_SQLITE_TRUE@am__append_63 = plugins/sqlite/libstrongswan-sqlite.la
+@USE_PADLOCK_TRUE@am__append_64 = plugins/padlock
+@MONOLITHIC_TRUE@@USE_PADLOCK_TRUE@am__append_65 = plugins/padlock/libstrongswan-padlock.la
+@USE_OPENSSL_TRUE@am__append_66 = plugins/openssl
+@MONOLITHIC_TRUE@@USE_OPENSSL_TRUE@am__append_67 = plugins/openssl/libstrongswan-openssl.la
+@USE_GCRYPT_TRUE@am__append_68 = plugins/gcrypt
+@MONOLITHIC_TRUE@@USE_GCRYPT_TRUE@am__append_69 = plugins/gcrypt/libstrongswan-gcrypt.la
+@USE_FIPS_PRF_TRUE@am__append_70 = plugins/fips_prf
+@MONOLITHIC_TRUE@@USE_FIPS_PRF_TRUE@am__append_71 = plugins/fips_prf/libstrongswan-fips-prf.la
+@USE_AGENT_TRUE@am__append_72 = plugins/agent
+@MONOLITHIC_TRUE@@USE_AGENT_TRUE@am__append_73 = plugins/agent/libstrongswan-agent.la
+@USE_PKCS11_TRUE@am__append_74 = plugins/pkcs11
+@MONOLITHIC_TRUE@@USE_PKCS11_TRUE@am__append_75 = plugins/pkcs11/libstrongswan-pkcs11.la
+@USE_CTR_TRUE@am__append_76 = plugins/ctr
+@MONOLITHIC_TRUE@@USE_CTR_TRUE@am__append_77 = plugins/ctr/libstrongswan-ctr.la
+@USE_CCM_TRUE@am__append_78 = plugins/ccm
+@MONOLITHIC_TRUE@@USE_CCM_TRUE@am__append_79 = plugins/ccm/libstrongswan-ccm.la
+@USE_GCM_TRUE@am__append_80 = plugins/gcm
+@MONOLITHIC_TRUE@@USE_GCM_TRUE@am__append_81 = plugins/gcm/libstrongswan-gcm.la
+@USE_TEST_VECTORS_TRUE@am__append_82 = plugins/test_vectors
+@MONOLITHIC_TRUE@@USE_TEST_VECTORS_TRUE@am__append_83 = plugins/test_vectors/libstrongswan-test-vectors.la
subdir = src/libstrongswan
-DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+DIST_COMMON = $(am__nobase_strongswan_include_HEADERS_DIST) \
+ $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
$(top_srcdir)/m4/config/ltoptions.m4 \
@@ -133,6 +134,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -156,101 +158,70 @@ am__nobase_list = $(am__nobase_strip_setup); \
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
-am__installdirs = "$(DESTDIR)$(ipseclibdir)"
+am__installdirs = "$(DESTDIR)$(ipseclibdir)" \
+ "$(DESTDIR)$(strongswan_includedir)"
LTLIBRARIES = $(ipseclib_LTLIBRARIES)
am__DEPENDENCIES_1 =
libstrongswan_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1) $(am__append_8) $(am__append_10) \
- $(am__append_12) $(am__append_14) $(am__append_16) \
- $(am__append_18) $(am__append_20) $(am__append_22) \
- $(am__append_24) $(am__append_26) $(am__append_28) \
- $(am__append_30) $(am__append_32) $(am__append_34) \
- $(am__append_36) $(am__append_38) $(am__append_40) \
- $(am__append_42) $(am__append_44) $(am__append_46) \
- $(am__append_48) $(am__append_50) $(am__append_52) \
- $(am__append_54) $(am__append_56) $(am__append_58) \
- $(am__append_60) $(am__append_62) $(am__append_64) \
- $(am__append_66) $(am__append_68) $(am__append_70) \
- $(am__append_72) $(am__append_74) $(am__append_76) \
- $(am__append_78) $(am__append_80)
-am__libstrongswan_la_SOURCES_DIST = library.c library.h chunk.c \
- chunk.h debug.c debug.h enum.c enum.h settings.h settings.c \
- printf_hook.c printf_hook.h asn1/asn1.c asn1/asn1.h \
- asn1/asn1_parser.c asn1/asn1_parser.h asn1/oid.c asn1/oid.h \
- bio/bio_reader.h bio/bio_reader.c bio/bio_writer.h \
- bio/bio_writer.c crypto/crypters/crypter.c \
- crypto/crypters/crypter.h crypto/hashers/hasher.h \
- crypto/hashers/hasher.c crypto/pkcs9.c crypto/pkcs9.h \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__append_9) $(am__append_11) \
+ $(am__append_13) $(am__append_15) $(am__append_17) \
+ $(am__append_19) $(am__append_21) $(am__append_23) \
+ $(am__append_25) $(am__append_27) $(am__append_29) \
+ $(am__append_31) $(am__append_33) $(am__append_35) \
+ $(am__append_37) $(am__append_39) $(am__append_41) \
+ $(am__append_43) $(am__append_45) $(am__append_47) \
+ $(am__append_49) $(am__append_51) $(am__append_53) \
+ $(am__append_55) $(am__append_57) $(am__append_59) \
+ $(am__append_61) $(am__append_63) $(am__append_65) \
+ $(am__append_67) $(am__append_69) $(am__append_71) \
+ $(am__append_73) $(am__append_75) $(am__append_77) \
+ $(am__append_79) $(am__append_81) $(am__append_83)
+am__libstrongswan_la_SOURCES_DIST = library.c chunk.c debug.c enum.c \
+ settings.c printf_hook.c asn1/asn1.c asn1/asn1_parser.c \
+ asn1/oid.c bio/bio_reader.c bio/bio_writer.c \
+ crypto/crypters/crypter.c crypto/hashers/hasher.c \
+ crypto/pkcs7.c crypto/pkcs9.c \
crypto/proposal/proposal_keywords.c \
- crypto/proposal/proposal_keywords.h crypto/prfs/prf.c \
- crypto/prfs/prf.h crypto/rngs/rng.c crypto/rngs/rng.h \
- crypto/prf_plus.h crypto/prf_plus.c crypto/signers/signer.c \
- crypto/signers/signer.h crypto/crypto_factory.c \
- crypto/crypto_factory.h crypto/crypto_tester.c \
- crypto/crypto_tester.h crypto/diffie_hellman.c \
- crypto/diffie_hellman.h crypto/aead.c crypto/aead.h \
- crypto/transform.c crypto/transform.h \
- credentials/credential_factory.c \
- credentials/credential_factory.h credentials/builder.c \
- credentials/builder.h credentials/cred_encoding.c \
- credentials/cred_encoding.h credentials/keys/private_key.c \
- credentials/keys/private_key.h credentials/keys/public_key.c \
- credentials/keys/public_key.h credentials/keys/shared_key.c \
- credentials/keys/shared_key.h \
+ crypto/proposal/proposal_keywords_static.c crypto/prfs/prf.c \
+ crypto/prfs/mac_prf.c crypto/rngs/rng.c crypto/prf_plus.c \
+ crypto/signers/signer.c crypto/signers/mac_signer.c \
+ crypto/crypto_factory.c crypto/crypto_tester.c \
+ crypto/diffie_hellman.c crypto/aead.c crypto/transform.c \
+ credentials/credential_factory.c credentials/builder.c \
+ credentials/cred_encoding.c credentials/keys/private_key.c \
+ credentials/keys/public_key.c credentials/keys/shared_key.c \
credentials/certificates/certificate.c \
- credentials/certificates/certificate.h \
- credentials/certificates/x509.h credentials/certificates/ac.h \
- credentials/certificates/crl.h credentials/certificates/crl.c \
- credentials/certificates/pkcs10.h \
- credentials/certificates/ocsp_request.h \
- credentials/certificates/ocsp_response.h \
+ credentials/certificates/crl.c \
credentials/certificates/ocsp_response.c \
- credentials/certificates/pgp_certificate.h \
credentials/ietf_attributes/ietf_attributes.c \
- credentials/ietf_attributes/ietf_attributes.h \
credentials/credential_manager.c \
- credentials/credential_manager.h \
credentials/sets/auth_cfg_wrapper.c \
- credentials/sets/auth_cfg_wrapper.h \
credentials/sets/ocsp_response_wrapper.c \
- credentials/sets/ocsp_response_wrapper.h \
- credentials/sets/cert_cache.c credentials/sets/cert_cache.h \
- credentials/sets/mem_cred.c credentials/sets/mem_cred.h \
- credentials/sets/callback_cred.c \
- credentials/sets/callback_cred.h credentials/auth_cfg.c \
- credentials/auth_cfg.h credentials/credential_set.h \
- credentials/cert_validator.h database/database.h \
- database/database.c database/database_factory.h \
- database/database_factory.c fetcher/fetcher.h \
- fetcher/fetcher.c fetcher/fetcher_manager.h \
- fetcher/fetcher_manager.c eap/eap.h eap/eap.c pen/pen.h \
- pen/pen.c plugins/plugin_loader.c plugins/plugin_loader.h \
- plugins/plugin.h plugins/plugin_feature.c \
- plugins/plugin_feature.h processing/jobs/job.h \
- processing/jobs/job.c processing/jobs/callback_job.c \
- processing/jobs/callback_job.h processing/processor.c \
- processing/processor.h processing/scheduler.c \
- processing/scheduler.h selectors/traffic_selector.c \
- selectors/traffic_selector.h threading/thread.h \
- threading/thread.c threading/thread_value.h \
- threading/thread_value.c threading/mutex.h threading/mutex.c \
- threading/condvar.h threading/rwlock.h threading/rwlock.c \
- threading/lock_profiler.h utils.h utils.c utils/host.c \
- utils/host.h utils/identification.c utils/identification.h \
- utils/lexparser.c utils/lexparser.h utils/linked_list.c \
- utils/linked_list.h utils/hashtable.c utils/hashtable.h \
- utils/enumerator.c utils/enumerator.h utils/optionsfrom.c \
- utils/optionsfrom.h utils/backtrace.c utils/backtrace.h \
- utils/leak_detective.c utils/leak_detective.h \
- integrity_checker.c integrity_checker.h
+ credentials/sets/cert_cache.c credentials/sets/mem_cred.c \
+ credentials/sets/callback_cred.c credentials/auth_cfg.c \
+ database/database.c database/database_factory.c \
+ fetcher/fetcher.c fetcher/fetcher_manager.c eap/eap.c \
+ ipsec/ipsec_types.c pen/pen.c plugins/plugin_loader.c \
+ plugins/plugin_feature.c processing/jobs/job.c \
+ processing/jobs/callback_job.c processing/processor.c \
+ processing/scheduler.c selectors/traffic_selector.c \
+ threading/thread.c threading/thread_value.c threading/mutex.c \
+ threading/semaphore.c threading/rwlock.c threading/spinlock.c \
+ utils.c utils/host.c utils/packet.c utils/identification.c \
+ utils/lexparser.c utils/linked_list.c utils/blocking_queue.c \
+ utils/hashtable.c utils/enumerator.c utils/optionsfrom.c \
+ utils/capabilities.c utils/backtrace.c utils/tun_device.c \
+ utils/leak_detective.c integrity_checker.c
@USE_LEAK_DETECTIVE_TRUE@am__objects_1 = leak_detective.lo
@USE_INTEGRITY_TEST_TRUE@am__objects_2 = integrity_checker.lo
am_libstrongswan_la_OBJECTS = library.lo chunk.lo debug.lo enum.lo \
settings.lo printf_hook.lo asn1.lo asn1_parser.lo oid.lo \
- bio_reader.lo bio_writer.lo crypter.lo hasher.lo pkcs9.lo \
- proposal_keywords.lo prf.lo rng.lo prf_plus.lo signer.lo \
+ bio_reader.lo bio_writer.lo crypter.lo hasher.lo pkcs7.lo \
+ pkcs9.lo proposal_keywords.lo proposal_keywords_static.lo \
+ prf.lo mac_prf.lo rng.lo prf_plus.lo signer.lo mac_signer.lo \
crypto_factory.lo crypto_tester.lo diffie_hellman.lo aead.lo \
transform.lo credential_factory.lo builder.lo cred_encoding.lo \
private_key.lo public_key.lo shared_key.lo certificate.lo \
@@ -258,14 +229,16 @@ am_libstrongswan_la_OBJECTS = library.lo chunk.lo debug.lo enum.lo \
credential_manager.lo auth_cfg_wrapper.lo \
ocsp_response_wrapper.lo cert_cache.lo mem_cred.lo \
callback_cred.lo auth_cfg.lo database.lo database_factory.lo \
- fetcher.lo fetcher_manager.lo eap.lo pen.lo plugin_loader.lo \
- plugin_feature.lo job.lo callback_job.lo processor.lo \
- scheduler.lo traffic_selector.lo thread.lo thread_value.lo \
- mutex.lo rwlock.lo utils.lo host.lo identification.lo \
- lexparser.lo linked_list.lo hashtable.lo enumerator.lo \
- optionsfrom.lo backtrace.lo $(am__objects_1) $(am__objects_2)
+ fetcher.lo fetcher_manager.lo eap.lo ipsec_types.lo pen.lo \
+ plugin_loader.lo plugin_feature.lo job.lo callback_job.lo \
+ processor.lo scheduler.lo traffic_selector.lo thread.lo \
+ thread_value.lo mutex.lo semaphore.lo rwlock.lo spinlock.lo \
+ utils.lo host.lo packet.lo identification.lo lexparser.lo \
+ linked_list.lo blocking_queue.lo hashtable.lo enumerator.lo \
+ optionsfrom.lo capabilities.lo backtrace.lo tun_device.lo \
+ $(am__objects_1) $(am__objects_2)
libstrongswan_la_OBJECTS = $(am_libstrongswan_la_OBJECTS)
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -287,6 +260,51 @@ RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
install-pdf-recursive install-ps-recursive install-recursive \
installcheck-recursive installdirs-recursive pdf-recursive \
ps-recursive uninstall-recursive
+am__nobase_strongswan_include_HEADERS_DIST = library.h chunk.h debug.h \
+ enum.h settings.h printf_hook.h asn1/asn1.h asn1/asn1_parser.h \
+ asn1/oid.h bio/bio_reader.h bio/bio_writer.h \
+ crypto/crypters/crypter.h crypto/hashers/hasher.h crypto/mac.h \
+ crypto/pkcs7.h crypto/pkcs9.h \
+ crypto/proposal/proposal_keywords.h \
+ crypto/proposal/proposal_keywords_static.h crypto/prfs/prf.h \
+ crypto/prfs/mac_prf.h crypto/rngs/rng.h crypto/nonce_gen.h \
+ crypto/prf_plus.h crypto/signers/signer.h \
+ crypto/signers/mac_signer.h crypto/crypto_factory.h \
+ crypto/crypto_tester.h crypto/diffie_hellman.h crypto/aead.h \
+ crypto/transform.h credentials/credential_factory.h \
+ credentials/builder.h credentials/cred_encoding.h \
+ credentials/keys/private_key.h credentials/keys/public_key.h \
+ credentials/keys/shared_key.h \
+ credentials/certificates/certificate.h \
+ credentials/certificates/x509.h credentials/certificates/ac.h \
+ credentials/certificates/crl.h \
+ credentials/certificates/pkcs10.h \
+ credentials/certificates/ocsp_request.h \
+ credentials/certificates/ocsp_response.h \
+ credentials/certificates/pgp_certificate.h \
+ credentials/ietf_attributes/ietf_attributes.h \
+ credentials/credential_manager.h \
+ credentials/sets/auth_cfg_wrapper.h \
+ credentials/sets/ocsp_response_wrapper.h \
+ credentials/sets/cert_cache.h credentials/sets/mem_cred.h \
+ credentials/sets/callback_cred.h credentials/auth_cfg.h \
+ credentials/credential_set.h credentials/cert_validator.h \
+ database/database.h database/database_factory.h \
+ fetcher/fetcher.h fetcher/fetcher_manager.h eap/eap.h \
+ pen/pen.h ipsec/ipsec_types.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 \
+ selectors/traffic_selector.h threading/thread.h \
+ threading/thread_value.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.h \
+ utils/host.h utils/packet.h utils/identification.h \
+ utils/lexparser.h utils/linked_list.h utils/blocking_queue.h \
+ utils/hashtable.h utils/enumerator.h utils/optionsfrom.h \
+ utils/capabilities.h utils/backtrace.h utils/tun_device.h \
+ utils/leak_detective.h integrity_checker.h
+HEADERS = $(nobase_strongswan_include_HEADERS)
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive
AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
@@ -296,14 +314,14 @@ ETAGS = etags
CTAGS = ctags
DIST_SUBDIRS = . plugins/af_alg plugins/aes plugins/des \
plugins/blowfish plugins/md4 plugins/md5 plugins/sha1 \
- plugins/sha2 plugins/gmp plugins/random plugins/hmac \
- plugins/cmac plugins/xcbc plugins/x509 plugins/revocation \
- plugins/constraints plugins/pubkey plugins/pkcs1 plugins/pkcs8 \
- plugins/pgp plugins/dnskey plugins/pem plugins/curl \
- plugins/soup plugins/ldap plugins/mysql plugins/sqlite \
- plugins/padlock plugins/openssl plugins/gcrypt \
- plugins/fips_prf plugins/agent plugins/pkcs11 plugins/ctr \
- plugins/ccm plugins/gcm plugins/test_vectors
+ plugins/sha2 plugins/gmp plugins/random plugins/nonce \
+ plugins/hmac plugins/cmac plugins/xcbc plugins/x509 \
+ plugins/revocation plugins/constraints plugins/pubkey \
+ plugins/pkcs1 plugins/pkcs8 plugins/pgp plugins/dnskey \
+ plugins/pem plugins/curl plugins/soup plugins/ldap \
+ plugins/mysql plugins/sqlite plugins/padlock plugins/openssl \
+ plugins/gcrypt plugins/fips_prf plugins/agent plugins/pkcs11 \
+ plugins/ctr plugins/ccm plugins/gcm plugins/test_vectors
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
am__relativize = \
dir0=`pwd`; \
@@ -338,6 +356,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -432,11 +451,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -453,11 +475,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -473,6 +496,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -482,7 +506,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -511,88 +534,93 @@ urandom_device = @urandom_device@
xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
ipseclib_LTLIBRARIES = libstrongswan.la
-libstrongswan_la_SOURCES = library.c library.h chunk.c chunk.h debug.c \
- debug.h enum.c enum.h settings.h settings.c printf_hook.c \
- printf_hook.h asn1/asn1.c asn1/asn1.h asn1/asn1_parser.c \
- asn1/asn1_parser.h asn1/oid.c asn1/oid.h bio/bio_reader.h \
- bio/bio_reader.c bio/bio_writer.h bio/bio_writer.c \
- crypto/crypters/crypter.c crypto/crypters/crypter.h \
- crypto/hashers/hasher.h crypto/hashers/hasher.c crypto/pkcs9.c \
- crypto/pkcs9.h crypto/proposal/proposal_keywords.c \
- crypto/proposal/proposal_keywords.h crypto/prfs/prf.c \
- crypto/prfs/prf.h crypto/rngs/rng.c crypto/rngs/rng.h \
- crypto/prf_plus.h crypto/prf_plus.c crypto/signers/signer.c \
- crypto/signers/signer.h crypto/crypto_factory.c \
- crypto/crypto_factory.h crypto/crypto_tester.c \
- crypto/crypto_tester.h crypto/diffie_hellman.c \
- crypto/diffie_hellman.h crypto/aead.c crypto/aead.h \
- crypto/transform.c crypto/transform.h \
- credentials/credential_factory.c \
- credentials/credential_factory.h credentials/builder.c \
- credentials/builder.h credentials/cred_encoding.c \
- credentials/cred_encoding.h credentials/keys/private_key.c \
- credentials/keys/private_key.h credentials/keys/public_key.c \
- credentials/keys/public_key.h credentials/keys/shared_key.c \
- credentials/keys/shared_key.h \
+libstrongswan_la_SOURCES = library.c chunk.c debug.c enum.c settings.c \
+ printf_hook.c asn1/asn1.c asn1/asn1_parser.c asn1/oid.c \
+ bio/bio_reader.c bio/bio_writer.c crypto/crypters/crypter.c \
+ crypto/hashers/hasher.c crypto/pkcs7.c crypto/pkcs9.c \
+ crypto/proposal/proposal_keywords.c \
+ crypto/proposal/proposal_keywords_static.c crypto/prfs/prf.c \
+ crypto/prfs/mac_prf.c crypto/rngs/rng.c crypto/prf_plus.c \
+ crypto/signers/signer.c crypto/signers/mac_signer.c \
+ crypto/crypto_factory.c crypto/crypto_tester.c \
+ crypto/diffie_hellman.c crypto/aead.c crypto/transform.c \
+ credentials/credential_factory.c credentials/builder.c \
+ credentials/cred_encoding.c credentials/keys/private_key.c \
+ credentials/keys/public_key.c credentials/keys/shared_key.c \
credentials/certificates/certificate.c \
- credentials/certificates/certificate.h \
- credentials/certificates/x509.h credentials/certificates/ac.h \
- credentials/certificates/crl.h credentials/certificates/crl.c \
- credentials/certificates/pkcs10.h \
- credentials/certificates/ocsp_request.h \
- credentials/certificates/ocsp_response.h \
+ credentials/certificates/crl.c \
credentials/certificates/ocsp_response.c \
- credentials/certificates/pgp_certificate.h \
credentials/ietf_attributes/ietf_attributes.c \
- credentials/ietf_attributes/ietf_attributes.h \
credentials/credential_manager.c \
- credentials/credential_manager.h \
credentials/sets/auth_cfg_wrapper.c \
- credentials/sets/auth_cfg_wrapper.h \
credentials/sets/ocsp_response_wrapper.c \
- credentials/sets/ocsp_response_wrapper.h \
- credentials/sets/cert_cache.c credentials/sets/cert_cache.h \
- credentials/sets/mem_cred.c credentials/sets/mem_cred.h \
- credentials/sets/callback_cred.c \
- credentials/sets/callback_cred.h credentials/auth_cfg.c \
- credentials/auth_cfg.h credentials/credential_set.h \
- credentials/cert_validator.h database/database.h \
- database/database.c database/database_factory.h \
- database/database_factory.c fetcher/fetcher.h \
- fetcher/fetcher.c fetcher/fetcher_manager.h \
- fetcher/fetcher_manager.c eap/eap.h eap/eap.c pen/pen.h \
- pen/pen.c plugins/plugin_loader.c plugins/plugin_loader.h \
- plugins/plugin.h plugins/plugin_feature.c \
- plugins/plugin_feature.h processing/jobs/job.h \
- processing/jobs/job.c processing/jobs/callback_job.c \
- processing/jobs/callback_job.h processing/processor.c \
- processing/processor.h processing/scheduler.c \
- processing/scheduler.h selectors/traffic_selector.c \
- selectors/traffic_selector.h threading/thread.h \
- threading/thread.c threading/thread_value.h \
- threading/thread_value.c threading/mutex.h threading/mutex.c \
- threading/condvar.h threading/rwlock.h threading/rwlock.c \
- threading/lock_profiler.h utils.h utils.c utils/host.c \
- utils/host.h utils/identification.c utils/identification.h \
- utils/lexparser.c utils/lexparser.h utils/linked_list.c \
- utils/linked_list.h utils/hashtable.c utils/hashtable.h \
- utils/enumerator.c utils/enumerator.h utils/optionsfrom.c \
- utils/optionsfrom.h utils/backtrace.c utils/backtrace.h \
+ credentials/sets/cert_cache.c credentials/sets/mem_cred.c \
+ credentials/sets/callback_cred.c credentials/auth_cfg.c \
+ database/database.c database/database_factory.c \
+ fetcher/fetcher.c fetcher/fetcher_manager.c eap/eap.c \
+ ipsec/ipsec_types.c pen/pen.c plugins/plugin_loader.c \
+ plugins/plugin_feature.c processing/jobs/job.c \
+ processing/jobs/callback_job.c processing/processor.c \
+ processing/scheduler.c selectors/traffic_selector.c \
+ threading/thread.c threading/thread_value.c threading/mutex.c \
+ threading/semaphore.c threading/rwlock.c threading/spinlock.c \
+ utils.c utils/host.c utils/packet.c utils/identification.c \
+ utils/lexparser.c utils/linked_list.c utils/blocking_queue.c \
+ utils/hashtable.c utils/enumerator.c utils/optionsfrom.c \
+ utils/capabilities.c utils/backtrace.c utils/tun_device.c \
$(am__append_2) $(am__append_5)
+@USE_DEV_HEADERS_TRUE@strongswan_includedir = ${dev_headers}
+@USE_DEV_HEADERS_TRUE@nobase_strongswan_include_HEADERS = \
+@USE_DEV_HEADERS_TRUE@library.h chunk.h debug.h enum.h settings.h printf_hook.h \
+@USE_DEV_HEADERS_TRUE@asn1/asn1.h asn1/asn1_parser.h asn1/oid.h bio/bio_reader.h bio/bio_writer.h \
+@USE_DEV_HEADERS_TRUE@crypto/crypters/crypter.h crypto/hashers/hasher.h crypto/mac.h \
+@USE_DEV_HEADERS_TRUE@crypto/pkcs7.h crypto/pkcs9.h crypto/proposal/proposal_keywords.h \
+@USE_DEV_HEADERS_TRUE@crypto/proposal/proposal_keywords_static.h \
+@USE_DEV_HEADERS_TRUE@crypto/prfs/prf.h crypto/prfs/mac_prf.h crypto/rngs/rng.h crypto/nonce_gen.h \
+@USE_DEV_HEADERS_TRUE@crypto/prf_plus.h crypto/signers/signer.h crypto/signers/mac_signer.h \
+@USE_DEV_HEADERS_TRUE@crypto/crypto_factory.h crypto/crypto_tester.h crypto/diffie_hellman.h \
+@USE_DEV_HEADERS_TRUE@crypto/aead.h crypto/transform.h \
+@USE_DEV_HEADERS_TRUE@credentials/credential_factory.h credentials/builder.h \
+@USE_DEV_HEADERS_TRUE@credentials/cred_encoding.h credentials/keys/private_key.h \
+@USE_DEV_HEADERS_TRUE@credentials/keys/public_key.h credentials/keys/shared_key.h \
+@USE_DEV_HEADERS_TRUE@credentials/certificates/certificate.h credentials/certificates/x509.h \
+@USE_DEV_HEADERS_TRUE@credentials/certificates/ac.h credentials/certificates/crl.h \
+@USE_DEV_HEADERS_TRUE@credentials/certificates/pkcs10.h credentials/certificates/ocsp_request.h \
+@USE_DEV_HEADERS_TRUE@credentials/certificates/ocsp_response.h \
+@USE_DEV_HEADERS_TRUE@credentials/certificates/pgp_certificate.h \
+@USE_DEV_HEADERS_TRUE@credentials/ietf_attributes/ietf_attributes.h \
+@USE_DEV_HEADERS_TRUE@credentials/credential_manager.h credentials/sets/auth_cfg_wrapper.h \
+@USE_DEV_HEADERS_TRUE@credentials/sets/ocsp_response_wrapper.h credentials/sets/cert_cache.h \
+@USE_DEV_HEADERS_TRUE@credentials/sets/mem_cred.h credentials/sets/callback_cred.h \
+@USE_DEV_HEADERS_TRUE@credentials/auth_cfg.h credentials/credential_set.h credentials/cert_validator.h \
+@USE_DEV_HEADERS_TRUE@database/database.h database/database_factory.h fetcher/fetcher.h \
+@USE_DEV_HEADERS_TRUE@fetcher/fetcher_manager.h eap/eap.h pen/pen.h ipsec/ipsec_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 selectors/traffic_selector.h \
+@USE_DEV_HEADERS_TRUE@threading/thread.h threading/thread_value.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 \
+@USE_DEV_HEADERS_TRUE@utils.h utils/host.h utils/packet.h utils/identification.h utils/lexparser.h \
+@USE_DEV_HEADERS_TRUE@utils/linked_list.h utils/blocking_queue.h utils/hashtable.h utils/enumerator.h \
+@USE_DEV_HEADERS_TRUE@utils/optionsfrom.h utils/capabilities.h utils/backtrace.h utils/tun_device.h \
+@USE_DEV_HEADERS_TRUE@utils/leak_detective.h integrity_checker.h
+
libstrongswan_la_LIBADD = $(PTHREADLIB) $(DLLIB) $(BTLIB) $(SOCKLIB) \
- $(RTLIB) $(am__append_6) $(am__append_8) $(am__append_10) \
- $(am__append_12) $(am__append_14) $(am__append_16) \
- $(am__append_18) $(am__append_20) $(am__append_22) \
- $(am__append_24) $(am__append_26) $(am__append_28) \
- $(am__append_30) $(am__append_32) $(am__append_34) \
- $(am__append_36) $(am__append_38) $(am__append_40) \
- $(am__append_42) $(am__append_44) $(am__append_46) \
- $(am__append_48) $(am__append_50) $(am__append_52) \
- $(am__append_54) $(am__append_56) $(am__append_58) \
- $(am__append_60) $(am__append_62) $(am__append_64) \
- $(am__append_66) $(am__append_68) $(am__append_70) \
- $(am__append_72) $(am__append_74) $(am__append_76) \
- $(am__append_78) $(am__append_80)
+ $(RTLIB) $(BFDLIB) $(am__append_6) $(am__append_7) \
+ $(am__append_9) $(am__append_11) $(am__append_13) \
+ $(am__append_15) $(am__append_17) $(am__append_19) \
+ $(am__append_21) $(am__append_23) $(am__append_25) \
+ $(am__append_27) $(am__append_29) $(am__append_31) \
+ $(am__append_33) $(am__append_35) $(am__append_37) \
+ $(am__append_39) $(am__append_41) $(am__append_43) \
+ $(am__append_45) $(am__append_47) $(am__append_49) \
+ $(am__append_51) $(am__append_53) $(am__append_55) \
+ $(am__append_57) $(am__append_59) $(am__append_61) \
+ $(am__append_63) $(am__append_65) $(am__append_67) \
+ $(am__append_69) $(am__append_71) $(am__append_73) \
+ $(am__append_75) $(am__append_77) $(am__append_79) \
+ $(am__append_81) $(am__append_83)
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -DIPSEC_DIR=\"${ipsecdir}\" \
-DIPSEC_LIB_DIR=\"${ipseclibdir}\" \
@@ -601,58 +629,58 @@ AM_CFLAGS = -DIPSEC_DIR=\"${ipsecdir}\" \
$(am__append_3) $(am__append_4)
EXTRA_DIST = \
asn1/oid.txt asn1/oid.pl \
-crypto/proposal/proposal_keywords.txt \
+crypto/proposal/proposal_keywords_static.txt \
Android.mk AndroidConfigLocal.h
BUILT_SOURCES = \
$(srcdir)/asn1/oid.c $(srcdir)/asn1/oid.h \
-$(srcdir)/crypto/proposal/proposal_keywords.c
+$(srcdir)/crypto/proposal/proposal_keywords_static.c
MAINTAINERCLEANFILES = \
$(srcdir)/asn1/oid.c $(srcdir)/asn1/oid.h \
-$(srcdir)/crypto/proposal/proposal_keywords.c
-
-@MONOLITHIC_FALSE@SUBDIRS = . $(am__append_7) $(am__append_9) \
-@MONOLITHIC_FALSE@ $(am__append_11) $(am__append_13) \
-@MONOLITHIC_FALSE@ $(am__append_15) $(am__append_17) \
-@MONOLITHIC_FALSE@ $(am__append_19) $(am__append_21) \
-@MONOLITHIC_FALSE@ $(am__append_23) $(am__append_25) \
-@MONOLITHIC_FALSE@ $(am__append_27) $(am__append_29) \
-@MONOLITHIC_FALSE@ $(am__append_31) $(am__append_33) \
-@MONOLITHIC_FALSE@ $(am__append_35) $(am__append_37) \
-@MONOLITHIC_FALSE@ $(am__append_39) $(am__append_41) \
-@MONOLITHIC_FALSE@ $(am__append_43) $(am__append_45) \
-@MONOLITHIC_FALSE@ $(am__append_47) $(am__append_49) \
-@MONOLITHIC_FALSE@ $(am__append_51) $(am__append_53) \
-@MONOLITHIC_FALSE@ $(am__append_55) $(am__append_57) \
-@MONOLITHIC_FALSE@ $(am__append_59) $(am__append_61) \
-@MONOLITHIC_FALSE@ $(am__append_63) $(am__append_65) \
-@MONOLITHIC_FALSE@ $(am__append_67) $(am__append_69) \
-@MONOLITHIC_FALSE@ $(am__append_71) $(am__append_73) \
-@MONOLITHIC_FALSE@ $(am__append_75) $(am__append_77) \
-@MONOLITHIC_FALSE@ $(am__append_79)
+$(srcdir)/crypto/proposal/proposal_keywords_static.c
+
+@MONOLITHIC_FALSE@SUBDIRS = . $(am__append_8) $(am__append_10) \
+@MONOLITHIC_FALSE@ $(am__append_12) $(am__append_14) \
+@MONOLITHIC_FALSE@ $(am__append_16) $(am__append_18) \
+@MONOLITHIC_FALSE@ $(am__append_20) $(am__append_22) \
+@MONOLITHIC_FALSE@ $(am__append_24) $(am__append_26) \
+@MONOLITHIC_FALSE@ $(am__append_28) $(am__append_30) \
+@MONOLITHIC_FALSE@ $(am__append_32) $(am__append_34) \
+@MONOLITHIC_FALSE@ $(am__append_36) $(am__append_38) \
+@MONOLITHIC_FALSE@ $(am__append_40) $(am__append_42) \
+@MONOLITHIC_FALSE@ $(am__append_44) $(am__append_46) \
+@MONOLITHIC_FALSE@ $(am__append_48) $(am__append_50) \
+@MONOLITHIC_FALSE@ $(am__append_52) $(am__append_54) \
+@MONOLITHIC_FALSE@ $(am__append_56) $(am__append_58) \
+@MONOLITHIC_FALSE@ $(am__append_60) $(am__append_62) \
+@MONOLITHIC_FALSE@ $(am__append_64) $(am__append_66) \
+@MONOLITHIC_FALSE@ $(am__append_68) $(am__append_70) \
+@MONOLITHIC_FALSE@ $(am__append_72) $(am__append_74) \
+@MONOLITHIC_FALSE@ $(am__append_76) $(am__append_78) \
+@MONOLITHIC_FALSE@ $(am__append_80) $(am__append_82)
# build plugins with their own Makefile
#######################################
-@MONOLITHIC_TRUE@SUBDIRS = $(am__append_7) $(am__append_9) \
-@MONOLITHIC_TRUE@ $(am__append_11) $(am__append_13) \
-@MONOLITHIC_TRUE@ $(am__append_15) $(am__append_17) \
-@MONOLITHIC_TRUE@ $(am__append_19) $(am__append_21) \
-@MONOLITHIC_TRUE@ $(am__append_23) $(am__append_25) \
-@MONOLITHIC_TRUE@ $(am__append_27) $(am__append_29) \
-@MONOLITHIC_TRUE@ $(am__append_31) $(am__append_33) \
-@MONOLITHIC_TRUE@ $(am__append_35) $(am__append_37) \
-@MONOLITHIC_TRUE@ $(am__append_39) $(am__append_41) \
-@MONOLITHIC_TRUE@ $(am__append_43) $(am__append_45) \
-@MONOLITHIC_TRUE@ $(am__append_47) $(am__append_49) \
-@MONOLITHIC_TRUE@ $(am__append_51) $(am__append_53) \
-@MONOLITHIC_TRUE@ $(am__append_55) $(am__append_57) \
-@MONOLITHIC_TRUE@ $(am__append_59) $(am__append_61) \
-@MONOLITHIC_TRUE@ $(am__append_63) $(am__append_65) \
-@MONOLITHIC_TRUE@ $(am__append_67) $(am__append_69) \
-@MONOLITHIC_TRUE@ $(am__append_71) $(am__append_73) \
-@MONOLITHIC_TRUE@ $(am__append_75) $(am__append_77) \
-@MONOLITHIC_TRUE@ $(am__append_79)
+@MONOLITHIC_TRUE@SUBDIRS = $(am__append_8) $(am__append_10) \
+@MONOLITHIC_TRUE@ $(am__append_12) $(am__append_14) \
+@MONOLITHIC_TRUE@ $(am__append_16) $(am__append_18) \
+@MONOLITHIC_TRUE@ $(am__append_20) $(am__append_22) \
+@MONOLITHIC_TRUE@ $(am__append_24) $(am__append_26) \
+@MONOLITHIC_TRUE@ $(am__append_28) $(am__append_30) \
+@MONOLITHIC_TRUE@ $(am__append_32) $(am__append_34) \
+@MONOLITHIC_TRUE@ $(am__append_36) $(am__append_38) \
+@MONOLITHIC_TRUE@ $(am__append_40) $(am__append_42) \
+@MONOLITHIC_TRUE@ $(am__append_44) $(am__append_46) \
+@MONOLITHIC_TRUE@ $(am__append_48) $(am__append_50) \
+@MONOLITHIC_TRUE@ $(am__append_52) $(am__append_54) \
+@MONOLITHIC_TRUE@ $(am__append_56) $(am__append_58) \
+@MONOLITHIC_TRUE@ $(am__append_60) $(am__append_62) \
+@MONOLITHIC_TRUE@ $(am__append_64) $(am__append_66) \
+@MONOLITHIC_TRUE@ $(am__append_68) $(am__append_70) \
+@MONOLITHIC_TRUE@ $(am__append_72) $(am__append_74) \
+@MONOLITHIC_TRUE@ $(am__append_76) $(am__append_78) \
+@MONOLITHIC_TRUE@ $(am__append_80) $(am__append_82)
all: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) all-recursive
@@ -736,9 +764,11 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backtrace.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bio_reader.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bio_writer.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/blocking_queue.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/builder.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/callback_cred.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/callback_job.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/capabilities.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cert_cache.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/certificate.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chunk.Plo@am__quote@
@@ -764,18 +794,23 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/identification.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ietf_attributes.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/integrity_checker.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipsec_types.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/job.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/leak_detective.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lexparser.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/library.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/linked_list.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mac_prf.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mac_signer.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mem_cred.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mutex.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ocsp_response.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ocsp_response_wrapper.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oid.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/optionsfrom.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/packet.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pen.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pkcs7.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pkcs9.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_feature.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_loader.Plo@am__quote@
@@ -785,17 +820,21 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/private_key.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/processor.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proposal_keywords.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proposal_keywords_static.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/public_key.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rng.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rwlock.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scheduler.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/semaphore.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/settings.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shared_key.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/signer.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spinlock.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread_value.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/traffic_selector.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transform.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tun_device.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Plo@am__quote@
.c.o:
@@ -868,6 +907,13 @@ hasher.lo: crypto/hashers/hasher.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o hasher.lo `test -f 'crypto/hashers/hasher.c' || echo '$(srcdir)/'`crypto/hashers/hasher.c
+pkcs7.lo: crypto/pkcs7.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pkcs7.lo -MD -MP -MF $(DEPDIR)/pkcs7.Tpo -c -o pkcs7.lo `test -f 'crypto/pkcs7.c' || echo '$(srcdir)/'`crypto/pkcs7.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pkcs7.Tpo $(DEPDIR)/pkcs7.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='crypto/pkcs7.c' object='pkcs7.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pkcs7.lo `test -f 'crypto/pkcs7.c' || echo '$(srcdir)/'`crypto/pkcs7.c
+
pkcs9.lo: crypto/pkcs9.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pkcs9.lo -MD -MP -MF $(DEPDIR)/pkcs9.Tpo -c -o pkcs9.lo `test -f 'crypto/pkcs9.c' || echo '$(srcdir)/'`crypto/pkcs9.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pkcs9.Tpo $(DEPDIR)/pkcs9.Plo
@@ -882,6 +928,13 @@ proposal_keywords.lo: crypto/proposal/proposal_keywords.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o proposal_keywords.lo `test -f 'crypto/proposal/proposal_keywords.c' || echo '$(srcdir)/'`crypto/proposal/proposal_keywords.c
+proposal_keywords_static.lo: crypto/proposal/proposal_keywords_static.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT proposal_keywords_static.lo -MD -MP -MF $(DEPDIR)/proposal_keywords_static.Tpo -c -o proposal_keywords_static.lo `test -f 'crypto/proposal/proposal_keywords_static.c' || echo '$(srcdir)/'`crypto/proposal/proposal_keywords_static.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/proposal_keywords_static.Tpo $(DEPDIR)/proposal_keywords_static.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='crypto/proposal/proposal_keywords_static.c' object='proposal_keywords_static.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o proposal_keywords_static.lo `test -f 'crypto/proposal/proposal_keywords_static.c' || echo '$(srcdir)/'`crypto/proposal/proposal_keywords_static.c
+
prf.lo: crypto/prfs/prf.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT prf.lo -MD -MP -MF $(DEPDIR)/prf.Tpo -c -o prf.lo `test -f 'crypto/prfs/prf.c' || echo '$(srcdir)/'`crypto/prfs/prf.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/prf.Tpo $(DEPDIR)/prf.Plo
@@ -889,6 +942,13 @@ prf.lo: crypto/prfs/prf.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o prf.lo `test -f 'crypto/prfs/prf.c' || echo '$(srcdir)/'`crypto/prfs/prf.c
+mac_prf.lo: crypto/prfs/mac_prf.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mac_prf.lo -MD -MP -MF $(DEPDIR)/mac_prf.Tpo -c -o mac_prf.lo `test -f 'crypto/prfs/mac_prf.c' || echo '$(srcdir)/'`crypto/prfs/mac_prf.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/mac_prf.Tpo $(DEPDIR)/mac_prf.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='crypto/prfs/mac_prf.c' object='mac_prf.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mac_prf.lo `test -f 'crypto/prfs/mac_prf.c' || echo '$(srcdir)/'`crypto/prfs/mac_prf.c
+
rng.lo: crypto/rngs/rng.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rng.lo -MD -MP -MF $(DEPDIR)/rng.Tpo -c -o rng.lo `test -f 'crypto/rngs/rng.c' || echo '$(srcdir)/'`crypto/rngs/rng.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/rng.Tpo $(DEPDIR)/rng.Plo
@@ -910,6 +970,13 @@ signer.lo: crypto/signers/signer.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o signer.lo `test -f 'crypto/signers/signer.c' || echo '$(srcdir)/'`crypto/signers/signer.c
+mac_signer.lo: crypto/signers/mac_signer.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mac_signer.lo -MD -MP -MF $(DEPDIR)/mac_signer.Tpo -c -o mac_signer.lo `test -f 'crypto/signers/mac_signer.c' || echo '$(srcdir)/'`crypto/signers/mac_signer.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/mac_signer.Tpo $(DEPDIR)/mac_signer.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='crypto/signers/mac_signer.c' object='mac_signer.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mac_signer.lo `test -f 'crypto/signers/mac_signer.c' || echo '$(srcdir)/'`crypto/signers/mac_signer.c
+
crypto_factory.lo: crypto/crypto_factory.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT crypto_factory.lo -MD -MP -MF $(DEPDIR)/crypto_factory.Tpo -c -o crypto_factory.lo `test -f 'crypto/crypto_factory.c' || echo '$(srcdir)/'`crypto/crypto_factory.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/crypto_factory.Tpo $(DEPDIR)/crypto_factory.Plo
@@ -1099,6 +1166,13 @@ eap.lo: eap/eap.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o eap.lo `test -f 'eap/eap.c' || echo '$(srcdir)/'`eap/eap.c
+ipsec_types.lo: ipsec/ipsec_types.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ipsec_types.lo -MD -MP -MF $(DEPDIR)/ipsec_types.Tpo -c -o ipsec_types.lo `test -f 'ipsec/ipsec_types.c' || echo '$(srcdir)/'`ipsec/ipsec_types.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ipsec_types.Tpo $(DEPDIR)/ipsec_types.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ipsec/ipsec_types.c' object='ipsec_types.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ipsec_types.lo `test -f 'ipsec/ipsec_types.c' || echo '$(srcdir)/'`ipsec/ipsec_types.c
+
pen.lo: pen/pen.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pen.lo -MD -MP -MF $(DEPDIR)/pen.Tpo -c -o pen.lo `test -f 'pen/pen.c' || echo '$(srcdir)/'`pen/pen.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pen.Tpo $(DEPDIR)/pen.Plo
@@ -1176,6 +1250,13 @@ mutex.lo: threading/mutex.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mutex.lo `test -f 'threading/mutex.c' || echo '$(srcdir)/'`threading/mutex.c
+semaphore.lo: threading/semaphore.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT semaphore.lo -MD -MP -MF $(DEPDIR)/semaphore.Tpo -c -o semaphore.lo `test -f 'threading/semaphore.c' || echo '$(srcdir)/'`threading/semaphore.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/semaphore.Tpo $(DEPDIR)/semaphore.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='threading/semaphore.c' object='semaphore.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o semaphore.lo `test -f 'threading/semaphore.c' || echo '$(srcdir)/'`threading/semaphore.c
+
rwlock.lo: threading/rwlock.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rwlock.lo -MD -MP -MF $(DEPDIR)/rwlock.Tpo -c -o rwlock.lo `test -f 'threading/rwlock.c' || echo '$(srcdir)/'`threading/rwlock.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/rwlock.Tpo $(DEPDIR)/rwlock.Plo
@@ -1183,6 +1264,13 @@ rwlock.lo: threading/rwlock.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rwlock.lo `test -f 'threading/rwlock.c' || echo '$(srcdir)/'`threading/rwlock.c
+spinlock.lo: threading/spinlock.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT spinlock.lo -MD -MP -MF $(DEPDIR)/spinlock.Tpo -c -o spinlock.lo `test -f 'threading/spinlock.c' || echo '$(srcdir)/'`threading/spinlock.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/spinlock.Tpo $(DEPDIR)/spinlock.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='threading/spinlock.c' object='spinlock.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o spinlock.lo `test -f 'threading/spinlock.c' || echo '$(srcdir)/'`threading/spinlock.c
+
host.lo: utils/host.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT host.lo -MD -MP -MF $(DEPDIR)/host.Tpo -c -o host.lo `test -f 'utils/host.c' || echo '$(srcdir)/'`utils/host.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/host.Tpo $(DEPDIR)/host.Plo
@@ -1190,6 +1278,13 @@ host.lo: utils/host.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o host.lo `test -f 'utils/host.c' || echo '$(srcdir)/'`utils/host.c
+packet.lo: utils/packet.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT packet.lo -MD -MP -MF $(DEPDIR)/packet.Tpo -c -o packet.lo `test -f 'utils/packet.c' || echo '$(srcdir)/'`utils/packet.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/packet.Tpo $(DEPDIR)/packet.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='utils/packet.c' object='packet.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o packet.lo `test -f 'utils/packet.c' || echo '$(srcdir)/'`utils/packet.c
+
identification.lo: utils/identification.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT identification.lo -MD -MP -MF $(DEPDIR)/identification.Tpo -c -o identification.lo `test -f 'utils/identification.c' || echo '$(srcdir)/'`utils/identification.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/identification.Tpo $(DEPDIR)/identification.Plo
@@ -1211,6 +1306,13 @@ linked_list.lo: utils/linked_list.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o linked_list.lo `test -f 'utils/linked_list.c' || echo '$(srcdir)/'`utils/linked_list.c
+blocking_queue.lo: utils/blocking_queue.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT blocking_queue.lo -MD -MP -MF $(DEPDIR)/blocking_queue.Tpo -c -o blocking_queue.lo `test -f 'utils/blocking_queue.c' || echo '$(srcdir)/'`utils/blocking_queue.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/blocking_queue.Tpo $(DEPDIR)/blocking_queue.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='utils/blocking_queue.c' object='blocking_queue.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o blocking_queue.lo `test -f 'utils/blocking_queue.c' || echo '$(srcdir)/'`utils/blocking_queue.c
+
hashtable.lo: utils/hashtable.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT hashtable.lo -MD -MP -MF $(DEPDIR)/hashtable.Tpo -c -o hashtable.lo `test -f 'utils/hashtable.c' || echo '$(srcdir)/'`utils/hashtable.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/hashtable.Tpo $(DEPDIR)/hashtable.Plo
@@ -1232,6 +1334,13 @@ optionsfrom.lo: utils/optionsfrom.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o optionsfrom.lo `test -f 'utils/optionsfrom.c' || echo '$(srcdir)/'`utils/optionsfrom.c
+capabilities.lo: utils/capabilities.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT capabilities.lo -MD -MP -MF $(DEPDIR)/capabilities.Tpo -c -o capabilities.lo `test -f 'utils/capabilities.c' || echo '$(srcdir)/'`utils/capabilities.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/capabilities.Tpo $(DEPDIR)/capabilities.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='utils/capabilities.c' object='capabilities.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o capabilities.lo `test -f 'utils/capabilities.c' || echo '$(srcdir)/'`utils/capabilities.c
+
backtrace.lo: utils/backtrace.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT backtrace.lo -MD -MP -MF $(DEPDIR)/backtrace.Tpo -c -o backtrace.lo `test -f 'utils/backtrace.c' || echo '$(srcdir)/'`utils/backtrace.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/backtrace.Tpo $(DEPDIR)/backtrace.Plo
@@ -1239,6 +1348,13 @@ backtrace.lo: utils/backtrace.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o backtrace.lo `test -f 'utils/backtrace.c' || echo '$(srcdir)/'`utils/backtrace.c
+tun_device.lo: utils/tun_device.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tun_device.lo -MD -MP -MF $(DEPDIR)/tun_device.Tpo -c -o tun_device.lo `test -f 'utils/tun_device.c' || echo '$(srcdir)/'`utils/tun_device.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tun_device.Tpo $(DEPDIR)/tun_device.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='utils/tun_device.c' object='tun_device.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tun_device.lo `test -f 'utils/tun_device.c' || echo '$(srcdir)/'`utils/tun_device.c
+
leak_detective.lo: utils/leak_detective.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT leak_detective.lo -MD -MP -MF $(DEPDIR)/leak_detective.Tpo -c -o leak_detective.lo `test -f 'utils/leak_detective.c' || echo '$(srcdir)/'`utils/leak_detective.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/leak_detective.Tpo $(DEPDIR)/leak_detective.Plo
@@ -1251,6 +1367,29 @@ mostlyclean-libtool:
clean-libtool:
-rm -rf .libs _libs
+install-nobase_strongswan_includeHEADERS: $(nobase_strongswan_include_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(strongswan_includedir)" || $(MKDIR_P) "$(DESTDIR)$(strongswan_includedir)"
+ @list='$(nobase_strongswan_include_HEADERS)'; test -n "$(strongswan_includedir)" || list=; \
+ $(am__nobase_list) | while read dir files; do \
+ xfiles=; for file in $$files; do \
+ if test -f "$$file"; then xfiles="$$xfiles $$file"; \
+ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \
+ test -z "$$xfiles" || { \
+ test "x$$dir" = x. || { \
+ echo "$(MKDIR_P) '$(DESTDIR)$(strongswan_includedir)/$$dir'"; \
+ $(MKDIR_P) "$(DESTDIR)$(strongswan_includedir)/$$dir"; }; \
+ echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(strongswan_includedir)/$$dir'"; \
+ $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(strongswan_includedir)/$$dir" || exit $$?; }; \
+ done
+
+uninstall-nobase_strongswan_includeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(nobase_strongswan_include_HEADERS)'; test -n "$(strongswan_includedir)" || list=; \
+ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(strongswan_includedir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(strongswan_includedir)" && rm -f $$files
# This directory's subdirectories are mostly independent; you can cd
# into them and run `make' without going through this Makefile.
@@ -1448,10 +1587,10 @@ distdir: $(DISTFILES)
check-am: all-am
check: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) check-recursive
-all-am: Makefile $(LTLIBRARIES)
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
installdirs: installdirs-recursive
installdirs-am:
- for dir in "$(DESTDIR)$(ipseclibdir)"; do \
+ for dir in "$(DESTDIR)$(ipseclibdir)" "$(DESTDIR)$(strongswan_includedir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: $(BUILT_SOURCES)
@@ -1505,7 +1644,8 @@ info: info-recursive
info-am:
-install-data-am: install-ipseclibLTLIBRARIES
+install-data-am: install-ipseclibLTLIBRARIES \
+ install-nobase_strongswan_includeHEADERS
install-dvi: install-dvi-recursive
@@ -1551,7 +1691,8 @@ ps: ps-recursive
ps-am:
-uninstall-am: uninstall-ipseclibLTLIBRARIES
+uninstall-am: uninstall-ipseclibLTLIBRARIES \
+ uninstall-nobase_strongswan_includeHEADERS
.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all check \
ctags-recursive install install-am install-strip \
@@ -1566,12 +1707,14 @@ uninstall-am: uninstall-ipseclibLTLIBRARIES
install-data-am install-dvi install-dvi-am install-exec \
install-exec-am install-html install-html-am install-info \
install-info-am install-ipseclibLTLIBRARIES install-man \
- install-pdf install-pdf-am install-ps install-ps-am \
- install-strip installcheck installcheck-am installdirs \
- installdirs-am maintainer-clean maintainer-clean-generic \
- mostlyclean mostlyclean-compile mostlyclean-generic \
- mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \
- uninstall uninstall-am uninstall-ipseclibLTLIBRARIES
+ install-nobase_strongswan_includeHEADERS install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs installdirs-am \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \
+ uninstall-ipseclibLTLIBRARIES \
+ uninstall-nobase_strongswan_includeHEADERS
library.lo : $(top_builddir)/config.status
@@ -1582,10 +1725,10 @@ $(srcdir)/asn1/oid.c : $(srcdir)/asn1/oid.pl $(srcdir)/asn1/oid.txt
$(srcdir)/asn1/oid.h : $(srcdir)/asn1/oid.pl $(srcdir)/asn1/oid.txt
(cd $(srcdir)/asn1/ && $(PERL) oid.pl)
-$(srcdir)/crypto/proposal/proposal_keywords.c: $(srcdir)/crypto/proposal/proposal_keywords.txt \
- $(srcdir)/crypto/proposal/proposal_keywords.h
- $(GPERF) -N proposal_get_token -m 10 -C -G -c -t -D < \
- $(srcdir)/crypto/proposal/proposal_keywords.txt > $@
+$(srcdir)/crypto/proposal/proposal_keywords_static.c: $(srcdir)/crypto/proposal/proposal_keywords_static.txt \
+ $(srcdir)/crypto/proposal/proposal_keywords_static.h
+ $(GPERF) -N proposal_get_token_static -m 10 -C -G -c -t -D < \
+ $(srcdir)/crypto/proposal/proposal_keywords_static.txt > $@
# 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.
diff --git a/src/libstrongswan/asn1/asn1.c b/src/libstrongswan/asn1/asn1.c
index 4cb38d126..c9f6fce25 100644
--- a/src/libstrongswan/asn1/asn1.c
+++ b/src/libstrongswan/asn1/asn1.c
@@ -28,7 +28,7 @@
/**
* Commonly used ASN1 values.
*/
-const chunk_t ASN1_INTEGER_0 = chunk_from_chars(0x02, 0x00);
+const chunk_t ASN1_INTEGER_0 = chunk_from_chars(0x02, 0x01, 0x00);
const chunk_t ASN1_INTEGER_1 = chunk_from_chars(0x02, 0x01, 0x01);
const chunk_t ASN1_INTEGER_2 = chunk_from_chars(0x02, 0x01, 0x02);
@@ -228,7 +228,8 @@ size_t asn1_length(chunk_t *blob)
/* read length field, skip tag and length */
n = blob->ptr[1];
- *blob = chunk_skip(*blob, 2);
+ blob->ptr += 2;
+ blob->len -= 2;
if ((n & 0x80) == 0)
{ /* single length octet */
@@ -760,16 +761,13 @@ chunk_t asn1_integer(const char *mode, chunk_t content)
size_t len;
u_char *pos;
- if (content.len == 0 || (content.len == 1 && *content.ptr == 0x00))
- {
- /* a zero ASN.1 integer does not have a value field */
- len = 0;
- }
- else
- {
- /* ASN.1 integers must be positive numbers in two's complement */
- len = content.len + ((*content.ptr & 0x80) ? 1 : 0);
+ if (content.len == 0)
+ { /* make sure 0 is encoded properly */
+ content = chunk_from_chars(0x00);
}
+
+ /* ASN.1 integers must be positive numbers in two's complement */
+ len = content.len + ((*content.ptr & 0x80) ? 1 : 0);
pos = asn1_build_object(&object, ASN1_INTEGER, len);
if (len > content.len)
{
diff --git a/src/libstrongswan/asn1/oid.c b/src/libstrongswan/asn1/oid.c
index bfc985c25..b21299620 100644
--- a/src/libstrongswan/asn1/oid.c
+++ b/src/libstrongswan/asn1/oid.c
@@ -179,8 +179,8 @@ const oid_t oid_names[] = {
{ 0x02, 167, 0, 7, "ecdsa-with-SHA256" }, /* 166 */
{ 0x03, 168, 0, 7, "ecdsa-with-SHA384" }, /* 167 */
{ 0x04, 0, 0, 7, "ecdsa-with-SHA512" }, /* 168 */
- {0x2B, 320, 1, 0, "" }, /* 169 */
- { 0x06, 234, 1, 1, "dod" }, /* 170 */
+ {0x2B, 323, 1, 0, "" }, /* 169 */
+ { 0x06, 237, 1, 1, "dod" }, /* 170 */
{ 0x01, 0, 1, 2, "internet" }, /* 171 */
{ 0x04, 194, 1, 3, "private" }, /* 172 */
{ 0x01, 0, 1, 4, "enterprise" }, /* 173 */
@@ -206,7 +206,7 @@ const oid_t oid_names[] = {
{ 0x4B, 0, 0, 11, "TCGID" }, /* 193 */
{ 0x05, 0, 1, 3, "security" }, /* 194 */
{ 0x05, 0, 1, 4, "mechanisms" }, /* 195 */
- { 0x07, 0, 1, 5, "id-pkix" }, /* 196 */
+ { 0x07, 234, 1, 5, "id-pkix" }, /* 196 */
{ 0x01, 201, 1, 6, "id-pe" }, /* 197 */
{ 0x01, 199, 0, 7, "authorityInfoAccess" }, /* 198 */
{ 0x03, 200, 0, 7, "qcStatements" }, /* 199 */
@@ -244,144 +244,147 @@ const oid_t oid_names[] = {
{ 0x02, 232, 0, 7, "caIssuers" }, /* 231 */
{ 0x03, 233, 0, 7, "timeStamping" }, /* 232 */
{ 0x05, 0, 0, 7, "caRepository" }, /* 233 */
- { 0x0E, 240, 1, 1, "oiw" }, /* 234 */
- { 0x03, 0, 1, 2, "secsig" }, /* 235 */
- { 0x02, 0, 1, 3, "algorithms" }, /* 236 */
- { 0x07, 238, 0, 4, "des-cbc" }, /* 237 */
- { 0x1A, 239, 0, 4, "sha-1" }, /* 238 */
- { 0x1D, 0, 0, 4, "sha-1WithRSASignature" }, /* 239 */
- { 0x24, 286, 1, 1, "TeleTrusT" }, /* 240 */
- { 0x03, 0, 1, 2, "algorithm" }, /* 241 */
- { 0x03, 0, 1, 3, "signatureAlgorithm" }, /* 242 */
- { 0x01, 247, 1, 4, "rsaSignature" }, /* 243 */
- { 0x02, 245, 0, 5, "rsaSigWithripemd160" }, /* 244 */
- { 0x03, 246, 0, 5, "rsaSigWithripemd128" }, /* 245 */
- { 0x04, 0, 0, 5, "rsaSigWithripemd256" }, /* 246 */
- { 0x02, 0, 1, 4, "ecSign" }, /* 247 */
- { 0x01, 249, 0, 5, "ecSignWithsha1" }, /* 248 */
- { 0x02, 250, 0, 5, "ecSignWithripemd160" }, /* 249 */
- { 0x03, 251, 0, 5, "ecSignWithmd2" }, /* 250 */
- { 0x04, 252, 0, 5, "ecSignWithmd5" }, /* 251 */
- { 0x05, 269, 1, 5, "ttt-ecg" }, /* 252 */
- { 0x01, 257, 1, 6, "fieldType" }, /* 253 */
- { 0x01, 0, 1, 7, "characteristictwoField" }, /* 254 */
- { 0x01, 0, 1, 8, "basisType" }, /* 255 */
- { 0x01, 0, 0, 9, "ipBasis" }, /* 256 */
- { 0x02, 259, 1, 6, "keyType" }, /* 257 */
- { 0x01, 0, 0, 7, "ecgPublicKey" }, /* 258 */
- { 0x03, 260, 0, 6, "curve" }, /* 259 */
- { 0x04, 267, 1, 6, "signatures" }, /* 260 */
- { 0x01, 262, 0, 7, "ecgdsa-with-RIPEMD160" }, /* 261 */
- { 0x02, 263, 0, 7, "ecgdsa-with-SHA1" }, /* 262 */
- { 0x03, 264, 0, 7, "ecgdsa-with-SHA224" }, /* 263 */
- { 0x04, 265, 0, 7, "ecgdsa-with-SHA256" }, /* 264 */
- { 0x05, 266, 0, 7, "ecgdsa-with-SHA384" }, /* 265 */
- { 0x06, 0, 0, 7, "ecgdsa-with-SHA512" }, /* 266 */
- { 0x05, 0, 1, 6, "module" }, /* 267 */
- { 0x01, 0, 0, 7, "1" }, /* 268 */
- { 0x08, 0, 1, 5, "ecStdCurvesAndGeneration" }, /* 269 */
- { 0x01, 0, 1, 6, "ellipticCurve" }, /* 270 */
- { 0x01, 0, 1, 7, "versionOne" }, /* 271 */
- { 0x01, 273, 0, 8, "brainpoolP160r1" }, /* 272 */
- { 0x02, 274, 0, 8, "brainpoolP160t1" }, /* 273 */
- { 0x03, 275, 0, 8, "brainpoolP192r1" }, /* 274 */
- { 0x04, 276, 0, 8, "brainpoolP192t1" }, /* 275 */
- { 0x05, 277, 0, 8, "brainpoolP224r1" }, /* 276 */
- { 0x06, 278, 0, 8, "brainpoolP224t1" }, /* 277 */
- { 0x07, 279, 0, 8, "brainpoolP256r1" }, /* 278 */
- { 0x08, 280, 0, 8, "brainpoolP256t1" }, /* 279 */
- { 0x09, 281, 0, 8, "brainpoolP320r1" }, /* 280 */
- { 0x0A, 282, 0, 8, "brainpoolP320t1" }, /* 281 */
- { 0x0B, 283, 0, 8, "brainpoolP384r1" }, /* 282 */
- { 0x0C, 284, 0, 8, "brainpoolP384t1" }, /* 283 */
- { 0x0D, 285, 0, 8, "brainpoolP512r1" }, /* 284 */
- { 0x0E, 0, 0, 8, "brainpoolP512t1" }, /* 285 */
- { 0x81, 0, 1, 1, "" }, /* 286 */
- { 0x04, 0, 1, 2, "Certicom" }, /* 287 */
- { 0x00, 0, 1, 3, "curve" }, /* 288 */
- { 0x01, 290, 0, 4, "sect163k1" }, /* 289 */
- { 0x02, 291, 0, 4, "sect163r1" }, /* 290 */
- { 0x03, 292, 0, 4, "sect239k1" }, /* 291 */
- { 0x04, 293, 0, 4, "sect113r1" }, /* 292 */
- { 0x05, 294, 0, 4, "sect113r2" }, /* 293 */
- { 0x06, 295, 0, 4, "secp112r1" }, /* 294 */
- { 0x07, 296, 0, 4, "secp112r2" }, /* 295 */
- { 0x08, 297, 0, 4, "secp160r1" }, /* 296 */
- { 0x09, 298, 0, 4, "secp160k1" }, /* 297 */
- { 0x0A, 299, 0, 4, "secp256k1" }, /* 298 */
- { 0x0F, 300, 0, 4, "sect163r2" }, /* 299 */
- { 0x10, 301, 0, 4, "sect283k1" }, /* 300 */
- { 0x11, 302, 0, 4, "sect283r1" }, /* 301 */
- { 0x16, 303, 0, 4, "sect131r1" }, /* 302 */
- { 0x17, 304, 0, 4, "sect131r2" }, /* 303 */
- { 0x18, 305, 0, 4, "sect193r1" }, /* 304 */
- { 0x19, 306, 0, 4, "sect193r2" }, /* 305 */
- { 0x1A, 307, 0, 4, "sect233k1" }, /* 306 */
- { 0x1B, 308, 0, 4, "sect233r1" }, /* 307 */
- { 0x1C, 309, 0, 4, "secp128r1" }, /* 308 */
- { 0x1D, 310, 0, 4, "secp128r2" }, /* 309 */
- { 0x1E, 311, 0, 4, "secp160r2" }, /* 310 */
- { 0x1F, 312, 0, 4, "secp192k1" }, /* 311 */
- { 0x20, 313, 0, 4, "secp224k1" }, /* 312 */
- { 0x21, 314, 0, 4, "secp224r1" }, /* 313 */
- { 0x22, 315, 0, 4, "secp384r1" }, /* 314 */
- { 0x23, 316, 0, 4, "secp521r1" }, /* 315 */
- { 0x24, 317, 0, 4, "sect409k1" }, /* 316 */
- { 0x25, 318, 0, 4, "sect409r1" }, /* 317 */
- { 0x26, 319, 0, 4, "sect571k1" }, /* 318 */
- { 0x27, 0, 0, 4, "sect571r1" }, /* 319 */
- {0x60, 366, 1, 0, "" }, /* 320 */
- { 0x86, 0, 1, 1, "" }, /* 321 */
- { 0x48, 0, 1, 2, "" }, /* 322 */
- { 0x01, 0, 1, 3, "organization" }, /* 323 */
- { 0x65, 342, 1, 4, "gov" }, /* 324 */
- { 0x03, 0, 1, 5, "csor" }, /* 325 */
- { 0x04, 0, 1, 6, "nistalgorithm" }, /* 326 */
- { 0x01, 337, 1, 7, "aes" }, /* 327 */
- { 0x02, 329, 0, 8, "id-aes128-CBC" }, /* 328 */
- { 0x06, 330, 0, 8, "id-aes128-GCM" }, /* 329 */
- { 0x07, 331, 0, 8, "id-aes128-CCM" }, /* 330 */
- { 0x16, 332, 0, 8, "id-aes192-CBC" }, /* 331 */
- { 0x1A, 333, 0, 8, "id-aes192-GCM" }, /* 332 */
- { 0x1B, 334, 0, 8, "id-aes192-CCM" }, /* 333 */
- { 0x2A, 335, 0, 8, "id-aes256-CBC" }, /* 334 */
- { 0x2E, 336, 0, 8, "id-aes256-GCM" }, /* 335 */
- { 0x2F, 0, 0, 8, "id-aes256-CCM" }, /* 336 */
- { 0x02, 0, 1, 7, "hashalgs" }, /* 337 */
- { 0x01, 339, 0, 8, "id-SHA-256" }, /* 338 */
- { 0x02, 340, 0, 8, "id-SHA-384" }, /* 339 */
- { 0x03, 341, 0, 8, "id-SHA-512" }, /* 340 */
- { 0x04, 0, 0, 8, "id-SHA-224" }, /* 341 */
- { 0x86, 0, 1, 4, "" }, /* 342 */
- { 0xf8, 0, 1, 5, "" }, /* 343 */
- { 0x42, 356, 1, 6, "netscape" }, /* 344 */
- { 0x01, 351, 1, 7, "" }, /* 345 */
- { 0x01, 347, 0, 8, "nsCertType" }, /* 346 */
- { 0x03, 348, 0, 8, "nsRevocationUrl" }, /* 347 */
- { 0x04, 349, 0, 8, "nsCaRevocationUrl" }, /* 348 */
- { 0x08, 350, 0, 8, "nsCaPolicyUrl" }, /* 349 */
- { 0x0d, 0, 0, 8, "nsComment" }, /* 350 */
- { 0x03, 354, 1, 7, "directory" }, /* 351 */
- { 0x01, 0, 1, 8, "" }, /* 352 */
- { 0x03, 0, 0, 9, "employeeNumber" }, /* 353 */
- { 0x04, 0, 1, 7, "policy" }, /* 354 */
- { 0x01, 0, 0, 8, "nsSGC" }, /* 355 */
- { 0x45, 0, 1, 6, "verisign" }, /* 356 */
- { 0x01, 0, 1, 7, "pki" }, /* 357 */
- { 0x09, 0, 1, 8, "attributes" }, /* 358 */
- { 0x02, 360, 0, 9, "messageType" }, /* 359 */
- { 0x03, 361, 0, 9, "pkiStatus" }, /* 360 */
- { 0x04, 362, 0, 9, "failInfo" }, /* 361 */
- { 0x05, 363, 0, 9, "senderNonce" }, /* 362 */
- { 0x06, 364, 0, 9, "recipientNonce" }, /* 363 */
- { 0x07, 365, 0, 9, "transID" }, /* 364 */
- { 0x08, 0, 0, 9, "extensionReq" }, /* 365 */
- {0x67, 0, 1, 0, "" }, /* 366 */
- { 0x81, 0, 1, 1, "" }, /* 367 */
- { 0x05, 0, 1, 2, "" }, /* 368 */
- { 0x02, 0, 1, 3, "tcg-attribute" }, /* 369 */
- { 0x01, 371, 0, 4, "tcg-at-tpmManufacturer" }, /* 370 */
- { 0x02, 372, 0, 4, "tcg-at-tpmModel" }, /* 371 */
- { 0x03, 373, 0, 4, "tcg-at-tpmVersion" }, /* 372 */
- { 0x0F, 0, 0, 4, "tcg-at-tpmIdLabel" } /* 373 */
+ { 0x08, 0, 1, 5, "ipsec" }, /* 234 */
+ { 0x02, 0, 1, 6, "certificate" }, /* 235 */
+ { 0x02, 0, 0, 7, "iKEIntermediate" }, /* 236 */
+ { 0x0E, 243, 1, 1, "oiw" }, /* 237 */
+ { 0x03, 0, 1, 2, "secsig" }, /* 238 */
+ { 0x02, 0, 1, 3, "algorithms" }, /* 239 */
+ { 0x07, 241, 0, 4, "des-cbc" }, /* 240 */
+ { 0x1A, 242, 0, 4, "sha-1" }, /* 241 */
+ { 0x1D, 0, 0, 4, "sha-1WithRSASignature" }, /* 242 */
+ { 0x24, 289, 1, 1, "TeleTrusT" }, /* 243 */
+ { 0x03, 0, 1, 2, "algorithm" }, /* 244 */
+ { 0x03, 0, 1, 3, "signatureAlgorithm" }, /* 245 */
+ { 0x01, 250, 1, 4, "rsaSignature" }, /* 246 */
+ { 0x02, 248, 0, 5, "rsaSigWithripemd160" }, /* 247 */
+ { 0x03, 249, 0, 5, "rsaSigWithripemd128" }, /* 248 */
+ { 0x04, 0, 0, 5, "rsaSigWithripemd256" }, /* 249 */
+ { 0x02, 0, 1, 4, "ecSign" }, /* 250 */
+ { 0x01, 252, 0, 5, "ecSignWithsha1" }, /* 251 */
+ { 0x02, 253, 0, 5, "ecSignWithripemd160" }, /* 252 */
+ { 0x03, 254, 0, 5, "ecSignWithmd2" }, /* 253 */
+ { 0x04, 255, 0, 5, "ecSignWithmd5" }, /* 254 */
+ { 0x05, 272, 1, 5, "ttt-ecg" }, /* 255 */
+ { 0x01, 260, 1, 6, "fieldType" }, /* 256 */
+ { 0x01, 0, 1, 7, "characteristictwoField" }, /* 257 */
+ { 0x01, 0, 1, 8, "basisType" }, /* 258 */
+ { 0x01, 0, 0, 9, "ipBasis" }, /* 259 */
+ { 0x02, 262, 1, 6, "keyType" }, /* 260 */
+ { 0x01, 0, 0, 7, "ecgPublicKey" }, /* 261 */
+ { 0x03, 263, 0, 6, "curve" }, /* 262 */
+ { 0x04, 270, 1, 6, "signatures" }, /* 263 */
+ { 0x01, 265, 0, 7, "ecgdsa-with-RIPEMD160" }, /* 264 */
+ { 0x02, 266, 0, 7, "ecgdsa-with-SHA1" }, /* 265 */
+ { 0x03, 267, 0, 7, "ecgdsa-with-SHA224" }, /* 266 */
+ { 0x04, 268, 0, 7, "ecgdsa-with-SHA256" }, /* 267 */
+ { 0x05, 269, 0, 7, "ecgdsa-with-SHA384" }, /* 268 */
+ { 0x06, 0, 0, 7, "ecgdsa-with-SHA512" }, /* 269 */
+ { 0x05, 0, 1, 6, "module" }, /* 270 */
+ { 0x01, 0, 0, 7, "1" }, /* 271 */
+ { 0x08, 0, 1, 5, "ecStdCurvesAndGeneration" }, /* 272 */
+ { 0x01, 0, 1, 6, "ellipticCurve" }, /* 273 */
+ { 0x01, 0, 1, 7, "versionOne" }, /* 274 */
+ { 0x01, 276, 0, 8, "brainpoolP160r1" }, /* 275 */
+ { 0x02, 277, 0, 8, "brainpoolP160t1" }, /* 276 */
+ { 0x03, 278, 0, 8, "brainpoolP192r1" }, /* 277 */
+ { 0x04, 279, 0, 8, "brainpoolP192t1" }, /* 278 */
+ { 0x05, 280, 0, 8, "brainpoolP224r1" }, /* 279 */
+ { 0x06, 281, 0, 8, "brainpoolP224t1" }, /* 280 */
+ { 0x07, 282, 0, 8, "brainpoolP256r1" }, /* 281 */
+ { 0x08, 283, 0, 8, "brainpoolP256t1" }, /* 282 */
+ { 0x09, 284, 0, 8, "brainpoolP320r1" }, /* 283 */
+ { 0x0A, 285, 0, 8, "brainpoolP320t1" }, /* 284 */
+ { 0x0B, 286, 0, 8, "brainpoolP384r1" }, /* 285 */
+ { 0x0C, 287, 0, 8, "brainpoolP384t1" }, /* 286 */
+ { 0x0D, 288, 0, 8, "brainpoolP512r1" }, /* 287 */
+ { 0x0E, 0, 0, 8, "brainpoolP512t1" }, /* 288 */
+ { 0x81, 0, 1, 1, "" }, /* 289 */
+ { 0x04, 0, 1, 2, "Certicom" }, /* 290 */
+ { 0x00, 0, 1, 3, "curve" }, /* 291 */
+ { 0x01, 293, 0, 4, "sect163k1" }, /* 292 */
+ { 0x02, 294, 0, 4, "sect163r1" }, /* 293 */
+ { 0x03, 295, 0, 4, "sect239k1" }, /* 294 */
+ { 0x04, 296, 0, 4, "sect113r1" }, /* 295 */
+ { 0x05, 297, 0, 4, "sect113r2" }, /* 296 */
+ { 0x06, 298, 0, 4, "secp112r1" }, /* 297 */
+ { 0x07, 299, 0, 4, "secp112r2" }, /* 298 */
+ { 0x08, 300, 0, 4, "secp160r1" }, /* 299 */
+ { 0x09, 301, 0, 4, "secp160k1" }, /* 300 */
+ { 0x0A, 302, 0, 4, "secp256k1" }, /* 301 */
+ { 0x0F, 303, 0, 4, "sect163r2" }, /* 302 */
+ { 0x10, 304, 0, 4, "sect283k1" }, /* 303 */
+ { 0x11, 305, 0, 4, "sect283r1" }, /* 304 */
+ { 0x16, 306, 0, 4, "sect131r1" }, /* 305 */
+ { 0x17, 307, 0, 4, "sect131r2" }, /* 306 */
+ { 0x18, 308, 0, 4, "sect193r1" }, /* 307 */
+ { 0x19, 309, 0, 4, "sect193r2" }, /* 308 */
+ { 0x1A, 310, 0, 4, "sect233k1" }, /* 309 */
+ { 0x1B, 311, 0, 4, "sect233r1" }, /* 310 */
+ { 0x1C, 312, 0, 4, "secp128r1" }, /* 311 */
+ { 0x1D, 313, 0, 4, "secp128r2" }, /* 312 */
+ { 0x1E, 314, 0, 4, "secp160r2" }, /* 313 */
+ { 0x1F, 315, 0, 4, "secp192k1" }, /* 314 */
+ { 0x20, 316, 0, 4, "secp224k1" }, /* 315 */
+ { 0x21, 317, 0, 4, "secp224r1" }, /* 316 */
+ { 0x22, 318, 0, 4, "secp384r1" }, /* 317 */
+ { 0x23, 319, 0, 4, "secp521r1" }, /* 318 */
+ { 0x24, 320, 0, 4, "sect409k1" }, /* 319 */
+ { 0x25, 321, 0, 4, "sect409r1" }, /* 320 */
+ { 0x26, 322, 0, 4, "sect571k1" }, /* 321 */
+ { 0x27, 0, 0, 4, "sect571r1" }, /* 322 */
+ {0x60, 369, 1, 0, "" }, /* 323 */
+ { 0x86, 0, 1, 1, "" }, /* 324 */
+ { 0x48, 0, 1, 2, "" }, /* 325 */
+ { 0x01, 0, 1, 3, "organization" }, /* 326 */
+ { 0x65, 345, 1, 4, "gov" }, /* 327 */
+ { 0x03, 0, 1, 5, "csor" }, /* 328 */
+ { 0x04, 0, 1, 6, "nistalgorithm" }, /* 329 */
+ { 0x01, 340, 1, 7, "aes" }, /* 330 */
+ { 0x02, 332, 0, 8, "id-aes128-CBC" }, /* 331 */
+ { 0x06, 333, 0, 8, "id-aes128-GCM" }, /* 332 */
+ { 0x07, 334, 0, 8, "id-aes128-CCM" }, /* 333 */
+ { 0x16, 335, 0, 8, "id-aes192-CBC" }, /* 334 */
+ { 0x1A, 336, 0, 8, "id-aes192-GCM" }, /* 335 */
+ { 0x1B, 337, 0, 8, "id-aes192-CCM" }, /* 336 */
+ { 0x2A, 338, 0, 8, "id-aes256-CBC" }, /* 337 */
+ { 0x2E, 339, 0, 8, "id-aes256-GCM" }, /* 338 */
+ { 0x2F, 0, 0, 8, "id-aes256-CCM" }, /* 339 */
+ { 0x02, 0, 1, 7, "hashalgs" }, /* 340 */
+ { 0x01, 342, 0, 8, "id-SHA-256" }, /* 341 */
+ { 0x02, 343, 0, 8, "id-SHA-384" }, /* 342 */
+ { 0x03, 344, 0, 8, "id-SHA-512" }, /* 343 */
+ { 0x04, 0, 0, 8, "id-SHA-224" }, /* 344 */
+ { 0x86, 0, 1, 4, "" }, /* 345 */
+ { 0xf8, 0, 1, 5, "" }, /* 346 */
+ { 0x42, 359, 1, 6, "netscape" }, /* 347 */
+ { 0x01, 354, 1, 7, "" }, /* 348 */
+ { 0x01, 350, 0, 8, "nsCertType" }, /* 349 */
+ { 0x03, 351, 0, 8, "nsRevocationUrl" }, /* 350 */
+ { 0x04, 352, 0, 8, "nsCaRevocationUrl" }, /* 351 */
+ { 0x08, 353, 0, 8, "nsCaPolicyUrl" }, /* 352 */
+ { 0x0d, 0, 0, 8, "nsComment" }, /* 353 */
+ { 0x03, 357, 1, 7, "directory" }, /* 354 */
+ { 0x01, 0, 1, 8, "" }, /* 355 */
+ { 0x03, 0, 0, 9, "employeeNumber" }, /* 356 */
+ { 0x04, 0, 1, 7, "policy" }, /* 357 */
+ { 0x01, 0, 0, 8, "nsSGC" }, /* 358 */
+ { 0x45, 0, 1, 6, "verisign" }, /* 359 */
+ { 0x01, 0, 1, 7, "pki" }, /* 360 */
+ { 0x09, 0, 1, 8, "attributes" }, /* 361 */
+ { 0x02, 363, 0, 9, "messageType" }, /* 362 */
+ { 0x03, 364, 0, 9, "pkiStatus" }, /* 363 */
+ { 0x04, 365, 0, 9, "failInfo" }, /* 364 */
+ { 0x05, 366, 0, 9, "senderNonce" }, /* 365 */
+ { 0x06, 367, 0, 9, "recipientNonce" }, /* 366 */
+ { 0x07, 368, 0, 9, "transID" }, /* 367 */
+ { 0x08, 0, 0, 9, "extensionReq" }, /* 368 */
+ {0x67, 0, 1, 0, "" }, /* 369 */
+ { 0x81, 0, 1, 1, "" }, /* 370 */
+ { 0x05, 0, 1, 2, "" }, /* 371 */
+ { 0x02, 0, 1, 3, "tcg-attribute" }, /* 372 */
+ { 0x01, 374, 0, 4, "tcg-at-tpmManufacturer" }, /* 373 */
+ { 0x02, 375, 0, 4, "tcg-at-tpmModel" }, /* 374 */
+ { 0x03, 376, 0, 4, "tcg-at-tpmVersion" }, /* 375 */
+ { 0x0F, 0, 0, 4, "tcg-at-tpmIdLabel" } /* 376 */
};
diff --git a/src/libstrongswan/asn1/oid.h b/src/libstrongswan/asn1/oid.h
index a01c434a9..5e30a3675 100644
--- a/src/libstrongswan/asn1/oid.h
+++ b/src/libstrongswan/asn1/oid.h
@@ -150,76 +150,77 @@ extern const oid_t oid_names[];
#define OID_ARCHIVE_CUTOFF 229
#define OID_SERVICE_LOCATOR 230
#define OID_CA_ISSUERS 231
-#define OID_DES_CBC 237
-#define OID_SHA1 238
-#define OID_SHA1_WITH_RSA_OIW 239
-#define OID_ECGDSA_PUBKEY 258
-#define OID_ECGDSA_SIG_WITH_RIPEMD160 261
-#define OID_ECGDSA_SIG_WITH_SHA1 262
-#define OID_ECGDSA_SIG_WITH_SHA224 263
-#define OID_ECGDSA_SIG_WITH_SHA256 264
-#define OID_ECGDSA_SIG_WITH_SHA384 265
-#define OID_ECGDSA_SIG_WITH_SHA512 266
-#define OID_SECT163K1 289
-#define OID_SECT163R1 290
-#define OID_SECT239K1 291
-#define OID_SECT113R1 292
-#define OID_SECT113R2 293
-#define OID_SECT112R1 294
-#define OID_SECT112R2 295
-#define OID_SECT160R1 296
-#define OID_SECT160K1 297
-#define OID_SECT256K1 298
-#define OID_SECT163R2 299
-#define OID_SECT283K1 300
-#define OID_SECT283R1 301
-#define OID_SECT131R1 302
-#define OID_SECT131R2 303
-#define OID_SECT193R1 304
-#define OID_SECT193R2 305
-#define OID_SECT233K1 306
-#define OID_SECT233R1 307
-#define OID_SECT128R1 308
-#define OID_SECT128R2 309
-#define OID_SECT160R2 310
-#define OID_SECT192K1 311
-#define OID_SECT224K1 312
-#define OID_SECT224R1 313
-#define OID_SECT384R1 314
-#define OID_SECT521R1 315
-#define OID_SECT409K1 316
-#define OID_SECT409R1 317
-#define OID_SECT571K1 318
-#define OID_SECT571R1 319
-#define OID_AES128_CBC 328
-#define OID_AES128_GCM 329
-#define OID_AES128_CCM 330
-#define OID_AES192_CBC 331
-#define OID_AES192_GCM 332
-#define OID_AES192_CCM 333
-#define OID_AES256_CBC 334
-#define OID_AES256_GCM 335
-#define OID_AES256_CCM 336
-#define OID_SHA256 338
-#define OID_SHA384 339
-#define OID_SHA512 340
-#define OID_SHA224 341
-#define OID_NS_REVOCATION_URL 347
-#define OID_NS_CA_REVOCATION_URL 348
-#define OID_NS_CA_POLICY_URL 349
-#define OID_NS_COMMENT 350
-#define OID_EMPLOYEE_NUMBER 353
-#define OID_PKI_MESSAGE_TYPE 359
-#define OID_PKI_STATUS 360
-#define OID_PKI_FAIL_INFO 361
-#define OID_PKI_SENDER_NONCE 362
-#define OID_PKI_RECIPIENT_NONCE 363
-#define OID_PKI_TRANS_ID 364
-#define OID_TPM_MANUFACTURER 370
-#define OID_TPM_MODEL 371
-#define OID_TPM_VERSION 372
-#define OID_TPM_ID_LABEL 373
+#define OID_IKE_INTERMEDIATE 236
+#define OID_DES_CBC 240
+#define OID_SHA1 241
+#define OID_SHA1_WITH_RSA_OIW 242
+#define OID_ECGDSA_PUBKEY 261
+#define OID_ECGDSA_SIG_WITH_RIPEMD160 264
+#define OID_ECGDSA_SIG_WITH_SHA1 265
+#define OID_ECGDSA_SIG_WITH_SHA224 266
+#define OID_ECGDSA_SIG_WITH_SHA256 267
+#define OID_ECGDSA_SIG_WITH_SHA384 268
+#define OID_ECGDSA_SIG_WITH_SHA512 269
+#define OID_SECT163K1 292
+#define OID_SECT163R1 293
+#define OID_SECT239K1 294
+#define OID_SECT113R1 295
+#define OID_SECT113R2 296
+#define OID_SECT112R1 297
+#define OID_SECT112R2 298
+#define OID_SECT160R1 299
+#define OID_SECT160K1 300
+#define OID_SECT256K1 301
+#define OID_SECT163R2 302
+#define OID_SECT283K1 303
+#define OID_SECT283R1 304
+#define OID_SECT131R1 305
+#define OID_SECT131R2 306
+#define OID_SECT193R1 307
+#define OID_SECT193R2 308
+#define OID_SECT233K1 309
+#define OID_SECT233R1 310
+#define OID_SECT128R1 311
+#define OID_SECT128R2 312
+#define OID_SECT160R2 313
+#define OID_SECT192K1 314
+#define OID_SECT224K1 315
+#define OID_SECT224R1 316
+#define OID_SECT384R1 317
+#define OID_SECT521R1 318
+#define OID_SECT409K1 319
+#define OID_SECT409R1 320
+#define OID_SECT571K1 321
+#define OID_SECT571R1 322
+#define OID_AES128_CBC 331
+#define OID_AES128_GCM 332
+#define OID_AES128_CCM 333
+#define OID_AES192_CBC 334
+#define OID_AES192_GCM 335
+#define OID_AES192_CCM 336
+#define OID_AES256_CBC 337
+#define OID_AES256_GCM 338
+#define OID_AES256_CCM 339
+#define OID_SHA256 341
+#define OID_SHA384 342
+#define OID_SHA512 343
+#define OID_SHA224 344
+#define OID_NS_REVOCATION_URL 350
+#define OID_NS_CA_REVOCATION_URL 351
+#define OID_NS_CA_POLICY_URL 352
+#define OID_NS_COMMENT 353
+#define OID_EMPLOYEE_NUMBER 356
+#define OID_PKI_MESSAGE_TYPE 362
+#define OID_PKI_STATUS 363
+#define OID_PKI_FAIL_INFO 364
+#define OID_PKI_SENDER_NONCE 365
+#define OID_PKI_RECIPIENT_NONCE 366
+#define OID_PKI_TRANS_ID 367
+#define OID_TPM_MANUFACTURER 373
+#define OID_TPM_MODEL 374
+#define OID_TPM_VERSION 375
+#define OID_TPM_ID_LABEL 376
-#define OID_MAX 374
+#define OID_MAX 377
#endif /* OID_H_ */
diff --git a/src/libstrongswan/asn1/oid.txt b/src/libstrongswan/asn1/oid.txt
index c3ff1a9e7..51a29eb33 100644
--- a/src/libstrongswan/asn1/oid.txt
+++ b/src/libstrongswan/asn1/oid.txt
@@ -232,6 +232,9 @@
0x02 "caIssuers" OID_CA_ISSUERS
0x03 "timeStamping"
0x05 "caRepository"
+ 0x08 "ipsec"
+ 0x02 "certificate"
+ 0x02 "iKEIntermediate" OID_IKE_INTERMEDIATE
0x0E "oiw"
0x03 "secsig"
0x02 "algorithms"
diff --git a/src/libstrongswan/bio/bio_reader.c b/src/libstrongswan/bio/bio_reader.c
index fce0d1aef..3a62bb541 100644
--- a/src/libstrongswan/bio/bio_reader.c
+++ b/src/libstrongswan/bio/bio_reader.c
@@ -1,4 +1,7 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
* Copyright (C) 2010 Martin Willi
* Copyright (C) 2010 revosec AG
*
@@ -47,8 +50,38 @@ METHOD(bio_reader_t, peek, chunk_t,
return this->buf;
}
-METHOD(bio_reader_t, read_uint8, bool,
- private_bio_reader_t *this, u_int8_t *res)
+/**
+ * A version of chunk_skip() that supports skipping from the end (i.e. simply
+ * reducing the size)
+ */
+static inline chunk_t chunk_skip_end(chunk_t chunk, size_t bytes, bool from_end)
+{
+ if (chunk.len > bytes)
+ {
+ if (!from_end)
+ {
+ chunk.ptr += bytes;
+ }
+ chunk.len -= bytes;
+ return chunk;
+ }
+ return chunk_empty;
+}
+
+/**
+ * Returns a pointer to the data to read, optionally from the end
+ */
+static inline u_char *get_ptr_end(private_bio_reader_t *this, u_int32_t len,
+ bool from_end)
+{
+ return from_end ? this->buf.ptr + (this->buf.len - len) : this->buf.ptr;
+}
+
+/**
+ * Read an u_int8_t from the buffer, optionally from the end of the buffer
+ */
+static bool read_uint8_internal(private_bio_reader_t *this, u_int8_t *res,
+ bool from_end)
{
if (this->buf.len < 1)
{
@@ -56,13 +89,16 @@ METHOD(bio_reader_t, read_uint8, bool,
this->buf.len);
return FALSE;
}
- *res = this->buf.ptr[0];
- this->buf = chunk_skip(this->buf, 1);
+ *res = *get_ptr_end(this, 1, from_end);
+ this->buf = chunk_skip_end(this->buf, 1, from_end);
return TRUE;
}
-METHOD(bio_reader_t, read_uint16, bool,
- private_bio_reader_t *this, u_int16_t *res)
+/**
+ * Read an u_int16_t from the buffer, optionally from the end
+ */
+static bool read_uint16_internal(private_bio_reader_t *this, u_int16_t *res,
+ bool from_end)
{
if (this->buf.len < 2)
{
@@ -70,13 +106,16 @@ METHOD(bio_reader_t, read_uint16, bool,
this->buf.len);
return FALSE;
}
- *res = untoh16(this->buf.ptr);
- this->buf = chunk_skip(this->buf, 2);
+ *res = untoh16(get_ptr_end(this, 2, from_end));
+ this->buf = chunk_skip_end(this->buf, 2, from_end);
return TRUE;
}
-METHOD(bio_reader_t, read_uint24, bool,
- private_bio_reader_t *this, u_int32_t *res)
+/**
+ * Read an u_int32_t (only 24-bit) from the buffer, optionally from the end
+ */
+static bool read_uint24_internal(private_bio_reader_t *this, u_int32_t *res,
+ bool from_end)
{
if (this->buf.len < 3)
{
@@ -84,13 +123,16 @@ METHOD(bio_reader_t, read_uint24, bool,
this->buf.len);
return FALSE;
}
- *res = untoh32(this->buf.ptr) >> 8;
- this->buf = chunk_skip(this->buf, 3);
+ *res = untoh32(get_ptr_end(this, 3, from_end)) >> 8;
+ this->buf = chunk_skip_end(this->buf, 3, from_end);
return TRUE;
}
-METHOD(bio_reader_t, read_uint32, bool,
- private_bio_reader_t *this, u_int32_t *res)
+/**
+ * Read an u_int32_t from the buffer, optionally from the end
+ */
+static bool read_uint32_internal(private_bio_reader_t *this, u_int32_t *res,
+ bool from_end)
{
if (this->buf.len < 4)
{
@@ -98,13 +140,16 @@ METHOD(bio_reader_t, read_uint32, bool,
this->buf.len);
return FALSE;
}
- *res = untoh32(this->buf.ptr);
- this->buf = chunk_skip(this->buf, 4);
+ *res = untoh32(get_ptr_end(this, 4, from_end));
+ this->buf = chunk_skip_end(this->buf, 4, from_end);
return TRUE;
}
-METHOD(bio_reader_t, read_uint64, bool,
- private_bio_reader_t *this, u_int64_t *res)
+/**
+ * Read an u_int64_t from the buffer, optionally from the end
+ */
+static bool read_uint64_internal(private_bio_reader_t *this, u_int64_t *res,
+ bool from_end)
{
if (this->buf.len < 8)
{
@@ -112,13 +157,16 @@ METHOD(bio_reader_t, read_uint64, bool,
this->buf.len);
return FALSE;
}
- *res = untoh64(this->buf.ptr);
- this->buf = chunk_skip(this->buf, 8);
+ *res = untoh64(get_ptr_end(this, 8, from_end));
+ this->buf = chunk_skip_end(this->buf, 8, from_end);
return TRUE;
}
-METHOD(bio_reader_t, read_data, bool,
- private_bio_reader_t *this, u_int32_t len, chunk_t *res)
+/**
+ * Read a chunk of data from the buffer, optionally from the end
+ */
+static bool read_data_internal(private_bio_reader_t *this, u_int32_t len,
+ chunk_t *res, bool from_end)
{
if (this->buf.len < len)
{
@@ -126,11 +174,83 @@ METHOD(bio_reader_t, read_data, bool,
this->buf.len, len);
return FALSE;
}
- *res = chunk_create(this->buf.ptr, len);
- this->buf = chunk_skip(this->buf, len);
+ *res = chunk_create(get_ptr_end(this, len, from_end), len);
+ this->buf = chunk_skip_end(this->buf, len, from_end);
return TRUE;
}
+METHOD(bio_reader_t, read_uint8, bool,
+ private_bio_reader_t *this, u_int8_t *res)
+{
+ return read_uint8_internal(this, res, FALSE);
+}
+
+METHOD(bio_reader_t, read_uint16, bool,
+ private_bio_reader_t *this, u_int16_t *res)
+{
+ return read_uint16_internal(this, res, FALSE);
+}
+
+METHOD(bio_reader_t, read_uint24, bool,
+ private_bio_reader_t *this, u_int32_t *res)
+{
+ return read_uint24_internal(this, res, FALSE);
+}
+
+METHOD(bio_reader_t, read_uint32, bool,
+ private_bio_reader_t *this, u_int32_t *res)
+{
+ return read_uint32_internal(this, res, FALSE);
+}
+
+METHOD(bio_reader_t, read_uint64, bool,
+ private_bio_reader_t *this, u_int64_t *res)
+{
+ return read_uint64_internal(this, res, FALSE);
+}
+
+METHOD(bio_reader_t, read_data, bool,
+ private_bio_reader_t *this, u_int32_t len, chunk_t *res)
+{
+ return read_data_internal(this, len, res, FALSE);
+}
+
+METHOD(bio_reader_t, read_uint8_end, bool,
+ private_bio_reader_t *this, u_int8_t *res)
+{
+ return read_uint8_internal(this, res, TRUE);
+}
+
+METHOD(bio_reader_t, read_uint16_end, bool,
+ private_bio_reader_t *this, u_int16_t *res)
+{
+ return read_uint16_internal(this, res, TRUE);
+}
+
+METHOD(bio_reader_t, read_uint24_end, bool,
+ private_bio_reader_t *this, u_int32_t *res)
+{
+ return read_uint24_internal(this, res, TRUE);
+}
+
+METHOD(bio_reader_t, read_uint32_end, bool,
+ private_bio_reader_t *this, u_int32_t *res)
+{
+ return read_uint32_internal(this, res, TRUE);
+}
+
+METHOD(bio_reader_t, read_uint64_end, bool,
+ private_bio_reader_t *this, u_int64_t *res)
+{
+ return read_uint64_internal(this, res, TRUE);
+}
+
+METHOD(bio_reader_t, read_data_end, bool,
+ private_bio_reader_t *this, u_int32_t len, chunk_t *res)
+{
+ return read_data_internal(this, len, res, TRUE);
+}
+
METHOD(bio_reader_t, read_data8, bool,
private_bio_reader_t *this, chunk_t *res)
{
@@ -202,6 +322,12 @@ bio_reader_t *bio_reader_create(chunk_t data)
.read_uint32 = _read_uint32,
.read_uint64 = _read_uint64,
.read_data = _read_data,
+ .read_uint8_end = _read_uint8_end,
+ .read_uint16_end = _read_uint16_end,
+ .read_uint24_end = _read_uint24_end,
+ .read_uint32_end = _read_uint32_end,
+ .read_uint64_end = _read_uint64_end,
+ .read_data_end = _read_data_end,
.read_data8 = _read_data8,
.read_data16 = _read_data16,
.read_data24 = _read_data24,
diff --git a/src/libstrongswan/bio/bio_reader.h b/src/libstrongswan/bio/bio_reader.h
index 85434a784..3162f3eda 100644
--- a/src/libstrongswan/bio/bio_reader.h
+++ b/src/libstrongswan/bio/bio_reader.h
@@ -1,4 +1,7 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
* Copyright (C) 2010 Martin Willi
* Copyright (C) 2010 revosec AG
*
@@ -27,6 +30,8 @@ typedef struct bio_reader_t bio_reader_t;
/**
* Buffered input parser.
+ *
+ * @note Integers are returned in host byte order.
*/
struct bio_reader_t {
@@ -94,6 +99,55 @@ struct bio_reader_t {
bool (*read_data)(bio_reader_t *this, u_int32_t len, chunk_t *res);
/**
+ * Read a 8-bit integer from the end of the buffer, reduce remaining.
+ *
+ * @param res pointer to result
+ * @return TRUE if integer read successfully
+ */
+ bool (*read_uint8_end)(bio_reader_t *this, u_int8_t *res);
+
+ /**
+ * Read a 16-bit integer from the end of the buffer, reduce remaining.
+ *
+ * @param res pointer to result
+ * @return TRUE if integer read successfully
+ */
+ bool (*read_uint16_end)(bio_reader_t *this, u_int16_t *res);
+
+ /**
+ * Read a 24-bit integer from the end of the buffer, reduce remaining.
+ *
+ * @param res pointer to result
+ * @return TRUE if integer read successfully
+ */
+ bool (*read_uint24_end)(bio_reader_t *this, u_int32_t *res);
+
+ /**
+ * Read a 32-bit integer from the end of the buffer, reduce remaining.
+ *
+ * @param res pointer to result
+ * @return TRUE if integer read successfully
+ */
+ bool (*read_uint32_end)(bio_reader_t *this, u_int32_t *res);
+
+ /**
+ * Read a 64-bit integer from the end of the buffer, reduce remaining.
+ *
+ * @param res pointer to result
+ * @return TRUE if integer read successfully
+ */
+ bool (*read_uint64_end)(bio_reader_t *this, u_int64_t *res);
+
+ /**
+ * Read a chunk of len bytes from the end of the buffer, reduce remaining.
+ *
+ * @param len number of bytes to read
+ * @param res ponter to result, not cloned
+ * @return TRUE if data read successfully
+ */
+ bool (*read_data_end)(bio_reader_t *this, u_int32_t len, chunk_t *res);
+
+ /**
* Read a chunk of bytes with a 8-bit length header, advance.
*
* @param res pointer to result, not cloned
diff --git a/src/libstrongswan/bio/bio_writer.c b/src/libstrongswan/bio/bio_writer.c
index bf373d6ac..8576843ee 100644
--- a/src/libstrongswan/bio/bio_writer.c
+++ b/src/libstrongswan/bio/bio_writer.c
@@ -1,4 +1,7 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
* Copyright (C) 2010 Martin Willi
* Copyright (C) 2010 revosec AG
*
@@ -199,12 +202,35 @@ METHOD(bio_writer_t, wrap32, void,
this->used += 4;
}
+METHOD(bio_writer_t, skip, chunk_t,
+ private_bio_writer_t *this, size_t len)
+{
+ chunk_t skipped;
+
+ while (this->used + len > this->buf.len)
+ {
+ increase(this);
+ }
+ skipped = chunk_create(this->buf.ptr + this->used, len);
+ this->used += len;
+ return skipped;
+}
+
METHOD(bio_writer_t, get_buf, chunk_t,
private_bio_writer_t *this)
{
return chunk_create(this->buf.ptr, this->used);
}
+METHOD(bio_writer_t, extract_buf, chunk_t,
+ private_bio_writer_t *this)
+{
+ chunk_t buf = get_buf(this);
+ this->buf = chunk_empty;
+ this->used = 0;
+ return buf;
+}
+
METHOD(bio_writer_t, destroy, void,
private_bio_writer_t *this)
{
@@ -235,7 +261,9 @@ bio_writer_t *bio_writer_create(u_int32_t bufsize)
.wrap16 = _wrap16,
.wrap24 = _wrap24,
.wrap32 = _wrap32,
+ .skip = _skip,
.get_buf = _get_buf,
+ .extract_buf = _extract_buf,
.destroy = _destroy,
},
.increase = bufsize ? max(bufsize, 4) : 32,
diff --git a/src/libstrongswan/bio/bio_writer.h b/src/libstrongswan/bio/bio_writer.h
index 0b50f7882..57a5c3d38 100644
--- a/src/libstrongswan/bio/bio_writer.h
+++ b/src/libstrongswan/bio/bio_writer.h
@@ -1,4 +1,7 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
* Copyright (C) 2010 Martin Willi
* Copyright (C) 2010 revosec AG
*
@@ -27,6 +30,8 @@ typedef struct bio_writer_t bio_writer_t;
/**
* Buffered output generator.
+ *
+ * @note Integers are converted to network byte order before writing.
*/
struct bio_writer_t {
@@ -121,6 +126,15 @@ struct bio_writer_t {
void (*wrap32)(bio_writer_t *this);
/**
+ * Skips len bytes in the buffer before the next data is written, returns
+ * a chunk covering the skipped bytes.
+ *
+ * @param len number of bytes to skip
+ * @return chunk pointing to skipped bytes in the internal buffer
+ */
+ chunk_t (*skip)(bio_writer_t *this, size_t len);
+
+ /**
* Get the encoded data buffer.
*
* @return chunk to internal buffer
@@ -128,6 +142,14 @@ struct bio_writer_t {
chunk_t (*get_buf)(bio_writer_t *this);
/**
+ * Return the encoded data buffer and detach it from the writer (resets
+ * the internal buffer).
+ *
+ * @return chunk to internal buffer (has to be freed)
+ */
+ chunk_t (*extract_buf)(bio_writer_t *this);
+
+ /**
* Destroy a bio_writer_t.
*/
void (*destroy)(bio_writer_t *this);
@@ -136,6 +158,9 @@ struct bio_writer_t {
/**
* Create a bio_writer instance.
*
+ * The size of the internal buffer is increased automatically by bufsize (or a
+ * default if not given) if the initial size does not suffice.
+ *
* @param bufsize initially allocated buffer size
*/
bio_writer_t *bio_writer_create(u_int32_t bufsize);
diff --git a/src/libstrongswan/chunk.c b/src/libstrongswan/chunk.c
index 9397c4e44..d7f1c31d9 100644
--- a/src/libstrongswan/chunk.c
+++ b/src/libstrongswan/chunk.c
@@ -658,7 +658,7 @@ u_int32_t chunk_hash(chunk_t chunk)
/**
* Described in header.
*/
-int chunk_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
+int chunk_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
const void *const *args)
{
chunk_t *chunk = *((chunk_t**)(args[0]));
@@ -670,7 +670,7 @@ int chunk_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
{
u_int chunk_len = chunk->len;
const void *new_args[] = {&chunk->ptr, &chunk_len};
- return mem_printf_hook(dst, len, spec, new_args);
+ return mem_printf_hook(data, spec, new_args);
}
while (copy.len > 0)
@@ -681,9 +681,9 @@ int chunk_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
}
else
{
- written += print_in_hook(dst, len, ":");
+ written += print_in_hook(data, ":");
}
- written += print_in_hook(dst, len, "%02x", *copy.ptr++);
+ written += print_in_hook(data, "%02x", *copy.ptr++);
copy.len--;
}
return written;
diff --git a/src/libstrongswan/chunk.h b/src/libstrongswan/chunk.h
index 3de02eee7..91b23da3b 100644
--- a/src/libstrongswan/chunk.h
+++ b/src/libstrongswan/chunk.h
@@ -265,6 +265,15 @@ static inline bool chunk_equals(chunk_t a, chunk_t b)
}
/**
+ * Compare two chunks (given as pointers) for equality (useful as callback),
+ * NULL chunks are never equal.
+ */
+static inline bool chunk_equals_ptr(chunk_t *a, chunk_t *b)
+{
+ return a != NULL && b != NULL && chunk_equals(*a, *b);
+}
+
+/**
* Increment a chunk, as it would reprensent a network order integer.
*
* @param chunk chunk to increment
@@ -303,7 +312,7 @@ u_int32_t chunk_hash_inc(chunk_t chunk, u_int32_t hash);
* chunk_t *chunk
* Use #-modifier to print a compact version
*/
-int chunk_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
+int chunk_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
const void *const *args);
#endif /** CHUNK_H_ @}*/
diff --git a/src/libstrongswan/credentials/auth_cfg.c b/src/libstrongswan/credentials/auth_cfg.c
index 12f75b240..6ee4f9b6e 100644
--- a/src/libstrongswan/credentials/auth_cfg.c
+++ b/src/libstrongswan/credentials/auth_cfg.c
@@ -23,20 +23,24 @@
#include <eap/eap.h>
#include <credentials/certificates/certificate.h>
-ENUM(auth_class_names, AUTH_CLASS_ANY, AUTH_CLASS_EAP,
+ENUM(auth_class_names, AUTH_CLASS_ANY, AUTH_CLASS_XAUTH,
"any",
"public key",
"pre-shared key",
"EAP",
+ "XAuth",
);
ENUM(auth_rule_names, AUTH_RULE_IDENTITY, AUTH_HELPER_REVOCATION_CERT,
"RULE_IDENTITY",
+ "RULE_IDENTITY_LOOSE",
"RULE_AUTH_CLASS",
"RULE_AAA_IDENTITY",
"RULE_EAP_IDENTITY",
"RULE_EAP_TYPE",
"RULE_EAP_VENDOR",
+ "RULE_XAUTH_BACKEND",
+ "RULE_XAUTH_IDENTITY",
"RULE_CA_CERT",
"RULE_IM_CERT",
"RULE_SUBJECT_CERT",
@@ -45,6 +49,7 @@ ENUM(auth_rule_names, AUTH_RULE_IDENTITY, AUTH_HELPER_REVOCATION_CERT,
"RULE_GROUP",
"RULE_RSA_STRENGTH",
"RULE_ECDSA_STRENGTH",
+ "RULE_SIGNATURE_SCHEME",
"RULE_CERT_POLICY",
"HELPER_IM_CERT",
"HELPER_SUBJECT_CERT",
@@ -66,8 +71,11 @@ static inline bool is_multi_value_rule(auth_rule_t type)
case AUTH_RULE_RSA_STRENGTH:
case AUTH_RULE_ECDSA_STRENGTH:
case AUTH_RULE_IDENTITY:
+ case AUTH_RULE_IDENTITY_LOOSE:
case AUTH_RULE_EAP_IDENTITY:
case AUTH_RULE_AAA_IDENTITY:
+ case AUTH_RULE_XAUTH_IDENTITY:
+ case AUTH_RULE_XAUTH_BACKEND:
case AUTH_RULE_SUBJECT_CERT:
case AUTH_HELPER_SUBJECT_CERT:
case AUTH_HELPER_SUBJECT_HASH_URL:
@@ -79,6 +87,7 @@ static inline bool is_multi_value_rule(auth_rule_t type)
case AUTH_RULE_CA_CERT:
case AUTH_RULE_IM_CERT:
case AUTH_RULE_CERT_POLICY:
+ case AUTH_RULE_SIGNATURE_SCHEME:
case AUTH_HELPER_IM_CERT:
case AUTH_HELPER_IM_HASH_URL:
case AUTH_HELPER_REVOCATION_CERT:
@@ -190,6 +199,7 @@ static entry_t *entry_create(auth_rule_t type, va_list args)
this->type = type;
switch (type)
{
+ case AUTH_RULE_IDENTITY_LOOSE:
case AUTH_RULE_AUTH_CLASS:
case AUTH_RULE_EAP_TYPE:
case AUTH_RULE_EAP_VENDOR:
@@ -197,12 +207,15 @@ static entry_t *entry_create(auth_rule_t type, va_list args)
case AUTH_RULE_OCSP_VALIDATION:
case AUTH_RULE_RSA_STRENGTH:
case AUTH_RULE_ECDSA_STRENGTH:
+ case AUTH_RULE_SIGNATURE_SCHEME:
/* integer type */
this->value = (void*)(uintptr_t)va_arg(args, u_int);
break;
case AUTH_RULE_IDENTITY:
case AUTH_RULE_EAP_IDENTITY:
case AUTH_RULE_AAA_IDENTITY:
+ case AUTH_RULE_XAUTH_BACKEND:
+ case AUTH_RULE_XAUTH_IDENTITY:
case AUTH_RULE_GROUP:
case AUTH_RULE_CA_CERT:
case AUTH_RULE_IM_CERT:
@@ -234,6 +247,7 @@ static bool entry_equals(entry_t *e1, entry_t *e2)
}
switch (e1->type)
{
+ case AUTH_RULE_IDENTITY_LOOSE:
case AUTH_RULE_AUTH_CLASS:
case AUTH_RULE_EAP_TYPE:
case AUTH_RULE_EAP_VENDOR:
@@ -241,6 +255,7 @@ static bool entry_equals(entry_t *e1, entry_t *e2)
case AUTH_RULE_OCSP_VALIDATION:
case AUTH_RULE_RSA_STRENGTH:
case AUTH_RULE_ECDSA_STRENGTH:
+ case AUTH_RULE_SIGNATURE_SCHEME:
{
return e1->value == e2->value;
}
@@ -261,6 +276,7 @@ static bool entry_equals(entry_t *e1, entry_t *e2)
case AUTH_RULE_IDENTITY:
case AUTH_RULE_EAP_IDENTITY:
case AUTH_RULE_AAA_IDENTITY:
+ case AUTH_RULE_XAUTH_IDENTITY:
case AUTH_RULE_GROUP:
{
identification_t *id1, *id2;
@@ -271,6 +287,7 @@ static bool entry_equals(entry_t *e1, entry_t *e2)
return id1->equals(id1, id2);
}
case AUTH_RULE_CERT_POLICY:
+ case AUTH_RULE_XAUTH_BACKEND:
case AUTH_HELPER_IM_HASH_URL:
case AUTH_HELPER_SUBJECT_HASH_URL:
{
@@ -293,6 +310,7 @@ static void destroy_entry_value(entry_t *entry)
case AUTH_RULE_EAP_IDENTITY:
case AUTH_RULE_AAA_IDENTITY:
case AUTH_RULE_GROUP:
+ case AUTH_RULE_XAUTH_IDENTITY:
{
identification_t *id = (identification_t*)entry->value;
id->destroy(id);
@@ -310,12 +328,14 @@ static void destroy_entry_value(entry_t *entry)
break;
}
case AUTH_RULE_CERT_POLICY:
+ case AUTH_RULE_XAUTH_BACKEND:
case AUTH_HELPER_IM_HASH_URL:
case AUTH_HELPER_SUBJECT_HASH_URL:
{
free(entry->value);
break;
}
+ case AUTH_RULE_IDENTITY_LOOSE:
case AUTH_RULE_AUTH_CLASS:
case AUTH_RULE_EAP_TYPE:
case AUTH_RULE_EAP_VENDOR:
@@ -323,6 +343,7 @@ static void destroy_entry_value(entry_t *entry)
case AUTH_RULE_OCSP_VALIDATION:
case AUTH_RULE_RSA_STRENGTH:
case AUTH_RULE_ECDSA_STRENGTH:
+ case AUTH_RULE_SIGNATURE_SCHEME:
case AUTH_RULE_MAX:
break;
}
@@ -345,6 +366,7 @@ static void replace(private_auth_cfg_t *this, entry_enumerator_t *enumerator,
entry->type = type;
switch (type)
{
+ case AUTH_RULE_IDENTITY_LOOSE:
case AUTH_RULE_AUTH_CLASS:
case AUTH_RULE_EAP_TYPE:
case AUTH_RULE_EAP_VENDOR:
@@ -352,12 +374,15 @@ static void replace(private_auth_cfg_t *this, entry_enumerator_t *enumerator,
case AUTH_RULE_OCSP_VALIDATION:
case AUTH_RULE_RSA_STRENGTH:
case AUTH_RULE_ECDSA_STRENGTH:
+ case AUTH_RULE_SIGNATURE_SCHEME:
/* integer type */
entry->value = (void*)(uintptr_t)va_arg(args, u_int);
break;
case AUTH_RULE_IDENTITY:
case AUTH_RULE_EAP_IDENTITY:
case AUTH_RULE_AAA_IDENTITY:
+ case AUTH_RULE_XAUTH_BACKEND:
+ case AUTH_RULE_XAUTH_IDENTITY:
case AUTH_RULE_GROUP:
case AUTH_RULE_CA_CERT:
case AUTH_RULE_IM_CERT:
@@ -423,12 +448,18 @@ METHOD(auth_cfg_t, get, void*,
case AUTH_RULE_RSA_STRENGTH:
case AUTH_RULE_ECDSA_STRENGTH:
return (void*)0;
+ case AUTH_RULE_SIGNATURE_SCHEME:
+ return HASH_UNKNOWN;
case AUTH_RULE_CRL_VALIDATION:
case AUTH_RULE_OCSP_VALIDATION:
return (void*)VALIDATION_FAILED;
+ case AUTH_RULE_IDENTITY_LOOSE:
+ return (void*)FALSE;
case AUTH_RULE_IDENTITY:
case AUTH_RULE_EAP_IDENTITY:
case AUTH_RULE_AAA_IDENTITY:
+ case AUTH_RULE_XAUTH_BACKEND:
+ case AUTH_RULE_XAUTH_IDENTITY:
case AUTH_RULE_GROUP:
case AUTH_RULE_CA_CERT:
case AUTH_RULE_IM_CERT:
@@ -472,7 +503,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, has_group = FALSE, group_match = FALSE;
+ bool success = TRUE, group_match = FALSE;
+ identification_t *require_group = NULL;
+ signature_scheme_t scheme = SIGN_UNKNOWN;
+ u_int strength = 0;
auth_rule_t t1, t2;
void *value;
@@ -571,6 +605,7 @@ METHOD(auth_cfg_t, complies, bool,
case AUTH_RULE_IDENTITY:
case AUTH_RULE_EAP_IDENTITY:
case AUTH_RULE_AAA_IDENTITY:
+ case AUTH_RULE_XAUTH_IDENTITY:
{
identification_t *id1, *id2;
@@ -578,6 +613,17 @@ METHOD(auth_cfg_t, complies, bool,
id2 = get(this, t1);
if (!id2 || !id2->matches(id2, id1))
{
+ if (t1 == AUTH_RULE_IDENTITY &&
+ constraints->get(constraints, AUTH_RULE_IDENTITY_LOOSE))
+ { /* also verify identity against subjectAltNames */
+ certificate_t *cert;
+
+ cert = get(this, AUTH_HELPER_SUBJECT_CERT);
+ if (cert && cert->has_subject(cert, id1))
+ {
+ break;
+ }
+ }
success = FALSE;
if (log_error)
{
@@ -633,15 +679,15 @@ METHOD(auth_cfg_t, complies, bool,
}
case AUTH_RULE_GROUP:
{
- identification_t *id1, *id2;
+ identification_t *group;
/* for groups, a match of a single group is sufficient */
- has_group = TRUE;
- id1 = (identification_t*)value;
+ require_group = (identification_t*)value;
e2 = create_enumerator(this);
- while (e2->enumerate(e2, &t2, &id2))
+ while (e2->enumerate(e2, &t2, &group))
{
- if (t2 == AUTH_RULE_GROUP && id2->matches(id2, id1))
+ if (t2 == AUTH_RULE_GROUP &&
+ group->matches(group, require_group))
{
group_match = TRUE;
}
@@ -652,44 +698,12 @@ METHOD(auth_cfg_t, complies, bool,
case AUTH_RULE_RSA_STRENGTH:
case AUTH_RULE_ECDSA_STRENGTH:
{
- uintptr_t strength;
-
- e2 = create_enumerator(this);
- while (e2->enumerate(e2, &t2, &strength))
- {
- if (t2 == t1)
- {
- if ((uintptr_t)value > strength)
- {
- success = FALSE;
- if (log_error)
- {
- DBG1(DBG_CFG, "constraint requires %d bit "
- "public keys, but %d bit key used",
- (uintptr_t)value, strength);
- }
- }
- }
- else if (t2 == AUTH_RULE_RSA_STRENGTH)
- {
- success = FALSE;
- if (log_error)
- {
- DBG1(DBG_CFG, "constraint requires %d bit ECDSA, "
- "but RSA used", (uintptr_t)value);
- }
- }
- else if (t2 == AUTH_RULE_ECDSA_STRENGTH)
- {
- success = FALSE;
- if (log_error)
- {
- DBG1(DBG_CFG, "constraint requires %d bit RSA, "
- "but ECDSA used", (uintptr_t)value);
- }
- }
- }
- e2->destroy(e2);
+ strength = (uintptr_t)value;
+ break;
+ }
+ case AUTH_RULE_SIGNATURE_SCHEME:
+ {
+ scheme = (uintptr_t)value;
break;
}
case AUTH_RULE_CERT_POLICY:
@@ -714,6 +728,10 @@ METHOD(auth_cfg_t, complies, bool,
}
break;
}
+ case AUTH_RULE_IDENTITY_LOOSE:
+ /* just an indication when verifying AUTH_RULE_IDENTITY */
+ case AUTH_RULE_XAUTH_BACKEND:
+ /* not enforced, just a hint for local authentication */
case AUTH_HELPER_IM_CERT:
case AUTH_HELPER_SUBJECT_CERT:
case AUTH_HELPER_IM_HASH_URL:
@@ -730,11 +748,83 @@ METHOD(auth_cfg_t, complies, bool,
}
e1->destroy(e1);
- if (has_group && !group_match)
+ /* Check if we have a matching constraint (or none at all) for used
+ * signature schemes. */
+ if (success && scheme != SIGN_UNKNOWN)
+ {
+ e2 = create_enumerator(this);
+ while (e2->enumerate(e2, &t2, &scheme))
+ {
+ if (t2 == AUTH_RULE_SIGNATURE_SCHEME)
+ {
+ success = FALSE;
+ e1 = constraints->create_enumerator(constraints);
+ while (e1->enumerate(e1, &t1, &value))
+ {
+ if (t1 == AUTH_RULE_SIGNATURE_SCHEME &&
+ (uintptr_t)value == scheme)
+ {
+ success = TRUE;
+ break;
+ }
+ }
+ e1->destroy(e1);
+ if (!success)
+ {
+ if (log_error)
+ {
+ DBG1(DBG_CFG, "signature scheme %N not acceptable",
+ signature_scheme_names, (int)scheme);
+ }
+ break;
+ }
+ }
+ }
+ e2->destroy(e2);
+ }
+
+ /* Check if we have a matching constraint (or none at all) for used
+ * public key strength */
+ if (success && strength)
+ {
+ e2 = create_enumerator(this);
+ while (e2->enumerate(e2, &t2, &strength))
+ {
+ if (t2 == AUTH_RULE_RSA_STRENGTH ||
+ t2 == AUTH_RULE_ECDSA_STRENGTH)
+ {
+ success = FALSE;
+ e1 = constraints->create_enumerator(constraints);
+ while (e1->enumerate(e1, &t1, &value))
+ {
+ if (t1 == t2 && (uintptr_t)value <= strength)
+ {
+ success = TRUE;
+ break;
+ }
+ }
+ e1->destroy(e1);
+ if (!success)
+ {
+ if (log_error)
+ {
+ DBG1(DBG_CFG, "%s-%d signatures not acceptable",
+ t2 == AUTH_RULE_RSA_STRENGTH ? "RSA" : "ECDSA",
+ strength);
+ }
+ break;
+ }
+ }
+ }
+ e2->destroy(e2);
+ }
+
+ if (require_group && !group_match)
{
if (log_error)
{
- DBG1(DBG_CFG, "constraint check failed: group membership required");
+ DBG1(DBG_CFG, "constraint check failed: group membership to "
+ "'%Y' required", require_group);
}
return FALSE;
}
@@ -774,6 +864,7 @@ static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy
add(this, type, cert->get_ref(cert));
break;
}
+ case AUTH_RULE_IDENTITY_LOOSE:
case AUTH_RULE_CRL_VALIDATION:
case AUTH_RULE_OCSP_VALIDATION:
case AUTH_RULE_AUTH_CLASS:
@@ -781,6 +872,7 @@ static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy
case AUTH_RULE_EAP_VENDOR:
case AUTH_RULE_RSA_STRENGTH:
case AUTH_RULE_ECDSA_STRENGTH:
+ case AUTH_RULE_SIGNATURE_SCHEME:
{
add(this, type, (uintptr_t)value);
break;
@@ -789,12 +881,14 @@ static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy
case AUTH_RULE_EAP_IDENTITY:
case AUTH_RULE_AAA_IDENTITY:
case AUTH_RULE_GROUP:
+ case AUTH_RULE_XAUTH_IDENTITY:
{
identification_t *id = (identification_t*)value;
add(this, type, id->clone(id));
break;
}
+ case AUTH_RULE_XAUTH_BACKEND:
case AUTH_RULE_CERT_POLICY:
case AUTH_HELPER_IM_HASH_URL:
case AUTH_HELPER_SUBJECT_HASH_URL:
@@ -821,9 +915,9 @@ static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy
}
/**
- * Implementation of auth_cfg_t.equals.
+ * Compare two auth_cfg_t objects for equality.
*/
-static bool equals(private_auth_cfg_t *this, private_auth_cfg_t *other)
+static bool auth_cfg_equals(private_auth_cfg_t *this, private_auth_cfg_t *other)
{
enumerator_t *e1, *e2;
entry_t *i1, *i2;
@@ -860,6 +954,20 @@ static bool equals(private_auth_cfg_t *this, private_auth_cfg_t *other)
return equal;
}
+/**
+ * Implementation of auth_cfg_t.equals.
+ */
+static bool equals(private_auth_cfg_t *this, private_auth_cfg_t *other)
+{
+ if (auth_cfg_equals(this, other))
+ {
+ /* as 'other' might contain entries that 'this' doesn't we also check
+ * the other way around */
+ return auth_cfg_equals(other, this);
+ }
+ return FALSE;
+}
+
METHOD(auth_cfg_t, purge, void,
private_auth_cfg_t *this, bool keep_ca)
{
@@ -904,6 +1012,7 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*,
case AUTH_RULE_EAP_IDENTITY:
case AUTH_RULE_AAA_IDENTITY:
case AUTH_RULE_GROUP:
+ case AUTH_RULE_XAUTH_IDENTITY:
{
identification_t *id = (identification_t*)entry->value;
clone->add(clone, entry->type, id->clone(id));
@@ -920,6 +1029,7 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*,
clone->add(clone, entry->type, cert->get_ref(cert));
break;
}
+ case AUTH_RULE_XAUTH_BACKEND:
case AUTH_RULE_CERT_POLICY:
case AUTH_HELPER_IM_HASH_URL:
case AUTH_HELPER_SUBJECT_HASH_URL:
@@ -927,6 +1037,7 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*,
clone->add(clone, entry->type, strdup(entry->value));
break;
}
+ case AUTH_RULE_IDENTITY_LOOSE:
case AUTH_RULE_AUTH_CLASS:
case AUTH_RULE_EAP_TYPE:
case AUTH_RULE_EAP_VENDOR:
@@ -934,6 +1045,7 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*,
case AUTH_RULE_OCSP_VALIDATION:
case AUTH_RULE_RSA_STRENGTH:
case AUTH_RULE_ECDSA_STRENGTH:
+ case AUTH_RULE_SIGNATURE_SCHEME:
clone->add(clone, entry->type, (uintptr_t)entry->value);
break;
case AUTH_RULE_MAX:
diff --git a/src/libstrongswan/credentials/auth_cfg.h b/src/libstrongswan/credentials/auth_cfg.h
index 4d12a9c14..79484a04c 100644
--- a/src/libstrongswan/credentials/auth_cfg.h
+++ b/src/libstrongswan/credentials/auth_cfg.h
@@ -42,6 +42,8 @@ enum auth_class_t {
AUTH_CLASS_PSK = 2,
/** authentication using EAP */
AUTH_CLASS_EAP = 3,
+ /** authentication using IKEv1 XAUTH */
+ AUTH_CLASS_XAUTH = 4,
};
/**
@@ -65,6 +67,9 @@ extern enum_name_t *auth_class_names;
enum auth_rule_t {
/** identity to use for IKEv2 authentication exchange, identification_t* */
AUTH_RULE_IDENTITY,
+ /** if TRUE don't send IDr as initiator, but verify the identity after
+ * receiving IDr (but also verify it against subjectAltNames), bool */
+ AUTH_RULE_IDENTITY_LOOSE,
/** authentication class, auth_class_t */
AUTH_RULE_AUTH_CLASS,
/** AAA-backend identity for EAP methods supporting it, identification_t* */
@@ -75,6 +80,10 @@ enum auth_rule_t {
AUTH_RULE_EAP_TYPE,
/** EAP vendor for vendor specific type, u_int32_t */
AUTH_RULE_EAP_VENDOR,
+ /** XAUTH backend name to use, char* */
+ AUTH_RULE_XAUTH_BACKEND,
+ /** XAuth identity to use or require, identification_t* */
+ AUTH_RULE_XAUTH_IDENTITY,
/** certificate authority, certificate_t* */
AUTH_RULE_CA_CERT,
/** intermediate certificate in trustchain, certificate_t* */
@@ -93,6 +102,8 @@ enum auth_rule_t {
AUTH_RULE_RSA_STRENGTH,
/** required ECDSA public key strength, u_int in bits */
AUTH_RULE_ECDSA_STRENGTH,
+ /** required signature scheme, signature_scheme_t */
+ AUTH_RULE_SIGNATURE_SCHEME,
/** certificatePolicy constraint, numerical OID as char* */
AUTH_RULE_CERT_POLICY,
@@ -172,7 +183,7 @@ struct auth_cfg_t {
* For rules we expect only once the latest value is returned.
*
* @param rule rule type
- * @return bool if item has been found
+ * @return rule or NULL (or an appropriate default) if not found
*/
void* (*get)(auth_cfg_t *this, auth_rule_t rule);
diff --git a/src/libstrongswan/credentials/certificates/certificate.h b/src/libstrongswan/credentials/certificates/certificate.h
index 2f471da5b..b7a88ffbd 100644
--- a/src/libstrongswan/credentials/certificates/certificate.h
+++ b/src/libstrongswan/credentials/certificates/certificate.h
@@ -143,9 +143,11 @@ struct certificate_t {
* Check if this certificate is issued and signed by a specific issuer.
*
* @param issuer issuer's certificate
+ * @param scheme receives signature scheme used during verification
* @return TRUE if certificate issued by issuer and trusted
*/
- bool (*issued_by)(certificate_t *this, certificate_t *issuer);
+ bool (*issued_by)(certificate_t *this, certificate_t *issuer,
+ signature_scheme_t *scheme);
/**
* Get the public key associated to this certificate.
diff --git a/src/libstrongswan/credentials/certificates/x509.h b/src/libstrongswan/credentials/certificates/x509.h
index 5125aca26..00171a718 100644
--- a/src/libstrongswan/credentials/certificates/x509.h
+++ b/src/libstrongswan/credentials/certificates/x509.h
@@ -56,6 +56,8 @@ enum x509_flag_t {
X509_IP_ADDR_BLOCKS = (1<<6),
/** cert has CRL sign key usage */
X509_CRL_SIGN = (1<<7),
+ /** cert has iKEIntermediate key usage */
+ X509_IKE_INTERMEDIATE = (1<<8),
};
/**
diff --git a/src/libstrongswan/credentials/credential_manager.c b/src/libstrongswan/credentials/credential_manager.c
index b3461b810..a96abdc69 100644
--- a/src/libstrongswan/credentials/credential_manager.c
+++ b/src/libstrongswan/credentials/credential_manager.c
@@ -53,6 +53,11 @@ struct private_credential_manager_t {
thread_value_t *local_sets;
/**
+ * Exclusive local sets, linked_list_t with credential_set_t
+ */
+ thread_value_t *exclusive_local_sets;
+
+ /**
* trust relationship and certificate cache
*/
cert_cache_t *cache;
@@ -117,12 +122,23 @@ typedef struct {
enumerator_t *global;
/** enumerator over local sets */
enumerator_t *local;
+ /** enumerator over exclusive local sets */
+ enumerator_t *exclusive;
} sets_enumerator_t;
METHOD(enumerator_t, sets_enumerate, bool,
sets_enumerator_t *this, credential_set_t **set)
{
+ if (this->exclusive)
+ {
+ if (this->exclusive->enumerate(this->exclusive, set))
+ { /* only enumerate last added */
+ this->exclusive->destroy(this->exclusive);
+ this->exclusive = NULL;
+ return TRUE;
+ }
+ }
if (this->global)
{
if (this->global->enumerate(this->global, set))
@@ -145,6 +161,7 @@ METHOD(enumerator_t, sets_destroy, void,
{
DESTROY_IF(this->global);
DESTROY_IF(this->local);
+ DESTROY_IF(this->exclusive);
free(this);
}
@@ -154,19 +171,28 @@ METHOD(enumerator_t, sets_destroy, void,
static enumerator_t *create_sets_enumerator(private_credential_manager_t *this)
{
sets_enumerator_t *enumerator;
- linked_list_t *local;
+ linked_list_t *list;
INIT(enumerator,
.public = {
.enumerate = (void*)_sets_enumerate,
.destroy = _sets_destroy,
},
- .global = this->sets->create_enumerator(this->sets),
);
- local = this->local_sets->get(this->local_sets);
- if (local)
+
+ list = this->exclusive_local_sets->get(this->exclusive_local_sets);
+ if (list && list->get_count(list))
+ {
+ enumerator->exclusive = list->create_enumerator(list);
+ }
+ else
{
- enumerator->local = local->create_enumerator(local);
+ enumerator->global = this->sets->create_enumerator(this->sets);
+ list = this->local_sets->get(this->local_sets);
+ if (list)
+ {
+ enumerator->local = list->create_enumerator(list);
+ }
}
return &enumerator->public;
}
@@ -373,26 +399,66 @@ METHOD(credential_manager_t, get_shared, shared_key_t*,
}
METHOD(credential_manager_t, add_local_set, void,
- private_credential_manager_t *this, credential_set_t *set)
+ private_credential_manager_t *this, credential_set_t *set, bool exclusive)
{
linked_list_t *sets;
+ thread_value_t *tv;
- sets = this->local_sets->get(this->local_sets);
+ if (exclusive)
+ {
+ tv = this->exclusive_local_sets;
+ }
+ else
+ {
+ tv = this->local_sets;
+ }
+ sets = tv->get(tv);
if (!sets)
- { /* first invocation */
+ {
sets = linked_list_create();
- this->local_sets->set(this->local_sets, sets);
+ tv->set(tv, sets);
+ }
+ if (exclusive)
+ {
+ sets->insert_first(sets, set);
+ }
+ else
+ {
+ sets->insert_last(sets, set);
}
- sets->insert_last(sets, set);
}
METHOD(credential_manager_t, remove_local_set, void,
private_credential_manager_t *this, credential_set_t *set)
{
linked_list_t *sets;
+ thread_value_t *tv;
- sets = this->local_sets->get(this->local_sets);
- sets->remove(sets, set, NULL);
+ tv = this->local_sets;
+ sets = tv->get(tv);
+ if (sets && sets->remove(sets, set, NULL) && sets->get_count(sets) == 0)
+ {
+ tv->set(tv, NULL);
+ sets->destroy(sets);
+ }
+ tv = this->exclusive_local_sets;
+ sets = tv->get(tv);
+ if (sets && sets->remove(sets, set, NULL) && sets->get_count(sets) == 0)
+ {
+ tv->set(tv, NULL);
+ sets->destroy(sets);
+ }
+}
+
+METHOD(credential_manager_t, issued_by, bool,
+ private_credential_manager_t *this, certificate_t *subject,
+ certificate_t *issuer, signature_scheme_t *scheme)
+{
+ if (this->cache)
+ {
+ return this->cache->issued_by(this->cache, subject, issuer, scheme);
+ }
+ return subject->issued_by(subject, issuer, scheme);
}
METHOD(credential_manager_t, cache_cert, void,
@@ -514,7 +580,8 @@ static certificate_t *get_pretrusted_cert(private_credential_manager_t *this,
* Get the issuing certificate of a subject certificate
*/
static certificate_t *get_issuer_cert(private_credential_manager_t *this,
- certificate_t *subject, bool trusted)
+ certificate_t *subject, bool trusted,
+ signature_scheme_t *scheme)
{
enumerator_t *enumerator;
certificate_t *issuer = NULL, *candidate;
@@ -523,7 +590,7 @@ static certificate_t *get_issuer_cert(private_credential_manager_t *this,
subject->get_issuer(subject), trusted);
while (enumerator->enumerate(enumerator, &candidate))
{
- if (this->cache->issued_by(this->cache, subject, candidate))
+ if (issued_by(this, subject, candidate, scheme))
{
issuer = candidate->get_ref(candidate);
break;
@@ -573,6 +640,7 @@ static bool verify_trust_chain(private_credential_manager_t *this,
{
certificate_t *current, *issuer;
auth_cfg_t *auth;
+ signature_scheme_t scheme;
int pathlen;
auth = auth_cfg_create();
@@ -582,11 +650,11 @@ static bool verify_trust_chain(private_credential_manager_t *this,
for (pathlen = 0; pathlen <= MAX_TRUST_PATH_LEN; pathlen++)
{
- issuer = get_issuer_cert(this, current, TRUE);
+ issuer = get_issuer_cert(this, current, TRUE, &scheme);
if (issuer)
{
/* accept only self-signed CAs as trust anchor */
- if (this->cache->issued_by(this->cache, issuer, issuer))
+ if (issued_by(this, issuer, issuer, NULL))
{
auth->add(auth, AUTH_RULE_CA_CERT, issuer->get_ref(issuer));
DBG1(DBG_CFG, " using trusted ca certificate \"%Y\"",
@@ -599,10 +667,11 @@ static bool verify_trust_chain(private_credential_manager_t *this,
DBG1(DBG_CFG, " using trusted intermediate ca certificate "
"\"%Y\"", issuer->get_subject(issuer));
}
+ auth->add(auth, AUTH_RULE_SIGNATURE_SCHEME, scheme);
}
else
{
- issuer = get_issuer_cert(this, current, FALSE);
+ issuer = get_issuer_cert(this, current, FALSE, &scheme);
if (issuer)
{
if (current->equals(current, issuer))
@@ -615,6 +684,7 @@ static bool verify_trust_chain(private_credential_manager_t *this,
auth->add(auth, AUTH_RULE_IM_CERT, issuer->get_ref(issuer));
DBG1(DBG_CFG, " using untrusted intermediate certificate "
"\"%Y\"", issuer->get_subject(issuer));
+ auth->add(auth, AUTH_RULE_SIGNATURE_SCHEME, scheme);
}
else
{
@@ -708,8 +778,7 @@ METHOD(enumerator_t, trusted_enumerate, bool,
/* if we find a trusted self signed certificate, we just accept it.
* However, in order to fulfill authorization rules, we try to build
* the trust chain if it is not self signed */
- if (this->this->cache->issued_by(this->this->cache,
- this->pretrusted, this->pretrusted) ||
+ if (issued_by(this->this, this->pretrusted, this->pretrusted, NULL) ||
verify_trust_chain(this->this, this->pretrusted, this->auth,
TRUE, this->online))
{
@@ -859,7 +928,7 @@ METHOD(credential_manager_t, create_public_enumerator, enumerator_t*,
if (auth)
{
enumerator->wrapper = auth_cfg_wrapper_create(auth);
- add_local_set(this, &enumerator->wrapper->set);
+ add_local_set(this, &enumerator->wrapper->set, FALSE);
}
this->lock->read_lock(this->lock);
return &enumerator->public;
@@ -916,8 +985,7 @@ static auth_cfg_t *build_trustchain(private_credential_manager_t *this,
}
else
{
- if (!has_anchor &&
- this->cache->issued_by(this->cache, current, current))
+ if (!has_anchor && issued_by(this, current, current, NULL))
{ /* If no trust anchor specified, accept any CA */
trustchain->add(trustchain, AUTH_RULE_CA_CERT, current);
return trustchain;
@@ -928,7 +996,7 @@ static auth_cfg_t *build_trustchain(private_credential_manager_t *this,
{
break;
}
- issuer = get_issuer_cert(this, current, FALSE);
+ issuer = get_issuer_cert(this, current, FALSE, NULL);
if (!issuer)
{
if (!has_anchor)
@@ -992,42 +1060,45 @@ METHOD(credential_manager_t, get_private, private_key_t*,
}
}
- /* if a specific certificate is preferred, check for a matching key */
- cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
- if (cert)
+ if (auth)
{
- private = get_private_by_cert(this, cert, type);
- if (private)
+ /* if a specific certificate is preferred, check for a matching key */
+ cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
+ if (cert)
{
- trustchain = build_trustchain(this, cert, auth);
- if (trustchain)
+ private = get_private_by_cert(this, cert, type);
+ if (private)
{
- auth->merge(auth, trustchain, FALSE);
- trustchain->destroy(trustchain);
+ trustchain = build_trustchain(this, cert, auth);
+ if (trustchain)
+ {
+ auth->merge(auth, trustchain, FALSE);
+ trustchain->destroy(trustchain);
+ }
+ return private;
}
- return private;
}
- }
- /* try to build a trust chain for each certificate found */
- enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE);
- while (enumerator->enumerate(enumerator, &cert))
- {
- private = get_private_by_cert(this, cert, type);
- if (private)
+ /* try to build a trust chain for each certificate found */
+ enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE);
+ while (enumerator->enumerate(enumerator, &cert))
{
- trustchain = build_trustchain(this, cert, auth);
- if (trustchain)
+ private = get_private_by_cert(this, cert, type);
+ if (private)
{
- auth->merge(auth, trustchain, FALSE);
- trustchain->destroy(trustchain);
- break;
+ trustchain = build_trustchain(this, cert, auth);
+ if (trustchain)
+ {
+ auth->merge(auth, trustchain, FALSE);
+ trustchain->destroy(trustchain);
+ break;
+ }
+ private->destroy(private);
+ private = NULL;
}
- private->destroy(private);
- private = NULL;
}
+ enumerator->destroy(enumerator);
}
- enumerator->destroy(enumerator);
/* if no valid trustchain was found, fall back to the first usable cert */
if (!private)
@@ -1038,7 +1109,10 @@ METHOD(credential_manager_t, get_private, private_key_t*,
private = get_private_by_cert(this, cert, type);
if (private)
{
- auth->add(auth, AUTH_RULE_SUBJECT_CERT, cert->get_ref(cert));
+ if (auth)
+ {
+ auth->add(auth, AUTH_RULE_SUBJECT_CERT, cert->get_ref(cert));
+ }
break;
}
}
@@ -1050,14 +1124,10 @@ METHOD(credential_manager_t, get_private, private_key_t*,
METHOD(credential_manager_t, flush_cache, void,
private_credential_manager_t *this, certificate_type_t type)
{
- this->cache->flush(this->cache, type);
-}
-
-METHOD(credential_manager_t, issued_by, bool,
- private_credential_manager_t *this, certificate_t *subject,
- certificate_t *issuer)
-{
- return this->cache->issued_by(this->cache, subject, issuer);
+ if (this->cache)
+ {
+ this->cache->flush(this->cache, type);
+ }
}
METHOD(credential_manager_t, add_set, void,
@@ -1097,10 +1167,14 @@ METHOD(credential_manager_t, destroy, void,
{
cache_queue(this);
this->cache_queue->destroy(this->cache_queue);
- this->sets->remove(this->sets, this->cache, NULL);
+ if (this->cache)
+ {
+ this->sets->remove(this->sets, this->cache, NULL);
+ this->cache->destroy(this->cache);
+ }
this->sets->destroy(this->sets);
this->local_sets->destroy(this->local_sets);
- this->cache->destroy(this->cache);
+ this->exclusive_local_sets->destroy(this->exclusive_local_sets);
this->validators->destroy(this->validators);
this->lock->destroy(this->lock);
this->queue_mutex->destroy(this->queue_mutex);
@@ -1137,14 +1211,18 @@ credential_manager_t *credential_manager_create()
},
.sets = linked_list_create(),
.validators = linked_list_create(),
- .cache = cert_cache_create(),
.cache_queue = linked_list_create(),
.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
.queue_mutex = mutex_create(MUTEX_TYPE_DEFAULT),
);
this->local_sets = thread_value_create((thread_cleanup_t)this->sets->destroy);
- this->sets->insert_first(this->sets, this->cache);
+ this->exclusive_local_sets = thread_value_create((thread_cleanup_t)this->sets->destroy);
+ if (lib->settings->get_bool(lib->settings, "libstrongswan.cert_cache", TRUE))
+ {
+ this->cache = cert_cache_create();
+ this->sets->insert_first(this->sets, this->cache);
+ }
return &this->public;
}
diff --git a/src/libstrongswan/credentials/credential_manager.h b/src/libstrongswan/credentials/credential_manager.h
index 8e8f04b8c..d9a47b7d7 100644
--- a/src/libstrongswan/credentials/credential_manager.h
+++ b/src/libstrongswan/credentials/credential_manager.h
@@ -89,7 +89,7 @@ struct credential_manager_t {
* @param type kind of requested shared key
* @param first first subject between key is shared
* @param second second subject between key is shared
- * @return enumerator over shared keys
+ * @return enumerator over (shared_key_t*,id_match_t,id_match_t)
*/
enumerator_t *(*create_shared_enumerator)(credential_manager_t *this,
shared_key_type_t type,
@@ -204,10 +204,12 @@ struct credential_manager_t {
*
* @param subject subject certificate to check
* @param issuer issuer certificate that potentially has signed subject
+ * @param scheme receives used signature scheme, if given
* @return TRUE if issuer signed subject
*/
bool (*issued_by)(credential_manager_t *this,
- certificate_t *subject, certificate_t *issuer);
+ certificate_t *subject, certificate_t *issuer,
+ signature_scheme_t *scheme);
/**
* Register a credential set to the manager.
@@ -230,10 +232,14 @@ struct credential_manager_t {
* operation, sets may be added for the calling thread only. This
* does not require a write lock and is therefore a much cheaper
* operation.
+ * The exclusive option allows to disable all other credential sets
+ * until the set is deregistered.
*
* @param set set to register
+ * @param exclusive TRUE to disable all other sets for this thread
*/
- void (*add_local_set)(credential_manager_t *this, credential_set_t *set);
+ void (*add_local_set)(credential_manager_t *this, credential_set_t *set,
+ bool exclusive);
/**
* Unregister a thread local credential set from the manager.
diff --git a/src/libstrongswan/credentials/sets/cert_cache.c b/src/libstrongswan/credentials/sets/cert_cache.c
index 968c3e31e..a7d0ed8f9 100644
--- a/src/libstrongswan/credentials/sets/cert_cache.c
+++ b/src/libstrongswan/credentials/sets/cert_cache.c
@@ -47,6 +47,11 @@ struct relation_t {
certificate_t *issuer;
/**
+ * Signature scheme used to sign this relation
+ */
+ signature_scheme_t scheme;
+
+ /**
* Cache hits
*/
u_int hits;
@@ -77,7 +82,8 @@ struct private_cert_cache_t {
* Cache relation in a free slot/replace an other
*/
static void cache(private_cert_cache_t *this,
- certificate_t *subject, certificate_t *issuer)
+ certificate_t *subject, certificate_t *issuer,
+ signature_scheme_t scheme)
{
relation_t *rel;
int i, offset, try;
@@ -95,6 +101,7 @@ static void cache(private_cert_cache_t *this,
{
rel->subject = subject->get_ref(subject);
rel->issuer = issuer->get_ref(issuer);
+ rel->scheme = scheme;
return rel->lock->unlock(rel->lock);
}
rel->lock->unlock(rel->lock);
@@ -123,6 +130,7 @@ static void cache(private_cert_cache_t *this,
}
rel->subject = subject->get_ref(subject);
rel->issuer = issuer->get_ref(issuer);
+ rel->scheme = scheme;
rel->hits = 0;
return rel->lock->unlock(rel->lock);
}
@@ -133,9 +141,11 @@ static void cache(private_cert_cache_t *this,
}
METHOD(cert_cache_t, issued_by, bool,
- private_cert_cache_t *this, certificate_t *subject, certificate_t *issuer)
+ private_cert_cache_t *this, certificate_t *subject, certificate_t *issuer,
+ signature_scheme_t *schemep)
{
relation_t *found = NULL, *current;
+ signature_scheme_t scheme;
int i;
for (i = 0; i < CACHE_SIZE; i++)
@@ -154,7 +164,11 @@ METHOD(cert_cache_t, issued_by, bool,
{
/* write hit counter is not locked, but not critical */
current->hits++;
- found = current;
+ found = current;;
+ if (schemep)
+ {
+ *schemep = current->scheme;
+ }
}
}
}
@@ -165,9 +179,13 @@ METHOD(cert_cache_t, issued_by, bool,
}
}
/* no cache hit, check and cache signature */
- if (subject->issued_by(subject, issuer))
+ if (subject->issued_by(subject, issuer, &scheme))
{
- cache(this, subject, issuer);
+ cache(this, subject, issuer, scheme);
+ if (schemep)
+ {
+ *schemep = scheme;
+ }
return TRUE;
}
return FALSE;
diff --git a/src/libstrongswan/credentials/sets/cert_cache.h b/src/libstrongswan/credentials/sets/cert_cache.h
index d2721866e..2bcdbe464 100644
--- a/src/libstrongswan/credentials/sets/cert_cache.h
+++ b/src/libstrongswan/credentials/sets/cert_cache.h
@@ -45,10 +45,12 @@ struct cert_cache_t {
*
* @param subject certificate to verify
* @param issuer issuing certificate to verify subject
+ * @param scheme receives used signature scheme, if given
* @return TRUE if subject issued by issuer
*/
bool (*issued_by)(cert_cache_t *this,
- certificate_t *subject, certificate_t *issuer);
+ certificate_t *subject, certificate_t *issuer,
+ signature_scheme_t *scheme);
/**
* Flush the certificate cache.
diff --git a/src/libstrongswan/crypto/aead.c b/src/libstrongswan/crypto/aead.c
index 51cb05909..02fb8d50a 100644
--- a/src/libstrongswan/crypto/aead.c
+++ b/src/libstrongswan/crypto/aead.c
@@ -40,26 +40,41 @@ struct private_aead_t {
signer_t *signer;
};
-METHOD(aead_t, encrypt, void,
+METHOD(aead_t, encrypt, bool,
private_aead_t *this, chunk_t plain, chunk_t assoc, chunk_t iv,
chunk_t *encrypted)
{
chunk_t encr, sig;
- this->signer->get_signature(this->signer, assoc, NULL);
- this->signer->get_signature(this->signer, iv, NULL);
+ if (!this->signer->get_signature(this->signer, assoc, NULL) ||
+ !this->signer->get_signature(this->signer, iv, NULL))
+ {
+ return FALSE;
+ }
if (encrypted)
{
- this->crypter->encrypt(this->crypter, plain, iv, &encr);
- this->signer->allocate_signature(this->signer, encr, &sig);
+ if (!this->crypter->encrypt(this->crypter, plain, iv, &encr))
+ {
+ return FALSE;
+ }
+ if (!this->signer->allocate_signature(this->signer, encr, &sig))
+ {
+ free(encr.ptr);
+ return FALSE;
+ }
*encrypted = chunk_cat("cmm", iv, encr, sig);
}
else
{
- this->crypter->encrypt(this->crypter, plain, iv, NULL);
- this->signer->get_signature(this->signer, plain, plain.ptr + plain.len);
+ if (!this->crypter->encrypt(this->crypter, plain, iv, NULL) ||
+ !this->signer->get_signature(this->signer,
+ plain, plain.ptr + plain.len))
+ {
+ return FALSE;
+ }
}
+ return TRUE;
}
METHOD(aead_t, decrypt, bool,
@@ -80,15 +95,17 @@ METHOD(aead_t, decrypt, bool,
chunk_split(encrypted, "mm", encrypted.len - sig.len,
&encrypted, sig.len, &sig);
- this->signer->get_signature(this->signer, assoc, NULL);
- this->signer->get_signature(this->signer, iv, NULL);
+ if (!this->signer->get_signature(this->signer, assoc, NULL) ||
+ !this->signer->get_signature(this->signer, iv, NULL))
+ {
+ return FALSE;
+ }
if (!this->signer->verify_signature(this->signer, encrypted, sig))
{
DBG1(DBG_LIB, "MAC verification failed");
return FALSE;
}
- this->crypter->decrypt(this->crypter, encrypted, iv, plain);
- return TRUE;
+ return this->crypter->decrypt(this->crypter, encrypted, iv, plain);
}
METHOD(aead_t, get_block_size, size_t,
@@ -116,7 +133,7 @@ METHOD(aead_t, get_key_size, size_t,
this->signer->get_key_size(this->signer);
}
-METHOD(aead_t, set_key, void,
+METHOD(aead_t, set_key, bool,
private_aead_t *this, chunk_t key)
{
chunk_t sig, enc;
@@ -124,8 +141,8 @@ METHOD(aead_t, set_key, void,
chunk_split(key, "mm", this->signer->get_key_size(this->signer), &sig,
this->crypter->get_key_size(this->crypter), &enc);
- this->signer->set_key(this->signer, sig);
- this->crypter->set_key(this->crypter, enc);
+ return this->signer->set_key(this->signer, sig) &&
+ this->crypter->set_key(this->crypter, enc);
}
METHOD(aead_t, destroy, void,
diff --git a/src/libstrongswan/crypto/aead.h b/src/libstrongswan/crypto/aead.h
index 3f6abb4f9..ec526a3d9 100644
--- a/src/libstrongswan/crypto/aead.h
+++ b/src/libstrongswan/crypto/aead.h
@@ -45,9 +45,10 @@ struct aead_t {
* @param assoc associated data to sign
* @param iv initialization vector
* @param encrypted allocated encryption result
+ * @return TRUE if successfully encrypted
*/
- void (*encrypt)(aead_t *this, chunk_t plain, chunk_t assoc, chunk_t iv,
- chunk_t *encrypted);
+ bool (*encrypt)(aead_t *this, chunk_t plain, chunk_t assoc, chunk_t iv,
+ chunk_t *encrypted) __attribute__((warn_unused_result));
/**
* Decrypt and verify data, verify associated data.
@@ -98,8 +99,10 @@ struct aead_t {
* Set the key for encryption and authentication.
*
* @param key encryption and authentication key
+ * @return TRUE if key set successfully
*/
- void (*set_key)(aead_t *this, chunk_t key);
+ bool (*set_key)(aead_t *this,
+ chunk_t key) __attribute__((warn_unused_result));
/**
* Destroy a aead_t.
diff --git a/src/libstrongswan/crypto/crypters/crypter.h b/src/libstrongswan/crypto/crypters/crypter.h
index 3bf039681..fe854f53d 100644
--- a/src/libstrongswan/crypto/crypters/crypter.h
+++ b/src/libstrongswan/crypto/crypters/crypter.h
@@ -90,9 +90,10 @@ struct crypter_t {
* @param data data to encrypt
* @param iv initializing vector
* @param encrypted chunk to allocate encrypted data, or NULL
+ * @return TRUE if encryption successful
*/
- void (*encrypt) (crypter_t *this, chunk_t data, chunk_t iv,
- chunk_t *encrypted);
+ bool (*encrypt)(crypter_t *this, chunk_t data, chunk_t iv,
+ chunk_t *encrypted) __attribute__((warn_unused_result));
/**
* Decrypt a chunk of data and allocate space for the decrypted value.
@@ -104,9 +105,10 @@ struct crypter_t {
* @param data data to decrypt
* @param iv initializing vector
* @param encrypted chunk to allocate decrypted data, or NULL
+ * @return TRUE if decryption successful
*/
- void (*decrypt) (crypter_t *this, chunk_t data, chunk_t iv,
- chunk_t *decrypted);
+ bool (*decrypt)(crypter_t *this, chunk_t data, chunk_t iv,
+ chunk_t *decrypted) __attribute__((warn_unused_result));
/**
* Get the block size of the crypto algorithm.
@@ -117,7 +119,7 @@ struct crypter_t {
*
* @return block size in bytes
*/
- size_t (*get_block_size) (crypter_t *this);
+ size_t (*get_block_size)(crypter_t *this);
/**
* Get the IV size of the crypto algorithm.
@@ -135,7 +137,7 @@ struct crypter_t {
*
* @return key size in bytes
*/
- size_t (*get_key_size) (crypter_t *this);
+ size_t (*get_key_size)(crypter_t *this);
/**
* Set the key.
@@ -143,13 +145,15 @@ struct crypter_t {
* The length of the key must match get_key_size().
*
* @param key key to set
+ * @return TRUE if key set successfully
*/
- void (*set_key) (crypter_t *this, chunk_t key);
+ bool (*set_key)(crypter_t *this,
+ chunk_t key) __attribute__((warn_unused_result));
/**
* Destroys a crypter_t object.
*/
- void (*destroy) (crypter_t *this);
+ void (*destroy)(crypter_t *this);
};
/**
diff --git a/src/libstrongswan/crypto/crypto_factory.c b/src/libstrongswan/crypto/crypto_factory.c
index 2d13896d6..3736ae38f 100644
--- a/src/libstrongswan/crypto/crypto_factory.c
+++ b/src/libstrongswan/crypto/crypto_factory.c
@@ -50,6 +50,7 @@ struct entry_t {
hasher_constructor_t create_hasher;
prf_constructor_t create_prf;
rng_constructor_t create_rng;
+ nonce_gen_constructor_t create_nonce_gen;
dh_constructor_t create_dh;
void *create;
};
@@ -98,6 +99,11 @@ struct private_crypto_factory_t {
linked_list_t *rngs;
/**
+ * registered nonce generators, as entry_t
+ */
+ linked_list_t *nonce_gens;
+
+ /**
* registered diffie hellman, as entry_t
*/
linked_list_t *dhs;
@@ -329,34 +335,49 @@ METHOD(crypto_factory_t, create_rng, rng_t*,
return NULL;
}
+METHOD(crypto_factory_t, create_nonce_gen, nonce_gen_t*,
+ private_crypto_factory_t *this)
+{
+ enumerator_t *enumerator;
+ entry_t *entry;
+ nonce_gen_t *nonce_gen = NULL;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->nonce_gens->create_enumerator(this->nonce_gens);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ nonce_gen = entry->create_nonce_gen();
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ return nonce_gen;
+}
+
METHOD(crypto_factory_t, create_dh, diffie_hellman_t*,
private_crypto_factory_t *this, diffie_hellman_group_t group, ...)
{
enumerator_t *enumerator;
entry_t *entry;
+ va_list args;
+ chunk_t g = chunk_empty, p = chunk_empty;
diffie_hellman_t *diffie_hellman = NULL;
+ if (group == MODP_CUSTOM)
+ {
+ va_start(args, group);
+ g = va_arg(args, chunk_t);
+ p = va_arg(args, chunk_t);
+ va_end(args);
+ }
+
this->lock->read_lock(this->lock);
enumerator = this->dhs->create_enumerator(this->dhs);
while (enumerator->enumerate(enumerator, &entry))
{
if (entry->algo == group)
{
- if (group == MODP_CUSTOM)
- {
- va_list args;
- chunk_t g, p;
-
- va_start(args, group);
- g = va_arg(args, chunk_t);
- p = va_arg(args, chunk_t);
- va_end(args);
- diffie_hellman = entry->create_dh(MODP_CUSTOM, g, p);
- }
- else
- {
- diffie_hellman = entry->create_dh(group);
- }
+ diffie_hellman = entry->create_dh(group, g, p);
if (diffie_hellman)
{
break;
@@ -618,6 +639,33 @@ METHOD(crypto_factory_t, remove_rng, void,
this->lock->unlock(this->lock);
}
+METHOD(crypto_factory_t, add_nonce_gen, void,
+ private_crypto_factory_t *this, const char *plugin_name,
+ nonce_gen_constructor_t create)
+{
+ add_entry(this, this->nonce_gens, 0, plugin_name, 0, create);
+}
+
+METHOD(crypto_factory_t, remove_nonce_gen, void,
+ private_crypto_factory_t *this, nonce_gen_constructor_t create)
+{
+ entry_t *entry;
+ enumerator_t *enumerator;
+
+ this->lock->write_lock(this->lock);
+ enumerator = this->nonce_gens->create_enumerator(this->nonce_gens);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->create_nonce_gen == create)
+ {
+ this->nonce_gens->remove_at(this->nonce_gens, enumerator);
+ free(entry);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+}
+
METHOD(crypto_factory_t, add_dh, void,
private_crypto_factory_t *this, diffie_hellman_group_t group,
const char *plugin_name, dh_constructor_t create)
@@ -756,7 +804,7 @@ METHOD(crypto_factory_t, create_prf_enumerator, enumerator_t*,
}
/**
- * Filter function to enumerate algorithm, not entry
+ * Filter function to enumerate group, not entry
*/
static bool dh_filter(void *n, entry_t **entry, diffie_hellman_group_t *group,
void *i2, const char **plugin_name)
@@ -773,7 +821,7 @@ METHOD(crypto_factory_t, create_dh_enumerator, enumerator_t*,
}
/**
- * Filter function to enumerate algorithm, not entry
+ * Filter function to enumerate strength, not entry
*/
static bool rng_filter(void *n, entry_t **entry, rng_quality_t *quality,
void *i2, const char **plugin_name)
@@ -788,6 +836,22 @@ METHOD(crypto_factory_t, create_rng_enumerator, enumerator_t*,
{
return create_enumerator(this, this->rngs, rng_filter);
}
+
+/**
+ * Filter function to enumerate plugin name, not entry
+ */
+static bool nonce_gen_filter(void *n, entry_t **entry, const char **plugin_name)
+{
+ *plugin_name = (*entry)->plugin_name;
+ return TRUE;
+}
+
+METHOD(crypto_factory_t, create_nonce_gen_enumerator, enumerator_t*,
+ private_crypto_factory_t *this)
+{
+ return create_enumerator(this, this->nonce_gens, nonce_gen_filter);
+}
+
METHOD(crypto_factory_t, add_test_vector, void,
private_crypto_factory_t *this, transform_type_t type, void *vector)
{
@@ -820,6 +884,7 @@ METHOD(crypto_factory_t, destroy, void,
this->hashers->destroy(this->hashers);
this->prfs->destroy(this->prfs);
this->rngs->destroy(this->rngs);
+ this->nonce_gens->destroy(this->nonce_gens);
this->dhs->destroy(this->dhs);
this->tester->destroy(this->tester);
this->lock->destroy(this->lock);
@@ -841,6 +906,7 @@ crypto_factory_t *crypto_factory_create()
.create_hasher = _create_hasher,
.create_prf = _create_prf,
.create_rng = _create_rng,
+ .create_nonce_gen = _create_nonce_gen,
.create_dh = _create_dh,
.add_crypter = _add_crypter,
.remove_crypter = _remove_crypter,
@@ -854,6 +920,8 @@ crypto_factory_t *crypto_factory_create()
.remove_prf = _remove_prf,
.add_rng = _add_rng,
.remove_rng = _remove_rng,
+ .add_nonce_gen = _add_nonce_gen,
+ .remove_nonce_gen = _remove_nonce_gen,
.add_dh = _add_dh,
.remove_dh = _remove_dh,
.create_crypter_enumerator = _create_crypter_enumerator,
@@ -863,6 +931,7 @@ crypto_factory_t *crypto_factory_create()
.create_prf_enumerator = _create_prf_enumerator,
.create_dh_enumerator = _create_dh_enumerator,
.create_rng_enumerator = _create_rng_enumerator,
+ .create_nonce_gen_enumerator = _create_nonce_gen_enumerator,
.add_test_vector = _add_test_vector,
.destroy = _destroy,
},
@@ -872,6 +941,7 @@ crypto_factory_t *crypto_factory_create()
.hashers = linked_list_create(),
.prfs = linked_list_create(),
.rngs = linked_list_create(),
+ .nonce_gens = linked_list_create(),
.dhs = linked_list_create(),
.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
.tester = crypto_tester_create(),
diff --git a/src/libstrongswan/crypto/crypto_factory.h b/src/libstrongswan/crypto/crypto_factory.h
index 8e5db6355..611ca0bbb 100644
--- a/src/libstrongswan/crypto/crypto_factory.h
+++ b/src/libstrongswan/crypto/crypto_factory.h
@@ -30,6 +30,7 @@ typedef struct crypto_factory_t crypto_factory_t;
#include <crypto/hashers/hasher.h>
#include <crypto/prfs/prf.h>
#include <crypto/rngs/rng.h>
+#include <crypto/nonce_gen.h>
#include <crypto/diffie_hellman.h>
#include <crypto/transform.h>
@@ -66,6 +67,11 @@ typedef prf_t* (*prf_constructor_t)(pseudo_random_function_t algo);
typedef rng_t* (*rng_constructor_t)(rng_quality_t quality);
/**
+ * Constructor function for nonce generators
+ */
+typedef nonce_gen_t* (*nonce_gen_constructor_t)();
+
+/**
* Constructor function for diffie hellman
*
* The DH constructor accepts additional arguments for:
@@ -132,6 +138,13 @@ struct crypto_factory_t {
rng_t* (*create_rng)(crypto_factory_t *this, rng_quality_t quality);
/**
+ * Create a nonce generator instance.
+ *
+ * @return nonce_gen_t instance, NULL if not supported
+ */
+ nonce_gen_t* (*create_nonce_gen)(crypto_factory_t *this);
+
+ /**
* Create a diffie hellman instance.
*
* Additional arguments are passed to the DH constructor.
@@ -253,6 +266,23 @@ struct crypto_factory_t {
void (*remove_rng)(crypto_factory_t *this, rng_constructor_t create);
/**
+ * Register a nonce generator.
+ *
+ * @param plugin_name plugin that registered this algorithm
+ * @param create constructor function for that nonce generator
+ */
+ void (*add_nonce_gen)(crypto_factory_t *this, const char *plugin_name,
+ nonce_gen_constructor_t create);
+
+ /**
+ * Unregister a nonce generator.
+ *
+ * @param create constructor function to unregister
+ */
+ void (*remove_nonce_gen)(crypto_factory_t *this,
+ nonce_gen_constructor_t create);
+
+ /**
* Register a diffie hellman constructor.
*
* @param group dh group to constructor
@@ -273,53 +303,60 @@ struct crypto_factory_t {
/**
* Create an enumerator over all registered crypter algorithms.
*
- * @return enumerator over encryption_algorithm_t
+ * @return enumerator over encryption_algorithm_t, plugin
*/
enumerator_t* (*create_crypter_enumerator)(crypto_factory_t *this);
/**
* Create an enumerator over all registered aead algorithms.
*
- * @return enumerator over encryption_algorithm_t
+ * @return enumerator over encryption_algorithm_t, plugin
*/
enumerator_t* (*create_aead_enumerator)(crypto_factory_t *this);
/**
* Create an enumerator over all registered signer algorithms.
*
- * @return enumerator over integrity_algorithm_t
+ * @return enumerator over integrity_algorithm_t, plugin
*/
enumerator_t* (*create_signer_enumerator)(crypto_factory_t *this);
/**
* Create an enumerator over all registered hasher algorithms.
*
- * @return enumerator over hash_algorithm_t
+ * @return enumerator over hash_algorithm_t, plugin
*/
enumerator_t* (*create_hasher_enumerator)(crypto_factory_t *this);
/**
* Create an enumerator over all registered PRFs.
*
- * @return enumerator over pseudo_random_function_t
+ * @return enumerator over pseudo_random_function_t, plugin
*/
enumerator_t* (*create_prf_enumerator)(crypto_factory_t *this);
/**
* Create an enumerator over all registered diffie hellman groups.
*
- * @return enumerator over diffie_hellman_group_t
+ * @return enumerator over diffie_hellman_group_t, plugin
*/
enumerator_t* (*create_dh_enumerator)(crypto_factory_t *this);
/**
* Create an enumerator over all registered random generators.
*
- * @return enumerator over rng_quality_t
+ * @return enumerator over rng_quality_t, plugin
*/
enumerator_t* (*create_rng_enumerator)(crypto_factory_t *this);
/**
+ * Create an enumerator over all registered nonce generators.
+ *
+ * @return enumerator over plugin
+ */
+ enumerator_t* (*create_nonce_gen_enumerator)(crypto_factory_t *this);
+
+ /**
* Add a test vector to the crypto factory.
*
* @param type type of the test vector
diff --git a/src/libstrongswan/crypto/crypto_tester.c b/src/libstrongswan/crypto/crypto_tester.c
index 8b1daa885..01e84a133 100644
--- a/src/libstrongswan/crypto/crypto_tester.c
+++ b/src/libstrongswan/crypto/crypto_tester.c
@@ -151,7 +151,10 @@ static u_int bench_crypter(private_crypto_tester_t *this,
memset(iv, 0x56, sizeof(iv));
memset(key, 0x12, sizeof(key));
- crypter->set_key(crypter, chunk_from_thing(key));
+ if (!crypter->set_key(crypter, chunk_from_thing(key)))
+ {
+ return 0;
+ }
buf = chunk_alloc(this->bench_size);
memset(buf.ptr, 0x34, buf.len);
@@ -160,10 +163,14 @@ static u_int bench_crypter(private_crypto_tester_t *this,
start_timing(&start);
while (end_timing(&start) < this->bench_time)
{
- crypter->encrypt(crypter, buf, chunk_from_thing(iv), NULL);
- runs++;
- crypter->decrypt(crypter, buf, chunk_from_thing(iv), NULL);
- runs++;
+ if (crypter->encrypt(crypter, buf, chunk_from_thing(iv), NULL))
+ {
+ runs++;
+ }
+ if (crypter->decrypt(crypter, buf, chunk_from_thing(iv), NULL))
+ {
+ runs++;
+ }
}
free(buf.ptr);
crypter->destroy(crypter);
@@ -186,7 +193,7 @@ METHOD(crypto_tester_t, test_crypter, bool,
while (enumerator->enumerate(enumerator, &vector))
{
crypter_t *crypter;
- chunk_t key, plain, cipher, iv;
+ chunk_t key, iv, plain = chunk_empty, cipher = chunk_empty;
if (vector->alg != alg)
{
@@ -196,53 +203,69 @@ METHOD(crypto_tester_t, test_crypter, bool,
{ /* test only vectors with a specific key size, if key size given */
continue;
}
+
+ tested++;
+ failed = TRUE;
crypter = create(alg, vector->key_size);
if (!crypter)
{
DBG1(DBG_LIB, "%N[%s]: %u bit key size not supported",
encryption_algorithm_names, alg, plugin_name,
BITS_PER_BYTE * vector->key_size);
- failed = TRUE;
continue;
}
- failed = FALSE;
- tested++;
-
key = chunk_create(vector->key, crypter->get_key_size(crypter));
- crypter->set_key(crypter, key);
+ if (!crypter->set_key(crypter, key))
+ {
+ goto failure;
+ }
iv = chunk_create(vector->iv, crypter->get_iv_size(crypter));
/* allocated encryption */
plain = chunk_create(vector->plain, vector->len);
- crypter->encrypt(crypter, plain, iv, &cipher);
+ if (!crypter->encrypt(crypter, plain, iv, &cipher))
+ {
+ goto failure;
+ }
if (!memeq(vector->cipher, cipher.ptr, cipher.len))
{
- failed = TRUE;
+ goto failure;
}
/* inline decryption */
- crypter->decrypt(crypter, cipher, iv, NULL);
+ if (!crypter->decrypt(crypter, cipher, iv, NULL))
+ {
+ goto failure;
+ }
if (!memeq(vector->plain, cipher.ptr, cipher.len))
{
- failed = TRUE;
+ goto failure;
}
- free(cipher.ptr);
/* allocated decryption */
- cipher = chunk_create(vector->cipher, vector->len);
- crypter->decrypt(crypter, cipher, iv, &plain);
+ if (!crypter->decrypt(crypter,
+ chunk_create(vector->cipher, vector->len), iv, &plain))
+ {
+ goto failure;
+ }
if (!memeq(vector->plain, plain.ptr, plain.len))
{
- failed = TRUE;
+ goto failure;
}
/* inline encryption */
- crypter->encrypt(crypter, plain, iv, NULL);
+ if (!crypter->encrypt(crypter, plain, iv, NULL))
+ {
+ goto failure;
+ }
if (!memeq(vector->cipher, plain.ptr, plain.len))
{
- failed = TRUE;
+ goto failure;
}
- free(plain.ptr);
+ failed = FALSE;
+failure:
crypter->destroy(crypter);
+ chunk_free(&cipher);
+ chunk_free(&plain);
if (failed)
{
DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
@@ -306,7 +329,10 @@ static u_int bench_aead(private_crypto_tester_t *this,
memset(iv, 0x56, sizeof(iv));
memset(key, 0x12, sizeof(key));
memset(assoc, 0x78, sizeof(assoc));
- aead->set_key(aead, chunk_from_thing(key));
+ if (!aead->set_key(aead, chunk_from_thing(key)))
+ {
+ return 0;
+ }
icv = aead->get_icv_size(aead);
buf = chunk_alloc(this->bench_size + icv);
@@ -317,12 +343,16 @@ static u_int bench_aead(private_crypto_tester_t *this,
start_timing(&start);
while (end_timing(&start) < this->bench_time)
{
- aead->encrypt(aead, buf, chunk_from_thing(assoc),
- chunk_from_thing(iv), NULL);
- runs += 2;
- aead->decrypt(aead, chunk_create(buf.ptr, buf.len + icv),
- chunk_from_thing(assoc), chunk_from_thing(iv), NULL);
- runs += 2;
+ if (aead->encrypt(aead, buf, chunk_from_thing(assoc),
+ chunk_from_thing(iv), NULL))
+ {
+ runs += 2;
+ }
+ if (aead->decrypt(aead, chunk_create(buf.ptr, buf.len + icv),
+ chunk_from_thing(assoc), chunk_from_thing(iv), NULL))
+ {
+ runs += 2;
+ }
}
free(buf.ptr);
aead->destroy(aead);
@@ -345,7 +375,7 @@ METHOD(crypto_tester_t, test_aead, bool,
while (enumerator->enumerate(enumerator, &vector))
{
aead_t *aead;
- chunk_t key, plain, cipher, iv, assoc;
+ chunk_t key, iv, assoc, plain = chunk_empty, cipher = chunk_empty;
size_t icv;
if (vector->alg != alg)
@@ -356,63 +386,72 @@ METHOD(crypto_tester_t, test_aead, bool,
{ /* test only vectors with a specific key size, if key size given */
continue;
}
+
+ tested++;
+ failed = TRUE;
aead = create(alg, vector->key_size);
if (!aead)
{
DBG1(DBG_LIB, "%N[%s]: %u bit key size not supported",
encryption_algorithm_names, alg, plugin_name,
BITS_PER_BYTE * vector->key_size);
- failed = TRUE;
continue;
}
- failed = FALSE;
- tested++;
-
key = chunk_create(vector->key, aead->get_key_size(aead));
- aead->set_key(aead, key);
+ if (!aead->set_key(aead, key))
+ {
+ goto failure;
+ }
iv = chunk_create(vector->iv, aead->get_iv_size(aead));
assoc = chunk_create(vector->adata, vector->alen);
icv = aead->get_icv_size(aead);
/* allocated encryption */
plain = chunk_create(vector->plain, vector->len);
- aead->encrypt(aead, plain, assoc, iv, &cipher);
+ if (!aead->encrypt(aead, plain, assoc, iv, &cipher))
+ {
+ goto failure;
+ }
if (!memeq(vector->cipher, cipher.ptr, cipher.len))
{
- failed = TRUE;
+ goto failure;
}
/* inline decryption */
if (!aead->decrypt(aead, cipher, assoc, iv, NULL))
{
- failed = TRUE;
+ goto failure;
}
if (!memeq(vector->plain, cipher.ptr, cipher.len - icv))
{
- failed = TRUE;
+ goto failure;
}
- free(cipher.ptr);
/* allocated decryption */
- cipher = chunk_create(vector->cipher, vector->len + icv);
- if (!aead->decrypt(aead, cipher, assoc, iv, &plain))
+ if (!aead->decrypt(aead, chunk_create(vector->cipher, vector->len + icv),
+ assoc, iv, &plain))
{
- plain = chunk_empty;
- failed = TRUE;
+ goto failure;
}
- else if (!memeq(vector->plain, plain.ptr, plain.len))
+ if (!memeq(vector->plain, plain.ptr, plain.len))
{
- failed = TRUE;
+ goto failure;
}
plain.ptr = realloc(plain.ptr, plain.len + icv);
/* inline encryption */
- aead->encrypt(aead, plain, assoc, iv, NULL);
+ if (!aead->encrypt(aead, plain, assoc, iv, NULL))
+ {
+ goto failure;
+ }
if (!memeq(vector->cipher, plain.ptr, plain.len + icv))
{
- failed = TRUE;
+ goto failure;
}
- free(plain.ptr);
+ failed = FALSE;
+failure:
aead->destroy(aead);
+ chunk_free(&cipher);
+ chunk_free(&plain);
if (failed)
{
DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
@@ -458,7 +497,7 @@ METHOD(crypto_tester_t, test_aead, bool,
* Benchmark a signer
*/
static u_int bench_signer(private_crypto_tester_t *this,
- encryption_algorithm_t alg, signer_constructor_t create)
+ integrity_algorithm_t alg, signer_constructor_t create)
{
signer_t *signer;
@@ -472,7 +511,10 @@ static u_int bench_signer(private_crypto_tester_t *this,
u_int runs;
memset(key, 0x12, sizeof(key));
- signer->set_key(signer, chunk_from_thing(key));
+ if (!signer->set_key(signer, chunk_from_thing(key)))
+ {
+ return 0;
+ }
buf = chunk_alloc(this->bench_size);
memset(buf.ptr, 0x34, buf.len);
@@ -481,10 +523,14 @@ static u_int bench_signer(private_crypto_tester_t *this,
start_timing(&start);
while (end_timing(&start) < this->bench_time)
{
- signer->get_signature(signer, buf, mac);
- runs++;
- signer->verify_signature(signer, buf, chunk_from_thing(mac));
- runs++;
+ if (signer->get_signature(signer, buf, mac))
+ {
+ runs++;
+ }
+ if (signer->verify_signature(signer, buf, chunk_from_thing(mac)))
+ {
+ runs++;
+ }
}
free(buf.ptr);
signer->destroy(signer);
@@ -507,7 +553,7 @@ METHOD(crypto_tester_t, test_signer, bool,
while (enumerator->enumerate(enumerator, &vector))
{
signer_t *signer;
- chunk_t key, data, mac;
+ chunk_t key, data, mac = chunk_empty;
if (vector->alg != alg)
{
@@ -515,63 +561,79 @@ METHOD(crypto_tester_t, test_signer, bool,
}
tested++;
+ failed = TRUE;
signer = create(alg);
if (!signer)
{
DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
integrity_algorithm_names, alg, plugin_name);
- failed = TRUE;
break;
}
- failed = FALSE;
-
key = chunk_create(vector->key, signer->get_key_size(signer));
- signer->set_key(signer, key);
-
+ if (!signer->set_key(signer, key))
+ {
+ goto failure;
+ }
/* allocated signature */
data = chunk_create(vector->data, vector->len);
- signer->allocate_signature(signer, data, &mac);
+ if (!signer->allocate_signature(signer, data, &mac))
+ {
+ goto failure;
+ }
if (mac.len != signer->get_block_size(signer))
{
- failed = TRUE;
+ goto failure;
}
if (!memeq(vector->mac, mac.ptr, mac.len))
{
- failed = TRUE;
+ goto failure;
}
/* signature to existing buffer */
memset(mac.ptr, 0, mac.len);
- signer->get_signature(signer, data, mac.ptr);
+ if (!signer->get_signature(signer, data, mac.ptr))
+ {
+ goto failure;
+ }
if (!memeq(vector->mac, mac.ptr, mac.len))
{
- failed = TRUE;
+ goto failure;
}
/* signature verification, good case */
if (!signer->verify_signature(signer, data, mac))
{
- failed = TRUE;
+ goto failure;
}
/* signature verification, bad case */
*(mac.ptr + mac.len - 1) += 1;
if (signer->verify_signature(signer, data, mac))
{
- failed = TRUE;
+ goto failure;
}
/* signature to existing buffer, using append mode */
if (data.len > 2)
{
- signer->allocate_signature(signer, chunk_create(data.ptr, 1), NULL);
- signer->get_signature(signer, chunk_create(data.ptr + 1, 1), NULL);
+ if (!signer->allocate_signature(signer,
+ chunk_create(data.ptr, 1), NULL))
+ {
+ goto failure;
+ }
+ if (!signer->get_signature(signer,
+ chunk_create(data.ptr + 1, 1), NULL))
+ {
+ goto failure;
+ }
if (!signer->verify_signature(signer, chunk_skip(data, 2),
chunk_create(vector->mac, mac.len)))
{
- failed = TRUE;
+ goto failure;
}
}
- free(mac.ptr);
+ failed = FALSE;
+failure:
signer->destroy(signer);
+ chunk_free(&mac);
if (failed)
{
DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
@@ -627,8 +689,10 @@ static u_int bench_hasher(private_crypto_tester_t *this,
start_timing(&start);
while (end_timing(&start) < this->bench_time)
{
- hasher->get_hash(hasher, buf, hash);
- runs++;
+ if (hasher->get_hash(hasher, buf, hash))
+ {
+ runs++;
+ }
}
free(buf.ptr);
hasher->destroy(hasher);
@@ -659,50 +723,73 @@ METHOD(crypto_tester_t, test_hasher, bool,
}
tested++;
+ failed = TRUE;
hasher = create(alg);
if (!hasher)
{
DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
hash_algorithm_names, alg, plugin_name);
- failed = TRUE;
break;
}
- failed = FALSE;
-
/* allocated hash */
data = chunk_create(vector->data, vector->len);
- hasher->allocate_hash(hasher, data, &hash);
+ if (!hasher->allocate_hash(hasher, data, &hash))
+ {
+ goto failure;
+ }
if (hash.len != hasher->get_hash_size(hasher))
{
- failed = TRUE;
+ goto failure;
}
if (!memeq(vector->hash, hash.ptr, hash.len))
{
- failed = TRUE;
+ goto failure;
}
- /* hash to existing buffer */
+ /* hash to existing buffer, with a reset */
memset(hash.ptr, 0, hash.len);
- hasher->get_hash(hasher, data, hash.ptr);
+ if (!hasher->get_hash(hasher, data, NULL))
+ {
+ goto failure;
+ }
+ if (!hasher->reset(hasher))
+ {
+ goto failure;
+ }
+ if (!hasher->get_hash(hasher, data, hash.ptr))
+ {
+ goto failure;
+ }
if (!memeq(vector->hash, hash.ptr, hash.len))
{
- failed = TRUE;
+ goto failure;
}
/* hasher to existing buffer, using append mode */
if (data.len > 2)
{
memset(hash.ptr, 0, hash.len);
- hasher->allocate_hash(hasher, chunk_create(data.ptr, 1), NULL);
- hasher->get_hash(hasher, chunk_create(data.ptr + 1, 1), NULL);
- hasher->get_hash(hasher, chunk_skip(data, 2), hash.ptr);
+ if (!hasher->allocate_hash(hasher, chunk_create(data.ptr, 1), NULL))
+ {
+ goto failure;
+ }
+ if (!hasher->get_hash(hasher, chunk_create(data.ptr + 1, 1), NULL))
+ {
+ goto failure;
+ }
+ if (!hasher->get_hash(hasher, chunk_skip(data, 2), hash.ptr))
+ {
+ goto failure;
+ }
if (!memeq(vector->hash, hash.ptr, hash.len))
{
- failed = TRUE;
+ goto failure;
}
}
- free(hash.ptr);
+ failed = FALSE;
+failure:
hasher->destroy(hasher);
+ chunk_free(&hash);
if (failed)
{
DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
@@ -746,11 +833,18 @@ static u_int bench_prf(private_crypto_tester_t *this,
prf = create(alg);
if (prf)
{
- char bytes[prf->get_block_size(prf)];
+ char bytes[prf->get_block_size(prf)], key[prf->get_block_size(prf)];
chunk_t buf;
struct timespec start;
u_int runs;
+ memset(key, 0x56, prf->get_block_size(prf));
+ if (!prf->set_key(prf, chunk_create(key, prf->get_block_size(prf))))
+ {
+ prf->destroy(prf);
+ return 0;
+ }
+
buf = chunk_alloc(this->bench_size);
memset(buf.ptr, 0x34, buf.len);
@@ -758,8 +852,10 @@ static u_int bench_prf(private_crypto_tester_t *this,
start_timing(&start);
while (end_timing(&start) < this->bench_time)
{
- prf->get_bytes(prf, buf, bytes);
- runs++;
+ if (prf->get_bytes(prf, buf, bytes))
+ {
+ runs++;
+ }
}
free(buf.ptr);
prf->destroy(prf);
@@ -782,7 +878,7 @@ METHOD(crypto_tester_t, test_prf, bool,
while (enumerator->enumerate(enumerator, &vector))
{
prf_t *prf;
- chunk_t key, seed, out;
+ chunk_t key, seed, out = chunk_empty;
if (vector->alg != alg)
{
@@ -790,41 +886,50 @@ METHOD(crypto_tester_t, test_prf, bool,
}
tested++;
+ failed = TRUE;
prf = create(alg);
if (!prf)
{
DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
pseudo_random_function_names, alg, plugin_name);
- failed = TRUE;
break;
}
- failed = FALSE;
-
key = chunk_create(vector->key, vector->key_size);
- prf->set_key(prf, key);
-
+ if (!prf->set_key(prf, key))
+ {
+ goto failure;
+ }
/* allocated bytes */
seed = chunk_create(vector->seed, vector->len);
- prf->allocate_bytes(prf, seed, &out);
+ if (!prf->allocate_bytes(prf, seed, &out))
+ {
+ goto failure;
+ }
if (out.len != prf->get_block_size(prf))
{
- failed = TRUE;
+ goto failure;
}
if (!memeq(vector->out, out.ptr, out.len))
{
- failed = TRUE;
+ goto failure;
}
/* bytes to existing buffer */
memset(out.ptr, 0, out.len);
if (vector->stateful)
{
- prf->set_key(prf, key);
+ if (!prf->set_key(prf, key))
+ {
+ goto failure;
+ }
+ }
+ if (!prf->get_bytes(prf, seed, out.ptr))
+ {
+ goto failure;
}
- prf->get_bytes(prf, seed, out.ptr);
if (!memeq(vector->out, out.ptr, out.len))
{
- failed = TRUE;
+ goto failure;
}
/* bytes to existing buffer, using append mode */
if (seed.len > 2)
@@ -832,19 +937,33 @@ METHOD(crypto_tester_t, test_prf, bool,
memset(out.ptr, 0, out.len);
if (vector->stateful)
{
- prf->set_key(prf, key);
+ if (!prf->set_key(prf, key))
+ {
+ goto failure;
+ }
+ }
+ if (!prf->allocate_bytes(prf, chunk_create(seed.ptr, 1), NULL))
+ {
+ goto failure;
+ }
+ if (!prf->get_bytes(prf, chunk_create(seed.ptr + 1, 1), NULL))
+ {
+ goto failure;
+ }
+ if (!prf->get_bytes(prf, chunk_skip(seed, 2), out.ptr))
+ {
+ goto failure;
}
- prf->allocate_bytes(prf, chunk_create(seed.ptr, 1), NULL);
- prf->get_bytes(prf, chunk_create(seed.ptr + 1, 1), NULL);
- prf->get_bytes(prf, chunk_skip(seed, 2), out.ptr);
if (!memeq(vector->out, out.ptr, out.len))
{
- failed = TRUE;
+ goto failure;
}
}
- free(out.ptr);
+ failed = FALSE;
+failure:
prf->destroy(prf);
+ chunk_free(&out);
if (failed)
{
DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
@@ -897,7 +1016,11 @@ static u_int bench_rng(private_crypto_tester_t *this,
start_timing(&start);
while (end_timing(&start) < this->bench_time)
{
- rng->get_bytes(rng, buf.len, buf.ptr);
+ if (!rng->get_bytes(rng, buf.len, buf.ptr))
+ {
+ runs = 0;
+ break;
+ }
runs++;
}
free(buf.ptr);
@@ -927,8 +1050,8 @@ METHOD(crypto_tester_t, test_rng, bool,
enumerator = this->rng->create_enumerator(this->rng);
while (enumerator->enumerate(enumerator, &vector))
{
+ chunk_t data = chunk_empty;
rng_t *rng;
- chunk_t data;
if (vector->quality != quality)
{
@@ -936,37 +1059,37 @@ METHOD(crypto_tester_t, test_rng, bool,
}
tested++;
+ failed = TRUE;
rng = create(quality);
if (!rng)
{
DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
rng_quality_names, quality, plugin_name);
- failed = TRUE;
break;
}
- failed = FALSE;
-
/* allocated bytes */
- rng->allocate_bytes(rng, vector->len, &data);
- if (data.len != vector->len)
+ if (!rng->allocate_bytes(rng, vector->len, &data) ||
+ data.len != vector->len ||
+ !vector->test(vector->user, data))
{
- failed = TRUE;
+ goto failure;
}
- if (!vector->test(vector->user, data))
+ /* write bytes into existing buffer */
+ memset(data.ptr, 0, data.len);
+ if (!rng->get_bytes(rng, vector->len, data.ptr))
{
- failed = TRUE;
+ goto failure;
}
- /* bytes to existing buffer */
- memset(data.ptr, 0, data.len);
- rng->get_bytes(rng, vector->len, data.ptr);
if (!vector->test(vector->user, data))
{
- failed = TRUE;
+ goto failure;
}
- free(data.ptr);
+ failed = FALSE;
+failure:
rng->destroy(rng);
+ chunk_free(&data);
if (failed)
{
DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
diff --git a/src/libstrongswan/crypto/hashers/hasher.c b/src/libstrongswan/crypto/hashers/hasher.c
index 81750a519..dc73d5223 100644
--- a/src/libstrongswan/crypto/hashers/hasher.c
+++ b/src/libstrongswan/crypto/hashers/hasher.c
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2005 Jan Hutter
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2005-2006 Martin Willi
- *
+ * Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -32,6 +32,19 @@ ENUM(hash_algorithm_names, HASH_UNKNOWN, HASH_SHA512,
"HASH_SHA512"
);
+ENUM(hash_algorithm_short_names, HASH_UNKNOWN, HASH_SHA512,
+ "unknown",
+ "preferred",
+ "md2",
+ "md4",
+ "md5",
+ "sha1",
+ "sha224",
+ "sha256",
+ "sha384",
+ "sha512"
+);
+
/*
* Described in header.
*/
@@ -68,6 +81,105 @@ hash_algorithm_t hasher_algorithm_from_oid(int oid)
/*
* Described in header.
*/
+hash_algorithm_t hasher_algorithm_from_prf(pseudo_random_function_t alg)
+{
+ switch (alg)
+ {
+ case PRF_HMAC_MD5:
+ return HASH_MD5;
+ case PRF_HMAC_SHA1:
+ case PRF_FIPS_SHA1_160:
+ case PRF_KEYED_SHA1:
+ return HASH_SHA1;
+ case PRF_HMAC_SHA2_256:
+ return HASH_SHA256;
+ case PRF_HMAC_SHA2_384:
+ return HASH_SHA384;
+ case PRF_HMAC_SHA2_512:
+ return HASH_SHA512;
+ case PRF_HMAC_TIGER:
+ case PRF_AES128_XCBC:
+ case PRF_AES128_CMAC:
+ case PRF_FIPS_DES:
+ case PRF_CAMELLIA128_XCBC:
+ case PRF_UNDEFINED:
+ break;
+ }
+ return HASH_UNKNOWN;
+}
+
+/*
+ * Described in header.
+ */
+hash_algorithm_t hasher_algorithm_from_integrity(integrity_algorithm_t alg,
+ size_t *length)
+{
+ if (length)
+ {
+ switch (alg)
+ {
+ case AUTH_HMAC_MD5_96:
+ case AUTH_HMAC_SHA1_96:
+ case AUTH_HMAC_SHA2_256_96:
+ *length = 12;
+ break;
+ case AUTH_HMAC_MD5_128:
+ case AUTH_HMAC_SHA1_128:
+ case AUTH_HMAC_SHA2_256_128:
+ *length = 16;
+ break;
+ case AUTH_HMAC_SHA1_160:
+ *length = 20;
+ break;
+ case AUTH_HMAC_SHA2_384_192:
+ *length = 24;
+ break;
+ case AUTH_HMAC_SHA2_256_256:
+ case AUTH_HMAC_SHA2_512_256:
+ *length = 32;
+ break;
+ case AUTH_HMAC_SHA2_384_384:
+ *length = 48;
+ break;
+ default:
+ break;
+ }
+ }
+ switch (alg)
+ {
+ case AUTH_HMAC_MD5_96:
+ case AUTH_HMAC_MD5_128:
+ case AUTH_KPDK_MD5:
+ return HASH_MD5;
+ case AUTH_HMAC_SHA1_96:
+ case AUTH_HMAC_SHA1_128:
+ case AUTH_HMAC_SHA1_160:
+ return HASH_SHA1;
+ case AUTH_HMAC_SHA2_256_96:
+ case AUTH_HMAC_SHA2_256_128:
+ case AUTH_HMAC_SHA2_256_256:
+ return HASH_SHA256;
+ case AUTH_HMAC_SHA2_384_192:
+ case AUTH_HMAC_SHA2_384_384:
+ return HASH_SHA384;
+ case AUTH_HMAC_SHA2_512_256:
+ return HASH_SHA512;
+ case AUTH_AES_CMAC_96:
+ case AUTH_AES_128_GMAC:
+ case AUTH_AES_192_GMAC:
+ case AUTH_AES_256_GMAC:
+ case AUTH_AES_XCBC_96:
+ case AUTH_DES_MAC:
+ case AUTH_CAMELLIA_XCBC_96:
+ case AUTH_UNDEFINED:
+ break;
+ }
+ return HASH_UNKNOWN;
+}
+
+/*
+ * Described in header.
+ */
int hasher_algorithm_to_oid(hash_algorithm_t alg)
{
int oid;
diff --git a/src/libstrongswan/crypto/hashers/hasher.h b/src/libstrongswan/crypto/hashers/hasher.h
index 9fa043c7e..759f6a23c 100644
--- a/src/libstrongswan/crypto/hashers/hasher.h
+++ b/src/libstrongswan/crypto/hashers/hasher.h
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2005 Jan Hutter
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2005-2006 Martin Willi
- *
+ * Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -27,6 +27,8 @@ typedef enum hash_algorithm_t hash_algorithm_t;
typedef struct hasher_t hasher_t;
#include <library.h>
+#include <crypto/prfs/prf.h>
+#include <crypto/signers/signer.h>
#include <credentials/keys/public_key.h>
/**
@@ -62,9 +64,15 @@ enum hash_algorithm_t {
extern enum_name_t *hash_algorithm_names;
/**
+ * Short names for hash_algorithm_names
+ */
+extern enum_name_t *hash_algorithm_short_names;
+
+/**
* Generic interface for all hash functions.
*/
struct hasher_t {
+
/**
* Hash data and write it in the buffer.
*
@@ -77,8 +85,10 @@ struct hasher_t {
*
* @param data data to hash
* @param hash pointer where the hash will be written
+ * @return TRUE if hash created successfully
*/
- void (*get_hash) (hasher_t *this, chunk_t data, u_int8_t *hash);
+ bool (*get_hash)(hasher_t *this, chunk_t data,
+ u_int8_t *hash) __attribute__((warn_unused_result));
/**
* Hash data and allocate space for the hash.
@@ -89,36 +99,61 @@ struct hasher_t {
*
* @param data chunk with data to hash
* @param hash chunk which will hold allocated hash
+ * @return TRUE if hash allocated successfully
*/
- void (*allocate_hash) (hasher_t *this, chunk_t data, chunk_t *hash);
+ bool (*allocate_hash)(hasher_t *this, chunk_t data,
+ chunk_t *hash) __attribute__((warn_unused_result));
/**
* Get the size of the resulting hash.
*
* @return hash size in bytes
*/
- size_t (*get_hash_size) (hasher_t *this);
+ size_t (*get_hash_size)(hasher_t *this);
/**
- * Resets the hashers state.
+ * Resets the hasher's state.
+ *
+ * @return TRUE if hasher reset successfully
*/
- void (*reset) (hasher_t *this);
+ bool (*reset)(hasher_t *this) __attribute__((warn_unused_result));
/**
* Destroys a hasher object.
*/
- void (*destroy) (hasher_t *this);
+ void (*destroy)(hasher_t *this);
};
/**
* Conversion of ASN.1 OID to hash algorithm.
*
* @param oid ASN.1 OID
- * @return hash algorithm, HASH_UNKNOWN if OID unsuported
+ * @return hash algorithm, HASH_UNKNOWN if OID unsupported
*/
hash_algorithm_t hasher_algorithm_from_oid(int oid);
/**
+ * Conversion of PRF algorithm to hash algorithm (if based on one).
+ *
+ * @param alg prf algorithm
+ * @return hash algorithm, HASH_UNKNOWN if not based on a hash
+ */
+hash_algorithm_t hasher_algorithm_from_prf(pseudo_random_function_t alg);
+
+/**
+ * Conversion of integrity algorithm to hash algorithm (if based on one).
+ *
+ * If length is not NULL the length of the resulting signature is returned,
+ * which might be smaller than the output size of the underlying hash.
+ *
+ * @param alg integrity algorithm
+ * @param length returns signature length, if not NULL
+ * @return hash algorithm, HASH_UNKNOWN if not based on a hash
+ */
+hash_algorithm_t hasher_algorithm_from_integrity(integrity_algorithm_t alg,
+ size_t *length);
+
+/**
* Conversion of hash algorithm into ASN.1 OID.
*
* @param alg hash algorithm
diff --git a/src/libstrongswan/crypto/mac.h b/src/libstrongswan/crypto/mac.h
new file mode 100644
index 000000000..f7b43ba39
--- /dev/null
+++ b/src/libstrongswan/crypto/mac.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2005-2008 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup mac mac
+ * @{ @ingroup crypto
+ */
+
+#ifndef MAC_H_
+#define MAC_H_
+
+typedef struct mac_t mac_t;
+
+#include <library.h>
+
+/**
+ * Generic interface for message authentication codes.
+ *
+ * Classes implementing this interface can use the PRF and signer wrappers.
+ */
+struct mac_t {
+
+ /**
+ * Generate message authentication code.
+ *
+ * If out is NULL, no result is given back. A next call will
+ * append the data to already supplied data. If out is not NULL,
+ * the mac of all apended data is calculated, written to out and the
+ * internal state is reset.
+ *
+ * @param data chunk of data to authenticate
+ * @param out pointer where the generated bytes will be written
+ * @return TRUE if mac generated successfully
+ */
+ bool (*get_mac)(mac_t *this, chunk_t data,
+ u_int8_t *out) __attribute__((warn_unused_result));
+
+ /**
+ * Get the size of the resulting MAC.
+ *
+ * @return block size in bytes
+ */
+ size_t (*get_mac_size)(mac_t *this);
+
+ /**
+ * Set the key to be used for the MAC.
+ *
+ * Any key length must be accepted.
+ *
+ * @param key key to set
+ * @return TRUE if key set successfully
+ */
+ bool (*set_key)(mac_t *this,
+ chunk_t key) __attribute__((warn_unused_result));
+
+ /**
+ * Destroys a mac_t object.
+ */
+ void (*destroy) (mac_t *this);
+};
+
+#endif /** MAC_H_ @}*/
diff --git a/src/libstrongswan/crypto/nonce_gen.h b/src/libstrongswan/crypto/nonce_gen.h
new file mode 100644
index 000000000..50f3c0090
--- /dev/null
+++ b/src/libstrongswan/crypto/nonce_gen.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+/**
+ * @defgroup nonce_gen nonce_gen
+ * @{ @ingroup crypto
+ */
+
+#ifndef NONCE_GEN_H_
+#define NONCE_GEN_H_
+
+typedef struct nonce_gen_t nonce_gen_t;
+
+#include <library.h>
+
+/**
+ * Generic interface for nonce generators.
+ */
+struct nonce_gen_t {
+
+ /**
+ * Generates a nonce and writes it into the buffer.
+ *
+ * @param size size of nonce in bytes
+ * @param buffer pointer where the generated nonce will be written
+ * @return TRUE if nonce allocation was succesful, FALSE otherwise
+ */
+ bool (*get_nonce)(nonce_gen_t *this, size_t size,
+ u_int8_t *buffer) __attribute__((warn_unused_result));
+
+ /**
+ * Generates a nonce and allocates space for it.
+ *
+ * @param size size of nonce in bytes
+ * @param chunk chunk which will hold the generated nonce
+ * @return TRUE if nonce allocation was succesful, FALSE otherwise
+ */
+ bool (*allocate_nonce)(nonce_gen_t *this, size_t size,
+ chunk_t *chunk) __attribute__((warn_unused_result));
+
+ /**
+ * Destroys a nonce generator object.
+ */
+ void (*destroy)(nonce_gen_t *this);
+};
+
+#endif /** NONCE_GEN_H_ @}*/
diff --git a/src/libstrongswan/crypto/pkcs7.c b/src/libstrongswan/crypto/pkcs7.c
new file mode 100644
index 000000000..0ec19f2cd
--- /dev/null
+++ b/src/libstrongswan/crypto/pkcs7.c
@@ -0,0 +1,1061 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2002-2008 Andreas Steffen
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Hochschule fuer Technik Rapperswil, Switzerland
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <library.h>
+#include <debug.h>
+
+#include <asn1/oid.h>
+#include <asn1/asn1.h>
+#include <asn1/asn1_parser.h>
+#include <credentials/certificates/x509.h>
+#include <credentials/keys/public_key.h>
+#include <crypto/pkcs9.h>
+#include <crypto/hashers/hasher.h>
+#include <crypto/crypters/crypter.h>
+#include <utils/linked_list.h>
+
+#include "pkcs7.h"
+
+typedef struct private_pkcs7_t private_pkcs7_t;
+
+/**
+ * Private data of a pkcs7_t object.
+ */
+struct private_pkcs7_t {
+ /**
+ * Public interface for this certificate.
+ */
+ pkcs7_t public;
+
+ /**
+ * contentInfo type
+ */
+ int type;
+
+ /**
+ * ASN.1 encoded content
+ */
+ chunk_t content;
+
+ /**
+ * ASN.1 parsing start level
+ */
+ u_int level;
+
+ /**
+ * retrieved data
+ */
+ chunk_t data;
+
+ /**
+ * ASN.1 encoded attributes
+ */
+ pkcs9_t *attributes;
+
+ /**
+ * Linked list of X.509 certificates
+ */
+ linked_list_t *certs;
+};
+
+METHOD(pkcs7_t, is_data, bool,
+ private_pkcs7_t *this)
+{
+ return this->type == OID_PKCS7_DATA;
+}
+
+METHOD(pkcs7_t, is_signedData, bool,
+ private_pkcs7_t *this)
+{
+ return this->type == OID_PKCS7_SIGNED_DATA;
+}
+
+METHOD(pkcs7_t, is_envelopedData, bool,
+ private_pkcs7_t *this)
+{
+ return this->type == OID_PKCS7_ENVELOPED_DATA;
+}
+
+/**
+ * ASN.1 definition of the PKCS#7 ContentInfo type
+ */
+static const asn1Object_t contentInfoObjects[] = {
+ { 0, "contentInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
+ { 1, "contentType", ASN1_OID, ASN1_BODY }, /* 1 */
+ { 1, "content", ASN1_CONTEXT_C_0, ASN1_OPT |
+ ASN1_BODY }, /* 2 */
+ { 1, "end opt", ASN1_EOC, ASN1_END }, /* 3 */
+ { 0, "exit", ASN1_EOC, ASN1_EXIT }
+};
+#define PKCS7_INFO_TYPE 1
+#define PKCS7_INFO_CONTENT 2
+
+/**
+ * Parse PKCS#7 contentInfo object
+ */
+static bool parse_contentInfo(private_pkcs7_t *this)
+{
+ asn1_parser_t *parser;
+ chunk_t object;
+ int objectID;
+ bool success = FALSE;
+
+ if (!this->data.ptr)
+ {
+ return FALSE;
+ }
+
+ parser = asn1_parser_create(contentInfoObjects, this->data);
+ parser->set_top_level(parser, this->level);
+
+ while (parser->iterate(parser, &objectID, &object))
+ {
+ if (objectID == PKCS7_INFO_TYPE)
+ {
+ this->type = asn1_known_oid(object);
+ if (this->type < OID_PKCS7_DATA ||
+ this->type > OID_PKCS7_ENCRYPTED_DATA)
+ {
+ DBG1(DBG_LIB, "unknown pkcs7 content type");
+ goto end;
+ }
+ }
+ else if (objectID == PKCS7_INFO_CONTENT && object.len > 0)
+ {
+ chunk_free(&this->content);
+ this->content = chunk_clone(object);
+ }
+ }
+ success = parser->success(parser);
+
+ if (success)
+ {
+ this->level += 2;
+ chunk_free(&this->data);
+ }
+
+end:
+ parser->destroy(parser);
+ return success;
+}
+
+/**
+ * Check whether to abort the requested parsing
+ */
+static bool abort_parsing(private_pkcs7_t *this, int type)
+{
+ if (this->type != type)
+ {
+ DBG1(DBG_LIB, "pkcs7 content to be parsed is not of type '%s'",
+ oid_names[type].name);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+METHOD(pkcs7_t, parse_data, bool,
+ private_pkcs7_t *this)
+{
+ chunk_t data;
+
+ if (!parse_contentInfo(this) ||
+ abort_parsing(this, OID_PKCS7_DATA))
+ {
+ return FALSE;
+ }
+ data = this->content;
+ if (data.len == 0)
+ {
+ this->data = chunk_empty;
+ return TRUE;
+ }
+ if (asn1_parse_simple_object(&data, ASN1_OCTET_STRING,
+ this->level, "data"))
+ {
+ this->data = chunk_clone(data);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * ASN.1 definition of the PKCS#7 signedData type
+ */
+static const asn1Object_t signedDataObjects[] = {
+ { 0, "signedData", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
+ { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
+ { 1, "digestAlgorithms", ASN1_SET, ASN1_LOOP }, /* 2 */
+ { 2, "algorithm", ASN1_EOC, ASN1_RAW }, /* 3 */
+ { 1, "end loop", ASN1_EOC, ASN1_END }, /* 4 */
+ { 1, "contentInfo", ASN1_EOC, ASN1_RAW }, /* 5 */
+ { 1, "certificates", ASN1_CONTEXT_C_0, ASN1_OPT |
+ ASN1_LOOP }, /* 6 */
+ { 2, "certificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 7 */
+ { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 8 */
+ { 1, "crls", ASN1_CONTEXT_C_1, ASN1_OPT |
+ ASN1_LOOP }, /* 9 */
+ { 2, "crl", ASN1_SEQUENCE, ASN1_OBJ }, /* 10 */
+ { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 11 */
+ { 1, "signerInfos", ASN1_SET, ASN1_LOOP }, /* 12 */
+ { 2, "signerInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 13 */
+ { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 14 */
+ { 3, "issuerAndSerialNumber", ASN1_SEQUENCE, ASN1_BODY }, /* 15 */
+ { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 16 */
+ { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 17 */
+ { 3, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 18 */
+ { 3, "authenticatedAttributes", ASN1_CONTEXT_C_0, ASN1_OPT |
+ ASN1_OBJ }, /* 19 */
+ { 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */
+ { 3, "digestEncryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 21 */
+ { 3, "encryptedDigest", ASN1_OCTET_STRING, ASN1_BODY }, /* 22 */
+ { 3, "unauthenticatedAttributes", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 23 */
+ { 3, "end opt", ASN1_EOC, ASN1_END }, /* 24 */
+ { 1, "end loop", ASN1_EOC, ASN1_END }, /* 25 */
+ { 0, "exit", ASN1_EOC, ASN1_EXIT }
+};
+#define PKCS7_SIGNED_VERSION 1
+#define PKCS7_DIGEST_ALG 3
+#define PKCS7_SIGNED_CONTENT_INFO 5
+#define PKCS7_SIGNED_CERT 7
+#define PKCS7_SIGNER_INFO 13
+#define PKCS7_SIGNER_INFO_VERSION 14
+#define PKCS7_SIGNED_ISSUER 16
+#define PKCS7_SIGNED_SERIAL_NUMBER 17
+#define PKCS7_DIGEST_ALGORITHM 18
+#define PKCS7_AUTH_ATTRIBUTES 19
+#define PKCS7_DIGEST_ENC_ALGORITHM 21
+#define PKCS7_ENCRYPTED_DIGEST 22
+
+METHOD(pkcs7_t, parse_signedData, bool,
+ private_pkcs7_t *this, certificate_t *cacert)
+{
+ asn1_parser_t *parser;
+ chunk_t object;
+ int objectID, version;
+ int digest_alg = OID_UNKNOWN;
+ int enc_alg = OID_UNKNOWN;
+ int signerInfos = 0;
+ bool success = FALSE;
+
+ chunk_t encrypted_digest = chunk_empty;
+
+ if (!parse_contentInfo(this) ||
+ abort_parsing(this, OID_PKCS7_SIGNED_DATA))
+ {
+ return FALSE;
+ }
+
+ parser = asn1_parser_create(signedDataObjects, this->content);
+ parser->set_top_level(parser, this->level);
+
+ while (parser->iterate(parser, &objectID, &object))
+ {
+ u_int level = parser->get_level(parser);
+
+ switch (objectID)
+ {
+ case PKCS7_SIGNED_VERSION:
+ version = object.len ? (int)*object.ptr : 0;
+ DBG2(DBG_LIB, " v%d", version);
+ break;
+ case PKCS7_DIGEST_ALG:
+ digest_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
+ break;
+ case PKCS7_SIGNED_CONTENT_INFO:
+ {
+ pkcs7_t *data = pkcs7_create_from_chunk(object, level+1);
+
+ if (!data || !data->parse_data(data))
+ {
+ DESTROY_IF(data);
+ goto end;
+ }
+ this->data = chunk_clone(data->get_data(data));
+ data->destroy(data);
+ break;
+ }
+ case PKCS7_SIGNED_CERT:
+ {
+ certificate_t *cert;
+
+ DBG2(DBG_LIB, " parsing pkcs7-wrapped certificate");
+ cert = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_X509,
+ BUILD_BLOB_ASN1_DER, object,
+ BUILD_END);
+ if (cert)
+ {
+ this->certs->insert_last(this->certs, cert);
+ }
+ break;
+ }
+ case PKCS7_SIGNER_INFO:
+ signerInfos++;
+ DBG2(DBG_LIB, " signer #%d", signerInfos);
+ break;
+ case PKCS7_SIGNER_INFO_VERSION:
+ version = object.len ? (int)*object.ptr : 0;
+ DBG2(DBG_LIB, " v%d", version);
+ break;
+ case PKCS7_SIGNED_ISSUER:
+ {
+ identification_t *issuer;
+
+ issuer = identification_create_from_encoding(ID_DER_ASN1_DN, object);
+ DBG2(DBG_LIB, " '%Y'", issuer);
+ issuer->destroy(issuer);
+ break;
+ }
+ case PKCS7_AUTH_ATTRIBUTES:
+ *object.ptr = ASN1_SET;
+ this->attributes = pkcs9_create_from_chunk(object, level+1);
+ *object.ptr = ASN1_CONTEXT_C_0;
+ break;
+ case PKCS7_DIGEST_ALGORITHM:
+ digest_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
+ break;
+ case PKCS7_DIGEST_ENC_ALGORITHM:
+ enc_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
+ break;
+ case PKCS7_ENCRYPTED_DIGEST:
+ encrypted_digest = object;
+ }
+ }
+ success = parser->success(parser);
+
+end:
+ parser->destroy(parser);
+ if (!success)
+ {
+ return FALSE;
+ }
+
+ /* check the signature only if a cacert is available */
+ if (cacert != NULL)
+ {
+ signature_scheme_t scheme;
+ public_key_t *key;
+
+ scheme = signature_scheme_from_oid(digest_alg);
+ if (scheme == SIGN_UNKNOWN)
+ {
+ DBG1(DBG_LIB, "unsupported signature scheme");
+ return FALSE;
+ }
+ if (signerInfos == 0)
+ {
+ DBG1(DBG_LIB, "no signerInfo object found");
+ return FALSE;
+ }
+ else if (signerInfos > 1)
+ {
+ DBG1(DBG_LIB, "more than one signerInfo object found");
+ return FALSE;
+ }
+ if (this->attributes == NULL)
+ {
+ DBG1(DBG_LIB, "no authenticatedAttributes object found");
+ return FALSE;
+ }
+ if (enc_alg != OID_RSA_ENCRYPTION)
+ {
+ DBG1(DBG_LIB, "only RSA digest encryption supported");
+ return FALSE;
+ }
+
+ /* verify the signature */
+ key = cacert->get_public_key(cacert);
+ if (key == NULL)
+ {
+ DBG1(DBG_LIB, "no public key found in CA certificate");
+ return FALSE;
+ }
+ if (key->verify(key, scheme,
+ this->attributes->get_encoding(this->attributes), encrypted_digest))
+ {
+ DBG2(DBG_LIB, "signature is valid");
+ }
+ else
+ {
+ DBG1(DBG_LIB, "invalid signature");
+ key->destroy(key);
+ return FALSE;
+ }
+ key->destroy(key);
+
+ if (this->data.ptr != NULL)
+ {
+ chunk_t messageDigest;
+
+ messageDigest = this->attributes->get_attribute(this->attributes,
+ OID_PKCS9_MESSAGE_DIGEST);
+ if (messageDigest.ptr == NULL)
+ {
+ DBG1(DBG_LIB, "messageDigest attribute not found");
+ return FALSE;
+ }
+ else
+ {
+ hash_algorithm_t algorithm;
+ hasher_t *hasher;
+ chunk_t hash;
+ bool valid;
+
+ algorithm = hasher_algorithm_from_oid(digest_alg);
+ hasher = lib->crypto->create_hasher(lib->crypto, algorithm);
+ if (!hasher || !hasher->allocate_hash(hasher, this->data, &hash))
+ {
+ DESTROY_IF(hasher);
+ DBG1(DBG_LIB, "hash algorithm %N not supported",
+ hash_algorithm_names, algorithm);
+ return FALSE;
+ }
+ hasher->destroy(hasher);
+ DBG3(DBG_LIB, "hash: %B", &hash);
+
+ valid = chunk_equals(messageDigest, hash);
+ free(hash.ptr);
+ if (valid)
+ {
+ DBG2(DBG_LIB, "messageDigest is valid");
+ }
+ else
+ {
+ DBG1(DBG_LIB, "invalid messageDigest");
+ return FALSE;
+ }
+ }
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * ASN.1 definition of the PKCS#7 envelopedData type
+ */
+static const asn1Object_t envelopedDataObjects[] = {
+ { 0, "envelopedData", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
+ { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
+ { 1, "recipientInfos", ASN1_SET, ASN1_LOOP }, /* 2 */
+ { 2, "recipientInfo", ASN1_SEQUENCE, ASN1_BODY }, /* 3 */
+ { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 4 */
+ { 3, "issuerAndSerialNumber", ASN1_SEQUENCE, ASN1_BODY }, /* 5 */
+ { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 6 */
+ { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 7 */
+ { 3, "encryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 8 */
+ { 3, "encryptedKey", ASN1_OCTET_STRING, ASN1_BODY }, /* 9 */
+ { 1, "end loop", ASN1_EOC, ASN1_END }, /* 10 */
+ { 1, "encryptedContentInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 11 */
+ { 2, "contentType", ASN1_OID, ASN1_BODY }, /* 12 */
+ { 2, "contentEncryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 13 */
+ { 2, "encryptedContent", ASN1_CONTEXT_S_0, ASN1_BODY }, /* 14 */
+ { 0, "exit", ASN1_EOC, ASN1_EXIT }
+};
+#define PKCS7_ENVELOPED_VERSION 1
+#define PKCS7_RECIPIENT_INFO_VERSION 4
+#define PKCS7_ISSUER 6
+#define PKCS7_SERIAL_NUMBER 7
+#define PKCS7_ENCRYPTION_ALG 8
+#define PKCS7_ENCRYPTED_KEY 9
+#define PKCS7_CONTENT_TYPE 12
+#define PKCS7_CONTENT_ENC_ALGORITHM 13
+#define PKCS7_ENCRYPTED_CONTENT 14
+
+METHOD(pkcs7_t, parse_envelopedData, bool,
+ private_pkcs7_t *this, chunk_t serialNumber, private_key_t *key)
+{
+ asn1_parser_t *parser;
+ chunk_t object;
+ int objectID, version;
+ bool success = FALSE;
+
+ chunk_t iv = chunk_empty;
+ chunk_t symmetric_key = chunk_empty;
+ chunk_t encrypted_content = chunk_empty;
+
+ crypter_t *crypter = NULL;
+
+ if (!parse_contentInfo(this) ||
+ abort_parsing(this, OID_PKCS7_ENVELOPED_DATA))
+ {
+ return FALSE;
+ }
+
+ parser = asn1_parser_create(envelopedDataObjects, this->content);
+ parser->set_top_level(parser, this->level);
+
+ while (parser->iterate(parser, &objectID, &object))
+ {
+ u_int level = parser->get_level(parser);
+
+ switch (objectID)
+ {
+ case PKCS7_ENVELOPED_VERSION:
+ {
+ version = object.len ? (int)*object.ptr : 0;
+ DBG2(DBG_LIB, " v%d", version);
+ if (version != 0)
+ {
+ DBG1(DBG_LIB, "envelopedData version is not 0");
+ goto end;
+ }
+ break;
+ }
+ case PKCS7_RECIPIENT_INFO_VERSION:
+ {
+ version = object.len ? (int)*object.ptr : 0;
+ DBG2(DBG_LIB, " v%d", version);
+ if (version != 0)
+ {
+ DBG1(DBG_LIB, "recipient info version is not 0");
+ goto end;
+ }
+ break;
+ }
+ case PKCS7_ISSUER:
+ {
+ identification_t *issuer;
+
+ issuer = identification_create_from_encoding(ID_DER_ASN1_DN,
+ object);
+ DBG2(DBG_LIB, " '%Y'", issuer);
+ issuer->destroy(issuer);
+ break;
+ }
+ case PKCS7_SERIAL_NUMBER:
+ {
+ if (!chunk_equals(serialNumber, object))
+ {
+ DBG1(DBG_LIB, "serial numbers do not match");
+ goto end;
+ }
+ break;
+ }
+ case PKCS7_ENCRYPTION_ALG:
+ {
+ int alg;
+
+ alg = asn1_parse_algorithmIdentifier(object, level, NULL);
+ if (alg != OID_RSA_ENCRYPTION)
+ {
+ DBG1(DBG_LIB, "only rsa encryption supported");
+ goto end;
+ }
+ break;
+ }
+ case PKCS7_ENCRYPTED_KEY:
+ {
+ if (!key->decrypt(key, ENCRYPT_RSA_PKCS1, object, &symmetric_key))
+ {
+ DBG1(DBG_LIB, "symmetric key could not be decrypted with rsa");
+ goto end;
+ }
+ DBG4(DBG_LIB, "symmetric key %B", &symmetric_key);
+ break;
+ }
+ case PKCS7_CONTENT_TYPE:
+ {
+ if (asn1_known_oid(object) != OID_PKCS7_DATA)
+ {
+ DBG1(DBG_LIB, "encrypted content not of type pkcs7 data");
+ goto end;
+ }
+ break;
+ }
+ case PKCS7_CONTENT_ENC_ALGORITHM:
+ {
+ encryption_algorithm_t enc_alg;
+ size_t key_size;
+ int alg;
+
+ alg = asn1_parse_algorithmIdentifier(object, level, &iv);
+ enc_alg = encryption_algorithm_from_oid(alg, &key_size);
+ if (enc_alg == ENCR_UNDEFINED)
+ {
+ DBG1(DBG_LIB, "unsupported content encryption algorithm");
+ goto end;
+ }
+ crypter = lib->crypto->create_crypter(lib->crypto, enc_alg,
+ key_size);
+ if (crypter == NULL)
+ {
+ DBG1(DBG_LIB, "crypter %N not available",
+ encryption_algorithm_names, enc_alg);
+ goto end;
+ }
+ if (symmetric_key.len != crypter->get_key_size(crypter))
+ {
+ DBG1(DBG_LIB, "symmetric key length %d is wrong",
+ symmetric_key.len);
+ goto end;
+ }
+ if (!asn1_parse_simple_object(&iv, ASN1_OCTET_STRING,
+ level + 1, "IV"))
+ {
+ DBG1(DBG_LIB, "IV could not be parsed");
+ goto end;
+ }
+ if (iv.len != crypter->get_iv_size(crypter))
+ {
+ DBG1(DBG_LIB, "IV length %d is wrong", iv.len);
+ goto end;
+ }
+ break;
+ }
+ case PKCS7_ENCRYPTED_CONTENT:
+ {
+ encrypted_content = object;
+ break;
+ }
+ }
+ }
+ success = parser->success(parser);
+
+end:
+ parser->destroy(parser);
+ if (!success)
+ {
+ goto failed;
+ }
+ success = FALSE;
+
+ /* decrypt the content */
+ if (!crypter->set_key(crypter, symmetric_key) ||
+ !crypter->decrypt(crypter, encrypted_content, iv, &this->data))
+ {
+ success = FALSE;
+ goto failed;
+ }
+ DBG4(DBG_LIB, "decrypted content with padding: %B", &this->data);
+
+ /* remove the padding */
+ {
+ u_char *pos = this->data.ptr + this->data.len - 1;
+ u_char pattern = *pos;
+ size_t padding = pattern;
+
+ if (padding > this->data.len)
+ {
+ DBG1(DBG_LIB, "padding greater than data length");
+ goto failed;
+ }
+ this->data.len -= padding;
+
+ while (padding-- > 0)
+ {
+ if (*pos-- != pattern)
+ {
+ DBG1(DBG_LIB, "wrong padding pattern");
+ goto failed;
+ }
+ }
+ }
+ success = TRUE;
+
+failed:
+ DESTROY_IF(crypter);
+ chunk_clear(&symmetric_key);
+ if (!success)
+ {
+ chunk_free(&this->data);
+ }
+ return success;
+}
+
+METHOD(pkcs7_t, get_data, chunk_t,
+ private_pkcs7_t *this)
+{
+ return this->data;
+}
+
+METHOD(pkcs7_t, get_contentInfo, chunk_t,
+ private_pkcs7_t *this)
+{
+ chunk_t content_type;
+
+ /* create DER-encoded OID for pkcs7_contentInfo type */
+ switch(this->type)
+ {
+ case OID_PKCS7_DATA:
+ case OID_PKCS7_SIGNED_DATA:
+ case OID_PKCS7_ENVELOPED_DATA:
+ case OID_PKCS7_SIGNED_ENVELOPED_DATA:
+ case OID_PKCS7_DIGESTED_DATA:
+ case OID_PKCS7_ENCRYPTED_DATA:
+ content_type = asn1_build_known_oid(this->type);
+ break;
+ case OID_UNKNOWN:
+ default:
+ DBG1(DBG_LIB, "invalid pkcs7 contentInfo type");
+ return chunk_empty;
+ }
+
+ return this->content.ptr == NULL
+ ? asn1_wrap(ASN1_SEQUENCE, "m", content_type)
+ : asn1_wrap(ASN1_SEQUENCE, "mm", content_type,
+ asn1_simple_object(ASN1_CONTEXT_C_0, this->content));
+}
+
+METHOD(pkcs7_t, create_certificate_enumerator, enumerator_t*,
+ private_pkcs7_t *this)
+{
+ return this->certs->create_enumerator(this->certs);
+}
+
+METHOD(pkcs7_t, set_certificate, void,
+ private_pkcs7_t *this, certificate_t *cert)
+{
+ if (cert)
+ {
+ this->certs->insert_last(this->certs, cert);
+ }
+}
+
+METHOD(pkcs7_t, set_attributes, void,
+ private_pkcs7_t *this, pkcs9_t *attributes)
+{
+ this->attributes = attributes;
+}
+
+METHOD(pkcs7_t, get_attributes, pkcs9_t*,
+ private_pkcs7_t *this)
+{
+ return this->attributes;
+}
+
+/**
+ * build a DER-encoded issuerAndSerialNumber object
+ */
+chunk_t pkcs7_build_issuerAndSerialNumber(certificate_t *cert)
+{
+ identification_t *issuer = cert->get_issuer(cert);
+ chunk_t serial = chunk_empty;
+
+ if (cert->get_type(cert) == CERT_X509)
+ {
+ x509_t *x509 = (x509_t*)cert;
+ serial = x509->get_serial(x509);
+ }
+
+ return asn1_wrap(ASN1_SEQUENCE, "cm",
+ issuer->get_encoding(issuer),
+ asn1_integer("c", serial));
+}
+
+METHOD(pkcs7_t, build_envelopedData, bool,
+ private_pkcs7_t *this, certificate_t *cert, encryption_algorithm_t alg,
+ size_t key_size)
+{
+ chunk_t iv, symmetricKey, protectedKey, in, out;
+ crypter_t *crypter;
+ int alg_oid;
+
+ /* select OID of symmetric encryption algorithm */
+ alg_oid = encryption_algorithm_to_oid(alg, key_size);
+ if (alg_oid == OID_UNKNOWN)
+ {
+ DBG1(DBG_LIB, " encryption algorithm %N not supported",
+ encryption_algorithm_names, alg);
+ return FALSE;
+ }
+ crypter = lib->crypto->create_crypter(lib->crypto, alg, key_size / 8);
+ if (crypter == NULL)
+ {
+ DBG1(DBG_LIB, " could not create crypter for algorithm %N",
+ encryption_algorithm_names, alg);
+ return FALSE;
+ }
+
+ /* generate a true random symmetric encryption key
+ * and a pseudo-random iv
+ */
+ {
+ rng_t *rng;
+
+ rng = lib->crypto->create_rng(lib->crypto, RNG_TRUE);
+ if (!rng || !rng->allocate_bytes(rng, crypter->get_key_size(crypter),
+ &symmetricKey))
+ {
+ DBG1(DBG_LIB, " failed to allocate symmetric encryption key");
+ DESTROY_IF(rng);
+ return FALSE;
+ }
+ DBG4(DBG_LIB, " symmetric encryption key: %B", &symmetricKey);
+ rng->destroy(rng);
+
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ if (!rng || !rng->allocate_bytes(rng, crypter->get_iv_size(crypter),
+ &iv))
+ {
+ DBG1(DBG_LIB, " failed to allocate initialization vector");
+ DESTROY_IF(rng);
+ return FALSE;
+ }
+ DBG4(DBG_LIB, " initialization vector: %B", &iv);
+ rng->destroy(rng);
+ }
+
+ /* pad the data so that the total length becomes
+ * a multiple of the block size
+ */
+ {
+ size_t block_size = crypter->get_block_size(crypter);
+ size_t padding = block_size - this->data.len % block_size;
+
+ in.len = this->data.len + padding;
+ in.ptr = malloc(in.len);
+
+ DBG2(DBG_LIB, " padding %d bytes of data to multiple block size of %d bytes",
+ (int)this->data.len, (int)in.len);
+
+ /* copy data */
+ memcpy(in.ptr, this->data.ptr, this->data.len);
+ /* append padding */
+ memset(in.ptr + this->data.len, padding, padding);
+ }
+ DBG3(DBG_LIB, " padded unencrypted data: %B", &in);
+
+ /* symmetric encryption of data object */
+ if (!crypter->set_key(crypter, symmetricKey) ||
+ !crypter->encrypt(crypter, in, iv, &out))
+ {
+ crypter->destroy(crypter);
+ chunk_clear(&in);
+ chunk_clear(&symmetricKey);
+ chunk_free(&iv);
+ return FALSE;
+ }
+ crypter->destroy(crypter);
+ chunk_clear(&in);
+ DBG3(DBG_LIB, " encrypted data: %B", &out);
+
+ /* protect symmetric key by public key encryption */
+ {
+ public_key_t *key = cert->get_public_key(cert);
+
+ if (key == NULL)
+ {
+ DBG1(DBG_LIB, " public key not found in encryption certificate");
+ chunk_clear(&symmetricKey);
+ chunk_free(&iv);
+ chunk_free(&out);
+ return FALSE;
+ }
+ key->encrypt(key, ENCRYPT_RSA_PKCS1, symmetricKey, &protectedKey);
+ key->destroy(key);
+ chunk_clear(&symmetricKey);
+ }
+
+ /* build pkcs7 enveloped data object */
+ {
+ chunk_t contentEncryptionAlgorithm = asn1_wrap(ASN1_SEQUENCE, "mm",
+ asn1_build_known_oid(alg_oid),
+ asn1_wrap(ASN1_OCTET_STRING, "m", iv));
+
+ chunk_t encryptedContentInfo = asn1_wrap(ASN1_SEQUENCE, "mmm",
+ asn1_build_known_oid(OID_PKCS7_DATA),
+ contentEncryptionAlgorithm,
+ asn1_wrap(ASN1_CONTEXT_S_0, "m", out));
+
+ chunk_t encryptedKey = asn1_wrap(ASN1_OCTET_STRING, "m", protectedKey);
+
+ chunk_t recipientInfo = asn1_wrap(ASN1_SEQUENCE, "cmmm",
+ ASN1_INTEGER_0,
+ pkcs7_build_issuerAndSerialNumber(cert),
+ asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
+ encryptedKey);
+
+ this->content = asn1_wrap(ASN1_SEQUENCE, "cmm",
+ ASN1_INTEGER_0,
+ asn1_wrap(ASN1_SET, "m", recipientInfo),
+ encryptedContentInfo);
+ chunk_free(&this->data);
+ this->type = OID_PKCS7_ENVELOPED_DATA;
+ this->data = get_contentInfo(this);
+ }
+ return TRUE;
+}
+
+METHOD(pkcs7_t, build_signedData, bool,
+ private_pkcs7_t *this, private_key_t *private_key, hash_algorithm_t alg)
+{
+ chunk_t authenticatedAttributes = chunk_empty;
+ chunk_t encryptedDigest = chunk_empty;
+ chunk_t signerInfo, encoding = chunk_empty;
+ signature_scheme_t scheme;
+ int digest_oid;
+ certificate_t *cert;
+
+ if (this->certs->get_first(this->certs, (void**)&cert) != SUCCESS)
+ {
+ DBG1(DBG_LIB, " no pkcs7 signer certificate found");
+ return FALSE;
+ }
+ digest_oid = hasher_algorithm_to_oid(alg);
+ scheme = signature_scheme_from_oid(digest_oid);
+
+ if (this->attributes != NULL)
+ {
+ if (this->data.ptr != NULL)
+ {
+ chunk_t messageDigest, signingTime, attributes;
+ hasher_t *hasher;
+ time_t now;
+
+ hasher = lib->crypto->create_hasher(lib->crypto, alg);
+ if (!hasher ||
+ !hasher->allocate_hash(hasher, this->data, &messageDigest))
+ {
+ DESTROY_IF(hasher);
+ DBG1(DBG_LIB, " hash algorithm %N not support",
+ hash_algorithm_names, alg);
+ return FALSE;
+ }
+ hasher->destroy(hasher);
+ this->attributes->set_attribute(this->attributes,
+ OID_PKCS9_MESSAGE_DIGEST,
+ messageDigest);
+ free(messageDigest.ptr);
+
+ /* take the current time as signingTime */
+ now = time(NULL);
+ signingTime = asn1_from_time(&now, ASN1_UTCTIME);
+ this->attributes->set_attribute_raw(this->attributes,
+ OID_PKCS9_SIGNING_TIME, signingTime);
+ this->attributes->set_attribute_raw(this->attributes,
+ OID_PKCS9_CONTENT_TYPE,
+ asn1_build_known_oid(OID_PKCS7_DATA));
+
+ attributes = this->attributes->get_encoding(this->attributes);
+
+ private_key->sign(private_key, scheme, attributes, &encryptedDigest);
+ authenticatedAttributes = chunk_clone(attributes);
+ *authenticatedAttributes.ptr = ASN1_CONTEXT_C_0;
+ }
+ }
+ else if (this->data.ptr != NULL)
+ {
+ private_key->sign(private_key, scheme, this->data, &encryptedDigest);
+ }
+ if (encryptedDigest.ptr)
+ {
+ encryptedDigest = asn1_wrap(ASN1_OCTET_STRING, "m", encryptedDigest);
+ }
+ signerInfo = asn1_wrap(ASN1_SEQUENCE, "cmmmmm",
+ ASN1_INTEGER_1,
+ pkcs7_build_issuerAndSerialNumber(cert),
+ asn1_algorithmIdentifier(digest_oid),
+ authenticatedAttributes,
+ asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
+ encryptedDigest);
+
+ if (this->data.ptr != NULL)
+ {
+ chunk_free(&this->content);
+ this->content = asn1_simple_object(ASN1_OCTET_STRING, this->data);
+ chunk_free(&this->data);
+ }
+ this->type = OID_PKCS7_DATA;
+ this->data = get_contentInfo(this);
+ chunk_free(&this->content);
+
+ cert->get_encoding(cert, CERT_ASN1_DER, &encoding);
+
+ this->content = asn1_wrap(ASN1_SEQUENCE, "cmcmm",
+ ASN1_INTEGER_1,
+ asn1_wrap(ASN1_SET, "m", asn1_algorithmIdentifier(digest_oid)),
+ this->data,
+ asn1_wrap(ASN1_CONTEXT_C_0, "m", encoding),
+ asn1_wrap(ASN1_SET, "m", signerInfo));
+ chunk_free(&this->data);
+ this->type = OID_PKCS7_SIGNED_DATA;
+ this->data = get_contentInfo(this);
+
+ return TRUE;
+}
+
+METHOD(pkcs7_t, destroy, void,
+ private_pkcs7_t *this)
+{
+ DESTROY_IF(this->attributes);
+ this->certs->destroy_offset(this->certs, offsetof(certificate_t, destroy));
+ free(this->content.ptr);
+ free(this->data.ptr);
+ free(this);
+}
+
+/**
+ * Generic private constructor
+ */
+static private_pkcs7_t *pkcs7_create_empty(void)
+{
+ private_pkcs7_t *this;
+
+ INIT(this,
+ .public = {
+ .is_data = _is_data,
+ .is_signedData = _is_signedData,
+ .is_envelopedData = _is_envelopedData,
+ .parse_data = _parse_data,
+ .parse_signedData = _parse_signedData,
+ .parse_envelopedData = _parse_envelopedData,
+ .get_data = _get_data,
+ .get_contentInfo = _get_contentInfo,
+ .create_certificate_enumerator = _create_certificate_enumerator,
+ .set_certificate = _set_certificate,
+ .set_attributes = _set_attributes,
+ .get_attributes = _get_attributes,
+ .build_envelopedData = _build_envelopedData,
+ .build_signedData = _build_signedData,
+ .destroy = _destroy,
+ },
+ .type = OID_UNKNOWN,
+ .certs = linked_list_create(),
+ );
+
+ return this;
+}
+
+/*
+ * Described in header.
+ */
+pkcs7_t *pkcs7_create_from_chunk(chunk_t chunk, u_int level)
+{
+ private_pkcs7_t *this = pkcs7_create_empty();
+
+ this->level = level;
+ this->data = chunk_clone(chunk);
+
+ return &this->public;
+}
+
+/*
+ * Described in header.
+ */
+pkcs7_t *pkcs7_create_from_data(chunk_t data)
+{
+ private_pkcs7_t *this = pkcs7_create_empty();
+
+ this->data = chunk_clone(data);
+
+ return &this->public;
+}
+
diff --git a/src/libstrongswan/crypto/pkcs7.h b/src/libstrongswan/crypto/pkcs7.h
new file mode 100644
index 000000000..7c9a6b037
--- /dev/null
+++ b/src/libstrongswan/crypto/pkcs7.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Copyright (C) 2002-2008 Andreas Steffen
+ * Hochschule fuer Technik Rapperswil, Switzerland
+ *
+ * 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 pkcs7 pkcs7
+ * @{ @ingroup crypto
+ */
+
+#ifndef PKCS7_H_
+#define PKCS7_H_
+
+typedef struct pkcs7_t pkcs7_t;
+
+#include <library.h>
+#include <credentials/keys/private_key.h>
+#include <crypto/pkcs9.h>
+#include <crypto/crypters/crypter.h>
+#include <utils/enumerator.h>
+
+/**
+ * PKCS#7 contentInfo object.
+ */
+struct pkcs7_t {
+
+ /**
+ * Check if the PKCS#7 contentType is data
+ *
+ * @return TRUE if the contentType is data
+ */
+ bool (*is_data) (pkcs7_t *this);
+
+ /**
+ * Check if the PKCS#7 contentType is signedData
+ *
+ * @return TRUE if the contentType is signedData
+ */
+ bool (*is_signedData) (pkcs7_t *this);
+
+ /**
+ * Check if the PKCS#7 contentType is envelopedData
+ *
+ * @return TRUE if the contentType is envelopedData
+ */
+ bool (*is_envelopedData) (pkcs7_t *this);
+
+ /**
+ * Parse a PKCS#7 data content.
+ *
+ * @return TRUE if parsing was successful
+ */
+ bool (*parse_data) (pkcs7_t *this);
+
+ /**
+ * Parse a PKCS#7 signedData content. The contained PKCS#7 data is parsed
+ * and verified.
+ *
+ * @param cacert cacert used to verify the signature
+ * @return TRUE if parsing was successful
+ */
+ bool (*parse_signedData) (pkcs7_t *this, certificate_t *cacert);
+
+ /**
+ * Parse a PKCS#7 envelopedData content.
+ *
+ * @param serialNumber serialNumber of the request
+ * @param key private key used to decrypt the symmetric key
+ * @return TRUE if parsing was successful
+ */
+ bool (*parse_envelopedData) (pkcs7_t *this, chunk_t serialNumber,
+ private_key_t *key);
+
+ /**
+ * Returns the parsed data object
+ *
+ * @return chunk containing the data object
+ */
+ chunk_t (*get_data) (pkcs7_t *this);
+
+ /**
+ * Returns the a DER-encoded contentInfo object
+ *
+ * @return chunk containing the contentInfo object
+ */
+ chunk_t (*get_contentInfo) (pkcs7_t *this);
+
+ /**
+ * Create an enumerator for the certificates.
+ *
+ * @return enumerator for the certificates
+ */
+ enumerator_t *(*create_certificate_enumerator) (pkcs7_t *this);
+
+ /**
+ * Add a certificate.
+ *
+ * @param cert certificate to be included (gets adopted)
+ */
+ void (*set_certificate) (pkcs7_t *this, certificate_t *cert);
+
+ /**
+ * Add authenticated attributes.
+ *
+ * @param attributes attributes to be included (gets adopted)
+ */
+ void (*set_attributes) (pkcs7_t *this, pkcs9_t *attributes);
+
+ /**
+ * Get attributes.
+ *
+ * @return attributes (internal data)
+ */
+ pkcs9_t *(*get_attributes) (pkcs7_t *this);
+
+ /**
+ * Build a data object
+ *
+ * @return TRUE if build was successful
+ */
+ bool (*build_data) (pkcs7_t *this);
+
+ /**
+ * Build an envelopedData object
+ *
+ * @param cert receivers's certificate
+ * @param alg encryption algorithm
+ * @param key_size key size to use
+ * @return TRUE if build was successful
+ */
+ bool (*build_envelopedData) (pkcs7_t *this, certificate_t *cert,
+ encryption_algorithm_t alg, size_t key_size);
+
+ /**
+ * Build an signedData object
+ *
+ * @param key signer's private key
+ * @param alg digest algorithm used for signature
+ * @return TRUE if build was successful
+ */
+ bool (*build_signedData) (pkcs7_t *this, private_key_t *key,
+ hash_algorithm_t alg);
+
+ /**
+ * Destroys the contentInfo object.
+ */
+ void (*destroy) (pkcs7_t *this);
+};
+
+/**
+ * Read a PKCS#7 contentInfo object from a DER encoded chunk.
+ *
+ * @param chunk chunk containing DER encoded data
+ * @param level ASN.1 parsing start level
+ * @return created pkcs7_contentInfo object, or NULL if invalid.
+ */
+pkcs7_t *pkcs7_create_from_chunk(chunk_t chunk, u_int level);
+
+/**
+ * Create a PKCS#7 contentInfo object
+ *
+ * @param data chunk containing data
+ * @return created pkcs7_contentInfo object.
+ */
+pkcs7_t *pkcs7_create_from_data(chunk_t data);
+
+#endif /** PKCS7_H_ @}*/
diff --git a/src/libstrongswan/crypto/pkcs9.c b/src/libstrongswan/crypto/pkcs9.c
index 63a615238..d24ab1b80 100644
--- a/src/libstrongswan/crypto/pkcs9.c
+++ b/src/libstrongswan/crypto/pkcs9.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C)2008 Andreas Steffen
+ * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2008 Andreas Steffen
* Hochschule fuer Technik Rapperswil, Switzerland
*
* This program is free software; you can redistribute it and/or modify it
@@ -74,58 +75,6 @@ struct attribute_t {
};
/**
- * PKCS#9 attribute type OIDs
- */
-static chunk_t ASN1_contentType_oid = chunk_from_chars(
- 0x06, 0x09,
- 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x03
-);
-static chunk_t ASN1_messageDigest_oid = chunk_from_chars(
- 0x06, 0x09,
- 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x04
-);
-static chunk_t ASN1_signingTime_oid = chunk_from_chars(
- 0x06, 0x09,
- 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x05
-);
-static chunk_t ASN1_messageType_oid = chunk_from_chars(
- 0x06, 0x0A,
- 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, 0x09, 0x02
-);
-static chunk_t ASN1_senderNonce_oid = chunk_from_chars(
- 0x06, 0x0A,
- 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, 0x09, 0x05
-);
-static chunk_t ASN1_transId_oid = chunk_from_chars(
- 0x06, 0x0A,
- 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, 0x09, 0x07
-);
-
-/**
- * return the ASN.1 encoded OID of a PKCS#9 attribute
- */
-static chunk_t asn1_attributeIdentifier(int oid)
-{
- switch (oid)
- {
- case OID_PKCS9_CONTENT_TYPE:
- return ASN1_contentType_oid;
- case OID_PKCS9_MESSAGE_DIGEST:
- return ASN1_messageDigest_oid;
- case OID_PKCS9_SIGNING_TIME:
- return ASN1_signingTime_oid;
- case OID_PKI_MESSAGE_TYPE:
- return ASN1_messageType_oid;
- case OID_PKI_SENDER_NONCE:
- return ASN1_senderNonce_oid;
- case OID_PKI_TRANS_ID:
- return ASN1_transId_oid;;
- default:
- return chunk_empty;
- }
-}
-
-/**
* return the ASN.1 encoding of a PKCS#9 attribute
*/
static asn1_t asn1_attributeType(int oid)
@@ -188,8 +137,8 @@ static attribute_t *attribute_create(int oid, chunk_t value)
.destroy = attribute_destroy,
.oid = oid,
.value = chunk_clone(value),
- .encoding = asn1_wrap(ASN1_SEQUENCE, "cm",
- asn1_attributeIdentifier(oid),
+ .encoding = asn1_wrap(ASN1_SEQUENCE, "mm",
+ asn1_build_known_oid(oid),
asn1_simple_object(ASN1_SET, value)),
);
@@ -263,43 +212,30 @@ METHOD(pkcs9_t, get_attribute, chunk_t,
}
}
enumerator->destroy(enumerator);
+ if (value.ptr &&
+ !asn1_parse_simple_object(&value, asn1_attributeType(oid), 0,
+ oid_names[oid].name))
+ {
+ return chunk_empty;
+ }
return value;
}
-METHOD(pkcs9_t, set_attribute, void,
+METHOD(pkcs9_t, set_attribute_raw, void,
private_pkcs9_t *this, int oid, chunk_t value)
{
attribute_t *attribute = attribute_create(oid, value);
- this->attributes->insert_last(this->attributes, (void*)attribute);
-}
-
-METHOD(pkcs9_t, get_messageDigest, chunk_t,
- private_pkcs9_t *this)
-{
- const int oid = OID_PKCS9_MESSAGE_DIGEST;
- chunk_t value = get_attribute(this, oid);
-
- if (value.ptr == NULL)
- {
- return chunk_empty;
- }
- if (!asn1_parse_simple_object(&value, asn1_attributeType(oid), 0,
- oid_names[oid].name))
- {
- return chunk_empty;
- }
- return chunk_clone(value);
+ this->attributes->insert_last(this->attributes, attribute);
+ chunk_free(&value);
}
-METHOD(pkcs9_t, set_messageDigest, void,
- private_pkcs9_t *this, chunk_t value)
+METHOD(pkcs9_t, set_attribute, void,
+ private_pkcs9_t *this, int oid, chunk_t value)
{
- const int oid = OID_PKCS9_MESSAGE_DIGEST;
- chunk_t messageDigest = asn1_simple_object(asn1_attributeType(oid), value);
+ chunk_t attr = asn1_simple_object(asn1_attributeType(oid), value);
- set_attribute(this, oid, messageDigest);
- free(messageDigest.ptr);
+ set_attribute_raw(this, oid, attr);
}
METHOD(pkcs9_t, destroy, void,
@@ -323,8 +259,7 @@ static private_pkcs9_t *pkcs9_create_empty(void)
.get_encoding = _get_encoding,
.get_attribute = _get_attribute,
.set_attribute = _set_attribute,
- .get_messageDigest = _get_messageDigest,
- .set_messageDigest = _set_messageDigest,
+ .set_attribute_raw = _set_attribute_raw,
.destroy = _destroy,
},
.attributes = linked_list_create(),
diff --git a/src/libstrongswan/crypto/pkcs9.h b/src/libstrongswan/crypto/pkcs9.h
index 5b85692d6..c442d4441 100644
--- a/src/libstrongswan/crypto/pkcs9.h
+++ b/src/libstrongswan/crypto/pkcs9.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2008 Andreas Steffen
* Hochschule fuer Technik Rapperswil, Switzerland
*
@@ -46,7 +47,7 @@ struct pkcs9_t {
* Gets a PKCS#9 attribute
*
* @param oid OID of the attribute
- * @return ASN.1 encoded value of the attribute
+ * @return value of the attribute (internal data)
*/
chunk_t (*get_attribute) (pkcs9_t *this, int oid);
@@ -54,23 +55,17 @@ struct pkcs9_t {
* Adds a PKCS#9 attribute
*
* @param oid OID of the attribute
- * @param value ASN.1 encoded value of the attribute
+ * @param value value of the attribute (gets cloned)
*/
void (*set_attribute) (pkcs9_t *this, int oid, chunk_t value);
/**
- * Gets a PKCS#9 messageDigest attribute
+ * Adds a ASN.1 encoded PKCS#9 attribute
*
- * @return messageDigest
- */
- chunk_t (*get_messageDigest) (pkcs9_t *this);
-
- /**
- * Add a PKCS#9 messageDigest attribute
- *
- * @param value messageDigest
+ * @param oid OID of the attribute
+ * @param value ASN.1 encoded value of the attribute (gets adopted)
*/
- void (*set_messageDigest) (pkcs9_t *this, chunk_t value);
+ void (*set_attribute_raw) (pkcs9_t *this, int oid, chunk_t value);
/**
* Destroys the PKCS#9 attribute list.
diff --git a/src/libstrongswan/crypto/prf_plus.c b/src/libstrongswan/crypto/prf_plus.c
index 8e815e608..94be1d5bf 100644
--- a/src/libstrongswan/crypto/prf_plus.c
+++ b/src/libstrongswan/crypto/prf_plus.c
@@ -25,6 +25,7 @@ typedef struct private_prf_plus_t private_prf_plus_t;
*
*/
struct private_prf_plus_t {
+
/**
* Public interface of prf_plus_t.
*/
@@ -41,65 +42,74 @@ struct private_prf_plus_t {
chunk_t seed;
/**
- * Buffer to store current PRF result.
+ * Octet which will be appended to the seed, 0 if not used
*/
- chunk_t buffer;
+ u_int8_t counter;
/**
* Already given out bytes in current buffer.
*/
- size_t given_out;
+ size_t used;
/**
- * Octet which will be appended to the seed.
+ * Buffer to store current PRF result.
*/
- u_int8_t appending_octet;
+ chunk_t buffer;
};
-METHOD(prf_plus_t, get_bytes, void,
+METHOD(prf_plus_t, get_bytes, bool,
private_prf_plus_t *this, size_t length, u_int8_t *buffer)
{
- chunk_t appending_chunk;
- size_t bytes_in_round;
- size_t total_bytes_written = 0;
-
- appending_chunk.ptr = &(this->appending_octet);
- appending_chunk.len = 1;
+ size_t round, written = 0;
while (length > 0)
- { /* still more to do... */
- if (this->buffer.len == this->given_out)
- { /* no bytes left in buffer, get next*/
- this->prf->get_bytes(this->prf, this->buffer, NULL);
- this->prf->get_bytes(this->prf, this->seed, NULL);
- this->prf->get_bytes(this->prf, appending_chunk, this->buffer.ptr);
- this->given_out = 0;
- this->appending_octet++;
+ {
+ if (this->buffer.len == this->used)
+ { /* buffer used, get next round */
+ if (!this->prf->get_bytes(this->prf, this->buffer, NULL))
+ {
+ return FALSE;
+ }
+ if (this->counter)
+ {
+ if (!this->prf->get_bytes(this->prf, this->seed, NULL) ||
+ !this->prf->get_bytes(this->prf,
+ chunk_from_thing(this->counter), this->buffer.ptr))
+ {
+ return FALSE;
+ }
+ this->counter++;
+ }
+ else
+ {
+ if (!this->prf->get_bytes(this->prf, this->seed,
+ this->buffer.ptr))
+ {
+ return FALSE;
+ }
+ }
+ this->used = 0;
}
- /* how many bytes can we write in this round ? */
- bytes_in_round = min(length, this->buffer.len - this->given_out);
- /* copy bytes from buffer with offset */
- memcpy(buffer + total_bytes_written, this->buffer.ptr + this->given_out, bytes_in_round);
-
- length -= bytes_in_round;
- this->given_out += bytes_in_round;
- total_bytes_written += bytes_in_round;
+ round = min(length, this->buffer.len - this->used);
+ memcpy(buffer + written, this->buffer.ptr + this->used, round);
+
+ length -= round;
+ this->used += round;
+ written += round;
}
+ return TRUE;
}
-METHOD(prf_plus_t, allocate_bytes, void,
+METHOD(prf_plus_t, allocate_bytes, bool,
private_prf_plus_t *this, size_t length, chunk_t *chunk)
{
if (length)
{
- chunk->ptr = malloc(length);
- chunk->len = length;
- get_bytes(this, length, chunk->ptr);
- }
- else
- {
- *chunk = chunk_empty;
+ *chunk = chunk_alloc(length);
+ return get_bytes(this, length, chunk->ptr);
}
+ *chunk = chunk_empty;
+ return TRUE;
}
METHOD(prf_plus_t, destroy, void,
@@ -113,10 +123,9 @@ METHOD(prf_plus_t, destroy, void,
/*
* Description in header.
*/
-prf_plus_t *prf_plus_create(prf_t *prf, chunk_t seed)
+prf_plus_t *prf_plus_create(prf_t *prf, bool counter, chunk_t seed)
{
private_prf_plus_t *this;
- chunk_t appending_chunk;
INIT(this,
.public = {
@@ -125,25 +134,30 @@ prf_plus_t *prf_plus_create(prf_t *prf, chunk_t seed)
.destroy = _destroy,
},
.prf = prf,
+ .seed = chunk_clone(seed),
+ .buffer = chunk_alloc(prf->get_block_size(prf)),
);
- /* allocate buffer for prf output */
- this->buffer.len = prf->get_block_size(prf);
- this->buffer.ptr = malloc(this->buffer.len);
-
- this->appending_octet = 0x01;
-
- /* clone seed */
- this->seed.ptr = clalloc(seed.ptr, seed.len);
- this->seed.len = seed.len;
-
- /* do the first run */
- appending_chunk.ptr = &(this->appending_octet);
- appending_chunk.len = 1;
- this->prf->get_bytes(this->prf, this->seed, NULL);
- this->prf->get_bytes(this->prf, appending_chunk, this->buffer.ptr);
- this->given_out = 0;
- this->appending_octet++;
+ if (counter)
+ {
+ this->counter = 0x01;
+ if (!this->prf->get_bytes(this->prf, this->seed, NULL) ||
+ !this->prf->get_bytes(this->prf, chunk_from_thing(this->counter),
+ this->buffer.ptr))
+ {
+ destroy(this);
+ return NULL;
+ }
+ this->counter++;
+ }
+ else
+ {
+ if (!this->prf->get_bytes(this->prf, this->seed, this->buffer.ptr))
+ {
+ destroy(this);
+ return NULL;
+ }
+ }
- return &(this->public);
+ return &this->public;
}
diff --git a/src/libstrongswan/crypto/prf_plus.h b/src/libstrongswan/crypto/prf_plus.h
index 4179f2695..f994dce16 100644
--- a/src/libstrongswan/crypto/prf_plus.h
+++ b/src/libstrongswan/crypto/prf_plus.h
@@ -27,52 +27,44 @@ typedef struct prf_plus_t prf_plus_t;
#include <crypto/prfs/prf.h>
/**
- * Implementation of the prf+ function described in IKEv2 RFC.
- *
- * This class implements the prf+ algorithm. Internally it uses a pseudo random
- * function, which implements the prf_t interface.
- * See IKEv2 RFC 2.13.
+ * Implementation of the prf+ function used in IKEv1/IKEv2 keymat extension.
*/
struct prf_plus_t {
+
/**
* Get pseudo random bytes.
*
- * Get the next few bytes of the prf+ output. Space
- * must be allocated by the caller.
- *
* @param length number of bytes to get
* @param buffer pointer where the generated bytes will be written
+ * @return TRUE if bytes generated successfully
*/
- void (*get_bytes) (prf_plus_t *this, size_t length, u_int8_t *buffer);
+ bool (*get_bytes)(prf_plus_t *this, size_t length,
+ u_int8_t *buffer) __attribute__((warn_unused_result));
/**
* Allocate pseudo random bytes.
*
- * Get the next few bytes of the prf+ output. This function
- * will allocate the required space.
- *
* @param length number of bytes to get
* @param chunk chunk which will hold generated bytes
+ * @return TRUE if bytes allocated successfully
*/
- void (*allocate_bytes) (prf_plus_t *this, size_t length, chunk_t *chunk);
+ bool (*allocate_bytes)(prf_plus_t *this, size_t length,
+ chunk_t *chunk) __attribute__((warn_unused_result));
/**
* Destroys a prf_plus_t object.
*/
- void (*destroy) (prf_plus_t *this);
+ void (*destroy)(prf_plus_t *this);
};
/**
* Creates a new prf_plus_t object.
*
- * Seed will be cloned. prf will
- * not be cloned, must be destroyed outside after
- * prf_plus_t usage.
- *
- * @param prf prf object to use
+ * @param prf prf object to use, must be destroyd after prf+.
+ * @param counter use an appending counter byte (for IKEv2 variant)
* @param seed input seed for prf
- * @return prf_plus_t object
+ * @return prf_plus_t object, NULL on failure
*/
-prf_plus_t *prf_plus_create(prf_t *prf, chunk_t seed);
+prf_plus_t *prf_plus_create(prf_t *prf, bool counter, chunk_t seed);
#endif /** PRF_PLUS_H_ @}*/
diff --git a/src/libstrongswan/crypto/prfs/mac_prf.c b/src/libstrongswan/crypto/prfs/mac_prf.c
new file mode 100644
index 000000000..b5f6be982
--- /dev/null
+++ b/src/libstrongswan/crypto/prfs/mac_prf.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "mac_prf.h"
+
+typedef struct private_prf_t private_prf_t;
+
+/**
+ * Private data of a mac_prf_t object.
+ */
+struct private_prf_t {
+
+ /**
+ * Public interface
+ */
+ prf_t public;
+
+ /**
+ * MAC to use
+ */
+ mac_t *mac;
+};
+
+METHOD(prf_t, get_bytes, bool,
+ private_prf_t *this, chunk_t seed, u_int8_t *buffer)
+{
+ return this->mac->get_mac(this->mac, seed, buffer);
+}
+
+METHOD(prf_t, allocate_bytes, bool,
+ private_prf_t *this, chunk_t seed, chunk_t *chunk)
+{
+ if (chunk)
+ {
+ *chunk = chunk_alloc(this->mac->get_mac_size(this->mac));
+ return this->mac->get_mac(this->mac, seed, chunk->ptr);
+ }
+ return this->mac->get_mac(this->mac, seed, NULL);
+}
+
+METHOD(prf_t, get_block_size, size_t,
+ private_prf_t *this)
+{
+ return this->mac->get_mac_size(this->mac);
+}
+
+METHOD(prf_t, get_key_size, size_t,
+ private_prf_t *this)
+{
+ /* IKEv2 uses MAC size as key size */
+ return this->mac->get_mac_size(this->mac);
+}
+
+METHOD(prf_t, set_key, bool,
+ private_prf_t *this, chunk_t key)
+{
+ return this->mac->set_key(this->mac, key);
+}
+
+METHOD(prf_t, destroy, void,
+ private_prf_t *this)
+{
+ this->mac->destroy(this->mac);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+prf_t *mac_prf_create(mac_t *mac)
+{
+ private_prf_t *this;
+
+ INIT(this,
+ .public = {
+ .get_bytes = _get_bytes,
+ .allocate_bytes = _allocate_bytes,
+ .get_block_size = _get_block_size,
+ .get_key_size = _get_key_size,
+ .set_key = _set_key,
+ .destroy = _destroy,
+ },
+ .mac = mac,
+ );
+
+ return &this->public;
+}
diff --git a/src/pluto/plugins/xauth/xauth_default_verifier.h b/src/libstrongswan/crypto/prfs/mac_prf.h
index e5814d7b4..b2c0c6e17 100644
--- a/src/pluto/plugins/xauth/xauth_default_verifier.h
+++ b/src/libstrongswan/crypto/prfs/mac_prf.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Andreas Steffen
+ * Copyright (C) 2012 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -14,20 +14,23 @@
*/
/**
- * @defgroup xauth_default_verifier xauth_default_verifier
- * @{ @ingroup xauth
+ * @defgroup mac_prf mac_prf
+ * @{ @ingroup crypto
*/
-#ifndef XAUTH_DEFAULT_VERIFIER_H_
-#define XAUTH_DEFAULT_VERIFIER_H_
-
-#include <xauth/xauth_verifier.h>
+#ifndef MAC_PRF_H_
+#define MAC_PRF_H_
+#include <crypto/mac.h>
+#include <crypto/prfs/prf.h>
/**
- * Create an xauth_default_verifier instance.
+ * Creates an implementation of the prf_t interface using the provided mac_t
+ * implementation. Basically a simple wrapper to map the interface.
+ *
+ * @param mac mac_t implementation
+ * @return prf_t object
*/
-xauth_verifier_t *xauth_default_verifier_create();
-
-#endif /** XAUTH_DEFAULT_VERIFIER_H_ @}*/
+prf_t *mac_prf_create(mac_t *mac);
+#endif /** MAC_PRF_H_ @}*/
diff --git a/src/libstrongswan/crypto/prfs/prf.h b/src/libstrongswan/crypto/prfs/prf.h
index ad15205d3..46e23b244 100644
--- a/src/libstrongswan/crypto/prfs/prf.h
+++ b/src/libstrongswan/crypto/prfs/prf.h
@@ -71,28 +71,33 @@ extern enum_name_t *pseudo_random_function_names;
* Generic interface for pseudo-random-functions.
*/
struct prf_t {
+
/**
* Generates pseudo random bytes and writes them in the buffer.
*
* @param seed a chunk containing the seed for the next bytes
* @param buffer pointer where the generated bytes will be written
+ * @return TRUE if bytes generated successfully
*/
- void (*get_bytes) (prf_t *this, chunk_t seed, u_int8_t *buffer);
+ bool (*get_bytes)(prf_t *this, chunk_t seed,
+ u_int8_t *buffer) __attribute__((warn_unused_result));
/**
* Generates pseudo random bytes and allocate space for them.
*
* @param seed a chunk containing the seed for the next bytes
* @param chunk chunk which will hold generated bytes
+ * @return TRUE if bytes allocated and generated successfully
*/
- void (*allocate_bytes) (prf_t *this, chunk_t seed, chunk_t *chunk);
+ bool (*allocate_bytes)(prf_t *this, chunk_t seed,
+ chunk_t *chunk) __attribute__((warn_unused_result));
/**
* Get the block size of this prf_t object.
*
* @return block size in bytes
*/
- size_t (*get_block_size) (prf_t *this);
+ size_t (*get_block_size)(prf_t *this);
/**
* Get the key size of this prf_t object.
@@ -102,19 +107,21 @@ struct prf_t {
*
* @return key size in bytes
*/
- size_t (*get_key_size) (prf_t *this);
+ size_t (*get_key_size)(prf_t *this);
/**
* Set the key for this prf_t object.
*
* @param key key to set
+ * @return TRUE if key set successfully
*/
- void (*set_key) (prf_t *this, chunk_t key);
+ bool (*set_key)(prf_t *this,
+ chunk_t key) __attribute__((warn_unused_result));
/**
* Destroys a prf object.
*/
- void (*destroy) (prf_t *this);
+ void (*destroy)(prf_t *this);
};
#endif /** PRF_H_ @}*/
diff --git a/src/libstrongswan/crypto/proposal/proposal_keywords.c b/src/libstrongswan/crypto/proposal/proposal_keywords.c
index 2060864a5..7356dc367 100644
--- a/src/libstrongswan/crypto/proposal/proposal_keywords.c
+++ b/src/libstrongswan/crypto/proposal/proposal_keywords.c
@@ -1,38 +1,6 @@
-/* C code produced by gperf version 3.0.3 */
-/* Command-line: /usr/bin/gperf -N proposal_get_token -m 10 -C -G -c -t -D */
-/* Computed positions: -k'1,5,7,10,15,$' */
-
-#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
- && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
- && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
- && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
- && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
- && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
- && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
- && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
- && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
- && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
- && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
- && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
- && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
- && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
- && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
- && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
- && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
- && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
- && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
- && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
- && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
- && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
- && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
-/* The character set is not based on ISO-646. */
-error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
-#endif
-
-
-/* proposal keywords
- * Copyright (C) 2009 Andreas Steffen
- * Hochschule fuer Technik Rapperswil, Switzerland
+/*
+ * Copyright (C) 2012 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
@@ -45,280 +13,134 @@ error "gperf generated tables don't work with this execution character set. Plea
* for more details.
*/
-#include <string.h>
+/*
+ * Copyright (c) 2012 Nanoteq Pty Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "proposal_keywords.h"
+#include "proposal_keywords_static.h"
-#include <crypto/transform.h>
-#include <crypto/crypters/crypter.h>
-#include <crypto/signers/signer.h>
-#include <crypto/diffie_hellman.h>
+#include <utils/linked_list.h>
+#include <threading/rwlock.h>
-struct proposal_token {
- char *name;
- transform_type_t type;
- u_int16_t algorithm;
- u_int16_t keysize;
-};
+typedef struct private_proposal_keywords_t private_proposal_keywords_t;
+
+struct private_proposal_keywords_t {
+
+ /**
+ * public interface
+ */
+ proposal_keywords_t public;
+
+ /**
+ * registered tokens, as proposal_token_t
+ */
+ linked_list_t * tokens;
-#define TOTAL_KEYWORDS 122
-#define MIN_WORD_LENGTH 3
-#define MAX_WORD_LENGTH 17
-#define MIN_HASH_VALUE 9
-#define MAX_HASH_VALUE 213
-/* maximum key range = 205, duplicates = 0 */
+ /**
+ * rwlock to lock access to modules
+ */
+ rwlock_t *lock;
+};
-#ifdef __GNUC__
-__inline
-#else
-#ifdef __cplusplus
-inline
-#endif
-#endif
-static unsigned int
-hash (str, len)
- register const char *str;
- register unsigned int len;
+/**
+ * Find the token object for the algorithm specified.
+ */
+static const proposal_token_t* find_token(private_proposal_keywords_t *this,
+ const char *str)
{
- static const unsigned char asso_values[] =
- {
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 14, 9,
- 4, 34, 66, 19, 8, 4, 5, 3, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 131, 214, 3, 22, 21,
- 3, 1, 101, 48, 3, 4, 214, 214, 3, 10,
- 57, 4, 214, 214, 94, 6, 3, 32, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214
- };
- register int hval = len;
+ proposal_token_t *token, *found = NULL;
+ enumerator_t *enumerator;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->tokens->create_enumerator(this->tokens);
+ while (enumerator->enumerate(enumerator, &token))
+ {
+ if (streq(token->name, str))
+ {
+ found = token;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+ return found;
+}
- switch (hval)
- {
- default:
- hval += asso_values[(unsigned char)str[14]];
- /*FALLTHROUGH*/
- case 14:
- case 13:
- case 12:
- case 11:
- case 10:
- hval += asso_values[(unsigned char)str[9]];
- /*FALLTHROUGH*/
- case 9:
- case 8:
- case 7:
- hval += asso_values[(unsigned char)str[6]];
- /*FALLTHROUGH*/
- case 6:
- case 5:
- hval += asso_values[(unsigned char)str[4]];
- /*FALLTHROUGH*/
- case 4:
- case 3:
- case 2:
- case 1:
- hval += asso_values[(unsigned char)str[0]+1];
- break;
- }
- return hval + asso_values[(unsigned char)str[len - 1]];
+METHOD(proposal_keywords_t, get_token, const proposal_token_t*,
+ private_proposal_keywords_t *this, const char *str)
+{
+ const proposal_token_t *token = proposal_get_token_static(str, strlen(str));
+ return token ?: find_token(this, str);
}
-static const struct proposal_token wordlist[] =
- {
- {"sha", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0},
- {"des", ENCRYPTION_ALGORITHM, ENCR_DES, 0},
- {"null", ENCRYPTION_ALGORITHM, ENCR_NULL, 0},
- {"sha1", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0},
- {"serpent", ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 128},
- {"camellia", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 128},
- {"sha512", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0},
- {"serpent192", ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 192},
- {"serpent128", ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 128},
- {"camellia192", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 192},
- {"cast128", ENCRYPTION_ALGORITHM, ENCR_CAST, 128},
- {"camellia128", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 128},
- {"aes", ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128},
- {"serpent256", ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 256},
- {"aes192", ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192},
- {"sha256", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0},
- {"aes128", ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128},
- {"camellia192ccm8", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 192},
- {"camellia128ccm8", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 128},
- {"camellia192ccm96", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 192},
- {"camellia128ccm96", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 128},
- {"camellia192ccm12", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 192},
- {"camellia128ccm12", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 128},
- {"camellia192ccm128",ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 192},
- {"camellia128ccm128",ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 128},
- {"camellia192ccm16", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 192},
- {"camellia128ccm16", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 128},
- {"camellia256", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 256},
- {"twofish", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 128},
- {"camellia256ccm8", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 256},
- {"aes256", ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256},
- {"camellia256ccm96", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 256},
- {"twofish192", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 192},
- {"camellia256ccm12", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 256},
- {"twofish128", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 128},
- {"camellia256ccm128",ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 256},
- {"camellia256ccm16", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 256},
- {"camelliaxcbc", INTEGRITY_ALGORITHM, AUTH_CAMELLIA_XCBC_96, 0},
- {"twofish256", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 256},
- {"aes192ccm8", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 192},
- {"aes128ccm8", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 128},
- {"aes192ccm96", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 192},
- {"aes128ccm96", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 128},
- {"aes192ccm12", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 192},
- {"aes128ccm12", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 128},
- {"aes192ccm128", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 192},
- {"aes128ccm128", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 128},
- {"aes192ccm16", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 192},
- {"aes128ccm16", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 128},
- {"3des", ENCRYPTION_ALGORITHM, ENCR_3DES, 0},
- {"modp8192", DIFFIE_HELLMAN_GROUP, MODP_8192_BIT, 0},
- {"modp768", DIFFIE_HELLMAN_GROUP, MODP_768_BIT, 0},
- {"md5", INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0},
- {"sha384", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0},
- {"aescmac", INTEGRITY_ALGORITHM, AUTH_AES_CMAC_96, 0},
- {"aes256ccm8", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 256},
- {"md5_128", INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_128, 0},
- {"aes256ccm96", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 256},
- {"aes256ccm12", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 256},
- {"aes256ccm128", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 256},
- {"aes256ccm16", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 256},
- {"aesxcbc", INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0},
- {"aes192gcm8", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 192},
- {"aes128gcm8", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 128},
- {"aes192gcm96", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 192},
- {"aes128gcm96", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 128},
- {"aes192gcm12", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 192},
- {"aes128gcm12", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 128},
- {"aes192gcm128", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 192},
- {"aes128gcm128", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 128},
- {"aes192gcm16", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 192},
- {"aes128gcm16", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 128},
- {"camellia192ccm64", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 192},
- {"camellia128ccm64", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 128},
- {"modp1024s160", DIFFIE_HELLMAN_GROUP, MODP_1024_160, 0},
- {"modp3072", DIFFIE_HELLMAN_GROUP, MODP_3072_BIT, 0},
- {"aes256gcm8", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 256},
- {"aes256gcm96", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 256},
- {"aes256gcm12", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 256},
- {"ecp192", DIFFIE_HELLMAN_GROUP, ECP_192_BIT, 0},
- {"aes256gcm128", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 256},
- {"modp1536", DIFFIE_HELLMAN_GROUP, MODP_1536_BIT, 0},
- {"aes256gcm16", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 256},
- {"camellia256ccm64", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 256},
- {"ecp521", DIFFIE_HELLMAN_GROUP, ECP_521_BIT, 0},
- {"camellia192ctr", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CTR, 192},
- {"camellia128ctr", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CTR, 128},
- {"noesn", EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0},
- {"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},
- {"aes192ccm64", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 192},
- {"aes128ccm64", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 128},
- {"ecp256", DIFFIE_HELLMAN_GROUP, ECP_256_BIT, 0},
- {"camellia256ctr", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CTR, 256},
- {"blowfish", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 128},
- {"modp2048", DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0},
- {"aes256gmac", ENCRYPTION_ALGORITHM, ENCR_NULL_AUTH_AES_GMAC, 256},
- {"modp4096", DIFFIE_HELLMAN_GROUP, MODP_4096_BIT, 0},
- {"modp1024", DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0},
- {"blowfish192", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 192},
- {"aes256ccm64", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 256},
- {"blowfish128", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 128},
- {"aes192ctr", ENCRYPTION_ALGORITHM, ENCR_AES_CTR, 192},
- {"aes128ctr", ENCRYPTION_ALGORITHM, ENCR_AES_CTR, 128},
- {"modp2048s256", DIFFIE_HELLMAN_GROUP, MODP_2048_256, 0},
- {"sha2_512", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0},
- {"aes192gcm64", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 192},
- {"aes128gcm64", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 128},
- {"esn", EXTENDED_SEQUENCE_NUMBERS, EXT_SEQ_NUMBERS, 0},
- {"sha1_160", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_160, 0},
- {"aes256ctr", ENCRYPTION_ALGORITHM, ENCR_AES_CTR, 256},
- {"blowfish256", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 256},
- {"sha2_256", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0},
- {"sha256_96", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_96, 0},
- {"aes256gcm64", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 256},
- {"sha2_256_96", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_96, 0},
- {"ecp224", DIFFIE_HELLMAN_GROUP, ECP_224_BIT, 0},
- {"ecp384", DIFFIE_HELLMAN_GROUP, ECP_384_BIT, 0},
- {"modp6144", DIFFIE_HELLMAN_GROUP, MODP_6144_BIT, 0},
- {"modp2048s224", DIFFIE_HELLMAN_GROUP, MODP_2048_224, 0},
- {"sha2_384", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0}
- };
+METHOD(proposal_keywords_t, register_token, void,
+ private_proposal_keywords_t *this, const char *name, transform_type_t type,
+ u_int16_t algorithm, u_int16_t keysize)
+{
+ proposal_token_t *token;
+
+ INIT(token,
+ .name = strdup(name),
+ .type = type,
+ .algorithm = algorithm,
+ .keysize = keysize,
+ );
-static const short lookup[] =
- {
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 0,
- 1, 2, -1, -1, -1, -1, 3, 4, -1, -1,
- -1, 5, 6, -1, -1, 7, -1, 8, 9, 10,
- 11, 12, -1, 13, -1, 14, 15, 16, 17, 18,
- 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
- -1, -1, -1, -1, 29, 30, 31, 32, 33, 34,
- 35, -1, 36, -1, 37, 38, 39, 40, 41, 42,
- 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
- 53, 54, 55, 56, 57, -1, 58, -1, 59, -1,
- 60, -1, 61, 62, 63, 64, 65, 66, 67, 68,
- 69, 70, 71, 72, 73, 74, -1, 75, -1, 76,
- -1, 77, -1, 78, 79, 80, 81, 82, -1, 83,
- 84, 85, 86, 87, -1, 88, 89, -1, 90, -1,
- -1, 91, 92, -1, 93, -1, -1, 94, -1, 95,
- 96, 97, 98, -1, 99, -1, 100, 101, 102, 103,
- 104, 105, -1, -1, -1, 106, -1, -1, 107, 108,
- -1, 109, -1, -1, 110, 111, 112, -1, -1, 113,
- 114, -1, -1, -1, 115, 116, -1, 117, 118, -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, 119, -1, -1, -1, 120,
- -1, -1, -1, 121
- };
+ this->lock->write_lock(this->lock);
+ this->tokens->insert_first(this->tokens, token);
+ this->lock->unlock(this->lock);
+}
-#ifdef __GNUC__
-__inline
-#ifdef __GNUC_STDC_INLINE__
-__attribute__ ((__gnu_inline__))
-#endif
-#endif
-const struct proposal_token *
-proposal_get_token (str, len)
- register const char *str;
- register unsigned int len;
+METHOD(proposal_keywords_t, destroy, void,
+ private_proposal_keywords_t *this)
{
- if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
- {
- register int key = hash (str, len);
+ proposal_token_t *token;
+
+ while (this->tokens->remove_first(this->tokens, (void**)&token) == SUCCESS)
+ {
+ free(token->name);
+ free(token);
+ }
+ this->tokens->destroy(this->tokens);
+ this->lock->destroy(this->lock);
+ free(this);
+}
- if (key <= MAX_HASH_VALUE && key >= 0)
- {
- register int index = lookup[key];
+/*
+ * Described in header.
+ */
+proposal_keywords_t *proposal_keywords_create()
+{
+ private_proposal_keywords_t *this;
- if (index >= 0)
- {
- register const char *s = wordlist[index].name;
+ INIT(this,
+ .public = {
+ .get_token = _get_token,
+ .register_token = _register_token,
+ .destroy = _destroy,
+ },
+ .tokens = linked_list_create(),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ );
- if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0')
- return &wordlist[index];
- }
- }
- }
- return 0;
+ return &this->public;
}
diff --git a/src/libstrongswan/crypto/proposal/proposal_keywords.h b/src/libstrongswan/crypto/proposal/proposal_keywords.h
index 53fa1728f..d6107abc0 100644
--- a/src/libstrongswan/crypto/proposal/proposal_keywords.h
+++ b/src/libstrongswan/crypto/proposal/proposal_keywords.h
@@ -1,6 +1,6 @@
-/* proposal keywords
- * Copyright (C) 2009 Andreas Steffen
- * Hochschule fuer Technik Rapperswil, Switzerland
+/*
+ * Copyright (C) 2012 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
@@ -13,22 +13,103 @@
* for more details.
*/
-#ifndef _PROPOSAL_KEYWORDS_H_
-#define _PROPOSAL_KEYWORDS_H_
+/*
+ * Copyright (c) 2012 Nanoteq Pty Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+/**
+ * @defgroup proposal_keywords proposal_keywords
+ * @{ @ingroup crypto
+ */
+
+#ifndef PROPOSAL_KEYWORDS_H_
+#define PROPOSAL_KEYWORDS_H_
+
+typedef struct proposal_token_t proposal_token_t;
+typedef struct proposal_keywords_t proposal_keywords_t;
+
+#include <library.h>
#include <crypto/transform.h>
-typedef struct proposal_token proposal_token_t;
+/**
+ * Class representing a proposal token.
+ */
+struct proposal_token_t {
+
+ /**
+ * The name of the token.
+ */
+ char *name;
+
+ /**
+ * The type of transform in the token.
+ */
+ transform_type_t type;
+
+ /**
+ * The IKE id of the algorithm.
+ */
+ u_int16_t algorithm;
-struct proposal_token {
- char *name;
- transform_type_t type;
- u_int16_t algorithm;
- u_int16_t keysize;
+ /**
+ * The key size associated with the specific algorithm.
+ */
+ u_int16_t keysize;
};
-extern const proposal_token_t* proposal_get_token(register const char *str,
- register unsigned int len);
+/**
+ * Class to manage proposal keywords
+ */
+struct proposal_keywords_t {
+
+ /**
+ * Returns the proposal token for the specified string if a token exists.
+ *
+ * @param str the string containing the name of the token
+ * @return proposal_token if found, NULL otherwise
+ */
+ const proposal_token_t *(*get_token)(proposal_keywords_t *this,
+ const char *str);
-#endif /* _PROPOSAL_KEYWORDS_H_ */
+ /**
+ * Register a new proposal token for an algorithm.
+ *
+ * @param name the string containing the name of the token
+ * @param type the transform_type_t for the token
+ * @param algorithm the IKE id of the algorithm
+ * @param keysize the key size associated with the specific algorithm
+ */
+ void (*register_token)(proposal_keywords_t *this, const char *name,
+ transform_type_t type, u_int16_t algorithm,
+ u_int16_t keysize);
+
+ /**
+ * Destroy a proposal_keywords_t instance.
+ */
+ void (*destroy)(proposal_keywords_t *this);
+};
+
+/**
+ * Create a proposal_keywords_t instance.
+ */
+proposal_keywords_t *proposal_keywords_create();
+#endif /** PROPOSAL_KEYWORDS_H_ @}*/
diff --git a/src/libstrongswan/crypto/proposal/proposal_keywords_static.c b/src/libstrongswan/crypto/proposal/proposal_keywords_static.c
new file mode 100644
index 000000000..ce52bc2ce
--- /dev/null
+++ b/src/libstrongswan/crypto/proposal/proposal_keywords_static.c
@@ -0,0 +1,324 @@
+/* C code produced by gperf version 3.0.3 */
+/* Command-line: /usr/bin/gperf -N proposal_get_token_static -m 10 -C -G -c -t -D */
+/* Computed positions: -k'1,5,7,10,15,$' */
+
+#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
+ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
+ && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
+ && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
+ && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
+ && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
+ && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
+ && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
+ && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
+ && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
+ && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
+ && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
+ && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
+ && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
+ && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
+ && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
+ && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
+ && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
+ && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
+ && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
+ && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
+ && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
+ && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
+/* The character set is not based on ISO-646. */
+error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
+#endif
+
+
+/*
+ * Copyright (C) 2009 Andreas Steffen
+ * Hochschule fuer Technik Rapperswil, Switzerland
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <string.h>
+
+#include <crypto/transform.h>
+#include <crypto/crypters/crypter.h>
+#include <crypto/signers/signer.h>
+#include <crypto/diffie_hellman.h>
+
+struct proposal_token {
+ char *name;
+ transform_type_t type;
+ u_int16_t algorithm;
+ u_int16_t keysize;
+};
+
+#define TOTAL_KEYWORDS 122
+#define MIN_WORD_LENGTH 3
+#define MAX_WORD_LENGTH 17
+#define MIN_HASH_VALUE 9
+#define MAX_HASH_VALUE 213
+/* maximum key range = 205, duplicates = 0 */
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static unsigned int
+hash (str, len)
+ register const char *str;
+ register unsigned int len;
+{
+ static const unsigned char asso_values[] =
+ {
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 14, 9,
+ 4, 34, 66, 19, 8, 4, 5, 3, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 131, 214, 3, 22, 21,
+ 3, 1, 101, 48, 3, 4, 214, 214, 3, 10,
+ 57, 4, 214, 214, 94, 6, 3, 32, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214
+ };
+ register int hval = len;
+
+ switch (hval)
+ {
+ default:
+ hval += asso_values[(unsigned char)str[14]];
+ /*FALLTHROUGH*/
+ case 14:
+ case 13:
+ case 12:
+ case 11:
+ case 10:
+ hval += asso_values[(unsigned char)str[9]];
+ /*FALLTHROUGH*/
+ case 9:
+ case 8:
+ case 7:
+ hval += asso_values[(unsigned char)str[6]];
+ /*FALLTHROUGH*/
+ case 6:
+ case 5:
+ hval += asso_values[(unsigned char)str[4]];
+ /*FALLTHROUGH*/
+ case 4:
+ case 3:
+ case 2:
+ case 1:
+ hval += asso_values[(unsigned char)str[0]+1];
+ break;
+ }
+ return hval + asso_values[(unsigned char)str[len - 1]];
+}
+
+static const struct proposal_token wordlist[] =
+ {
+ {"sha", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0},
+ {"des", ENCRYPTION_ALGORITHM, ENCR_DES, 0},
+ {"null", ENCRYPTION_ALGORITHM, ENCR_NULL, 0},
+ {"sha1", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0},
+ {"serpent", ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 128},
+ {"camellia", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 128},
+ {"sha512", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0},
+ {"serpent192", ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 192},
+ {"serpent128", ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 128},
+ {"camellia192", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 192},
+ {"cast128", ENCRYPTION_ALGORITHM, ENCR_CAST, 128},
+ {"camellia128", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 128},
+ {"aes", ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128},
+ {"serpent256", ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 256},
+ {"aes192", ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192},
+ {"sha256", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0},
+ {"aes128", ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128},
+ {"camellia192ccm8", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 192},
+ {"camellia128ccm8", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 128},
+ {"camellia192ccm96", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 192},
+ {"camellia128ccm96", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 128},
+ {"camellia192ccm12", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 192},
+ {"camellia128ccm12", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 128},
+ {"camellia192ccm128",ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 192},
+ {"camellia128ccm128",ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 128},
+ {"camellia192ccm16", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 192},
+ {"camellia128ccm16", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 128},
+ {"camellia256", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 256},
+ {"twofish", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 128},
+ {"camellia256ccm8", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 256},
+ {"aes256", ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256},
+ {"camellia256ccm96", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 256},
+ {"twofish192", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 192},
+ {"camellia256ccm12", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 256},
+ {"twofish128", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 128},
+ {"camellia256ccm128",ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 256},
+ {"camellia256ccm16", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 256},
+ {"camelliaxcbc", INTEGRITY_ALGORITHM, AUTH_CAMELLIA_XCBC_96, 0},
+ {"twofish256", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 256},
+ {"aes192ccm8", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 192},
+ {"aes128ccm8", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 128},
+ {"aes192ccm96", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 192},
+ {"aes128ccm96", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 128},
+ {"aes192ccm12", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 192},
+ {"aes128ccm12", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 128},
+ {"aes192ccm128", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 192},
+ {"aes128ccm128", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 128},
+ {"aes192ccm16", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 192},
+ {"aes128ccm16", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 128},
+ {"3des", ENCRYPTION_ALGORITHM, ENCR_3DES, 0},
+ {"modp8192", DIFFIE_HELLMAN_GROUP, MODP_8192_BIT, 0},
+ {"modp768", DIFFIE_HELLMAN_GROUP, MODP_768_BIT, 0},
+ {"md5", INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0},
+ {"sha384", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0},
+ {"aescmac", INTEGRITY_ALGORITHM, AUTH_AES_CMAC_96, 0},
+ {"aes256ccm8", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 256},
+ {"md5_128", INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_128, 0},
+ {"aes256ccm96", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 256},
+ {"aes256ccm12", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 256},
+ {"aes256ccm128", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 256},
+ {"aes256ccm16", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 256},
+ {"aesxcbc", INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0},
+ {"aes192gcm8", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 192},
+ {"aes128gcm8", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 128},
+ {"aes192gcm96", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 192},
+ {"aes128gcm96", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 128},
+ {"aes192gcm12", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 192},
+ {"aes128gcm12", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 128},
+ {"aes192gcm128", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 192},
+ {"aes128gcm128", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 128},
+ {"aes192gcm16", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 192},
+ {"aes128gcm16", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 128},
+ {"camellia192ccm64", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 192},
+ {"camellia128ccm64", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 128},
+ {"modp1024s160", DIFFIE_HELLMAN_GROUP, MODP_1024_160, 0},
+ {"modp3072", DIFFIE_HELLMAN_GROUP, MODP_3072_BIT, 0},
+ {"aes256gcm8", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 256},
+ {"aes256gcm96", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 256},
+ {"aes256gcm12", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 256},
+ {"ecp192", DIFFIE_HELLMAN_GROUP, ECP_192_BIT, 0},
+ {"aes256gcm128", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 256},
+ {"modp1536", DIFFIE_HELLMAN_GROUP, MODP_1536_BIT, 0},
+ {"aes256gcm16", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 256},
+ {"camellia256ccm64", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 256},
+ {"ecp521", DIFFIE_HELLMAN_GROUP, ECP_521_BIT, 0},
+ {"camellia192ctr", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CTR, 192},
+ {"camellia128ctr", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CTR, 128},
+ {"noesn", EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0},
+ {"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},
+ {"aes192ccm64", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 192},
+ {"aes128ccm64", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 128},
+ {"ecp256", DIFFIE_HELLMAN_GROUP, ECP_256_BIT, 0},
+ {"camellia256ctr", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CTR, 256},
+ {"blowfish", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 128},
+ {"modp2048", DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0},
+ {"aes256gmac", ENCRYPTION_ALGORITHM, ENCR_NULL_AUTH_AES_GMAC, 256},
+ {"modp4096", DIFFIE_HELLMAN_GROUP, MODP_4096_BIT, 0},
+ {"modp1024", DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0},
+ {"blowfish192", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 192},
+ {"aes256ccm64", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 256},
+ {"blowfish128", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 128},
+ {"aes192ctr", ENCRYPTION_ALGORITHM, ENCR_AES_CTR, 192},
+ {"aes128ctr", ENCRYPTION_ALGORITHM, ENCR_AES_CTR, 128},
+ {"modp2048s256", DIFFIE_HELLMAN_GROUP, MODP_2048_256, 0},
+ {"sha2_512", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0},
+ {"aes192gcm64", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 192},
+ {"aes128gcm64", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 128},
+ {"esn", EXTENDED_SEQUENCE_NUMBERS, EXT_SEQ_NUMBERS, 0},
+ {"sha1_160", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_160, 0},
+ {"aes256ctr", ENCRYPTION_ALGORITHM, ENCR_AES_CTR, 256},
+ {"blowfish256", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 256},
+ {"sha2_256", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0},
+ {"sha256_96", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_96, 0},
+ {"aes256gcm64", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 256},
+ {"sha2_256_96", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_96, 0},
+ {"ecp224", DIFFIE_HELLMAN_GROUP, ECP_224_BIT, 0},
+ {"ecp384", DIFFIE_HELLMAN_GROUP, ECP_384_BIT, 0},
+ {"modp6144", DIFFIE_HELLMAN_GROUP, MODP_6144_BIT, 0},
+ {"modp2048s224", DIFFIE_HELLMAN_GROUP, MODP_2048_224, 0},
+ {"sha2_384", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0}
+ };
+
+static const short lookup[] =
+ {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 0,
+ 1, 2, -1, -1, -1, -1, 3, 4, -1, -1,
+ -1, 5, 6, -1, -1, 7, -1, 8, 9, 10,
+ 11, 12, -1, 13, -1, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+ -1, -1, -1, -1, 29, 30, 31, 32, 33, 34,
+ 35, -1, 36, -1, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+ 53, 54, 55, 56, 57, -1, 58, -1, 59, -1,
+ 60, -1, 61, 62, 63, 64, 65, 66, 67, 68,
+ 69, 70, 71, 72, 73, 74, -1, 75, -1, 76,
+ -1, 77, -1, 78, 79, 80, 81, 82, -1, 83,
+ 84, 85, 86, 87, -1, 88, 89, -1, 90, -1,
+ -1, 91, 92, -1, 93, -1, -1, 94, -1, 95,
+ 96, 97, 98, -1, 99, -1, 100, 101, 102, 103,
+ 104, 105, -1, -1, -1, 106, -1, -1, 107, 108,
+ -1, 109, -1, -1, 110, 111, 112, -1, -1, 113,
+ 114, -1, -1, -1, 115, 116, -1, 117, 118, -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, 119, -1, -1, -1, 120,
+ -1, -1, -1, 121
+ };
+
+#ifdef __GNUC__
+__inline
+#ifdef __GNUC_STDC_INLINE__
+__attribute__ ((__gnu_inline__))
+#endif
+#endif
+const struct proposal_token *
+proposal_get_token_static (str, len)
+ register const char *str;
+ register unsigned int len;
+{
+ if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
+ {
+ register int key = hash (str, len);
+
+ if (key <= MAX_HASH_VALUE && key >= 0)
+ {
+ register int index = lookup[key];
+
+ if (index >= 0)
+ {
+ register const char *s = wordlist[index].name;
+
+ if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0')
+ return &wordlist[index];
+ }
+ }
+ }
+ return 0;
+}
diff --git a/src/pluto/cookie.h b/src/libstrongswan/crypto/proposal/proposal_keywords_static.h
index 809d66491..bc421dcc5 100644
--- a/src/pluto/cookie.h
+++ b/src/libstrongswan/crypto/proposal/proposal_keywords_static.h
@@ -1,5 +1,6 @@
-/* cookie generation/verification routines.
- * Copyright (C) 1998-2002 D. Hugh Redelmeier.
+/*
+ * Copyright (C) 2009 Andreas Steffen
+ * Hochschule fuer Technik Rapperswil, Switzerland
*
* 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
@@ -12,11 +13,13 @@
* for more details.
*/
-#include <freeswan.h>
+#ifndef PROPOSAL_KEYWORDS_STATIC_H_
+#define PROPOSAL_KEYWORDS_STATIC_H_
-extern const u_char zero_cookie[COOKIE_SIZE]; /* guaranteed 0 */
+#include "proposal_keywords.h"
-extern void get_cookie(bool initiator, u_int8_t *cookie, int length,
- ip_address *addr);
+const proposal_token_t* proposal_get_token_static(register const char *str,
+ register unsigned int len);
+
+#endif /* PROPOSAL_KEYWORDS_STATIC_H_ */
-#define is_zero_cookie(cookie) all_zero((cookie), COOKIE_SIZE)
diff --git a/src/libstrongswan/crypto/proposal/proposal_keywords.txt b/src/libstrongswan/crypto/proposal/proposal_keywords_static.txt
index 1d04f2dc4..7f8c95757 100644
--- a/src/libstrongswan/crypto/proposal/proposal_keywords.txt
+++ b/src/libstrongswan/crypto/proposal/proposal_keywords_static.txt
@@ -1,5 +1,5 @@
%{
-/* proposal keywords
+/*
* Copyright (C) 2009 Andreas Steffen
* Hochschule fuer Technik Rapperswil, Switzerland
*
@@ -23,10 +23,10 @@
%}
struct proposal_token {
- char *name;
- transform_type_t type;
+ char *name;
+ transform_type_t type;
u_int16_t algorithm;
- u_int16_t keysize;
+ u_int16_t keysize;
};
%%
null, ENCRYPTION_ALGORITHM, ENCR_NULL, 0
diff --git a/src/libstrongswan/crypto/rngs/rng.c b/src/libstrongswan/crypto/rngs/rng.c
index 67fd76910..f8fd50d3f 100644
--- a/src/libstrongswan/crypto/rngs/rng.c
+++ b/src/libstrongswan/crypto/rngs/rng.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -20,3 +21,43 @@ ENUM(rng_quality_names, RNG_WEAK, RNG_TRUE,
"RNG_STRONG",
"RNG_TRUE",
);
+
+/*
+ * Described in header.
+ */
+bool rng_get_bytes_not_zero(rng_t *rng, size_t len, u_int8_t *buffer, bool all)
+{
+ u_int8_t *pos = buffer, *check = buffer + (all ? len : min(1, len));
+
+ if (!rng->get_bytes(rng, len, pos))
+ {
+ return FALSE;
+ }
+
+ for (; pos < check; pos++)
+ {
+ while (*pos == 0)
+ {
+ if (!rng->get_bytes(rng, 1, pos))
+ {
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+
+/*
+ * Described in header.
+ */
+bool rng_allocate_bytes_not_zero(rng_t *rng, size_t len, chunk_t *chunk,
+ bool all)
+{
+ *chunk = chunk_alloc(len);
+ if (!rng_get_bytes_not_zero(rng, len, chunk->ptr, all))
+ {
+ chunk_clear(chunk);
+ return FALSE;
+ }
+ return TRUE;
+}
diff --git a/src/libstrongswan/crypto/rngs/rng.h b/src/libstrongswan/crypto/rngs/rng.h
index 36ef52bb4..aee829d71 100644
--- a/src/libstrongswan/crypto/rngs/rng.h
+++ b/src/libstrongswan/crypto/rngs/rng.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -53,21 +54,53 @@ struct rng_t {
*
* @param len number of bytes to get
* @param buffer pointer where the generated bytes will be written
+ * @return TRUE if bytes successfully written
*/
- void (*get_bytes) (rng_t *this, size_t len, u_int8_t *buffer);
+ bool (*get_bytes)(rng_t *this, size_t len,
+ u_int8_t *buffer) __attribute__((warn_unused_result));
/**
* Generates random bytes and allocate space for them.
*
* @param len number of bytes to get
* @param chunk chunk which will hold generated bytes
+ * @return TRUE if allocation succeeded
*/
- void (*allocate_bytes) (rng_t *this, size_t len, chunk_t *chunk);
+ bool (*allocate_bytes)(rng_t *this, size_t len,
+ chunk_t *chunk) __attribute__((warn_unused_result));
/**
* Destroys a rng object.
*/
- void (*destroy) (rng_t *this);
+ void (*destroy)(rng_t *this);
};
+/**
+ * Wrapper around rng_t.get_bytes() ensuring that either all bytes or at least
+ * the first byte is not zero.
+ *
+ * @param rng rng_t object
+ * @param len number of bytes to get
+ * @param buffer pointer where the generated bytes will be written
+ * @param all TRUE if all bytes have to be non-zero, FALSE for first
+ * @return TRUE if bytes successfully written
+ */
+bool rng_get_bytes_not_zero(rng_t *rng, size_t len, u_int8_t *buffer,
+ bool all) __attribute__((warn_unused_result));
+
+/**
+ * Wrapper around rng_t.allocate_bytes() ensuring that either all bytes or at
+ * least the first byte is not zero.
+ *
+ * @param rng rng_t object
+ * @param len number of bytes to get
+ * @param chunk chunk that stores the generated bytes (allocated)
+ * @param all TRUE if all bytes have to be non-zero, FALSE for first
+ * @return TRUE if bytes successfully written
+ */
+bool rng_allocate_bytes_not_zero(rng_t *rng, size_t len, chunk_t *chunk,
+ bool all) __attribute__((warn_unused_result));
+
+
+
#endif /** RNG_H_ @}*/
diff --git a/src/libstrongswan/crypto/signers/mac_signer.c b/src/libstrongswan/crypto/signers/mac_signer.c
new file mode 100644
index 000000000..7c52aa305
--- /dev/null
+++ b/src/libstrongswan/crypto/signers/mac_signer.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2005-2008 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "mac_signer.h"
+
+typedef struct private_signer_t private_signer_t;
+
+/**
+ * Private data of a mac_signer_t object.
+ */
+struct private_signer_t {
+
+ /**
+ * Public interface
+ */
+ signer_t public;
+
+ /**
+ * MAC to use
+ */
+ mac_t *mac;
+
+ /**
+ * Truncation of MAC output
+ */
+ size_t truncation;
+};
+
+METHOD(signer_t, get_signature, bool,
+ private_signer_t *this, chunk_t data, u_int8_t *buffer)
+{
+ if (buffer)
+ {
+ u_int8_t mac[this->mac->get_mac_size(this->mac)];
+
+ if (!this->mac->get_mac(this->mac, data, mac))
+ {
+ return FALSE;
+ }
+ memcpy(buffer, mac, this->truncation);
+ return TRUE;
+ }
+ return this->mac->get_mac(this->mac, data, NULL);
+}
+
+METHOD(signer_t, allocate_signature, bool,
+ private_signer_t *this, chunk_t data, chunk_t *chunk)
+{
+ if (chunk)
+ {
+ u_int8_t mac[this->mac->get_mac_size(this->mac)];
+
+ if (!this->mac->get_mac(this->mac, data, mac))
+ {
+ return FALSE;
+ }
+ *chunk = chunk_alloc(this->truncation);
+ memcpy(chunk->ptr, mac, this->truncation);
+ return TRUE;
+ }
+ return this->mac->get_mac(this->mac, data, NULL);
+}
+
+METHOD(signer_t, verify_signature, bool,
+ private_signer_t *this, chunk_t data, chunk_t signature)
+{
+ u_int8_t mac[this->mac->get_mac_size(this->mac)];
+
+ if (signature.len != this->truncation)
+ {
+ return FALSE;
+ }
+ return this->mac->get_mac(this->mac, data, mac) &&
+ memeq(signature.ptr, mac, this->truncation);
+}
+
+METHOD(signer_t, get_key_size, size_t,
+ private_signer_t *this)
+{
+ return this->mac->get_mac_size(this->mac);
+}
+
+METHOD(signer_t, get_block_size, size_t,
+ private_signer_t *this)
+{
+ return this->truncation;
+}
+
+METHOD(signer_t, set_key, bool,
+ private_signer_t *this, chunk_t key)
+{
+ return this->mac->set_key(this->mac, key);
+}
+
+METHOD(signer_t, destroy, void,
+ private_signer_t *this)
+{
+ this->mac->destroy(this->mac);
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+signer_t *mac_signer_create(mac_t *mac, size_t len)
+{
+ private_signer_t *this;
+
+ INIT(this,
+ .public = {
+ .get_signature = _get_signature,
+ .allocate_signature = _allocate_signature,
+ .verify_signature = _verify_signature,
+ .get_block_size = _get_block_size,
+ .get_key_size = _get_key_size,
+ .set_key = _set_key,
+ .destroy = _destroy,
+ },
+ .truncation = min(len, mac->get_mac_size(mac)),
+ .mac = mac,
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libstrongswan/plugins/cmac/cmac_signer.h b/src/libstrongswan/crypto/signers/mac_signer.h
index 2e3724471..a50c8cadf 100644
--- a/src/libstrongswan/plugins/cmac/cmac_signer.h
+++ b/src/libstrongswan/crypto/signers/mac_signer.h
@@ -14,34 +14,28 @@
*/
/**
- * @defgroup cmac_signer cmac_signer
- * @{ @ingroup cmac_p
+ * @defgroup mac_signer mac_signer
+ * @{ @ingroup crypto
*/
-#ifndef CMAC_SIGNER_H_
-#define CMAC_SIGNER_H_
+#ifndef MAC_SIGNER_H_
+#define MAC_SIGNER_H_
-typedef struct cmac_signer_t cmac_signer_t;
+typedef struct mac_signer_t mac_signer_t;
+#include <crypto/mac.h>
#include <crypto/signers/signer.h>
/**
- * Implementation of signer_t on CBC symmetric cipher using CMAC, RFC 4494.
- */
-struct cmac_signer_t {
-
- /**
- * Implements signer_t interface.
- */
- signer_t signer;
-};
-
-/**
- * Creates a new cmac_signer_t.
+ * Creates an implementation of the signer_t interface using the provided mac_t
+ * implementation and truncation length.
+ *
+ * @note len will be set to mac_t.get_mac_size() if it is greater than that.
*
- * @param algo algorithm to implement
- * @return cmac_signer_t, NULL if not supported
+ * @param mac mac_t implementation
+ * @param len length of resulting signature
+ * @return mac_signer_t
*/
-cmac_signer_t *cmac_signer_create(integrity_algorithm_t algo);
+signer_t *mac_signer_create(mac_t *mac, size_t len);
-#endif /** CMAC_SIGNER_H_ @}*/
+#endif /** MAC_SIGNER_H_ @}*/
diff --git a/src/libstrongswan/crypto/signers/signer.h b/src/libstrongswan/crypto/signers/signer.h
index c6870e475..9b6bd479a 100644
--- a/src/libstrongswan/crypto/signers/signer.h
+++ b/src/libstrongswan/crypto/signers/signer.h
@@ -91,8 +91,10 @@ struct signer_t {
*
* @param data a chunk containing the data to sign
* @param buffer pointer where the signature will be written
+ * @return TRUE if signature created successfully
*/
- void (*get_signature) (signer_t *this, chunk_t data, u_int8_t *buffer);
+ bool (*get_signature)(signer_t *this, chunk_t data,
+ u_int8_t *buffer) __attribute__((warn_unused_result));
/**
* Generate a signature and allocate space for it.
@@ -102,8 +104,10 @@ struct signer_t {
*
* @param data a chunk containing the data to sign
* @param chunk chunk which will hold the allocated signature
+ * @return TRUE if signature allocated successfully
*/
- void (*allocate_signature) (signer_t *this, chunk_t data, chunk_t *chunk);
+ bool (*allocate_signature)(signer_t *this, chunk_t data,
+ chunk_t *chunk) __attribute__((warn_unused_result));
/**
* Verify a signature.
@@ -116,33 +120,35 @@ struct signer_t {
* @param signature a chunk containing the signature
* @return TRUE, if signature is valid, FALSE otherwise
*/
- bool (*verify_signature) (signer_t *this, chunk_t data, chunk_t signature);
+ bool (*verify_signature)(signer_t *this, chunk_t data, chunk_t signature);
/**
* Get the block size of this signature algorithm.
*
* @return block size in bytes
*/
- size_t (*get_block_size) (signer_t *this);
+ size_t (*get_block_size)(signer_t *this);
/**
* Get the key size of the signature algorithm.
*
* @return key size in bytes
*/
- size_t (*get_key_size) (signer_t *this);
+ size_t (*get_key_size)(signer_t *this);
/**
* Set the key for this object.
*
* @param key key to set
+ * @return TRUE if key set
*/
- void (*set_key) (signer_t *this, chunk_t key);
+ bool (*set_key)(signer_t *this,
+ chunk_t key) __attribute__((warn_unused_result));
/**
* Destroys a signer_t object.
*/
- void (*destroy) (signer_t *this);
+ void (*destroy)(signer_t *this);
};
#endif /** SIGNER_H_ @}*/
diff --git a/src/libstrongswan/crypto/transform.c b/src/libstrongswan/crypto/transform.c
index 1e108f1de..56252971a 100644
--- a/src/libstrongswan/crypto/transform.c
+++ b/src/libstrongswan/crypto/transform.c
@@ -15,12 +15,13 @@
#include <crypto/transform.h>
-ENUM_BEGIN(transform_type_names, UNDEFINED_TRANSFORM_TYPE, AEAD_ALGORITHM,
+ENUM_BEGIN(transform_type_names, UNDEFINED_TRANSFORM_TYPE, COMPRESSION_ALGORITHM,
"UNDEFINED_TRANSFORM_TYPE",
"HASH_ALGORITHM",
"RANDOM_NUMBER_GENERATOR",
- "AEAD_ALGORITHM");
-ENUM_NEXT(transform_type_names, ENCRYPTION_ALGORITHM, EXTENDED_SEQUENCE_NUMBERS, AEAD_ALGORITHM,
+ "AEAD_ALGORITHM",
+ "COMPRESSION_ALGORITHM");
+ENUM_NEXT(transform_type_names, ENCRYPTION_ALGORITHM, EXTENDED_SEQUENCE_NUMBERS, COMPRESSION_ALGORITHM,
"ENCRYPTION_ALGORITHM",
"PSEUDO_RANDOM_FUNCTION",
"INTEGRITY_ALGORITHM",
diff --git a/src/libstrongswan/crypto/transform.h b/src/libstrongswan/crypto/transform.h
index 1393c674c..311df068f 100644
--- a/src/libstrongswan/crypto/transform.h
+++ b/src/libstrongswan/crypto/transform.h
@@ -23,7 +23,7 @@
typedef enum transform_type_t transform_type_t;
-#include <library.h>
+#include <enum.h>
/**
* Type of a transform, as in IKEv2 RFC 3.3.2.
@@ -33,6 +33,7 @@ enum transform_type_t {
HASH_ALGORITHM = 242,
RANDOM_NUMBER_GENERATOR = 243,
AEAD_ALGORITHM = 244,
+ COMPRESSION_ALGORITHM = 245,
ENCRYPTION_ALGORITHM = 1,
PSEUDO_RANDOM_FUNCTION = 2,
INTEGRITY_ALGORITHM = 3,
diff --git a/src/libstrongswan/debug.c b/src/libstrongswan/debug.c
index d6c5b06b6..e8c9e6b98 100644
--- a/src/libstrongswan/debug.c
+++ b/src/libstrongswan/debug.c
@@ -33,6 +33,8 @@ ENUM(debug_names, DBG_DMN, DBG_LIB,
"IMV",
"PTS",
"TLS",
+ "APP",
+ "ESP",
"LIB",
);
@@ -52,6 +54,8 @@ ENUM(debug_lower_names, DBG_DMN, DBG_LIB,
"imv",
"pts",
"tls",
+ "app",
+ "esp",
"lib",
);
diff --git a/src/libstrongswan/debug.h b/src/libstrongswan/debug.h
index 2a6ff98ad..ff4b4a1e9 100644
--- a/src/libstrongswan/debug.h
+++ b/src/libstrongswan/debug.h
@@ -62,6 +62,10 @@ enum debug_t {
DBG_PTS,
/** libtls */
DBG_TLS,
+ /** applications other than daemons */
+ DBG_APP,
+ /** libipsec */
+ DBG_ESP,
/** libstrongswan */
DBG_LIB,
/** number of groups */
diff --git a/src/libstrongswan/eap/eap.c b/src/libstrongswan/eap/eap.c
index efd3ee981..1e4cf11bf 100644
--- a/src/libstrongswan/eap/eap.c
+++ b/src/libstrongswan/eap/eap.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2006 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -13,8 +14,13 @@
* for more details.
*/
+#include <stdlib.h>
+#include <errno.h>
+
#include "eap.h"
+#include <debug.h>
+
ENUM(eap_code_names, EAP_REQUEST, EAP_FAILURE,
"EAP_REQUEST",
"EAP_RESPONSE",
@@ -51,12 +57,12 @@ ENUM_NEXT(eap_type_names, EAP_MSTLV, EAP_MSTLV, EAP_MSCHAPV2,
"EAP_MSTLV");
ENUM_NEXT(eap_type_names, EAP_TNC, EAP_TNC, EAP_MSTLV,
"EAP_TNC");
-ENUM_NEXT(eap_type_names, EAP_DYNAMIC, EAP_EXPERIMENTAL, EAP_TNC,
- "EAP_DYNAMIC",
- "EAP_RADIUS",
+ENUM_NEXT(eap_type_names, EAP_EXPANDED, EAP_DYNAMIC, EAP_TNC,
"EAP_EXPANDED",
- "EAP_EXPERIMENTAL");
-ENUM_END(eap_type_names, EAP_EXPERIMENTAL);
+ "EAP_EXPERIMENTAL",
+ "EAP_RADIUS",
+ "EAP_DYNAMIC");
+ENUM_END(eap_type_names, EAP_DYNAMIC);
ENUM_BEGIN(eap_type_short_names, EAP_IDENTITY, EAP_GTC,
"ID",
@@ -80,12 +86,12 @@ ENUM_NEXT(eap_type_short_names, EAP_MSTLV, EAP_MSTLV, EAP_MSCHAPV2,
"MSTLV");
ENUM_NEXT(eap_type_short_names, EAP_TNC, EAP_TNC, EAP_MSTLV,
"TNC");
-ENUM_NEXT(eap_type_short_names, EAP_DYNAMIC, EAP_EXPERIMENTAL, EAP_TNC,
- "DYN",
- "RAD",
+ENUM_NEXT(eap_type_short_names, EAP_EXPANDED, EAP_DYNAMIC, EAP_TNC,
"EXP",
- "XP");
-ENUM_END(eap_type_short_names, EAP_EXPERIMENTAL);
+ "XP",
+ "RAD",
+ "DYN");
+ENUM_END(eap_type_short_names, EAP_DYNAMIC);
/*
* See header
@@ -108,6 +114,7 @@ eap_type_t eap_type_from_string(char *name)
{"peap", EAP_PEAP},
{"mschapv2", EAP_MSCHAPV2},
{"tnc", EAP_TNC},
+ {"dynamic", EAP_DYNAMIC},
{"radius", EAP_RADIUS},
};
@@ -120,3 +127,56 @@ eap_type_t eap_type_from_string(char *name)
}
return 0;
}
+
+/*
+ * See header
+ */
+eap_vendor_type_t *eap_vendor_type_from_string(char *str)
+{
+ enumerator_t *enumerator;
+ eap_vendor_type_t *result = NULL;
+ eap_type_t type = 0;
+ u_int32_t vendor = 0;
+ char *part, *end;
+
+ /* parse EAP method string of the form: [eap-]type[-vendor] */
+ enumerator = enumerator_create_token(str, "-", " ");
+ while (enumerator->enumerate(enumerator, &part))
+ {
+ if (!type)
+ {
+ if (streq(part, "eap"))
+ { /* skip 'eap' at the beginning */
+ continue;
+ }
+ type = eap_type_from_string(part);
+ if (!type)
+ {
+ type = strtoul(part, &end, 0);
+ if (*end != '\0' || errno)
+ {
+ DBG1(DBG_LIB, "unknown or invalid EAP method: %s", part);
+ break;
+ }
+ }
+ continue;
+ }
+ vendor = strtoul(part, &end, 0);
+ if (*end != '\0' || errno)
+ {
+ DBG1(DBG_LIB, "invalid EAP vendor: %s", part);
+ type = 0;
+ }
+ break;
+ }
+ enumerator->destroy(enumerator);
+
+ if (type)
+ {
+ INIT(result,
+ .type = type,
+ .vendor = vendor,
+ );
+ }
+ return result;
+}
diff --git a/src/libstrongswan/eap/eap.h b/src/libstrongswan/eap/eap.h
index 945e4bc59..0e144b123 100644
--- a/src/libstrongswan/eap/eap.h
+++ b/src/libstrongswan/eap/eap.h
@@ -1,6 +1,8 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2010 Martin Willi
* Copyright (C) 2010 revosec AG
+ * 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
@@ -14,7 +16,7 @@
*/
/**
- * @defgroup eap eap
+ * @defgroup leap eap
* @{ @ingroup libstrongswan
*/
@@ -23,6 +25,7 @@
typedef enum eap_code_t eap_code_t;
typedef enum eap_type_t eap_type_t;
+typedef struct eap_vendor_type_t eap_vendor_type_t;
#include <library.h>
@@ -62,14 +65,14 @@ enum eap_type_t {
EAP_AKA = 23,
EAP_PEAP = 25,
EAP_MSCHAPV2 = 26,
- EAP_MSTLV = 33,
+ EAP_MSTLV = 33,
EAP_TNC = 38,
- /** select EAP method dynamically based on i.e. EAP-Identity */
- EAP_DYNAMIC = 252,
- /** not a method, but an implementation providing different methods */
- EAP_RADIUS = 253,
EAP_EXPANDED = 254,
EAP_EXPERIMENTAL = 255,
+ /** not a method, but an implementation providing different methods */
+ EAP_RADIUS = 256,
+ /** not a method, select method dynamically based on client selection */
+ EAP_DYNAMIC = 257,
};
/**
@@ -83,6 +86,22 @@ extern enum_name_t *eap_type_names;
extern enum_name_t *eap_type_short_names;
/**
+ * Struct that stores EAP type and vendor ID
+ */
+struct eap_vendor_type_t {
+
+ /**
+ * EAP type
+ */
+ eap_type_t type;
+
+ /**
+ * Vendor Id
+ */
+ u_int32_t vendor;
+};
+
+/**
* EAP packet format
*/
typedef struct __attribute__((packed)) {
@@ -101,4 +120,12 @@ typedef struct __attribute__((packed)) {
*/
eap_type_t eap_type_from_string(char *name);
+/**
+ * Parse a string of the form [eap-]type[-vendor].
+ *
+ * @param str EAP method string
+ * @return parsed type (gets allocated), NULL if unknown or failed
+ */
+eap_vendor_type_t *eap_vendor_type_from_string(char *str);
+
#endif /** EAP_H_ @}*/
diff --git a/src/libstrongswan/enum.c b/src/libstrongswan/enum.c
index 5c811bd17..2dc7c5dde 100644
--- a/src/libstrongswan/enum.c
+++ b/src/libstrongswan/enum.c
@@ -60,7 +60,7 @@ int enum_from_name(enum_name_t *e, char *name)
/**
* Described in header.
*/
-int enum_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
+int enum_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
const void *const *args)
{
enum_name_t *ed = *((enum_name_t**)(args[0]));
@@ -70,10 +70,10 @@ int enum_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
if (name == NULL)
{
- return print_in_hook(dst, len, "(%d)", val);
+ return print_in_hook(data, "(%d)", val);
}
else
{
- return print_in_hook(dst, len, "%s", name);
+ return print_in_hook(data, "%s", name);
}
}
diff --git a/src/libstrongswan/enum.h b/src/libstrongswan/enum.h
index d5f169772..840371245 100644
--- a/src/libstrongswan/enum.h
+++ b/src/libstrongswan/enum.h
@@ -130,7 +130,7 @@ int enum_from_name(enum_name_t *e, char *name);
* Arguments are:
* enum_names_t *names, int value
*/
-int enum_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
+int enum_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
const void *const *args);
#endif /** ENUM_H_ @}*/
diff --git a/src/pluto/plugins/xauth/xauth_default_provider.h b/src/libstrongswan/ipsec/ipsec_types.c
index ff1a91d16..e4e927313 100644
--- a/src/pluto/plugins/xauth/xauth_default_provider.h
+++ b/src/libstrongswan/ipsec/ipsec_types.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Andreas Steffen
+ * Copyright (C) 2012 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -13,21 +13,26 @@
* for more details.
*/
-/**
- * @defgroup xauth_default_provider xauth_default_provider
- * @{ @ingroup xauth
- */
-
-#ifndef XAUTH_DEFAULT_PROVIDER_H_
-#define XAUTH_DEFAULT_PROVIDER_H_
-
-#include <xauth/xauth_provider.h>
+#include "ipsec_types.h"
+ENUM(ipsec_mode_names, MODE_TRANSPORT, MODE_DROP,
+ "TRANSPORT",
+ "TUNNEL",
+ "BEET",
+ "PASS",
+ "DROP"
+);
-/**
- * Create an xauth_default_provider instance.
- */
-xauth_provider_t *xauth_default_provider_create();
-
-#endif /** XAUTH_DEFAULT_PROVIDER_H_ @}*/
+ENUM(policy_dir_names, POLICY_IN, POLICY_FWD,
+ "in",
+ "out",
+ "fwd"
+);
+ENUM(ipcomp_transform_names, IPCOMP_NONE, IPCOMP_LZJH,
+ "IPCOMP_NONE",
+ "IPCOMP_OUI",
+ "IPCOMP_DEFLATE",
+ "IPCOMP_LZS",
+ "IPCOMP_LZJH"
+);
diff --git a/src/libstrongswan/ipsec/ipsec_types.h b/src/libstrongswan/ipsec/ipsec_types.h
new file mode 100644
index 000000000..32e55bc50
--- /dev/null
+++ b/src/libstrongswan/ipsec/ipsec_types.h
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup ipsec_types ipsec_types
+ * @{ @ingroup ipsec
+ */
+
+#ifndef IPSEC_TYPES_H_
+#define IPSEC_TYPES_H_
+
+typedef enum ipsec_mode_t ipsec_mode_t;
+typedef enum policy_dir_t policy_dir_t;
+typedef enum policy_type_t policy_type_t;
+typedef enum policy_priority_t policy_priority_t;
+typedef enum ipcomp_transform_t ipcomp_transform_t;
+typedef struct ipsec_sa_cfg_t ipsec_sa_cfg_t;
+typedef struct lifetime_cfg_t lifetime_cfg_t;
+typedef struct mark_t mark_t;
+
+#include <library.h>
+
+/**
+ * Mode of an IPsec SA.
+ */
+enum ipsec_mode_t {
+ /** not using any encapsulation */
+ MODE_NONE = 0,
+ /** transport mode, no inner address */
+ MODE_TRANSPORT = 1,
+ /** tunnel mode, inner and outer addresses */
+ MODE_TUNNEL,
+ /** BEET mode, tunnel mode but fixed, bound inner addresses */
+ MODE_BEET,
+ /** passthrough policy for traffic without an IPsec SA */
+ MODE_PASS,
+ /** drop policy discarding traffic */
+ MODE_DROP
+};
+
+/**
+ * enum names for ipsec_mode_t.
+ */
+extern enum_name_t *ipsec_mode_names;
+
+/**
+ * Direction of a policy. These are equal to those
+ * defined in xfrm.h, but we want to stay implementation
+ * neutral here.
+ */
+enum policy_dir_t {
+ /** Policy for inbound traffic */
+ POLICY_IN = 0,
+ /** Policy for outbound traffic */
+ POLICY_OUT = 1,
+ /** Policy for forwarded traffic */
+ POLICY_FWD = 2,
+};
+
+/**
+ * enum names for policy_dir_t.
+ */
+extern enum_name_t *policy_dir_names;
+
+/**
+ * Type of a policy.
+ */
+enum policy_type_t {
+ /** Normal IPsec policy */
+ POLICY_IPSEC = 1,
+ /** Passthrough policy (traffic is ignored by IPsec) */
+ POLICY_PASS,
+ /** Drop policy (traffic is discarded) */
+ POLICY_DROP,
+};
+
+/**
+ * High-level priority of a policy.
+ */
+enum policy_priority_t {
+ /** Default priority */
+ POLICY_PRIORITY_DEFAULT,
+ /** Priority for trap policies */
+ POLICY_PRIORITY_ROUTED,
+ /** Priority for fallback drop policies */
+ POLICY_PRIORITY_FALLBACK,
+};
+
+/**
+ * IPComp transform IDs, as in RFC 4306
+ */
+enum ipcomp_transform_t {
+ IPCOMP_NONE = 0,
+ IPCOMP_OUI = 1,
+ IPCOMP_DEFLATE = 2,
+ IPCOMP_LZS = 3,
+ IPCOMP_LZJH = 4,
+};
+
+/**
+ * enum strings for ipcomp_transform_t.
+ */
+extern enum_name_t *ipcomp_transform_names;
+
+/**
+ * This struct contains details about IPsec SA(s) tied to a policy.
+ */
+struct ipsec_sa_cfg_t {
+ /** mode of SA (tunnel, transport) */
+ ipsec_mode_t mode;
+ /** unique ID */
+ u_int32_t reqid;
+ /** details about ESP/AH */
+ struct {
+ /** TRUE if this protocol is used */
+ bool use;
+ /** SPI for ESP/AH */
+ u_int32_t spi;
+ } esp, ah;
+ /** details about IPComp */
+ struct {
+ /** the IPComp transform used */
+ u_int16_t transform;
+ /** CPI for IPComp */
+ u_int16_t cpi;
+ } ipcomp;
+};
+
+/**
+ * A lifetime_cfg_t defines the lifetime limits of an SA.
+ *
+ * Set any of these values to 0 to ignore.
+ */
+struct lifetime_cfg_t {
+ struct {
+ /** Limit before the SA gets invalid. */
+ u_int64_t life;
+ /** Limit before the SA gets rekeyed. */
+ u_int64_t rekey;
+ /** The range of a random value subtracted from rekey. */
+ u_int64_t jitter;
+ } time, bytes, packets;
+};
+
+/**
+ * A mark_t defines an optional mark in an IPsec SA.
+ */
+struct mark_t {
+ /** Mark value */
+ u_int32_t value;
+ /** Mark mask */
+ u_int32_t mask;
+};
+
+/**
+ * Special mark value that uses the reqid of the CHILD_SA as mark
+ */
+#define MARK_REQID (0xFFFFFFFF)
+
+#endif /** IPSEC_TYPES_H_ @}*/
diff --git a/src/libstrongswan/library.c b/src/libstrongswan/library.c
index cd6a41f44..1179b468c 100644
--- a/src/libstrongswan/library.c
+++ b/src/libstrongswan/library.c
@@ -23,6 +23,7 @@
#include <utils/identification.h>
#include <utils/host.h>
#include <utils/hashtable.h>
+#include <utils/backtrace.h>
#include <selectors/traffic_selector.h>
#define CHECKSUM_LIBRARY IPSEC_LIB_DIR"/libchecksum.so"
@@ -72,6 +73,7 @@ void library_deinit()
this->public.creds->destroy(this->public.creds);
this->public.encoding->destroy(this->public.encoding);
this->public.crypto->destroy(this->public.crypto);
+ this->public.proposal->destroy(this->public.proposal);
this->public.fetcher->destroy(this->public.fetcher);
this->public.db->destroy(this->public.db);
this->public.printf_hook->destroy(this->public.printf_hook);
@@ -88,6 +90,7 @@ void library_deinit()
}
threads_deinit();
+ backtrace_deinit();
free(this);
lib = NULL;
@@ -146,6 +149,7 @@ bool library_init(char *settings)
);
lib = &this->public;
+ backtrace_init();
threads_init();
#ifdef LEAK_DETECTIVE
@@ -179,6 +183,7 @@ bool library_init(char *settings)
this->objects = hashtable_create((hashtable_hash_t)hash,
(hashtable_equals_t)equals, 4);
this->public.settings = settings_create(settings);
+ this->public.proposal = proposal_keywords_create();
this->public.crypto = crypto_factory_create();
this->public.creds = credential_factory_create();
this->public.credmgr = credential_manager_create();
@@ -204,6 +209,7 @@ bool library_init(char *settings)
return FALSE;
#endif /* INTEGRITY_TEST */
}
+
return TRUE;
}
diff --git a/src/libstrongswan/library.h b/src/libstrongswan/library.h
index 7e76e1927..b79bd91be 100644
--- a/src/libstrongswan/library.h
+++ b/src/libstrongswan/library.h
@@ -43,6 +43,9 @@
* @defgroup fetcher fetcher
* @ingroup libstrongswan
*
+ * @defgroup ipsec ipsec
+ * @ingroup libstrongswan
+ *
* @defgroup plugins plugins
* @ingroup libstrongswan
*
@@ -67,6 +70,10 @@
#ifndef LIBRARY_H_
#define LIBRARY_H_
+#ifndef CONFIG_H_INCLUDED
+# error config.h not included, pass "-include [...]/config.h" to gcc
+#endif
+
#include "printf_hook.h"
#include "utils.h"
#include "chunk.h"
@@ -75,6 +82,7 @@
#include "processing/processor.h"
#include "processing/scheduler.h"
#include "crypto/crypto_factory.h"
+#include "crypto/proposal/proposal_keywords.h"
#include "fetcher/fetcher_manager.h"
#include "database/database_factory.h"
#include "credentials/credential_factory.h"
@@ -113,6 +121,11 @@ struct library_t {
printf_hook_t *printf_hook;
/**
+ * Proposal keywords registry
+ */
+ proposal_keywords_t *proposal;
+
+ /**
* crypto algorithm registry and factory
*/
crypto_factory_t *crypto;
diff --git a/src/libstrongswan/pen/pen.c b/src/libstrongswan/pen/pen.c
index 3dd92218d..a80e949e3 100644
--- a/src/libstrongswan/pen/pen.c
+++ b/src/libstrongswan/pen/pen.c
@@ -17,7 +17,9 @@
ENUM_BEGIN(pen_names, PEN_IETF, PEN_IETF,
"IETF");
-ENUM_NEXT(pen_names, PEN_MICROSOFT, PEN_MICROSOFT, PEN_IETF,
+ENUM_NEXT(pen_names, PEN_IBM, PEN_IBM, PEN_IETF,
+ "IBM");
+ENUM_NEXT(pen_names, PEN_MICROSOFT, PEN_MICROSOFT, PEN_IBM,
"Microsoft");
ENUM_NEXT(pen_names, PEN_OSC, PEN_OSC, PEN_MICROSOFT,
"OSC");
@@ -27,7 +29,9 @@ ENUM_NEXT(pen_names, PEN_FHH, PEN_FHH, PEN_TCG,
"FHH");
ENUM_NEXT(pen_names, PEN_ITA, PEN_ITA, PEN_FHH,
"ITA-HSR");
-ENUM_NEXT(pen_names, PEN_RESERVED, PEN_RESERVED, PEN_ITA,
+ENUM_NEXT(pen_names, PEN_OPENPTS, PEN_OPENPTS, PEN_ITA,
+ "OpenPTS");
+ENUM_NEXT(pen_names, PEN_RESERVED, PEN_RESERVED, PEN_OPENPTS,
"Reserved");
ENUM_END(pen_names, PEN_RESERVED);
diff --git a/src/libstrongswan/pen/pen.h b/src/libstrongswan/pen/pen.h
index 396cc7199..78b6e4df2 100644
--- a/src/libstrongswan/pen/pen.h
+++ b/src/libstrongswan/pen/pen.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
+ * Copyright (C) 2011-2012 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -27,18 +27,38 @@
#include <library.h>
typedef enum pen_t pen_t;
+typedef struct pen_type_t pen_type_t;
enum pen_t {
PEN_IETF = 0x000000, /* 0 */
+ PEN_IBM = 0x000002, /* 2 */
PEN_MICROSOFT = 0x000137, /* 311 */
PEN_OSC = 0x002358, /* 9048 */
PEN_TCG = 0x005597, /* 21911 */
PEN_FHH = 0x0080ab, /* 32939 */
PEN_ITA = 0x00902a, /* 36906 */
+ PEN_OPENPTS = 0x00950e, /* 38158 */
PEN_RESERVED = 0xffffff, /* 16777215 */
};
/**
+ * Vendor specific type
+ */
+struct pen_type_t {
+ pen_t vendor_id;
+ u_int32_t type;
+};
+
+/**
+ * Create a pen_type_t struct
+ */
+static inline pen_type_t pen_type_create(pen_t vendor_id, u_int32_t type)
+{
+ pen_type_t pen_type = {vendor_id, type};
+ return pen_type;
+}
+
+/**
* enum names for pen_t.
*/
extern enum_name_t *pen_names;
diff --git a/src/libstrongswan/plugins/aes/Makefile.in b/src/libstrongswan/plugins/aes/Makefile.in
index 53eecbe8d..c09cf66a7 100644
--- a/src/libstrongswan/plugins/aes/Makefile.in
+++ b/src/libstrongswan/plugins/aes/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -82,7 +83,7 @@ libstrongswan_aes_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(libstrongswan_aes_la_LDFLAGS) $(LDFLAGS) -o $@
@MONOLITHIC_FALSE@am_libstrongswan_aes_la_rpath = -rpath $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_aes_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -108,6 +109,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -202,11 +204,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -223,11 +228,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -243,6 +249,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -252,7 +259,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/aes/aes_crypter.c b/src/libstrongswan/plugins/aes/aes_crypter.c
index 2a1fed944..6b3d03cea 100644
--- a/src/libstrongswan/plugins/aes/aes_crypter.c
+++ b/src/libstrongswan/plugins/aes/aes_crypter.c
@@ -1331,7 +1331,7 @@ static void decrypt_block(const private_aes_crypter_t *this, const unsigned char
state_out(out_blk, b0);
}
-METHOD(crypter_t, decrypt, void,
+METHOD(crypter_t, decrypt, bool,
private_aes_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *decrypted)
{
int pos;
@@ -1371,9 +1371,10 @@ METHOD(crypter_t, decrypt, void,
out-=16;
pos-=16;
}
+ return TRUE;
}
-METHOD(crypter_t, encrypt, void,
+METHOD(crypter_t, encrypt, bool,
private_aes_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *encrypted)
{
int pos;
@@ -1408,6 +1409,7 @@ METHOD(crypter_t, encrypt, void,
out+=16;
pos+=16;
}
+ return TRUE;
}
METHOD(crypter_t, get_block_size, size_t,
@@ -1428,7 +1430,7 @@ METHOD(crypter_t, get_key_size, size_t,
return this->key_size;
}
-METHOD(crypter_t, set_key, void,
+METHOD(crypter_t, set_key, bool,
private_aes_crypter_t *this, chunk_t key)
{
u_int32_t *kf, *kt, rci, f = 0;
@@ -1513,6 +1515,7 @@ METHOD(crypter_t, set_key, void,
}
cpy(kt, kf);
}
+ return TRUE;
}
METHOD(crypter_t, destroy, void,
diff --git a/src/libstrongswan/plugins/af_alg/Makefile.in b/src/libstrongswan/plugins/af_alg/Makefile.in
index 679e883e1..d3da24718 100644
--- a/src/libstrongswan/plugins/af_alg/Makefile.in
+++ b/src/libstrongswan/plugins/af_alg/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -86,7 +87,7 @@ libstrongswan_af_alg_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@MONOLITHIC_FALSE@am_libstrongswan_af_alg_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_af_alg_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -112,6 +113,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -206,11 +208,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -227,11 +232,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -247,6 +253,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -256,7 +263,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/af_alg/af_alg_crypter.c b/src/libstrongswan/plugins/af_alg/af_alg_crypter.c
index 9c547140d..5d0976d95 100644
--- a/src/libstrongswan/plugins/af_alg/af_alg_crypter.c
+++ b/src/libstrongswan/plugins/af_alg/af_alg_crypter.c
@@ -131,32 +131,26 @@ static size_t lookup_alg(encryption_algorithm_t algo, char **name,
return 0;
}
-METHOD(crypter_t, decrypt, void,
+METHOD(crypter_t, decrypt, bool,
private_af_alg_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
{
if (dst)
{
*dst = chunk_alloc(data.len);
- this->ops->crypt(this->ops, ALG_OP_DECRYPT, iv, data, dst->ptr);
- }
- else
- {
- this->ops->crypt(this->ops, ALG_OP_DECRYPT, iv, data, data.ptr);
+ return this->ops->crypt(this->ops, ALG_OP_DECRYPT, iv, data, dst->ptr);
}
+ return this->ops->crypt(this->ops, ALG_OP_DECRYPT, iv, data, data.ptr);
}
-METHOD(crypter_t, encrypt, void,
+METHOD(crypter_t, encrypt, bool,
private_af_alg_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
{
if (dst)
{
*dst = chunk_alloc(data.len);
- this->ops->crypt(this->ops, ALG_OP_ENCRYPT, iv, data, dst->ptr);
- }
- else
- {
- this->ops->crypt(this->ops, ALG_OP_ENCRYPT, iv, data, data.ptr);
+ return this->ops->crypt(this->ops, ALG_OP_ENCRYPT, iv, data, dst->ptr);
}
+ return this->ops->crypt(this->ops, ALG_OP_ENCRYPT, iv, data, data.ptr);
}
METHOD(crypter_t, get_block_size, size_t,
@@ -177,10 +171,10 @@ METHOD(crypter_t, get_key_size, size_t,
return this->keymat_size;
}
-METHOD(crypter_t, set_key, void,
+METHOD(crypter_t, set_key, bool,
private_af_alg_crypter_t *this, chunk_t key)
{
- this->ops->set_key(this->ops, key);
+ return this->ops->set_key(this->ops, key);
}
METHOD(crypter_t, destroy, void,
diff --git a/src/libstrongswan/plugins/af_alg/af_alg_hasher.c b/src/libstrongswan/plugins/af_alg/af_alg_hasher.c
index ef2350497..47a6e5e0e 100644
--- a/src/libstrongswan/plugins/af_alg/af_alg_hasher.c
+++ b/src/libstrongswan/plugins/af_alg/af_alg_hasher.c
@@ -99,30 +99,28 @@ METHOD(hasher_t, get_hash_size, size_t,
return this->size;
}
-METHOD(hasher_t, reset, void,
+METHOD(hasher_t, reset, bool,
private_af_alg_hasher_t *this)
{
this->ops->reset(this->ops);
+ return TRUE;
}
-METHOD(hasher_t, get_hash, void,
+METHOD(hasher_t, get_hash, bool,
private_af_alg_hasher_t *this, chunk_t chunk, u_int8_t *hash)
{
- this->ops->hash(this->ops, chunk, hash, this->size);
+ return this->ops->hash(this->ops, chunk, hash, this->size);
}
-METHOD(hasher_t, allocate_hash, void,
+METHOD(hasher_t, allocate_hash, bool,
private_af_alg_hasher_t *this, chunk_t chunk, chunk_t *hash)
{
if (hash)
{
*hash = chunk_alloc(get_hash_size(this));
- get_hash(this, chunk, hash->ptr);
- }
- else
- {
- get_hash(this, chunk, NULL);
+ return get_hash(this, chunk, hash->ptr);
}
+ return get_hash(this, chunk, NULL);
}
METHOD(hasher_t, destroy, void,
diff --git a/src/libstrongswan/plugins/af_alg/af_alg_ops.c b/src/libstrongswan/plugins/af_alg/af_alg_ops.c
index a7b5de264..7fe47c578 100644
--- a/src/libstrongswan/plugins/af_alg/af_alg_ops.c
+++ b/src/libstrongswan/plugins/af_alg/af_alg_ops.c
@@ -54,7 +54,7 @@ METHOD(af_alg_ops_t, reset, void,
}
}
-METHOD(af_alg_ops_t, hash, void,
+METHOD(af_alg_ops_t, hash, bool,
private_af_alg_ops_t *this, chunk_t data, char *out, size_t outlen)
{
ssize_t len;
@@ -62,39 +62,52 @@ METHOD(af_alg_ops_t, hash, void,
while (this->op == -1)
{
this->op = accept(this->tfm, NULL, 0);
- if (this->op == -1)
+ if (this->op == -1 && errno != EINTR)
{
DBG1(DBG_LIB, "opening AF_ALG hasher failed: %s", strerror(errno));
- sleep(1);
+ return FALSE;
}
}
+
do
{
len = send(this->op, data.ptr, data.len, out ? 0 : MSG_MORE);
if (len == -1)
{
+ if (errno == EINTR)
+ {
+ continue;
+ }
DBG1(DBG_LIB, "writing to AF_ALG hasher failed: %s", strerror(errno));
- sleep(1);
- }
- else
- {
- data = chunk_skip(data, len);
+ return FALSE;
}
+ data = chunk_skip(data, len);
}
while (data.len);
if (out)
{
- while (read(this->op, out, outlen) != outlen)
+ while (outlen)
{
- DBG1(DBG_LIB, "reading AF_ALG hasher failed: %s", strerror(errno));
- sleep(1);
+ len = read(this->op, out, outlen);
+ if (len == -1)
+ {
+ if (errno == EINTR)
+ {
+ continue;
+ }
+ DBG1(DBG_LIB, "reading AF_ALG hasher failed: %s", strerror(errno));
+ return FALSE;
+ }
+ outlen -= len;
+ out += len;
}
reset(this);
}
+ return TRUE;
}
-METHOD(af_alg_ops_t, crypt, void,
+METHOD(af_alg_ops_t, crypt, bool,
private_af_alg_ops_t *this, u_int32_t type, chunk_t iv, chunk_t data,
char *out)
{
@@ -107,11 +120,16 @@ METHOD(af_alg_ops_t, crypt, void,
ssize_t len;
int op;
- while ((op = accept(this->tfm, NULL, 0)) == -1)
+ do
{
- DBG1(DBG_LIB, "accepting AF_ALG crypter failed: %s", strerror(errno));
- sleep(1);
+ op = accept(this->tfm, NULL, 0);
+ if (op == -1 && errno != EINTR)
+ {
+ DBG1(DBG_LIB, "accepting AF_ALG crypter failed: %s", strerror(errno));
+ return FALSE;
+ }
}
+ while (op == -1);
memset(buf, 0, sizeof(buf));
@@ -143,30 +161,39 @@ METHOD(af_alg_ops_t, crypt, void,
len = sendmsg(op, &msg, 0);
if (len == -1)
{
- DBG1(DBG_LIB, "writing to AF_ALG crypter failed: %s",
- strerror(errno));
- sleep(1);
- continue;
+ if (errno == EINTR)
+ {
+ continue;
+ }
+ DBG1(DBG_LIB, "writing to AF_ALG crypter failed: %s", strerror(errno));
+ return FALSE;
}
- if (read(op, out, len) != len)
+ while (read(op, out, len) != len)
{
- DBG1(DBG_LIB, "reading from AF_ALG crypter failed: %s",
- strerror(errno));
+ if (errno != EINTR)
+ {
+ DBG1(DBG_LIB, "reading from AF_ALG crypter failed: %s",
+ strerror(errno));
+ return FALSE;
+ }
}
data = chunk_skip(data, len);
/* no IV for subsequent data chunks */
msg.msg_controllen = 0;
}
close(op);
+ return TRUE;
}
-METHOD(af_alg_ops_t, set_key, void,
+METHOD(af_alg_ops_t, set_key, bool,
private_af_alg_ops_t *this, chunk_t key)
{
if (setsockopt(this->tfm, SOL_ALG, ALG_SET_KEY, key.ptr, key.len) == -1)
{
DBG1(DBG_LIB, "setting AF_ALG key failed: %s", strerror(errno));
+ return FALSE;
}
+ return TRUE;
}
METHOD(af_alg_ops_t, destroy, void,
diff --git a/src/libstrongswan/plugins/af_alg/af_alg_ops.h b/src/libstrongswan/plugins/af_alg/af_alg_ops.h
index ad164029f..e34f22977 100644
--- a/src/libstrongswan/plugins/af_alg/af_alg_ops.h
+++ b/src/libstrongswan/plugins/af_alg/af_alg_ops.h
@@ -46,8 +46,9 @@ struct af_alg_ops_t {
* @param data data to hash
* @param out buffer to write hash to, NULL for append mode
* @param outlen number of bytes to read into out
+ * @return TRUE if successful
*/
- void (*hash)(af_alg_ops_t *this, chunk_t data, char *out, size_t outlen);
+ bool (*hash)(af_alg_ops_t *this, chunk_t data, char *out, size_t outlen);
/**
* Reset hasher state.
@@ -61,16 +62,18 @@ struct af_alg_ops_t {
* @param iv iv to use
* @param data data to encrypt/decrypt
* @param out buffer write processed data to
+ * @return TRUE if successful
*/
- void (*crypt)(af_alg_ops_t *this, u_int32_t type, chunk_t iv, chunk_t data,
+ bool (*crypt)(af_alg_ops_t *this, u_int32_t type, chunk_t iv, chunk_t data,
char *out);
/**
* Set the key for en-/decryption or HMAC/XCBC operations.
*
* @param key key to set for transform
+ * @return TRUE if successful
*/
- void (*set_key)(af_alg_ops_t *this, chunk_t key);
+ bool (*set_key)(af_alg_ops_t *this, chunk_t key);
/**
* Destroy a af_alg_ops_t.
diff --git a/src/libstrongswan/plugins/af_alg/af_alg_prf.c b/src/libstrongswan/plugins/af_alg/af_alg_prf.c
index a7912291f..720738a84 100644
--- a/src/libstrongswan/plugins/af_alg/af_alg_prf.c
+++ b/src/libstrongswan/plugins/af_alg/af_alg_prf.c
@@ -105,24 +105,21 @@ static size_t lookup_alg(pseudo_random_function_t algo, char **name, bool *xcbc)
return 0;
}
-METHOD(prf_t, get_bytes, void,
+METHOD(prf_t, get_bytes, bool,
private_af_alg_prf_t *this, chunk_t seed, u_int8_t *buffer)
{
- this->ops->hash(this->ops, seed, buffer, this->block_size);
+ return this->ops->hash(this->ops, seed, buffer, this->block_size);
}
-METHOD(prf_t, allocate_bytes, void,
+METHOD(prf_t, allocate_bytes, bool,
private_af_alg_prf_t *this, chunk_t seed, chunk_t *chunk)
{
if (chunk)
{
*chunk = chunk_alloc(this->block_size);
- get_bytes(this, seed, chunk->ptr);
- }
- else
- {
- get_bytes(this, seed, NULL);
+ return get_bytes(this, seed, chunk->ptr);
}
+ return get_bytes(this, seed, NULL);
}
METHOD(prf_t, get_block_size, size_t,
@@ -137,7 +134,7 @@ METHOD(prf_t, get_key_size, size_t,
return this->block_size;
}
-METHOD(prf_t, set_key, void,
+METHOD(prf_t, set_key, bool,
private_af_alg_prf_t *this, chunk_t key)
{
char buf[this->block_size];
@@ -155,12 +152,15 @@ METHOD(prf_t, set_key, void,
else if (key.len > this->block_size)
{
memset(buf, 0, this->block_size);
- this->ops->set_key(this->ops, chunk_from_thing(buf));
- this->ops->hash(this->ops, key, buf, this->block_size);
+ if (!this->ops->set_key(this->ops, chunk_from_thing(buf)) ||
+ !this->ops->hash(this->ops, key, buf, this->block_size))
+ {
+ return FALSE;
+ }
key = chunk_from_thing(buf);
}
}
- this->ops->set_key(this->ops, key);
+ return this->ops->set_key(this->ops, key);
}
METHOD(prf_t, destroy, void,
diff --git a/src/libstrongswan/plugins/af_alg/af_alg_signer.c b/src/libstrongswan/plugins/af_alg/af_alg_signer.c
index 6cd79f8f2..d995b1351 100644
--- a/src/libstrongswan/plugins/af_alg/af_alg_signer.c
+++ b/src/libstrongswan/plugins/af_alg/af_alg_signer.c
@@ -107,24 +107,21 @@ static size_t lookup_alg(integrity_algorithm_t algo, char **name,
return 0;
}
-METHOD(signer_t, get_signature, void,
+METHOD(signer_t, get_signature, bool,
private_af_alg_signer_t *this, chunk_t data, u_int8_t *buffer)
{
- this->ops->hash(this->ops, data, buffer, this->block_size);
+ return this->ops->hash(this->ops, data, buffer, this->block_size);
}
-METHOD(signer_t, allocate_signature, void,
+METHOD(signer_t, allocate_signature, bool,
private_af_alg_signer_t *this, chunk_t data, chunk_t *chunk)
{
if (chunk)
{
*chunk = chunk_alloc(this->block_size);
- get_signature(this, data, chunk->ptr);
- }
- else
- {
- get_signature(this, data, NULL);
+ return get_signature(this, data, chunk->ptr);
}
+ return get_signature(this, data, NULL);
}
METHOD(signer_t, verify_signature, bool,
@@ -136,7 +133,10 @@ METHOD(signer_t, verify_signature, bool,
{
return FALSE;
}
- get_signature(this, data, sig);
+ if (!get_signature(this, data, sig))
+ {
+ return FALSE;
+ }
return memeq(signature.ptr, sig, signature.len);
}
@@ -152,10 +152,10 @@ METHOD(signer_t, get_block_size, size_t,
return this->block_size;
}
-METHOD(signer_t, set_key, void,
+METHOD(signer_t, set_key, bool,
private_af_alg_signer_t *this, chunk_t key)
{
- this->ops->set_key(this->ops, key);
+ return this->ops->set_key(this->ops, key);
}
METHOD(signer_t, destroy, void,
diff --git a/src/libstrongswan/plugins/agent/Makefile.in b/src/libstrongswan/plugins/agent/Makefile.in
index 452233b85..8e606bf39 100644
--- a/src/libstrongswan/plugins/agent/Makefile.in
+++ b/src/libstrongswan/plugins/agent/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -84,7 +85,7 @@ libstrongswan_agent_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@MONOLITHIC_FALSE@am_libstrongswan_agent_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_agent_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -110,6 +111,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -204,11 +206,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -225,11 +230,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -245,6 +251,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -254,7 +261,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/blowfish/Makefile.in b/src/libstrongswan/plugins/blowfish/Makefile.in
index 52f5fa98a..c8b904eb9 100644
--- a/src/libstrongswan/plugins/blowfish/Makefile.in
+++ b/src/libstrongswan/plugins/blowfish/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -86,7 +87,7 @@ libstrongswan_blowfish_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_blowfish_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_blowfish_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -112,6 +113,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -206,11 +208,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -227,11 +232,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -247,6 +253,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -256,7 +263,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/blowfish/blowfish_crypter.c b/src/libstrongswan/plugins/blowfish/blowfish_crypter.c
index fc3649b36..253f9b4a4 100644
--- a/src/libstrongswan/plugins/blowfish/blowfish_crypter.c
+++ b/src/libstrongswan/plugins/blowfish/blowfish_crypter.c
@@ -87,7 +87,7 @@ struct private_blowfish_crypter_t {
u_int32_t key_size;
};
-METHOD(crypter_t, decrypt, void,
+METHOD(crypter_t, decrypt, bool,
private_blowfish_crypter_t *this, chunk_t data, chunk_t iv,
chunk_t *decrypted)
{
@@ -108,9 +108,11 @@ METHOD(crypter_t, decrypt, void,
BF_cbc_encrypt(in, out, data.len, &this->schedule, iv.ptr, 0);
free(iv.ptr);
+
+ return TRUE;
}
-METHOD(crypter_t, encrypt, void,
+METHOD(crypter_t, encrypt, bool,
private_blowfish_crypter_t *this, chunk_t data, chunk_t iv,
chunk_t *encrypted)
{
@@ -131,6 +133,8 @@ METHOD(crypter_t, encrypt, void,
BF_cbc_encrypt(in, out, data.len, &this->schedule, iv.ptr, 1);
free(iv.ptr);
+
+ return TRUE;
}
METHOD(crypter_t, get_block_size, size_t,
@@ -151,10 +155,11 @@ METHOD(crypter_t, get_key_size, size_t,
return this->key_size;
}
-METHOD(crypter_t, set_key, void,
+METHOD(crypter_t, set_key, bool,
private_blowfish_crypter_t *this, chunk_t key)
{
BF_set_key(&this->schedule, key.len , key.ptr);
+ return TRUE;
}
METHOD(crypter_t, destroy, void,
diff --git a/src/libstrongswan/plugins/ccm/Makefile.in b/src/libstrongswan/plugins/ccm/Makefile.in
index 2ffe6194b..bb094f04c 100644
--- a/src/libstrongswan/plugins/ccm/Makefile.in
+++ b/src/libstrongswan/plugins/ccm/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -82,7 +83,7 @@ libstrongswan_ccm_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(libstrongswan_ccm_la_LDFLAGS) $(LDFLAGS) -o $@
@MONOLITHIC_FALSE@am_libstrongswan_ccm_la_rpath = -rpath $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_ccm_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -108,6 +109,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -202,11 +204,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -223,11 +228,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -243,6 +249,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -252,7 +259,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/ccm/ccm_aead.c b/src/libstrongswan/plugins/ccm/ccm_aead.c
index 0d2a56a49..0e2f9b75f 100644
--- a/src/libstrongswan/plugins/ccm/ccm_aead.c
+++ b/src/libstrongswan/plugins/ccm/ccm_aead.c
@@ -126,7 +126,7 @@ static void build_ctr(private_ccm_aead_t *this, u_int32_t i, chunk_t iv,
/**
* En-/Decrypt data
*/
-static void crypt_data(private_ccm_aead_t *this, chunk_t iv,
+static bool crypt_data(private_ccm_aead_t *this, chunk_t iv,
chunk_t in, chunk_t out)
{
char ctr[BLOCK_SIZE];
@@ -139,8 +139,11 @@ static void crypt_data(private_ccm_aead_t *this, chunk_t iv,
while (in.len > 0)
{
memcpy(block, ctr, BLOCK_SIZE);
- this->crypter->encrypt(this->crypter, chunk_from_thing(block),
- chunk_from_thing(zero), NULL);
+ if (!this->crypter->encrypt(this->crypter, chunk_from_thing(block),
+ chunk_from_thing(zero), NULL))
+ {
+ return FALSE;
+ }
chunk_increment(chunk_from_thing(ctr));
if (in.ptr != out.ptr)
@@ -151,12 +154,13 @@ static void crypt_data(private_ccm_aead_t *this, chunk_t iv,
in = chunk_skip(in, BLOCK_SIZE);
out = chunk_skip(out, BLOCK_SIZE);
}
+ return TRUE;
}
/**
* En-/Decrypt the ICV
*/
-static void crypt_icv(private_ccm_aead_t *this, chunk_t iv, char *icv)
+static bool crypt_icv(private_ccm_aead_t *this, chunk_t iv, char *icv)
{
char ctr[BLOCK_SIZE];
char zero[BLOCK_SIZE];
@@ -164,15 +168,19 @@ static void crypt_icv(private_ccm_aead_t *this, chunk_t iv, char *icv)
build_ctr(this, 0, iv, ctr);
memset(zero, 0, BLOCK_SIZE);
- this->crypter->encrypt(this->crypter, chunk_from_thing(ctr),
- chunk_from_thing(zero), NULL);
+ if (!this->crypter->encrypt(this->crypter, chunk_from_thing(ctr),
+ chunk_from_thing(zero), NULL))
+ {
+ return FALSE;
+ }
memxor(icv, ctr, this->icv_size);
+ return TRUE;
}
/**
* Create the ICV
*/
-static void create_icv(private_ccm_aead_t *this, chunk_t plain, chunk_t assoc,
+static bool create_icv(private_ccm_aead_t *this, chunk_t plain, chunk_t assoc,
chunk_t iv, char *icv)
{
char zero[BLOCK_SIZE];
@@ -217,14 +225,19 @@ static void create_icv(private_ccm_aead_t *this, chunk_t plain, chunk_t assoc,
memset(pos, 0, len);
/* encrypt inline with CBC, zero IV */
- this->crypter->encrypt(this->crypter, chunk, chunk_from_thing(zero), NULL);
+ if (!this->crypter->encrypt(this->crypter, chunk,
+ chunk_from_thing(zero), NULL))
+ {
+ free(chunk.ptr);
+ return FALSE;
+ }
/* copy last icv_size bytes as ICV to output */
memcpy(icv, chunk.ptr + chunk.len - BLOCK_SIZE, this->icv_size);
- /* encrypt the ICV value */
- crypt_icv(this, iv, icv);
-
free(chunk.ptr);
+
+ /* encrypt the ICV value */
+ return crypt_icv(this, iv, icv);
}
/**
@@ -235,26 +248,22 @@ static bool verify_icv(private_ccm_aead_t *this, chunk_t plain, chunk_t assoc,
{
char buf[this->icv_size];
- create_icv(this, plain, assoc, iv, buf);
-
- return memeq(buf, icv, this->icv_size);
+ return create_icv(this, plain, assoc, iv, buf) &&
+ memeq(buf, icv, this->icv_size);
}
-METHOD(aead_t, encrypt, void,
+METHOD(aead_t, encrypt, bool,
private_ccm_aead_t *this, chunk_t plain, chunk_t assoc, chunk_t iv,
chunk_t *encrypted)
{
if (encrypted)
{
*encrypted = chunk_alloc(plain.len + this->icv_size);
- create_icv(this, plain, assoc, iv, encrypted->ptr + plain.len);
- crypt_data(this, iv, plain, *encrypted);
- }
- else
- {
- create_icv(this, plain, assoc, iv, plain.ptr + plain.len);
- crypt_data(this, iv, plain, plain);
+ return create_icv(this, plain, assoc, iv, encrypted->ptr + plain.len) &&
+ crypt_data(this, iv, plain, *encrypted);
}
+ return create_icv(this, plain, assoc, iv, plain.ptr + plain.len) &&
+ crypt_data(this, iv, plain, plain);
}
METHOD(aead_t, decrypt, bool,
@@ -269,16 +278,13 @@ METHOD(aead_t, decrypt, bool,
if (plain)
{
*plain = chunk_alloc(encrypted.len);
- crypt_data(this, iv, encrypted, *plain);
- return verify_icv(this, *plain, assoc, iv,
- encrypted.ptr + encrypted.len);
- }
- else
- {
- crypt_data(this, iv, encrypted, encrypted);
- return verify_icv(this, encrypted, assoc, iv,
+ return crypt_data(this, iv, encrypted, *plain) &&
+ verify_icv(this, *plain, assoc, iv,
encrypted.ptr + encrypted.len);
}
+ return crypt_data(this, iv, encrypted, encrypted) &&
+ verify_icv(this, encrypted, assoc, iv,
+ encrypted.ptr + encrypted.len);
}
METHOD(aead_t, get_block_size, size_t,
@@ -305,12 +311,12 @@ METHOD(aead_t, get_key_size, size_t,
return this->crypter->get_key_size(this->crypter) + SALT_SIZE;
}
-METHOD(aead_t, set_key, void,
+METHOD(aead_t, set_key, bool,
private_ccm_aead_t *this, chunk_t key)
{
memcpy(this->salt, key.ptr + key.len - SALT_SIZE, SALT_SIZE);
key.len -= SALT_SIZE;
- this->crypter->set_key(this->crypter, key);
+ return this->crypter->set_key(this->crypter, key);
}
METHOD(aead_t, destroy, void,
diff --git a/src/libstrongswan/plugins/cmac/Makefile.am b/src/libstrongswan/plugins/cmac/Makefile.am
index ce0104f11..5cac3959c 100644
--- a/src/libstrongswan/plugins/cmac/Makefile.am
+++ b/src/libstrongswan/plugins/cmac/Makefile.am
@@ -10,7 +10,6 @@ plugin_LTLIBRARIES = libstrongswan-cmac.la
endif
libstrongswan_cmac_la_SOURCES = \
- cmac_plugin.h cmac_plugin.c cmac.h cmac.c \
- cmac_prf.h cmac_prf.c cmac_signer.h cmac_signer.c
+ cmac_plugin.h cmac_plugin.c cmac.h cmac.c
libstrongswan_cmac_la_LDFLAGS = -module -avoid-version
diff --git a/src/libstrongswan/plugins/cmac/Makefile.in b/src/libstrongswan/plugins/cmac/Makefile.in
index 093e63f32..eba059a29 100644
--- a/src/libstrongswan/plugins/cmac/Makefile.in
+++ b/src/libstrongswan/plugins/cmac/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -75,15 +76,14 @@ am__base_list = \
am__installdirs = "$(DESTDIR)$(plugindir)"
LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_cmac_la_LIBADD =
-am_libstrongswan_cmac_la_OBJECTS = cmac_plugin.lo cmac.lo cmac_prf.lo \
- cmac_signer.lo
+am_libstrongswan_cmac_la_OBJECTS = cmac_plugin.lo cmac.lo
libstrongswan_cmac_la_OBJECTS = $(am_libstrongswan_cmac_la_OBJECTS)
libstrongswan_cmac_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libstrongswan_cmac_la_LDFLAGS) $(LDFLAGS) -o $@
@MONOLITHIC_FALSE@am_libstrongswan_cmac_la_rpath = -rpath $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_cmac_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -109,6 +109,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -203,11 +204,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -224,11 +228,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -244,6 +249,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -253,7 +259,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -286,8 +291,7 @@ AM_CFLAGS = -rdynamic
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-cmac.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-cmac.la
libstrongswan_cmac_la_SOURCES = \
- cmac_plugin.h cmac_plugin.c cmac.h cmac.c \
- cmac_prf.h cmac_prf.c cmac_signer.h cmac_signer.c
+ cmac_plugin.h cmac_plugin.c cmac.h cmac.c
libstrongswan_cmac_la_LDFLAGS = -module -avoid-version
all: all-am
@@ -375,8 +379,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmac.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmac_plugin.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmac_prf.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmac_signer.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
diff --git a/src/libstrongswan/plugins/cmac/cmac.c b/src/libstrongswan/plugins/cmac/cmac.c
index 5ec7073c7..725d02d76 100644
--- a/src/libstrongswan/plugins/cmac/cmac.c
+++ b/src/libstrongswan/plugins/cmac/cmac.c
@@ -18,20 +18,23 @@
#include "cmac.h"
#include <debug.h>
+#include <crypto/mac.h>
+#include <crypto/prfs/mac_prf.h>
+#include <crypto/signers/mac_signer.h>
-typedef struct private_cmac_t private_cmac_t;
+typedef struct private_mac_t private_mac_t;
/**
- * Private data of a cmac_t object.
+ * Private data of a mac_t object.
*
* The variable names are the same as in the RFC.
*/
-struct private_cmac_t {
+struct private_mac_t {
/**
* Public interface.
*/
- cmac_t public;
+ mac_t public;
/**
* Block size, in bytes
@@ -72,7 +75,7 @@ struct private_cmac_t {
/**
* process supplied data, but do not run final operation
*/
-static void update(private_cmac_t *this, chunk_t data)
+static bool update(private_mac_t *this, chunk_t data)
{
chunk_t iv;
@@ -80,7 +83,7 @@ static void update(private_cmac_t *this, chunk_t data)
{ /* no complete block (or last block), just copy into remaining */
memcpy(this->remaining + this->remaining_bytes, data.ptr, data.len);
this->remaining_bytes += data.len;
- return;
+ return TRUE;
}
iv = chunk_alloca(this->b);
@@ -97,7 +100,10 @@ static void update(private_cmac_t *this, chunk_t data)
this->b - this->remaining_bytes);
data = chunk_skip(data, this->b - this->remaining_bytes);
memxor(this->t, this->remaining, this->b);
- this->k->encrypt(this->k, chunk_create(this->t, this->b), iv, NULL);
+ if (!this->k->encrypt(this->k, chunk_create(this->t, this->b), iv, NULL))
+ {
+ return FALSE;
+ }
/* process blocks M_2 ... M_n-1 */
while (data.len > this->b)
@@ -105,18 +111,23 @@ static void update(private_cmac_t *this, chunk_t data)
memcpy(this->remaining, data.ptr, this->b);
data = chunk_skip(data, this->b);
memxor(this->t, this->remaining, this->b);
- this->k->encrypt(this->k, chunk_create(this->t, this->b), iv, NULL);
+ if (!this->k->encrypt(this->k, chunk_create(this->t, this->b), iv, NULL))
+ {
+ return FALSE;
+ }
}
/* store remaining bytes of block M_n */
memcpy(this->remaining, data.ptr, data.len);
this->remaining_bytes = data.len;
+
+ return TRUE;
}
/**
* process last block M_last
*/
-static void final(private_cmac_t *this, u_int8_t *out)
+static bool final(private_mac_t *this, u_int8_t *out)
{
chunk_t iv;
@@ -153,29 +164,38 @@ static void final(private_cmac_t *this, u_int8_t *out)
* T := AES-128(K,T);
*/
memxor(this->t, this->remaining, this->b);
- this->k->encrypt(this->k, chunk_create(this->t, this->b), iv, NULL);
+ if (!this->k->encrypt(this->k, chunk_create(this->t, this->b), iv, NULL))
+ {
+ return FALSE;
+ }
memcpy(out, this->t, this->b);
/* reset state */
memset(this->t, 0, this->b);
this->remaining_bytes = 0;
+
+ return TRUE;
}
-METHOD(cmac_t, get_mac, void,
- private_cmac_t *this, chunk_t data, u_int8_t *out)
+METHOD(mac_t, get_mac, bool,
+ private_mac_t *this, chunk_t data, u_int8_t *out)
{
/* update T, do not process last block */
- update(this, data);
+ if (!update(this, data))
+ {
+ return FALSE;
+ }
if (out)
{ /* if not in append mode, process last block and output result */
- final(this, out);
+ return final(this, out);
}
+ return TRUE;
}
-METHOD(cmac_t, get_block_size, size_t,
- private_cmac_t *this)
+METHOD(mac_t, get_mac_size, size_t,
+ private_mac_t *this)
{
return this->b;
}
@@ -222,8 +242,8 @@ static void derive_key(chunk_t chunk)
}
}
-METHOD(cmac_t, set_key, void,
- private_cmac_t *this, chunk_t key)
+METHOD(mac_t, set_key, bool,
+ private_mac_t *this, chunk_t key)
{
chunk_t resized, iv, l;
@@ -236,8 +256,11 @@ METHOD(cmac_t, set_key, void,
{ /* use cmac recursively to resize longer or shorter keys */
resized = chunk_alloca(this->b);
memset(resized.ptr, 0, resized.len);
- set_key(this, resized);
- get_mac(this, key, resized.ptr);
+ if (!set_key(this, resized) ||
+ !get_mac(this, key, resized.ptr))
+ {
+ return FALSE;
+ }
}
/*
@@ -256,17 +279,22 @@ METHOD(cmac_t, set_key, void,
memset(iv.ptr, 0, iv.len);
l = chunk_alloca(this->b);
memset(l.ptr, 0, l.len);
- this->k->set_key(this->k, resized);
- this->k->encrypt(this->k, l, iv, NULL);
+ if (!this->k->set_key(this->k, resized) ||
+ !this->k->encrypt(this->k, l, iv, NULL))
+ {
+ return FALSE;
+ }
derive_key(l);
memcpy(this->k1, l.ptr, l.len);
derive_key(l);
memcpy(this->k2, l.ptr, l.len);
memwipe(l.ptr, l.len);
+
+ return TRUE;
}
-METHOD(cmac_t, destroy, void,
- private_cmac_t *this)
+METHOD(mac_t, destroy, void,
+ private_mac_t *this)
{
this->k->destroy(this->k);
memwipe(this->k1, this->b);
@@ -281,9 +309,9 @@ METHOD(cmac_t, destroy, void,
/*
* Described in header
*/
-cmac_t *cmac_create(encryption_algorithm_t algo, size_t key_size)
+mac_t *cmac_create(encryption_algorithm_t algo, size_t key_size)
{
- private_cmac_t *this;
+ private_mac_t *this;
crypter_t *crypter;
u_int8_t b;
@@ -303,7 +331,7 @@ cmac_t *cmac_create(encryption_algorithm_t algo, size_t key_size)
INIT(this,
.public = {
.get_mac = _get_mac,
- .get_block_size = _get_block_size,
+ .get_mac_size = _get_mac_size,
.set_key = _set_key,
.destroy = _destroy,
},
@@ -319,3 +347,48 @@ cmac_t *cmac_create(encryption_algorithm_t algo, size_t key_size)
return &this->public;
}
+/*
+ * Described in header.
+ */
+prf_t *cmac_prf_create(pseudo_random_function_t algo)
+{
+ mac_t *cmac;
+
+ switch (algo)
+ {
+ case PRF_AES128_CMAC:
+ cmac = cmac_create(ENCR_AES_CBC, 16);
+ break;
+ default:
+ return NULL;
+ }
+ if (cmac)
+ {
+ return mac_prf_create(cmac);
+ }
+ return NULL;
+}
+
+/*
+ * Described in header
+ */
+signer_t *cmac_signer_create(integrity_algorithm_t algo)
+{
+ size_t truncation;
+ mac_t *cmac;
+
+ switch (algo)
+ {
+ case AUTH_AES_CMAC_96:
+ cmac = cmac_create(ENCR_AES_CBC, 16);
+ truncation = 12;
+ break;
+ default:
+ return NULL;
+ }
+ if (cmac)
+ {
+ return mac_signer_create(cmac, truncation);
+ }
+ return NULL;
+}
diff --git a/src/libstrongswan/plugins/cmac/cmac.h b/src/libstrongswan/plugins/cmac/cmac.h
index 061609127..dc85e3bc3 100644
--- a/src/libstrongswan/plugins/cmac/cmac.h
+++ b/src/libstrongswan/plugins/cmac/cmac.h
@@ -14,6 +14,11 @@
*/
/**
+ * Cipher-based Message Authentication Code (CMAC).
+ *
+ * This class implements the message authentication algorithm
+ * described in RFC 4493.
+ *
* @defgroup cmac cmac
* @{ @ingroup cmac_p
*/
@@ -21,58 +26,23 @@
#ifndef CMAC_H_
#define CMAC_H_
-#include <crypto/crypters/crypter.h>
-
-typedef struct cmac_t cmac_t;
+#include <crypto/prfs/prf.h>
+#include <crypto/signers/signer.h>
/**
- * Cipher-based Message Authentication Code (CMAC).
+ * Creates a new prf_t object based on a CMAC.
*
- * This class implements the message authentication algorithm
- * described in RFC 4493.
+ * @param algo algorithm to implement
+ * @return prf_t object, NULL if not supported
*/
-struct cmac_t {
-
- /**
- * Generate message authentication code.
- *
- * If buffer is NULL, no result is given back. A next call will
- * append the data to already supplied data. If buffer is not NULL,
- * the mac of all apended data is calculated, returned and the internal
- * state is reset.
- *
- * @param data chunk of data to authenticate
- * @param buffer pointer where the generated bytes will be written
- */
- void (*get_mac) (cmac_t *this, chunk_t data, u_int8_t *buffer);
-
- /**
- * Get the block size of this cmac_t object.
- *
- * @return block size in bytes
- */
- size_t (*get_block_size) (cmac_t *this);
-
- /**
- * Set the key for this cmac_t object.
- *
- * @param key key to set
- */
- void (*set_key) (cmac_t *this, chunk_t key);
-
- /**
- * Destroys a cmac_t object.
- */
- void (*destroy) (cmac_t *this);
-};
+prf_t *cmac_prf_create(pseudo_random_function_t algo);
/**
- * Creates a new cmac_t object.
+ * Creates a new signer_t object based on a CMAC.
*
- * @param algo underlying crypto algorithm
- * @param key_size key size to use, if required for algorithm
- * @return cmac_t object, NULL if not supported
+ * @param algo algorithm to implement
+ * @return signer_t, NULL if not supported
*/
-cmac_t *cmac_create(encryption_algorithm_t algo, size_t key_size);
+signer_t *cmac_signer_create(integrity_algorithm_t algo);
#endif /** CMAC_H_ @}*/
diff --git a/src/libstrongswan/plugins/cmac/cmac_plugin.c b/src/libstrongswan/plugins/cmac/cmac_plugin.c
index 5b42c5002..694e598a5 100644
--- a/src/libstrongswan/plugins/cmac/cmac_plugin.c
+++ b/src/libstrongswan/plugins/cmac/cmac_plugin.c
@@ -16,8 +16,7 @@
#include "cmac_plugin.h"
#include <library.h>
-#include "cmac_prf.h"
-#include "cmac_signer.h"
+#include "cmac.h"
typedef struct private_cmac_plugin_t private_cmac_plugin_t;
diff --git a/src/libstrongswan/plugins/cmac/cmac_prf.c b/src/libstrongswan/plugins/cmac/cmac_prf.c
deleted file mode 100644
index 17affe439..000000000
--- a/src/libstrongswan/plugins/cmac/cmac_prf.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2012 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 "cmac_prf.h"
-
-#include "cmac.h"
-
-typedef struct private_cmac_prf_t private_cmac_prf_t;
-
-/**
- * Private data of a cmac_prf_t object.
- */
-struct private_cmac_prf_t {
-
- /**
- * Public cmac_prf_t interface.
- */
- cmac_prf_t public;
-
- /**
- * cmac to use for generation.
- */
- cmac_t *cmac;
-};
-
-METHOD(prf_t, get_bytes, void,
- private_cmac_prf_t *this, chunk_t seed, u_int8_t *buffer)
-{
- this->cmac->get_mac(this->cmac, seed, buffer);
-}
-
-METHOD(prf_t, allocate_bytes, void,
- private_cmac_prf_t *this, chunk_t seed, chunk_t *chunk)
-{
- if (chunk)
- {
- *chunk = chunk_alloc(this->cmac->get_block_size(this->cmac));
- get_bytes(this, seed, chunk->ptr);
- }
- else
- {
- get_bytes(this, seed, NULL);
- }
-}
-
-METHOD(prf_t, get_block_size, size_t,
- private_cmac_prf_t *this)
-{
- return this->cmac->get_block_size(this->cmac);
-}
-
-METHOD(prf_t, get_key_size, size_t,
- private_cmac_prf_t *this)
-{
- /* in cmac, block and key size are always equal */
- return this->cmac->get_block_size(this->cmac);
-}
-
-METHOD(prf_t, set_key, void,
- private_cmac_prf_t *this, chunk_t key)
-{
- this->cmac->set_key(this->cmac, key);
-}
-
-METHOD(prf_t, destroy, void,
- private_cmac_prf_t *this)
-{
- this->cmac->destroy(this->cmac);
- free(this);
-}
-
-/*
- * Described in header.
- */
-cmac_prf_t *cmac_prf_create(pseudo_random_function_t algo)
-{
- private_cmac_prf_t *this;
- cmac_t *cmac;
-
- switch (algo)
- {
- case PRF_AES128_CMAC:
- cmac = cmac_create(ENCR_AES_CBC, 16);
- break;
- default:
- return NULL;
- }
- if (!cmac)
- {
- return NULL;
- }
-
- INIT(this,
- .public = {
- .prf = {
- .get_bytes = _get_bytes,
- .allocate_bytes = _allocate_bytes,
- .get_block_size = _get_block_size,
- .get_key_size = _get_key_size,
- .set_key = _set_key,
- .destroy = _destroy,
- },
- },
- .cmac = cmac,
- );
-
- return &this->public;
-}
-
diff --git a/src/libstrongswan/plugins/cmac/cmac_signer.c b/src/libstrongswan/plugins/cmac/cmac_signer.c
deleted file mode 100644
index 82e8885d6..000000000
--- a/src/libstrongswan/plugins/cmac/cmac_signer.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2012 Tobias Brunner
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <string.h>
-
-#include "cmac_signer.h"
-#include "cmac.h"
-
-typedef struct private_cmac_signer_t private_cmac_signer_t;
-
-/**
- * Private data structure with signing context.
- */
-struct private_cmac_signer_t {
-
- /**
- * Public interface.
- */
- cmac_signer_t public;
-
- /**
- * Assigned cmac function.
- */
- cmac_t *cmac;
-
- /**
- * Block size (truncation of CMAC MAC)
- */
- size_t block_size;
-};
-
-METHOD(signer_t, get_signature, void,
- private_cmac_signer_t *this, chunk_t data, u_int8_t *buffer)
-{
- if (buffer == NULL)
- { /* append mode */
- this->cmac->get_mac(this->cmac, data, NULL);
- }
- else
- {
- u_int8_t mac[this->cmac->get_block_size(this->cmac)];
-
- this->cmac->get_mac(this->cmac, data, mac);
- memcpy(buffer, mac, this->block_size);
- }
-}
-
-METHOD(signer_t, allocate_signature, void,
- private_cmac_signer_t *this, chunk_t data, chunk_t *chunk)
-{
- if (chunk == NULL)
- { /* append mode */
- this->cmac->get_mac(this->cmac, data, NULL);
- }
- else
- {
- u_int8_t mac[this->cmac->get_block_size(this->cmac)];
-
- this->cmac->get_mac(this->cmac, data, mac);
-
- chunk->ptr = malloc(this->block_size);
- chunk->len = this->block_size;
-
- memcpy(chunk->ptr, mac, this->block_size);
- }
-}
-
-METHOD(signer_t, verify_signature, bool,
- private_cmac_signer_t *this, chunk_t data, chunk_t signature)
-{
- u_int8_t mac[this->cmac->get_block_size(this->cmac)];
-
- if (signature.len != this->block_size)
- {
- return FALSE;
- }
-
- this->cmac->get_mac(this->cmac, data, mac);
- return memeq(signature.ptr, mac, this->block_size);
-}
-
-METHOD(signer_t, get_key_size, size_t,
- private_cmac_signer_t *this)
-{
- return this->cmac->get_block_size(this->cmac);
-}
-
-METHOD(signer_t, get_block_size, size_t,
- private_cmac_signer_t *this)
-{
- return this->block_size;
-}
-
-METHOD(signer_t, set_key, void,
- private_cmac_signer_t *this, chunk_t key)
-{
- this->cmac->set_key(this->cmac, key);
-}
-
-METHOD(signer_t, destroy, void,
- private_cmac_signer_t *this)
-{
- this->cmac->destroy(this->cmac);
- free(this);
-}
-
-/*
- * Described in header
- */
-cmac_signer_t *cmac_signer_create(integrity_algorithm_t algo)
-{
- private_cmac_signer_t *this;
- size_t truncation;
- cmac_t *cmac;
-
- switch (algo)
- {
- case AUTH_AES_CMAC_96:
- cmac = cmac_create(ENCR_AES_CBC, 16);
- truncation = 12;
- break;
- default:
- return NULL;
- }
- if (cmac == NULL)
- {
- return NULL;
- }
-
- INIT(this,
- .public = {
- .signer = {
- .get_signature = _get_signature,
- .allocate_signature = _allocate_signature,
- .verify_signature = _verify_signature,
- .get_key_size = _get_key_size,
- .get_block_size = _get_block_size,
- .set_key = _set_key,
- .destroy = _destroy,
- },
- },
- .cmac = cmac,
- .block_size = min(truncation, cmac->get_block_size(cmac)),
- );
-
- return &this->public;
-}
diff --git a/src/libstrongswan/plugins/constraints/Makefile.in b/src/libstrongswan/plugins/constraints/Makefile.in
index 06b66db60..693d76334 100644
--- a/src/libstrongswan/plugins/constraints/Makefile.in
+++ b/src/libstrongswan/plugins/constraints/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -86,7 +87,7 @@ libstrongswan_constraints_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_constraints_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_constraints_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -112,6 +113,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -206,11 +208,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -227,11 +232,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -247,6 +253,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -256,7 +263,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/ctr/Makefile.in b/src/libstrongswan/plugins/ctr/Makefile.in
index 853625a19..adab5d7d5 100644
--- a/src/libstrongswan/plugins/ctr/Makefile.in
+++ b/src/libstrongswan/plugins/ctr/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -82,7 +83,7 @@ libstrongswan_ctr_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(libstrongswan_ctr_la_LDFLAGS) $(LDFLAGS) -o $@
@MONOLITHIC_FALSE@am_libstrongswan_ctr_la_rpath = -rpath $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_ctr_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -108,6 +109,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -202,11 +204,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -223,11 +228,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -243,6 +249,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -252,7 +259,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/ctr/ctr_ipsec_crypter.c b/src/libstrongswan/plugins/ctr/ctr_ipsec_crypter.c
index ddcae423b..59d201a6f 100644
--- a/src/libstrongswan/plugins/ctr/ctr_ipsec_crypter.c
+++ b/src/libstrongswan/plugins/ctr/ctr_ipsec_crypter.c
@@ -45,7 +45,7 @@ struct private_ctr_ipsec_crypter_t {
/**
* Do the CTR crypto operation
*/
-static void crypt_ctr(private_ctr_ipsec_crypter_t *this,
+static bool crypt_ctr(private_ctr_ipsec_crypter_t *this,
chunk_t in, chunk_t out)
{
size_t is, bs;
@@ -63,8 +63,11 @@ static void crypt_ctr(private_ctr_ipsec_crypter_t *this,
memset(iv, 0, is);
memcpy(block, state.ptr, bs);
- this->crypter->encrypt(this->crypter,
- chunk_create(block, bs), chunk_create(iv, is), NULL);
+ if (!this->crypter->encrypt(this->crypter, chunk_create(block, bs),
+ chunk_create(iv, is), NULL))
+ {
+ return FALSE;
+ }
chunk_increment(state);
if (in.ptr != out.ptr)
@@ -75,9 +78,10 @@ static void crypt_ctr(private_ctr_ipsec_crypter_t *this,
in = chunk_skip(in, bs);
out = chunk_skip(out, bs);
}
+ return TRUE;
}
-METHOD(crypter_t, crypt, void,
+METHOD(crypter_t, crypt, bool,
private_ctr_ipsec_crypter_t *this, chunk_t in, chunk_t iv, chunk_t *out)
{
memcpy(this->state.iv, iv.ptr, sizeof(this->state.iv));
@@ -85,12 +89,9 @@ METHOD(crypter_t, crypt, void,
if (out)
{
*out = chunk_alloc(in.len);
- crypt_ctr(this, in, *out);
- }
- else
- {
- crypt_ctr(this, in, in);
+ return crypt_ctr(this, in, *out);
}
+ return crypt_ctr(this, in, in);
}
METHOD(crypter_t, get_block_size, size_t,
@@ -112,13 +113,13 @@ METHOD(crypter_t, get_key_size, size_t,
+ sizeof(this->state.nonce);
}
-METHOD(crypter_t, set_key, void,
+METHOD(crypter_t, set_key, bool,
private_ctr_ipsec_crypter_t *this, chunk_t key)
{
memcpy(this->state.nonce, key.ptr + key.len - sizeof(this->state.nonce),
sizeof(this->state.nonce));
key.len -= sizeof(this->state.nonce);
- this->crypter->set_key(this->crypter, key);
+ return this->crypter->set_key(this->crypter, key);
}
METHOD(crypter_t, destroy, void,
diff --git a/src/libstrongswan/plugins/curl/Makefile.in b/src/libstrongswan/plugins/curl/Makefile.in
index 5b83c60f8..b6f38681f 100644
--- a/src/libstrongswan/plugins/curl/Makefile.in
+++ b/src/libstrongswan/plugins/curl/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -82,7 +83,7 @@ libstrongswan_curl_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(libstrongswan_curl_la_LDFLAGS) $(LDFLAGS) -o $@
@MONOLITHIC_FALSE@am_libstrongswan_curl_la_rpath = -rpath $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_curl_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -108,6 +109,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -202,11 +204,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -223,11 +228,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -243,6 +249,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -252,7 +259,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/des/Makefile.in b/src/libstrongswan/plugins/des/Makefile.in
index f4056951a..04d489824 100644
--- a/src/libstrongswan/plugins/des/Makefile.in
+++ b/src/libstrongswan/plugins/des/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -82,7 +83,7 @@ libstrongswan_des_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(libstrongswan_des_la_LDFLAGS) $(LDFLAGS) -o $@
@MONOLITHIC_FALSE@am_libstrongswan_des_la_rpath = -rpath $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_des_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -108,6 +109,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -202,11 +204,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -223,11 +228,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -243,6 +249,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -252,7 +259,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/des/des_crypter.c b/src/libstrongswan/plugins/des/des_crypter.c
index bc399ef8a..c81318b19 100644
--- a/src/libstrongswan/plugins/des/des_crypter.c
+++ b/src/libstrongswan/plugins/des/des_crypter.c
@@ -1416,7 +1416,7 @@ static void des_ede3_cbc_encrypt(des_cblock *input, des_cblock *output, long len
tin[0]=tin[1]=0;
}
-METHOD(crypter_t, decrypt, void,
+METHOD(crypter_t, decrypt, bool,
private_des_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *decrypted)
{
des_cblock ivb;
@@ -1431,10 +1431,11 @@ METHOD(crypter_t, decrypt, void,
memcpy(&ivb, iv.ptr, sizeof(des_cblock));
des_cbc_encrypt((des_cblock*)(data.ptr), (des_cblock*)out,
data.len, this->ks, &ivb, DES_DECRYPT);
+ return TRUE;
}
-METHOD(crypter_t, encrypt, void,
+METHOD(crypter_t, encrypt, bool,
private_des_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *encrypted)
{
des_cblock ivb;
@@ -1449,9 +1450,10 @@ METHOD(crypter_t, encrypt, void,
memcpy(&ivb, iv.ptr, sizeof(des_cblock));
des_cbc_encrypt((des_cblock*)(data.ptr), (des_cblock*)out,
data.len, this->ks, &ivb, DES_ENCRYPT);
+ return TRUE;
}
-METHOD(crypter_t, decrypt_ecb, void,
+METHOD(crypter_t, decrypt_ecb, bool,
private_des_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *decrypted)
{
u_int8_t *out;
@@ -1464,9 +1466,10 @@ METHOD(crypter_t, decrypt_ecb, void,
}
des_ecb_encrypt((des_cblock*)(data.ptr), (des_cblock*)out,
data.len, this->ks, DES_DECRYPT);
+ return TRUE;
}
-METHOD(crypter_t, encrypt_ecb, void,
+METHOD(crypter_t, encrypt_ecb, bool,
private_des_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *encrypted)
{
u_int8_t *out;
@@ -1479,9 +1482,10 @@ METHOD(crypter_t, encrypt_ecb, void,
}
des_ecb_encrypt((des_cblock*)(data.ptr), (des_cblock*)out,
data.len, this->ks, DES_ENCRYPT);
+ return TRUE;
}
-METHOD(crypter_t, decrypt3, void,
+METHOD(crypter_t, decrypt3, bool,
private_des_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *decrypted)
{
des_cblock ivb;
@@ -1497,9 +1501,10 @@ METHOD(crypter_t, decrypt3, void,
des_ede3_cbc_encrypt((des_cblock*)(data.ptr), (des_cblock*)out,
data.len, this->ks3[0], this->ks3[1], this->ks3[2],
&ivb, DES_DECRYPT);
+ return TRUE;
}
-METHOD(crypter_t, encrypt3, void,
+METHOD(crypter_t, encrypt3, bool,
private_des_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *encrypted)
{
des_cblock ivb;
@@ -1515,6 +1520,7 @@ METHOD(crypter_t, encrypt3, void,
des_ede3_cbc_encrypt((des_cblock*)(data.ptr), (des_cblock*)out,
data.len, this->ks3[0], this->ks3[1], this->ks3[2],
&ivb, DES_ENCRYPT);
+ return TRUE;
}
METHOD(crypter_t, get_block_size, size_t,
@@ -1535,18 +1541,20 @@ METHOD(crypter_t, get_key_size, size_t,
return this->key_size;
}
-METHOD(crypter_t, set_key, void,
+METHOD(crypter_t, set_key, bool,
private_des_crypter_t *this, chunk_t key)
{
des_set_key((des_cblock*)(key.ptr), &this->ks);
+ return TRUE;
}
-METHOD(crypter_t, set_key3, void,
+METHOD(crypter_t, set_key3, bool,
private_des_crypter_t *this, chunk_t key)
{
des_set_key((des_cblock*)(key.ptr) + 0, &this->ks3[0]);
des_set_key((des_cblock*)(key.ptr) + 1, &this->ks3[1]);
des_set_key((des_cblock*)(key.ptr) + 2, &this->ks3[2]);
+ return TRUE;
}
METHOD(crypter_t, destroy, void,
diff --git a/src/libstrongswan/plugins/dnskey/Makefile.in b/src/libstrongswan/plugins/dnskey/Makefile.in
index dabddd6d0..2f86f7558 100644
--- a/src/libstrongswan/plugins/dnskey/Makefile.in
+++ b/src/libstrongswan/plugins/dnskey/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -85,7 +86,7 @@ libstrongswan_dnskey_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@MONOLITHIC_FALSE@am_libstrongswan_dnskey_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_dnskey_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -111,6 +112,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -205,11 +207,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -226,11 +231,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -246,6 +252,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -255,7 +262,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/fips_prf/Makefile.in b/src/libstrongswan/plugins/fips_prf/Makefile.in
index cbe9ef303..017f00e50 100644
--- a/src/libstrongswan/plugins/fips_prf/Makefile.in
+++ b/src/libstrongswan/plugins/fips_prf/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -85,7 +86,7 @@ libstrongswan_fips_prf_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_fips_prf_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_fips_prf_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -111,6 +112,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -205,11 +207,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -226,11 +231,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -246,6 +252,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -255,7 +262,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/fips_prf/fips_prf.c b/src/libstrongswan/plugins/fips_prf/fips_prf.c
index c0666367a..3fe204d35 100644
--- a/src/libstrongswan/plugins/fips_prf/fips_prf.c
+++ b/src/libstrongswan/plugins/fips_prf/fips_prf.c
@@ -48,7 +48,7 @@ struct private_fips_prf_t {
/**
* G function, either SHA1 or DES
*/
- void (*g)(private_fips_prf_t *this, chunk_t c, u_int8_t res[]);
+ bool (*g)(private_fips_prf_t *this, chunk_t c, u_int8_t res[]);
};
/**
@@ -106,7 +106,7 @@ static void chunk_mod(size_t length, chunk_t chunk, u_int8_t buffer[])
* 0xcb, 0x0f, 0x6c, 0x55, 0xba, 0xbb, 0x13, 0x78,
* 0x8e, 0x20, 0xd7, 0x37, 0xa3, 0x27, 0x51, 0x16
*/
-METHOD(prf_t, get_bytes, void,
+METHOD(prf_t, get_bytes, bool,
private_fips_prf_t *this, chunk_t seed, u_int8_t w[])
{
int i;
@@ -138,6 +138,8 @@ METHOD(prf_t, get_bytes, void,
}
/* 3.3 done already, mod q not used */
+
+ return TRUE;
}
METHOD(prf_t, get_block_size, size_t,
@@ -145,11 +147,11 @@ METHOD(prf_t, get_block_size, size_t,
{
return 2 * this->b;
}
-METHOD(prf_t, allocate_bytes, void,
+METHOD(prf_t, allocate_bytes, bool,
private_fips_prf_t *this, chunk_t seed, chunk_t *chunk)
{
*chunk = chunk_alloc(get_block_size(this));
- get_bytes(this, seed, chunk->ptr);
+ return get_bytes(this, seed, chunk->ptr);
}
METHOD(prf_t, get_key_size, size_t,
@@ -158,17 +160,18 @@ METHOD(prf_t, get_key_size, size_t,
return this->b;
}
-METHOD(prf_t, set_key, void,
+METHOD(prf_t, set_key, bool,
private_fips_prf_t *this, chunk_t key)
{
/* save key as "key mod 2^b" */
chunk_mod(this->b, key, this->key);
+ return TRUE;
}
/**
* Implementation of the G() function based on SHA1
*/
-void g_sha1(private_fips_prf_t *this, chunk_t c, u_int8_t res[])
+static bool g_sha1(private_fips_prf_t *this, chunk_t c, u_int8_t res[])
{
u_int8_t buf[64];
@@ -187,8 +190,12 @@ void g_sha1(private_fips_prf_t *this, chunk_t c, u_int8_t res[])
}
/* use the keyed hasher, but use an empty key to use SHA1 IV */
- this->keyed_prf->set_key(this->keyed_prf, chunk_empty);
- this->keyed_prf->get_bytes(this->keyed_prf, c, res);
+ if (!this->keyed_prf->set_key(this->keyed_prf, chunk_empty) ||
+ !this->keyed_prf->get_bytes(this->keyed_prf, c, res))
+ {
+ return FALSE;
+ }
+ return TRUE;
}
METHOD(prf_t, destroy, void,
diff --git a/src/libstrongswan/plugins/gcm/Makefile.in b/src/libstrongswan/plugins/gcm/Makefile.in
index 8285b5aeb..0c5eea0a7 100644
--- a/src/libstrongswan/plugins/gcm/Makefile.in
+++ b/src/libstrongswan/plugins/gcm/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -82,7 +83,7 @@ libstrongswan_gcm_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(libstrongswan_gcm_la_LDFLAGS) $(LDFLAGS) -o $@
@MONOLITHIC_FALSE@am_libstrongswan_gcm_la_rpath = -rpath $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_gcm_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -108,6 +109,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -202,11 +204,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -223,11 +228,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -243,6 +249,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -252,7 +259,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/gcm/gcm_aead.c b/src/libstrongswan/plugins/gcm/gcm_aead.c
index 0d7d91dbf..79ee65d98 100644
--- a/src/libstrongswan/plugins/gcm/gcm_aead.c
+++ b/src/libstrongswan/plugins/gcm/gcm_aead.c
@@ -149,7 +149,7 @@ static void ghash(private_gcm_aead_t *this, chunk_t x, char *res)
/**
* GCTR function, en-/decrypts x inline
*/
-static void gctr(private_gcm_aead_t *this, char *icb, chunk_t x)
+static bool gctr(private_gcm_aead_t *this, char *icb, chunk_t x)
{
char cb[BLOCK_SIZE], iv[BLOCK_SIZE], tmp[BLOCK_SIZE];
@@ -159,12 +159,16 @@ static void gctr(private_gcm_aead_t *this, char *icb, chunk_t x)
while (x.len)
{
memcpy(tmp, cb, BLOCK_SIZE);
- this->crypter->encrypt(this->crypter, chunk_from_thing(tmp),
- chunk_from_thing(iv), NULL);
+ if (!this->crypter->encrypt(this->crypter, chunk_from_thing(tmp),
+ chunk_from_thing(iv), NULL))
+ {
+ return FALSE;
+ }
memxor(x.ptr, tmp, min(BLOCK_SIZE, x.len));
chunk_increment(chunk_from_thing(cb));
x = chunk_skip(x, BLOCK_SIZE);
}
+ return TRUE;
}
/**
@@ -180,21 +184,21 @@ static void create_j(private_gcm_aead_t *this, char *iv, char *j)
/**
* Create GHASH subkey H
*/
-static void create_h(private_gcm_aead_t *this, char *h)
+static bool create_h(private_gcm_aead_t *this, char *h)
{
char zero[BLOCK_SIZE];
memset(zero, 0, BLOCK_SIZE);
memset(h, 0, BLOCK_SIZE);
- this->crypter->encrypt(this->crypter, chunk_create(h, BLOCK_SIZE),
- chunk_from_thing(zero), NULL);
+ return this->crypter->encrypt(this->crypter, chunk_create(h, BLOCK_SIZE),
+ chunk_from_thing(zero), NULL);
}
/**
* Encrypt/decrypt
*/
-static void crypt(private_gcm_aead_t *this, char *j, chunk_t in, chunk_t out)
+static bool crypt(private_gcm_aead_t *this, char *j, chunk_t in, chunk_t out)
{
char icb[BLOCK_SIZE];
@@ -206,13 +210,13 @@ static void crypt(private_gcm_aead_t *this, char *j, chunk_t in, chunk_t out)
{
memcpy(out.ptr, in.ptr, in.len);
}
- gctr(this, icb, out);
+ return gctr(this, icb, out);
}
/**
* Create ICV
*/
-static void create_icv(private_gcm_aead_t *this, chunk_t assoc, chunk_t crypt,
+static bool create_icv(private_gcm_aead_t *this, chunk_t assoc, chunk_t crypt,
char *j, char *icv)
{
size_t assoc_pad, crypt_pad;
@@ -249,9 +253,12 @@ static void create_icv(private_gcm_aead_t *this, chunk_t assoc, chunk_t crypt,
ghash(this, chunk, s);
free(chunk.ptr);
- gctr(this, j, chunk_from_thing(s));
-
+ if (!gctr(this, j, chunk_from_thing(s)))
+ {
+ return FALSE;
+ }
memcpy(icv, s, this->icv_size);
+ return TRUE;
}
/**
@@ -262,12 +269,11 @@ static bool verify_icv(private_gcm_aead_t *this, chunk_t assoc, chunk_t crypt,
{
char tmp[this->icv_size];
- create_icv(this, assoc, crypt, j, tmp);
-
- return memeq(tmp, icv, this->icv_size);
+ return create_icv(this, assoc, crypt, j, tmp) &&
+ memeq(tmp, icv, this->icv_size);
}
-METHOD(aead_t, encrypt, void,
+METHOD(aead_t, encrypt, bool,
private_gcm_aead_t *this, chunk_t plain, chunk_t assoc, chunk_t iv,
chunk_t *encrypted)
{
@@ -278,16 +284,13 @@ METHOD(aead_t, encrypt, void,
if (encrypted)
{
*encrypted = chunk_alloc(plain.len + this->icv_size);
- crypt(this, j, plain, *encrypted);
- create_icv(this, assoc,
- chunk_create(encrypted->ptr, encrypted->len - this->icv_size),
- j, encrypted->ptr + encrypted->len - this->icv_size);
- }
- else
- {
- crypt(this, j, plain, plain);
- create_icv(this, assoc, plain, j, plain.ptr + plain.len);
+ return crypt(this, j, plain, *encrypted) &&
+ create_icv(this, assoc,
+ chunk_create(encrypted->ptr, encrypted->len - this->icv_size),
+ j, encrypted->ptr + encrypted->len - this->icv_size);
}
+ return crypt(this, j, plain, plain) &&
+ create_icv(this, assoc, plain, j, plain.ptr + plain.len);
}
METHOD(aead_t, decrypt, bool,
@@ -311,13 +314,9 @@ METHOD(aead_t, decrypt, bool,
if (plain)
{
*plain = chunk_alloc(encrypted.len);
- crypt(this, j, encrypted, *plain);
+ return crypt(this, j, encrypted, *plain);
}
- else
- {
- crypt(this, j, encrypted, encrypted);
- }
- return TRUE;
+ return crypt(this, j, encrypted, encrypted);
}
METHOD(aead_t, get_block_size, size_t,
@@ -344,13 +343,13 @@ METHOD(aead_t, get_key_size, size_t,
return this->crypter->get_key_size(this->crypter) + SALT_SIZE;
}
-METHOD(aead_t, set_key, void,
+METHOD(aead_t, set_key, bool,
private_gcm_aead_t *this, chunk_t key)
{
memcpy(this->salt, key.ptr + key.len - SALT_SIZE, SALT_SIZE);
key.len -= SALT_SIZE;
- this->crypter->set_key(this->crypter, key);
- create_h(this, this->h);
+ return this->crypter->set_key(this->crypter, key) &&
+ create_h(this, this->h);
}
METHOD(aead_t, destroy, void,
diff --git a/src/libstrongswan/plugins/gcrypt/Makefile.in b/src/libstrongswan/plugins/gcrypt/Makefile.in
index 4dc72fed0..72e525b16 100644
--- a/src/libstrongswan/plugins/gcrypt/Makefile.in
+++ b/src/libstrongswan/plugins/gcrypt/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -86,7 +87,7 @@ libstrongswan_gcrypt_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@MONOLITHIC_FALSE@am_libstrongswan_gcrypt_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_gcrypt_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -112,6 +113,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -206,11 +208,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -227,11 +232,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -247,6 +253,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -256,7 +263,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_crypter.c b/src/libstrongswan/plugins/gcrypt/gcrypt_crypter.c
index 599481911..0b5dc0365 100644
--- a/src/libstrongswan/plugins/gcrypt/gcrypt_crypter.c
+++ b/src/libstrongswan/plugins/gcrypt/gcrypt_crypter.c
@@ -59,50 +59,47 @@ struct private_gcrypt_crypter_t {
/**
* Set the IV for en/decryption
*/
-static void set_iv(private_gcrypt_crypter_t *this, chunk_t iv)
+static bool set_iv(private_gcrypt_crypter_t *this, chunk_t iv)
{
if (this->ctr_mode)
{
memcpy(this->ctr.iv, iv.ptr, sizeof(this->ctr.iv));
this->ctr.counter = htonl(1);
- gcry_cipher_setctr(this->h, &this->ctr, sizeof(this->ctr));
- }
- else
- {
- gcry_cipher_setiv(this->h, iv.ptr, iv.len);
+ return gcry_cipher_setctr(this->h, &this->ctr, sizeof(this->ctr)) == 0;
}
+ return gcry_cipher_setiv(this->h, iv.ptr, iv.len) == 0;
}
-METHOD(crypter_t, decrypt, void,
+METHOD(crypter_t, decrypt, bool,
private_gcrypt_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
{
- set_iv(this, iv);
-
- if (dst)
+ if (!set_iv(this, iv))
{
- *dst = chunk_alloc(data.len);
- gcry_cipher_decrypt(this->h, dst->ptr, dst->len, data.ptr, data.len);
+ return FALSE;
}
- else
+ if (dst)
{
- gcry_cipher_decrypt(this->h, data.ptr, data.len, NULL, 0);
+ *dst = chunk_alloc(data.len);
+ return gcry_cipher_decrypt(this->h, dst->ptr, dst->len,
+ data.ptr, data.len) == 0;
}
+ return gcry_cipher_decrypt(this->h, data.ptr, data.len, NULL, 0) == 0;
}
-METHOD(crypter_t, encrypt, void,
+METHOD(crypter_t, encrypt, bool,
private_gcrypt_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
{
- set_iv(this, iv);
-
- if (dst)
+ if (!set_iv(this, iv))
{
- *dst = chunk_alloc(data.len);
- gcry_cipher_encrypt(this->h, dst->ptr, dst->len, data.ptr, data.len);
+ return FALSE;
}
- else
+ if (dst)
{
- gcry_cipher_encrypt(this->h, data.ptr, data.len, NULL, 0);
+ *dst = chunk_alloc(data.len);
+ return gcry_cipher_encrypt(this->h, dst->ptr, dst->len,
+ data.ptr, data.len) == 0;
}
+ return gcry_cipher_encrypt(this->h, data.ptr, data.len, NULL, 0) == 0;
}
METHOD(crypter_t, get_block_size, size_t,
@@ -144,7 +141,7 @@ METHOD(crypter_t, get_key_size, size_t,
return len;
}
-METHOD(crypter_t, set_key, void,
+METHOD(crypter_t, set_key, bool,
private_gcrypt_crypter_t *this, chunk_t key)
{
if (this->ctr_mode)
@@ -154,7 +151,7 @@ METHOD(crypter_t, set_key, void,
sizeof(this->ctr.nonce));
key.len -= sizeof(this->ctr.nonce);
}
- gcry_cipher_setkey(this->h, key.ptr, key.len);
+ return gcry_cipher_setkey(this->h, key.ptr, key.len) == 0;
}
METHOD(crypter_t, destroy, void,
diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_dh.c b/src/libstrongswan/plugins/gcrypt/gcrypt_dh.c
index 6c4665da2..0efd3ba16 100644
--- a/src/libstrongswan/plugins/gcrypt/gcrypt_dh.c
+++ b/src/libstrongswan/plugins/gcrypt/gcrypt_dh.c
@@ -208,9 +208,8 @@ gcrypt_dh_t *create_generic(diffie_hellman_group_t group, size_t exp_len,
}
rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
- if (rng)
+ if (rng && rng->allocate_bytes(rng, exp_len, &random))
{ /* prefer external randomizer */
- rng->allocate_bytes(rng, exp_len, &random);
rng->destroy(rng);
err = gcry_mpi_scan(&this->xa, GCRYMPI_FMT_USG,
random.ptr, random.len, NULL);
@@ -226,6 +225,7 @@ gcrypt_dh_t *create_generic(diffie_hellman_group_t group, size_t exp_len,
}
else
{ /* fallback to gcrypt internal randomizer, shouldn't ever happen */
+ DESTROY_IF(rng);
this->xa = gcry_mpi_new(exp_len * 8);
gcry_mpi_randomize(this->xa, exp_len * 8, GCRY_STRONG_RANDOM);
}
diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_hasher.c b/src/libstrongswan/plugins/gcrypt/gcrypt_hasher.c
index 96c87614f..3155a4aa0 100644
--- a/src/libstrongswan/plugins/gcrypt/gcrypt_hasher.c
+++ b/src/libstrongswan/plugins/gcrypt/gcrypt_hasher.c
@@ -43,13 +43,14 @@ METHOD(hasher_t, get_hash_size, size_t,
return gcry_md_get_algo_dlen(gcry_md_get_algo(this->hd));
}
-METHOD(hasher_t, reset, void,
+METHOD(hasher_t, reset, bool,
private_gcrypt_hasher_t *this)
{
gcry_md_reset(this->hd);
+ return TRUE;
}
-METHOD(hasher_t, get_hash, void,
+METHOD(hasher_t, get_hash, bool,
private_gcrypt_hasher_t *this, chunk_t chunk, u_int8_t *hash)
{
gcry_md_write(this->hd, chunk.ptr, chunk.len);
@@ -58,20 +59,18 @@ METHOD(hasher_t, get_hash, void,
memcpy(hash, gcry_md_read(this->hd, 0), get_hash_size(this));
gcry_md_reset(this->hd);
}
+ return TRUE;
}
-METHOD(hasher_t, allocate_hash, void,
+METHOD(hasher_t, allocate_hash, bool,
private_gcrypt_hasher_t *this, chunk_t chunk, chunk_t *hash)
{
if (hash)
{
*hash = chunk_alloc(get_hash_size(this));
- get_hash(this, chunk, hash->ptr);
- }
- else
- {
- get_hash(this, chunk, NULL);
+ return get_hash(this, chunk, hash->ptr);
}
+ return get_hash(this, chunk, NULL);
}
METHOD(hasher_t, destroy, void,
diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c b/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c
index a48d4a133..5ebdcebce 100644
--- a/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c
+++ b/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c
@@ -132,9 +132,9 @@ METHOD(plugin_t, get_features, int,
PLUGIN_PROVIDE(CRYPTER, ENCR_TWOFISH_CBC, 32),
/* hashers */
PLUGIN_REGISTER(HASHER, gcrypt_hasher_create),
+ PLUGIN_PROVIDE(HASHER, HASH_SHA1),
PLUGIN_PROVIDE(HASHER, HASH_MD4),
PLUGIN_PROVIDE(HASHER, HASH_MD5),
- PLUGIN_PROVIDE(HASHER, HASH_SHA1),
PLUGIN_PROVIDE(HASHER, HASH_SHA224),
PLUGIN_PROVIDE(HASHER, HASH_SHA256),
PLUGIN_PROVIDE(HASHER, HASH_SHA384),
diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_rng.c b/src/libstrongswan/plugins/gcrypt/gcrypt_rng.c
index d29755de9..dc34a8d66 100644
--- a/src/libstrongswan/plugins/gcrypt/gcrypt_rng.c
+++ b/src/libstrongswan/plugins/gcrypt/gcrypt_rng.c
@@ -35,7 +35,7 @@ struct private_gcrypt_rng_t {
rng_quality_t quality;
};
-METHOD(rng_t, get_bytes, void,
+METHOD(rng_t, get_bytes, bool,
private_gcrypt_rng_t *this, size_t bytes, u_int8_t *buffer)
{
switch (this->quality)
@@ -50,13 +50,15 @@ METHOD(rng_t, get_bytes, void,
gcry_randomize(buffer, bytes, GCRY_VERY_STRONG_RANDOM);
break;
}
+ return TRUE;
}
-METHOD(rng_t, allocate_bytes, void,
+METHOD(rng_t, allocate_bytes, bool,
private_gcrypt_rng_t *this, size_t bytes, chunk_t *chunk)
{
*chunk = chunk_alloc(bytes);
get_bytes(this, chunk->len, chunk->ptr);
+ return TRUE;
}
METHOD(rng_t, destroy, void,
diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c
index eb38eea3b..9fdb2d45b 100644
--- a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c
+++ b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c
@@ -165,11 +165,11 @@ static bool sign_pkcs1(private_gcrypt_rsa_private_key_t *this,
return FALSE;
}
hasher = lib->crypto->create_hasher(lib->crypto, hash_algorithm);
- if (!hasher)
+ if (!hasher || !hasher->allocate_hash(hasher, data, &hash))
{
+ DESTROY_IF(hasher);
return FALSE;
}
- hasher->allocate_hash(hasher, data, &hash);
hasher->destroy(hasher);
err = gcry_sexp_build(&in, NULL, "(data(flags pkcs1)(hash %s %b))",
diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c
index f8645da97..c54f2c0cf 100644
--- a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c
+++ b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c
@@ -121,11 +121,11 @@ static bool verify_pkcs1(private_gcrypt_rsa_public_key_t *this,
gcry_sexp_t in, sig;
hasher = lib->crypto->create_hasher(lib->crypto, algorithm);
- if (!hasher)
+ if (!hasher || !hasher->allocate_hash(hasher, data, &hash))
{
+ DESTROY_IF(hasher);
return FALSE;
}
- hasher->allocate_hash(hasher, data, &hash);
hasher->destroy(hasher);
err = gcry_sexp_build(&in, NULL, "(data(flags pkcs1)(hash %s %b))",
diff --git a/src/libstrongswan/plugins/gmp/Makefile.in b/src/libstrongswan/plugins/gmp/Makefile.in
index 34a23312b..f1bb28c1f 100644
--- a/src/libstrongswan/plugins/gmp/Makefile.in
+++ b/src/libstrongswan/plugins/gmp/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -83,7 +84,7 @@ libstrongswan_gmp_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(libstrongswan_gmp_la_LDFLAGS) $(LDFLAGS) -o $@
@MONOLITHIC_FALSE@am_libstrongswan_gmp_la_rpath = -rpath $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_gmp_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -109,6 +110,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -203,11 +205,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -224,11 +229,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -244,6 +250,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -253,7 +260,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c b/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c
index e99502b27..7d232e4f1 100644
--- a/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c
+++ b/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c
@@ -230,8 +230,13 @@ static gmp_diffie_hellman_t *create_generic(diffie_hellman_group_t group,
destroy(this);
return NULL;
}
-
- rng->allocate_bytes(rng, exp_len, &random);
+ if (!rng->allocate_bytes(rng, exp_len, &random))
+ {
+ DBG1(DBG_LIB, "failed to allocate DH secret");
+ rng->destroy(rng);
+ destroy(this);
+ return NULL;
+ }
rng->destroy(rng);
if (exp_len == this->p_len)
diff --git a/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c b/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c
index 1b6c20817..590ab6cb4 100644
--- a/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c
+++ b/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c
@@ -149,7 +149,12 @@ static status_t compute_prime(private_gmp_rsa_private_key_t *this,
mpz_init(*prime);
do
{
- rng->allocate_bytes(rng, prime_size, &random_bytes);
+ if (!rng->allocate_bytes(rng, prime_size, &random_bytes))
+ {
+ DBG1(DBG_LIB, "failed to allocate random prime");
+ rng->destroy(rng);
+ return FAILED;
+ }
/* make sure the two most significant bits are set */
random_bytes.ptr[0] = random_bytes.ptr[0] | 0xC0;
@@ -230,11 +235,11 @@ static bool build_emsa_pkcs1_signature(private_gmp_rsa_private_key_t *this,
}
hasher = lib->crypto->create_hasher(lib->crypto, hash_algorithm);
- if (hasher == NULL)
+ if (!hasher || !hasher->allocate_hash(hasher, data, &hash))
{
+ DESTROY_IF(hasher);
return FALSE;
}
- hasher->allocate_hash(hasher, data, &hash);
hasher->destroy(hasher);
/* build DER-encoded digestInfo */
diff --git a/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c b/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c
index 898892f5b..2d84f0025 100644
--- a/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c
+++ b/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c
@@ -252,7 +252,11 @@ static bool verify_emsa_pkcs1_signature(private_gmp_rsa_public_key_t *this,
}
/* build our own hash and compare */
- hasher->allocate_hash(hasher, data, &hash);
+ if (!hasher->allocate_hash(hasher, data, &hash))
+ {
+ hasher->destroy(hasher);
+ goto end_parser;
+ }
hasher->destroy(hasher);
success = memeq(object.ptr, hash.ptr, hash.len);
free(hash.ptr);
@@ -314,7 +318,7 @@ METHOD(public_key_t, encrypt_, bool,
{
chunk_t em;
u_char *pos;
- int padding, i;
+ int padding;
rng_t *rng;
if (scheme != ENCRYPT_RSA_PKCS1)
@@ -348,16 +352,12 @@ METHOD(public_key_t, encrypt_, bool,
*pos++ = 0x02;
/* fill with pseudo random octets */
- rng->get_bytes(rng, padding, pos);
-
- /* replace zero-valued random octets */
- for (i = 0; i < padding; i++)
+ if (!rng_get_bytes_not_zero(rng, padding, pos, TRUE))
{
- while (*pos == 0)
- {
- rng->get_bytes(rng, 1, pos);
- }
- pos++;
+ DBG1(DBG_LIB, "failed to allocate padding");
+ chunk_clear(&em);
+ rng->destroy(rng);
+ return FALSE;
}
rng->destroy(rng);
diff --git a/src/libstrongswan/plugins/hmac/Makefile.am b/src/libstrongswan/plugins/hmac/Makefile.am
index 77aa0ffd1..4faf321ef 100644
--- a/src/libstrongswan/plugins/hmac/Makefile.am
+++ b/src/libstrongswan/plugins/hmac/Makefile.am
@@ -10,7 +10,6 @@ plugin_LTLIBRARIES = libstrongswan-hmac.la
endif
libstrongswan_hmac_la_SOURCES = \
- hmac_plugin.h hmac_plugin.c hmac.h hmac.c \
- hmac_prf.h hmac_prf.c hmac_signer.h hmac_signer.c
+ hmac_plugin.h hmac_plugin.c hmac.h hmac.c
libstrongswan_hmac_la_LDFLAGS = -module -avoid-version
diff --git a/src/libstrongswan/plugins/hmac/Makefile.in b/src/libstrongswan/plugins/hmac/Makefile.in
index 5242764d4..aed35cf16 100644
--- a/src/libstrongswan/plugins/hmac/Makefile.in
+++ b/src/libstrongswan/plugins/hmac/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -75,15 +76,14 @@ am__base_list = \
am__installdirs = "$(DESTDIR)$(plugindir)"
LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_hmac_la_LIBADD =
-am_libstrongswan_hmac_la_OBJECTS = hmac_plugin.lo hmac.lo hmac_prf.lo \
- hmac_signer.lo
+am_libstrongswan_hmac_la_OBJECTS = hmac_plugin.lo hmac.lo
libstrongswan_hmac_la_OBJECTS = $(am_libstrongswan_hmac_la_OBJECTS)
libstrongswan_hmac_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libstrongswan_hmac_la_LDFLAGS) $(LDFLAGS) -o $@
@MONOLITHIC_FALSE@am_libstrongswan_hmac_la_rpath = -rpath $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_hmac_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -109,6 +109,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -203,11 +204,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -224,11 +228,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -244,6 +249,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -253,7 +259,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -286,8 +291,7 @@ AM_CFLAGS = -rdynamic
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-hmac.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-hmac.la
libstrongswan_hmac_la_SOURCES = \
- hmac_plugin.h hmac_plugin.c hmac.h hmac.c \
- hmac_prf.h hmac_prf.c hmac_signer.h hmac_signer.c
+ hmac_plugin.h hmac_plugin.c hmac.h hmac.c
libstrongswan_hmac_la_LDFLAGS = -module -avoid-version
all: all-am
@@ -375,8 +379,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hmac.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hmac_plugin.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hmac_prf.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hmac_signer.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
diff --git a/src/libstrongswan/plugins/hmac/hmac.c b/src/libstrongswan/plugins/hmac/hmac.c
index 91294305e..44cb46b4d 100644
--- a/src/libstrongswan/plugins/hmac/hmac.c
+++ b/src/libstrongswan/plugins/hmac/hmac.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -14,23 +15,25 @@
* for more details.
*/
-#include <string.h>
-
#include "hmac.h"
+#include <crypto/mac.h>
+#include <crypto/prfs/mac_prf.h>
+#include <crypto/signers/mac_signer.h>
-typedef struct private_hmac_t private_hmac_t;
+typedef struct private_mac_t private_mac_t;
/**
- * Private data of a hmac_t object.
+ * Private data of a mac_t object.
*
* The variable names are the same as in the RFC.
*/
-struct private_hmac_t {
+struct private_mac_t {
+
/**
- * Public hmac_t interface.
+ * Implements mac_t interface
*/
- hmac_t public;
+ mac_t public;
/**
* Block size, as in RFC.
@@ -53,8 +56,8 @@ struct private_hmac_t {
chunk_t ipaded_key;
};
-METHOD(hmac_t, get_mac, void,
- private_hmac_t *this, chunk_t data, u_int8_t *out)
+METHOD(mac_t, get_mac, bool,
+ private_mac_t *this, chunk_t data, u_int8_t *out)
{
/* H(K XOR opad, H(K XOR ipad, text))
*
@@ -69,51 +72,28 @@ METHOD(hmac_t, get_mac, void,
if (out == NULL)
{
/* append data to inner */
- this->h->get_hash(this->h, data, NULL);
+ return this->h->get_hash(this->h, data, NULL);
}
- else
- {
- /* append and do outer hash */
- inner.ptr = buffer;
- inner.len = this->h->get_hash_size(this->h);
-
- /* complete inner */
- this->h->get_hash(this->h, data, buffer);
- /* do outer */
- this->h->get_hash(this->h, this->opaded_key, NULL);
- this->h->get_hash(this->h, inner, out);
+ /* append and do outer hash */
+ inner.ptr = buffer;
+ inner.len = this->h->get_hash_size(this->h);
- /* reinit for next call */
- this->h->get_hash(this->h, this->ipaded_key, NULL);
- }
+ /* complete inner, do outer and reinit for next call */
+ return this->h->get_hash(this->h, data, buffer) &&
+ this->h->get_hash(this->h, this->opaded_key, NULL) &&
+ this->h->get_hash(this->h, inner, out) &&
+ this->h->get_hash(this->h, this->ipaded_key, NULL);
}
-METHOD(hmac_t, allocate_mac, void,
- private_hmac_t *this, chunk_t data, chunk_t *out)
-{
- /* allocate space and use get_mac */
- if (out == NULL)
- {
- /* append mode */
- get_mac(this, data, NULL);
- }
- else
- {
- out->len = this->h->get_hash_size(this->h);
- out->ptr = malloc(out->len);
- get_mac(this, data, out->ptr);
- }
-}
-
-METHOD(hmac_t, get_block_size, size_t,
- private_hmac_t *this)
+METHOD(mac_t, get_mac_size, size_t,
+ private_mac_t *this)
{
return this->h->get_hash_size(this->h);
}
-METHOD(hmac_t, set_key, void,
- private_hmac_t *this, chunk_t key)
+METHOD(mac_t, set_key, bool,
+ private_mac_t *this, chunk_t key)
{
int i;
u_int8_t buffer[this->b];
@@ -123,7 +103,10 @@ METHOD(hmac_t, set_key, void,
if (key.len > this->b)
{
/* if key is too long, it will be hashed */
- this->h->get_hash(this->h, key, buffer);
+ if (!this->h->get_hash(this->h, key, buffer))
+ {
+ return FALSE;
+ }
}
else
{
@@ -139,12 +122,12 @@ METHOD(hmac_t, set_key, void,
}
/* begin hashing of inner pad */
- this->h->reset(this->h);
- this->h->get_hash(this->h, this->ipaded_key, NULL);
+ return this->h->reset(this->h) &&
+ this->h->get_hash(this->h, this->ipaded_key, NULL);
}
-METHOD(hmac_t, destroy, void,
- private_hmac_t *this)
+METHOD(mac_t, destroy, void,
+ private_mac_t *this)
{
this->h->destroy(this->h);
chunk_clear(&this->opaded_key);
@@ -153,17 +136,16 @@ METHOD(hmac_t, destroy, void,
}
/*
- * Described in header
+ * Creates an mac_t object
*/
-hmac_t *hmac_create(hash_algorithm_t hash_algorithm)
+static mac_t *hmac_create(hash_algorithm_t hash_algorithm)
{
- private_hmac_t *this;
+ private_mac_t *this;
INIT(this,
.public = {
.get_mac = _get_mac,
- .allocate_mac = _allocate_mac,
- .get_block_size = _get_block_size,
+ .get_mac_size = _get_mac_size,
.set_key = _set_key,
.destroy = _destroy,
},
@@ -202,3 +184,34 @@ hmac_t *hmac_create(hash_algorithm_t hash_algorithm)
return &this->public;
}
+
+/*
+ * Described in header
+ */
+prf_t *hmac_prf_create(pseudo_random_function_t algo)
+{
+ mac_t *hmac;
+
+ hmac = hmac_create(hasher_algorithm_from_prf(algo));
+ if (hmac)
+ {
+ return mac_prf_create(hmac);
+ }
+ return NULL;
+}
+
+/*
+ * Described in header
+ */
+signer_t *hmac_signer_create(integrity_algorithm_t algo)
+{
+ mac_t *hmac;
+ size_t trunc;
+
+ hmac = hmac_create(hasher_algorithm_from_integrity(algo, &trunc));
+ if (hmac)
+ {
+ return mac_signer_create(hmac, trunc);
+ }
+ return NULL;
+}
diff --git a/src/libstrongswan/plugins/hmac/hmac.h b/src/libstrongswan/plugins/hmac/hmac.h
index 1ed041596..bf66dd4aa 100644
--- a/src/libstrongswan/plugins/hmac/hmac.h
+++ b/src/libstrongswan/plugins/hmac/hmac.h
@@ -1,6 +1,5 @@
/*
- * Copyright (C) 2005-2008 Martin Willi
- * Copyright (C) 2005 Jan Hutter
+ * Copyright (C) 2012 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -15,79 +14,34 @@
*/
/**
- * @defgroup hmac hmac
+ * Implements the message authentication algorithm described in RFC2104.
+ *
+ * It uses a hash function, which must be implemented as a hasher_t class.
+ *
+ * @defgroup hmac_mac mac
* @{ @ingroup hmac_p
*/
#ifndef HMAC_H_
#define HMAC_H_
-typedef struct hmac_t hmac_t;
-
-#include <crypto/hashers/hasher.h>
+#include <crypto/prfs/prf.h>
+#include <crypto/signers/signer.h>
/**
- * Message authentication using hash functions.
+ * Creates a new prf_t object based on an HMAC.
*
- * This class implements the message authentication algorithm
- * described in RFC2104. It uses a hash function, which must
- * be implemented as a hasher_t class.
+ * @param algo algorithm to implement
+ * @return prf_t object, NULL if not supported
*/
-struct hmac_t {
- /**
- * Generate message authentication code.
- *
- * If buffer is NULL, no result is given back. A next call will
- * append the data to already supplied data. If buffer is not NULL,
- * the mac of all apended data is calculated, returned and the
- * state of the hmac_t is reseted.
- *
- * @param data chunk of data to authenticate
- * @param buffer pointer where the generated bytes will be written
- */
- void (*get_mac) (hmac_t *this, chunk_t data, u_int8_t *buffer);
-
- /**
- * Generates message authentication code and allocate space for them.
- *
- * If chunk is NULL, no result is given back. A next call will
- * append the data to already supplied. If chunk is not NULL,
- * the mac of all apended data is calculated, returned and the
- * state of the hmac_t reset;
- *
- * @param data chunk of data to authenticate
- * @param chunk chunk which will hold generated bytes
- */
- void (*allocate_mac) (hmac_t *this, chunk_t data, chunk_t *chunk);
-
- /**
- * Get the block size of this hmac_t object.
- *
- * @return block size in bytes
- */
- size_t (*get_block_size) (hmac_t *this);
-
- /**
- * Set the key for this hmac_t object.
- *
- * Any key length is accepted.
- *
- * @param key key to set
- */
- void (*set_key) (hmac_t *this, chunk_t key);
-
- /**
- * Destroys a hmac_t object.
- */
- void (*destroy) (hmac_t *this);
-};
+prf_t *hmac_prf_create(pseudo_random_function_t algo);
/**
- * Creates a new hmac_t object.
+ * Creates a new signer_t object based on an HMAC.
*
- * @param hash_algorithm hash algorithm to use
- * @return hmac_t object, NULL if not supported
+ * @param algo algorithm to implement
+ * @return signer_t, NULL if not supported
*/
-hmac_t *hmac_create(hash_algorithm_t hash_algorithm);
+signer_t *hmac_signer_create(integrity_algorithm_t algo);
#endif /** HMAC_H_ @}*/
diff --git a/src/libstrongswan/plugins/hmac/hmac_plugin.c b/src/libstrongswan/plugins/hmac/hmac_plugin.c
index 7d9ff3c67..f9c0c484b 100644
--- a/src/libstrongswan/plugins/hmac/hmac_plugin.c
+++ b/src/libstrongswan/plugins/hmac/hmac_plugin.c
@@ -16,8 +16,7 @@
#include "hmac_plugin.h"
#include <library.h>
-#include "hmac_signer.h"
-#include "hmac_prf.h"
+#include "hmac.h"
typedef struct private_hmac_plugin_t private_hmac_plugin_t;
diff --git a/src/libstrongswan/plugins/hmac/hmac_prf.c b/src/libstrongswan/plugins/hmac/hmac_prf.c
deleted file mode 100644
index ca10612f9..000000000
--- a/src/libstrongswan/plugins/hmac/hmac_prf.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2005-2006 Martin Willi
- * Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include "hmac_prf.h"
-
-#include "hmac.h"
-
-
-typedef struct private_hmac_prf_t private_hmac_prf_t;
-
-/**
- * Private data of a hma_prf_t object.
- */
-struct private_hmac_prf_t {
- /**
- * Public hmac_prf_t interface.
- */
- hmac_prf_t public;
-
- /**
- * Hmac to use for generation.
- */
- hmac_t *hmac;
-};
-
-METHOD(prf_t, get_bytes, void,
- private_hmac_prf_t *this, chunk_t seed, u_int8_t *buffer)
-{
- this->hmac->get_mac(this->hmac, seed, buffer);
-}
-
-METHOD(prf_t, allocate_bytes, void,
- private_hmac_prf_t *this, chunk_t seed, chunk_t *chunk)
-{
- this->hmac->allocate_mac(this->hmac, seed, chunk);
-}
-
-METHOD(prf_t, get_block_size, size_t,
- private_hmac_prf_t *this)
-{
- return this->hmac->get_block_size(this->hmac);
-}
-
-METHOD(prf_t, get_key_size, size_t,
- private_hmac_prf_t *this)
-{
- /* for HMAC prfs, IKEv2 uses block size as key size */
- return this->hmac->get_block_size(this->hmac);
-}
-
-METHOD(prf_t, set_key, void,
- private_hmac_prf_t *this, chunk_t key)
-{
- this->hmac->set_key(this->hmac, key);
-}
-
-METHOD(prf_t, destroy, void,
- private_hmac_prf_t *this)
-{
- this->hmac->destroy(this->hmac);
- free(this);
-}
-
-/*
- * Described in header.
- */
-hmac_prf_t *hmac_prf_create(pseudo_random_function_t algo)
-{
- private_hmac_prf_t *this;
- hmac_t *hmac;
-
- switch (algo)
- {
- case PRF_HMAC_SHA1:
- hmac = hmac_create(HASH_SHA1);
- break;
- case PRF_HMAC_MD5:
- hmac = hmac_create(HASH_MD5);
- break;
- case PRF_HMAC_SHA2_256:
- hmac = hmac_create(HASH_SHA256);
- break;
- case PRF_HMAC_SHA2_384:
- hmac = hmac_create(HASH_SHA384);
- break;
- case PRF_HMAC_SHA2_512:
- hmac = hmac_create(HASH_SHA512);
- break;
- default:
- return NULL;
- }
- if (hmac == NULL)
- {
- return NULL;
- }
-
- INIT(this,
- .public = {
- .prf = {
- .get_bytes = _get_bytes,
- .allocate_bytes = _allocate_bytes,
- .get_block_size = _get_block_size,
- .get_key_size = _get_key_size,
- .set_key = _set_key,
- .destroy = _destroy,
- },
- },
- .hmac = hmac,
- );
-
- return &this->public;
-}
-
diff --git a/src/libstrongswan/plugins/hmac/hmac_prf.h b/src/libstrongswan/plugins/hmac/hmac_prf.h
deleted file mode 100644
index 29d7269ae..000000000
--- a/src/libstrongswan/plugins/hmac/hmac_prf.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2008 Martin Willi
- * Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup hmac_prf hmac_prf
- * @{ @ingroup hmac_p
- */
-
-#ifndef PRF_HMAC_H_
-#define PRF_HMAC_H_
-
-typedef struct hmac_prf_t hmac_prf_t;
-
-#include <crypto/prfs/prf.h>
-
-/**
- * Implementation of prf_t interface using the HMAC algorithm.
- *
- * This simply wraps a hmac_t in a prf_t. More a question of
- * interface matching.
- */
-struct hmac_prf_t {
-
- /**
- * Implements prf_t interface.
- */
- prf_t prf;
-};
-
-/**
- * Creates a new hmac_prf_t object.
- *
- * @param algo algorithm to implement
- * @return hmac_prf_t object, NULL if hash not supported
- */
-hmac_prf_t *hmac_prf_create(pseudo_random_function_t algo);
-
-#endif /** PRF_HMAC_SHA1_H_ @}*/
diff --git a/src/libstrongswan/plugins/hmac/hmac_signer.c b/src/libstrongswan/plugins/hmac/hmac_signer.c
deleted file mode 100644
index 511a3e3a5..000000000
--- a/src/libstrongswan/plugins/hmac/hmac_signer.c
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright (C) 2005-2008 Martin Willi
- * Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <string.h>
-
-#include "hmac_signer.h"
-#include "hmac.h"
-
-typedef struct private_hmac_signer_t private_hmac_signer_t;
-
-/**
- * Private data structure with signing context.
- */
-struct private_hmac_signer_t {
- /**
- * Public interface of hmac_signer_t.
- */
- hmac_signer_t public;
-
- /**
- * Assigned hmac function.
- */
- hmac_t *hmac;
-
- /**
- * Block size (truncation of HMAC Hash)
- */
- size_t block_size;
-};
-
-METHOD(signer_t, get_signature, void,
- private_hmac_signer_t *this, chunk_t data, u_int8_t *buffer)
-{
- if (buffer == NULL)
- { /* append mode */
- this->hmac->get_mac(this->hmac, data, NULL);
- }
- else
- {
- u_int8_t mac[this->hmac->get_block_size(this->hmac)];
-
- this->hmac->get_mac(this->hmac, data, mac);
- memcpy(buffer, mac, this->block_size);
- }
-}
-
-METHOD(signer_t, allocate_signature, void,
- private_hmac_signer_t *this, chunk_t data, chunk_t *chunk)
-{
- if (chunk == NULL)
- { /* append mode */
- this->hmac->get_mac(this->hmac, data, NULL);
- }
- else
- {
- u_int8_t mac[this->hmac->get_block_size(this->hmac)];
-
- this->hmac->get_mac(this->hmac, data, mac);
-
- chunk->ptr = malloc(this->block_size);
- chunk->len = this->block_size;
-
- memcpy(chunk->ptr, mac, this->block_size);
- }
-}
-
-METHOD(signer_t, verify_signature, bool,
- private_hmac_signer_t *this, chunk_t data, chunk_t signature)
-{
- u_int8_t mac[this->hmac->get_block_size(this->hmac)];
-
- this->hmac->get_mac(this->hmac, data, mac);
-
- if (signature.len != this->block_size)
- {
- return FALSE;
- }
- return memeq(signature.ptr, mac, this->block_size);
-}
-
-METHOD(signer_t, get_key_size, size_t,
- private_hmac_signer_t *this)
-{
- return this->hmac->get_block_size(this->hmac);
-}
-
-METHOD(signer_t, get_block_size, size_t,
- private_hmac_signer_t *this)
-{
- return this->block_size;
-}
-
-METHOD(signer_t, set_key, void,
- private_hmac_signer_t *this, chunk_t key)
-{
- this->hmac->set_key(this->hmac, key);
-}
-
-METHOD(signer_t, destroy, void,
- private_hmac_signer_t *this)
-{
- this->hmac->destroy(this->hmac);
- free(this);
-}
-
-/*
- * Described in header
- */
-hmac_signer_t *hmac_signer_create(integrity_algorithm_t algo)
-{
- private_hmac_signer_t *this;
- hmac_t *hmac;
- size_t trunc;
-
- switch (algo)
- {
- case AUTH_HMAC_SHA1_96:
- hmac = hmac_create(HASH_SHA1);
- trunc = 12;
- break;
- case AUTH_HMAC_SHA1_128:
- hmac = hmac_create(HASH_SHA1);
- trunc = 16;
- break;
- case AUTH_HMAC_SHA1_160:
- hmac = hmac_create(HASH_SHA1);
- trunc = 20;
- break;
- case AUTH_HMAC_MD5_96:
- hmac = hmac_create(HASH_MD5);
- trunc = 12;
- break;
- case AUTH_HMAC_MD5_128:
- hmac = hmac_create(HASH_MD5);
- trunc = 16;
- break;
- case AUTH_HMAC_SHA2_256_128:
- hmac = hmac_create(HASH_SHA256);
- trunc = 16;
- break;
- case AUTH_HMAC_SHA2_384_192:
- hmac = hmac_create(HASH_SHA384);
- trunc = 24;
- break;
- case AUTH_HMAC_SHA2_512_256:
- hmac = hmac_create(HASH_SHA512);
- trunc = 32;
- break;
- case AUTH_HMAC_SHA2_256_256:
- hmac = hmac_create(HASH_SHA256);
- trunc = 32;
- break;
- case AUTH_HMAC_SHA2_384_384:
- hmac = hmac_create(HASH_SHA384);
- trunc = 48;
- break;
- default:
- return NULL;
- }
-
- if (hmac == NULL)
- {
- return NULL;
- }
-
- INIT(this,
- .public = {
- .signer = {
- .get_signature = _get_signature,
- .allocate_signature = _allocate_signature,
- .verify_signature = _verify_signature,
- .get_key_size = _get_key_size,
- .get_block_size = _get_block_size,
- .set_key = _set_key,
- .destroy = _destroy,
- },
- },
- .block_size = min(trunc, hmac->get_block_size(hmac)),
- .hmac = hmac,
- );
-
- return &this->public;
-}
-
diff --git a/src/libstrongswan/plugins/hmac/hmac_signer.h b/src/libstrongswan/plugins/hmac/hmac_signer.h
deleted file mode 100644
index 5e798683b..000000000
--- a/src/libstrongswan/plugins/hmac/hmac_signer.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2005-2008 Martin Willi
- * Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup hmac_signer hmac_signer
- * @{ @ingroup hmac_p
- */
-
-#ifndef HMAC_SIGNER_H_
-#define HMAC_SIGNER_H_
-
-typedef struct hmac_signer_t hmac_signer_t;
-
-#include <crypto/signers/signer.h>
-
-/**
- * Implementation of signer_t interface using HMAC.
- *
- * HMAC uses a standard hash function implemented in a hasher_t to build a MAC.
- */
-struct hmac_signer_t {
-
- /**
- * Implements signer_t interface.
- */
- signer_t signer;
-};
-
-/**
- * Creates a new hmac_signer_t.
- *
- * HMAC signatures are often truncated to shorten them to a more usable, but
- * still secure enough length.
- * Block size must be equal or smaller then the hash algorithms hash.
- *
- * @param algo algorithm to implement
- * @return hmac_signer_t, NULL if not supported
- */
-hmac_signer_t *hmac_signer_create(integrity_algorithm_t algo);
-
-#endif /** HMAC_SIGNER_H_ @}*/
diff --git a/src/libstrongswan/plugins/ldap/Makefile.in b/src/libstrongswan/plugins/ldap/Makefile.in
index 851df5667..d11feddb1 100644
--- a/src/libstrongswan/plugins/ldap/Makefile.in
+++ b/src/libstrongswan/plugins/ldap/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -82,7 +83,7 @@ libstrongswan_ldap_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(libstrongswan_ldap_la_LDFLAGS) $(LDFLAGS) -o $@
@MONOLITHIC_FALSE@am_libstrongswan_ldap_la_rpath = -rpath $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_ldap_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -108,6 +109,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -202,11 +204,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -223,11 +228,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -243,6 +249,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -252,7 +259,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/ldap/ldap_fetcher.c b/src/libstrongswan/plugins/ldap/ldap_fetcher.c
index fc6114b0a..75f964853 100644
--- a/src/libstrongswan/plugins/ldap/ldap_fetcher.c
+++ b/src/libstrongswan/plugins/ldap/ldap_fetcher.c
@@ -176,13 +176,14 @@ METHOD(fetcher_t, set_option, bool,
switch (option)
{
case FETCH_TIMEOUT:
- {
this->timeout = va_arg(args, u_int);
- return TRUE;
- }
+ break;
default:
+ va_end(args);
return FALSE;
}
+ va_end(args);
+ return TRUE;
}
METHOD(fetcher_t, destroy, void,
diff --git a/src/libstrongswan/plugins/md4/Makefile.in b/src/libstrongswan/plugins/md4/Makefile.in
index f5b06a0df..14b6370f4 100644
--- a/src/libstrongswan/plugins/md4/Makefile.in
+++ b/src/libstrongswan/plugins/md4/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -82,7 +83,7 @@ libstrongswan_md4_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(libstrongswan_md4_la_LDFLAGS) $(LDFLAGS) -o $@
@MONOLITHIC_FALSE@am_libstrongswan_md4_la_rpath = -rpath $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_md4_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -108,6 +109,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -202,11 +204,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -223,11 +228,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -243,6 +249,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -252,7 +259,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/md4/md4_hasher.c b/src/libstrongswan/plugins/md4/md4_hasher.c
index 6a31017c2..06c9ec2f8 100644
--- a/src/libstrongswan/plugins/md4/md4_hasher.c
+++ b/src/libstrongswan/plugins/md4/md4_hasher.c
@@ -266,20 +266,32 @@ static void MD4Final (private_md4_hasher_t *this, u_int8_t digest[16])
}
}
+METHOD(hasher_t, reset, bool,
+ private_md4_hasher_t *this)
+{
+ this->state[0] = 0x67452301;
+ this->state[1] = 0xefcdab89;
+ this->state[2] = 0x98badcfe;
+ this->state[3] = 0x10325476;
+ this->count[0] = 0;
+ this->count[1] = 0;
+ return TRUE;
+}
-METHOD(hasher_t, get_hash, void,
+METHOD(hasher_t, get_hash, bool,
private_md4_hasher_t *this, chunk_t chunk, u_int8_t *buffer)
{
MD4Update(this, chunk.ptr, chunk.len);
if (buffer != NULL)
{
MD4Final(this, buffer);
- this->public.hasher_interface.reset(&(this->public.hasher_interface));
+ reset(this);
}
+ return TRUE;
}
-METHOD(hasher_t, allocate_hash, void,
+METHOD(hasher_t, allocate_hash, bool,
private_md4_hasher_t *this, chunk_t chunk, chunk_t *hash)
{
chunk_t allocated_hash;
@@ -291,10 +303,11 @@ METHOD(hasher_t, allocate_hash, void,
allocated_hash.len = HASH_SIZE_MD4;
MD4Final(this, allocated_hash.ptr);
- this->public.hasher_interface.reset(&(this->public.hasher_interface));
+ reset(this);
*hash = allocated_hash;
}
+ return TRUE;
}
METHOD(hasher_t, get_hash_size, size_t,
@@ -303,17 +316,6 @@ METHOD(hasher_t, get_hash_size, size_t,
return HASH_SIZE_MD4;
}
-METHOD(hasher_t, reset, void,
- private_md4_hasher_t *this)
-{
- this->state[0] = 0x67452301;
- this->state[1] = 0xefcdab89;
- this->state[2] = 0x98badcfe;
- this->state[3] = 0x10325476;
- this->count[0] = 0;
- this->count[1] = 0;
-}
-
METHOD(hasher_t, destroy, void,
private_md4_hasher_t *this)
{
diff --git a/src/libstrongswan/plugins/md5/Makefile.in b/src/libstrongswan/plugins/md5/Makefile.in
index f7762c37e..ba228f8ea 100644
--- a/src/libstrongswan/plugins/md5/Makefile.in
+++ b/src/libstrongswan/plugins/md5/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -82,7 +83,7 @@ libstrongswan_md5_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(libstrongswan_md5_la_LDFLAGS) $(LDFLAGS) -o $@
@MONOLITHIC_FALSE@am_libstrongswan_md5_la_rpath = -rpath $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_md5_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -108,6 +109,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -202,11 +204,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -223,11 +228,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -243,6 +249,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -252,7 +259,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/md5/md5_hasher.c b/src/libstrongswan/plugins/md5/md5_hasher.c
index 45c2391ef..99b505e58 100644
--- a/src/libstrongswan/plugins/md5/md5_hasher.c
+++ b/src/libstrongswan/plugins/md5/md5_hasher.c
@@ -299,33 +299,42 @@ static void MD5Final (private_md5_hasher_t *this, u_int8_t digest[16])
}
}
-METHOD(hasher_t, get_hash, void,
+METHOD(hasher_t, reset, bool,
+ private_md5_hasher_t *this)
+{
+ this->state[0] = 0x67452301;
+ this->state[1] = 0xefcdab89;
+ this->state[2] = 0x98badcfe;
+ this->state[3] = 0x10325476;
+ this->count[0] = 0;
+ this->count[1] = 0;
+
+ return TRUE;
+}
+
+METHOD(hasher_t, get_hash, bool,
private_md5_hasher_t *this, chunk_t chunk, u_int8_t *buffer)
{
MD5Update(this, chunk.ptr, chunk.len);
if (buffer != NULL)
{
MD5Final(this, buffer);
- this->public.hasher_interface.reset(&(this->public.hasher_interface));
+ reset(this);
}
+ return TRUE;
}
-METHOD(hasher_t, allocate_hash, void,
+METHOD(hasher_t, allocate_hash, bool,
private_md5_hasher_t *this, chunk_t chunk, chunk_t *hash)
{
- chunk_t allocated_hash;
-
MD5Update(this, chunk.ptr, chunk.len);
if (hash != NULL)
{
- allocated_hash.ptr = malloc(HASH_SIZE_MD5);
- allocated_hash.len = HASH_SIZE_MD5;
-
- MD5Final(this, allocated_hash.ptr);
- this->public.hasher_interface.reset(&(this->public.hasher_interface));
-
- *hash = allocated_hash;
+ *hash = chunk_alloc(HASH_SIZE_MD5);
+ MD5Final(this, hash->ptr);
+ reset(this);
}
+ return TRUE;
}
METHOD(hasher_t, get_hash_size, size_t,
@@ -334,17 +343,6 @@ METHOD(hasher_t, get_hash_size, size_t,
return HASH_SIZE_MD5;
}
-METHOD(hasher_t, reset, void,
- private_md5_hasher_t *this)
-{
- this->state[0] = 0x67452301;
- this->state[1] = 0xefcdab89;
- this->state[2] = 0x98badcfe;
- this->state[3] = 0x10325476;
- this->count[0] = 0;
- this->count[1] = 0;
-}
-
METHOD(hasher_t, destroy, void,
private_md5_hasher_t *this)
{
diff --git a/src/libstrongswan/plugins/md5/md5_plugin.c b/src/libstrongswan/plugins/md5/md5_plugin.c
index a3ad7b305..4a61af618 100644
--- a/src/libstrongswan/plugins/md5/md5_plugin.c
+++ b/src/libstrongswan/plugins/md5/md5_plugin.c
@@ -51,8 +51,6 @@ METHOD(plugin_t, get_features, int,
METHOD(plugin_t, destroy, void,
private_md5_plugin_t *this)
{
- lib->crypto->remove_hasher(lib->crypto,
- (hasher_constructor_t)md5_hasher_create);
free(this);
}
diff --git a/src/libstrongswan/plugins/mysql/Makefile.in b/src/libstrongswan/plugins/mysql/Makefile.in
index 5025a0eb8..88dba0967 100644
--- a/src/libstrongswan/plugins/mysql/Makefile.in
+++ b/src/libstrongswan/plugins/mysql/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -84,7 +85,7 @@ libstrongswan_mysql_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@MONOLITHIC_FALSE@am_libstrongswan_mysql_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_mysql_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -110,6 +111,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -204,11 +206,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -225,11 +230,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -245,6 +251,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -254,7 +261,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/mysql/mysql_database.c b/src/libstrongswan/plugins/mysql/mysql_database.c
index 25ea42a4f..1a20a804a 100644
--- a/src/libstrongswan/plugins/mysql/mysql_database.c
+++ b/src/libstrongswan/plugins/mysql/mysql_database.c
@@ -472,6 +472,7 @@ static bool mysql_enumerator_enumerate(mysql_enumerator_t *this, ...)
break;
}
}
+ va_end(args);
return TRUE;
}
diff --git a/src/libstrongswan/plugins/nonce/Makefile.am b/src/libstrongswan/plugins/nonce/Makefile.am
new file mode 100644
index 000000000..0a2ccfc08
--- /dev/null
+++ b/src/libstrongswan/plugins/nonce/Makefile.am
@@ -0,0 +1,16 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-nonce.la
+else
+plugin_LTLIBRARIES = libstrongswan-nonce.la
+endif
+
+libstrongswan_nonce_la_SOURCES = \
+ nonce_plugin.h nonce_plugin.c \
+ nonce_nonceg.c nonce_nonceg.h
+
+libstrongswan_nonce_la_LDFLAGS = -module -avoid-version
diff --git a/src/pluto/plugins/xauth/Makefile.in b/src/libstrongswan/plugins/nonce/Makefile.in
index 5a575548e..7ce23b4d9 100644
--- a/src/pluto/plugins/xauth/Makefile.in
+++ b/src/libstrongswan/plugins/nonce/Makefile.in
@@ -34,7 +34,7 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-subdir = src/pluto/plugins/xauth
+subdir = src/libstrongswan/plugins/nonce
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -73,15 +74,17 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
-LTLIBRARIES = $(plugin_LTLIBRARIES)
-libstrongswan_xauth_la_LIBADD =
-am_libstrongswan_xauth_la_OBJECTS = xauth_plugin.lo \
- xauth_default_provider.lo xauth_default_verifier.lo
-libstrongswan_xauth_la_OBJECTS = $(am_libstrongswan_xauth_la_OBJECTS)
-libstrongswan_xauth_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_nonce_la_LIBADD =
+am_libstrongswan_nonce_la_OBJECTS = nonce_plugin.lo nonce_nonceg.lo
+libstrongswan_nonce_la_OBJECTS = $(am_libstrongswan_nonce_la_OBJECTS)
+libstrongswan_nonce_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
- $(libstrongswan_xauth_la_LDFLAGS) $(LDFLAGS) -o $@
-DEFAULT_INCLUDES = -I.@am__isrc@
+ $(libstrongswan_nonce_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_nonce_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_nonce_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -94,8 +97,8 @@ CCLD = $(CC)
LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
-SOURCES = $(libstrongswan_xauth_la_SOURCES)
-DIST_SOURCES = $(libstrongswan_xauth_la_SOURCES)
+SOURCES = $(libstrongswan_nonce_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_nonce_la_SOURCES)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -107,6 +110,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -201,11 +205,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -222,11 +229,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -242,6 +250,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -251,7 +260,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -279,18 +287,15 @@ top_srcdir = @top_srcdir@
urandom_device = @urandom_device@
xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
-INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
- -I$(top_srcdir)/src/libfreeswan -I$(top_srcdir)/src/whack \
- -I$(top_srcdir)/src/pluto
-
+INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
-plugin_LTLIBRARIES = libstrongswan-xauth.la
-libstrongswan_xauth_la_SOURCES = \
- xauth_plugin.h xauth_plugin.c \
- xauth_default_provider.c xauth_default_provider.h \
- xauth_default_verifier.c xauth_default_verifier.h
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-nonce.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-nonce.la
+libstrongswan_nonce_la_SOURCES = \
+ nonce_plugin.h nonce_plugin.c \
+ nonce_nonceg.c nonce_nonceg.h
-libstrongswan_xauth_la_LDFLAGS = -module -avoid-version
+libstrongswan_nonce_la_LDFLAGS = -module -avoid-version
all: all-am
.SUFFIXES:
@@ -304,9 +309,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/pluto/plugins/xauth/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libstrongswan/plugins/nonce/Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --gnu src/pluto/plugins/xauth/Makefile
+ $(AUTOMAKE) --gnu src/libstrongswan/plugins/nonce/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
@@ -325,6 +330,15 @@ $(top_srcdir)/configure: $(am__configure_deps)
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
@@ -356,8 +370,8 @@ clean-pluginLTLIBRARIES:
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
-libstrongswan-xauth.la: $(libstrongswan_xauth_la_OBJECTS) $(libstrongswan_xauth_la_DEPENDENCIES)
- $(libstrongswan_xauth_la_LINK) -rpath $(plugindir) $(libstrongswan_xauth_la_OBJECTS) $(libstrongswan_xauth_la_LIBADD) $(LIBS)
+libstrongswan-nonce.la: $(libstrongswan_nonce_la_OBJECTS) $(libstrongswan_nonce_la_DEPENDENCIES)
+ $(libstrongswan_nonce_la_LINK) $(am_libstrongswan_nonce_la_rpath) $(libstrongswan_nonce_la_OBJECTS) $(libstrongswan_nonce_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -365,9 +379,8 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xauth_default_provider.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xauth_default_verifier.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xauth_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nonce_nonceg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nonce_plugin.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@@ -512,8 +525,8 @@ maintainer-clean-generic:
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
-clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
- mostlyclean-am
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
@@ -584,18 +597,19 @@ uninstall-am: uninstall-pluginLTLIBRARIES
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libtool clean-pluginLTLIBRARIES ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-pluginLTLIBRARIES \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libstrongswan/plugins/nonce/nonce_nonceg.c b/src/libstrongswan/plugins/nonce/nonce_nonceg.c
new file mode 100644
index 000000000..0402e3574
--- /dev/null
+++ b/src/libstrongswan/plugins/nonce/nonce_nonceg.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2012 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 "nonce_nonceg.h"
+
+#include <debug.h>
+
+typedef struct private_nonce_nonceg_t private_nonce_nonceg_t;
+
+/**
+ * Private data of a nonce_nonceg_t object.
+ */
+struct private_nonce_nonceg_t {
+
+ /**
+ * Public nonce_nonceg_t interface.
+ */
+ nonce_nonceg_t public;
+
+ /**
+ * Random number generator
+ */
+ rng_t* rng;
+};
+
+METHOD(nonce_gen_t, get_nonce, bool,
+ private_nonce_nonceg_t *this, size_t size, u_int8_t *buffer)
+{
+ return this->rng->get_bytes(this->rng, size, buffer);
+}
+
+METHOD(nonce_gen_t, allocate_nonce, bool,
+ private_nonce_nonceg_t *this, size_t size, chunk_t *chunk)
+{
+ return this->rng->allocate_bytes(this->rng, size, chunk);
+}
+
+METHOD(nonce_gen_t, destroy, void,
+ private_nonce_nonceg_t *this)
+{
+ DESTROY_IF(this->rng);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+nonce_nonceg_t *nonce_nonceg_create()
+{
+ private_nonce_nonceg_t *this;
+
+ INIT(this,
+ .public = {
+ .nonce_gen = {
+ .get_nonce = _get_nonce,
+ .allocate_nonce = _allocate_nonce,
+ .destroy = _destroy,
+ },
+ },
+ );
+
+ this->rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ if (!this->rng)
+ {
+ DBG1(DBG_LIB, "no RNG found for quality %N", rng_quality_names,
+ RNG_WEAK);
+ destroy(this);
+ return NULL;
+ }
+
+ return &this->public;
+}
diff --git a/src/libstrongswan/plugins/nonce/nonce_nonceg.h b/src/libstrongswan/plugins/nonce/nonce_nonceg.h
new file mode 100644
index 000000000..2ae0c97de
--- /dev/null
+++ b/src/libstrongswan/plugins/nonce/nonce_nonceg.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+/**
+ * @defgroup nonce_nonceg nonce_nonceg
+ * @{ @ingroup nonce_p
+ */
+
+#ifndef NONCE_NONCEG_H_
+#define NONCE_NONCEG_H_
+
+typedef struct nonce_nonceg_t nonce_nonceg_t;
+
+#include <library.h>
+
+/**
+ * nonce_gen_t implementation using an rng plugin
+ */
+struct nonce_nonceg_t {
+
+ /**
+ * Implements nonce_gen_t.
+ */
+ nonce_gen_t nonce_gen;
+};
+
+/**
+ * Creates an nonce_nonceg_t instance.
+ *
+ * @return created nonce_nonceg_t
+ */
+nonce_nonceg_t *nonce_nonceg_create();
+
+#endif /** NONCE_NONCEG_H_ @} */
diff --git a/src/libcharon/plugins/socket_raw/socket_raw_plugin.c b/src/libstrongswan/plugins/nonce/nonce_plugin.c
index 1299c30ca..90f2e8fac 100644
--- a/src/libcharon/plugins/socket_raw/socket_raw_plugin.c
+++ b/src/libstrongswan/plugins/nonce/nonce_plugin.c
@@ -1,8 +1,6 @@
/*
- * Copyright (C) 2010 Tobias Brunner
+ * Copyright (C) 2012 Adrian-Ken Rueegsegger
* Hochschule fuer Technik Rapperswil
- * Copyright (C) 2010 Martin Willi
- * Copyright (C) 2010 revosec AG
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -15,44 +13,44 @@
* for more details.
*/
-#include "socket_raw_plugin.h"
+#include "nonce_plugin.h"
-#include "socket_raw_socket.h"
+#include <library.h>
+#include "nonce_nonceg.h"
-#include <daemon.h>
-
-typedef struct private_socket_raw_plugin_t private_socket_raw_plugin_t;
+typedef struct private_nonce_plugin_t private_nonce_plugin_t;
/**
- * Private data of socket plugin
+ * private data of nonce_plugin
*/
-struct private_socket_raw_plugin_t {
+struct private_nonce_plugin_t {
/**
- * Implements plugin interface
+ * public functions
*/
- socket_raw_plugin_t public;
+ nonce_plugin_t public;
};
METHOD(plugin_t, get_name, char*,
- private_socket_raw_plugin_t *this)
+ private_nonce_plugin_t *this)
{
- return "socket-raw";
+ return "nonce";
}
METHOD(plugin_t, get_features, int,
- private_socket_raw_plugin_t *this, plugin_feature_t *features[])
+ private_nonce_plugin_t *this, plugin_feature_t *features[])
{
static plugin_feature_t f[] = {
- PLUGIN_CALLBACK(socket_register, socket_raw_socket_create),
- PLUGIN_PROVIDE(CUSTOM, "socket"),
+ PLUGIN_REGISTER(NONCE_GEN, nonce_nonceg_create),
+ PLUGIN_PROVIDE(NONCE_GEN),
+ PLUGIN_DEPENDS(RNG, RNG_WEAK),
};
*features = f;
return countof(f);
}
METHOD(plugin_t, destroy, void,
- private_socket_raw_plugin_t *this)
+ private_nonce_plugin_t *this)
{
free(this);
}
@@ -60,9 +58,9 @@ METHOD(plugin_t, destroy, void,
/*
* see header file
*/
-plugin_t *socket_raw_plugin_create()
+plugin_t *nonce_plugin_create()
{
- private_socket_raw_plugin_t *this;
+ private_nonce_plugin_t *this;
INIT(this,
.public = {
@@ -76,4 +74,3 @@ plugin_t *socket_raw_plugin_create()
return &this->public.plugin;
}
-
diff --git a/src/pluto/plugins/xauth/xauth_plugin.h b/src/libstrongswan/plugins/nonce/nonce_plugin.h
index 4f14828d2..f4be1c3a8 100644
--- a/src/pluto/plugins/xauth/xauth_plugin.h
+++ b/src/libstrongswan/plugins/nonce/nonce_plugin.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Andreas Steffen
+ * Copyright (C) 2012 Adrian-Ken Rueegsegger
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -14,29 +14,29 @@
*/
/**
- * @defgroup xauth xauth
- * @ingroup pplugins
+ * @defgroup nonce_p nonce
+ * @ingroup plugins
*
- * @defgroup xauth_plugin xauth_plugin
- * @{ @ingroup xauth
+ * @defgroup nonce_plugin nonce_plugin
+ * @{ @ingroup nonce_p
*/
-#ifndef XAUTH_PLUGIN_H_
-#define XAUTH_PLUGIN_H_
+#ifndef NONCE_PLUGIN_H_
+#define NONCE_PLUGIN_H_
#include <plugins/plugin.h>
-typedef struct xauth_plugin_t xauth_plugin_t;
+typedef struct nonce_plugin_t nonce_plugin_t;
/**
- * XAUTH plugin
+ * Plugin implementing a nonce generator using an RNG.
*/
-struct xauth_plugin_t {
+struct nonce_plugin_t {
/**
- * implements plugin interface
+ * Implements plugin interface
*/
plugin_t plugin;
};
-#endif /** XAUTH_PLUGIN_H_ @}*/
+#endif /** NONCE_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/openssl/Makefile.am b/src/libstrongswan/plugins/openssl/Makefile.am
index 5c845a19c..c59888663 100644
--- a/src/libstrongswan/plugins/openssl/Makefile.am
+++ b/src/libstrongswan/plugins/openssl/Makefile.am
@@ -22,7 +22,9 @@ libstrongswan_openssl_la_SOURCES = \
openssl_ec_private_key.c openssl_ec_private_key.h \
openssl_ec_public_key.c openssl_ec_public_key.h \
openssl_x509.c openssl_x509.h \
- openssl_crl.c openssl_crl.h
+ openssl_crl.c openssl_crl.h \
+ openssl_rng.c openssl_rng.h \
+ openssl_hmac.c openssl_hmac.h
libstrongswan_openssl_la_LDFLAGS = -module -avoid-version
libstrongswan_openssl_la_LIBADD = -lcrypto
diff --git a/src/libstrongswan/plugins/openssl/Makefile.in b/src/libstrongswan/plugins/openssl/Makefile.in
index 8994ff1b4..ada44ead3 100644
--- a/src/libstrongswan/plugins/openssl/Makefile.in
+++ b/src/libstrongswan/plugins/openssl/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -80,7 +81,8 @@ am_libstrongswan_openssl_la_OBJECTS = openssl_plugin.lo \
openssl_sha1_prf.lo openssl_diffie_hellman.lo \
openssl_rsa_private_key.lo openssl_rsa_public_key.lo \
openssl_ec_diffie_hellman.lo openssl_ec_private_key.lo \
- openssl_ec_public_key.lo openssl_x509.lo openssl_crl.lo
+ openssl_ec_public_key.lo openssl_x509.lo openssl_crl.lo \
+ openssl_rng.lo openssl_hmac.lo
libstrongswan_openssl_la_OBJECTS = \
$(am_libstrongswan_openssl_la_OBJECTS)
libstrongswan_openssl_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@@ -89,7 +91,7 @@ libstrongswan_openssl_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@MONOLITHIC_FALSE@am_libstrongswan_openssl_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_openssl_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -115,6 +117,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -209,11 +212,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -230,11 +236,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -250,6 +257,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -259,7 +267,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -304,7 +311,9 @@ libstrongswan_openssl_la_SOURCES = \
openssl_ec_private_key.c openssl_ec_private_key.h \
openssl_ec_public_key.c openssl_ec_public_key.h \
openssl_x509.c openssl_x509.h \
- openssl_crl.c openssl_crl.h
+ openssl_crl.c openssl_crl.h \
+ openssl_rng.c openssl_rng.h \
+ openssl_hmac.c openssl_hmac.h
libstrongswan_openssl_la_LDFLAGS = -module -avoid-version
libstrongswan_openssl_la_LIBADD = -lcrypto
@@ -398,7 +407,9 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_ec_private_key.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_ec_public_key.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_hasher.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_hmac.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_rng.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_rsa_private_key.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_rsa_public_key.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_sha1_prf.Plo@am__quote@
diff --git a/src/libstrongswan/plugins/openssl/openssl_crl.c b/src/libstrongswan/plugins/openssl/openssl_crl.c
index 9a9efb2b6..e529ff8a5 100644
--- a/src/libstrongswan/plugins/openssl/openssl_crl.c
+++ b/src/libstrongswan/plugins/openssl/openssl_crl.c
@@ -225,7 +225,8 @@ METHOD(certificate_t, has_subject_or_issuer, id_match_t,
}
METHOD(certificate_t, issued_by, bool,
- private_openssl_crl_t *this, certificate_t *issuer)
+ private_openssl_crl_t *this, certificate_t *issuer,
+ signature_scheme_t *scheme)
{
chunk_t fingerprint, tbs;
public_key_t *key;
@@ -270,6 +271,10 @@ METHOD(certificate_t, issued_by, bool,
openssl_asn1_str2chunk(this->crl->signature));
free(tbs.ptr);
key->destroy(key);
+ if (valid && scheme)
+ {
+ *scheme = this->scheme;
+ }
return valid;
}
diff --git a/src/libstrongswan/plugins/openssl/openssl_crypter.c b/src/libstrongswan/plugins/openssl/openssl_crypter.c
index cd9a3bd4a..07b96b320 100644
--- a/src/libstrongswan/plugins/openssl/openssl_crypter.c
+++ b/src/libstrongswan/plugins/openssl/openssl_crypter.c
@@ -90,7 +90,7 @@ static char* lookup_algorithm(u_int16_t ikev2_algo, size_t *key_size)
/**
* Do the actual en/decryption in an EVP context
*/
-static void crypt(private_openssl_crypter_t *this, chunk_t data, chunk_t iv,
+static bool crypt(private_openssl_crypter_t *this, chunk_t data, chunk_t iv,
chunk_t *dst, int enc)
{
int len;
@@ -104,25 +104,26 @@ static void crypt(private_openssl_crypter_t *this, chunk_t data, chunk_t iv,
}
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
- EVP_CipherInit_ex(&ctx, this->cipher, NULL, NULL, NULL, enc);
- EVP_CIPHER_CTX_set_padding(&ctx, 0); /* disable padding */
- EVP_CIPHER_CTX_set_key_length(&ctx, this->key.len);
- EVP_CipherInit_ex(&ctx, NULL, NULL, this->key.ptr, iv.ptr, enc);
- EVP_CipherUpdate(&ctx, out, &len, data.ptr, data.len);
- EVP_CipherFinal_ex(&ctx, out + len, &len); /* since padding is disabled this does nothing */
- EVP_CIPHER_CTX_cleanup(&ctx);
+ return EVP_CipherInit_ex(&ctx, this->cipher, NULL, NULL, NULL, enc) &&
+ EVP_CIPHER_CTX_set_padding(&ctx, 0) /* disable padding */ &&
+ EVP_CIPHER_CTX_set_key_length(&ctx, this->key.len) &&
+ EVP_CipherInit_ex(&ctx, NULL, NULL, this->key.ptr, iv.ptr, enc) &&
+ EVP_CipherUpdate(&ctx, out, &len, data.ptr, data.len) &&
+ /* since padding is disabled this does nothing */
+ EVP_CipherFinal_ex(&ctx, out + len, &len) &&
+ EVP_CIPHER_CTX_cleanup(&ctx);
}
-METHOD(crypter_t, decrypt, void,
+METHOD(crypter_t, decrypt, bool,
private_openssl_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
{
- crypt(this, data, iv, dst, 0);
+ return crypt(this, data, iv, dst, 0);
}
-METHOD(crypter_t, encrypt, void,
+METHOD(crypter_t, encrypt, bool,
private_openssl_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
{
- crypt(this, data, iv, dst, 1);
+ return crypt(this, data, iv, dst, 1);
}
METHOD(crypter_t, get_block_size, size_t,
@@ -143,10 +144,11 @@ METHOD(crypter_t, get_key_size, size_t,
return this->key.len;
}
-METHOD(crypter_t, set_key, void,
+METHOD(crypter_t, set_key, bool,
private_openssl_crypter_t *this, chunk_t key)
{
memcpy(this->key.ptr, key.ptr, min(key.len, this->key.len));
+ return TRUE;
}
METHOD(crypter_t, destroy, void,
diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c
index 7461695ad..9cb68a3ab 100644
--- a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c
+++ b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c
@@ -221,13 +221,13 @@ bool openssl_ec_fingerprint(EC_KEY *ec, cred_encoding_type_t type, chunk_t *fp)
return FALSE;
}
hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
- if (!hasher)
+ if (!hasher || !hasher->allocate_hash(hasher, key, fp))
{
DBG1(DBG_LIB, "SHA1 hash algorithm not supported, fingerprinting failed");
+ DESTROY_IF(hasher);
free(key.ptr);
return FALSE;
}
- hasher->allocate_hash(hasher, key, fp);
hasher->destroy(hasher);
free(key.ptr);
lib->encoding->cache(lib->encoding, type, ec, *fp);
diff --git a/src/libstrongswan/plugins/openssl/openssl_hasher.c b/src/libstrongswan/plugins/openssl/openssl_hasher.c
index d81f4b21e..50b14698b 100644
--- a/src/libstrongswan/plugins/openssl/openssl_hasher.c
+++ b/src/libstrongswan/plugins/openssl/openssl_hasher.c
@@ -40,91 +40,45 @@ struct private_openssl_hasher_t {
EVP_MD_CTX *ctx;
};
-/**
- * Mapping from the algorithms defined in IKEv2 to
- * OpenSSL algorithm names
- */
-typedef struct {
- /**
- * Identifier specified in IKEv2
- */
- int ikev2_id;
-
- /**
- * Name of the algorithm, as used in OpenSSL
- */
- char *name;
-} openssl_algorithm_t;
-
-#define END_OF_LIST -1
-
-/**
- * Algorithms for integrity
- */
-static openssl_algorithm_t integrity_algs[] = {
- {HASH_MD2, "md2"},
- {HASH_MD5, "md5"},
- {HASH_SHA1, "sha1"},
- {HASH_SHA224, "sha224"},
- {HASH_SHA256, "sha256"},
- {HASH_SHA384, "sha384"},
- {HASH_SHA512, "sha512"},
- {HASH_MD4, "md4"},
- {END_OF_LIST, NULL},
-};
-
-/**
- * Look up an OpenSSL algorithm name
- */
-static char* lookup_algorithm(openssl_algorithm_t *openssl_algo,
- u_int16_t ikev2_algo)
-{
- while (openssl_algo->ikev2_id != END_OF_LIST)
- {
- if (ikev2_algo == openssl_algo->ikev2_id)
- {
- return openssl_algo->name;
- }
- openssl_algo++;
- }
- return NULL;
-}
-
METHOD(hasher_t, get_hash_size, size_t,
private_openssl_hasher_t *this)
{
return this->hasher->md_size;
}
-METHOD(hasher_t, reset, void,
+METHOD(hasher_t, reset, bool,
private_openssl_hasher_t *this)
{
- EVP_DigestInit_ex(this->ctx, this->hasher, NULL);
+ return EVP_DigestInit_ex(this->ctx, this->hasher, NULL) == 1;
}
-METHOD(hasher_t, get_hash, void,
+METHOD(hasher_t, get_hash, bool,
private_openssl_hasher_t *this, chunk_t chunk, u_int8_t *hash)
{
- EVP_DigestUpdate(this->ctx, chunk.ptr, chunk.len);
+ if (EVP_DigestUpdate(this->ctx, chunk.ptr, chunk.len) != 1)
+ {
+ return FALSE;
+ }
if (hash)
{
- EVP_DigestFinal_ex(this->ctx, hash, NULL);
- reset(this);
+ if (EVP_DigestFinal_ex(this->ctx, hash, NULL) != 1)
+ {
+ return FALSE;
+ }
+ return reset(this);
}
+ return TRUE;
}
-METHOD(hasher_t, allocate_hash, void,
+METHOD(hasher_t, allocate_hash, bool,
private_openssl_hasher_t *this, chunk_t chunk, chunk_t *hash)
{
if (hash)
{
*hash = chunk_alloc(get_hash_size(this));
- get_hash(this, chunk, hash->ptr);
- }
- else
- {
- get_hash(this, chunk, NULL);
+ return get_hash(this, chunk, hash->ptr);
}
+ return get_hash(this, chunk, NULL);
}
METHOD(hasher_t, destroy, void,
@@ -140,11 +94,11 @@ METHOD(hasher_t, destroy, void,
openssl_hasher_t *openssl_hasher_create(hash_algorithm_t algo)
{
private_openssl_hasher_t *this;
+ char* name;
- char* name = lookup_algorithm(integrity_algs, algo);
+ name = enum_to_name(hash_algorithm_short_names, algo);
if (!name)
{
- /* algo unavailable */
return NULL;
}
@@ -171,7 +125,11 @@ openssl_hasher_t *openssl_hasher_create(hash_algorithm_t algo)
this->ctx = EVP_MD_CTX_create();
/* initialization */
- reset(this);
+ if (!reset(this))
+ {
+ destroy(this);
+ return NULL;
+ }
return &this->public;
}
diff --git a/src/libstrongswan/plugins/openssl/openssl_hmac.c b/src/libstrongswan/plugins/openssl/openssl_hmac.c
new file mode 100644
index 000000000..5d05425d3
--- /dev/null
+++ b/src/libstrongswan/plugins/openssl/openssl_hmac.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+/*
+ * Copyright (C) 2012 Aleksandr Grinberg
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+
+#include "openssl_hmac.h"
+
+#include <crypto/mac.h>
+#include <crypto/prfs/mac_prf.h>
+#include <crypto/signers/mac_signer.h>
+
+typedef struct private_mac_t private_mac_t;
+
+/**
+ * Private data of a mac_t object.
+ */
+struct private_mac_t {
+
+ /**
+ * Public interface
+ */
+ mac_t public;
+
+ /**
+ * Hasher to use
+ */
+ const EVP_MD *hasher;
+
+ /**
+ * Current HMAC context
+ */
+ HMAC_CTX hmac;
+};
+
+METHOD(mac_t, set_key, bool,
+ private_mac_t *this, chunk_t key)
+{
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+ return HMAC_Init_ex(&this->hmac, key.ptr, key.len, this->hasher, NULL);
+#else /* OPENSSL_VERSION_NUMBER < 1.0 */
+ HMAC_Init_ex(&this->hmac, key.ptr, key.len, this->hasher, NULL);
+ return TRUE;
+#endif
+}
+
+METHOD(mac_t, get_mac, bool,
+ private_mac_t *this, chunk_t data, u_int8_t *out)
+{
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+ if (!HMAC_Update(&this->hmac, data.ptr, data.len))
+ {
+ return FALSE;
+ }
+ if (out == NULL)
+ {
+ return TRUE;
+ }
+ if (!HMAC_Final(&this->hmac, out, NULL))
+ {
+ return FALSE;
+ }
+#else /* OPENSSL_VERSION_NUMBER < 1.0 */
+ HMAC_Update(&this->hmac, data.ptr, data.len);
+ if (out == NULL)
+ {
+ return TRUE;
+ }
+ HMAC_Final(&this->hmac, out, NULL);
+#endif
+ return set_key(this, chunk_empty);
+}
+
+METHOD(mac_t, get_mac_size, size_t,
+ private_mac_t *this)
+{
+ return EVP_MD_size(this->hasher);
+}
+
+METHOD(mac_t, destroy, void,
+ private_mac_t *this)
+{
+ HMAC_CTX_cleanup(&this->hmac);
+ free(this);
+}
+
+/*
+ * Create an OpenSSL-backed implementation of the mac_t interface
+ */
+static mac_t *hmac_create(hash_algorithm_t algo)
+{
+ private_mac_t *this;
+ char *name;
+
+ name = enum_to_name(hash_algorithm_short_names, algo);
+ if (!name)
+ {
+ return NULL;
+ }
+
+ INIT(this,
+ .public = {
+ .get_mac = _get_mac,
+ .get_mac_size = _get_mac_size,
+ .set_key = _set_key,
+ .destroy = _destroy,
+ },
+ .hasher = EVP_get_digestbyname(name),
+ );
+
+ if (!this->hasher)
+ {
+ free(this);
+ return NULL;
+ }
+
+ HMAC_CTX_init(&this->hmac);
+ if (!set_key(this, chunk_empty))
+ {
+ destroy(this);
+ return NULL;
+ }
+
+ return &this->public;
+}
+
+/*
+ * Described in header
+ */
+prf_t *openssl_hmac_prf_create(pseudo_random_function_t algo)
+{
+ mac_t *hmac;
+
+ hmac = hmac_create(hasher_algorithm_from_prf(algo));
+ if (hmac)
+ {
+ return mac_prf_create(hmac);
+ }
+ return NULL;
+}
+
+/*
+ * Described in header
+ */
+signer_t *openssl_hmac_signer_create(integrity_algorithm_t algo)
+{
+ mac_t *hmac;
+ size_t trunc;
+
+ hmac = hmac_create(hasher_algorithm_from_integrity(algo, &trunc));
+ if (hmac)
+ {
+ return mac_signer_create(hmac, trunc);
+ }
+ return NULL;
+}
+
diff --git a/src/libstrongswan/plugins/cmac/cmac_prf.h b/src/libstrongswan/plugins/openssl/openssl_hmac.h
index a53cc5947..95ab6bfc3 100644
--- a/src/libstrongswan/plugins/cmac/cmac_prf.h
+++ b/src/libstrongswan/plugins/openssl/openssl_hmac.h
@@ -14,37 +14,32 @@
*/
/**
- * @defgroup cmac_prf cmac_prf
- * @{ @ingroup cmac_p
+ * Implements HMAC based PRF and signer using OpenSSL's HMAC functions.
+ *
+ * @defgroup openssl_hmac openssl_hmac
+ * @{ @ingroup openssl_p
*/
-#ifndef PRF_CMAC_H_
-#define PRF_CMAC_H_
-
-typedef struct cmac_prf_t cmac_prf_t;
+#ifndef OPENSSL_HMAC_H_
+#define OPENSSL_HMAC_H_
#include <crypto/prfs/prf.h>
+#include <crypto/signers/signer.h>
/**
- * Implementation of prf_t on CBC block cipher using CMAC, RFC 4493 / RFC 4615.
+ * Creates a new prf_t object based on an HMAC.
*
- * This simply wraps a cmac_t in a prf_t. More a question of
- * interface matching.
+ * @param algo algorithm to implement
+ * @return prf_t object, NULL if not supported
*/
-struct cmac_prf_t {
-
- /**
- * Implements prf_t interface.
- */
- prf_t prf;
-};
+prf_t *openssl_hmac_prf_create(pseudo_random_function_t algo);
/**
- * Creates a new cmac_prf_t object.
+ * Creates a new signer_t object based on an HMAC.
*
* @param algo algorithm to implement
- * @return cmac_prf_t object, NULL if hash not supported
+ * @return signer_t, NULL if not supported
*/
-cmac_prf_t *cmac_prf_create(pseudo_random_function_t algo);
+signer_t *openssl_hmac_signer_create(integrity_algorithm_t algo);
-#endif /** PRF_CMAC_H_ @}*/
+#endif /** OPENSSL_HMAC_H_ @}*/
diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c
index c93ceacc9..b69de981e 100644
--- a/src/libstrongswan/plugins/openssl/openssl_plugin.c
+++ b/src/libstrongswan/plugins/openssl/openssl_plugin.c
@@ -40,6 +40,8 @@
#include "openssl_ec_public_key.h"
#include "openssl_x509.h"
#include "openssl_crl.h"
+#include "openssl_rng.h"
+#include "openssl_hmac.h"
typedef struct private_openssl_plugin_t private_openssl_plugin_t;
@@ -127,7 +129,9 @@ static void destroy_function(struct CRYPTO_dynlock_value *lock,
*/
static unsigned long id_function(void)
{
- return (unsigned long)thread_current_id();
+ /* ensure the thread ID is never zero, otherwise OpenSSL might try to
+ * acquire locks recursively */
+ return 1 + (unsigned long)thread_current_id();
}
/**
@@ -170,7 +174,11 @@ static bool seed_rng()
return FALSE;
}
}
- rng->get_bytes(rng, sizeof(buf), buf);
+ if (!rng->get_bytes(rng, sizeof(buf), buf))
+ {
+ rng->destroy(rng);
+ return FALSE;
+ }
RAND_seed(buf, sizeof(buf));
}
DESTROY_IF(rng);
@@ -260,6 +268,41 @@ METHOD(plugin_t, get_features, int,
PLUGIN_REGISTER(PRF, openssl_sha1_prf_create),
PLUGIN_PROVIDE(PRF, PRF_KEYED_SHA1),
#endif
+#ifndef OPENSSL_NO_HMAC
+ PLUGIN_REGISTER(PRF, openssl_hmac_prf_create),
+#ifndef OPENSSL_NO_MD5
+ PLUGIN_PROVIDE(PRF, PRF_HMAC_MD5),
+#endif
+#ifndef OPENSSL_NO_SHA1
+ PLUGIN_PROVIDE(PRF, PRF_HMAC_SHA1),
+#endif
+#ifndef OPENSSL_NO_SHA256
+ PLUGIN_PROVIDE(PRF, PRF_HMAC_SHA2_256),
+#endif
+#ifndef OPENSSL_NO_SHA512
+ PLUGIN_PROVIDE(PRF, PRF_HMAC_SHA2_384),
+ PLUGIN_PROVIDE(PRF, PRF_HMAC_SHA2_512),
+#endif
+ PLUGIN_REGISTER(SIGNER, openssl_hmac_signer_create),
+#ifndef OPENSSL_NO_MD5
+ PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_MD5_96),
+ PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_MD5_128),
+#endif
+#ifndef OPENSSL_NO_SHA1
+ PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA1_96),
+ PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA1_128),
+ PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA1_160),
+#endif
+#ifndef OPENSSL_NO_SHA256
+ PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_256_128),
+ PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_256_256),
+#endif
+#ifndef OPENSSL_NO_SHA512
+ PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_384_192),
+ PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_384_384),
+ PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_512_256),
+#endif
+#endif /* OPENSSL_NO_HMAC */
#ifndef OPENSSL_NO_DH
/* MODP DH groups */
PLUGIN_REGISTER(DH, openssl_diffie_hellman_create),
@@ -284,7 +327,7 @@ METHOD(plugin_t, get_features, int,
PLUGIN_PROVIDE(PRIVKEY, KEY_ANY),
PLUGIN_REGISTER(PRIVKEY_GEN, openssl_rsa_private_key_gen, FALSE),
PLUGIN_PROVIDE(PRIVKEY_GEN, KEY_RSA),
- PLUGIN_REGISTER(PUBKEY, openssl_rsa_public_key_load, FALSE),
+ PLUGIN_REGISTER(PUBKEY, openssl_rsa_public_key_load, TRUE),
PLUGIN_PROVIDE(PUBKEY, KEY_RSA),
PLUGIN_REGISTER(PUBKEY, openssl_rsa_public_key_load, TRUE),
PLUGIN_PROVIDE(PUBKEY, KEY_ANY),
@@ -317,6 +360,9 @@ METHOD(plugin_t, get_features, int,
/* certificate/CRL loading */
PLUGIN_REGISTER(CERT_DECODE, openssl_x509_load, TRUE),
PLUGIN_PROVIDE(CERT_DECODE, CERT_X509),
+ PLUGIN_SDEPEND(PUBKEY, KEY_RSA),
+ PLUGIN_SDEPEND(PUBKEY, KEY_ECDSA),
+ PLUGIN_SDEPEND(PUBKEY, KEY_DSA),
PLUGIN_REGISTER(CERT_DECODE, openssl_crl_load, TRUE),
PLUGIN_PROVIDE(CERT_DECODE, CERT_X509_CRL),
#ifndef OPENSSL_NO_ECDH
@@ -360,6 +406,9 @@ METHOD(plugin_t, get_features, int,
PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_ECDSA_521),
#endif
#endif /* OPENSSL_NO_ECDSA */
+ PLUGIN_REGISTER(RNG, openssl_rng_create),
+ PLUGIN_PROVIDE(RNG, RNG_STRONG),
+ PLUGIN_PROVIDE(RNG, RNG_WEAK),
};
*features = f;
return countof(f);
diff --git a/src/libstrongswan/plugins/openssl/openssl_rng.c b/src/libstrongswan/plugins/openssl/openssl_rng.c
new file mode 100644
index 000000000..c83244f60
--- /dev/null
+++ b/src/libstrongswan/plugins/openssl/openssl_rng.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2012 Aleksandr Grinberg
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <debug.h>
+#include <openssl/rand.h>
+#include <openssl/err.h>
+
+#include "openssl_rng.h"
+
+typedef struct private_openssl_rng_t private_openssl_rng_t;
+
+/**
+ * Private data of openssl_rng_t
+ */
+struct private_openssl_rng_t {
+
+ /**
+ * Public part of this class.
+ */
+ openssl_rng_t public;
+
+ /**
+ * Quality of randomness
+ */
+ rng_quality_t quality;
+};
+
+METHOD(rng_t, get_bytes, bool,
+ private_openssl_rng_t *this, size_t bytes, u_int8_t *buffer)
+{
+ u_int32_t ret;
+
+ if (this->quality == RNG_STRONG)
+ {
+ ret = RAND_bytes((char*)buffer, bytes);
+ }
+ else
+ {
+ ret = RAND_pseudo_bytes((char*)buffer, bytes);
+ }
+ return ret != 0;
+}
+
+METHOD(rng_t, allocate_bytes, bool,
+ private_openssl_rng_t *this, size_t bytes, chunk_t *chunk)
+{
+ *chunk = chunk_alloc(bytes);
+ if (!get_bytes(this, chunk->len, chunk->ptr))
+ {
+ chunk_free(chunk);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+METHOD(rng_t, destroy, void,
+ private_openssl_rng_t *this)
+{
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+openssl_rng_t *openssl_rng_create(rng_quality_t quality)
+{
+ private_openssl_rng_t *this;
+
+ INIT(this,
+ .public = {
+ .rng = {
+ .get_bytes = _get_bytes,
+ .allocate_bytes = _allocate_bytes,
+ .destroy = _destroy,
+ },
+ },
+ .quality = quality,
+ );
+
+ return &this->public;
+}
diff --git a/src/libstrongswan/plugins/openssl/openssl_rng.h b/src/libstrongswan/plugins/openssl/openssl_rng.h
new file mode 100644
index 000000000..a4596563a
--- /dev/null
+++ b/src/libstrongswan/plugins/openssl/openssl_rng.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2012 Aleksandr Grinberg
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/**
+ * @defgroup openssl_rng openssl_rng
+ * @{ @ingroup openssl_p
+ */
+
+#ifndef OPENSSL_RNG_H_
+#define OPENSSL_RNG_H_
+
+#include <library.h>
+
+typedef struct openssl_rng_t openssl_rng_t;
+
+/**
+ * Implementation of random number using OpenSSL.
+ */
+struct openssl_rng_t {
+
+ /**
+ * Implements rng_t interface.
+ */
+ rng_t rng;
+};
+
+/**
+ * Constructor to create openssl_rng_t.
+ *
+ * @param quality quality of randomness
+ * @return openssl_rng_t
+ */
+openssl_rng_t *openssl_rng_create(rng_quality_t quality);
+
+#endif /** OPENSSL_RNG_H_ @}*/
diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c
index d1afd94cc..98cd700bf 100644
--- a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c
+++ b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c
@@ -475,7 +475,8 @@ static bool login(ENGINE *engine, chunk_t keyid)
{
found = TRUE;
key = shared->get_key(shared);
- if (snprintf(pin, sizeof(pin), "%.*s", key.len, key.ptr) >= sizeof(pin))
+ if (snprintf(pin, sizeof(pin),
+ "%.*s", (int)key.len, key.ptr) >= sizeof(pin))
{
continue;
}
diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c
index a24bae5d6..5872a8159 100644
--- a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c
+++ b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c
@@ -217,13 +217,13 @@ bool openssl_rsa_fingerprint(RSA *rsa, cred_encoding_type_t type, chunk_t *fp)
return FALSE;
}
hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
- if (!hasher)
+ if (!hasher || !hasher->allocate_hash(hasher, key, fp))
{
DBG1(DBG_LIB, "SHA1 hash algorithm not supported, fingerprinting failed");
+ DESTROY_IF(hasher);
free(key.ptr);
return FALSE;
}
- hasher->allocate_hash(hasher, key, fp);
free(key.ptr);
hasher->destroy(hasher);
lib->encoding->cache(lib->encoding, type, rsa, *fp);
diff --git a/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c b/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c
index 20f2fa984..8501e2cd4 100644
--- a/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c
+++ b/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c
@@ -35,7 +35,7 @@ struct private_openssl_sha1_prf_t {
SHA_CTX ctx;
};
-METHOD(prf_t, get_bytes, void,
+METHOD(prf_t, get_bytes, bool,
private_openssl_sha1_prf_t *this, chunk_t seed, u_int8_t *bytes)
{
SHA1_Update(&this->ctx, seed.ptr, seed.len);
@@ -50,6 +50,8 @@ METHOD(prf_t, get_bytes, void,
hash[3] = htonl(this->ctx.h3);
hash[4] = htonl(this->ctx.h4);
}
+
+ return TRUE;
}
METHOD(prf_t, get_block_size, size_t,
@@ -58,18 +60,15 @@ METHOD(prf_t, get_block_size, size_t,
return HASH_SIZE_SHA1;
}
-METHOD(prf_t, allocate_bytes, void,
+METHOD(prf_t, allocate_bytes, bool,
private_openssl_sha1_prf_t *this, chunk_t seed, chunk_t *chunk)
{
if (chunk)
{
*chunk = chunk_alloc(HASH_SIZE_SHA1);
- get_bytes(this, seed, chunk->ptr);
- }
- else
- {
- get_bytes(this, seed, NULL);
+ return get_bytes(this, seed, chunk->ptr);
}
+ return get_bytes(this, seed, NULL);
}
METHOD(prf_t, get_key_size, size_t,
@@ -78,11 +77,15 @@ METHOD(prf_t, get_key_size, size_t,
return HASH_SIZE_SHA1;
}
-METHOD(prf_t, set_key, void,
+METHOD(prf_t, set_key, bool,
private_openssl_sha1_prf_t *this, chunk_t key)
{
SHA1_Init(&this->ctx);
+ if (key.len % 4)
+ {
+ return FALSE;
+ }
if (key.len >= 4)
{
this->ctx.h0 ^= untoh32(key.ptr);
@@ -103,6 +106,7 @@ METHOD(prf_t, set_key, void,
{
this->ctx.h4 ^= untoh32(key.ptr + 16);
}
+ return TRUE;
}
METHOD(prf_t, destroy, void,
diff --git a/src/libstrongswan/plugins/openssl/openssl_x509.c b/src/libstrongswan/plugins/openssl/openssl_x509.c
index 5caf5182c..e85c5cc90 100644
--- a/src/libstrongswan/plugins/openssl/openssl_x509.c
+++ b/src/libstrongswan/plugins/openssl/openssl_x509.c
@@ -350,7 +350,8 @@ METHOD(certificate_t, has_issuer, id_match_t,
}
METHOD(certificate_t, issued_by, bool,
- private_openssl_x509_t *this, certificate_t *issuer)
+ private_openssl_x509_t *this, certificate_t *issuer,
+ signature_scheme_t *scheme)
{
public_key_t *key;
bool valid;
@@ -393,6 +394,10 @@ METHOD(certificate_t, issued_by, bool,
openssl_asn1_str2chunk(this->x509->signature));
free(tbs.ptr);
key->destroy(key);
+ if (valid && scheme)
+ {
+ *scheme = this->scheme;
+ }
return valid;
}
@@ -968,14 +973,14 @@ static bool parse_certificate(private_openssl_x509_t *this)
parse_extKeyUsage(this);
hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
- if (!hasher)
+ if (!hasher || !hasher->allocate_hash(hasher, this->encoding, &this->hash))
{
+ DESTROY_IF(hasher);
return FALSE;
}
- hasher->allocate_hash(hasher, this->encoding, &this->hash);
hasher->destroy(hasher);
- if (issued_by(this, &this->public.x509.interface))
+ if (issued_by(this, &this->public.x509.interface, NULL))
{
this->flags |= X509_SELF_SIGNED;
}
diff --git a/src/libstrongswan/plugins/padlock/Makefile.in b/src/libstrongswan/plugins/padlock/Makefile.in
index 6ff607456..5a559eadf 100644
--- a/src/libstrongswan/plugins/padlock/Makefile.in
+++ b/src/libstrongswan/plugins/padlock/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -85,7 +86,7 @@ libstrongswan_padlock_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@MONOLITHIC_FALSE@am_libstrongswan_padlock_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_padlock_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -111,6 +112,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -205,11 +207,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -226,11 +231,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -246,6 +252,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -255,7 +262,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/padlock/padlock_aes_crypter.c b/src/libstrongswan/plugins/padlock/padlock_aes_crypter.c
index 119de86aa..b5060de0a 100644
--- a/src/libstrongswan/plugins/padlock/padlock_aes_crypter.c
+++ b/src/libstrongswan/plugins/padlock/padlock_aes_crypter.c
@@ -109,16 +109,18 @@ static void crypt(private_padlock_aes_crypter_t *this, char *iv,
memwipe(key_aligned, sizeof(key_aligned));
}
-METHOD(crypter_t, decrypt, void,
+METHOD(crypter_t, decrypt, bool,
private_padlock_aes_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
{
crypt(this, iv.ptr, data, dst, TRUE);
+ return TRUE;
}
-METHOD(crypter_t, encrypt, void,
+METHOD(crypter_t, encrypt, bool,
private_padlock_aes_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
{
crypt(this, iv.ptr, data, dst, FALSE);
+ return TRUE;
}
METHOD(crypter_t, get_block_size, size_t,
@@ -139,10 +141,11 @@ METHOD(crypter_t, get_key_size, size_t,
return this->key.len;
}
-METHOD(crypter_t, set_key, void,
+METHOD(crypter_t, set_key, bool,
private_padlock_aes_crypter_t *this, chunk_t key)
{
memcpy(this->key.ptr, key.ptr, min(key.len, this->key.len));
+ return TRUE;
}
METHOD(crypter_t, destroy, void,
diff --git a/src/libstrongswan/plugins/padlock/padlock_rng.c b/src/libstrongswan/plugins/padlock/padlock_rng.c
index 3d805df9d..517914ab5 100644
--- a/src/libstrongswan/plugins/padlock/padlock_rng.c
+++ b/src/libstrongswan/plugins/padlock/padlock_rng.c
@@ -69,7 +69,7 @@ static void rng(char *buf, int len, int quality)
}
}
-METHOD(rng_t, allocate_bytes, void,
+METHOD(rng_t, allocate_bytes, bool,
private_padlock_rng_t *this, size_t bytes, chunk_t *chunk)
{
chunk->len = bytes;
@@ -77,9 +77,10 @@ METHOD(rng_t, allocate_bytes, void,
chunk->ptr = malloc(bytes + 7);
rng(chunk->ptr, chunk->len, this->quality);
+ return TRUE;
}
-METHOD(rng_t, get_bytes, void,
+METHOD(rng_t, get_bytes, bool,
private_padlock_rng_t *this, size_t bytes, u_int8_t *buffer)
{
chunk_t chunk;
@@ -88,6 +89,7 @@ METHOD(rng_t, get_bytes, void,
allocate_bytes(this, bytes, &chunk);
memcpy(buffer, chunk.ptr, bytes);
chunk_clear(&chunk);
+ return TRUE;
}
METHOD(rng_t, destroy, void,
diff --git a/src/libstrongswan/plugins/padlock/padlock_sha1_hasher.c b/src/libstrongswan/plugins/padlock/padlock_sha1_hasher.c
index 66a077353..4489b902a 100644
--- a/src/libstrongswan/plugins/padlock/padlock_sha1_hasher.c
+++ b/src/libstrongswan/plugins/padlock/padlock_sha1_hasher.c
@@ -83,13 +83,14 @@ static void append_data(private_padlock_sha1_hasher_t *this, chunk_t data)
this->data.len += data.len;
}
-METHOD(hasher_t, reset, void,
+METHOD(hasher_t, reset, bool,
private_padlock_sha1_hasher_t *this)
{
chunk_free(&this->data);
+ return TRUE;
}
-METHOD(hasher_t, get_hash, void,
+METHOD(hasher_t, get_hash, bool,
private_padlock_sha1_hasher_t *this, chunk_t chunk, u_int8_t *hash)
{
if (hash)
@@ -109,20 +110,18 @@ METHOD(hasher_t, get_hash, void,
{
append_data(this, chunk);
}
+ return TRUE;
}
-METHOD(hasher_t, allocate_hash, void,
+METHOD(hasher_t, allocate_hash, bool,
private_padlock_sha1_hasher_t *this, chunk_t chunk, chunk_t *hash)
{
if (hash)
{
*hash = chunk_alloc(HASH_SIZE_SHA1);
- get_hash(this, chunk, hash->ptr);
- }
- else
- {
- get_hash(this, chunk, NULL);
+ return get_hash(this, chunk, hash->ptr);
}
+ return get_hash(this, chunk, NULL);
}
METHOD(hasher_t, get_hash_size, size_t,
diff --git a/src/libstrongswan/plugins/pem/Makefile.in b/src/libstrongswan/plugins/pem/Makefile.in
index 98c196ef4..7988d1e74 100644
--- a/src/libstrongswan/plugins/pem/Makefile.in
+++ b/src/libstrongswan/plugins/pem/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -83,7 +84,7 @@ libstrongswan_pem_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(libstrongswan_pem_la_LDFLAGS) $(LDFLAGS) -o $@
@MONOLITHIC_FALSE@am_libstrongswan_pem_la_rpath = -rpath $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_pem_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -109,6 +110,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -203,11 +205,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -224,11 +229,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -244,6 +250,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -253,7 +260,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/pem/pem_builder.c b/src/libstrongswan/plugins/pem/pem_builder.c
index c5d96be47..9b9777031 100644
--- a/src/libstrongswan/plugins/pem/pem_builder.c
+++ b/src/libstrongswan/plugins/pem/pem_builder.c
@@ -104,15 +104,21 @@ static status_t pem_decrypt(chunk_t *blob, encryption_algorithm_t alg,
}
hash.len = hasher->get_hash_size(hasher);
hash.ptr = alloca(hash.len);
- hasher->get_hash(hasher, passphrase, NULL);
- hasher->get_hash(hasher, salt, hash.ptr);
+ if (!hasher->get_hash(hasher, passphrase, NULL) ||
+ !hasher->get_hash(hasher, salt, hash.ptr))
+ {
+ return FAILED;
+ }
memcpy(key.ptr, hash.ptr, hash.len);
if (key.len > hash.len)
{
- hasher->get_hash(hasher, hash, NULL);
- hasher->get_hash(hasher, passphrase, NULL);
- hasher->get_hash(hasher, salt, hash.ptr);
+ if (!hasher->get_hash(hasher, hash, NULL) ||
+ !hasher->get_hash(hasher, passphrase, NULL) ||
+ !hasher->get_hash(hasher, salt, hash.ptr))
+ {
+ return FAILED;
+ }
memcpy(key.ptr + hash.len, hash.ptr, key.len - hash.len);
}
hasher->destroy(hasher);
@@ -125,7 +131,6 @@ static status_t pem_decrypt(chunk_t *blob, encryption_algorithm_t alg,
encryption_algorithm_names, alg);
return NOT_SUPPORTED;
}
- crypter->set_key(crypter, key);
if (iv.len != crypter->get_iv_size(crypter) ||
blob->len % crypter->get_block_size(crypter))
@@ -134,7 +139,12 @@ static status_t pem_decrypt(chunk_t *blob, encryption_algorithm_t alg,
DBG1(DBG_ASN, " data size is not multiple of block size");
return PARSE_ERROR;
}
- crypter->decrypt(crypter, *blob, iv, &decrypted);
+ if (!crypter->set_key(crypter, key) ||
+ !crypter->decrypt(crypter, *blob, iv, &decrypted))
+ {
+ crypter->destroy(crypter);
+ return FAILED;
+ }
crypter->destroy(crypter);
memcpy(blob->ptr, decrypted.ptr, blob->len);
chunk_free(&decrypted);
@@ -275,7 +285,7 @@ static status_t pem_to_bin(chunk_t *blob, bool *pgp)
else
{
DBG1(DBG_ASN, " encryption algorithm '%.*s'"
- " not supported", dek.len, dek.ptr);
+ " not supported", (int)dek.len, dek.ptr);
return NOT_SUPPORTED;
}
eat_whitespace(&value);
diff --git a/src/libstrongswan/plugins/pem/pem_plugin.c b/src/libstrongswan/plugins/pem/pem_plugin.c
index fca717a10..d74ab9ee3 100644
--- a/src/libstrongswan/plugins/pem/pem_plugin.c
+++ b/src/libstrongswan/plugins/pem/pem_plugin.c
@@ -46,46 +46,64 @@ METHOD(plugin_t, get_features, int,
/* private key PEM decoding */
PLUGIN_REGISTER(PRIVKEY, pem_private_key_load, FALSE),
PLUGIN_PROVIDE(PRIVKEY, KEY_ANY),
- PLUGIN_DEPENDS(HASHER, HASH_MD5),
+ PLUGIN_DEPENDS(PRIVKEY, KEY_ANY),
+ PLUGIN_SDEPEND(HASHER, HASH_MD5),
PLUGIN_REGISTER(PRIVKEY, pem_private_key_load, FALSE),
PLUGIN_PROVIDE(PRIVKEY, KEY_RSA),
- PLUGIN_DEPENDS(HASHER, HASH_MD5),
+ PLUGIN_DEPENDS(PRIVKEY, KEY_RSA),
+ PLUGIN_SDEPEND(HASHER, HASH_MD5),
PLUGIN_REGISTER(PRIVKEY, pem_private_key_load, FALSE),
PLUGIN_PROVIDE(PRIVKEY, KEY_ECDSA),
- PLUGIN_DEPENDS(HASHER, HASH_MD5),
+ PLUGIN_DEPENDS(PRIVKEY, KEY_ECDSA),
+ PLUGIN_SDEPEND(HASHER, HASH_MD5),
PLUGIN_REGISTER(PRIVKEY, pem_private_key_load, FALSE),
PLUGIN_PROVIDE(PRIVKEY, KEY_DSA),
- PLUGIN_DEPENDS(HASHER, HASH_MD5),
+ PLUGIN_DEPENDS(PRIVKEY, KEY_DSA),
+ PLUGIN_SDEPEND(HASHER, HASH_MD5),
/* public key PEM decoding */
PLUGIN_REGISTER(PUBKEY, pem_public_key_load, FALSE),
PLUGIN_PROVIDE(PUBKEY, KEY_ANY),
+ PLUGIN_DEPENDS(PUBKEY, KEY_ANY),
PLUGIN_REGISTER(PUBKEY, pem_public_key_load, FALSE),
PLUGIN_PROVIDE(PUBKEY, KEY_RSA),
+ PLUGIN_DEPENDS(PUBKEY, KEY_RSA),
PLUGIN_REGISTER(PUBKEY, pem_public_key_load, FALSE),
PLUGIN_PROVIDE(PUBKEY, KEY_ECDSA),
+ PLUGIN_DEPENDS(PUBKEY, KEY_ECDSA),
PLUGIN_REGISTER(PUBKEY, pem_public_key_load, FALSE),
PLUGIN_PROVIDE(PUBKEY, KEY_DSA),
+ PLUGIN_DEPENDS(PUBKEY, KEY_DSA),
/* certificate PEM decoding */
PLUGIN_REGISTER(CERT_DECODE, pem_certificate_load, FALSE),
PLUGIN_PROVIDE(CERT_DECODE, CERT_ANY),
+ PLUGIN_SDEPEND(CERT_DECODE, CERT_X509),
+ PLUGIN_SDEPEND(CERT_DECODE, CERT_GPG),
PLUGIN_REGISTER(CERT_DECODE, pem_certificate_load, FALSE),
PLUGIN_PROVIDE(CERT_DECODE, CERT_X509),
+ PLUGIN_DEPENDS(CERT_DECODE, CERT_X509),
PLUGIN_REGISTER(CERT_DECODE, pem_certificate_load, FALSE),
PLUGIN_PROVIDE(CERT_DECODE, CERT_X509_CRL),
+ PLUGIN_DEPENDS(CERT_DECODE, CERT_X509_CRL),
PLUGIN_REGISTER(CERT_DECODE, pem_certificate_load, FALSE),
PLUGIN_PROVIDE(CERT_DECODE, CERT_X509_OCSP_REQUEST),
+ PLUGIN_DEPENDS(CERT_DECODE, CERT_X509_OCSP_REQUEST),
PLUGIN_REGISTER(CERT_DECODE, pem_certificate_load, FALSE),
PLUGIN_PROVIDE(CERT_DECODE, CERT_X509_OCSP_RESPONSE),
+ PLUGIN_DEPENDS(CERT_DECODE, CERT_X509_OCSP_RESPONSE),
PLUGIN_REGISTER(CERT_DECODE, pem_certificate_load, FALSE),
PLUGIN_PROVIDE(CERT_DECODE, CERT_X509_AC),
+ PLUGIN_DEPENDS(CERT_DECODE, CERT_X509_AC),
PLUGIN_REGISTER(CERT_DECODE, pem_certificate_load, FALSE),
PLUGIN_PROVIDE(CERT_DECODE, CERT_PKCS10_REQUEST),
+ PLUGIN_DEPENDS(CERT_DECODE, CERT_PKCS10_REQUEST),
PLUGIN_REGISTER(CERT_DECODE, pem_certificate_load, FALSE),
PLUGIN_PROVIDE(CERT_DECODE, CERT_TRUSTED_PUBKEY),
+ PLUGIN_DEPENDS(CERT_DECODE, CERT_TRUSTED_PUBKEY),
PLUGIN_REGISTER(CERT_DECODE, pem_certificate_load, FALSE),
PLUGIN_PROVIDE(CERT_DECODE, CERT_GPG),
+ PLUGIN_DEPENDS(CERT_DECODE, CERT_GPG),
/* pluto specific certificate formats */
PLUGIN_REGISTER(CERT_DECODE, pem_certificate_load, FALSE),
diff --git a/src/libstrongswan/plugins/pgp/Makefile.in b/src/libstrongswan/plugins/pgp/Makefile.in
index 946424eee..65acdc196 100644
--- a/src/libstrongswan/plugins/pgp/Makefile.in
+++ b/src/libstrongswan/plugins/pgp/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -83,7 +84,7 @@ libstrongswan_pgp_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(libstrongswan_pgp_la_LDFLAGS) $(LDFLAGS) -o $@
@MONOLITHIC_FALSE@am_libstrongswan_pgp_la_rpath = -rpath $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_pgp_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -109,6 +110,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -203,11 +205,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -224,11 +229,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -244,6 +250,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -253,7 +260,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/pgp/pgp_cert.c b/src/libstrongswan/plugins/pgp/pgp_cert.c
index 70a236855..a99bed2f6 100644
--- a/src/libstrongswan/plugins/pgp/pgp_cert.c
+++ b/src/libstrongswan/plugins/pgp/pgp_cert.c
@@ -114,7 +114,7 @@ METHOD(certificate_t, has_issuer, id_match_t,
}
METHOD(certificate_t, issued_by,bool,
- private_pgp_cert_t *this, certificate_t *issuer)
+ private_pgp_cert_t *this, certificate_t *issuer, signature_scheme_t *scheme)
{
/* TODO: check signature blobs for a valid signature */
return FALSE;
@@ -321,8 +321,12 @@ static bool parse_public_key(private_pgp_cert_t *this, chunk_t packet)
DBG1(DBG_ASN, "no SHA-1 hasher available");
return FALSE;
}
- hasher->allocate_hash(hasher, pubkey_packet_header, NULL);
- hasher->allocate_hash(hasher, pubkey_packet, &this->fingerprint);
+ if (!hasher->allocate_hash(hasher, pubkey_packet_header, NULL) ||
+ !hasher->allocate_hash(hasher, pubkey_packet, &this->fingerprint))
+ {
+ hasher->destroy(hasher);
+ return FALSE;
+ }
hasher->destroy(hasher);
DBG2(DBG_ASN, "L2 - v4 fingerprint %#B", &this->fingerprint);
}
diff --git a/src/libstrongswan/plugins/pgp/pgp_encoder.c b/src/libstrongswan/plugins/pgp/pgp_encoder.c
index 9043cdb9f..d16d1d71b 100644
--- a/src/libstrongswan/plugins/pgp/pgp_encoder.c
+++ b/src/libstrongswan/plugins/pgp/pgp_encoder.c
@@ -44,8 +44,12 @@ static bool build_v3_fingerprint(chunk_t *encoding, va_list args)
{
e = chunk_skip(e, 1);
}
- hasher->allocate_hash(hasher, n, NULL);
- hasher->allocate_hash(hasher, e, encoding);
+ if (!hasher->allocate_hash(hasher, n, NULL) ||
+ !hasher->allocate_hash(hasher, e, encoding))
+ {
+ hasher->destroy(hasher);
+ return FALSE;
+ }
hasher->destroy(hasher);
return TRUE;
}
diff --git a/src/libstrongswan/plugins/pkcs1/Makefile.in b/src/libstrongswan/plugins/pkcs1/Makefile.in
index f9322a62d..85246f3de 100644
--- a/src/libstrongswan/plugins/pkcs1/Makefile.in
+++ b/src/libstrongswan/plugins/pkcs1/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -84,7 +85,7 @@ libstrongswan_pkcs1_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@MONOLITHIC_FALSE@am_libstrongswan_pkcs1_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_pkcs1_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -110,6 +111,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -204,11 +206,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -225,11 +230,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -245,6 +251,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -254,7 +261,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/pkcs1/pkcs1_encoder.c b/src/libstrongswan/plugins/pkcs1/pkcs1_encoder.c
index 6957b2ad1..9122e8d8e 100644
--- a/src/libstrongswan/plugins/pkcs1/pkcs1_encoder.c
+++ b/src/libstrongswan/plugins/pkcs1/pkcs1_encoder.c
@@ -94,14 +94,14 @@ static bool hash_pubkey(chunk_t pubkey, chunk_t *hash)
hasher_t *hasher;
hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
- if (hasher == NULL)
+ if (!hasher || !hasher->allocate_hash(hasher, pubkey, hash))
{
+ DESTROY_IF(hasher);
chunk_free(&pubkey);
DBG1(DBG_LIB, "SHA1 hash algorithm not supported, "
"fingerprinting failed");
return FALSE;
}
- hasher->allocate_hash(hasher, pubkey, hash);
hasher->destroy(hasher);
chunk_free(&pubkey);
return TRUE;
diff --git a/src/libstrongswan/plugins/pkcs11/Makefile.in b/src/libstrongswan/plugins/pkcs11/Makefile.in
index 2ead77f5a..dc0ab1e82 100644
--- a/src/libstrongswan/plugins/pkcs11/Makefile.in
+++ b/src/libstrongswan/plugins/pkcs11/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -87,7 +88,7 @@ libstrongswan_pkcs11_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@MONOLITHIC_FALSE@am_libstrongswan_pkcs11_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_pkcs11_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -113,6 +114,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -207,11 +209,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -228,11 +233,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -248,6 +254,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -257,7 +264,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_creds.c b/src/libstrongswan/plugins/pkcs11/pkcs11_creds.c
index a81ec1147..7536ce1d3 100644
--- a/src/libstrongswan/plugins/pkcs11/pkcs11_creds.c
+++ b/src/libstrongswan/plugins/pkcs11/pkcs11_creds.c
@@ -109,7 +109,8 @@ static void find_certificates(private_pkcs11_creds_t *this,
if (cert)
{
DBG1(DBG_CFG, " loaded %strusted cert '%.*s'",
- entry->trusted ? "" : "un", entry->label.len, entry->label.ptr);
+ entry->trusted ? "" : "un", (int)entry->label.len,
+ entry->label.ptr);
/* trusted certificates are also returned as untrusted */
this->untrusted->insert_last(this->untrusted, cert);
if (entry->trusted)
@@ -120,7 +121,7 @@ static void find_certificates(private_pkcs11_creds_t *this,
else
{
DBG1(DBG_CFG, " loading cert '%.*s' failed",
- entry->label.len, entry->label.ptr);
+ (int)entry->label.len, entry->label.ptr);
}
free(entry->value.ptr);
free(entry->label.ptr);
diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_hasher.c b/src/libstrongswan/plugins/pkcs11/pkcs11_hasher.c
index 069fa98b6..53a2bfca7 100644
--- a/src/libstrongswan/plugins/pkcs11/pkcs11_hasher.c
+++ b/src/libstrongswan/plugins/pkcs11/pkcs11_hasher.c
@@ -84,7 +84,7 @@ METHOD(hasher_t, get_hash_size, size_t,
/**
* Save the Operation state to host memory
*/
-static void save_state(private_pkcs11_hasher_t *this)
+static bool save_state(private_pkcs11_hasher_t *this)
{
CK_RV rv;
@@ -110,20 +110,20 @@ static void save_state(private_pkcs11_hasher_t *this)
continue;
case CKR_OK:
this->have_state = TRUE;
- return;
+ return TRUE;
default:
break;
}
break;
}
DBG1(DBG_CFG, "C_GetOperationState() failed: %N", ck_rv_names, rv);
- abort();
+ return FALSE;
}
/**
* Load the Operation state from host memory
*/
-static void load_state(private_pkcs11_hasher_t *this)
+static bool load_state(private_pkcs11_hasher_t *this)
{
CK_RV rv;
@@ -132,18 +132,20 @@ static void load_state(private_pkcs11_hasher_t *this)
if (rv != CKR_OK)
{
DBG1(DBG_CFG, "C_SetOperationState() failed: %N", ck_rv_names, rv);
- abort();
+ return FALSE;
}
this->have_state = FALSE;
+ return TRUE;
}
-METHOD(hasher_t, reset, void,
+METHOD(hasher_t, reset, bool,
private_pkcs11_hasher_t *this)
{
this->have_state = FALSE;
+ return TRUE;
}
-METHOD(hasher_t, get_hash, void,
+METHOD(hasher_t, get_hash, bool,
private_pkcs11_hasher_t *this, chunk_t chunk, u_int8_t *hash)
{
CK_RV rv;
@@ -152,7 +154,11 @@ METHOD(hasher_t, get_hash, void,
this->mutex->lock(this->mutex);
if (this->have_state)
{
- load_state(this);
+ if (!load_state(this))
+ {
+ this->mutex->unlock(this->mutex);
+ return FALSE;
+ }
}
else
{
@@ -160,7 +166,8 @@ METHOD(hasher_t, get_hash, void,
if (rv != CKR_OK)
{
DBG1(DBG_CFG, "C_DigestInit() failed: %N", ck_rv_names, rv);
- abort();
+ this->mutex->unlock(this->mutex);
+ return FALSE;
}
}
if (chunk.len)
@@ -169,7 +176,8 @@ METHOD(hasher_t, get_hash, void,
if (rv != CKR_OK)
{
DBG1(DBG_CFG, "C_DigestUpdate() failed: %N", ck_rv_names, rv);
- abort();
+ this->mutex->unlock(this->mutex);
+ return FALSE;
}
}
if (hash)
@@ -180,28 +188,31 @@ METHOD(hasher_t, get_hash, void,
if (rv != CKR_OK)
{
DBG1(DBG_CFG, "C_DigestFinal() failed: %N", ck_rv_names, rv);
- abort();
+ this->mutex->unlock(this->mutex);
+ return FALSE;
}
}
else
{
- save_state(this);
+ if (!save_state(this))
+ {
+ this->mutex->unlock(this->mutex);
+ return FALSE;
+ }
}
this->mutex->unlock(this->mutex);
+ return TRUE;
}
-METHOD(hasher_t, allocate_hash, void,
+METHOD(hasher_t, allocate_hash, bool,
private_pkcs11_hasher_t *this, chunk_t chunk, chunk_t *hash)
{
if (hash)
{
*hash = chunk_alloc(this->size);
- get_hash(this, chunk, hash->ptr);
- }
- else
- {
- get_hash(this, chunk, NULL);
+ return get_hash(this, chunk, hash->ptr);
}
+ return get_hash(this, chunk, NULL);
}
METHOD(hasher_t, destroy, void,
diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_manager.c b/src/libstrongswan/plugins/pkcs11/pkcs11_manager.c
index 5b321b26e..83c383671 100644
--- a/src/libstrongswan/plugins/pkcs11/pkcs11_manager.c
+++ b/src/libstrongswan/plugins/pkcs11/pkcs11_manager.c
@@ -61,8 +61,6 @@ typedef struct {
char *path;
/* loaded library */
pkcs11_library_t *lib;
- /* event dispatcher job */
- callback_job_t *job;
} lib_entry_t;
/**
@@ -70,10 +68,6 @@ typedef struct {
*/
static void lib_entry_destroy(lib_entry_t *entry)
{
- if (entry->job)
- {
- entry->job->cancel(entry->job);
- }
entry->lib->destroy(entry->lib);
free(entry);
}
@@ -202,14 +196,6 @@ static job_requeue_t dispatch_slot_events(lib_entry_t *entry)
}
/**
- * End dispatching, unset job
- */
-static void end_dispatch(lib_entry_t *entry)
-{
- entry->job = NULL;
-}
-
-/**
* Get the slot list of a library
*/
static CK_SLOT_ID_PTR get_slot_list(pkcs11_library_t *p11, CK_ULONG *out)
@@ -384,9 +370,9 @@ pkcs11_manager_t *pkcs11_manager_create(pkcs11_manager_token_event_t cb,
while (enumerator->enumerate(enumerator, &entry))
{
query_slots(entry);
- entry->job = callback_job_create_with_prio((void*)dispatch_slot_events,
- entry, (void*)end_dispatch, NULL, JOB_PRIO_CRITICAL);
- lib->processor->queue_job(lib->processor, (job_t*)entry->job);
+ lib->processor->queue_job(lib->processor,
+ (job_t*)callback_job_create_with_prio((void*)dispatch_slot_events,
+ entry, NULL, (void*)return_false, JOB_PRIO_CRITICAL));
}
enumerator->destroy(enumerator);
diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c b/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c
index b616abc38..f7f7d3f79 100644
--- a/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c
+++ b/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c
@@ -266,13 +266,15 @@ METHOD(private_key_t, sign, bool,
}
if (hash_alg != HASH_UNKNOWN)
{
- hasher_t *hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
- if (!hasher)
+ hasher_t *hasher;
+
+ hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
+ if (!hasher || !hasher->allocate_hash(hasher, data, &hash))
{
+ DESTROY_IF(hasher);
this->lib->f->C_CloseSession(session);
return FALSE;
}
- hasher->allocate_hash(hasher, data, &hash);
hasher->destroy(hasher);
data = hash;
}
diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_public_key.c b/src/libstrongswan/plugins/pkcs11/pkcs11_public_key.c
index d4ec9235d..f0d7093db 100644
--- a/src/libstrongswan/plugins/pkcs11/pkcs11_public_key.c
+++ b/src/libstrongswan/plugins/pkcs11/pkcs11_public_key.c
@@ -235,13 +235,15 @@ METHOD(public_key_t, verify, bool,
}
if (hash_alg != HASH_UNKNOWN)
{
- hasher_t *hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
- if (!hasher)
+ hasher_t *hasher;
+
+ hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
+ if (!hasher || !hasher->allocate_hash(hasher, data, &hash))
{
+ DESTROY_IF(hasher);
this->lib->f->C_CloseSession(session);
return FALSE;
}
- hasher->allocate_hash(hasher, data, &hash);
hasher->destroy(hasher);
data = hash;
}
@@ -374,12 +376,12 @@ static bool fingerprint_ecdsa(private_pkcs11_public_key_t *this,
return FALSE;
}
hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
- if (!hasher)
+ if (!hasher || !hasher->allocate_hash(hasher, asn1, fp))
{
+ DESTROY_IF(hasher);
chunk_clear(&asn1);
return FALSE;
}
- hasher->allocate_hash(hasher, asn1, fp);
hasher->destroy(hasher);
chunk_clear(&asn1);
lib->encoding->cache(lib->encoding, type, this, *fp);
diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_rng.c b/src/libstrongswan/plugins/pkcs11/pkcs11_rng.c
index 45cf0b7c2..20e4b6f76 100644
--- a/src/libstrongswan/plugins/pkcs11/pkcs11_rng.c
+++ b/src/libstrongswan/plugins/pkcs11/pkcs11_rng.c
@@ -43,7 +43,7 @@ struct private_pkcs11_rng_t {
};
-METHOD(rng_t, get_bytes, void,
+METHOD(rng_t, get_bytes, bool,
private_pkcs11_rng_t *this, size_t bytes, u_int8_t *buffer)
{
CK_RV rv;
@@ -51,15 +51,21 @@ METHOD(rng_t, get_bytes, void,
if (rv != CKR_OK)
{
DBG1(DBG_CFG, "C_GenerateRandom() failed: %N", ck_rv_names, rv);
- abort();
+ return FALSE;
}
+ return TRUE;
}
-METHOD(rng_t, allocate_bytes, void,
+METHOD(rng_t, allocate_bytes, bool,
private_pkcs11_rng_t *this, size_t bytes, chunk_t *chunk)
{
*chunk = chunk_alloc(bytes);
- get_bytes(this, chunk->len, chunk->ptr);
+ if (!get_bytes(this, chunk->len, chunk->ptr))
+ {
+ chunk_clear(chunk);
+ return FALSE;
+ }
+ return TRUE;
}
METHOD(rng_t, destroy, void,
diff --git a/src/libstrongswan/plugins/pkcs8/Makefile.in b/src/libstrongswan/plugins/pkcs8/Makefile.in
index 2b9c6cf95..60d7ae643 100644
--- a/src/libstrongswan/plugins/pkcs8/Makefile.in
+++ b/src/libstrongswan/plugins/pkcs8/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -83,7 +84,7 @@ libstrongswan_pkcs8_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@MONOLITHIC_FALSE@am_libstrongswan_pkcs8_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_pkcs8_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -109,6 +110,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -203,11 +205,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -224,11 +229,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -244,6 +250,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -253,7 +260,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/pkcs8/pkcs8_builder.c b/src/libstrongswan/plugins/pkcs8/pkcs8_builder.c
index 346240ae1..a501423b1 100644
--- a/src/libstrongswan/plugins/pkcs8/pkcs8_builder.c
+++ b/src/libstrongswan/plugins/pkcs8/pkcs8_builder.c
@@ -126,7 +126,7 @@ static bool verify_padding(chunk_t *blob)
/**
* Prototype for key derivation functions.
*/
-typedef void (*kdf_t)(void *generator, chunk_t password, chunk_t salt,
+typedef bool (*kdf_t)(void *generator, chunk_t password, chunk_t salt,
u_int64_t iterations, chunk_t key);
/**
@@ -164,10 +164,15 @@ static private_key_t *decrypt_private_key(chunk_t blob,
{
chunk_t decrypted;
- kdf(generator, shared->get_key(shared), salt, iterations, keymat);
-
- crypter->set_key(crypter, key);
- crypter->decrypt(crypter, blob, iv, &decrypted);
+ if (!kdf(generator, shared->get_key(shared), salt, iterations, keymat))
+ {
+ continue;
+ }
+ if (!crypter->set_key(crypter, key) ||
+ !crypter->decrypt(crypter, blob, iv, &decrypted))
+ {
+ continue;
+ }
if (verify_padding(&decrypted))
{
private_key = parse_private_key(decrypted);
@@ -188,34 +193,44 @@ static private_key_t *decrypt_private_key(chunk_t blob,
/**
* Function F of PBKDF2
*/
-static void pbkdf2_f(chunk_t block, prf_t *prf, chunk_t seed,
+static bool pbkdf2_f(chunk_t block, prf_t *prf, chunk_t seed,
u_int64_t iterations)
{
chunk_t u;
u_int64_t i;
u = chunk_alloca(prf->get_block_size(prf));
- prf->get_bytes(prf, seed, u.ptr);
+ if (!prf->get_bytes(prf, seed, u.ptr))
+ {
+ return FALSE;
+ }
memcpy(block.ptr, u.ptr, block.len);
for (i = 1; i < iterations; i++)
{
- prf->get_bytes(prf, u, u.ptr);
+ if (!prf->get_bytes(prf, u, u.ptr))
+ {
+ return FALSE;
+ }
memxor(block.ptr, u.ptr, block.len);
}
+ return TRUE;
}
/**
* PBKDF2 key derivation function
*/
-static void pbkdf2(prf_t *prf, chunk_t password, chunk_t salt,
+static bool pbkdf2(prf_t *prf, chunk_t password, chunk_t salt,
u_int64_t iterations, chunk_t key)
{
chunk_t keymat, block, seed;
size_t blocks;
u_int32_t i = 0, *ni;
- prf->set_key(prf, password);
+ if (!prf->set_key(prf, password))
+ {
+ return FALSE;
+ }
block.len = prf->get_block_size(prf);
blocks = (key.len - 1) / block.len + 1;
@@ -228,10 +243,15 @@ static void pbkdf2(prf_t *prf, chunk_t password, chunk_t salt,
{
*ni = htonl(i + 1);
block.ptr = keymat.ptr + (i * block.len);
- pbkdf2_f(block, prf, seed, iterations);
+ if (!pbkdf2_f(block, prf, seed, iterations))
+ {
+ return FALSE;
+ }
}
memcpy(key.ptr, keymat.ptr, key.len);
+
+ return TRUE;
}
/**
@@ -266,22 +286,30 @@ static private_key_t *decrypt_private_key_pbes2(chunk_t blob,
/**
* PBKDF1 key derivation function
*/
-static void pbkdf1(hasher_t *hasher, chunk_t password, chunk_t salt,
+static bool pbkdf1(hasher_t *hasher, chunk_t password, chunk_t salt,
u_int64_t iterations, chunk_t key)
{
chunk_t hash;
u_int64_t i;
hash = chunk_alloca(hasher->get_hash_size(hasher));
- hasher->get_hash(hasher, password, NULL);
- hasher->get_hash(hasher, salt, hash.ptr);
+ if (!hasher->get_hash(hasher, password, NULL) ||
+ !hasher->get_hash(hasher, salt, hash.ptr))
+ {
+ return FALSE;
+ }
for (i = 1; i < iterations; i++)
{
- hasher->get_hash(hasher, hash, hash.ptr);
+ if (!hasher->get_hash(hasher, hash, hash.ptr))
+ {
+ return FALSE;
+ }
}
memcpy(key.ptr, hash.ptr, key.len);
+
+ return TRUE;
}
/**
@@ -535,7 +563,7 @@ static const asn1Object_t encryptedPKIObjects[] = {
static private_key_t *parse_encrypted_private_key(chunk_t blob)
{
asn1_parser_t *parser;
- chunk_t object, params, salt, iv;
+ chunk_t object, params, salt = chunk_empty, iv = chunk_empty;
u_int64_t iterations = 0;
int objectID;
encryption_algorithm_t encr = ENCR_UNDEFINED;
diff --git a/src/libstrongswan/plugins/plugin_feature.c b/src/libstrongswan/plugins/plugin_feature.c
index 2a97205bb..6e043878c 100644
--- a/src/libstrongswan/plugins/plugin_feature.c
+++ b/src/libstrongswan/plugins/plugin_feature.c
@@ -1,4 +1,7 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
* Copyright (C) 2011 Martin Willi
* Copyright (C) 2011 revosec AG
*
@@ -29,6 +32,7 @@ ENUM(plugin_feature_names, FEATURE_NONE, FEATURE_CUSTOM,
"PRF",
"DH",
"RNG",
+ "NONCE_GEN",
"PRIVKEY",
"PRIVKEY_GEN",
"PRIVKEY_SIGN",
@@ -40,6 +44,8 @@ ENUM(plugin_feature_names, FEATURE_NONE, FEATURE_CUSTOM,
"CERT_ENCODE",
"EAP_SERVER",
"EAP_CLIENT",
+ "XAUTH_SERVER",
+ "XAUTH_CLIENT",
"DATABASE",
"FETCHER",
"CUSTOM",
@@ -48,6 +54,56 @@ ENUM(plugin_feature_names, FEATURE_NONE, FEATURE_CUSTOM,
/**
* See header.
*/
+u_int32_t plugin_feature_hash(plugin_feature_t *feature)
+{
+ chunk_t data;
+
+ switch (feature->type)
+ {
+ case FEATURE_NONE:
+ case FEATURE_RNG:
+ case FEATURE_NONCE_GEN:
+ case FEATURE_DATABASE:
+ case FEATURE_FETCHER:
+ /* put these special cases in their (type-specific) buckets */
+ data = chunk_empty;
+ break;
+ case FEATURE_CRYPTER:
+ case FEATURE_AEAD:
+ case FEATURE_SIGNER:
+ case FEATURE_HASHER:
+ case FEATURE_PRF:
+ case FEATURE_DH:
+ case FEATURE_PRIVKEY:
+ case FEATURE_PRIVKEY_GEN:
+ case FEATURE_PUBKEY:
+ case FEATURE_PRIVKEY_SIGN:
+ case FEATURE_PUBKEY_VERIFY:
+ case FEATURE_PRIVKEY_DECRYPT:
+ case FEATURE_PUBKEY_ENCRYPT:
+ case FEATURE_CERT_DECODE:
+ case FEATURE_CERT_ENCODE:
+ case FEATURE_EAP_SERVER:
+ case FEATURE_EAP_PEER:
+ data = chunk_from_thing(feature->arg);
+ break;
+ case FEATURE_CUSTOM:
+ data = chunk_create(feature->arg.custom,
+ strlen(feature->arg.custom));
+ break;
+ case FEATURE_XAUTH_SERVER:
+ case FEATURE_XAUTH_PEER:
+ data = chunk_create(feature->arg.xauth,
+ strlen(feature->arg.xauth));
+ break;
+ }
+ return chunk_hash_inc(chunk_from_thing(feature->type),
+ chunk_hash(data));
+}
+
+/**
+ * See header.
+ */
bool plugin_feature_matches(plugin_feature_t *a, plugin_feature_t *b)
{
if (a->type == b->type)
@@ -72,6 +128,8 @@ bool plugin_feature_matches(plugin_feature_t *a, plugin_feature_t *b)
return a->arg.dh_group == b->arg.dh_group;
case FEATURE_RNG:
return a->arg.rng_quality <= b->arg.rng_quality;
+ case FEATURE_NONCE_GEN:
+ return TRUE;
case FEATURE_PRIVKEY:
case FEATURE_PRIVKEY_GEN:
case FEATURE_PUBKEY:
@@ -96,6 +154,9 @@ bool plugin_feature_matches(plugin_feature_t *a, plugin_feature_t *b)
streq(a->arg.fetcher, b->arg.fetcher);
case FEATURE_CUSTOM:
return streq(a->arg.custom, b->arg.custom);
+ case FEATURE_XAUTH_SERVER:
+ case FEATURE_XAUTH_PEER:
+ return streq(a->arg.xauth, b->arg.xauth);
}
}
return FALSE;
@@ -167,6 +228,12 @@ char* plugin_feature_get_string(plugin_feature_t *feature)
return str;
}
break;
+ case FEATURE_NONCE_GEN:
+ if (asprintf(&str, "%N", plugin_feature_names, feature->type) > 0)
+ {
+ return str;
+ }
+ break;
case FEATURE_PRIVKEY:
case FEATURE_PRIVKEY_GEN:
case FEATURE_PUBKEY:
@@ -229,6 +296,14 @@ char* plugin_feature_get_string(plugin_feature_t *feature)
return str;
}
break;
+ case FEATURE_XAUTH_SERVER:
+ case FEATURE_XAUTH_PEER:
+ if (asprintf(&str, "%N:%s", plugin_feature_names, feature->type,
+ feature->arg.xauth) > 0)
+ {
+ return str;
+ }
+ break;
}
if (!str)
{
@@ -251,7 +326,8 @@ bool plugin_feature_load(plugin_t *plugin, plugin_feature_t *feature,
}
if (reg->kind == FEATURE_CALLBACK)
{
- if (reg->arg.cb.f(plugin, feature, TRUE, reg->arg.cb.data))
+ if (!reg->arg.cb.f ||
+ reg->arg.cb.f(plugin, feature, TRUE, reg->arg.cb.data))
{
return TRUE;
}
@@ -288,6 +364,10 @@ bool plugin_feature_load(plugin_t *plugin, plugin_feature_t *feature,
lib->crypto->add_rng(lib->crypto, feature->arg.rng_quality,
name, reg->arg.reg.f);
break;
+ case FEATURE_NONCE_GEN:
+ lib->crypto->add_nonce_gen(lib->crypto,
+ name, reg->arg.reg.f);
+ break;
case FEATURE_PRIVKEY:
case FEATURE_PRIVKEY_GEN:
lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY,
@@ -330,7 +410,8 @@ bool plugin_feature_unload(plugin_t *plugin, plugin_feature_t *feature,
}
if (reg->kind == FEATURE_CALLBACK)
{
- if (reg->arg.cb.f(plugin, feature, FALSE, reg->arg.cb.data))
+ if (!reg->arg.cb.f ||
+ reg->arg.cb.f(plugin, feature, FALSE, reg->arg.cb.data))
{
return TRUE;
}
@@ -359,6 +440,9 @@ bool plugin_feature_unload(plugin_t *plugin, plugin_feature_t *feature,
case FEATURE_RNG:
lib->crypto->remove_rng(lib->crypto, reg->arg.reg.f);
break;
+ case FEATURE_NONCE_GEN:
+ lib->crypto->remove_nonce_gen(lib->crypto, reg->arg.reg.f);
+ break;
case FEATURE_PRIVKEY:
case FEATURE_PRIVKEY_GEN:
lib->creds->remove_builder(lib->creds, reg->arg.reg.f);
diff --git a/src/libstrongswan/plugins/plugin_feature.h b/src/libstrongswan/plugins/plugin_feature.h
index b1500feba..90f8a948a 100644
--- a/src/libstrongswan/plugins/plugin_feature.h
+++ b/src/libstrongswan/plugins/plugin_feature.h
@@ -1,4 +1,7 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
* Copyright (C) 2011 Martin Willi
* Copyright (C) 2011 revosec AG
*
@@ -48,17 +51,19 @@ typedef bool (*plugin_feature_callback_t)(plugin_t *plugin,
* features provided by the plugin, hard (DEPENDS) or soft (SDEPEND) dependency
* specified is related to the previously defined PROVIDE feature.
* If a plugin feature requires to hook in functionality into the library
- * or a daemon, it can use REGISTER or CALLBACK entries. Each PROVIDED feature
+ * or a daemon, it can use REGISTER or CALLBACK entries. Each PROVIDE feature
* uses the REGISTER/CALLBACK entry defined previously. The REGISTER entry
* defines a common feature registration function directly passed to the
* associated manager or factory (crypto/credential factory etc.). A callback
* function is more generic allows the loader to invoke a callback to do
- * the registration.
+ * the registration. PROVIDE features that do not use a registration or callback
+ * function must be listed before any REGISTER/CALLBACK entry, or use the NOOP
+ * helper macro.
*
- * To conviently create feature lists, use the four macros PLUGIN_REGISTER,
- * PLUGIN_CALLBACK, PLUGIN_PROVIDE, PLUGIN_DEPENDS and PLUGIN_SDEPEND. Use
- * identation to show how the registration functions and dependencies are
- * related to a provided feature, such as:
+ * To conveniently create feature lists, use the macros PLUGIN_REGISTER,
+ * PLUGIN_CALLBACK, PLUGIN_NOOP, PLUGIN_PROVIDE, PLUGIN_DEPENDS and
+ * PLUGIN_SDEPEND. Use indentation to show how the registration functions
+ * and dependencies are related to a provided feature, such as:
*
* @verbatim
// two features, one with two dependencies, both use a callback to register
@@ -72,7 +77,8 @@ typedef bool (*plugin_feature_callback_t)(plugin_t *plugin,
PLUGIN_PROVIDE(...),
PLUGIN_DEPENDS(...),
// feature that does not use a registration function
- PLUGIN_PROVIDE(...),
+ PLUGIN_NOOP,
+ PLUGIN_PROVIDE(...),
@endverbatim
*/
struct plugin_feature_t {
@@ -107,6 +113,8 @@ struct plugin_feature_t {
FEATURE_DH,
/** rng_t */
FEATURE_RNG,
+ /** nonce_gen_t */
+ FEATURE_NONCE_GEN,
/** generic private key support */
FEATURE_PRIVKEY,
/** generating new private keys */
@@ -129,6 +137,10 @@ struct plugin_feature_t {
FEATURE_EAP_SERVER,
/** EAP peer implementation */
FEATURE_EAP_PEER,
+ /** XAuth server implementation */
+ FEATURE_XAUTH_SERVER,
+ /** XAuth peer implementation */
+ FEATURE_XAUTH_PEER,
/** database_t */
FEATURE_DATABASE,
/** fetcher_t */
@@ -182,6 +194,8 @@ struct plugin_feature_t {
char *fetcher;
/** FEATURE_CUSTOM */
char *custom;
+ /** FEATURE_XAUTH_SERVER/CLIENT */
+ char *xauth;
/** FEATURE_REGISTER */
struct {
@@ -221,6 +235,11 @@ struct plugin_feature_t {
#define PLUGIN_CALLBACK(cb, data) _PLUGIN_FEATURE_CALLBACK(cb, data)
/**
+ * The upcoming features use neither a callback nor a register function.
+ */
+#define PLUGIN_NOOP _PLUGIN_FEATURE_CALLBACK(NULL, NULL)
+
+/**
* Define a feature the plugin provides.
*
* @param type feature type to provide
@@ -252,6 +271,7 @@ struct plugin_feature_t {
#define _PLUGIN_FEATURE_PRF(kind, alg) __PLUGIN_FEATURE(kind, PRF, .prf = alg)
#define _PLUGIN_FEATURE_DH(kind, group) __PLUGIN_FEATURE(kind, DH, .dh_group = group)
#define _PLUGIN_FEATURE_RNG(kind, quality) __PLUGIN_FEATURE(kind, RNG, .rng_quality = quality)
+#define _PLUGIN_FEATURE_NONCE_GEN(kind, ...) __PLUGIN_FEATURE(kind, NONCE_GEN, .custom = NULL)
#define _PLUGIN_FEATURE_PRIVKEY(kind, type) __PLUGIN_FEATURE(kind, PRIVKEY, .privkey = type)
#define _PLUGIN_FEATURE_PRIVKEY_GEN(kind, type) __PLUGIN_FEATURE(kind, PRIVKEY_GEN, .privkey_gen = type)
#define _PLUGIN_FEATURE_PRIVKEY_SIGN(kind, scheme) __PLUGIN_FEATURE(kind, PRIVKEY_SIGN, .privkey_sign = scheme)
@@ -266,6 +286,8 @@ struct plugin_feature_t {
#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_CUSTOM(kind, name) __PLUGIN_FEATURE(kind, CUSTOM, .custom = name)
+#define _PLUGIN_FEATURE_XAUTH_SERVER(kind, name) __PLUGIN_FEATURE(kind, XAUTH_SERVER, .xauth = name)
+#define _PLUGIN_FEATURE_XAUTH_PEER(kind, name) __PLUGIN_FEATURE(kind, XAUTH_PEER, .xauth = name)
#define __PLUGIN_FEATURE_REGISTER(type, _f) (plugin_feature_t){ FEATURE_REGISTER, FEATURE_##type, .arg.reg.f = _f }
#define __PLUGIN_FEATURE_REGISTER_BUILDER(type, _f, _final) (plugin_feature_t){ FEATURE_REGISTER, FEATURE_##type, .arg.reg = {.f = _f, .final = _final, }}
@@ -276,6 +298,7 @@ struct plugin_feature_t {
#define _PLUGIN_FEATURE_REGISTER_PRF(type, f) __PLUGIN_FEATURE_REGISTER(type, f)
#define _PLUGIN_FEATURE_REGISTER_DH(type, f) __PLUGIN_FEATURE_REGISTER(type, f)
#define _PLUGIN_FEATURE_REGISTER_RNG(type, f) __PLUGIN_FEATURE_REGISTER(type, f)
+#define _PLUGIN_FEATURE_REGISTER_NONCE_GEN(type, f) __PLUGIN_FEATURE_REGISTER(type, f)
#define _PLUGIN_FEATURE_REGISTER_PRIVKEY(type, f, final) __PLUGIN_FEATURE_REGISTER_BUILDER(type, f, final)
#define _PLUGIN_FEATURE_REGISTER_PRIVKEY_GEN(type, f, final)__PLUGIN_FEATURE_REGISTER_BUILDER(type, f, final)
#define _PLUGIN_FEATURE_REGISTER_PUBKEY(type, f, final) __PLUGIN_FEATURE_REGISTER_BUILDER(type, f, final)
@@ -292,6 +315,18 @@ struct plugin_feature_t {
extern enum_name_t *plugin_feature_names;
/**
+ * Calculates a hash value for the given feature.
+ *
+ * Since this is intended to be used with the plugin_features_matches function
+ * the hash is not really unique for all types of features (e.g. RNGs are all
+ * mapped to the same value because they are loosely matched by said function).
+ *
+ * @param feature feature to hash
+ * @return hash value of the feature
+ */
+u_int32_t plugin_feature_hash(plugin_feature_t *feature);
+
+/**
* Check if feature a matches to feature b.
*
* @param a feature to check
diff --git a/src/libstrongswan/plugins/plugin_loader.c b/src/libstrongswan/plugins/plugin_loader.c
index f97cbb31f..95a0bfc02 100644
--- a/src/libstrongswan/plugins/plugin_loader.c
+++ b/src/libstrongswan/plugins/plugin_loader.c
@@ -25,6 +25,7 @@
#include <debug.h>
#include <library.h>
#include <integrity_checker.h>
+#include <utils/hashtable.h>
#include <utils/linked_list.h>
#include <plugins/plugin.h>
@@ -47,6 +48,11 @@ struct private_plugin_loader_t {
linked_list_t *plugins;
/**
+ * Hashtable for loaded features, as plugin_feature_t
+ */
+ hashtable_t *loaded_features;
+
+ /**
* List of names of loaded plugins
*/
char *loaded_plugins;
@@ -63,6 +69,11 @@ struct plugin_entry_t {
plugin_t *plugin;
/**
+ * TRUE, if the plugin is marked as critical
+ */
+ bool critical;
+
+ /**
* dlopen handle, if in separate lib
*/
void *handle;
@@ -94,12 +105,93 @@ static void plugin_entry_destroy(plugin_entry_t *entry)
}
/**
+ * Wrapper for static plugin features
+ */
+typedef struct {
+
+ /**
+ * Implements plugin_t interface
+ */
+ plugin_t public;
+
+ /**
+ * Name of the module registering these features
+ */
+ char *name;
+
+ /**
+ * Static plugin features
+ */
+ plugin_feature_t *features;
+
+ /**
+ * Number of plugin features
+ */
+ int count;
+
+} static_features_t;
+
+METHOD(plugin_t, get_static_name, char*,
+ static_features_t *this)
+{
+ return this->name;
+}
+
+METHOD(plugin_t, get_static_features, int,
+ static_features_t *this, plugin_feature_t *features[])
+{
+ *features = this->features;
+ return this->count;
+}
+
+METHOD(plugin_t, static_destroy, void,
+ static_features_t *this)
+{
+ free(this->features);
+ free(this->name);
+ free(this);
+}
+
+/**
+ * Create a wrapper around static plugin features.
+ */
+static plugin_t *static_features_create(const char *name,
+ plugin_feature_t features[], int count)
+{
+ static_features_t *this;
+
+ INIT(this,
+ .public = {
+ .get_name = _get_static_name,
+ .get_features = _get_static_features,
+ .destroy = _static_destroy,
+ },
+ .name = strdup(name),
+ .features = calloc(count, sizeof(plugin_feature_t)),
+ .count = count,
+ );
+
+ memcpy(this->features, features, sizeof(plugin_feature_t) * count);
+
+ return &this->public;
+}
+
+/**
+ * Compare function for hashtable of loaded features.
+ */
+static bool plugin_feature_equals(plugin_feature_t *a, plugin_feature_t *b)
+{
+ return a == b;
+}
+
+/**
* create a plugin
* returns: NOT_FOUND, if the constructor was not found
* FAILED, if the plugin could not be constructed
*/
static status_t create_plugin(private_plugin_loader_t *this, void *handle,
- char *name, bool integrity, plugin_entry_t **entry)
+ char *name, bool integrity, bool critical,
+ plugin_entry_t **entry)
{
char create[128];
plugin_t *plugin;
@@ -135,6 +227,7 @@ static status_t create_plugin(private_plugin_loader_t *this, void *handle,
}
INIT(*entry,
.plugin = plugin,
+ .critical = critical,
.loaded = linked_list_create(),
.failed = linked_list_create(),
);
@@ -145,19 +238,23 @@ static status_t create_plugin(private_plugin_loader_t *this, void *handle,
/**
* load a single plugin
*/
-static bool load_plugin(private_plugin_loader_t *this, char *name, char *file)
+static bool load_plugin(private_plugin_loader_t *this, char *name, char *file,
+ bool critical)
{
plugin_entry_t *entry;
void *handle;
- switch (create_plugin(this, RTLD_DEFAULT, name, FALSE, &entry))
+ switch (create_plugin(this, RTLD_DEFAULT, name, FALSE, critical, &entry))
{
case SUCCESS:
this->plugins->insert_last(this->plugins, entry);
return TRUE;
case NOT_FOUND:
- /* try to load the plugin from a file */
- break;
+ if (file)
+ { /* try to load the plugin from a file */
+ break;
+ }
+ /* fall-through */
default:
return FALSE;
}
@@ -176,7 +273,7 @@ static bool load_plugin(private_plugin_loader_t *this, char *name, char *file)
DBG1(DBG_LIB, "plugin '%s' failed to load: %s", name, dlerror());
return FALSE;
}
- if (create_plugin(this, handle, name, TRUE, &entry) != SUCCESS)
+ if (create_plugin(this, handle, name, TRUE, critical, &entry) != SUCCESS)
{
dlclose(handle);
return FALSE;
@@ -294,32 +391,15 @@ static bool dependencies_satisfied(private_plugin_loader_t *this,
/* first entry is provided feature, followed by dependencies */
for (i = 1; i < count; i++)
{
- enumerator_t *entries, *loaded;
- plugin_feature_t *feature;
- plugin_entry_t *current;
- bool found = FALSE;
+ plugin_feature_t *found;
if (features[i].kind != FEATURE_DEPENDS &&
features[i].kind != FEATURE_SDEPEND)
{ /* end of dependencies */
break;
}
- entries = this->plugins->create_enumerator(this->plugins);
- while (entries->enumerate(entries, &current))
- {
- loaded = current->loaded->create_enumerator(current->loaded);
- while (loaded->enumerate(loaded, &feature))
- {
- if (plugin_feature_matches(&features[i], feature))
- {
- found = TRUE;
- break;
- }
- }
- loaded->destroy(loaded);
- }
- entries->destroy(entries);
-
+ found = this->loaded_features->get_match(this->loaded_features,
+ &features[i], (hashtable_equals_t)plugin_feature_matches);
if (!found && (features[i].kind != FEATURE_SDEPEND || soft))
{
if (report)
@@ -361,7 +441,8 @@ static bool dependency_required(private_plugin_loader_t *this,
count = entry->plugin->get_features(entry->plugin, &features);
for (i = 0; i < count; i++)
{
- if (feature_loaded(this, entry, &features[i]))
+ if (&features[i] != dep &&
+ feature_loaded(this, entry, &features[i]))
{
while (++i < count && (features[i].kind == FEATURE_DEPENDS ||
features[i].kind == FEATURE_SDEPEND))
@@ -410,6 +491,8 @@ static int load_features(private_plugin_loader_t *this, bool soft, bool report)
{
if (plugin_feature_load(entry->plugin, feature, reg))
{
+ this->loaded_features->put(this->loaded_features,
+ feature, feature);
entry->loaded->insert_last(entry->loaded, feature);
loaded++;
}
@@ -428,6 +511,10 @@ static int load_features(private_plugin_loader_t *this, bool soft, bool report)
}
feature++;
}
+ if (loaded && !report)
+ { /* got new feature, restart from beginning of list */
+ break;
+ }
}
enumerator->destroy(enumerator);
return loaded;
@@ -451,6 +538,8 @@ static int unload_features(private_plugin_loader_t *this, plugin_entry_t *entry)
!dependency_required(this, feature) &&
plugin_feature_unload(entry->plugin, feature, reg))
{
+ this->loaded_features->remove(this->loaded_features,
+ feature);
entry->loaded->remove(entry->loaded, feature, NULL);
unloaded++;
}
@@ -468,6 +557,55 @@ static int unload_features(private_plugin_loader_t *this, plugin_entry_t *entry)
}
/**
+ * Check that we have all features loaded for critical plugins
+ */
+static bool missing_critical_features(private_plugin_loader_t *this)
+{
+ enumerator_t *enumerator;
+ plugin_entry_t *entry;
+ bool critical_failed = FALSE;
+
+ enumerator = this->plugins->create_enumerator(this->plugins);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (!entry->plugin->get_features)
+ { /* feature interface not supported */
+ continue;
+ }
+ if (entry->critical)
+ {
+ plugin_feature_t *feature;
+ char *name, *provide;
+ int count, i, failed = 0;
+
+ name = entry->plugin->get_name(entry->plugin);
+ count = entry->plugin->get_features(entry->plugin, &feature);
+ for (i = 0; i < count; i++, feature++)
+ {
+ if (feature->kind == FEATURE_PROVIDE &&
+ !feature_loaded(this, entry, feature))
+ {
+ provide = plugin_feature_get_string(feature);
+ DBG2(DBG_LIB, " failed to load %s in critical plugin '%s'",
+ provide, name);
+ free(provide);
+ failed++;
+ }
+ }
+ if (failed)
+ {
+ DBG1(DBG_LIB, "failed to load %d feature%s in critical plugin "
+ "'%s'", failed, failed > 1 ? "s" : "", name);
+ critical_failed = TRUE;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return critical_failed;
+}
+
+/**
* Remove plugins that we were not able to load any features from.
*/
static void purge_plugins(private_plugin_loader_t *this)
@@ -491,6 +629,24 @@ static void purge_plugins(private_plugin_loader_t *this)
enumerator->destroy(enumerator);
}
+METHOD(plugin_loader_t, add_static_features, void,
+ private_plugin_loader_t *this, const char *name,
+ plugin_feature_t features[], int count, bool critical)
+{
+ plugin_entry_t *entry;
+ plugin_t *plugin;
+
+ plugin = static_features_create(name, features, count);
+
+ INIT(entry,
+ .plugin = plugin,
+ .critical = critical,
+ .loaded = linked_list_create(),
+ .failed = linked_list_create(),
+ );
+ this->plugins->insert_last(this->plugins, entry);
+}
+
METHOD(plugin_loader_t, load_plugins, bool,
private_plugin_loader_t *this, char *path, char *list)
{
@@ -498,16 +654,18 @@ METHOD(plugin_loader_t, load_plugins, bool,
char *token;
bool critical_failed = FALSE;
+#ifdef PLUGINDIR
if (path == NULL)
{
path = PLUGINDIR;
}
+#endif /* PLUGINDIR */
enumerator = enumerator_create_token(list, " ", " ");
while (!critical_failed && enumerator->enumerate(enumerator, &token))
{
bool critical = FALSE;
- char file[PATH_MAX];
+ char buf[PATH_MAX], *file = NULL;
int len;
token = strdup(token);
@@ -522,12 +680,16 @@ METHOD(plugin_loader_t, load_plugins, bool,
free(token);
continue;
}
- if (snprintf(file, sizeof(file), "%s/libstrongswan-%s.so",
- path, token) >= sizeof(file))
+ if (path)
{
- return FALSE;
+ if (snprintf(buf, sizeof(buf), "%s/libstrongswan-%s.so",
+ path, token) >= sizeof(buf))
+ {
+ return FALSE;
+ }
+ file = buf;
}
- if (!load_plugin(this, token, file) && critical)
+ if (!load_plugin(this, token, file, critical) && critical)
{
critical_failed = TRUE;
DBG1(DBG_LIB, "loading critical plugin '%s' failed", token);
@@ -550,6 +712,8 @@ METHOD(plugin_loader_t, load_plugins, bool,
}
/* report missing dependencies */
load_features(this, FALSE, TRUE);
+ /* check for unloaded features provided by critical plugins */
+ critical_failed = missing_critical_features(this);
/* unload plugins that we were not able to load any features for */
purge_plugins(this);
}
@@ -660,6 +824,7 @@ METHOD(plugin_loader_t, destroy, void,
private_plugin_loader_t *this)
{
unload(this);
+ this->loaded_features->destroy(this->loaded_features);
this->plugins->destroy(this->plugins);
free(this->loaded_plugins);
free(this);
@@ -674,6 +839,7 @@ plugin_loader_t *plugin_loader_create()
INIT(this,
.public = {
+ .add_static_features = _add_static_features,
.load = _load_plugins,
.reload = _reload,
.unload = _unload,
@@ -682,6 +848,9 @@ plugin_loader_t *plugin_loader_create()
.destroy = _destroy,
},
.plugins = linked_list_create(),
+ .loaded_features = hashtable_create(
+ (hashtable_hash_t)plugin_feature_hash,
+ (hashtable_equals_t)plugin_feature_equals, 64),
);
return &this->public;
diff --git a/src/libstrongswan/plugins/plugin_loader.h b/src/libstrongswan/plugins/plugin_loader.h
index 7fd07044d..94181dbb6 100644
--- a/src/libstrongswan/plugins/plugin_loader.h
+++ b/src/libstrongswan/plugins/plugin_loader.h
@@ -26,12 +26,36 @@ typedef struct plugin_loader_t plugin_loader_t;
#include <utils/enumerator.h>
+/* to avoid circular references we can't include plugin_feature.h */
+struct plugin_feature_t;
+
/**
* The plugin_loader loads plugins from a directory and initializes them
*/
struct plugin_loader_t {
/**
+ * Add static plugin features, not loaded via plugins.
+ *
+ * Similar to features provided by plugins they are evaluated during load(),
+ * and unloaded when unload() is called.
+ *
+ * If critical is TRUE load() will fail if any of the added features could
+ * not be loaded.
+ *
+ * @note The name should be unique otherwise a plugin with the same name is
+ * not loaded.
+ *
+ * @param name name of the component adding the features
+ * @param features array of plugin features
+ * @param count number of features in the array
+ * @param critical TRUE if the features are critical
+ */
+ void (*add_static_features) (plugin_loader_t *this, const char *name,
+ struct plugin_feature_t *features, int count,
+ bool critical);
+
+ /**
* Load a list of plugins from a directory.
*
* Each plugin in list may have a ending exclamation mark (!) to mark it
diff --git a/src/libstrongswan/plugins/pubkey/Makefile.in b/src/libstrongswan/plugins/pubkey/Makefile.in
index 0de048791..6680873c2 100644
--- a/src/libstrongswan/plugins/pubkey/Makefile.in
+++ b/src/libstrongswan/plugins/pubkey/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -84,7 +85,7 @@ libstrongswan_pubkey_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@MONOLITHIC_FALSE@am_libstrongswan_pubkey_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_pubkey_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -110,6 +111,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -204,11 +206,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -225,11 +230,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -245,6 +251,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -254,7 +261,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/pubkey/pubkey_cert.c b/src/libstrongswan/plugins/pubkey/pubkey_cert.c
index 67240fe0c..0304ccb36 100644
--- a/src/libstrongswan/plugins/pubkey/pubkey_cert.c
+++ b/src/libstrongswan/plugins/pubkey/pubkey_cert.c
@@ -126,8 +126,13 @@ METHOD(certificate_t, equals, bool,
}
METHOD(certificate_t, issued_by, bool,
- private_pubkey_cert_t *this, certificate_t *issuer)
+ private_pubkey_cert_t *this, certificate_t *issuer,
+ signature_scheme_t *scheme)
{
+ if (scheme)
+ {
+ *scheme = SIGN_UNKNOWN;
+ }
return equals(this, issuer);
}
diff --git a/src/libstrongswan/plugins/pubkey/pubkey_plugin.c b/src/libstrongswan/plugins/pubkey/pubkey_plugin.c
index 92bfc2e63..a898bbfcc 100644
--- a/src/libstrongswan/plugins/pubkey/pubkey_plugin.c
+++ b/src/libstrongswan/plugins/pubkey/pubkey_plugin.c
@@ -43,6 +43,11 @@ METHOD(plugin_t, get_features, int,
static plugin_feature_t f[] = {
PLUGIN_REGISTER(CERT_ENCODE, pubkey_cert_wrap, FALSE),
PLUGIN_PROVIDE(CERT_ENCODE, CERT_TRUSTED_PUBKEY),
+ PLUGIN_REGISTER(CERT_DECODE, pubkey_cert_wrap, TRUE),
+ PLUGIN_PROVIDE(CERT_DECODE, CERT_TRUSTED_PUBKEY),
+ PLUGIN_SDEPEND(PUBKEY, KEY_RSA),
+ PLUGIN_SDEPEND(PUBKEY, KEY_ECDSA),
+ PLUGIN_SDEPEND(PUBKEY, KEY_DSA),
};
*features = f;
return countof(f);
diff --git a/src/libstrongswan/plugins/random/Makefile.in b/src/libstrongswan/plugins/random/Makefile.in
index 9b549b071..a393e8049 100644
--- a/src/libstrongswan/plugins/random/Makefile.in
+++ b/src/libstrongswan/plugins/random/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -84,7 +85,7 @@ libstrongswan_random_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@MONOLITHIC_FALSE@am_libstrongswan_random_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_random_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -110,6 +111,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -204,11 +206,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -225,11 +230,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -245,6 +251,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -254,7 +261,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/random/random_plugin.c b/src/libstrongswan/plugins/random/random_plugin.c
index 7f81e2622..cef20047a 100644
--- a/src/libstrongswan/plugins/random/random_plugin.c
+++ b/src/libstrongswan/plugins/random/random_plugin.c
@@ -15,9 +15,24 @@
#include "random_plugin.h"
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
#include <library.h>
+#include <debug.h>
#include "random_rng.h"
+#ifndef DEV_RANDOM
+# define DEV_RANDOM "/dev/random"
+#endif
+
+#ifndef DEV_URANDOM
+# define DEV_URANDOM "/dev/urandom"
+#endif
+
typedef struct private_random_plugin_t private_random_plugin_t;
/**
@@ -31,6 +46,41 @@ struct private_random_plugin_t {
random_plugin_t public;
};
+/** /dev/random file descriptor */
+static int dev_random = -1;
+/** /dev/urandom file descriptor */
+static int dev_urandom = -1;
+
+/**
+ * See header.
+ */
+int random_plugin_get_dev_random()
+{
+ return dev_random;
+}
+
+/**
+ * See header.
+ */
+int random_plugin_get_dev_urandom()
+{
+ return dev_urandom;
+}
+
+/**
+ * Open a random device file
+ */
+static bool open_dev(char *file, int *fd)
+{
+ *fd = open(file, O_RDONLY);
+ if (*fd == -1)
+ {
+ DBG1(DBG_LIB, "opening \"%s\" failed: %s", file, strerror(errno));
+ return FALSE;
+ }
+ return TRUE;
+}
+
METHOD(plugin_t, get_name, char*,
private_random_plugin_t *this)
{
@@ -52,6 +102,14 @@ METHOD(plugin_t, get_features, int,
METHOD(plugin_t, destroy, void,
private_random_plugin_t *this)
{
+ if (dev_random != -1)
+ {
+ close(dev_random);
+ }
+ if (dev_urandom != -1)
+ {
+ close(dev_urandom);
+ }
free(this);
}
@@ -61,6 +119,7 @@ METHOD(plugin_t, destroy, void,
plugin_t *random_plugin_create()
{
private_random_plugin_t *this;
+ char *urandom_file, *random_file;
INIT(this,
.public = {
@@ -72,6 +131,17 @@ plugin_t *random_plugin_create()
},
);
+ urandom_file = lib->settings->get_str(lib->settings,
+ "libstrongswan.plugins.random.urandom", DEV_URANDOM);
+ random_file = lib->settings->get_str(lib->settings,
+ "libstrongswan.plugins.random.random", DEV_RANDOM);
+ if (!open_dev(urandom_file, &dev_urandom) ||
+ !open_dev(random_file, &dev_random))
+ {
+ destroy(this);
+ return NULL;
+ }
+
return &this->public.plugin;
}
diff --git a/src/libstrongswan/plugins/random/random_plugin.h b/src/libstrongswan/plugins/random/random_plugin.h
index 7e22c3e5f..c34fa8196 100644
--- a/src/libstrongswan/plugins/random/random_plugin.h
+++ b/src/libstrongswan/plugins/random/random_plugin.h
@@ -39,4 +39,14 @@ struct random_plugin_t {
plugin_t plugin;
};
+/**
+ * Get the /dev/random file descriptor
+ */
+int random_plugin_get_dev_random();
+
+/**
+ * Get the /dev/urandom file descriptor
+ */
+int random_plugin_get_dev_urandom();
+
#endif /** RANDOM_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/random/random_rng.c b/src/libstrongswan/plugins/random/random_rng.c
index 1d99a63d5..52cfc080e 100644
--- a/src/libstrongswan/plugins/random/random_rng.c
+++ b/src/libstrongswan/plugins/random/random_rng.c
@@ -15,22 +15,12 @@
*/
#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <debug.h>
#include "random_rng.h"
-
-#ifndef DEV_RANDOM
-# define DEV_RANDOM "/dev/random"
-#endif
-
-#ifndef DEV_URANDOM
-# define DEV_URANDOM "/dev/urandom"
-#endif
+#include "random_plugin.h"
typedef struct private_random_rng_t private_random_rng_t;
@@ -47,15 +37,10 @@ struct private_random_rng_t {
/**
* random device, depends on quality
*/
- int dev;
-
- /**
- * file we read random bytes from
- */
- char *file;
+ int fd;
};
-METHOD(rng_t, get_bytes, void,
+METHOD(rng_t, get_bytes, bool,
private_random_rng_t *this, size_t bytes, u_int8_t *buffer)
{
size_t done;
@@ -65,30 +50,29 @@ METHOD(rng_t, get_bytes, void,
while (done < bytes)
{
- got = read(this->dev, buffer + done, bytes - done);
+ got = read(this->fd, buffer + done, bytes - done);
if (got <= 0)
{
- DBG1(DBG_LIB, "reading from \"%s\" failed: %s, retrying...",
- this->file, strerror(errno));
- close(this->dev);
+ DBG1(DBG_LIB, "reading from random FD %d failed: %s, retrying...",
+ this->fd, strerror(errno));
sleep(1);
- this->dev = open(this->file, 0);
}
done += got;
}
+ return TRUE;
}
-METHOD(rng_t, allocate_bytes, void,
+METHOD(rng_t, allocate_bytes, bool,
private_random_rng_t *this, size_t bytes, chunk_t *chunk)
{
*chunk = chunk_alloc(bytes);
get_bytes(this, chunk->len, chunk->ptr);
+ return TRUE;
}
METHOD(rng_t, destroy, void,
private_random_rng_t *this)
{
- close(this->dev);
free(this);
}
@@ -109,22 +93,18 @@ random_rng_t *random_rng_create(rng_quality_t quality)
},
);
- if (quality == RNG_TRUE)
+ switch (quality)
{
- this->file = DEV_RANDOM;
- }
- else
- {
- this->file = DEV_URANDOM;
+ case RNG_TRUE:
+ this->fd = random_plugin_get_dev_random();
+ break;
+ case RNG_STRONG:
+ case RNG_WEAK:
+ default:
+ this->fd = random_plugin_get_dev_urandom();
+ break;
}
- this->dev = open(this->file, 0);
- if (this->dev < 0)
- {
- DBG1(DBG_LIB, "opening \"%s\" failed: %s", this->file, strerror(errno));
- free(this);
- return NULL;
- }
return &this->public;
}
diff --git a/src/libstrongswan/plugins/revocation/Makefile.in b/src/libstrongswan/plugins/revocation/Makefile.in
index a78762c82..e2cbbbbe0 100644
--- a/src/libstrongswan/plugins/revocation/Makefile.in
+++ b/src/libstrongswan/plugins/revocation/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -86,7 +87,7 @@ libstrongswan_revocation_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_revocation_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_revocation_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -112,6 +113,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -206,11 +208,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -227,11 +232,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -247,6 +253,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -256,7 +263,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/revocation/revocation_validator.c b/src/libstrongswan/plugins/revocation/revocation_validator.c
index 34f347d1a..dc8e454e7 100644
--- a/src/libstrongswan/plugins/revocation/revocation_validator.c
+++ b/src/libstrongswan/plugins/revocation/revocation_validator.c
@@ -103,7 +103,7 @@ static bool verify_ocsp(ocsp_response_t *response, auth_cfg_t *auth)
bool verified = FALSE;
wrapper = ocsp_response_wrapper_create((ocsp_response_t*)response);
- lib->credmgr->add_local_set(lib->credmgr, &wrapper->set);
+ lib->credmgr->add_local_set(lib->credmgr, &wrapper->set, FALSE);
subject = &response->certificate;
responder = subject->get_issuer(subject);
@@ -111,7 +111,7 @@ static bool verify_ocsp(ocsp_response_t *response, auth_cfg_t *auth)
KEY_ANY, responder, FALSE);
while (enumerator->enumerate(enumerator, &issuer, &current))
{
- if (lib->credmgr->issued_by(lib->credmgr, subject, issuer))
+ if (lib->credmgr->issued_by(lib->credmgr, subject, issuer, NULL))
{
DBG1(DBG_CFG, " ocsp response correctly signed by \"%Y\"",
issuer->get_subject(issuer));
@@ -341,7 +341,7 @@ static bool verify_crl(certificate_t *crl, auth_cfg_t *auth)
KEY_ANY, crl->get_issuer(crl), FALSE);
while (enumerator->enumerate(enumerator, &issuer, &current))
{
- if (lib->credmgr->issued_by(lib->credmgr, crl, issuer))
+ if (lib->credmgr->issued_by(lib->credmgr, crl, issuer, NULL))
{
DBG1(DBG_CFG, " crl correctly signed by \"%Y\"",
issuer->get_subject(issuer));
diff --git a/src/libstrongswan/plugins/sha1/Makefile.in b/src/libstrongswan/plugins/sha1/Makefile.in
index f59c7516d..5188c3fbf 100644
--- a/src/libstrongswan/plugins/sha1/Makefile.in
+++ b/src/libstrongswan/plugins/sha1/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -83,7 +84,7 @@ libstrongswan_sha1_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(libstrongswan_sha1_la_LDFLAGS) $(LDFLAGS) -o $@
@MONOLITHIC_FALSE@am_libstrongswan_sha1_la_rpath = -rpath $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_sha1_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -109,6 +110,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -203,11 +205,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -224,11 +229,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -244,6 +250,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -253,7 +260,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/sha1/sha1_hasher.c b/src/libstrongswan/plugins/sha1/sha1_hasher.c
index 4d69ad5a4..b0efbae7d 100644
--- a/src/libstrongswan/plugins/sha1/sha1_hasher.c
+++ b/src/libstrongswan/plugins/sha1/sha1_hasher.c
@@ -175,7 +175,7 @@ static void SHA1Final(private_sha1_hasher_t *this, u_int8_t *digest)
}
}
-METHOD(hasher_t, reset, void,
+METHOD(hasher_t, reset, bool,
private_sha1_hasher_t *this)
{
this->state[0] = 0x67452301;
@@ -185,9 +185,11 @@ METHOD(hasher_t, reset, void,
this->state[4] = 0xC3D2E1F0;
this->count[0] = 0;
this->count[1] = 0;
+
+ return TRUE;
}
-METHOD(hasher_t, get_hash, void,
+METHOD(hasher_t, get_hash, bool,
private_sha1_hasher_t *this, chunk_t chunk, u_int8_t *buffer)
{
SHA1Update(this, chunk.ptr, chunk.len);
@@ -196,9 +198,10 @@ METHOD(hasher_t, get_hash, void,
SHA1Final(this, buffer);
reset(this);
}
+ return TRUE;
}
-METHOD(hasher_t, allocate_hash, void,
+METHOD(hasher_t, allocate_hash, bool,
private_sha1_hasher_t *this, chunk_t chunk, chunk_t *hash)
{
SHA1Update(this, chunk.ptr, chunk.len);
@@ -210,6 +213,7 @@ METHOD(hasher_t, allocate_hash, void,
SHA1Final(this, hash->ptr);
reset(this);
}
+ return TRUE;
}
METHOD(hasher_t, get_hash_size, size_t,
diff --git a/src/libstrongswan/plugins/sha1/sha1_prf.c b/src/libstrongswan/plugins/sha1/sha1_prf.c
index 11f588c9d..cdc494b34 100644
--- a/src/libstrongswan/plugins/sha1/sha1_prf.c
+++ b/src/libstrongswan/plugins/sha1/sha1_prf.c
@@ -59,7 +59,7 @@ struct private_sha1_prf_t {
*/
extern void SHA1Update(private_sha1_hasher_t* this, u_int8_t *data, u_int32_t len);
-METHOD(prf_t, get_bytes, void,
+METHOD(prf_t, get_bytes, bool,
private_sha1_prf_t *this, chunk_t seed, u_int8_t *bytes)
{
u_int32_t *hash = (u_int32_t*)bytes;
@@ -71,6 +71,8 @@ METHOD(prf_t, get_bytes, void,
hash[2] = htonl(this->hasher->state[2]);
hash[3] = htonl(this->hasher->state[3]);
hash[4] = htonl(this->hasher->state[4]);
+
+ return TRUE;
}
METHOD(prf_t, get_block_size, size_t,
@@ -79,11 +81,11 @@ METHOD(prf_t, get_block_size, size_t,
return HASH_SIZE_SHA1;
}
-METHOD(prf_t, allocate_bytes, void,
+METHOD(prf_t, allocate_bytes, bool,
private_sha1_prf_t *this, chunk_t seed, chunk_t *chunk)
{
*chunk = chunk_alloc(HASH_SIZE_SHA1);
- get_bytes(this, seed, chunk->ptr);
+ return get_bytes(this, seed, chunk->ptr);
}
METHOD(prf_t, get_key_size, size_t,
@@ -92,18 +94,23 @@ METHOD(prf_t, get_key_size, size_t,
return sizeof(this->hasher->state);
}
-METHOD(prf_t, set_key, void,
+METHOD(prf_t, set_key, bool,
private_sha1_prf_t *this, chunk_t key)
{
int i, rounds;
u_int32_t *iv = (u_int32_t*)key.ptr;
- this->hasher->public.hasher_interface.reset(&this->hasher->public.hasher_interface);
+ if (!this->hasher->public.hasher_interface.reset(
+ &this->hasher->public.hasher_interface))
+ {
+ return FALSE;
+ }
rounds = min(key.len/sizeof(u_int32_t), sizeof(this->hasher->state));
for (i = 0; i < rounds; i++)
{
this->hasher->state[i] ^= htonl(iv[i]);
}
+ return TRUE;
}
METHOD(prf_t, destroy, void,
diff --git a/src/libstrongswan/plugins/sha2/Makefile.in b/src/libstrongswan/plugins/sha2/Makefile.in
index c99f30e43..adf7d10b4 100644
--- a/src/libstrongswan/plugins/sha2/Makefile.in
+++ b/src/libstrongswan/plugins/sha2/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -82,7 +83,7 @@ libstrongswan_sha2_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(libstrongswan_sha2_la_LDFLAGS) $(LDFLAGS) -o $@
@MONOLITHIC_FALSE@am_libstrongswan_sha2_la_rpath = -rpath $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_sha2_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -108,6 +109,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -202,11 +204,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -223,11 +228,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -243,6 +249,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -252,7 +259,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/sha2/sha2_hasher.c b/src/libstrongswan/plugins/sha2/sha2_hasher.c
index 60fe4bd20..1c6dd2533 100644
--- a/src/libstrongswan/plugins/sha2/sha2_hasher.c
+++ b/src/libstrongswan/plugins/sha2/sha2_hasher.c
@@ -426,41 +426,49 @@ static void sha512_final(private_sha512_hasher_t *ctx)
} while(++j < 8);
}
-METHOD(hasher_t, reset224, void,
+METHOD(hasher_t, reset224, bool,
private_sha256_hasher_t *this)
{
memcpy(&this->sha_H[0], &sha224_hashInit[0], sizeof(this->sha_H));
this->sha_blocks = 0;
this->sha_bufCnt = 0;
+
+ return TRUE;
}
-METHOD(hasher_t, reset256, void,
+METHOD(hasher_t, reset256, bool,
private_sha256_hasher_t *this)
{
memcpy(&this->sha_H[0], &sha256_hashInit[0], sizeof(this->sha_H));
this->sha_blocks = 0;
this->sha_bufCnt = 0;
+
+ return TRUE;
}
-METHOD(hasher_t, reset384, void,
+METHOD(hasher_t, reset384, bool,
private_sha512_hasher_t *this)
{
memcpy(&this->sha_H[0], &sha384_hashInit[0], sizeof(this->sha_H));
this->sha_blocks = 0;
this->sha_blocksMSB = 0;
this->sha_bufCnt = 0;
+
+ return TRUE;
}
-METHOD(hasher_t, reset512, void,
+METHOD(hasher_t, reset512, bool,
private_sha512_hasher_t *this)
{
memcpy(&this->sha_H[0], &sha512_hashInit[0], sizeof(this->sha_H));
this->sha_blocks = 0;
this->sha_blocksMSB = 0;
this->sha_bufCnt = 0;
+
+ return TRUE;
}
-METHOD(hasher_t, get_hash224, void,
+METHOD(hasher_t, get_hash224, bool,
private_sha256_hasher_t *this, chunk_t chunk, u_int8_t *buffer)
{
sha256_write(this, chunk.ptr, chunk.len);
@@ -470,9 +478,10 @@ METHOD(hasher_t, get_hash224, void,
memcpy(buffer, this->sha_out, HASH_SIZE_SHA224);
reset224(this);
}
+ return TRUE;
}
-METHOD(hasher_t, get_hash256, void,
+METHOD(hasher_t, get_hash256, bool,
private_sha256_hasher_t *this, chunk_t chunk, u_int8_t *buffer)
{
sha256_write(this, chunk.ptr, chunk.len);
@@ -482,9 +491,10 @@ METHOD(hasher_t, get_hash256, void,
memcpy(buffer, this->sha_out, HASH_SIZE_SHA256);
reset256(this);
}
+ return TRUE;
}
-METHOD(hasher_t, get_hash384, void,
+METHOD(hasher_t, get_hash384, bool,
private_sha512_hasher_t *this, chunk_t chunk, u_int8_t *buffer)
{
sha512_write(this, chunk.ptr, chunk.len);
@@ -494,9 +504,10 @@ METHOD(hasher_t, get_hash384, void,
memcpy(buffer, this->sha_out, HASH_SIZE_SHA384);
reset384(this);
}
+ return TRUE;
}
-METHOD(hasher_t, get_hash512, void,
+METHOD(hasher_t, get_hash512, bool,
private_sha512_hasher_t *this, chunk_t chunk, u_int8_t *buffer)
{
sha512_write(this, chunk.ptr, chunk.len);
@@ -506,9 +517,10 @@ METHOD(hasher_t, get_hash512, void,
memcpy(buffer, this->sha_out, HASH_SIZE_SHA512);
reset512(this);
}
+ return TRUE;
}
-METHOD(hasher_t, allocate_hash224, void,
+METHOD(hasher_t, allocate_hash224, bool,
private_sha256_hasher_t *this, chunk_t chunk, chunk_t *hash)
{
chunk_t allocated_hash;
@@ -522,9 +534,10 @@ METHOD(hasher_t, allocate_hash224, void,
reset224(this);
*hash = allocated_hash;
}
+ return TRUE;
}
-METHOD(hasher_t, allocate_hash256, void,
+METHOD(hasher_t, allocate_hash256, bool,
private_sha256_hasher_t *this, chunk_t chunk, chunk_t *hash)
{
chunk_t allocated_hash;
@@ -538,9 +551,10 @@ METHOD(hasher_t, allocate_hash256, void,
reset256(this);
*hash = allocated_hash;
}
+ return TRUE;
}
-METHOD(hasher_t, allocate_hash384, void,
+METHOD(hasher_t, allocate_hash384, bool,
private_sha512_hasher_t *this, chunk_t chunk, chunk_t *hash)
{
chunk_t allocated_hash;
@@ -554,9 +568,10 @@ METHOD(hasher_t, allocate_hash384, void,
reset384(this);
*hash = allocated_hash;
}
+ return TRUE;
}
-METHOD(hasher_t, allocate_hash512, void,
+METHOD(hasher_t, allocate_hash512, bool,
private_sha512_hasher_t *this, chunk_t chunk, chunk_t *hash)
{
chunk_t allocated_hash;
@@ -570,6 +585,7 @@ METHOD(hasher_t, allocate_hash512, void,
reset512(this);
*hash = allocated_hash;
}
+ return TRUE;
}
METHOD(hasher_t, get_hash_size224, size_t,
diff --git a/src/libstrongswan/plugins/soup/Makefile.in b/src/libstrongswan/plugins/soup/Makefile.in
index ce4b07769..5ab3f94aa 100644
--- a/src/libstrongswan/plugins/soup/Makefile.in
+++ b/src/libstrongswan/plugins/soup/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -83,7 +84,7 @@ libstrongswan_soup_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(libstrongswan_soup_la_LDFLAGS) $(LDFLAGS) -o $@
@MONOLITHIC_FALSE@am_libstrongswan_soup_la_rpath = -rpath $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_soup_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -109,6 +110,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -203,11 +205,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -224,11 +229,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -244,6 +250,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -253,7 +260,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/sqlite/Makefile.in b/src/libstrongswan/plugins/sqlite/Makefile.in
index 391827724..f13540edb 100644
--- a/src/libstrongswan/plugins/sqlite/Makefile.in
+++ b/src/libstrongswan/plugins/sqlite/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -85,7 +86,7 @@ libstrongswan_sqlite_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@MONOLITHIC_FALSE@am_libstrongswan_sqlite_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_sqlite_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -111,6 +112,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -205,11 +207,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -226,11 +231,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -246,6 +252,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -255,7 +262,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/sqlite/sqlite_database.c b/src/libstrongswan/plugins/sqlite/sqlite_database.c
index f9e06199e..0fb3c7fff 100644
--- a/src/libstrongswan/plugins/sqlite/sqlite_database.c
+++ b/src/libstrongswan/plugins/sqlite/sqlite_database.c
@@ -206,6 +206,7 @@ static bool sqlite_enumerator_enumerate(sqlite_enumerator_t *this, ...)
}
default:
DBG1(DBG_LIB, "invalid result type supplied");
+ va_end(args);
return FALSE;
}
}
diff --git a/src/libstrongswan/plugins/test_vectors/Makefile.in b/src/libstrongswan/plugins/test_vectors/Makefile.in
index 7e0271b13..f717ad6d9 100644
--- a/src/libstrongswan/plugins/test_vectors/Makefile.in
+++ b/src/libstrongswan/plugins/test_vectors/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -91,7 +92,7 @@ libstrongswan_test_vectors_la_LINK = $(LIBTOOL) --tag=CC \
@MONOLITHIC_FALSE@am_libstrongswan_test_vectors_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_test_vectors_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -117,6 +118,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -211,11 +213,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -232,11 +237,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -252,6 +258,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -261,7 +268,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/test_vectors/test_vectors.h b/src/libstrongswan/plugins/test_vectors/test_vectors.h
index 40fb51da6..a00469779 100644
--- a/src/libstrongswan/plugins/test_vectors/test_vectors.h
+++ b/src/libstrongswan/plugins/test_vectors/test_vectors.h
@@ -140,6 +140,7 @@ TEST_VECTOR_HASHER(md5_7)
TEST_VECTOR_HASHER(sha1_1)
TEST_VECTOR_HASHER(sha1_2)
TEST_VECTOR_HASHER(sha1_3)
+TEST_VECTOR_HASHER(sha1_4)
TEST_VECTOR_HASHER(sha224_1)
TEST_VECTOR_HASHER(sha224_2)
TEST_VECTOR_HASHER(sha224_3)
diff --git a/src/libstrongswan/plugins/test_vectors/test_vectors/sha1.c b/src/libstrongswan/plugins/test_vectors/test_vectors/sha1.c
index 51f22716e..669adf8c6 100644
--- a/src/libstrongswan/plugins/test_vectors/test_vectors/sha1.c
+++ b/src/libstrongswan/plugins/test_vectors/test_vectors/sha1.c
@@ -49,3 +49,9 @@ hasher_test_vector_t sha1_3 = {
"\x2b\xad\x27\xb3"
};
+hasher_test_vector_t sha1_4 = {
+ .alg = HASH_SHA1, .len = 62,
+ .data = "12345678901234567890123456789012345678901234567890123456789012",
+ .hash = "\xd8\xd0\x73\xb3\x83\x15\x66\x17\xc5\xca\xdf\x17\xf6\x15\x96\xa3"
+ "\x84\x0a\xfd\x8b"
+};
diff --git a/src/libstrongswan/plugins/x509/Makefile.in b/src/libstrongswan/plugins/x509/Makefile.in
index 8c05cb22d..6d9f88647 100644
--- a/src/libstrongswan/plugins/x509/Makefile.in
+++ b/src/libstrongswan/plugins/x509/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -84,7 +85,7 @@ libstrongswan_x509_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(libstrongswan_x509_la_LDFLAGS) $(LDFLAGS) -o $@
@MONOLITHIC_FALSE@am_libstrongswan_x509_la_rpath = -rpath $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_x509_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -110,6 +111,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -204,11 +206,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -225,11 +230,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -245,6 +251,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -254,7 +261,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libstrongswan/plugins/x509/x509_ac.c b/src/libstrongswan/plugins/x509/x509_ac.c
index a2cb589e0..d6ca8c4fa 100644
--- a/src/libstrongswan/plugins/x509/x509_ac.c
+++ b/src/libstrongswan/plugins/x509/x509_ac.c
@@ -701,7 +701,7 @@ METHOD(certificate_t, has_issuer, id_match_t,
}
METHOD(certificate_t, issued_by, bool,
- private_x509_ac_t *this, certificate_t *issuer)
+ private_x509_ac_t *this, certificate_t *issuer, signature_scheme_t *schemep)
{
public_key_t *key;
signature_scheme_t scheme;
@@ -750,6 +750,10 @@ METHOD(certificate_t, issued_by, bool,
}
valid = key->verify(key, scheme, this->certificateInfo, this->signature);
key->destroy(key);
+ if (valid && schemep)
+ {
+ *schemep = scheme;
+ }
return valid;
}
diff --git a/src/libstrongswan/plugins/x509/x509_cert.c b/src/libstrongswan/plugins/x509/x509_cert.c
index 4859f4310..2269eb453 100644
--- a/src/libstrongswan/plugins/x509/x509_cert.c
+++ b/src/libstrongswan/plugins/x509/x509_cert.c
@@ -752,6 +752,9 @@ static void parse_extendedKeyUsage(chunk_t blob, int level0,
case OID_CLIENT_AUTH:
this->flags |= X509_CLIENT_AUTH;
break;
+ case OID_IKE_INTERMEDIATE:
+ this->flags |= X509_IKE_INTERMEDIATE;
+ break;
case OID_OCSP_SIGNING:
this->flags |= X509_OCSP_SIGNER;
break;
@@ -1105,19 +1108,19 @@ static void parse_policyConstraints(chunk_t blob, int level0,
* ASN.1 definition of ipAddrBlocks according to RFC 3779
*/
static const asn1Object_t ipAddrBlocksObjects[] = {
- { 0, "ipAddrBlocks", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
+ { 0, "ipAddrBlocks", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
{ 1, "ipAddressFamily", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */
- { 2, "addressFamily", ASN1_OCTET_STRING, ASN1_BODY }, /* 2 */
- { 2, "inherit", ASN1_NULL, ASN1_OPT|ASN1_NONE }, /* 3 */
- { 2, "end choice", ASN1_EOC, ASN1_END }, /* 4 */
- { 2, "addressesOrRanges", ASN1_SEQUENCE, ASN1_OPT|ASN1_LOOP }, /* 5 */
- { 3, "addressPrefix", ASN1_BIT_STRING, ASN1_OPT|ASN1_BODY }, /* 6 */
- { 3, "end choice", ASN1_EOC, ASN1_END }, /* 7 */
- { 3, "addressRange", ASN1_SEQUENCE, ASN1_OPT|ASN1_NONE }, /* 8 */
- { 4, "min", ASN1_BIT_STRING, ASN1_BODY }, /* 9 */
- { 4, "max", ASN1_BIT_STRING, ASN1_BODY }, /* 10 */
- { 3, "end choice", ASN1_EOC, ASN1_END }, /* 11 */
- { 2, "end opt/loop", ASN1_EOC, ASN1_END }, /* 12 */
+ { 2, "addressFamily", ASN1_OCTET_STRING, ASN1_BODY }, /* 2 */
+ { 2, "inherit", ASN1_NULL, ASN1_OPT|ASN1_NONE }, /* 3 */
+ { 2, "end choice", ASN1_EOC, ASN1_END }, /* 4 */
+ { 2, "addressesOrRanges", ASN1_SEQUENCE, ASN1_OPT|ASN1_LOOP }, /* 5 */
+ { 3, "addressPrefix", ASN1_BIT_STRING, ASN1_OPT|ASN1_BODY }, /* 6 */
+ { 3, "end choice", ASN1_EOC, ASN1_END }, /* 7 */
+ { 3, "addressRange", ASN1_SEQUENCE, ASN1_OPT|ASN1_NONE }, /* 8 */
+ { 4, "min", ASN1_BIT_STRING, ASN1_BODY }, /* 9 */
+ { 4, "max", ASN1_BIT_STRING, ASN1_BODY }, /* 10 */
+ { 3, "end choice", ASN1_EOC, ASN1_END }, /* 11 */
+ { 2, "end opt/loop", ASN1_EOC, ASN1_END }, /* 12 */
{ 0, "end loop", ASN1_EOC, ASN1_END }, /* 13 */
{ 0, "exit", ASN1_EOC, ASN1_EXIT }
};
@@ -1480,18 +1483,20 @@ end:
/* check if the certificate is self-signed */
if (this->public.interface.interface.issued_by(
&this->public.interface.interface,
- &this->public.interface.interface))
+ &this->public.interface.interface,
+ NULL))
{
this->flags |= X509_SELF_SIGNED;
}
/* create certificate hash */
hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
- if (hasher == NULL)
+ if (!hasher ||
+ !hasher->allocate_hash(hasher, this->encoding, &this->encoding_hash))
{
+ DESTROY_IF(hasher);
DBG1(DBG_ASN, " unable to create hash of certificate, SHA1 not supported");
return FALSE;
}
- hasher->allocate_hash(hasher, this->encoding, &this->encoding_hash);
hasher->destroy(hasher);
}
return success;
@@ -1565,7 +1570,8 @@ METHOD(certificate_t, has_issuer, id_match_t,
}
METHOD(certificate_t, issued_by, bool,
- private_x509_cert_t *this, certificate_t *issuer)
+ private_x509_cert_t *this, certificate_t *issuer,
+ signature_scheme_t *schemep)
{
public_key_t *key;
signature_scheme_t scheme;
@@ -1609,6 +1615,10 @@ METHOD(certificate_t, issued_by, bool,
}
valid = key->verify(key, scheme, this->tbsCertificate, this->signature);
key->destroy(key);
+ if (valid && schemep)
+ {
+ *schemep = scheme;
+ }
return valid;
}
@@ -1994,6 +2004,7 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert,
chunk_t subjectKeyIdentifier = chunk_empty, authKeyIdentifier = chunk_empty;
chunk_t crlDistributionPoints = chunk_empty, authorityInfoAccess = chunk_empty;
chunk_t policyConstraints = chunk_empty, inhibitAnyPolicy = chunk_empty;
+ chunk_t ikeIntermediate = chunk_empty;
identification_t *issuer, *subject;
chunk_t key_info;
signature_scheme_t scheme;
@@ -2107,7 +2118,7 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert,
asn1_wrap(ASN1_BIT_STRING, "c", keyUsageBits)));
}
- /* add serverAuth extendedKeyUsage flag */
+ /* add extendedKeyUsage flags */
if (cert->flags & X509_SERVER_AUTH)
{
serverAuth = asn1_build_known_oid(OID_SERVER_AUTH);
@@ -2116,20 +2127,24 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert,
{
clientAuth = asn1_build_known_oid(OID_CLIENT_AUTH);
}
-
- /* add ocspSigning extendedKeyUsage flag */
+ if (cert->flags & X509_IKE_INTERMEDIATE)
+ {
+ ikeIntermediate = asn1_build_known_oid(OID_IKE_INTERMEDIATE);
+ }
if (cert->flags & X509_OCSP_SIGNER)
{
ocspSigning = asn1_build_known_oid(OID_OCSP_SIGNING);
}
- if (serverAuth.ptr || clientAuth.ptr || ocspSigning.ptr)
+ if (serverAuth.ptr || clientAuth.ptr || ikeIntermediate.ptr ||
+ ocspSigning.ptr)
{
extendedKeyUsage = asn1_wrap(ASN1_SEQUENCE, "mm",
asn1_build_known_oid(OID_EXTENDED_KEY_USAGE),
asn1_wrap(ASN1_OCTET_STRING, "m",
- asn1_wrap(ASN1_SEQUENCE, "mmm",
- serverAuth, clientAuth, ocspSigning)));
+ asn1_wrap(ASN1_SEQUENCE, "mmmm",
+ serverAuth, clientAuth, ikeIntermediate,
+ ocspSigning)));
}
/* add subjectKeyIdentifier to CA and OCSP signer certificates */
@@ -2330,11 +2345,12 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert,
asn1_bitstring("c", cert->signature));
hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
- if (!hasher)
+ if (!hasher ||
+ !hasher->allocate_hash(hasher, cert->encoding, &cert->encoding_hash))
{
+ DESTROY_IF(hasher);
return FALSE;
}
- hasher->allocate_hash(hasher, cert->encoding, &cert->encoding_hash);
hasher->destroy(hasher);
return TRUE;
}
diff --git a/src/libstrongswan/plugins/x509/x509_crl.c b/src/libstrongswan/plugins/x509/x509_crl.c
index 7bcca16a3..47621103e 100644
--- a/src/libstrongswan/plugins/x509/x509_crl.c
+++ b/src/libstrongswan/plugins/x509/x509_crl.c
@@ -221,7 +221,7 @@ static bool parse(private_x509_crl_t *this)
{
asn1_parser_t *parser;
chunk_t object;
- chunk_t extnID;
+ chunk_t extnID = chunk_empty;
chunk_t userCertificate = chunk_empty;
int objectID;
int sig_alg = OID_UNKNOWN;
@@ -442,7 +442,7 @@ METHOD(certificate_t, has_issuer, id_match_t,
}
METHOD(certificate_t, issued_by, bool,
- private_x509_crl_t *this, certificate_t *issuer)
+ private_x509_crl_t *this, certificate_t *issuer, signature_scheme_t *schemep)
{
public_key_t *key;
signature_scheme_t scheme;
@@ -490,6 +490,10 @@ METHOD(certificate_t, issued_by, bool,
}
valid = key->verify(key, scheme, this->tbsCertList, this->signature);
key->destroy(key);
+ if (valid && schemep)
+ {
+ *schemep = scheme;
+ }
return valid;
}
diff --git a/src/libstrongswan/plugins/x509/x509_ocsp_request.c b/src/libstrongswan/plugins/x509/x509_ocsp_request.c
index 33d0aa792..bbd1c5905 100644
--- a/src/libstrongswan/plugins/x509/x509_ocsp_request.c
+++ b/src/libstrongswan/plugins/x509/x509_ocsp_request.c
@@ -159,22 +159,24 @@ static chunk_t build_requestList(private_x509_ocsp_request_t *this)
enumerator_t *enumerator;
issuer = cert->get_subject(cert);
- hasher->allocate_hash(hasher, issuer->get_encoding(issuer),
- &issuerNameHash);
- hasher->destroy(hasher);
-
- enumerator = this->candidates->create_enumerator(this->candidates);
- while (enumerator->enumerate(enumerator, &x509))
+ if (hasher->allocate_hash(hasher, issuer->get_encoding(issuer),
+ &issuerNameHash))
{
- chunk_t request, serialNumber;
-
- serialNumber = x509->get_serial(x509);
- request = build_Request(this, issuerNameHash, issuerKeyHash,
- serialNumber);
- list = chunk_cat("mm", list, request);
+ enumerator = this->candidates->create_enumerator(
+ this->candidates);
+ while (enumerator->enumerate(enumerator, &x509))
+ {
+ chunk_t request, serialNumber;
+
+ serialNumber = x509->get_serial(x509);
+ request = build_Request(this, issuerNameHash,
+ issuerKeyHash, serialNumber);
+ list = chunk_cat("mm", list, request);
+ }
+ enumerator->destroy(enumerator);
+ chunk_free(&issuerNameHash);
}
- enumerator->destroy(enumerator);
- chunk_free(&issuerNameHash);
+ hasher->destroy(hasher);
}
}
else
@@ -199,15 +201,15 @@ static chunk_t build_nonce(private_x509_ocsp_request_t *this)
rng_t *rng;
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
- if (rng)
+ if (!rng || !rng->allocate_bytes(rng, NONCE_LEN, &this->nonce))
{
- rng->allocate_bytes(rng, NONCE_LEN, &this->nonce);
- rng->destroy(rng);
- return asn1_wrap(ASN1_SEQUENCE, "cm", ASN1_nonce_oid,
- asn1_simple_object(ASN1_OCTET_STRING, this->nonce));
+ DBG1(DBG_LIB, "creating OCSP request nonce failed, no RNG found");
+ DESTROY_IF(rng);
+ return chunk_empty;
}
- DBG1(DBG_LIB, "creating OCSP request nonce failed, no RNG found");
- return chunk_empty;
+ rng->destroy(rng);
+ return asn1_wrap(ASN1_SEQUENCE, "cm", ASN1_nonce_oid,
+ asn1_simple_object(ASN1_OCTET_STRING, this->nonce));
}
/**
@@ -364,7 +366,8 @@ METHOD(certificate_t, has_issuer, id_match_t,
}
METHOD(certificate_t, issued_by, bool,
- private_x509_ocsp_request_t *this, certificate_t *issuer)
+ private_x509_ocsp_request_t *this, certificate_t *issuer,
+ signature_scheme_t *scheme)
{
DBG1(DBG_LIB, "OCSP request validation not implemented!");
return FALSE;
diff --git a/src/libstrongswan/plugins/x509/x509_ocsp_response.c b/src/libstrongswan/plugins/x509/x509_ocsp_response.c
index 7dfef3993..27497e0e3 100644
--- a/src/libstrongswan/plugins/x509/x509_ocsp_response.c
+++ b/src/libstrongswan/plugins/x509/x509_ocsp_response.c
@@ -201,19 +201,22 @@ METHOD(ocsp_response_t, get_status, cert_validation_t,
/* check issuerNameHash, if available */
else if (response->issuerNameHash.ptr)
{
+ id = issuercert->get_subject(issuercert);
hasher = lib->crypto->create_hasher(lib->crypto,
hasher_algorithm_from_oid(response->hashAlgorithm));
- if (!hasher)
+ if (!hasher ||
+ !hasher->allocate_hash(hasher, id->get_encoding(id), &hash))
{
+ DESTROY_IF(hasher);
continue;
}
- id = issuercert->get_subject(issuercert);
- hasher->allocate_hash(hasher, id->get_encoding(id), &hash);
hasher->destroy(hasher);
if (!chunk_equals(hash, response->issuerNameHash))
{
+ free(hash.ptr);
continue;
}
+ free(hash.ptr);
}
else
{
@@ -670,7 +673,8 @@ METHOD(certificate_t, has_issuer, id_match_t,
}
METHOD(certificate_t, issued_by, bool,
- private_x509_ocsp_response_t *this, certificate_t *issuer)
+ private_x509_ocsp_response_t *this, certificate_t *issuer,
+ signature_scheme_t *schemep)
{
public_key_t *key;
signature_scheme_t scheme;
@@ -722,6 +726,10 @@ METHOD(certificate_t, issued_by, bool,
}
valid = key->verify(key, scheme, this->tbsResponseData, this->signature);
key->destroy(key);
+ if (valid && schemep)
+ {
+ *schemep = scheme;
+ }
return valid;
}
diff --git a/src/libstrongswan/plugins/x509/x509_pkcs10.c b/src/libstrongswan/plugins/x509/x509_pkcs10.c
index ca08db2c6..9fa91fed2 100644
--- a/src/libstrongswan/plugins/x509/x509_pkcs10.c
+++ b/src/libstrongswan/plugins/x509/x509_pkcs10.c
@@ -123,10 +123,12 @@ METHOD(certificate_t, has_subject, id_match_t,
}
METHOD(certificate_t, issued_by, bool,
- private_x509_pkcs10_t *this, certificate_t *issuer)
+ private_x509_pkcs10_t *this, certificate_t *issuer,
+ signature_scheme_t *schemep)
{
public_key_t *key;
signature_scheme_t scheme;
+ bool valid;
if (&this->public.interface.interface != issuer)
{
@@ -150,8 +152,13 @@ METHOD(certificate_t, issued_by, bool,
{
return FALSE;
}
- return key->verify(key, scheme, this->certificationRequestInfo,
- this->signature);
+ valid = key->verify(key, scheme, this->certificationRequestInfo,
+ this->signature);
+ if (valid && schemep)
+ {
+ *schemep = scheme;
+ }
+ return valid;
}
METHOD(certificate_t, get_public_key, public_key_t*,
@@ -327,7 +334,7 @@ static bool parse_challengePassword(private_x509_pkcs10_t *this, chunk_t blob, i
return FALSE;
}
DBG2(DBG_ASN, "L%d - challengePassword:", level);
- DBG4(DBG_ASN, " '%.*s'", blob.len, blob.ptr);
+ DBG4(DBG_ASN, " '%.*s'", (int)blob.len, blob.ptr);
return TRUE;
}
@@ -441,7 +448,7 @@ end:
if (success)
{
/* check if the certificate request is self-signed */
- if (issued_by(this, &this->public.interface.interface))
+ if (issued_by(this, &this->public.interface.interface, NULL))
{
this->self_signed = TRUE;
}
diff --git a/src/libstrongswan/plugins/x509/x509_plugin.c b/src/libstrongswan/plugins/x509/x509_plugin.c
index ed6fbfd91..15fea7ee0 100644
--- a/src/libstrongswan/plugins/x509/x509_plugin.c
+++ b/src/libstrongswan/plugins/x509/x509_plugin.c
@@ -52,6 +52,9 @@ METHOD(plugin_t, get_features, int,
PLUGIN_REGISTER(CERT_DECODE, x509_cert_load, TRUE),
PLUGIN_PROVIDE(CERT_DECODE, CERT_X509),
PLUGIN_DEPENDS(HASHER, HASH_SHA1),
+ PLUGIN_SDEPEND(PUBKEY, KEY_RSA),
+ PLUGIN_SDEPEND(PUBKEY, KEY_ECDSA),
+ PLUGIN_SDEPEND(PUBKEY, KEY_DSA),
PLUGIN_REGISTER(CERT_ENCODE, x509_ac_gen, FALSE),
PLUGIN_PROVIDE(CERT_ENCODE, CERT_X509_AC),
diff --git a/src/libstrongswan/plugins/xcbc/Makefile.am b/src/libstrongswan/plugins/xcbc/Makefile.am
index 7de306832..28e99f650 100644
--- a/src/libstrongswan/plugins/xcbc/Makefile.am
+++ b/src/libstrongswan/plugins/xcbc/Makefile.am
@@ -10,7 +10,6 @@ plugin_LTLIBRARIES = libstrongswan-xcbc.la
endif
libstrongswan_xcbc_la_SOURCES = \
- xcbc_plugin.h xcbc_plugin.c xcbc.h xcbc.c \
- xcbc_prf.h xcbc_prf.c xcbc_signer.h xcbc_signer.c
+ xcbc_plugin.h xcbc_plugin.c xcbc.h xcbc.c
libstrongswan_xcbc_la_LDFLAGS = -module -avoid-version
diff --git a/src/libstrongswan/plugins/xcbc/Makefile.in b/src/libstrongswan/plugins/xcbc/Makefile.in
index ae23ce730..b4d0a2160 100644
--- a/src/libstrongswan/plugins/xcbc/Makefile.in
+++ b/src/libstrongswan/plugins/xcbc/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -75,15 +76,14 @@ am__base_list = \
am__installdirs = "$(DESTDIR)$(plugindir)"
LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_xcbc_la_LIBADD =
-am_libstrongswan_xcbc_la_OBJECTS = xcbc_plugin.lo xcbc.lo xcbc_prf.lo \
- xcbc_signer.lo
+am_libstrongswan_xcbc_la_OBJECTS = xcbc_plugin.lo xcbc.lo
libstrongswan_xcbc_la_OBJECTS = $(am_libstrongswan_xcbc_la_OBJECTS)
libstrongswan_xcbc_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libstrongswan_xcbc_la_LDFLAGS) $(LDFLAGS) -o $@
@MONOLITHIC_FALSE@am_libstrongswan_xcbc_la_rpath = -rpath $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_xcbc_la_rpath =
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -109,6 +109,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -203,11 +204,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -224,11 +228,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -244,6 +249,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -253,7 +259,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -286,8 +291,7 @@ AM_CFLAGS = -rdynamic
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-xcbc.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-xcbc.la
libstrongswan_xcbc_la_SOURCES = \
- xcbc_plugin.h xcbc_plugin.c xcbc.h xcbc.c \
- xcbc_prf.h xcbc_prf.c xcbc_signer.h xcbc_signer.c
+ xcbc_plugin.h xcbc_plugin.c xcbc.h xcbc.c
libstrongswan_xcbc_la_LDFLAGS = -module -avoid-version
all: all-am
@@ -375,8 +379,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xcbc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xcbc_plugin.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xcbc_prf.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xcbc_signer.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
diff --git a/src/libstrongswan/plugins/xcbc/xcbc.c b/src/libstrongswan/plugins/xcbc/xcbc.c
index 53629abe5..1bb7e640a 100644
--- a/src/libstrongswan/plugins/xcbc/xcbc.c
+++ b/src/libstrongswan/plugins/xcbc/xcbc.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -18,20 +19,23 @@
#include "xcbc.h"
#include <debug.h>
+#include <crypto/mac.h>
+#include <crypto/prfs/mac_prf.h>
+#include <crypto/signers/mac_signer.h>
-typedef struct private_xcbc_t private_xcbc_t;
+typedef struct private_mac_t private_mac_t;
/**
- * Private data of a xcbc_t object.
+ * Private data of a mac_t object.
*
* The variable names are the same as in the RFC.
*/
-struct private_xcbc_t {
+struct private_mac_t {
/**
- * Public xcbc_t interface.
+ * Public mac_t interface.
*/
- xcbc_t public;
+ mac_t public;
/**
* Block size, in bytes
@@ -77,7 +81,7 @@ struct private_xcbc_t {
/**
* xcbc supplied data, but do not run final operation
*/
-static void update(private_xcbc_t *this, chunk_t data)
+static bool update(private_mac_t *this, chunk_t data)
{
chunk_t iv;
@@ -90,7 +94,7 @@ static void update(private_xcbc_t *this, chunk_t data)
{ /* no complete block, just copy into remaining */
memcpy(this->remaining + this->remaining_bytes, data.ptr, data.len);
this->remaining_bytes += data.len;
- return;
+ return TRUE;
}
iv = chunk_alloca(this->b);
@@ -106,7 +110,10 @@ static void update(private_xcbc_t *this, chunk_t data)
this->b - this->remaining_bytes);
data = chunk_skip(data, this->b - this->remaining_bytes);
memxor(this->e, this->remaining, this->b);
- this->k1->encrypt(this->k1, chunk_create(this->e, this->b), iv, NULL);
+ if (!this->k1->encrypt(this->k1, chunk_create(this->e, this->b), iv, NULL))
+ {
+ return FALSE;
+ }
/* process blocks M[2] ... M[n-1] */
while (data.len > this->b)
@@ -114,18 +121,24 @@ static void update(private_xcbc_t *this, chunk_t data)
memcpy(this->remaining, data.ptr, this->b);
data = chunk_skip(data, this->b);
memxor(this->e, this->remaining, this->b);
- this->k1->encrypt(this->k1, chunk_create(this->e, this->b), iv, NULL);
+ if (!this->k1->encrypt(this->k1, chunk_create(this->e, this->b),
+ iv, NULL))
+ {
+ return FALSE;
+ }
}
/* store remaining bytes of block M[n] */
memcpy(this->remaining, data.ptr, data.len);
this->remaining_bytes = data.len;
+
+ return TRUE;
}
/**
* run last round, data is in this->e
*/
-static void final(private_xcbc_t *this, u_int8_t *out)
+static bool final(private_mac_t *this, u_int8_t *out)
{
chunk_t iv;
@@ -141,7 +154,6 @@ static void final(private_xcbc_t *this, u_int8_t *out)
*/
memxor(this->e, this->remaining, this->b);
memxor(this->e, this->k2, this->b);
- this->k1->encrypt(this->k1, chunk_create(this->e, this->b), iv, NULL);
}
else
{
@@ -164,7 +176,10 @@ static void final(private_xcbc_t *this, u_int8_t *out)
*/
memxor(this->e, this->remaining, this->b);
memxor(this->e, this->k3, this->b);
- this->k1->encrypt(this->k1, chunk_create(this->e, this->b), iv, NULL);
+ }
+ if (!this->k1->encrypt(this->k1, chunk_create(this->e, this->b), iv, NULL))
+ {
+ return FALSE;
}
memcpy(out, this->e, this->b);
@@ -173,28 +188,34 @@ static void final(private_xcbc_t *this, u_int8_t *out)
memset(this->e, 0, this->b);
this->remaining_bytes = 0;
this->zero = TRUE;
+
+ return TRUE;
}
-METHOD(xcbc_t, get_mac, void,
- private_xcbc_t *this, chunk_t data, u_int8_t *out)
+METHOD(mac_t, get_mac, bool,
+ private_mac_t *this, chunk_t data, u_int8_t *out)
{
/* update E, do not process last block */
- update(this, data);
+ if (!update(this, data))
+ {
+ return FALSE;
+ }
if (out)
{ /* if not in append mode, process last block and output result */
- final(this, out);
+ return final(this, out);
}
+ return TRUE;
}
-METHOD(xcbc_t, get_block_size, size_t,
- private_xcbc_t *this)
+METHOD(mac_t, get_mac_size, size_t,
+ private_mac_t *this)
{
return this->b;
}
-METHOD(xcbc_t, set_key, void,
- private_xcbc_t *this, chunk_t key)
+METHOD(mac_t, set_key, bool,
+ private_mac_t *this, chunk_t key)
{
chunk_t iv, k1, lengthened;
@@ -213,8 +234,11 @@ METHOD(xcbc_t, set_key, void,
{ /* shorten key using xcbc */
lengthened = chunk_alloca(this->b);
memset(lengthened.ptr, 0, lengthened.len);
- set_key(this, lengthened);
- get_mac(this, key, lengthened.ptr);
+ if (!set_key(this, lengthened) ||
+ !get_mac(this, key, lengthened.ptr))
+ {
+ return FALSE;
+ }
}
k1 = chunk_alloca(this->b);
@@ -228,20 +252,26 @@ METHOD(xcbc_t, set_key, void,
* K2 = 0x02020202020202020202020202020202 encrypted with Key K
* K3 = 0x03030303030303030303030303030303 encrypted with Key K
*/
- this->k1->set_key(this->k1, lengthened);
+
+ memset(k1.ptr, 0x01, this->b);
memset(this->k2, 0x02, this->b);
- this->k1->encrypt(this->k1, chunk_create(this->k2, this->b), iv, NULL);
memset(this->k3, 0x03, this->b);
- this->k1->encrypt(this->k1, chunk_create(this->k3, this->b), iv, NULL);
- memset(k1.ptr, 0x01, this->b);
- this->k1->encrypt(this->k1, k1, iv, NULL);
- this->k1->set_key(this->k1, k1);
+ if (!this->k1->set_key(this->k1, lengthened) ||
+ !this->k1->encrypt(this->k1, chunk_create(this->k2, this->b), iv, NULL) ||
+ !this->k1->encrypt(this->k1, chunk_create(this->k3, this->b), iv, NULL) ||
+ !this->k1->encrypt(this->k1, k1, iv, NULL) ||
+ !this->k1->set_key(this->k1, k1))
+ {
+ memwipe(k1.ptr, k1.len);
+ return FALSE;
+ }
memwipe(k1.ptr, k1.len);
+ return TRUE;
}
-METHOD(xcbc_t, destroy, void,
- private_xcbc_t *this)
+METHOD(mac_t, destroy, void,
+ private_mac_t *this)
{
this->k1->destroy(this->k1);
memwipe(this->k2, this->b);
@@ -256,9 +286,9 @@ METHOD(xcbc_t, destroy, void,
/*
* Described in header
*/
-xcbc_t *xcbc_create(encryption_algorithm_t algo, size_t key_size)
+static mac_t *xcbc_create(encryption_algorithm_t algo, size_t key_size)
{
- private_xcbc_t *this;
+ private_mac_t *this;
crypter_t *crypter;
u_int8_t b;
@@ -278,7 +308,7 @@ xcbc_t *xcbc_create(encryption_algorithm_t algo, size_t key_size)
INIT(this,
.public = {
.get_mac = _get_mac,
- .get_block_size = _get_block_size,
+ .get_mac_size = _get_mac_size,
.set_key = _set_key,
.destroy = _destroy,
},
@@ -295,3 +325,55 @@ xcbc_t *xcbc_create(encryption_algorithm_t algo, size_t key_size)
return &this->public;
}
+/*
+ * Described in header.
+ */
+prf_t *xcbc_prf_create(pseudo_random_function_t algo)
+{
+ mac_t *xcbc;
+
+ switch (algo)
+ {
+ case PRF_AES128_XCBC:
+ xcbc = xcbc_create(ENCR_AES_CBC, 16);
+ break;
+ case PRF_CAMELLIA128_XCBC:
+ xcbc = xcbc_create(ENCR_CAMELLIA_CBC, 16);
+ break;
+ default:
+ return NULL;
+ }
+ if (xcbc)
+ {
+ return mac_prf_create(xcbc);
+ }
+ return NULL;
+}
+
+/*
+ * Described in header
+ */
+signer_t *xcbc_signer_create(integrity_algorithm_t algo)
+{
+ size_t trunc;
+ mac_t *xcbc;
+
+ switch (algo)
+ {
+ case AUTH_AES_XCBC_96:
+ xcbc = xcbc_create(ENCR_AES_CBC, 16);
+ trunc = 12;
+ break;
+ case AUTH_CAMELLIA_XCBC_96:
+ xcbc = xcbc_create(ENCR_CAMELLIA_CBC, 16);
+ trunc = 12;
+ break;
+ default:
+ return NULL;
+ }
+ if (xcbc)
+ {
+ return mac_signer_create(xcbc, trunc);
+ }
+ return NULL;
+}
diff --git a/src/libstrongswan/plugins/xcbc/xcbc.h b/src/libstrongswan/plugins/xcbc/xcbc.h
index 5d5eb04fb..a36069a17 100644
--- a/src/libstrongswan/plugins/xcbc/xcbc.h
+++ b/src/libstrongswan/plugins/xcbc/xcbc.h
@@ -14,6 +14,11 @@
*/
/**
+ * Message authentication using CBC crypter.
+ *
+ * This class implements the message authentication algorithm
+ * described in RFC3566.
+ *
* @defgroup xcbc xcbc
* @{ @ingroup xcbc_p
*/
@@ -21,58 +26,23 @@
#ifndef XCBC_H_
#define XCBC_H_
-typedef struct xcbc_t xcbc_t;
-
-#include <crypto/hashers/hasher.h>
+#include <crypto/prfs/prf.h>
+#include <crypto/signers/signer.h>
/**
- * Message authentication using CBC crypter.
+ * Creates a new prf_t object based on a XCBC MAC.
*
- * This class implements the message authentication algorithm
- * described in RFC3566.
+ * @param algo algorithm to implement
+ * @return prf_t object, NULL if not supported
*/
-struct xcbc_t {
-
- /**
- * Generate message authentication code.
- *
- * If buffer is NULL, no result is given back. A next call will
- * append the data to already supplied data. If buffer is not NULL,
- * the mac of all apended data is calculated, returned and the
- * state of the xcbc_t is reseted.
- *
- * @param data chunk of data to authenticate
- * @param buffer pointer where the generated bytes will be written
- */
- void (*get_mac) (xcbc_t *this, chunk_t data, u_int8_t *buffer);
-
- /**
- * Get the block size of this xcbc_t object.
- *
- * @return block size in bytes
- */
- size_t (*get_block_size) (xcbc_t *this);
-
- /**
- * Set the key for this xcbc_t object.
- *
- * @param key key to set
- */
- void (*set_key) (xcbc_t *this, chunk_t key);
-
- /**
- * Destroys a xcbc_t object.
- */
- void (*destroy) (xcbc_t *this);
-};
+prf_t *xcbc_prf_create(pseudo_random_function_t algo);
/**
- * Creates a new xcbc_t object.
+ * Creates a new signer_t object based on a XCBC MAC.
*
- * @param algo underlying crypto algorithm
- * @param key_size key size to use, if required for algorithm
- * @return xcbc_t object, NULL if not supported
+ * @param algo algorithm to implement
+ * @return signer_t, NULL if not supported
*/
-xcbc_t *xcbc_create(encryption_algorithm_t algo, size_t key_size);
+signer_t *xcbc_signer_create(integrity_algorithm_t algo);
#endif /** XCBC_H_ @}*/
diff --git a/src/libstrongswan/plugins/xcbc/xcbc_plugin.c b/src/libstrongswan/plugins/xcbc/xcbc_plugin.c
index 3c3b9d12a..4706a9574 100644
--- a/src/libstrongswan/plugins/xcbc/xcbc_plugin.c
+++ b/src/libstrongswan/plugins/xcbc/xcbc_plugin.c
@@ -16,8 +16,7 @@
#include "xcbc_plugin.h"
#include <library.h>
-#include "xcbc_signer.h"
-#include "xcbc_prf.h"
+#include "xcbc.h"
typedef struct private_xcbc_plugin_t private_xcbc_plugin_t;
diff --git a/src/libstrongswan/plugins/xcbc/xcbc_prf.c b/src/libstrongswan/plugins/xcbc/xcbc_prf.c
deleted file mode 100644
index ac9e1fda0..000000000
--- a/src/libstrongswan/plugins/xcbc/xcbc_prf.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2008 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include "xcbc_prf.h"
-
-#include "xcbc.h"
-
-typedef struct private_xcbc_prf_t private_xcbc_prf_t;
-
-/**
- * Private data of a xcbc_prf_t object.
- */
-struct private_xcbc_prf_t {
-
- /**
- * Public xcbc_prf_t interface.
- */
- xcbc_prf_t public;
-
- /**
- * xcbc to use for generation.
- */
- xcbc_t *xcbc;
-};
-
-METHOD(prf_t, get_bytes, void,
- private_xcbc_prf_t *this, chunk_t seed, u_int8_t *buffer)
-{
- this->xcbc->get_mac(this->xcbc, seed, buffer);
-}
-
-METHOD(prf_t, allocate_bytes, void,
- private_xcbc_prf_t *this, chunk_t seed, chunk_t *chunk)
-{
- if (chunk)
- {
- *chunk = chunk_alloc(this->xcbc->get_block_size(this->xcbc));
- get_bytes(this, seed, chunk->ptr);
- }
- else
- {
- get_bytes(this, seed, NULL);
- }
-}
-
-METHOD(prf_t, get_block_size, size_t,
- private_xcbc_prf_t *this)
-{
- return this->xcbc->get_block_size(this->xcbc);
-}
-
-METHOD(prf_t, get_key_size, size_t,
- private_xcbc_prf_t *this)
-{
- /* in xcbc, block and key size are always equal */
- return this->xcbc->get_block_size(this->xcbc);
-}
-
-METHOD(prf_t, set_key, void,
- private_xcbc_prf_t *this, chunk_t key)
-{
- this->xcbc->set_key(this->xcbc, key);
-}
-
-METHOD(prf_t, destroy, void,
- private_xcbc_prf_t *this)
-{
- this->xcbc->destroy(this->xcbc);
- free(this);
-}
-
-/*
- * Described in header.
- */
-xcbc_prf_t *xcbc_prf_create(pseudo_random_function_t algo)
-{
- private_xcbc_prf_t *this;
- xcbc_t *xcbc;
-
- switch (algo)
- {
- case PRF_AES128_XCBC:
- xcbc = xcbc_create(ENCR_AES_CBC, 16);
- break;
- case PRF_CAMELLIA128_XCBC:
- xcbc = xcbc_create(ENCR_CAMELLIA_CBC, 16);
- break;
- default:
- return NULL;
- }
- if (!xcbc)
- {
- return NULL;
- }
-
- INIT(this,
- .public = {
- .prf = {
- .get_bytes = _get_bytes,
- .allocate_bytes = _allocate_bytes,
- .get_block_size = _get_block_size,
- .get_key_size = _get_key_size,
- .set_key = _set_key,
- .destroy = _destroy,
- },
- },
- .xcbc = xcbc,
- );
-
- return &this->public;
-}
-
diff --git a/src/libstrongswan/plugins/xcbc/xcbc_prf.h b/src/libstrongswan/plugins/xcbc/xcbc_prf.h
deleted file mode 100644
index 294a853b4..000000000
--- a/src/libstrongswan/plugins/xcbc/xcbc_prf.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2008 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup xcbc_prf xcbc_prf
- * @{ @ingroup xcbc_p
- */
-
-#ifndef PRF_XCBC_H_
-#define PRF_XCBC_H_
-
-typedef struct xcbc_prf_t xcbc_prf_t;
-
-#include <crypto/prfs/prf.h>
-
-/**
- * Implementation of prf_t on CBC block cipher using XCBC, RFC3664/RFC4434.
- *
- * This simply wraps a xcbc_t in a prf_t. More a question of
- * interface matching.
- */
-struct xcbc_prf_t {
-
- /**
- * Implements prf_t interface.
- */
- prf_t prf;
-};
-
-/**
- * Creates a new xcbc_prf_t object.
- *
- * @param algo algorithm to implement
- * @return xcbc_prf_t object, NULL if hash not supported
- */
-xcbc_prf_t *xcbc_prf_create(pseudo_random_function_t algo);
-
-#endif /** PRF_XCBC_SHA1_H_ @}*/
diff --git a/src/libstrongswan/plugins/xcbc/xcbc_signer.c b/src/libstrongswan/plugins/xcbc/xcbc_signer.c
deleted file mode 100644
index ece592323..000000000
--- a/src/libstrongswan/plugins/xcbc/xcbc_signer.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2008 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <string.h>
-
-#include "xcbc_signer.h"
-#include "xcbc.h"
-
-typedef struct private_xcbc_signer_t private_xcbc_signer_t;
-
-/**
- * Private data structure with signing context.
- */
-struct private_xcbc_signer_t {
-
- /**
- * Public interface of xcbc_signer_t.
- */
- xcbc_signer_t public;
-
- /**
- * Assigned xcbc function.
- */
- xcbc_t *xcbc;
-
- /**
- * Block size (truncation of XCBC MAC)
- */
- size_t block_size;
-};
-
-METHOD(signer_t, get_signature, void,
- private_xcbc_signer_t *this, chunk_t data, u_int8_t *buffer)
-{
- if (buffer == NULL)
- { /* append mode */
- this->xcbc->get_mac(this->xcbc, data, NULL);
- }
- else
- {
- u_int8_t mac[this->xcbc->get_block_size(this->xcbc)];
-
- this->xcbc->get_mac(this->xcbc, data, mac);
- memcpy(buffer, mac, this->block_size);
- }
-}
-
-METHOD(signer_t, allocate_signature, void,
- private_xcbc_signer_t *this, chunk_t data, chunk_t *chunk)
-{
- if (chunk == NULL)
- { /* append mode */
- this->xcbc->get_mac(this->xcbc, data, NULL);
- }
- else
- {
- u_int8_t mac[this->xcbc->get_block_size(this->xcbc)];
-
- this->xcbc->get_mac(this->xcbc, data, mac);
-
- chunk->ptr = malloc(this->block_size);
- chunk->len = this->block_size;
-
- memcpy(chunk->ptr, mac, this->block_size);
- }
-}
-
-METHOD(signer_t, verify_signature, bool,
- private_xcbc_signer_t *this, chunk_t data, chunk_t signature)
-{
- u_int8_t mac[this->xcbc->get_block_size(this->xcbc)];
-
- if (signature.len != this->block_size)
- {
- return FALSE;
- }
-
- this->xcbc->get_mac(this->xcbc, data, mac);
- return memeq(signature.ptr, mac, this->block_size);
-}
-
-METHOD(signer_t, get_key_size, size_t,
- private_xcbc_signer_t *this)
-{
- return this->xcbc->get_block_size(this->xcbc);
-}
-
-METHOD(signer_t, get_block_size, size_t,
- private_xcbc_signer_t *this)
-{
- return this->block_size;
-}
-
-METHOD(signer_t, set_key, void,
- private_xcbc_signer_t *this, chunk_t key)
-{
- this->xcbc->set_key(this->xcbc, key);
-}
-
-METHOD(signer_t, destroy, void,
- private_xcbc_signer_t *this)
-{
- this->xcbc->destroy(this->xcbc);
- free(this);
-}
-
-/*
- * Described in header
- */
-xcbc_signer_t *xcbc_signer_create(integrity_algorithm_t algo)
-{
- private_xcbc_signer_t *this;
- size_t trunc;
- xcbc_t *xcbc;
-
- switch (algo)
- {
- case AUTH_AES_XCBC_96:
- xcbc = xcbc_create(ENCR_AES_CBC, 16);
- trunc = 12;
- break;
- case AUTH_CAMELLIA_XCBC_96:
- xcbc = xcbc_create(ENCR_CAMELLIA_CBC, 16);
- trunc = 12;
- break;
- default:
- return NULL;
- }
- if (xcbc == NULL)
- {
- return NULL;
- }
-
- INIT(this,
- .public = {
- .signer = {
- .get_signature = _get_signature,
- .allocate_signature = _allocate_signature,
- .verify_signature = _verify_signature,
- .get_key_size = _get_key_size,
- .get_block_size = _get_block_size,
- .set_key = _set_key,
- .destroy = _destroy,
- },
- },
- .xcbc = xcbc,
- .block_size = min(trunc, xcbc->get_block_size(xcbc)),
- );
-
- return &this->public;
-}
-
diff --git a/src/libstrongswan/plugins/xcbc/xcbc_signer.h b/src/libstrongswan/plugins/xcbc/xcbc_signer.h
deleted file mode 100644
index 56b55f223..000000000
--- a/src/libstrongswan/plugins/xcbc/xcbc_signer.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2008 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup xcbc_signer xcbc_signer
- * @{ @ingroup xcbc_p
- */
-
-#ifndef XCBC_SIGNER_H_
-#define XCBC_SIGNER_H_
-
-typedef struct xcbc_signer_t xcbc_signer_t;
-
-#include <crypto/signers/signer.h>
-
-/**
- * Implementation of signer_t based on CBC symmetric cypher. XCBC, RFC3566.
- */
-struct xcbc_signer_t {
-
- /**
- * Implements signer_t interface.
- */
- signer_t signer;
-};
-
-/**
- * Creates a new xcbc_signer_t.
- *
- * @param algo algorithm to implement
- * @return xcbc_signer_t, NULL if not supported
- */
-xcbc_signer_t *xcbc_signer_create(integrity_algorithm_t algo);
-
-#endif /** XCBC_SIGNER_H_ @}*/
diff --git a/src/libstrongswan/printf_hook.c b/src/libstrongswan/printf_hook.c
index c3b5191fd..6e51aa4c3 100644
--- a/src/libstrongswan/printf_hook.c
+++ b/src/libstrongswan/printf_hook.c
@@ -86,21 +86,18 @@ static printf_hook_handler_t *printf_hooks[NUM_HANDLERS];
static int custom_print(FILE *stream, const struct printf_info *info,
const void *const *args)
{
- int written;
- char buf[PRINTF_BUF_LEN];
printf_hook_spec_t spec;
printf_hook_handler_t *handler = printf_hooks[SPEC_TO_INDEX(info->spec)];
+ printf_hook_data_t data = {
+ .stream = stream,
+ };
spec.hash = info->alt;
+ spec.plus = info->showsign;
spec.minus = info->left;
spec.width = info->width;
- written = handler->hook(buf, sizeof(buf), &spec, args);
- if (written > 0)
- {
- ignore_result(fwrite(buf, 1, written, stream));
- }
- return written;
+ return handler->hook(&data, &spec, args);
}
/**
@@ -145,11 +142,14 @@ static int custom_arginfo(const struct printf_info *info, size_t n, int *argtype
*/
static int custom_fmt_cb(Vstr_base *base, size_t pos, Vstr_fmt_spec *fmt_spec)
{
- int i, written;
- char buf[PRINTF_BUF_LEN];
+ int i;
const void *args[ARGS_MAX];
printf_hook_spec_t spec;
printf_hook_handler_t *handler = printf_hooks[SPEC_TO_INDEX(fmt_spec->name[0])];
+ printf_hook_data_t data = {
+ .base = base,
+ .pos = pos,
+ };
for (i = 0; i < handler->numargs; i++)
{
@@ -165,14 +165,11 @@ static int custom_fmt_cb(Vstr_base *base, size_t pos, Vstr_fmt_spec *fmt_spec)
}
spec.hash = fmt_spec->fmt_hash;
+ spec.plus = fmt_spec->fmt_plus;
spec.minus = fmt_spec->fmt_minus;
spec.width = fmt_spec->fmt_field_width;
- written = handler->hook(buf, sizeof(buf), &spec, args);
- if (written > 0)
- {
- vstr_add_buf(base, pos, buf, written);
- }
+ handler->hook(&data, &spec, args);
return 1;
}
@@ -241,6 +238,21 @@ static inline Vstr_conf *get_vstr_conf()
}
/**
+ * Described in header
+ */
+size_t vstr_print_in_hook(struct Vstr_base *base, size_t pos, const char *fmt,
+ ...)
+{
+ va_list args;
+ int written;
+
+ va_start(args, fmt);
+ written = vstr_add_vfmt(base, pos, fmt, args);
+ va_end(args);
+ return written;
+}
+
+/**
* Wrapper functions for printf and alike
*/
int vstr_wrapper_printf(const char *format, ...)
diff --git a/src/libstrongswan/printf_hook.h b/src/libstrongswan/printf_hook.h
index 11fd66ce9..7d3f23bce 100644
--- a/src/libstrongswan/printf_hook.h
+++ b/src/libstrongswan/printf_hook.h
@@ -24,9 +24,17 @@
typedef struct printf_hook_t printf_hook_t;
typedef struct printf_hook_spec_t printf_hook_spec_t;
+typedef struct printf_hook_data_t printf_hook_data_t;
typedef enum printf_hook_argtype_t printf_hook_argtype_t;
#if !defined(USE_VSTR) && \
+ !defined(HAVE_PRINTF_FUNCTION) && \
+ !defined(HAVE_PRINTF_SPECIFIER)
+/* assume newer glibc register_printf_specifier if none given */
+#define HAVE_PRINTF_SPECIFIER
+#endif
+
+#if !defined(USE_VSTR) && \
(defined(HAVE_PRINTF_FUNCTION) || defined(HAVE_PRINTF_SPECIFIER))
#include <stdio.h>
@@ -38,6 +46,29 @@ enum printf_hook_argtype_t {
PRINTF_HOOK_ARGTYPE_POINTER = PA_POINTER,
};
+/**
+ * Data to pass to a printf hook.
+ */
+struct printf_hook_data_t {
+
+ /**
+ * Output FILE stream
+ */
+ FILE *stream;;
+};
+
+/**
+ * Helper macro to be used in printf hook callbacks.
+ */
+#define print_in_hook(data, fmt, ...) ({\
+ ssize_t _written = fprintf(data->stream, fmt, ##__VA_ARGS__);\
+ if (_written < 0)\
+ {\
+ _written = 0;\
+ }\
+ _written;\
+})
+
#else
#include <vstr.h>
@@ -66,6 +97,37 @@ int vstr_wrapper_vsprintf(char *str, const char *format, va_list ap);
int vstr_wrapper_vsnprintf(char *str, size_t size, const char *format, va_list ap);
int vstr_wrapper_vasprintf(char **str, const char *format, va_list ap);
+#ifdef printf
+#undef printf
+#endif
+#ifdef fprintf
+#undef fprintf
+#endif
+#ifdef sprintf
+#undef sprintf
+#endif
+#ifdef snprintf
+#undef snprintf
+#endif
+#ifdef asprintf
+#undef asprintf
+#endif
+#ifdef vprintf
+#undef vprintf
+#endif
+#ifdef vfprintf
+#undef vfprintf
+#endif
+#ifdef vsprintf
+#undef vsprintf
+#endif
+#ifdef vsnprintf
+#undef vsnprintf
+#endif
+#ifdef vasprintf
+#undef vasprintf
+#endif
+
#define printf vstr_wrapper_printf
#define fprintf vstr_wrapper_fprintf
#define sprintf vstr_wrapper_sprintf
@@ -78,36 +140,59 @@ int vstr_wrapper_vasprintf(char **str, const char *format, va_list ap);
#define vsnprintf vstr_wrapper_vsnprintf
#define vasprintf vstr_wrapper_vasprintf
-#endif
+/**
+ * Data to pass to a printf hook.
+ */
+struct printf_hook_data_t {
+
+ /**
+ * Base to append printf to
+ */
+ Vstr_base *base;
+
+ /**
+ * Position in base to write to
+ */
+ size_t pos;
+};
/**
- * Callback function type for printf hooks.
+ * Wrapper around vstr_add_vfmt(), avoids having to link all users of
+ * print_in_hook() against libvstr.
*
- * @param dst destination buffer
- * @param len length of the buffer
- * @param spec format specifier
- * @param args arguments array
+ * @param base Vstr_string to add string to
+ * @param pos position to write to
+ * @param fmt format string
+ * @param ... arguments
* @return number of characters written
*/
-typedef int (*printf_hook_function_t)(char *dst, size_t len,
- printf_hook_spec_t *spec,
- const void *const *args);
+size_t vstr_print_in_hook(struct Vstr_base *base, size_t pos, const char *fmt,
+ ...);
/**
* Helper macro to be used in printf hook callbacks.
- * buf and buflen get modified.
*/
-#define print_in_hook(buf, buflen, fmt, ...) ({\
- int _written = snprintf(buf, buflen, fmt, ##__VA_ARGS__);\
- if (_written < 0 || _written >= buflen)\
- {\
- _written = buflen - 1;\
- }\
- buf += _written;\
- buflen -= _written;\
+#define print_in_hook(data, fmt, ...) ({\
+ size_t _written; \
+ _written = vstr_print_in_hook(data->base, data->pos, fmt, ##__VA_ARGS__);\
+ data->pos += _written;\
_written;\
})
+#endif
+
+/**
+ * Callback function type for printf hooks.
+ *
+ * @param data hook data, to pass to print_in_hook()
+ * @param spec format specifier
+ * @param args arguments array
+ * @return number of characters written
+ */
+typedef int (*printf_hook_function_t)(printf_hook_data_t *data,
+ printf_hook_spec_t *spec,
+ const void *const *args);
+
/**
* Properties of the format specifier
*/
@@ -123,6 +208,11 @@ struct printf_hook_spec_t {
int minus;
/**
+ * TRUE if a '+' was used in the format specifier
+ */
+ int plus;
+
+ /**
* The width as given in the format specifier.
*/
int width;
diff --git a/src/libstrongswan/processing/jobs/callback_job.c b/src/libstrongswan/processing/jobs/callback_job.c
index 13f22e69c..a5ddc8ff6 100644
--- a/src/libstrongswan/processing/jobs/callback_job.c
+++ b/src/libstrongswan/processing/jobs/callback_job.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Tobias Brunner
+ * Copyright (C) 2009-2012 Tobias Brunner
* Copyright (C) 2007-2011 Martin Willi
* Copyright (C) 2011 revosec AG
* Hochschule fuer Technik Rapperswil
@@ -17,10 +17,9 @@
#include "callback_job.h"
-#include <semaphore.h>
-
#include <threading/thread.h>
#include <threading/condvar.h>
+#include <threading/semaphore.h>
#include <threading/mutex.h>
#include <utils/linked_list.h>
@@ -52,42 +51,9 @@ struct private_callback_job_t {
callback_job_cleanup_t cleanup;
/**
- * thread of the job, if running
- */
- thread_t *thread;
-
- /**
- * mutex to access jobs interna
- */
- mutex_t *mutex;
-
- /**
- * list of associated child jobs
- */
- linked_list_t *children;
-
- /**
- * parent of this job, or NULL
+ * cancel function
*/
- private_callback_job_t *parent;
-
- /**
- * TRUE if the job got cancelled
- */
- bool cancelled;
-
- /**
- * condvar to synchronize the cancellation/destruction of the job
- */
- condvar_t *destroyable;
-
- /**
- * semaphore to synchronize the termination of the assigned thread.
- *
- * separately allocated during cancellation, so that we can wait on it
- * without risking that it gets freed too early during destruction.
- */
- sem_t *terminated;
+ callback_job_cancel_t cancel;
/**
* Priority of this job
@@ -95,141 +61,26 @@ struct private_callback_job_t {
job_priority_t prio;
};
-/**
- * unregister a child from its parent, if any.
- * note: this->mutex has to be locked
- */
-static void unregister(private_callback_job_t *this)
-{
- if (this->parent)
- {
- this->parent->mutex->lock(this->parent->mutex);
- if (this->parent->cancelled && !this->cancelled)
- {
- /* if the parent has been cancelled but we have not yet, we do not
- * unregister until we got cancelled by the parent. */
- this->parent->mutex->unlock(this->parent->mutex);
- this->destroyable->wait(this->destroyable, this->mutex);
- this->parent->mutex->lock(this->parent->mutex);
- }
- this->parent->children->remove(this->parent->children, this, NULL);
- this->parent->mutex->unlock(this->parent->mutex);
- this->parent = NULL;
- }
-}
-
METHOD(job_t, destroy, void,
private_callback_job_t *this)
{
- this->mutex->lock(this->mutex);
- unregister(this);
if (this->cleanup)
{
this->cleanup(this->data);
}
- if (this->terminated)
- {
- sem_post(this->terminated);
- }
- this->children->destroy(this->children);
- this->destroyable->destroy(this->destroyable);
- this->mutex->unlock(this->mutex);
- this->mutex->destroy(this->mutex);
free(this);
}
-METHOD(callback_job_t, cancel, void,
+METHOD(job_t, execute, job_requeue_t,
private_callback_job_t *this)
{
- callback_job_t *child;
- sem_t *terminated = NULL;
-
- this->mutex->lock(this->mutex);
- this->cancelled = TRUE;
- /* terminate children */
- while (this->children->get_first(this->children, (void**)&child) == SUCCESS)
- {
- this->mutex->unlock(this->mutex);
- child->cancel(child);
- this->mutex->lock(this->mutex);
- }
- if (this->thread)
- {
- /* terminate the thread, if there is currently one executing the job.
- * we wait for its termination using a semaphore */
- this->thread->cancel(this->thread);
- terminated = this->terminated = malloc_thing(sem_t);
- sem_init(terminated, 0, 0);
- }
- else
- {
- /* if the job is currently queued, it gets terminated later.
- * we can't wait, because it might not get executed at all.
- * we also unregister the queued job manually from its parent (the
- * others get unregistered during destruction) */
- unregister(this);
- }
- this->destroyable->signal(this->destroyable);
- this->mutex->unlock(this->mutex);
-
- if (terminated)
- {
- sem_wait(terminated);
- sem_destroy(terminated);
- free(terminated);
- }
+ return this->callback(this->data);
}
-METHOD(job_t, execute, void,
+METHOD(job_t, cancel, bool,
private_callback_job_t *this)
{
- bool cleanup = FALSE, requeue = FALSE;
-
- thread_cleanup_push((thread_cleanup_t)destroy, this);
-
- this->mutex->lock(this->mutex);
- this->thread = thread_current();
- this->mutex->unlock(this->mutex);
-
- while (TRUE)
- {
- this->mutex->lock(this->mutex);
- if (this->cancelled)
- {
- this->mutex->unlock(this->mutex);
- cleanup = TRUE;
- break;
- }
- this->mutex->unlock(this->mutex);
- switch (this->callback(this->data))
- {
- case JOB_REQUEUE_DIRECT:
- continue;
- case JOB_REQUEUE_FAIR:
- {
- requeue = TRUE;
- break;
- }
- case JOB_REQUEUE_NONE:
- default:
- {
- cleanup = TRUE;
- break;
- }
- }
- break;
- }
- this->mutex->lock(this->mutex);
- this->thread = NULL;
- this->mutex->unlock(this->mutex);
- /* manually create a cancellation point to avoid that a cancelled thread
- * goes back into the thread pool */
- thread_cancellation_point();
- if (requeue)
- {
- lib->processor->queue_job(lib->processor, &this->public.job);
- }
- thread_cleanup_pop(cleanup);
+ return this->cancel(this->data);
}
METHOD(job_t, get_priority, job_priority_t,
@@ -242,8 +93,8 @@ METHOD(job_t, get_priority, job_priority_t,
* Described in header.
*/
callback_job_t *callback_job_create_with_prio(callback_job_cb_t cb, void *data,
- callback_job_cleanup_t cleanup, callback_job_t *parent,
- job_priority_t prio)
+ callback_job_cleanup_t cleanup, callback_job_cancel_t cancel,
+ job_priority_t prio)
{
private_callback_job_t *this;
@@ -254,24 +105,17 @@ callback_job_t *callback_job_create_with_prio(callback_job_cb_t cb, void *data,
.get_priority = _get_priority,
.destroy = _destroy,
},
- .cancel = _cancel,
},
- .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
.callback = cb,
.data = data,
.cleanup = cleanup,
- .children = linked_list_create(),
- .parent = (private_callback_job_t*)parent,
- .destroyable = condvar_create(CONDVAR_TYPE_DEFAULT),
+ .cancel = cancel,
.prio = prio,
);
- /* register us at parent */
- if (parent)
+ if (cancel)
{
- this->parent->mutex->lock(this->parent->mutex);
- this->parent->children->insert_last(this->parent->children, this);
- this->parent->mutex->unlock(this->parent->mutex);
+ this->public.job.cancel = _cancel;
}
return &this->public;
@@ -282,8 +126,8 @@ callback_job_t *callback_job_create_with_prio(callback_job_cb_t cb, void *data,
*/
callback_job_t *callback_job_create(callback_job_cb_t cb, void *data,
callback_job_cleanup_t cleanup,
- callback_job_t *parent)
+ callback_job_cancel_t cancel)
{
- return callback_job_create_with_prio(cb, data, cleanup, parent,
+ return callback_job_create_with_prio(cb, data, cleanup, cancel,
JOB_PRIO_MEDIUM);
}
diff --git a/src/libstrongswan/processing/jobs/callback_job.h b/src/libstrongswan/processing/jobs/callback_job.h
index 3e92b01c0..6f2e39eb8 100644
--- a/src/libstrongswan/processing/jobs/callback_job.h
+++ b/src/libstrongswan/processing/jobs/callback_job.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2007-2011 Martin Willi
* Copyright (C) 2011 revosec AG
* Hochschule fuer Technik Rapperswil
@@ -27,33 +28,6 @@ typedef struct callback_job_t callback_job_t;
#include <library.h>
#include <processing/jobs/job.h>
-
-typedef enum job_requeue_t job_requeue_t;
-
-/**
- * Job requeueing policy.
- *
- * The job requeueing policy defines how a job is handled when the callback
- * function returns.
- */
-enum job_requeue_t {
-
- /**
- * Do not requeue job, destroy it
- */
- JOB_REQUEUE_NONE,
-
- /**
- * Reque the job fairly, meaning it has to requeue as any other job
- */
- JOB_REQUEUE_FAIR,
-
- /**
- * Reexecute the job directly, without the need of requeueing it
- */
- JOB_REQUEUE_DIRECT,
-};
-
/**
* The callback function to use for the callback job.
*
@@ -73,11 +47,22 @@ typedef job_requeue_t (*callback_job_cb_t)(void *data);
* to supply to the constructor.
*
* @param data param supplied to job
- * @return requeing policy how to requeue the job
*/
typedef void (*callback_job_cleanup_t)(void *data);
/**
+ * Cancellation function to use for the callback job.
+ *
+ * Optional function to be called when a job has to be canceled.
+ *
+ * See job_t.cancel() for details on the return value.
+ *
+ * @param data param supplied to job
+ * @return TRUE if canceled, FALSE to explicitly cancel the thread
+ */
+typedef bool (*callback_job_cancel_t)(void *data);
+
+/**
* Class representing an callback Job.
*
* This is a special job which allows a simple callback function to
@@ -91,14 +76,6 @@ struct callback_job_t {
*/
job_t job;
- /**
- * Cancel the job's thread and wait for its termination.
- *
- * This only works reliably for jobs that always use JOB_REQUEUE_FAIR or
- * JOB_REQUEUE_DIRECT, otherwise the job may already be destroyed when
- * cancel is called.
- */
- void (*cancel)(callback_job_t *this);
};
/**
@@ -106,19 +83,20 @@ struct callback_job_t {
*
* The cleanup function is called when the job gets destroyed to destroy
* the associated data.
- * If parent is not NULL, the specified job gets an association. Whenever
- * the parent gets cancelled (or runs out), all of its children are cancelled,
- * too.
+ *
+ * The cancel function is optional and should only be provided if the callback
+ * function calls potentially blocking functions and/or always returns
+ * JOB_REQUEUE_DIRECT.
*
* @param cb callback to call from the processor
* @param data user data to supply to callback
* @param cleanup destructor for data on destruction, or NULL
- * @param parent parent of this job
+ * @param cancel function to cancel the job, or NULL
* @return callback_job_t object
*/
callback_job_t *callback_job_create(callback_job_cb_t cb, void *data,
callback_job_cleanup_t cleanup,
- callback_job_t *parent);
+ callback_job_cancel_t cancel);
/**
* Creates a callback job, with priority.
@@ -128,12 +106,12 @@ callback_job_t *callback_job_create(callback_job_cb_t cb, void *data,
* @param cb callback to call from the processor
* @param data user data to supply to callback
* @param cleanup destructor for data on destruction, or NULL
- * @param parent parent of this job
+ * @param cancel function to cancel the job, or NULL
* @param prio job priority
* @return callback_job_t object
*/
callback_job_t *callback_job_create_with_prio(callback_job_cb_t cb, void *data,
- callback_job_cleanup_t cleanup, callback_job_t *parent,
- job_priority_t prio);
+ callback_job_cleanup_t cleanup, callback_job_cancel_t cancel,
+ job_priority_t prio);
#endif /** CALLBACK_JOB_H_ @}*/
diff --git a/src/libstrongswan/processing/jobs/job.h b/src/libstrongswan/processing/jobs/job.h
index d25cee03e..64454718a 100644
--- a/src/libstrongswan/processing/jobs/job.h
+++ b/src/libstrongswan/processing/jobs/job.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -24,6 +25,9 @@
typedef struct job_t job_t;
typedef enum job_priority_t job_priority_t;
+typedef enum job_status_t job_status_t;
+typedef enum job_requeue_type_t job_requeue_type_t;
+typedef struct job_requeue_t job_requeue_t;
#include <library.h>
@@ -48,18 +52,107 @@ enum job_priority_t {
extern enum_name_t *job_priority_names;
/**
+ * Job status
+ */
+enum job_status_t {
+ /** The job is queued and has not yet been executed */
+ JOB_STATUS_QUEUED = 0,
+ /** During execution */
+ JOB_STATUS_EXECUTING,
+ /** If the job got canceled */
+ JOB_STATUS_CANCELED,
+ /** The job was executed successfully */
+ JOB_STATUS_DONE,
+};
+
+/**
+ * How a job is handled after is has been executed.
+ */
+enum job_requeue_type_t {
+ /** Do not requeue job, destroy it */
+ JOB_REQUEUE_TYPE_NONE = 0,
+ /** Requeue the job fairly, i.e. it is inserted at the end of the queue */
+ JOB_REQUEUE_TYPE_FAIR,
+ /** Reexecute the job directly, without the need of requeueing it */
+ JOB_REQUEUE_TYPE_DIRECT,
+ /** Rescheduled the job via scheduler_t */
+ JOB_REQUEUE_TYPE_SCHEDULE,
+};
+
+/**
+ * Job requeueing policy.
+ *
+ * The job requeueing policy defines how a job is handled after it has been
+ * executed.
+ */
+struct job_requeue_t {
+ /** How to handle the job after executing it */
+ job_requeue_type_t type;
+ /** How to reschedule the job, if so */
+ enum {
+ JOB_SCHEDULE,
+ JOB_SCHEDULE_MS,
+ JOB_SCHEDULE_TV,
+ } schedule;
+ /** Time to reschedule the job */
+ union {
+ u_int32_t rel;
+ timeval_t abs;
+ } time;
+};
+
+/**
+ * Helper macros to easily define requeueing policies.
+ */
+#define __JOB_REQUEUE(t) (job_requeue_t){ .type = t }
+#define JOB_REQUEUE_NONE __JOB_REQUEUE(JOB_REQUEUE_TYPE_NONE)
+#define JOB_REQUEUE_FAIR __JOB_REQUEUE(JOB_REQUEUE_TYPE_FAIR)
+#define JOB_REQUEUE_DIRECT __JOB_REQUEUE(JOB_REQUEUE_TYPE_DIRECT)
+#define __JOB_RESCHEDULE(t, ...) (job_requeue_t){ .type = JOB_REQUEUE_TYPE_SCHEDULE, .schedule = t, { __VA_ARGS__ } }
+#define JOB_RESCHEDULE(s) __JOB_RESCHEDULE(JOB_SCHEDULE, .rel = s)
+#define JOB_RESCHEDULE_MS(ms) __JOB_RESCHEDULE(JOB_SCHEDULE_MS, .rel = ms)
+#define JOB_RESCHEDULE_TV(tv) __JOB_RESCHEDULE(JOB_SCHEDULE_TV, .abs = tv)
+
+/**
* Job interface as it is stored in the job queue.
*/
struct job_t {
/**
+ * Status of this job, is modified exclusively by the processor/scheduler
+ */
+ job_status_t status;
+
+ /**
* Execute a job.
*
* The processing facility executes a job using this method. Jobs are
- * one-shot, they destroy themself after execution, so don't use a job
- * once it has been executed.
+ * one-shot, they are destroyed after execution (depending on the return
+ * value here), so don't use a job once it has been queued.
+ *
+ * @return policy how to requeue the job
+ */
+ job_requeue_t (*execute) (job_t *this);
+
+ /**
+ * Cancel a job.
+ *
+ * Implementing this method is optional. It allows potentially blocking
+ * jobs to be canceled during shutdown.
+ *
+ * If no special action is to be taken simply return FALSE then the thread
+ * executing the job will be canceled. If TRUE is returned the job is
+ * expected to return from execute() itself (i.e. the thread won't be
+ * canceled explicitly and can still be joined later).
+ * Jobs that return FALSE have to make sure they provide the appropriate
+ * cancellation points.
+ *
+ * @note Regular jobs that do not block MUST NOT implement this method.
+ * @note This method could be called even before execute() has been called.
+ *
+ * @return FALSE to cancel the thread, TRUE if canceled otherwise
*/
- void (*execute) (job_t *this);
+ bool (*cancel)(job_t *this);
/**
* Get the priority of a job.
@@ -71,10 +164,12 @@ struct job_t {
/**
* Destroy a job.
*
- * Is only called whenever a job was not executed (e.g. due daemon shutdown).
- * After execution, jobs destroy themself.
+ * Is called after a job is executed or got canceled. It is also called
+ * for queued jobs that were never executed.
+ *
+ * Use the status of a job to decide what to do during destruction.
*/
- void (*destroy) (job_t *this);
+ void (*destroy)(job_t *this);
};
#endif /** JOB_H_ @}*/
diff --git a/src/libstrongswan/processing/processor.c b/src/libstrongswan/processing/processor.c
index 222f1a535..5b7fd467c 100644
--- a/src/libstrongswan/processing/processor.c
+++ b/src/libstrongswan/processing/processor.c
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2005-2011 Martin Willi
* Copyright (C) 2011 revosec AG
- * Copyright (C) 2008-2011 Tobias Brunner
+ * Copyright (C) 2008-2012 Tobias Brunner
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -58,7 +58,7 @@ struct private_processor_t {
/**
* All threads managed in the pool (including threads that have been
- * cancelled, this allows to join them during destruction)
+ * canceled, this allows to join them later), as worker_thread_t
*/
linked_list_t *threads;
@@ -73,11 +73,6 @@ struct private_processor_t {
int prio_threads[JOB_PRIO_MAX];
/**
- * Priority of the job executed by a thread
- */
- thread_value_t *priority;
-
- /**
* access to job lists is locked through this mutex
*/
mutex_t *mutex;
@@ -93,39 +88,71 @@ struct private_processor_t {
condvar_t *thread_terminated;
};
-static void process_jobs(private_processor_t *this);
+/**
+ * Worker thread
+ */
+typedef struct {
+
+ /**
+ * Reference to the processor
+ */
+ private_processor_t *processor;
+
+ /**
+ * The actual thread
+ */
+ thread_t *thread;
+
+ /**
+ * Job currently being executed by this worker thread
+ */
+ job_t *job;
+
+ /**
+ * Priority of the current job
+ */
+ job_priority_t priority;
+
+} worker_thread_t;
+
+static void process_jobs(worker_thread_t *worker);
/**
* restart a terminated thread
*/
-static void restart(private_processor_t *this)
+static void restart(worker_thread_t *worker)
{
- thread_t *thread;
+ private_processor_t *this = worker->processor;
DBG2(DBG_JOB, "terminated worker thread %.2u", thread_current_id());
- /* respawn thread if required */
this->mutex->lock(this->mutex);
- if (this->desired_threads < this->total_threads ||
- (thread = thread_create((thread_main_t)process_jobs, this)) == NULL)
- {
- this->total_threads--;
- this->thread_terminated->signal(this->thread_terminated);
- }
- else
+ /* cleanup worker thread */
+ this->working_threads[worker->priority]--;
+ worker->job->status = JOB_STATUS_CANCELED;
+ worker->job->destroy(worker->job);
+ worker->job = NULL;
+
+ /* respawn thread if required */
+ if (this->desired_threads >= this->total_threads)
{
- this->threads->insert_last(this->threads, thread);
+ worker_thread_t *new_worker;
+
+ INIT(new_worker,
+ .processor = this,
+ );
+ new_worker->thread = thread_create((thread_main_t)process_jobs,
+ new_worker);
+ if (new_worker->thread)
+ {
+ this->threads->insert_last(this->threads, new_worker);
+ this->mutex->unlock(this->mutex);
+ return;
+ }
+ free(new_worker);
}
- this->mutex->unlock(this->mutex);
-}
-
-/**
- * Decrement working thread count of a priority class
- */
-static void decrement_working_threads(private_processor_t *this)
-{
- this->mutex->lock(this->mutex);
- this->working_threads[(intptr_t)this->priority->get(this->priority)]--;
+ this->total_threads--;
+ this->thread_terminated->signal(this->thread_terminated);
this->mutex->unlock(this->mutex);
}
@@ -147,9 +174,11 @@ static u_int get_idle_threads_nolock(private_processor_t *this)
/**
* Process queued jobs, called by the worker threads
*/
-static void process_jobs(private_processor_t *this)
+static void process_jobs(worker_thread_t *worker)
{
- /* worker threads are not cancellable by default */
+ private_processor_t *this = worker->processor;
+
+ /* worker threads are not cancelable by default */
thread_cancelability(FALSE);
DBG2(DBG_JOB, "started worker thread %.2u", thread_current_id());
@@ -157,7 +186,6 @@ static void process_jobs(private_processor_t *this)
this->mutex->lock(this->mutex);
while (this->desired_threads >= this->total_threads)
{
- job_t *job = NULL;
int i, reserved = 0, idle;
idle = get_idle_threads_nolock(this);
@@ -176,27 +204,80 @@ static void process_jobs(private_processor_t *this)
reserved += this->prio_threads[i] - this->working_threads[i];
}
if (this->jobs[i]->remove_first(this->jobs[i],
- (void**)&job) == SUCCESS)
+ (void**)&worker->job) == SUCCESS)
{
+ job_requeue_t requeue;
+
this->working_threads[i]++;
+ worker->job->status = JOB_STATUS_EXECUTING;
+ worker->priority = i;
this->mutex->unlock(this->mutex);
- this->priority->set(this->priority, (void*)(intptr_t)i);
- /* terminated threads are restarted to get a constant pool */
- thread_cleanup_push((thread_cleanup_t)restart, this);
- thread_cleanup_push((thread_cleanup_t)decrement_working_threads,
- this);
- job->execute(job);
- thread_cleanup_pop(FALSE);
+ /* canceled threads are restarted to get a constant pool */
+ thread_cleanup_push((thread_cleanup_t)restart, worker);
+ while (TRUE)
+ {
+ requeue = worker->job->execute(worker->job);
+ if (requeue.type != JOB_REQUEUE_TYPE_DIRECT)
+ {
+ break;
+ }
+ else if (!worker->job->cancel)
+ { /* only allow cancelable jobs to requeue directly */
+ requeue.type = JOB_REQUEUE_TYPE_FAIR;
+ break;
+ }
+ }
thread_cleanup_pop(FALSE);
this->mutex->lock(this->mutex);
this->working_threads[i]--;
+ if (worker->job->status == JOB_STATUS_CANCELED)
+ { /* job was canceled via a custom cancel() method or did not
+ * use JOB_REQUEUE_TYPE_DIRECT */
+ worker->job->destroy(worker->job);
+ break;
+ }
+ switch (requeue.type)
+ {
+ case JOB_REQUEUE_TYPE_NONE:
+ worker->job->status = JOB_STATUS_DONE;
+ worker->job->destroy(worker->job);
+ break;
+ case JOB_REQUEUE_TYPE_FAIR:
+ worker->job->status = JOB_STATUS_QUEUED;
+ this->jobs[i]->insert_last(this->jobs[i],
+ worker->job);
+ this->job_added->signal(this->job_added);
+ break;
+ case JOB_REQUEUE_TYPE_SCHEDULE:
+ /* scheduler_t does not hold its lock when queeuing jobs
+ * so this should be safe without unlocking our mutex */
+ switch (requeue.schedule)
+ {
+ case JOB_SCHEDULE:
+ lib->scheduler->schedule_job(lib->scheduler,
+ worker->job, requeue.time.rel);
+ break;
+ case JOB_SCHEDULE_MS:
+ lib->scheduler->schedule_job_ms(lib->scheduler,
+ worker->job, requeue.time.rel);
+ break;
+ case JOB_SCHEDULE_TV:
+ lib->scheduler->schedule_job_tv(lib->scheduler,
+ worker->job, requeue.time.abs);
+ break;
+ }
+ break;
+ default:
+ break;
+ }
break;
}
}
- if (!job)
+ if (!worker->job)
{
this->job_added->wait(this->job_added, this->mutex);
}
+ worker->job = NULL;
}
this->total_threads--;
this->thread_terminated->signal(this->thread_terminated);
@@ -266,6 +347,8 @@ METHOD(processor_t, queue_job, void,
job_priority_t prio;
prio = sane_prio(job->get_priority(job));
+ job->status = JOB_STATUS_QUEUED;
+
this->mutex->lock(this->mutex);
this->jobs[prio]->insert_last(this->jobs[prio], job);
this->job_added->signal(this->job_added);
@@ -278,19 +361,26 @@ METHOD(processor_t, set_threads, void,
this->mutex->lock(this->mutex);
if (count > this->total_threads)
{ /* increase thread count */
+ worker_thread_t *worker;
int i;
- thread_t *current;
this->desired_threads = count;
DBG1(DBG_JOB, "spawning %d worker threads", count - this->total_threads);
for (i = this->total_threads; i < count; i++)
{
- current = thread_create((thread_main_t)process_jobs, this);
- if (current)
+ INIT(worker,
+ .processor = this,
+ );
+ worker->thread = thread_create((thread_main_t)process_jobs, worker);
+ if (worker->thread)
{
- this->threads->insert_last(this->threads, current);
+ this->threads->insert_last(this->threads, worker);
this->total_threads++;
}
+ else
+ {
+ free(worker);
+ }
}
}
else if (count < this->total_threads)
@@ -301,26 +391,49 @@ METHOD(processor_t, set_threads, void,
this->mutex->unlock(this->mutex);
}
-METHOD(processor_t, destroy, void,
+METHOD(processor_t, cancel, void,
private_processor_t *this)
{
- thread_t *current;
- int i;
+ enumerator_t *enumerator;
+ worker_thread_t *worker;
- set_threads(this, 0);
this->mutex->lock(this->mutex);
+ this->desired_threads = 0;
+ /* cancel potentially blocking jobs */
+ enumerator = this->threads->create_enumerator(this->threads);
+ while (enumerator->enumerate(enumerator, (void**)&worker))
+ {
+ if (worker->job && worker->job->cancel)
+ {
+ worker->job->status = JOB_STATUS_CANCELED;
+ if (!worker->job->cancel(worker->job))
+ { /* job requests to be canceled explicitly, otherwise we assume
+ * the thread terminates itself and can be joined */
+ worker->thread->cancel(worker->thread);
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
while (this->total_threads > 0)
{
this->job_added->broadcast(this->job_added);
this->thread_terminated->wait(this->thread_terminated, this->mutex);
}
while (this->threads->remove_first(this->threads,
- (void**)&current) == SUCCESS)
+ (void**)&worker) == SUCCESS)
{
- current->join(current);
+ worker->thread->join(worker->thread);
+ free(worker);
}
this->mutex->unlock(this->mutex);
- this->priority->destroy(this->priority);
+}
+
+METHOD(processor_t, destroy, void,
+ private_processor_t *this)
+{
+ int i;
+
+ cancel(this);
this->thread_terminated->destroy(this->thread_terminated);
this->job_added->destroy(this->job_added);
this->mutex->destroy(this->mutex);
@@ -348,10 +461,10 @@ processor_t *processor_create()
.get_job_load = _get_job_load,
.queue_job = _queue_job,
.set_threads = _set_threads,
+ .cancel = _cancel,
.destroy = _destroy,
},
.threads = linked_list_create(),
- .priority = thread_value_create(NULL),
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
.job_added = condvar_create(CONDVAR_TYPE_DEFAULT),
.thread_terminated = condvar_create(CONDVAR_TYPE_DEFAULT),
diff --git a/src/libstrongswan/processing/processor.h b/src/libstrongswan/processing/processor.h
index 5db42c04c..94860f5d3 100644
--- a/src/libstrongswan/processing/processor.h
+++ b/src/libstrongswan/processing/processor.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -51,7 +52,7 @@ struct processor_t {
/**
* Get the number of threads currently working, per priority class.
*
- * @param prioritiy to check
+ * @param priority to check
* @return number of threads in priority working
*/
u_int (*get_working_threads)(processor_t *this, job_priority_t prio);
@@ -78,14 +79,21 @@ struct processor_t {
*
* If the number of threads is smaller than number of currently running
* threads, thread count is decreased. Use 0 to disable the processor.
- * This call blocks if it decreases thread count until threads have
- * terminated, so make sure there are not too many blocking jobs.
+ *
+ * This call does not block and wait for threads to terminate if the number
+ * of threads is reduced. Instead use cancel() for that during shutdown.
*
* @param count number of threads to allocate
*/
void (*set_threads)(processor_t *this, u_int count);
/**
+ * Sets the number of threads to 0 and cancels all blocking jobs, then waits
+ * for all threads to be terminated.
+ */
+ void (*cancel)(processor_t *this);
+
+ /**
* Destroy a processor object.
*/
void (*destroy) (processor_t *processor);
diff --git a/src/libstrongswan/processing/scheduler.c b/src/libstrongswan/processing/scheduler.c
index f3cc1164a..c97dbc4be 100644
--- a/src/libstrongswan/processing/scheduler.c
+++ b/src/libstrongswan/processing/scheduler.c
@@ -68,11 +68,6 @@ struct private_scheduler_t {
scheduler_t public;
/**
- * Job which queues scheduled jobs to the processor.
- */
- callback_job_t *job;
-
- /**
* The heap in which the events are stored.
*/
event_t **heap;
@@ -250,6 +245,7 @@ METHOD(scheduler_t, schedule_job_tv, void,
event = malloc_thing(event_t);
event->job = job;
+ event->job->status = JOB_STATUS_QUEUED;
event->time = tv;
this->mutex->lock(this->mutex);
@@ -308,7 +304,6 @@ METHOD(scheduler_t, destroy, void,
private_scheduler_t *this)
{
event_t *event;
- this->job->cancel(this->job);
this->condvar->destroy(this->condvar);
this->mutex->destroy(this->mutex);
while ((event = remove_event(this)) != NULL)
@@ -325,6 +320,7 @@ METHOD(scheduler_t, destroy, void,
scheduler_t * scheduler_create()
{
private_scheduler_t *this;
+ callback_job_t *job;
INIT(this,
.public = {
@@ -341,9 +337,9 @@ scheduler_t * scheduler_create()
this->heap = (event_t**)calloc(this->heap_size + 1, sizeof(event_t*));
- this->job = callback_job_create_with_prio((callback_job_cb_t)schedule,
- this, NULL, NULL, JOB_PRIO_CRITICAL);
- lib->processor->queue_job(lib->processor, (job_t*)this->job);
+ job = callback_job_create_with_prio((callback_job_cb_t)schedule, this,
+ NULL, return_false, JOB_PRIO_CRITICAL);
+ lib->processor->queue_job(lib->processor, (job_t*)job);
return &this->public;
}
diff --git a/src/libstrongswan/selectors/traffic_selector.c b/src/libstrongswan/selectors/traffic_selector.c
index b1bcf1b2d..b19b962e6 100644
--- a/src/libstrongswan/selectors/traffic_selector.c
+++ b/src/libstrongswan/selectors/traffic_selector.c
@@ -179,8 +179,8 @@ static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol, ts
/**
* Described in header.
*/
-int traffic_selector_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
- const void *const *args)
+int traffic_selector_printf_hook(printf_hook_data_t *data,
+ printf_hook_spec_t *spec, const void *const *args)
{
private_traffic_selector_t *this = *((private_traffic_selector_t**)(args[0]));
linked_list_t *list = *((linked_list_t**)(args[0]));
@@ -195,7 +195,7 @@ int traffic_selector_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec
if (this == NULL)
{
- return print_in_hook(dst, len, "(null)");
+ return print_in_hook(data, "(null)");
}
if (spec->hash)
@@ -204,7 +204,7 @@ int traffic_selector_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec
while (enumerator->enumerate(enumerator, (void**)&this))
{
/* call recursivly */
- written += print_in_hook(dst, len, "%R ", this);
+ written += print_in_hook(data, "%R ", this);
}
enumerator->destroy(enumerator);
return written;
@@ -216,7 +216,7 @@ int traffic_selector_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec
memeq(this->from, from, this->type == TS_IPV4_ADDR_RANGE ? 4 : 16) &&
memeq(this->to, to, this->type == TS_IPV4_ADDR_RANGE ? 4 : 16))
{
- written += print_in_hook(dst, len, "dynamic");
+ written += print_in_hook(data, "dynamic");
}
else
{
@@ -238,11 +238,11 @@ int traffic_selector_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec
{
inet_ntop(AF_INET6, &this->to6, to_str, sizeof(to_str));
}
- written += print_in_hook(dst, len, "%s..%s", from_str, to_str);
+ written += print_in_hook(data, "%s..%s", from_str, to_str);
}
else
{
- written += print_in_hook(dst, len, "%s/%d", from_str, this->netbits);
+ written += print_in_hook(data, "%s/%d", from_str, this->netbits);
}
}
@@ -255,7 +255,7 @@ int traffic_selector_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec
return written;
}
- written += print_in_hook(dst, len, "[");
+ written += print_in_hook(data, "[");
/* build protocol string */
if (has_proto)
@@ -264,18 +264,18 @@ int traffic_selector_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec
if (proto)
{
- written += print_in_hook(dst, len, "%s", proto->p_name);
+ written += print_in_hook(data, "%s", proto->p_name);
serv_proto = proto->p_name;
}
else
{
- written += print_in_hook(dst, len, "%d", this->protocol);
+ written += print_in_hook(data, "%d", this->protocol);
}
}
if (has_proto && has_ports)
{
- written += print_in_hook(dst, len, "/");
+ written += print_in_hook(data, "/");
}
/* build port string */
@@ -287,20 +287,20 @@ int traffic_selector_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec
if (serv)
{
- written += print_in_hook(dst, len, "%s", serv->s_name);
+ written += print_in_hook(data, "%s", serv->s_name);
}
else
{
- written += print_in_hook(dst, len, "%d", this->from_port);
+ written += print_in_hook(data, "%d", this->from_port);
}
}
else
{
- written += print_in_hook(dst, len, "%d-%d", this->from_port, this->to_port);
+ written += print_in_hook(data, "%d-%d", this->from_port, this->to_port);
}
}
- written += print_in_hook(dst, len, "]");
+ written += print_in_hook(data, "]");
return written;
}
@@ -310,6 +310,10 @@ int traffic_selector_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec
*/
static traffic_selector_t *get_subset(private_traffic_selector_t *this, private_traffic_selector_t *other)
{
+ if (this->dynamic || other->dynamic)
+ { /* no set_address() applied, TS has no subset */
+ return NULL;
+ }
if (this->type == other->type && (this->protocol == other->protocol ||
this->protocol == 0 || other->protocol == 0))
{
@@ -367,7 +371,6 @@ static traffic_selector_t *get_subset(private_traffic_selector_t *this, private_
/* we have a match in protocol, port, and address: return it... */
new_ts = traffic_selector_create(protocol, this->type, from_port, to_port);
- new_ts->dynamic = this->dynamic || other->dynamic;
memcpy(new_ts->from, from, size);
memcpy(new_ts->to, to, size);
calc_netbits(new_ts);
@@ -510,7 +513,7 @@ METHOD(traffic_selector_t, is_dynamic, bool,
METHOD(traffic_selector_t, set_address, void,
private_traffic_selector_t *this, host_t *host)
{
- if (this->dynamic)
+ if (is_host(this, NULL))
{
this->type = host->get_family(host) == AF_INET ?
TS_IPV4_ADDR_RANGE : TS_IPV6_ADDR_RANGE;
@@ -528,6 +531,7 @@ METHOD(traffic_selector_t, set_address, void,
memcpy(this->to, from.ptr, from.len);
this->netbits = from.len * 8;
}
+ this->dynamic = FALSE;
}
}
@@ -571,7 +575,7 @@ METHOD(traffic_selector_t, includes, bool,
return FALSE;
}
-METHOD(traffic_selector_t, to_subnet, void,
+METHOD(traffic_selector_t, to_subnet, bool,
private_traffic_selector_t *this, host_t **net, u_int8_t *mask)
{
/* there is no way to do this cleanly, as the address range may
@@ -597,7 +601,7 @@ METHOD(traffic_selector_t, to_subnet, void,
break;
default:
/* unreachable */
- return;
+ return FALSE;
}
net_chunk.ptr = malloc(net_chunk.len);
@@ -616,6 +620,8 @@ METHOD(traffic_selector_t, to_subnet, void,
*net = host_create_from_chunk(family, net_chunk, port);
chunk_free(&net_chunk);
+
+ return this->netbits != NON_SUBNET_ADDRESS_RANGE;
}
METHOD(traffic_selector_t, clone_, traffic_selector_t*,
@@ -735,66 +741,36 @@ traffic_selector_t *traffic_selector_create_from_rfc3779_format(ts_type_t type,
traffic_selector_t *traffic_selector_create_from_subnet(host_t *net,
u_int8_t netbits, u_int8_t protocol, u_int16_t port)
{
- private_traffic_selector_t *this = traffic_selector_create(protocol, 0, 0, 65535);
+ private_traffic_selector_t *this;
+ chunk_t from;
+
+ this = traffic_selector_create(protocol, 0, 0, 65535);
switch (net->get_family(net))
{
case AF_INET:
- {
- chunk_t from;
-
this->type = TS_IPV4_ADDR_RANGE;
- from = net->get_address(net);
- memcpy(this->from, from.ptr, from.len);
- if (this->from4[0] == 0)
- {
- /* use /0 for 0.0.0.0 */
- this->to4[0] = ~0;
- this->netbits = 0;
- }
- else
- {
- calc_range(this, netbits);
- }
break;
- }
case AF_INET6:
- {
- chunk_t from;
-
this->type = TS_IPV6_ADDR_RANGE;
- from = net->get_address(net);
- memcpy(this->from, from.ptr, from.len);
- if (this->from6[0] == 0 && this->from6[1] == 0 &&
- this->from6[2] == 0 && this->from6[3] == 0)
- {
- /* use /0 for ::0 */
- this->to6[0] = ~0;
- this->to6[1] = ~0;
- this->to6[2] = ~0;
- this->to6[3] = ~0;
- this->netbits = 0;
- }
- else
- {
- calc_range(this, netbits);
- }
break;
- }
default:
- {
net->destroy(net);
free(this);
return NULL;
- }
}
+ from = net->get_address(net);
+ memcpy(this->from, from.ptr, from.len);
+ netbits = min(netbits, this->type == TS_IPV4_ADDR_RANGE ? 32 : 128);
+ calc_range(this, netbits);
if (port)
{
this->from_port = port;
this->to_port = port;
}
net->destroy(net);
- return (&this->public);
+
+ return &this->public;
}
/*
diff --git a/src/libstrongswan/selectors/traffic_selector.h b/src/libstrongswan/selectors/traffic_selector.h
index 257da3f24..7a81521e9 100644
--- a/src/libstrongswan/selectors/traffic_selector.h
+++ b/src/libstrongswan/selectors/traffic_selector.h
@@ -203,8 +203,9 @@ struct traffic_selector_t {
*
* @param net converted subnet (has to be freed)
* @param mask converted net mask
+ * @return TRUE if traffic selector matches exactly to the subnet
*/
- void (*to_subnet) (traffic_selector_t *this, host_t **net, u_int8_t *mask);
+ bool (*to_subnet) (traffic_selector_t *this, host_t **net, u_int8_t *mask);
/**
* Destroys the ts object
@@ -309,7 +310,7 @@ traffic_selector_t *traffic_selector_create_dynamic(u_int8_t protocol,
* With the #-specifier, arguments are:
* linked_list_t *list containing traffic_selector_t*
*/
-int traffic_selector_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
- const void *const *args);
+int traffic_selector_printf_hook(printf_hook_data_t *data,
+ printf_hook_spec_t *spec, const void *const *args);
#endif /** TRAFFIC_SELECTOR_H_ @}*/
diff --git a/src/libstrongswan/settings.c b/src/libstrongswan/settings.c
index b26fbebb4..8977cd9ed 100644
--- a/src/libstrongswan/settings.c
+++ b/src/libstrongswan/settings.c
@@ -1117,14 +1117,21 @@ static bool load_files_internal(private_settings_t *this, section_t *parent,
char *pattern, bool merge)
{
char *text;
- linked_list_t *contents = linked_list_create();
- section_t *section = section_create(NULL);
+ linked_list_t *contents;
+ section_t *section;
if (pattern == NULL)
{
+#ifdef STRONGSWAN_CONF
pattern = STRONGSWAN_CONF;
+#else
+ return FALSE;
+#endif
}
+ contents = linked_list_create();
+ section = section_create(NULL);
+
if (!parse_files(contents, NULL, 0, pattern, section))
{
contents->destroy_function(contents, (void*)free);
diff --git a/src/libstrongswan/settings.h b/src/libstrongswan/settings.h
index a864779f1..c8b50d008 100644
--- a/src/libstrongswan/settings.h
+++ b/src/libstrongswan/settings.h
@@ -189,7 +189,7 @@ struct settings_t {
* @param key key including sections, printf style format
* @param def value returned if key not found
* @param ... argument list for key
- * @return value of the key
+ * @return value of the key (in seconds)
*/
u_int32_t (*get_time)(settings_t *this, char *key, u_int32_t def, ...);
diff --git a/src/libstrongswan/threading/mutex.c b/src/libstrongswan/threading/mutex.c
index 3bdb3bf29..2ef918a28 100644
--- a/src/libstrongswan/threading/mutex.c
+++ b/src/libstrongswan/threading/mutex.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2009 Tobias Brunner
+ * Copyright (C) 2008-2012 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -73,9 +73,9 @@ struct private_r_mutex_t {
pthread_t thread;
/**
- * times we have locked the lock, stored per thread
+ * times the current thread locked the mutex
*/
- pthread_key_t times;
+ u_int times;
};
/**
@@ -127,35 +127,24 @@ METHOD(mutex_t, lock_r, void,
{
pthread_t self = pthread_self();
- if (this->thread == self)
+ if (pthread_equal(this->thread, self))
{
- uintptr_t times;
-
- /* times++ */
- times = (uintptr_t)pthread_getspecific(this->times);
- pthread_setspecific(this->times, (void*)times + 1);
+ this->times++;
}
else
{
lock(&this->generic);
this->thread = self;
- /* times = 1 */
- pthread_setspecific(this->times, (void*)1);
+ this->times = 1;
}
}
METHOD(mutex_t, unlock_r, void,
private_r_mutex_t *this)
{
- uintptr_t times;
-
- /* times-- */
- times = (uintptr_t)pthread_getspecific(this->times);
- pthread_setspecific(this->times, (void*)--times);
-
- if (times == 0)
+ if (--this->times == 0)
{
- this->thread = 0;
+ memset(&this->thread, 0, sizeof(this->thread));
unlock(&this->generic);
}
}
@@ -173,7 +162,6 @@ METHOD(mutex_t, mutex_destroy_r, void,
{
profiler_cleanup(&this->generic.profile);
pthread_mutex_destroy(&this->generic.mutex);
- pthread_key_delete(this->times);
free(this);
}
@@ -200,7 +188,6 @@ mutex_t *mutex_create(mutex_type_t type)
);
pthread_mutex_init(&this->generic.mutex, NULL);
- pthread_key_create(&this->times, NULL);
profiler_init(&this->generic.profile);
return &this->generic.public;
@@ -233,11 +220,15 @@ METHOD(condvar_t, wait_, void,
if (mutex->recursive)
{
private_r_mutex_t* recursive = (private_r_mutex_t*)mutex;
+ u_int times;
+ /* keep track of the number of times this thread locked the mutex */
+ times = recursive->times;
/* mutex owner gets cleared during condvar wait */
- recursive->thread = 0;
+ memset(&recursive->thread, 0, sizeof(recursive->thread));
pthread_cond_wait(&this->condvar, &mutex->mutex);
recursive->thread = pthread_self();
+ recursive->times = times;
}
else
{
@@ -262,11 +253,14 @@ METHOD(condvar_t, timed_wait_abs, bool,
if (mutex->recursive)
{
private_r_mutex_t* recursive = (private_r_mutex_t*)mutex;
+ u_int times;
- recursive->thread = 0;
+ times = recursive->times;
+ memset(&recursive->thread, 0, sizeof(recursive->thread));
timed_out = pthread_cond_timedwait(&this->condvar, &mutex->mutex,
&ts) == ETIMEDOUT;
recursive->thread = pthread_self();
+ recursive->times = times;
}
else
{
diff --git a/src/libstrongswan/threading/rwlock.c b/src/libstrongswan/threading/rwlock.c
index 15dc0b334..7097a8e8c 100644
--- a/src/libstrongswan/threading/rwlock.c
+++ b/src/libstrongswan/threading/rwlock.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2009 Tobias Brunner
+ * Copyright (C) 2008-2012 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -21,11 +21,14 @@
#include <debug.h>
#include "rwlock.h"
+#include "rwlock_condvar.h"
+#include "thread.h"
#include "condvar.h"
#include "mutex.h"
#include "lock_profiler.h"
typedef struct private_rwlock_t private_rwlock_t;
+typedef struct private_rwlock_condvar_t private_rwlock_condvar_t;
/**
* private data of rwlock
@@ -72,9 +75,9 @@ struct private_rwlock_t {
u_int reader_count;
/**
- * current writer thread, if any
+ * TRUE, if a writer is holding the lock currently
*/
- pthread_t writer;
+ bool writer;
#endif /* HAVE_PTHREAD_RWLOCK_INIT */
@@ -84,6 +87,27 @@ struct private_rwlock_t {
lock_profile_t profile;
};
+/**
+ * private data of condvar
+ */
+struct private_rwlock_condvar_t {
+
+ /**
+ * public interface
+ */
+ rwlock_condvar_t public;
+
+ /**
+ * mutex used to implement rwlock condvar
+ */
+ mutex_t *mutex;
+
+ /**
+ * regular condvar to implement rwlock condvar
+ */
+ condvar_t *condvar;
+};
+
#ifdef HAVE_PTHREAD_RWLOCK_INIT
@@ -175,37 +199,81 @@ rwlock_t *rwlock_create(rwlock_type_t type)
/**
* This implementation of the rwlock_t interface uses mutex_t and condvar_t
- * primitives, if the pthread_rwlock_* group of functions is not available.
+ * primitives, if the pthread_rwlock_* group of functions is not available or
+ * don't allow recursive locking for readers.
*
* The following constraints are enforced:
* - Multiple readers can hold the lock at the same time.
* - Only a single writer can hold the lock at any given time.
* - A writer must block until all readers have released the lock before
* obtaining the lock exclusively.
- * - Readers that arrive while a writer is waiting to acquire the lock will
- * block until after the writer has obtained and released the lock.
+ * - Readers that don't hold any read lock and arrive while a writer is
+ * waiting to acquire the lock will block until after the writer has
+ * obtained and released the lock.
* These constraints allow for read sharing, prevent write sharing, prevent
- * read-write sharing and prevent starvation of writers by a steady stream
- * of incoming readers. Reader starvation is not prevented (this could happen
- * if there are more writers than readers).
+ * read-write sharing and (largely) prevent starvation of writers by a steady
+ * stream of incoming readers. Reader starvation is not prevented (this could
+ * happen if there are more writers than readers).
*
- * The implementation does not support recursive locking and readers must not
- * acquire the lock exclusively at the same time and vice-versa (this is not
- * checked or enforced so behave yourself to prevent deadlocks).
+ * The implementation supports recursive locking of the read lock but not of
+ * the write lock. Readers must not acquire the lock exclusively at the same
+ * time and vice-versa (this is not checked or enforced so behave yourself to
+ * prevent deadlocks).
+ *
+ * Since writers are preferred a thread currently holding the read lock that
+ * tries to acquire the read lock recursively while a writer is waiting would
+ * result in a deadlock. In order to avoid having to use a thread-specific
+ * value for each rwlock_t (or a list of threads) to keep track if a thread
+ * already acquired the read lock we use a single thread-specific value for all
+ * rwlock_t objects that keeps track of how many read locks a thread currently
+ * holds. Preferring readers that already hold ANY read locks prevents this
+ * deadlock while it still largely avoids writer starvation (for locks that can
+ * only be acquired while holding another read lock this will obviously not
+ * work).
*/
+/**
+ * Keep track of how many read locks a thread holds.
+ */
+static pthread_key_t is_reader;
+
+/**
+ * Only initialize the read lock counter once.
+ */
+static pthread_once_t is_reader_initialized = PTHREAD_ONCE_INIT;
+
+/**
+ * Initialize the read lock counter.
+ */
+static void initialize_is_reader()
+{
+ pthread_key_create(&is_reader, NULL);
+}
+
METHOD(rwlock_t, read_lock, void,
private_rwlock_t *this)
{
+ uintptr_t reading;
+
+ reading = (uintptr_t)pthread_getspecific(is_reader);
profiler_start(&this->profile);
this->mutex->lock(this->mutex);
- while (this->writer || this->waiting_writers)
+ if (!this->writer && reading > 0)
{
- this->readers->wait(this->readers, this->mutex);
+ /* directly allow threads that hold ANY read locks, to avoid a deadlock
+ * caused by preferring writers in the loop below */
+ }
+ else
+ {
+ while (this->writer || this->waiting_writers)
+ {
+ this->readers->wait(this->readers, this->mutex);
+ }
}
this->reader_count++;
profiler_end(&this->profile);
this->mutex->unlock(this->mutex);
+ pthread_setspecific(is_reader, (void*)(reading + 1));
}
METHOD(rwlock_t, write_lock, void,
@@ -219,7 +287,7 @@ METHOD(rwlock_t, write_lock, void,
this->writers->wait(this->writers, this->mutex);
}
this->waiting_writers--;
- this->writer = pthread_self();
+ this->writer = TRUE;
profiler_end(&this->profile);
this->mutex->unlock(this->mutex);
}
@@ -231,8 +299,7 @@ METHOD(rwlock_t, try_write_lock, bool,
this->mutex->lock(this->mutex);
if (!this->writer && !this->reader_count)
{
- res = TRUE;
- this->writer = pthread_self();
+ res = this->writer = TRUE;
}
this->mutex->unlock(this->mutex);
return res;
@@ -242,9 +309,20 @@ METHOD(rwlock_t, unlock, void,
private_rwlock_t *this)
{
this->mutex->lock(this->mutex);
- if (this->writer == pthread_self())
+ if (this->writer)
+ {
+ this->writer = FALSE;
+ }
+ else
+ {
+ uintptr_t reading;
+
+ this->reader_count--;
+ reading = (uintptr_t)pthread_getspecific(is_reader);
+ pthread_setspecific(is_reader, (void*)(reading - 1));
+ }
+ if (!this->reader_count)
{
- this->writer = 0;
if (this->waiting_writers)
{
this->writers->signal(this->writers);
@@ -254,14 +332,6 @@ METHOD(rwlock_t, unlock, void,
this->readers->broadcast(this->readers);
}
}
- else
- {
- this->reader_count--;
- if (!this->reader_count)
- {
- this->writers->signal(this->writers);
- }
- }
this->mutex->unlock(this->mutex);
}
@@ -280,6 +350,8 @@ METHOD(rwlock_t, destroy, void,
*/
rwlock_t *rwlock_create(rwlock_type_t type)
{
+ pthread_once(&is_reader_initialized, initialize_is_reader);
+
switch (type)
{
case RWLOCK_TYPE_DEFAULT:
@@ -309,3 +381,110 @@ rwlock_t *rwlock_create(rwlock_type_t type)
#endif /* HAVE_PTHREAD_RWLOCK_INIT */
+
+METHOD(rwlock_condvar_t, wait_, void,
+ private_rwlock_condvar_t *this, rwlock_t *lock)
+{
+ /* at this point we have the write lock locked, to make signals more
+ * predictable we try to prevent other threads from signaling by acquiring
+ * the mutex while we still hold the write lock (this assumes they will
+ * hold the write lock themselves when signaling, which is not mandatory) */
+ this->mutex->lock(this->mutex);
+ /* unlock the rwlock and wait for a signal */
+ lock->unlock(lock);
+ /* if the calling thread enabled thread cancelability we want to replicate
+ * the behavior of the regular condvar, i.e. the lock will be held again
+ * before executing cleanup functions registered by the calling thread */
+ thread_cleanup_push((thread_cleanup_t)lock->write_lock, lock);
+ thread_cleanup_push((thread_cleanup_t)this->mutex->unlock, this->mutex);
+ this->condvar->wait(this->condvar, this->mutex);
+ /* we release the mutex to allow other threads into the condvar (might even
+ * be required so we can acquire the lock again below) */
+ thread_cleanup_pop(TRUE);
+ /* finally we reacquire the lock we held previously */
+ thread_cleanup_pop(TRUE);
+}
+
+METHOD(rwlock_condvar_t, timed_wait_abs, bool,
+ private_rwlock_condvar_t *this, rwlock_t *lock, timeval_t time)
+{
+ bool timed_out;
+
+ /* see wait() above for details on what is going on here */
+ this->mutex->lock(this->mutex);
+ lock->unlock(lock);
+ thread_cleanup_push((thread_cleanup_t)lock->write_lock, lock);
+ thread_cleanup_push((thread_cleanup_t)this->mutex->unlock, this->mutex);
+ timed_out = this->condvar->timed_wait_abs(this->condvar, this->mutex, time);
+ thread_cleanup_pop(TRUE);
+ thread_cleanup_pop(!timed_out);
+ return timed_out;
+}
+
+METHOD(rwlock_condvar_t, timed_wait, bool,
+ private_rwlock_condvar_t *this, rwlock_t *lock, u_int timeout)
+{
+ timeval_t tv;
+ u_int s, ms;
+
+ time_monotonic(&tv);
+
+ s = timeout / 1000;
+ ms = timeout % 1000;
+
+ tv.tv_sec += s;
+ tv.tv_usec += ms * 1000;
+
+ if (tv.tv_usec > 1000000 /* 1s */)
+ {
+ tv.tv_usec -= 1000000;
+ tv.tv_sec++;
+ }
+ return timed_wait_abs(this, lock, tv);
+}
+
+METHOD(rwlock_condvar_t, signal_, void,
+ private_rwlock_condvar_t *this)
+{
+ this->mutex->lock(this->mutex);
+ this->condvar->signal(this->condvar);
+ this->mutex->unlock(this->mutex);
+}
+
+METHOD(rwlock_condvar_t, broadcast, void,
+ private_rwlock_condvar_t *this)
+{
+ this->mutex->lock(this->mutex);
+ this->condvar->broadcast(this->condvar);
+ this->mutex->unlock(this->mutex);
+}
+
+METHOD(rwlock_condvar_t, condvar_destroy, void,
+ private_rwlock_condvar_t *this)
+{
+ this->condvar->destroy(this->condvar);
+ this->mutex->destroy(this->mutex);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+rwlock_condvar_t *rwlock_condvar_create()
+{
+ private_rwlock_condvar_t *this;
+
+ INIT(this,
+ .public = {
+ .wait = _wait_,
+ .timed_wait = _timed_wait,
+ .timed_wait_abs = _timed_wait_abs,
+ .signal = _signal_,
+ .broadcast = _broadcast,
+ .destroy = _condvar_destroy,
+ },
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ .condvar = condvar_create(CONDVAR_TYPE_DEFAULT),
+ );
+ return &this->public;
+}
diff --git a/src/libstrongswan/threading/rwlock_condvar.h b/src/libstrongswan/threading/rwlock_condvar.h
new file mode 100644
index 000000000..2b40c3fc6
--- /dev/null
+++ b/src/libstrongswan/threading/rwlock_condvar.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup rwlock_condvar rwlock_condvar
+ * @{ @ingroup threading
+ */
+
+#ifndef RWLOCK_CONDVAR_H_
+#define RWLOCK_CONDVAR_H_
+
+typedef struct rwlock_condvar_t rwlock_condvar_t;
+
+#include "rwlock.h"
+
+/**
+ * A special condvar implementation that can be used in conjunction
+ * with rwlock_t (the write lock to be precise).
+ *
+ * @note The implementation does not verify that the current thread actually
+ * holds the write lock and not the read lock, so watch out.
+ */
+struct rwlock_condvar_t {
+
+ /**
+ * Wait on a condvar until it gets signalized.
+ *
+ * @param lock lock to release while waiting (write lock)
+ */
+ void (*wait)(rwlock_condvar_t *this, rwlock_t *lock);
+
+ /**
+ * Wait on a condvar until it gets signalized, or times out.
+ *
+ * @param lock lock to release while waiting (write lock)
+ * @param timeout timeout im ms
+ * @return TRUE if timed out, FALSE otherwise
+ */
+ bool (*timed_wait)(rwlock_condvar_t *this, rwlock_t *lock, u_int timeout);
+
+ /**
+ * Wait on a condvar until it gets signalized, or times out.
+ *
+ * The passed timeval should be calculated based on the time_monotonic()
+ * function.
+ *
+ * @param lock lock to release while waiting (write lock)
+ * @param tv absolute time until timeout
+ * @return TRUE if timed out, FALSE otherwise
+ */
+ bool (*timed_wait_abs)(rwlock_condvar_t *this, rwlock_t *lock,
+ timeval_t tv);
+
+ /**
+ * Wake up a single thread in a condvar.
+ */
+ void (*signal)(rwlock_condvar_t *this);
+
+ /**
+ * Wake up all threads in a condvar.
+ */
+ void (*broadcast)(rwlock_condvar_t *this);
+
+ /**
+ * Destroy a condvar and free its resources.
+ */
+ void (*destroy)(rwlock_condvar_t *this);
+};
+
+/**
+ * Create a condvar instance.
+ *
+ * @return condvar instance
+ */
+rwlock_condvar_t *rwlock_condvar_create();
+
+#endif /** RWLOCK_CONDVAR_H_ @} */
+
diff --git a/src/libstrongswan/threading/semaphore.c b/src/libstrongswan/threading/semaphore.c
new file mode 100644
index 000000000..b785ff944
--- /dev/null
+++ b/src/libstrongswan/threading/semaphore.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2011 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <library.h>
+
+#if defined(HAVE_CLOCK_GETTIME) && \
+ (defined(HAVE_CONDATTR_CLOCK_MONOTONIC) || \
+ defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC))
+/* if we use MONOTONIC times, we can't use POSIX_SEMAPHORES since they use
+ * times based on CLOCK_REALTIME */
+#undef HAVE_SEM_TIMEDWAIT
+#endif /* HAVE_CLOCK_GETTIME && ... */
+
+#ifdef HAVE_SEM_TIMEDWAIT
+#include <semaphore.h>
+#else /* !HAVE_SEM_TIMEDWAIT */
+#include <threading/condvar.h>
+#endif /* HAVE_SEM_TIMEDWAIT */
+
+#include "semaphore.h"
+
+typedef struct private_semaphore_t private_semaphore_t;
+
+/**
+ * private data of a semaphore
+ */
+struct private_semaphore_t {
+ /**
+ * public interface
+ */
+ semaphore_t public;
+
+#ifdef HAVE_SEM_TIMEDWAIT
+ /**
+ * wrapped POSIX semaphore object
+ */
+ sem_t sem;
+#else /* !HAVE_SEM_TIMEDWAIT */
+
+ /**
+ * Mutex to lock count variable
+ */
+ mutex_t *mutex;
+
+ /**
+ * Condvar to signal count increase
+ */
+ condvar_t *cond;
+
+ /**
+ * Semaphore count value
+ */
+ u_int count;
+#endif /* HAVE_SEM_TIMEDWAIT */
+};
+
+METHOD(semaphore_t, wait_, void,
+ private_semaphore_t *this)
+{
+#ifdef HAVE_SEM_TIMEDWAIT
+ sem_wait(&this->sem);
+#else /* !HAVE_SEM_TIMEDWAIT */
+ this->mutex->lock(this->mutex);
+ while (this->count == 0)
+ {
+ this->cond->wait(this->cond, this->mutex);
+ }
+ this->count--;
+ this->mutex->unlock(this->mutex);
+#endif /* HAVE_SEM_TIMEDWAIT */
+}
+
+METHOD(semaphore_t, timed_wait_abs, bool,
+ private_semaphore_t *this, timeval_t tv)
+{
+#ifdef HAVE_SEM_TIMEDWAIT
+ timespec_t ts;
+
+ ts.tv_sec = tv.tv_sec;
+ ts.tv_nsec = tv.tv_usec * 1000;
+
+ /* there are errors other than ETIMEDOUT possible, but we consider them
+ * all as timeout */
+ return sem_timedwait(&this->sem, &ts) == -1;
+#else /* !HAVE_SEM_TIMEDWAIT */
+ this->mutex->lock(this->mutex);
+ while (this->count == 0)
+ {
+ if (this->cond->timed_wait_abs(this->cond, this->mutex, tv))
+ {
+ this->mutex->unlock(this->mutex);
+ return TRUE;
+ }
+ }
+ this->count--;
+ this->mutex->unlock(this->mutex);
+ return FALSE;
+#endif /* HAVE_SEM_TIMEDWAIT */
+}
+
+METHOD(semaphore_t, timed_wait, bool,
+ private_semaphore_t *this, u_int timeout)
+{
+ timeval_t tv, add;
+
+ add.tv_sec = timeout / 1000;
+ add.tv_usec = (timeout % 1000) * 1000;
+
+ time_monotonic(&tv);
+ timeradd(&tv, &add, &tv);
+
+ return timed_wait_abs(this, tv);
+}
+
+METHOD(semaphore_t, post, void,
+ private_semaphore_t *this)
+{
+#ifdef HAVE_SEM_TIMEDWAIT
+ sem_post(&this->sem);
+#else /* !HAVE_SEM_TIMEDWAIT */
+ this->mutex->lock(this->mutex);
+ this->count++;
+ this->mutex->unlock(this->mutex);
+ this->cond->signal(this->cond);
+#endif /* HAVE_SEM_TIMEDWAIT */
+}
+
+METHOD(semaphore_t, destroy, void,
+ private_semaphore_t *this)
+{
+#ifdef HAVE_SEM_TIMEDWAIT
+ sem_destroy(&this->sem);
+#else /* !HAVE_SEM_TIMEDWAIT */
+ this->cond->destroy(this->cond);
+ this->mutex->destroy(this->mutex);
+#endif /* HAVE_SEM_TIMEDWAIT */
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+semaphore_t *semaphore_create(u_int value)
+{
+ private_semaphore_t *this;
+
+ INIT(this,
+ .public = {
+ .wait = _wait_,
+ .timed_wait = _timed_wait,
+ .timed_wait_abs = _timed_wait_abs,
+ .post = _post,
+ .destroy = _destroy,
+ },
+ );
+
+#ifdef HAVE_SEM_TIMEDWAIT
+ sem_init(&this->sem, 0, value);
+#else /* !HAVE_SEM_TIMEDWAIT */
+ this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);
+ this->cond = condvar_create(CONDVAR_TYPE_DEFAULT);
+ this->count = value;
+#endif /* HAVE_SEM_TIMEDWAIT */
+
+ return &this->public;
+}
+
diff --git a/src/libstrongswan/threading/semaphore.h b/src/libstrongswan/threading/semaphore.h
new file mode 100644
index 000000000..cdb0a6f19
--- /dev/null
+++ b/src/libstrongswan/threading/semaphore.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2011 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup semaphore semaphore
+ * @{ @ingroup threading
+ */
+
+#ifndef THREADING_SEMAPHORE_H_
+#define THREADING_SEMAPHORE_H_
+
+typedef struct semaphore_t semaphore_t;
+
+/**
+ * A semaphore is basically an integer whose value is never allowed to be
+ * lower than 0. Two operations can be performed on it: increment the
+ * value by one, and decrement the value by one. If the value is currently
+ * zero, then the decrement operation will blcok until the value becomes
+ * greater than zero.
+ */
+struct semaphore_t {
+
+ /**
+ * Decrease the value by one, if it is greater than zero. Otherwise the
+ * current thread is blocked and it waits until the value increases.
+ */
+ void (*wait)(semaphore_t *this);
+
+ /**
+ * Decrease the value by one, if it is greater than zero. Otherwise the
+ * current thread is blocked and it waits until the value increases, or the
+ * call times out.
+ *
+ * @param timeout timeout im ms
+ * @return TRUE if timed out, FALSE otherwise
+ */
+ bool (*timed_wait)(semaphore_t *this, u_int timeout);
+
+ /**
+ * Decrease the value by one, if it is greater than zero. Otherwise the
+ * current thread is blocked and it waits until the value increases, or the
+ * call times out.
+ *
+ * The passed timeval should be calculated based on the time_monotonic()
+ * function.
+ *
+ * @param tv absolute time until timeout
+ * @return TRUE if timed out, FALSE otherwise
+ */
+ bool (*timed_wait_abs)(semaphore_t *this, timeval_t tv);
+
+ /**
+ * Increase the value by one. If the value becomes greater than zero, then
+ * another thread waiting will be woken up.
+ */
+ void (*post)(semaphore_t *this);
+
+ /**
+ * Destroy a semaphore and free its resources.
+ */
+ void (*destroy)(semaphore_t *this);
+};
+
+/**
+ * Create a semaphore instance.
+ *
+ * @param value initial value (typically 0)
+ * @return semaphore instance
+ */
+semaphore_t *semaphore_create(u_int value);
+
+#endif /** THREADING_SEMAPHORE_H_ @} */
+
diff --git a/src/libstrongswan/threading/spinlock.c b/src/libstrongswan/threading/spinlock.c
new file mode 100644
index 000000000..812cf696b
--- /dev/null
+++ b/src/libstrongswan/threading/spinlock.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <unistd.h> /* for _POSIX_SPIN_LOCKS */
+#include <pthread.h>
+
+#include <library.h>
+#include <debug.h>
+
+#include "spinlock.h"
+#include "mutex.h"
+#include "lock_profiler.h"
+
+#if defined(_POSIX_SPIN_LOCKS) && _POSIX_SPIN_LOCKS == -1
+#undef _POSIX_SPIN_LOCKS
+#endif
+
+typedef struct private_spinlock_t private_spinlock_t;
+
+/**
+ * private data
+ */
+struct private_spinlock_t {
+
+ /**
+ * public functions
+ */
+ spinlock_t public;
+
+#ifdef _POSIX_SPIN_LOCKS
+
+ /**
+ * wrapped pthread spin lock
+ */
+ pthread_spinlock_t spinlock;
+
+ /**
+ * profiling info, if enabled (the mutex below does profile itself)
+ */
+ lock_profile_t profile;
+
+#else /* _POSIX_SPIN_LOCKS */
+
+ /**
+ * use a mutex if spin locks are not available
+ */
+ mutex_t *mutex;
+
+#endif /* _POSIX_SPIN_LOCKS */
+};
+
+METHOD(spinlock_t, lock, void,
+ private_spinlock_t *this)
+{
+#ifdef _POSIX_SPIN_LOCKS
+ int err;
+
+ profiler_start(&this->profile);
+ err = pthread_spin_lock(&this->spinlock);
+ if (err)
+ {
+ DBG1(DBG_LIB, "!!! SPIN LOCK LOCK ERROR: %s !!!", strerror(err));
+ }
+ profiler_end(&this->profile);
+#else
+ this->mutex->lock(this->mutex);
+#endif
+}
+
+METHOD(spinlock_t, unlock, void,
+ private_spinlock_t *this)
+{
+#ifdef _POSIX_SPIN_LOCKS
+ int err;
+
+ err = pthread_spin_unlock(&this->spinlock);
+ if (err)
+ {
+ DBG1(DBG_LIB, "!!! SPIN LOCK UNLOCK ERROR: %s !!!", strerror(err));
+ }
+#else
+ this->mutex->unlock(this->mutex);
+#endif
+}
+
+METHOD(spinlock_t, destroy, void,
+ private_spinlock_t *this)
+{
+#ifdef _POSIX_SPIN_LOCKS
+ profiler_cleanup(&this->profile);
+ pthread_spin_destroy(&this->spinlock);
+#else
+ this->mutex->destroy(this->mutex);
+#endif
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+spinlock_t *spinlock_create()
+{
+ private_spinlock_t *this;
+
+ INIT(this,
+ .public = {
+ .lock = _lock,
+ .unlock = _unlock,
+ .destroy = _destroy,
+ },
+ );
+
+#ifdef _POSIX_SPIN_LOCKS
+ pthread_spin_init(&this->spinlock, PTHREAD_PROCESS_PRIVATE);
+ profiler_init(&this->profile);
+#else
+ #warning Using mutexes as spin lock alternatives
+ this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);
+#endif
+
+ return &this->public;
+}
+
+
diff --git a/src/libstrongswan/threading/spinlock.h b/src/libstrongswan/threading/spinlock.h
new file mode 100644
index 000000000..883980cc2
--- /dev/null
+++ b/src/libstrongswan/threading/spinlock.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup spinlock spinlock
+ * @{ @ingroup threading
+ */
+
+#ifndef THREADING_SPINLOCK_H_
+#define THREADING_SPINLOCK_H_
+
+typedef struct spinlock_t spinlock_t;
+
+/**
+ * Spin lock wrapper implements a lock with low overhead when the lock is held
+ * only for a short time (waiting wastes processor cycles, though).
+ *
+ * If native spin locks are not available regular mutexes are used as fallback.
+ */
+struct spinlock_t {
+
+ /**
+ * Acquire the lock.
+ */
+ void (*lock)(spinlock_t *this);
+
+ /**
+ * Release the lock.
+ */
+ void (*unlock)(spinlock_t *this);
+
+ /**
+ * Destroy the instance.
+ */
+ void (*destroy)(spinlock_t *this);
+};
+
+/**
+ * Create a spin lock instance.
+ *
+ * @return unlocked instance
+ */
+spinlock_t *spinlock_create();
+
+#endif /** THREADING_SPINLOCK_H_ @} */
+
diff --git a/src/libstrongswan/threading/thread.c b/src/libstrongswan/threading/thread.c
index 49a1b8430..9ef514ebc 100644
--- a/src/libstrongswan/threading/thread.c
+++ b/src/libstrongswan/threading/thread.c
@@ -114,7 +114,7 @@ typedef struct {
/**
* Next thread ID.
*/
-static u_int next_id = 1;
+static u_int next_id;
/**
* Mutex to safely access the next thread ID.
@@ -452,6 +452,7 @@ void threads_init()
dummy1 = thread_value_create(NULL);
+ next_id = 1;
main_thread->id = 0;
main_thread->thread_id = pthread_self();
current_thread = thread_value_create(NULL);
@@ -482,4 +483,3 @@ void threads_deinit()
current_thread->destroy(current_thread);
id_mutex->destroy(id_mutex);
}
-
diff --git a/src/libstrongswan/threading/thread_value.c b/src/libstrongswan/threading/thread_value.c
index 3fa70acb2..190b7434f 100644
--- a/src/libstrongswan/threading/thread_value.c
+++ b/src/libstrongswan/threading/thread_value.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Tobias Brunner
+ * Copyright (C) 2009-2012 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -33,6 +33,11 @@ struct private_thread_value_t {
*/
pthread_key_t key;
+ /**
+ * Destructor to cleanup the value of the thread destroying this object
+ */
+ thread_cleanup_t destructor;
+
};
METHOD(thread_value_t, set, void,
@@ -50,11 +55,22 @@ METHOD(thread_value_t, get, void*,
METHOD(thread_value_t, destroy, void,
private_thread_value_t *this)
{
+ void *val;
+
+ /* the destructor is not called automatically for the thread calling
+ * pthread_key_delete() */
+ if (this->destructor)
+ {
+ val = pthread_getspecific(this->key);
+ if (val)
+ {
+ this->destructor(val);
+ }
+ }
pthread_key_delete(this->key);
free(this);
}
-
/**
* Described in header.
*/
@@ -68,6 +84,7 @@ thread_value_t *thread_value_create(thread_cleanup_t destructor)
.get = _get,
.destroy = _destroy,
},
+ .destructor = destructor,
);
pthread_key_create(&this->key, destructor);
diff --git a/src/libstrongswan/utils.c b/src/libstrongswan/utils.c
index f76245a19..d43a4bc2f 100644
--- a/src/libstrongswan/utils.c
+++ b/src/libstrongswan/utils.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2011 Tobias Brunner
+ * Copyright (C) 2008-2012 Tobias Brunner
* Copyright (C) 2005-2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -25,6 +25,7 @@
#include <limits.h>
#include <dirent.h>
#include <time.h>
+#include <pthread.h>
#include "enum.h"
#include "debug.h"
@@ -194,6 +195,85 @@ bool mkdir_p(const char *path, mode_t mode)
return TRUE;
}
+
+/**
+ * The size of the thread-specific error buffer
+ */
+#define STRERROR_BUF_LEN 256
+
+/**
+ * Key to store thread-specific error buffer
+ */
+static pthread_key_t strerror_buf_key;
+
+/**
+ * Only initialize the key above once
+ */
+static pthread_once_t strerror_buf_key_once = PTHREAD_ONCE_INIT;
+
+/**
+ * Create the key used for the thread-specific error buffer
+ */
+static void create_strerror_buf_key()
+{
+ pthread_key_create(&strerror_buf_key, free);
+}
+
+/**
+ * Retrieve the error buffer assigned to the current thread (or create it)
+ */
+static inline char *get_strerror_buf()
+{
+ char *buf;
+
+ pthread_once(&strerror_buf_key_once, create_strerror_buf_key);
+ buf = pthread_getspecific(strerror_buf_key);
+ if (!buf)
+ {
+ buf = malloc(STRERROR_BUF_LEN);
+ pthread_setspecific(strerror_buf_key, buf);
+ }
+ return buf;
+}
+
+#ifdef HAVE_STRERROR_R
+/*
+ * Described in header.
+ */
+const char *safe_strerror(int errnum)
+{
+ char *buf = get_strerror_buf(), *msg;
+
+#ifdef STRERROR_R_CHAR_P
+ /* char* version which may or may not return the original buffer */
+ msg = strerror_r(errnum, buf, STRERROR_BUF_LEN);
+#else
+ /* int version returns 0 on success */
+ msg = strerror_r(errnum, buf, STRERROR_BUF_LEN) ? "Unknown error" : buf;
+#endif
+ return msg;
+}
+#else /* HAVE_STRERROR_R */
+/* we actually wan't to call strerror(3) below */
+#undef strerror
+/*
+ * Described in header.
+ */
+const char *safe_strerror(int errnum)
+{
+ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+ char *buf = get_strerror_buf();
+
+ /* use a mutex to ensure calling strerror(3) is thread-safe */
+ pthread_mutex_lock(&mutex);
+ strncpy(buf, strerror(errnum), STRERROR_BUF_LEN);
+ pthread_mutex_unlock(&mutex);
+ buf[STRERROR_BUF_LEN - 1] = '\0';
+ return buf;
+}
+#endif /* HAVE_STRERROR_R */
+
+
#ifndef HAVE_CLOSEFROM
/**
* Described in header.
@@ -315,7 +395,6 @@ void nop()
}
#ifndef HAVE_GCC_ATOMIC_OPERATIONS
-#include <pthread.h>
/**
* We use a single mutex for all refcount variables.
@@ -371,7 +450,7 @@ _cas_impl(ptr, void*)
/**
* Described in header.
*/
-int time_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
+int time_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
const void *const *args)
{
static const char* months[] = {
@@ -384,7 +463,7 @@ int time_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
if (time == UNDEFINED_TIME)
{
- return print_in_hook(dst, len, "--- -- --:--:--%s----",
+ return print_in_hook(data, "--- -- --:--:--%s----",
utc ? " UTC " : " ");
}
if (utc)
@@ -395,7 +474,7 @@ int time_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
{
localtime_r(time, &t);
}
- return print_in_hook(dst, len, "%s %02d %02d:%02d:%02d%s%04d",
+ return print_in_hook(data, "%s %02d %02d:%02d:%02d%s%04d",
months[t.tm_mon], t.tm_mday, t.tm_hour, t.tm_min,
t.tm_sec, utc ? " UTC " : " ", t.tm_year + 1900);
}
@@ -403,7 +482,7 @@ int time_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
/**
* Described in header.
*/
-int time_delta_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
+int time_delta_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
const void *const *args)
{
char* unit = "second";
@@ -426,7 +505,7 @@ int time_delta_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
delta /= 60;
unit = "minute";
}
- return print_in_hook(dst, len, "%" PRIu64 " %s%s", delta, unit,
+ return print_in_hook(data, "%" PRIu64 " %s%s", delta, unit,
(delta == 1) ? "" : "s");
}
@@ -440,7 +519,7 @@ static char hexdig_upper[] = "0123456789ABCDEF";
/**
* Described in header.
*/
-int mem_printf_hook(char *dst, size_t dstlen,
+int mem_printf_hook(printf_hook_data_t *data,
printf_hook_spec_t *spec, const void *const *args)
{
char *bytes = *((void**)(args[0]));
@@ -455,7 +534,7 @@ int mem_printf_hook(char *dst, size_t dstlen,
int i = 0;
int written = 0;
- written += print_in_hook(dst, dstlen, "=> %u bytes @ %p", len, bytes);
+ written += print_in_hook(data, "=> %u bytes @ %p", len, bytes);
while (bytes_pos < bytes_roof)
{
@@ -476,7 +555,7 @@ int mem_printf_hook(char *dst, size_t dstlen,
*buffer_pos++ = '\0';
ascii_buffer[i] = '\0';
- written += print_in_hook(dst, dstlen, "\n%4d: %s %s",
+ written += print_in_hook(data, "\n%4d: %s %s",
line_start, buffer, ascii_buffer);
buffer_pos = buffer;
diff --git a/src/libstrongswan/utils.h b/src/libstrongswan/utils.h
index cedfe8fd1..f47c65ac1 100644
--- a/src/libstrongswan/utils.h
+++ b/src/libstrongswan/utils.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2011 Tobias Brunner
+ * Copyright (C) 2008-2012 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -52,9 +52,33 @@
#define BUF_LEN 512
/**
- * Macro compares two strings for equality
+ * General purpose boolean type.
*/
-#define streq(x,y) (strcmp(x, y) == 0)
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# ifndef HAVE__BOOL
+# define _Bool signed char
+# endif /* HAVE__BOOL */
+# define bool _Bool
+# define false 0
+# define true 1
+# define __bool_true_false_are_defined 1
+#endif /* HAVE_STDBOOL_H */
+#ifndef FALSE
+# define FALSE false
+#endif /* FALSE */
+#ifndef TRUE
+# define TRUE true
+#endif /* TRUE */
+
+/**
+ * Helper function that compares two strings for equality
+ */
+static inline bool streq(const char *x, const char *y)
+{
+ return strcmp(x, y) == 0;
+}
/**
* Macro compares two strings for equality, length limited
@@ -62,9 +86,12 @@
#define strneq(x,y,len) (strncmp(x, y, len) == 0)
/**
- * Macro compares two strings for equality ignoring case
+ * Helper function that compares two strings for equality ignoring case
*/
-#define strcaseeq(x,y) (strcasecmp(x, y) == 0)
+static inline bool strcaseeq(const char *x, const char *y)
+{
+ return strcasecmp(x, y) == 0;
+}
/**
* Macro compares two strings for equality ignoring case, length limited
@@ -74,7 +101,10 @@
/**
* NULL-safe strdup variant
*/
-#define strdupnull(x) ({ char *_x = x; _x ? strdup(_x) : NULL; })
+static inline char *strdupnull(const char *s)
+{
+ return s ? strdup(s) : NULL;
+}
/**
* Macro compares two binary blobs for equality
@@ -121,9 +151,8 @@
/**
* Object allocation/initialization macro, using designated initializer.
*/
-#define INIT(this, ...) ({ (this) = malloc(sizeof(*(this))); \
- *(this) = (typeof(*(this))){ __VA_ARGS__ }; \
- (this); })
+#define INIT(this, ...) { (this) = malloc(sizeof(*(this))); \
+ *(this) = (typeof(*(this))){ __VA_ARGS__ }; }
/**
* Method declaration/definition macro, providing private and public interface.
@@ -136,7 +165,7 @@
#define METHOD(iface, name, ret, this, ...) \
static ret name(union {iface *_public; this;} \
__attribute__((transparent_union)), ##__VA_ARGS__); \
- static const typeof(name) *_##name = (const typeof(name)*)name; \
+ static typeof(name) *_##name = (typeof(name)*)name; \
static ret name(this, ##__VA_ARGS__)
/**
@@ -145,7 +174,7 @@
#define METHOD2(iface1, iface2, name, ret, this, ...) \
static ret name(union {iface1 *_public1; iface2 *_public2; this;} \
__attribute__((transparent_union)), ##__VA_ARGS__); \
- static const typeof(name) *_##name = (const typeof(name)*)name; \
+ static typeof(name) *_##name = (typeof(name)*)name; \
static ret name(this, ##__VA_ARGS__)
/**
@@ -201,27 +230,6 @@
#define TIME_32_BIT_SIGNED_MAX 0x7fffffff
/**
- * General purpose boolean type.
- */
-#ifdef HAVE_STDBOOL_H
-# include <stdbool.h>
-#else
-# ifndef HAVE__BOOL
-# define _Bool signed char
-# endif /* HAVE__BOOL */
-# define bool _Bool
-# define false 0
-# define true 1
-# define __bool_true_false_are_defined 1
-#endif /* HAVE_STDBOOL_H */
-#ifndef FALSE
-# define FALSE false
-#endif /* FALSE */
-#ifndef TRUE
-# define TRUE true
-#endif /* TRUE */
-
-/**
* define some missing fixed width int types on OpenSolaris.
* TODO: since the uintXX_t types are defined by the C99 standard we should
* probably use those anyway
@@ -408,6 +416,23 @@ char *translate(char *str, const char *from, const char *to);
*/
bool mkdir_p(const char *path, mode_t mode);
+/**
+ * Thread-safe wrapper around strerror and strerror_r.
+ *
+ * This is required because the first is not thread-safe (on some platforms)
+ * and the second uses two different signatures (POSIX/GNU) and is impractical
+ * to use anyway.
+ *
+ * @param errnum error code (i.e. errno)
+ * @return error message
+ */
+const char *safe_strerror(int errnum);
+
+/**
+ * Replace usages of strerror(3) with thread-safe variant.
+ */
+#define strerror(errnum) safe_strerror(errnum)
+
#ifndef HAVE_CLOSEFROM
/**
* Close open file descriptors greater than or equal to lowfd.
@@ -491,6 +516,11 @@ static inline void htoun32(void *network, u_int32_t host)
static inline void htoun64(void *network, u_int64_t host)
{
char *unaligned = (char*)network;
+
+#ifdef be64toh
+ host = htobe64(host);
+ memcpy((char*)unaligned, &host, sizeof(host));
+#else
u_int32_t high_part, low_part;
high_part = host >> 32;
@@ -501,6 +531,7 @@ static inline void htoun64(void *network, u_int64_t host)
memcpy(unaligned, &high_part, sizeof(high_part));
unaligned += sizeof(high_part);
memcpy(unaligned, &low_part, sizeof(low_part));
+#endif
}
/**
@@ -542,6 +573,13 @@ static inline u_int32_t untoh32(void *network)
static inline u_int64_t untoh64(void *network)
{
char *unaligned = (char*)network;
+
+#ifdef be64toh
+ u_int64_t tmp;
+
+ memcpy(&tmp, unaligned, sizeof(tmp));
+ return be64toh(tmp);
+#else
u_int32_t high_part, low_part;
memcpy(&high_part, unaligned, sizeof(high_part));
@@ -552,6 +590,7 @@ static inline u_int64_t untoh64(void *network)
low_part = ntohl(low_part);
return (((u_int64_t)high_part) << 32) + low_part;
+#endif
}
/**
@@ -612,7 +651,6 @@ bool cas_bool(bool *ptr, bool oldval, bool newval);
*/
bool cas_ptr(void **ptr, void *oldval, void *newval);
-
#endif /* HAVE_GCC_ATOMIC_OPERATIONS */
/**
@@ -621,7 +659,7 @@ bool cas_ptr(void **ptr, void *oldval, void *newval);
* Arguments are:
* time_t* time, bool utc
*/
-int time_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
+int time_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
const void *const *args);
/**
@@ -630,7 +668,7 @@ int time_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
* Arguments are:
* time_t* begin, time_t* end
*/
-int time_delta_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
+int time_delta_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
const void *const *args);
/**
@@ -639,7 +677,7 @@ int time_delta_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
* Arguments are:
* u_char *ptr, u_int len
*/
-int mem_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
+int mem_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
const void *const *args);
#endif /** UTILS_H_ @}*/
diff --git a/src/libstrongswan/utils/backtrace.c b/src/libstrongswan/utils/backtrace.c
index cb83d9830..b6015fb35 100644
--- a/src/libstrongswan/utils/backtrace.c
+++ b/src/libstrongswan/utils/backtrace.c
@@ -50,6 +50,284 @@ struct private_backtrace_t {
void *frames[];
};
+#ifdef HAVE_DLADDR
+#ifdef HAVE_BFD_H
+
+#include <bfd.h>
+#include <utils/hashtable.h>
+#include <threading/mutex.h>
+
+/**
+ * Hashtable-cached bfd handle
+ */
+typedef struct {
+ /** binary file name on disk */
+ char *filename;
+ /** bfd handle */
+ bfd *abfd;
+ /** loaded symbols */
+ asymbol **syms;
+} bfd_entry_t;
+
+/**
+ * Destroy a bfd_entry
+ */
+static void bfd_entry_destroy(bfd_entry_t *this)
+{
+ free(this->filename);
+ free(this->syms);
+ bfd_close(this->abfd);
+ free(this);
+}
+
+/**
+ * Data to pass to find_addr()
+ */
+typedef struct {
+ /** used bfd entry */
+ bfd_entry_t *entry;
+ /** backtrace address */
+ bfd_vma vma;
+ /** stream to log to */
+ FILE *file;
+ /** TRUE if complete */
+ bool found;
+} bfd_find_data_t;
+
+/**
+ * bfd entry cache
+ */
+static hashtable_t *bfds;
+
+static mutex_t *bfd_mutex;
+
+/**
+ * Hashtable hash function
+ */
+static u_int bfd_hash(char *key)
+{
+ return chunk_hash(chunk_create(key, strlen(key)));
+}
+
+/**
+ * Hashtable equals function
+ */
+static bool bfd_equals(char *a, char *b)
+{
+ return streq(a, b);
+}
+
+/**
+ * See header.
+ */
+void backtrace_init()
+{
+ bfd_init();
+ bfds = hashtable_create((hashtable_hash_t)bfd_hash,
+ (hashtable_equals_t)bfd_equals, 8);
+ bfd_mutex = mutex_create(MUTEX_TYPE_DEFAULT);
+}
+
+/**
+ * See header.
+ */
+void backtrace_deinit()
+{
+ enumerator_t *enumerator;
+ bfd_entry_t *entry;
+ char *key;
+
+ enumerator = bfds->create_enumerator(bfds);
+ while (enumerator->enumerate(enumerator, &key, &entry))
+ {
+ bfds->remove_at(bfds, enumerator);
+ bfd_entry_destroy(entry);
+ }
+ enumerator->destroy(enumerator);
+
+ bfds->destroy(bfds);
+ bfd_mutex->destroy(bfd_mutex);
+}
+
+/**
+ * Find and print information to an address
+ */
+static void find_addr(bfd *abfd, asection *section, bfd_find_data_t *data)
+{
+ bfd_size_type size;
+ bfd_vma vma;
+ const char *source;
+ const char *function;
+ u_int line;
+
+ if (!data->found || (bfd_get_section_flags(abfd, section) & SEC_ALLOC) != 0)
+ {
+ vma = bfd_get_section_vma(abfd, section);
+ if (data->vma >= vma)
+ {
+ size = bfd_get_section_size(section);
+ if (data->vma < vma + size)
+ {
+ data->found = bfd_find_nearest_line(abfd, section,
+ data->entry->syms, data->vma - vma,
+ &source, &function, &line);
+ if (data->found)
+ {
+ if (source || function)
+ {
+ fprintf(data->file, " -> ");
+ if (function)
+ {
+ fprintf(data->file, "\e[34m%s() ", function);
+ }
+ if (source)
+ {
+ fprintf(data->file, "\e[32m@ %s:%d", source, line);
+ }
+ fprintf(data->file, "\e[0m\n");
+ }
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Find a cached bfd entry, create'n'cache if not found
+ */
+static bfd_entry_t *get_bfd_entry(char *filename)
+{
+ bool dynamic = FALSE, ok = FALSE;
+ bfd_entry_t *entry;
+ long size;
+
+ /* check cache */
+ entry = bfds->get(bfds, filename);
+ if (entry)
+ {
+ return entry;
+ }
+
+ INIT(entry,
+ .abfd = bfd_openr(filename, NULL),
+ );
+
+ if (!entry->abfd)
+ {
+ free(entry);
+ return NULL;
+ }
+#ifdef BFD_DECOMPRESS
+ entry->abfd->flags |= BFD_DECOMPRESS;
+#endif
+ if (bfd_check_format(entry->abfd, bfd_archive) == 0 &&
+ bfd_check_format_matches(entry->abfd, bfd_object, NULL))
+ {
+ if (bfd_get_file_flags(entry->abfd) & HAS_SYMS)
+ {
+ size = bfd_get_symtab_upper_bound(entry->abfd);
+ if (size == 0)
+ {
+ size = bfd_get_dynamic_symtab_upper_bound(entry->abfd);
+ }
+ if (size >= 0)
+ {
+ entry->syms = malloc(size);
+ if (dynamic)
+ {
+ ok = bfd_canonicalize_dynamic_symtab(entry->abfd,
+ entry->syms) >= 0;
+ }
+ else
+ {
+ ok = bfd_canonicalize_symtab(entry->abfd,
+ entry->syms) >= 0;
+ }
+ }
+ }
+ }
+ if (ok)
+ {
+ entry->filename = strdup(filename);
+ bfds->put(bfds, entry->filename, entry);
+ return entry;
+ }
+ bfd_entry_destroy(entry);
+ return NULL;
+}
+
+/**
+ * Print the source file with line number to file, libbfd variant
+ */
+static void print_sourceline(FILE *file, char *filename, void *ptr)
+{
+ bfd_entry_t *entry;
+ bfd_find_data_t data = {
+ .file = file,
+ .vma = (uintptr_t)ptr,
+ };
+ bool old = FALSE;
+
+ bfd_mutex->lock(bfd_mutex);
+ if (lib->leak_detective)
+ {
+ old = lib->leak_detective->set_state(lib->leak_detective, FALSE);
+ }
+ entry = get_bfd_entry(filename);
+ if (entry)
+ {
+ data.entry = entry;
+ bfd_map_over_sections(entry->abfd, (void*)find_addr, &data);
+ }
+ if (lib->leak_detective)
+ {
+ lib->leak_detective->set_state(lib->leak_detective, old);
+ }
+ bfd_mutex->unlock(bfd_mutex);
+}
+
+#else /* !HAVE_BFD_H */
+
+void backtrace_init() {}
+void backtrace_deinit() {}
+
+/**
+ * Print the source file with line number to file, slow addr2line variant
+ */
+static void print_sourceline(FILE *file, char *filename, void *ptr)
+{
+ char cmd[1024];
+ FILE *output;
+ int c;
+
+ snprintf(cmd, sizeof(cmd), "addr2line -e %s %p", filename, ptr);
+ output = popen(cmd, "r");
+ if (output)
+ {
+ fprintf(file, " -> \e[32m");
+ while (TRUE)
+ {
+ c = getc(output);
+ if (c == '\n' || c == EOF)
+ {
+ break;
+ }
+ fputc(c, file);
+ }
+ pclose(output);
+ fprintf(file, "\e[0m\n");
+ }
+}
+
+#endif /* HAVE_BFD_H */
+
+#else /* !HAVE_DLADDR */
+
+void backtrace_init() {}
+void backtrace_deinit() {}
+
+#endif /* HAVE_DLADDR */
+
METHOD(backtrace_t, log_, void,
private_backtrace_t *this, FILE *file, bool detailed)
{
@@ -67,9 +345,6 @@ METHOD(backtrace_t, log_, void,
if (dladdr(this->frames[i], &info))
{
- char cmd[1024];
- FILE *output;
- int c;
void *ptr = this->frames[i];
if (strstr(info.dli_fname, ".so"))
@@ -89,37 +364,14 @@ METHOD(backtrace_t, log_, void,
}
if (detailed)
{
- fprintf(file, " -> \e[32m");
- snprintf(cmd, sizeof(cmd), "addr2line -e %s %p",
- info.dli_fname, ptr);
- output = popen(cmd, "r");
- if (output)
- {
- while (TRUE)
- {
- c = getc(output);
- if (c == '\n' || c == EOF)
- {
- break;
- }
- fputc(c, file);
- }
- pclose(output);
- }
- else
- {
- #endif /* HAVE_DLADDR */
- fprintf(file, " %s\n", strings[i]);
- #ifdef HAVE_DLADDR
- }
- fprintf(file, "\n\e[0m");
+ print_sourceline(file, (char*)info.dli_fname, ptr);
}
}
else
+#endif /* HAVE_DLADDR */
{
fprintf(file, " %s\n", strings[i]);
}
-#endif /* HAVE_DLADDR */
}
free (strings);
#else /* !HAVE_BACKTRACE */
@@ -248,3 +500,20 @@ backtrace_t *backtrace_create(int skip)
return &this->public;
}
+/**
+ * See header
+ */
+void backtrace_dump(char *label, FILE *file, bool detailed)
+{
+ backtrace_t *backtrace;
+
+ backtrace = backtrace_create(2);
+
+ if (label)
+ {
+ fprintf(file, "Debug backtrace: %s\n", label);
+ }
+ backtrace->log(backtrace, file, detailed);
+ backtrace->destroy(backtrace);
+}
+
diff --git a/src/libstrongswan/utils/backtrace.h b/src/libstrongswan/utils/backtrace.h
index 9d59d2503..aeeba4dd6 100644
--- a/src/libstrongswan/utils/backtrace.h
+++ b/src/libstrongswan/utils/backtrace.h
@@ -77,4 +77,23 @@ struct backtrace_t {
*/
backtrace_t *backtrace_create(int skip);
+/**
+ * Create a backtrace, dump it and clean it up.
+ *
+ * @param label description to print for this backtrace, or NULL
+ * @param file FILE to log backtrace to
+ * @param detailed TRUE to resolve line/file using addr2line (slow)
+ */
+void backtrace_dump(char *label, FILE *file, bool detailed);
+
+/**
+ * Initialize backtracing framework.
+ */
+void backtrace_init();
+
+/**
+ * Deinitialize backtracing framework.
+ */
+void backtrace_deinit();
+
#endif /** BACKTRACE_H_ @}*/
diff --git a/src/libstrongswan/utils/blocking_queue.c b/src/libstrongswan/utils/blocking_queue.c
new file mode 100644
index 000000000..c70184198
--- /dev/null
+++ b/src/libstrongswan/utils/blocking_queue.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012 Giuliano Grassi
+ * Copyright (C) 2012 Ralf Sager
+ * 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 "blocking_queue.h"
+
+#include <threading/mutex.h>
+#include <threading/thread.h>
+#include <threading/condvar.h>
+#include <utils/linked_list.h>
+
+typedef struct private_blocking_queue_t private_blocking_queue_t;
+
+/**
+ * Private data of a blocking_queue_t object.
+ */
+struct private_blocking_queue_t {
+
+ /**
+ * Public part
+ */
+ blocking_queue_t public;
+
+ /**
+ * Linked list containing all items in the queue
+ */
+ linked_list_t *list;
+
+ /**
+ * Mutex used to synchronize access to the queue
+ */
+ mutex_t *mutex;
+
+ /**
+ * Condvar used to wait for items
+ */
+ condvar_t *condvar;
+
+};
+
+METHOD(blocking_queue_t, enqueue, void,
+ private_blocking_queue_t *this, void *item)
+{
+ this->mutex->lock(this->mutex);
+ this->list->insert_first(this->list, item);
+ this->condvar->signal(this->condvar);
+ this->mutex->unlock(this->mutex);
+}
+
+METHOD(blocking_queue_t, dequeue, void*,
+ private_blocking_queue_t *this)
+{
+ bool oldstate;
+ void *item;
+
+
+ this->mutex->lock(this->mutex);
+ thread_cleanup_push((thread_cleanup_t)this->mutex->unlock, this->mutex);
+ /* ensure that a canceled thread does not dequeue any items */
+ thread_cancellation_point();
+ while (this->list->remove_last(this->list, &item) != SUCCESS)
+ {
+ oldstate = thread_cancelability(TRUE);
+ this->condvar->wait(this->condvar, this->mutex);
+ thread_cancelability(oldstate);
+ }
+ thread_cleanup_pop(TRUE);
+ return item;
+}
+
+METHOD(blocking_queue_t, destroy, void,
+ private_blocking_queue_t *this)
+{
+ this->list->destroy(this->list);
+ this->condvar->destroy(this->condvar);
+ this->mutex->destroy(this->mutex);
+ free(this);
+}
+
+METHOD(blocking_queue_t, destroy_offset, void,
+ private_blocking_queue_t *this, size_t offset)
+{
+ this->list->invoke_offset(this->list, offset);
+ destroy(this);
+}
+
+METHOD(blocking_queue_t, destroy_function, void,
+ private_blocking_queue_t *this, void (*fn)(void*))
+{
+ this->list->invoke_function(this->list, (linked_list_invoke_t)fn);
+ destroy(this);
+}
+
+/*
+ * Described in header.
+ */
+blocking_queue_t *blocking_queue_create()
+{
+ private_blocking_queue_t *this;
+
+ INIT(this,
+ .public = {
+ .enqueue = _enqueue,
+ .dequeue = _dequeue,
+ .destroy = _destroy,
+ .destroy_offset = _destroy_offset,
+ .destroy_function = _destroy_function,
+ },
+ .list = linked_list_create(),
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ .condvar = condvar_create(CONDVAR_TYPE_DEFAULT),
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libstrongswan/utils/blocking_queue.h b/src/libstrongswan/utils/blocking_queue.h
new file mode 100644
index 000000000..cf2712cf4
--- /dev/null
+++ b/src/libstrongswan/utils/blocking_queue.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012 Giuliano Grassi
+ * Copyright (C) 2012 Ralf Sager
+ * 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 blocking_queue blocking_queue
+ * @{ @ingroup utils
+ */
+
+#ifndef BLOCKING_QUEUE_H_
+#define BLOCKING_QUEUE_H_
+
+typedef struct blocking_queue_t blocking_queue_t;
+
+#include <library.h>
+
+/**
+ * Class implementing a synchronized blocking queue based on linked_list_t
+ */
+struct blocking_queue_t {
+
+ /**
+ * Inserts a new item at the tail of the queue
+ *
+ * @param item item to insert in queue
+ */
+ void (*enqueue)(blocking_queue_t *this, void *item);
+
+ /**
+ * Removes the first item in the queue and returns its value.
+ * If the queue is empty, this call blocks until a new item is inserted.
+ *
+ * @note This is a thread cancellation point
+ *
+ * @return removed item
+ */
+ void *(*dequeue)(blocking_queue_t *this);
+
+ /**
+ * Destroys a blocking_queue_t object.
+ *
+ * @note No thread must wait in dequeue() when this function is called
+ */
+ void (*destroy)(blocking_queue_t *this);
+
+ /**
+ * Destroys a queue and its objects using the given destructor.
+ *
+ * If a queue and the contained objects should be destroyed, use
+ * destroy_offset. The supplied offset specifies the destructor to
+ * call on each object. The offset may be calculated using the offsetof
+ * macro, e.g.: queue->destroy_offset(queue, offsetof(object_t, destroy));
+ *
+ * @note No thread must wait in dequeue() when this function is called
+ *
+ * @param offset offset of the objects destructor
+ */
+ void (*destroy_offset)(blocking_queue_t *this, size_t offset);
+
+ /**
+ * Destroys a queue and its objects using a cleanup function.
+ *
+ * If a queue and its contents should get destroyed using a specific
+ * cleanup function, use destroy_function. This is useful when the
+ * list contains malloc()-ed blocks which should get freed,
+ * e.g.: queue->destroy_function(queue, free);
+ *
+ * @note No thread must wait in dequeue() when this function is called
+ *
+ * @param function function to call on each object
+ */
+ void (*destroy_function)(blocking_queue_t *this, void (*)(void*));
+
+};
+
+/**
+ * Creates an empty queue object.
+ *
+ * @return blocking_queue_t object.
+ */
+blocking_queue_t *blocking_queue_create();
+
+#endif /** BLOCKING_QUEUE_H_ @}*/
+
diff --git a/src/libstrongswan/utils/capabilities.c b/src/libstrongswan/utils/capabilities.c
new file mode 100644
index 000000000..34128d010
--- /dev/null
+++ b/src/libstrongswan/utils/capabilities.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 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 "capabilities.h"
+
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#include <unistd.h>
+#ifdef HAVE_PRCTL
+# include <sys/prctl.h>
+#endif /* HAVE_PRCTL */
+
+#include <debug.h>
+
+#if !defined(HAVE_GETPWNAM_R) || !defined(HAVE_GETGRNAM_R)
+# include <threading/mutex.h>
+# define EMULATE_R_FUNCS
+#endif
+
+typedef struct private_capabilities_t private_capabilities_t;
+
+/**
+ * Private data of an capabilities_t object.
+ */
+struct private_capabilities_t {
+
+ /**
+ * Public capabilities_t interface.
+ */
+ capabilities_t public;
+
+ /**
+ * user ID to switch during rights dropping
+ */
+ uid_t uid;
+
+ /**
+ * group ID to switch during rights dropping
+ */
+ gid_t gid;
+
+ /**
+ * capabilities to keep
+ */
+#ifdef CAPABILITIES_LIBCAP
+ cap_t caps;
+#endif /* CAPABILITIES_LIBCAP */
+#ifdef CAPABILITIES_NATIVE
+ struct __user_cap_data_struct caps[2];
+#endif /* CAPABILITIES_NATIVE */
+
+#ifdef EMULATE_R_FUNCS
+ /**
+ * mutex to emulate get(pw|gr)nam_r functions
+ */
+ mutex_t *mutex;
+#endif
+};
+
+METHOD(capabilities_t, keep, void,
+ private_capabilities_t *this, u_int cap)
+{
+#ifdef CAPABILITIES_LIBCAP
+ cap_set_flag(this->caps, CAP_EFFECTIVE, 1, &cap, CAP_SET);
+ cap_set_flag(this->caps, CAP_INHERITABLE, 1, &cap, CAP_SET);
+ cap_set_flag(this->caps, CAP_PERMITTED, 1, &cap, CAP_SET);
+#endif /* CAPABILITIES_LIBCAP */
+#ifdef CAPABILITIES_NATIVE
+ int i = 0;
+
+ if (cap >= 32)
+ {
+ i++;
+ cap -= 32;
+ }
+ this->caps[i].effective |= 1 << cap;
+ this->caps[i].permitted |= 1 << cap;
+ this->caps[i].inheritable |= 1 << cap;
+#endif /* CAPABILITIES_NATIVE */
+}
+
+METHOD(capabilities_t, get_uid, uid_t,
+ private_capabilities_t *this)
+{
+ return this->uid;
+}
+
+METHOD(capabilities_t, get_gid, gid_t,
+ private_capabilities_t *this)
+{
+ return this->gid;
+}
+
+METHOD(capabilities_t, set_uid, void,
+ private_capabilities_t *this, uid_t uid)
+{
+ this->uid = uid;
+}
+
+METHOD(capabilities_t, set_gid, void,
+ private_capabilities_t *this, gid_t gid)
+{
+ this->gid = gid;
+}
+
+METHOD(capabilities_t, resolve_uid, bool,
+ private_capabilities_t *this, char *username)
+{
+ struct passwd *pwp;
+ int err;
+
+#ifdef HAVE_GETPWNAM_R
+ struct passwd passwd;
+ char buf[1024];
+
+ err = getpwnam_r(username, &passwd, buf, sizeof(buf), &pwp);
+ if (pwp)
+ {
+ this->uid = pwp->pw_uid;
+ }
+#else /* HAVE GETPWNAM_R */
+ this->mutex->lock(this->mutex);
+ pwp = getpwnam(username);
+ if (pwp)
+ {
+ this->uid = pwp->pw_uid;
+ }
+ err = errno;
+ this->mutex->unlock(this->mutex);
+#endif /* HAVE GETPWNAM_R */
+ if (pwp)
+ {
+ return TRUE;
+ }
+ DBG1(DBG_LIB, "resolving user '%s' failed: %s", username,
+ err ? strerror(err) : "user not found");
+ return FALSE;
+}
+
+METHOD(capabilities_t, resolve_gid, bool,
+ private_capabilities_t *this, char *groupname)
+{
+ struct group *grp;
+ int err;
+
+#ifdef HAVE_GETGRNAM_R
+ struct group group;
+ char buf[1024];
+
+ err = getgrnam_r(groupname, &group, buf, sizeof(buf), &grp);
+ if (grp)
+ {
+ this->gid = grp->gr_gid;
+ }
+#else /* HAVE_GETGRNAM_R */
+ this->mutex->lock(this->mutex);
+ grp = getgrnam(groupname);
+ if (grp)
+ {
+ this->gid = grp->gr_gid;
+ }
+ err = errno;
+ this->mutex->unlock(this->mutex);
+#endif /* HAVE_GETGRNAM_R */
+ if (grp)
+ {
+ return TRUE;
+ }
+ DBG1(DBG_LIB, "resolving user '%s' failed: %s", groupname,
+ err ? strerror(err) : "group not found");
+ return FALSE;
+}
+
+METHOD(capabilities_t, drop, bool,
+ private_capabilities_t *this)
+{
+#ifdef HAVE_PRCTL
+ prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
+#endif
+
+ if (this->gid && setgid(this->gid) != 0)
+ {
+ DBG1(DBG_LIB, "change to unprivileged group %u failed: %s",
+ this->gid, strerror(errno));
+ return FALSE;
+ }
+ if (this->uid && setuid(this->uid) != 0)
+ {
+ DBG1(DBG_LIB, "change to unprivileged user %u failed: %s",
+ this->uid, strerror(errno));
+ return FALSE;
+ }
+
+#ifdef CAPABILITIES_LIBCAP
+ if (cap_set_proc(this->caps) != 0)
+ {
+ DBG1(DBG_LIB, "dropping capabilities failed: %s", strerror(errno));
+ return FALSE;
+ }
+#endif /* CAPABILITIES_LIBCAP */
+#ifdef CAPABILITIES_NATIVE
+ struct __user_cap_header_struct header = {
+#if defined(_LINUX_CAPABILITY_VERSION_3)
+ .version = _LINUX_CAPABILITY_VERSION_3,
+#elif defined(_LINUX_CAPABILITY_VERSION_2)
+ .version = _LINUX_CAPABILITY_VERSION_2,
+#elif defined(_LINUX_CAPABILITY_VERSION_1)
+ .version = _LINUX_CAPABILITY_VERSION_1,
+#else
+ .version = _LINUX_CAPABILITY_VERSION,
+#endif
+ };
+ if (capset(&header, this->caps) != 0)
+ {
+ DBG1(DBG_LIB, "dropping capabilities failed: %s", strerror(errno));
+ return FALSE;
+ }
+#endif /* CAPABILITIES_NATIVE */
+#ifdef CAPABILITIES
+ DBG1(DBG_LIB, "dropped capabilities, running as uid %u, gid %u",
+ this->uid, this->gid);
+#endif /* CAPABILITIES */
+ return TRUE;
+}
+
+METHOD(capabilities_t, destroy, void,
+ private_capabilities_t *this)
+{
+#ifdef EMULATE_R_FUNCS
+ this->mutex->destroy(this->mutex);
+#endif /* EMULATE_R_FUNCS */
+#ifdef CAPABILITIES_LIBCAP
+ cap_free(this->caps);
+#endif /* CAPABILITIES_LIBCAP */
+ free(this);
+}
+
+/**
+ * See header
+ */
+capabilities_t *capabilities_create()
+{
+ private_capabilities_t *this;
+
+ INIT(this,
+ .public = {
+ .keep = _keep,
+ .get_uid = _get_uid,
+ .get_gid = _get_gid,
+ .set_uid = _set_uid,
+ .set_gid = _set_gid,
+ .resolve_uid = _resolve_uid,
+ .resolve_gid = _resolve_gid,
+ .drop = _drop,
+ .destroy = _destroy,
+ },
+ );
+
+#ifdef CAPABILITIES
+#ifdef CAPABILITIES_LIBCAP
+ this->caps = cap_init();
+#endif /* CAPABILITIES_LIBCAP */
+ if (lib->leak_detective)
+ {
+ keep(this, CAP_SYS_NICE);
+ }
+#endif /* CAPABILITIES */
+
+#ifdef EMULATE_R_FUNCS
+ this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);
+#endif /* EMULATE_R_FUNCS */
+
+ return &this->public;
+}
diff --git a/src/libstrongswan/utils/capabilities.h b/src/libstrongswan/utils/capabilities.h
new file mode 100644
index 000000000..cd23cbf10
--- /dev/null
+++ b/src/libstrongswan/utils/capabilities.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 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 capabilities capabilities
+ * @{ @ingroup utils
+ */
+
+#ifndef CAPABILITIES_H_
+#define CAPABILITIES_H_
+
+#include <library.h>
+#ifdef HAVE_SYS_CAPABILITY_H
+# include <sys/capability.h>
+#elif defined(CAPABILITIES_NATIVE)
+# include <linux/capability.h>
+#endif
+
+typedef struct capabilities_t capabilities_t;
+
+/**
+ * POSIX capability dropping abstraction layer.
+ */
+struct capabilities_t {
+
+ /**
+ * Register a capability to keep while calling drop().
+ *
+ * @param cap capability to keep
+ */
+ void (*keep)(capabilities_t *this, u_int cap);
+
+ /**
+ * Get the user ID set through set_uid/resolve_uid.
+ *
+ * @return currently set user ID
+ */
+ uid_t (*get_uid)(capabilities_t *this);
+
+ /**
+ * Get the group ID set through set_gid/resolve_gid.
+ *
+ * @return currently set group ID
+ */
+ gid_t (*get_gid)(capabilities_t *this);
+
+ /**
+ * Set the numerical user ID to use during rights dropping.
+ *
+ * @param uid user ID to use
+ */
+ void (*set_uid)(capabilities_t *this, uid_t uid);
+
+ /**
+ * Set the numerical group ID to use during rights dropping.
+ *
+ * @param gid group ID to use
+ */
+ void (*set_gid)(capabilities_t *this, gid_t gid);
+
+ /**
+ * Resolve a username and set the user ID accordingly.
+ *
+ * @param username username get the uid for
+ * @return TRUE if username resolved and uid set
+ */
+ bool (*resolve_uid)(capabilities_t *this, char *username);
+
+ /**
+ * Resolve a groupname and set the group ID accordingly.
+ *
+ * @param groupname groupname to get the gid for
+ * @return TRUE if groupname resolved and gid set
+ */
+ bool (*resolve_gid)(capabilities_t *this, char *groupname);
+
+ /**
+ * Drop all capabilities not previously passed to keep(), switch to UID/GID.
+ *
+ * @return TRUE if capability drop successful
+ */
+ bool (*drop)(capabilities_t *this);
+
+ /**
+ * Destroy a capabilities_t.
+ */
+ void (*destroy)(capabilities_t *this);
+};
+
+/**
+ * Create a capabilities instance.
+ */
+capabilities_t *capabilities_create();
+
+#endif /** CAPABILITIES_H_ @}*/
diff --git a/src/libstrongswan/utils/enumerator.c b/src/libstrongswan/utils/enumerator.c
index fb461b448..53c94f9dd 100644
--- a/src/libstrongswan/utils/enumerator.c
+++ b/src/libstrongswan/utils/enumerator.c
@@ -121,7 +121,7 @@ static bool enumerate_dir_enum(dir_enum_t *this, char **relative,
/**
* See header
*/
-enumerator_t* enumerator_create_directory(char *path)
+enumerator_t* enumerator_create_directory(const char *path)
{
int len;
dir_enum_t *this = malloc_thing(dir_enum_t);
@@ -168,9 +168,9 @@ typedef struct {
/** current position */
char *pos;
/** separater chars */
- char *sep;
+ const char *sep;
/** trim chars */
- char *trim;
+ const char *trim;
} token_enum_t;
/**
@@ -187,7 +187,8 @@ static void destroy_token_enum(token_enum_t *this)
*/
static bool enumerate_token_enum(token_enum_t *this, char **token)
{
- char *pos = NULL, *tmp, *sep, *trim;
+ const char *sep, *trim;
+ char *pos = NULL, *tmp;
bool last = FALSE;
/* trim leading characters/separators */
@@ -303,7 +304,8 @@ static bool enumerate_token_enum(token_enum_t *this, char **token)
/**
* See header
*/
-enumerator_t* enumerator_create_token(char *string, char *sep, char *trim)
+enumerator_t* enumerator_create_token(const char *string, const char *sep,
+ const char *trim)
{
token_enum_t *enumerator = malloc_thing(token_enum_t);
diff --git a/src/libstrongswan/utils/enumerator.h b/src/libstrongswan/utils/enumerator.h
index 12b5712ae..8c3d70173 100644
--- a/src/libstrongswan/utils/enumerator.h
+++ b/src/libstrongswan/utils/enumerator.h
@@ -93,7 +93,7 @@ enumerator_t *enumerator_create_single(void *item, void (*cleanup)(void *item));
* @param path path of the directory
* @return the directory enumerator, NULL on failure
*/
-enumerator_t* enumerator_create_directory(char *path);
+enumerator_t* enumerator_create_directory(const char *path);
/**
* Create an enumerator over tokens of a string.
@@ -106,7 +106,8 @@ enumerator_t* enumerator_create_directory(char *path);
* @param trim characters to trim from tokens
* @return enumerator over char* tokens
*/
-enumerator_t* enumerator_create_token(char *string, char *sep, char *trim);
+enumerator_t* enumerator_create_token(const char *string, const char *sep,
+ const char *trim);
/**
* Creates an enumerator which enumerates over enumerated enumerators :-).
diff --git a/src/libstrongswan/utils/hashtable.c b/src/libstrongswan/utils/hashtable.c
index 33f645170..d181d8ec8 100644
--- a/src/libstrongswan/utils/hashtable.c
+++ b/src/libstrongswan/utils/hashtable.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2011 Tobias Brunner
+ * Copyright (C) 2008-2012 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -251,16 +251,21 @@ METHOD(hashtable_t, put, void*,
return old_value;
}
-METHOD(hashtable_t, get, void*,
- private_hashtable_t *this, void *key)
+static void *get_internal(private_hashtable_t *this, void *key,
+ hashtable_equals_t equals)
{
void *value = NULL;
pair_t *pair;
+ if (!this->count)
+ { /* no need to calculate the hash */
+ return NULL;
+ }
+
pair = this->table[this->hash(key) & this->mask];
while (pair)
{
- if (this->equals(key, pair->key))
+ if (equals(key, pair->key))
{
value = pair->value;
break;
@@ -270,6 +275,18 @@ METHOD(hashtable_t, get, void*,
return value;
}
+METHOD(hashtable_t, get, void*,
+ private_hashtable_t *this, void *key)
+{
+ return get_internal(this, key, this->equals);
+}
+
+METHOD(hashtable_t, get_match, void*,
+ private_hashtable_t *this, void *key, hashtable_equals_t match)
+{
+ return get_internal(this, key, match);
+}
+
METHOD(hashtable_t, remove_, void*,
private_hashtable_t *this, void *key)
{
@@ -409,6 +426,7 @@ hashtable_t *hashtable_create(hashtable_hash_t hash, hashtable_equals_t equals,
.public = {
.put = _put,
.get = _get,
+ .get_match = _get_match,
.remove = _remove_,
.remove_at = (void*)_remove_at,
.get_count = _get_count,
diff --git a/src/libstrongswan/utils/hashtable.h b/src/libstrongswan/utils/hashtable.h
index 27aca9b68..0a21ca373 100644
--- a/src/libstrongswan/utils/hashtable.h
+++ b/src/libstrongswan/utils/hashtable.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2010 Tobias Brunner
+ * Copyright (C) 2008-2012 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -78,6 +78,22 @@ struct hashtable_t {
void *(*get) (hashtable_t *this, void *key);
/**
+ * Returns the value with a matching key, if the hash table contains such an
+ * entry, otherwise NULL is returned.
+ *
+ * Compared to get() the given match function is used to compare the keys
+ * for equality. The hash function does have to be deviced properly in
+ * order to make this work if the match function compares keys differently
+ * than the equals function provided to the constructor. This basically
+ * allows to enumerate all entries with the same hash value.
+ *
+ * @param key the key to match against
+ * @param match match function to be used when comparing keys
+ * @return the value, NULL if not found
+ */
+ void *(*get_match) (hashtable_t *this, void *key, hashtable_equals_t match);
+
+ /**
* Removes the value with the given key from the hash table and returns the
* removed value (or NULL if no such value existed).
*
diff --git a/src/libstrongswan/utils/host.c b/src/libstrongswan/utils/host.c
index d3020a5d0..e17b6ad02 100644
--- a/src/libstrongswan/utils/host.c
+++ b/src/libstrongswan/utils/host.c
@@ -74,20 +74,16 @@ METHOD(host_t, get_sockaddr_len, socklen_t*,
METHOD(host_t, is_anyaddr, bool,
private_host_t *this)
{
+ static const u_int8_t zeroes[IPV6_LEN];
+
switch (this->address.sa_family)
{
case AF_INET:
{
- u_int8_t zeroes[IPV4_LEN];
-
- memset(zeroes, 0, IPV4_LEN);
return memeq(zeroes, &(this->address4.sin_addr.s_addr), IPV4_LEN);
}
case AF_INET6:
{
- u_int8_t zeroes[IPV6_LEN];
-
- memset(zeroes, 0, IPV6_LEN);
return memeq(zeroes, &(this->address6.sin6_addr.s6_addr), IPV6_LEN);
}
default:
@@ -100,7 +96,7 @@ METHOD(host_t, is_anyaddr, bool,
/**
* Described in header.
*/
-int host_printf_hook(char *dst, size_t dstlen, printf_hook_spec_t *spec,
+int host_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
const void *const *args)
{
private_host_t *this = *((private_host_t**)(args[0]));
@@ -110,7 +106,7 @@ int host_printf_hook(char *dst, size_t dstlen, printf_hook_spec_t *spec,
{
snprintf(buffer, sizeof(buffer), "(null)");
}
- else if (is_anyaddr(this))
+ else if (is_anyaddr(this) && !spec->plus)
{
snprintf(buffer, sizeof(buffer), "%%any%s",
this->address.sa_family == AF_INET6 ? "6" : "");
@@ -152,9 +148,9 @@ int host_printf_hook(char *dst, size_t dstlen, printf_hook_spec_t *spec,
}
if (spec->minus)
{
- return print_in_hook(dst, dstlen, "%-*s", spec->width, buffer);
+ return print_in_hook(data, "%-*s", spec->width, buffer);
}
- return print_in_hook(dst, dstlen, "%*s", spec->width, buffer);
+ return print_in_hook(data, "%*s", spec->width, buffer);
}
METHOD(host_t, get_address, chunk_t,
@@ -430,13 +426,15 @@ host_t *host_create_from_sockaddr(sockaddr_t *sockaddr)
{
case AF_INET:
{
- memcpy(&this->address4, sockaddr, sizeof(struct sockaddr_in));
+ memcpy(&this->address4, (struct sockaddr_in*)sockaddr,
+ sizeof(struct sockaddr_in));
this->socklen = sizeof(struct sockaddr_in);
return &this->public;
}
case AF_INET6:
{
- memcpy(&this->address6, sockaddr, sizeof(struct sockaddr_in6));
+ memcpy(&this->address6, (struct sockaddr_in6*)sockaddr,
+ sizeof(struct sockaddr_in6));
this->socklen = sizeof(struct sockaddr_in6);
return &this->public;
}
diff --git a/src/libstrongswan/utils/host.h b/src/libstrongswan/utils/host.h
index 0a1be6e47..a8b010544 100644
--- a/src/libstrongswan/utils/host.h
+++ b/src/libstrongswan/utils/host.h
@@ -155,7 +155,7 @@ struct host_t {
*
* @param string string of an address, such as "152.96.193.130"
* @param port port number
- * @return host_t, NULL if string not an address.
+ * @return host_t, NULL if string not an address.
*/
host_t *host_create_from_string(char *string, u_int16_t port);
@@ -165,7 +165,7 @@ host_t *host_create_from_string(char *string, u_int16_t port);
* @param string hostname to resolve
* @param family family to prefer, 0 for first match
* @param port port number
- * @return host_t, NULL lookup failed
+ * @return host_t, NULL lookup failed
*/
host_t *host_create_from_dns(char *string, int family, u_int16_t port);
@@ -174,10 +174,10 @@ host_t *host_create_from_dns(char *string, int family, u_int16_t port);
*
* If family is AF_UNSPEC, it is guessed using address.len.
*
- * @param family Address family, such as AF_INET or AF_INET6
+ * @param family Address family, such as AF_INET or AF_INET6
* @param address address as chunk_t in network order
* @param port port number
- * @return host_t, NULL if family not supported/chunk invalid
+ * @return host_t, NULL if family not supported/chunk invalid
*/
host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port);
@@ -185,7 +185,7 @@ host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port);
* Constructor to create a host_t object from a sockaddr struct
*
* @param sockaddr sockaddr struct which contains family, address and port
- * @return host_t, NULL if family not supported
+ * @return host_t, NULL if family not supported
*/
host_t *host_create_from_sockaddr(sockaddr_t *sockaddr);
@@ -202,7 +202,7 @@ host_t *host_create_from_subnet(char *string, int *bits);
* Create a host without an address, a "any" host.
*
* @param family family of the any host
- * @return host_t, NULL if family not supported
+ * @return host_t, NULL if family not supported
*/
host_t *host_create_any(int family);
@@ -212,8 +212,9 @@ host_t *host_create_any(int family);
* Arguments are:
* host_t *host
* Use #-modifier to include port number
+ * Use +-modifier to force numeric representation (instead of e.g. %any)
*/
-int host_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
+int host_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
const void *const *args);
#endif /** HOST_H_ @}*/
diff --git a/src/libstrongswan/utils/identification.c b/src/libstrongswan/utils/identification.c
index 9f0007f78..2669c2da6 100644
--- a/src/libstrongswan/utils/identification.c
+++ b/src/libstrongswan/utils/identification.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Tobias Brunner
+ * Copyright (C) 2009-2012 Tobias Brunner
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -310,7 +310,7 @@ static void dntoa(chunk_t dn, char *buf, size_t len)
len -= written;
chunk_printable(data, &printable, '?');
- written = snprintf(buf, len, "%.*s", printable.len, printable.ptr);
+ written = snprintf(buf, len, "%.*s", (int)printable.len, printable.ptr);
chunk_free(&printable);
if (written < 0 || written >= len)
{
@@ -414,14 +414,22 @@ static status_t atodn(char *src, chunk_t *dn)
}
break;
case SEARCH_NAME:
- if (*src != ' ' && *src != '=')
+ if (*src == ' ' || *src == '=')
+ {
+ break;
+ }
+ else if (*src != ',' && *src != '/')
{
name.ptr = src;
name.len = 1;
whitespace = 0;
state = READ_NAME;
+ break;
}
- break;
+ name = chunk_empty;
+ whitespace = 0;
+ state = READ_NAME;
+ /* fall-through */
case READ_NAME:
if (*src != ',' && *src != '/' && *src != '\0')
{
@@ -748,8 +756,8 @@ METHOD(identification_t, matches_dn, id_match_t,
/**
* Described in header.
*/
-int identification_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
- const void *const *args)
+int identification_printf_hook(printf_hook_data_t *data,
+ printf_hook_spec_t *spec, const void *const *args)
{
private_identification_t *this = *((private_identification_t**)(args[0]));
chunk_t proper;
@@ -757,7 +765,7 @@ int identification_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
if (this == NULL)
{
- return print_in_hook(dst, len, "%*s", spec->width, "(null)");
+ return print_in_hook(data, "%*s", spec->width, "(null)");
}
switch (this->type)
@@ -783,7 +791,7 @@ int identification_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
case ID_RFC822_ADDR:
case ID_DER_ASN1_GN_URI:
chunk_printable(this->encoded, &proper, '?');
- snprintf(buf, sizeof(buf), "%.*s", proper.len, proper.ptr);
+ snprintf(buf, sizeof(buf), "%.*s", (int)proper.len, proper.ptr);
chunk_free(&proper);
break;
case ID_DER_ASN1_DN:
@@ -796,8 +804,8 @@ int identification_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
if (chunk_printable(this->encoded, NULL, '?') &&
this->encoded.len != HASH_SIZE_SHA1)
{ /* fully printable, use ascii version */
- snprintf(buf, sizeof(buf), "%.*s",
- this->encoded.len, this->encoded.ptr);
+ snprintf(buf, sizeof(buf), "%.*s", (int)this->encoded.len,
+ this->encoded.ptr);
}
else
{ /* not printable, hex dump */
@@ -813,9 +821,9 @@ int identification_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
}
if (spec->minus)
{
- return print_in_hook(dst, len, "%-*s", spec->width, buf);
+ return print_in_hook(data, "%-*s", spec->width, buf);
}
- return print_in_hook(dst, len, "%*s", spec->width, buf);
+ return print_in_hook(data, "%*s", spec->width, buf);
}
METHOD(identification_t, clone_, identification_t*,
@@ -1016,7 +1024,7 @@ identification_t * identification_create_from_data(chunk_t data)
char buf[data.len + 1];
/* use string constructor */
- snprintf(buf, sizeof(buf), "%.*s", data.len, data.ptr);
+ snprintf(buf, sizeof(buf), "%.*s", (int)data.len, data.ptr);
return identification_create_from_string(buf);
}
diff --git a/src/libstrongswan/utils/identification.h b/src/libstrongswan/utils/identification.h
index 3978b23f3..024fcea4b 100644
--- a/src/libstrongswan/utils/identification.h
+++ b/src/libstrongswan/utils/identification.h
@@ -342,7 +342,7 @@ identification_t * identification_create_from_sockaddr(sockaddr_t *sockaddr);
* Arguments are:
* identification_t *identification
*/
-int identification_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
- const void *const *args);
+int identification_printf_hook(printf_hook_data_t *data,
+ printf_hook_spec_t *spec, const void *const *args);
#endif /** IDENTIFICATION_H_ @}*/
diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c
index 0a8789335..cface0538 100644
--- a/src/libstrongswan/utils/leak_detective.c
+++ b/src/libstrongswan/utils/leak_detective.c
@@ -188,6 +188,7 @@ static void uninstall_hooks()
char *whitelist[] = {
/* backtraces, including own */
"backtrace_create",
+ "safe_strerror",
/* pthread stuff */
"pthread_create",
"pthread_setspecific",
@@ -224,6 +225,7 @@ char *whitelist[] = {
"getpwent_r",
"setpwent",
"endpwent",
+ "getspnam_r",
/* ignore dlopen, as we do not dlclose to get proper leak reports */
"dlopen",
"dlerror",
@@ -396,6 +398,35 @@ METHOD(leak_detective_t, report, void,
}
}
+METHOD(leak_detective_t, set_state, bool,
+ private_leak_detective_t *this, bool enable)
+{
+ static struct sched_param oldparams;
+ static int oldpolicy;
+ struct sched_param params;
+ pthread_t thread_id;
+
+ if (enable == installed)
+ {
+ return installed;
+ }
+ thread_id = pthread_self();
+ if (enable)
+ {
+ install_hooks();
+ pthread_setschedparam(thread_id, oldpolicy, &oldparams);
+ }
+ else
+ {
+ pthread_getschedparam(thread_id, &oldpolicy, &oldparams);
+ params.__sched_priority = sched_get_priority_max(SCHED_FIFO);
+ pthread_setschedparam(thread_id, SCHED_FIFO, &params);
+ uninstall_hooks();
+ }
+ installed = enable;
+ return !installed;
+}
+
METHOD(leak_detective_t, usage, void,
private_leak_detective_t *this, FILE *out)
{
@@ -444,7 +475,7 @@ void *malloc_hook(size_t bytes, const void *caller)
hdr->magic = MEMORY_HEADER_MAGIC;
hdr->bytes = bytes;
- hdr->backtrace = backtrace_create(3);
+ hdr->backtrace = backtrace_create(2);
tail->magic = MEMORY_TAIL_MAGIC;
install_hooks();
@@ -513,7 +544,7 @@ void free_hook(void *ptr, const void *caller)
/* memory was not allocated by our hooks */
fprintf(stderr, "freeing invalid memory (%p)", ptr);
}
- backtrace = backtrace_create(3);
+ backtrace = backtrace_create(2);
backtrace->log(backtrace, stderr, TRUE);
backtrace->destroy(backtrace);
}
@@ -569,15 +600,17 @@ void *realloc_hook(void *old, size_t bytes, const void *caller)
if (hdr->magic != MEMORY_HEADER_MAGIC ||
tail->magic != MEMORY_TAIL_MAGIC)
{
- fprintf(stderr, "reallocating invalid memory (%p): "
- "header magic 0x%x, tail magic 0x%x:\n",
- old, hdr->magic, tail->magic);
- backtrace = backtrace_create(3);
+ fprintf(stderr, "reallocating invalid memory (%p):\n"
+ "header magic 0x%x:\n", old, hdr->magic);
+ backtrace = backtrace_create(2);
backtrace->log(backtrace, stderr, TRUE);
backtrace->destroy(backtrace);
}
- /* clear tail magic, allocate, set tail magic */
- memset(&tail->magic, MEMORY_ALLOC_PATTERN, sizeof(tail->magic));
+ else
+ {
+ /* clear tail magic, allocate, set tail magic */
+ memset(&tail->magic, MEMORY_ALLOC_PATTERN, sizeof(tail->magic));
+ }
hdr = realloc(hdr, sizeof(memory_header_t) + bytes + sizeof(memory_tail_t));
tail = ((void*)hdr) + bytes + sizeof(memory_header_t);
tail->magic = MEMORY_TAIL_MAGIC;
@@ -585,7 +618,7 @@ void *realloc_hook(void *old, size_t bytes, const void *caller)
/* update statistics */
hdr->bytes = bytes;
hdr->backtrace->destroy(hdr->backtrace);
- hdr->backtrace = backtrace_create(3);
+ hdr->backtrace = backtrace_create(2);
/* update header of linked list neighbours */
if (hdr->next)
@@ -619,6 +652,7 @@ leak_detective_t *leak_detective_create()
.public = {
.report = _report,
.usage = _usage,
+ .set_state = _set_state,
.destroy = _destroy,
},
);
diff --git a/src/libstrongswan/utils/leak_detective.h b/src/libstrongswan/utils/leak_detective.h
index 8c80d2532..55d7e44d9 100644
--- a/src/libstrongswan/utils/leak_detective.h
+++ b/src/libstrongswan/utils/leak_detective.h
@@ -50,6 +50,14 @@ struct leak_detective_t {
void (*usage)(leak_detective_t *this, FILE *out);
/**
+ * Enable/disable leak detective hooks.
+ *
+ * @param TRUE to enable, FALSE to disable
+ * @return state active before calling set_state
+ */
+ bool (*set_state)(leak_detective_t *this, bool enabled);
+
+ /**
* Destroy a leak_detective instance.
*/
void (*destroy)(leak_detective_t *this);
diff --git a/src/libstrongswan/utils/linked_list.c b/src/libstrongswan/utils/linked_list.c
index 59d416f2f..1ff80999b 100644
--- a/src/libstrongswan/utils/linked_list.c
+++ b/src/libstrongswan/utils/linked_list.c
@@ -16,6 +16,7 @@
*/
#include <stdlib.h>
+#include <stdarg.h>
#include "linked_list.h"
@@ -572,3 +573,43 @@ linked_list_t *linked_list_create()
return &this->public;
}
+
+/*
+ * See header.
+ */
+linked_list_t *linked_list_create_from_enumerator(enumerator_t *enumerator)
+{
+ linked_list_t *list;
+ void *item;
+
+ list = linked_list_create();
+
+ while (enumerator->enumerate(enumerator, &item))
+ {
+ list->insert_last(list, item);
+ }
+ enumerator->destroy(enumerator);
+
+ return list;
+}
+
+/*
+ * See header.
+ */
+linked_list_t *linked_list_create_with_items(void *item, ...)
+{
+ linked_list_t *list;
+ va_list args;
+
+ list = linked_list_create();
+
+ va_start(args, item);
+ while (item)
+ {
+ list->insert_last(list, item);
+ item = va_arg(args, void*);
+ }
+ va_end(args);
+
+ return list;
+}
diff --git a/src/libstrongswan/utils/linked_list.h b/src/libstrongswan/utils/linked_list.h
index 293ca8661..1b5518480 100644
--- a/src/libstrongswan/utils/linked_list.h
+++ b/src/libstrongswan/utils/linked_list.h
@@ -299,4 +299,21 @@ struct linked_list_t {
*/
linked_list_t *linked_list_create(void);
+/**
+ * Creates a linked list from an enumerator.
+ *
+ * @param enumerator enumerator over void*, gets destroyed
+ * @return linked_list_t object, containing enumerated values
+ */
+linked_list_t *linked_list_create_from_enumerator(enumerator_t *enumerator);
+
+/**
+ * Creates a linked list from a NULL terminated vararg list of items.
+ *
+ * @param first first item
+ * @param ... subsequent items, terminated by NULL
+ * @return linked_list_t object, containing passed items
+ */
+linked_list_t *linked_list_create_with_items(void *first, ...);
+
#endif /** LINKED_LIST_H_ @}*/
diff --git a/src/libcharon/network/packet.c b/src/libstrongswan/utils/packet.c
index 19db362f7..a2c329d60 100644
--- a/src/libcharon/network/packet.c
+++ b/src/libstrongswan/utils/packet.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -42,6 +43,11 @@ struct private_packet_t {
* message data
*/
chunk_t data;
+
+ /**
+ * actual chunk returned from get_data, adjusted when skip_bytes is called
+ */
+ chunk_t adjusted_data;
};
METHOD(packet_t, set_source, void,
@@ -73,14 +79,20 @@ METHOD(packet_t, get_destination, host_t*,
METHOD(packet_t, get_data, chunk_t,
private_packet_t *this)
{
- return this->data;
+ return this->adjusted_data;
}
METHOD(packet_t, set_data, void,
private_packet_t *this, chunk_t data)
{
free(this->data.ptr);
- this->data = data;
+ this->adjusted_data = this->data = data;
+}
+
+METHOD(packet_t, skip_bytes, void,
+ private_packet_t *this, size_t bytes)
+{
+ this->adjusted_data = chunk_skip(this->adjusted_data, bytes);
}
METHOD(packet_t, destroy, void,
@@ -98,25 +110,26 @@ METHOD(packet_t, clone_, packet_t*,
packet_t *other;
other = packet_create();
- if (this->destination != NULL)
+ if (this->destination)
{
- other->set_destination(other, this->destination->clone(this->destination));
+ other->set_destination(other,
+ this->destination->clone(this->destination));
}
- if (this->source != NULL)
+ if (this->source)
{
other->set_source(other, this->source->clone(this->source));
}
- if (this->data.ptr != NULL)
+ if (this->data.ptr)
{
- other->set_data(other, chunk_clone(this->data));
+ other->set_data(other, chunk_clone(this->adjusted_data));
}
return other;
}
-/*
- * Documented in header
+/**
+ * Described in header.
*/
-packet_t *packet_create(void)
+packet_t *packet_create_from_data(host_t *src, host_t *dst, chunk_t data)
{
private_packet_t *this;
@@ -128,11 +141,23 @@ packet_t *packet_create(void)
.get_source = _get_source,
.set_destination = _set_destination,
.get_destination = _get_destination,
+ .skip_bytes = _skip_bytes,
.clone = _clone_,
.destroy = _destroy,
},
+ .source = src,
+ .destination = dst,
+ .adjusted_data = data,
+ .data = data,
);
return &this->public;
}
+/*
+ * Described in header.
+ */
+packet_t *packet_create()
+{
+ return packet_create_from_data(NULL, NULL, chunk_empty);
+}
diff --git a/src/libstrongswan/utils/packet.h b/src/libstrongswan/utils/packet.h
new file mode 100644
index 000000000..5c4440115
--- /dev/null
+++ b/src/libstrongswan/utils/packet.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup packet packet
+ * @{ @ingroup utils
+ */
+
+#ifndef PACKET_H_
+#define PACKET_H_
+
+typedef struct packet_t packet_t;
+
+#include <library.h>
+#include <utils/host.h>
+
+/**
+ * Abstraction of an IP/UDP-Packet, contains data, sender and receiver.
+ */
+struct packet_t {
+
+ /**
+ * Set the source address.
+ *
+ * @param source address to set as source (gets owned)
+ */
+ void (*set_source)(packet_t *packet, host_t *source);
+
+ /**
+ * Set the destination address.
+ *
+ * @param source address to set as destination (gets owned)
+ */
+ void (*set_destination)(packet_t *packet, host_t *destination);
+
+ /**
+ * Get the source address.
+ *
+ * @return source address (internal data)
+ */
+ host_t *(*get_source)(packet_t *packet);
+
+ /**
+ * Get the destination address.
+ *
+ * @return destination address (internal data)
+ */
+ host_t *(*get_destination)(packet_t *packet);
+
+ /**
+ * Get the data from the packet.
+ *
+ * @return chunk containing the data (internal data)
+ */
+ chunk_t (*get_data)(packet_t *packet);
+
+ /**
+ * Set the data in the packet.
+ *
+ * @param data chunk with data to set (gets owned)
+ */
+ void (*set_data)(packet_t *packet, chunk_t data);
+
+ /**
+ * Increase the offset where the actual packet data starts.
+ *
+ * The total offset applies to future calls of get_data() and clone().
+ *
+ * @note The offset is reset to 0 when set_data() is called.
+ *
+ * @param bytes the number of additional bytes to skip
+ */
+ void (*skip_bytes)(packet_t *packet, size_t bytes);
+
+ /**
+ * Clones a packet_t object.
+ *
+ * @note Data is cloned without skipped bytes.
+ *
+ * @param clone clone of the packet
+ */
+ packet_t* (*clone)(packet_t *packet);
+
+ /**
+ * Destroy the packet, freeing contained data.
+ */
+ void (*destroy)(packet_t *packet);
+};
+
+/**
+ * Create an empty packet
+ *
+ * @return packet_t object
+ */
+packet_t *packet_create();
+
+/**
+ * Create a packet from the supplied data
+ *
+ * @param src source address (gets owned)
+ * @param dst destination address (gets owned)
+ * @param data packet data (gets owned)
+ * @return packet_t object
+ */
+packet_t *packet_create_from_data(host_t *src, host_t *dst, chunk_t data);
+
+#endif /** PACKET_H_ @}*/
diff --git a/src/libstrongswan/utils/tun_device.c b/src/libstrongswan/utils/tun_device.c
new file mode 100644
index 000000000..36f3359c0
--- /dev/null
+++ b/src/libstrongswan/utils/tun_device.c
@@ -0,0 +1,461 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012 Giuliano Grassi
+ * Copyright (C) 2012 Ralf Sager
+ * Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2012 Martin Willi
+ *
+ * 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 <errno.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <net/if.h>
+
+#ifdef __APPLE__
+#include <net/if_utun.h>
+#include <netinet/in_var.h>
+#include <sys/kern_control.h>
+#elif defined(__linux__)
+#include <linux/if_tun.h>
+#else
+#include <net/if_tun.h>
+#endif
+
+#include "tun_device.h"
+
+#include <library.h>
+#include <debug.h>
+#include <threading/thread.h>
+
+#define TUN_DEFAULT_MTU 1500
+
+typedef struct private_tun_device_t private_tun_device_t;
+
+struct private_tun_device_t {
+
+ /**
+ * Public interface
+ */
+ tun_device_t public;
+
+ /**
+ * The TUN device's file descriptor
+ */
+ int tunfd;
+
+ /**
+ * Name of the TUN device
+ */
+ char if_name[IFNAMSIZ];
+
+ /**
+ * Socket used for ioctl() to set interface addr, ...
+ */
+ int sock;
+
+ /**
+ * The current MTU
+ */
+ int mtu;
+};
+
+/**
+ * Set the sockaddr_t from the given netmask
+ */
+static void set_netmask(struct ifreq *ifr, int family, u_int8_t netmask)
+{
+ int len, bytes, bits;
+ char *target;
+
+ switch (family)
+ {
+ case AF_INET:
+ {
+ struct sockaddr_in *addr = (struct sockaddr_in*)&ifr->ifr_addr;
+ addr->sin_family = AF_INET;
+ target = (char*)&addr->sin_addr;
+ len = 4;
+ break;
+ }
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *addr = (struct sockaddr_in6*)&ifr->ifr_addr;
+ addr->sin6_family = AF_INET6;
+ target = (char*)&addr->sin6_addr;
+ len = 16;
+ break;
+ }
+ default:
+ return;
+ }
+
+ bytes = (netmask + 7) / 8;
+ bits = (bytes * 8) - netmask;
+
+ memset(target, 0xff, bytes);
+ memset(target + bytes, 0x00, len - bytes);
+ target[bytes - 1] = bits ? (u_int8_t)(0xff << bits) : 0xff;
+}
+
+METHOD(tun_device_t, set_address, bool,
+ private_tun_device_t *this, host_t *addr, u_int8_t netmask)
+{
+ struct ifreq ifr;
+ int family;
+
+ family = addr->get_family(addr);
+ if ((netmask > 32 && family == AF_INET) || netmask > 128)
+ {
+ DBG1(DBG_LIB, "failed to set address on %s: invalid netmask",
+ this->if_name);
+ return FALSE;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
+ memcpy(&ifr.ifr_addr, addr->get_sockaddr(addr), sizeof(sockaddr_t));
+
+ if (ioctl(this->sock, SIOCSIFADDR, &ifr) < 0)
+ {
+ DBG1(DBG_LIB, "failed to set address on %s: %s",
+ this->if_name, strerror(errno));
+ return FALSE;
+ }
+#ifdef __APPLE__
+ if (ioctl(this->sock, SIOCSIFDSTADDR, &ifr) < 0)
+ {
+ DBG1(DBG_LIB, "failed to set dest address on %s: %s",
+ this->if_name, strerror(errno));
+ return FALSE;
+ }
+#endif /* __APPLE__ */
+
+ set_netmask(&ifr, family, netmask);
+
+ if (ioctl(this->sock, SIOCSIFNETMASK, &ifr) < 0)
+ {
+ DBG1(DBG_LIB, "failed to set netmask on %s: %s",
+ this->if_name, strerror(errno));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+METHOD(tun_device_t, up, bool,
+ private_tun_device_t *this)
+{
+ struct ifreq ifr;
+
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
+
+ if (ioctl(this->sock, SIOCGIFFLAGS, &ifr) < 0)
+ {
+ DBG1(DBG_LIB, "failed to get interface flags for %s: %s", this->if_name,
+ strerror(errno));
+ return FALSE;
+ }
+
+ ifr.ifr_flags |= IFF_RUNNING | IFF_UP;
+
+ if (ioctl(this->sock, SIOCSIFFLAGS, &ifr) < 0)
+ {
+ DBG1(DBG_LIB, "failed to set interface flags on %s: %s", this->if_name,
+ strerror(errno));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+METHOD(tun_device_t, set_mtu, bool,
+ private_tun_device_t *this, int mtu)
+{
+ struct ifreq ifr;
+
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
+ ifr.ifr_mtu = mtu;
+
+ if (ioctl(this->sock, SIOCSIFMTU, &ifr) < 0)
+ {
+ DBG1(DBG_LIB, "failed to set MTU on %s: %s", this->if_name,
+ strerror(errno));
+ return FALSE;
+ }
+ this->mtu = mtu;
+ return TRUE;
+}
+
+METHOD(tun_device_t, get_mtu, int,
+ private_tun_device_t *this)
+{
+ struct ifreq ifr;
+
+ if (this->mtu > 0)
+ {
+ return this->mtu;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
+ this->mtu = TUN_DEFAULT_MTU;
+
+ if (ioctl(this->sock, SIOCGIFMTU, &ifr) == 0)
+ {
+ this->mtu = ifr.ifr_mtu;
+ }
+ return this->mtu;
+}
+
+METHOD(tun_device_t, get_name, char*,
+ private_tun_device_t *this)
+{
+ return this->if_name;
+}
+
+METHOD(tun_device_t, write_packet, bool,
+ private_tun_device_t *this, chunk_t packet)
+{
+ ssize_t s;
+
+ s = write(this->tunfd, packet.ptr, packet.len);
+ if (s < 0)
+ {
+ DBG1(DBG_LIB, "failed to write packet to TUN device %s: %s",
+ this->if_name, strerror(errno));
+ return FALSE;
+ }
+ else if (s != packet.len)
+ {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+METHOD(tun_device_t, read_packet, bool,
+ private_tun_device_t *this, chunk_t *packet)
+{
+ ssize_t len;
+ fd_set set;
+ bool old;
+
+ FD_ZERO(&set);
+ FD_SET(this->tunfd, &set);
+
+ old = thread_cancelability(TRUE);
+ len = select(this->tunfd + 1, &set, NULL, NULL, NULL);
+ thread_cancelability(old);
+
+ if (len < 0)
+ {
+ DBG1(DBG_LIB, "select on TUN device %s failed: %s", this->if_name,
+ strerror(errno));
+ return FALSE;
+ }
+ /* FIXME: this is quite expensive for lots of small packets, copy from
+ * local buffer instead? */
+ *packet = chunk_alloc(get_mtu(this));
+ len = read(this->tunfd, packet->ptr, packet->len);
+ if (len < 0)
+ {
+ DBG1(DBG_LIB, "reading from TUN device %s failed: %s", this->if_name,
+ strerror(errno));
+ chunk_free(packet);
+ return FALSE;
+ }
+ packet->len = len;
+ return TRUE;
+}
+
+METHOD(tun_device_t, destroy, void,
+ private_tun_device_t *this)
+{
+ if (this->tunfd > 0)
+ {
+ close(this->tunfd);
+#ifdef __FreeBSD__
+ /* tun(4) says the following: "These network interfaces persist until
+ * the if_tun.ko module is unloaded, or until removed with the
+ * ifconfig(8) command." So simply closing the FD is not enough. */
+ struct ifreq ifr;
+
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
+ if (ioctl(this->sock, SIOCIFDESTROY, &ifr) < 0)
+ {
+ DBG1(DBG_LIB, "failed to destroy %s: %s", this->if_name,
+ strerror(errno));
+ }
+#endif /* __FreeBSD__ */
+ }
+ if (this->sock > 0)
+ {
+ close(this->sock);
+ }
+ free(this);
+}
+
+/**
+ * Initialize the tun device
+ */
+static bool init_tun(private_tun_device_t *this, const char *name_tmpl)
+{
+#ifdef __APPLE__
+
+ struct ctl_info info;
+ struct sockaddr_ctl addr;
+ socklen_t size = IFNAMSIZ;
+
+ memset(&info, 0, sizeof(info));
+ memset(&addr, 0, sizeof(addr));
+
+ this->tunfd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
+ if (this->tunfd < 0)
+ {
+ DBG1(DBG_LIB, "failed to open tundevice PF_SYSTEM socket: %s",
+ strerror(errno));
+ return FALSE;
+ }
+
+ /* get a control identifier for the utun kernel extension */
+ strncpy(info.ctl_name, UTUN_CONTROL_NAME, strlen(UTUN_CONTROL_NAME));
+ if (ioctl(this->tunfd, CTLIOCGINFO, &info) < 0)
+ {
+ DBG1(DBG_LIB, "failed to ioctl tundevice: %s", strerror(errno));
+ close(this->tunfd);
+ return FALSE;
+ }
+
+ addr.sc_id = info.ctl_id;
+ addr.sc_len = sizeof(addr);
+ addr.sc_family = AF_SYSTEM;
+ addr.ss_sysaddr = AF_SYS_CONTROL;
+ /* allocate identifier dynamically */
+ addr.sc_unit = 0;
+
+ if (connect(this->tunfd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
+ {
+ DBG1(DBG_LIB, "failed to connect tundevice: %s", strerror(errno));
+ close(this->tunfd);
+ return FALSE;
+ }
+ if (getsockopt(this->tunfd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME,
+ this->if_name, &size) < 0)
+ {
+ DBG1(DBG_LIB, "getting tundevice name failed: %s", strerror(errno));
+ close(this->tunfd);
+ return FALSE;
+ }
+ return TRUE;
+
+#elif defined(IFF_TUN)
+
+ struct ifreq ifr;
+
+ strncpy(this->if_name, name_tmpl ?: "tun%d", IFNAMSIZ);
+ this->if_name[IFNAMSIZ-1] = '\0';
+
+ this->tunfd = open("/dev/net/tun", O_RDWR);
+ if (this->tunfd < 0)
+ {
+ DBG1(DBG_LIB, "failed to open /dev/net/tun: %s", strerror(errno));
+ return FALSE;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+
+ /* TUN device, no packet info */
+ ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
+
+ strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
+ if (ioctl(this->tunfd, TUNSETIFF, (void*)&ifr) < 0)
+ {
+ DBG1(DBG_LIB, "failed to configure TUN device: %s", strerror(errno));
+ close(this->tunfd);
+ return FALSE;
+ }
+ strncpy(this->if_name, ifr.ifr_name, IFNAMSIZ);
+ return TRUE;
+
+#else /* !IFF_TUN */
+
+ /* this works on FreeBSD and might also work on Linux with older TUN
+ * driver versions (no IFF_TUN) */
+ char devname[IFNAMSIZ];
+ int i;
+
+ if (name_tmpl)
+ {
+ DBG1(DBG_LIB, "arbitrary naming of TUN devices is not supported");
+ }
+
+ for (i = 0; i < 256; i++)
+ {
+ snprintf(devname, IFNAMSIZ, "/dev/tun%d", i);
+ this->tunfd = open(devname, O_RDWR);
+ if (this->tunfd > 0)
+ { /* for ioctl(2) calls only the interface name is used */
+ snprintf(this->if_name, IFNAMSIZ, "tun%d", i);
+ break;
+ }
+ DBG1(DBG_LIB, "failed to open %s: %s", this->if_name, strerror(errno));
+ }
+ return this->tunfd > 0;
+
+#endif /* !__APPLE__ */
+}
+
+/*
+ * Described in header
+ */
+tun_device_t *tun_device_create(const char *name_tmpl)
+{
+ private_tun_device_t *this;
+
+ INIT(this,
+ .public = {
+ .read_packet = _read_packet,
+ .write_packet = _write_packet,
+ .get_mtu = _get_mtu,
+ .set_mtu = _set_mtu,
+ .get_name = _get_name,
+ .set_address = _set_address,
+ .up = _up,
+ .destroy = _destroy,
+ },
+ .tunfd = -1,
+ .sock = -1,
+ );
+
+ if (!init_tun(this, name_tmpl))
+ {
+ free(this);
+ return NULL;
+ }
+ DBG1(DBG_LIB, "created TUN device: %s", this->if_name);
+
+ this->sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (this->sock < 0)
+ {
+ DBG1(DBG_LIB, "failed to open socket to configure TUN device");
+ destroy(this);
+ return NULL;
+ }
+ return &this->public;
+}
diff --git a/src/libstrongswan/utils/tun_device.h b/src/libstrongswan/utils/tun_device.h
new file mode 100644
index 000000000..71af0386b
--- /dev/null
+++ b/src/libstrongswan/utils/tun_device.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012 Giuliano Grassi
+ * Copyright (C) 2012 Ralf Sager
+ * 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 tun_device tun_device
+ * @{ @ingroup utils
+ */
+
+#ifndef TUN_DEVICE_H_
+#define TUN_DEVICE_H_
+
+#include <library.h>
+#include <utils/host.h>
+
+typedef struct tun_device_t tun_device_t;
+
+/**
+ * Class to create TUN devices
+ *
+ * Creating such a device requires the CAP_NET_ADMIN capability.
+ *
+ * @note The implementation is currently very Linux specific
+ */
+struct tun_device_t {
+
+ /**
+ * Read a packet from the TUN device
+ *
+ * @note This call blocks until a packet is available. It is a thread
+ * cancellation point.
+ *
+ * @param packet the packet read from the device
+ * @return TRUE if successful
+ */
+ bool (*read_packet)(tun_device_t *this, chunk_t *packet);
+
+ /**
+ * Write a packet to the TUN device
+ *
+ * @param packet the packet to write to the TUN device
+ * @return TRUE if successful
+ */
+ bool (*write_packet)(tun_device_t *this, chunk_t packet);
+
+ /**
+ * Set the IP address of the device
+ *
+ * @param addr the desired interface address
+ * @param netmask the netmask to use
+ * @return TRUE if operation successful
+ */
+ bool (*set_address)(tun_device_t *this, host_t *addr, u_int8_t netmask);
+
+ /**
+ * Bring the TUN device up
+ *
+ * @return TRUE if operation successful
+ */
+ bool (*up)(tun_device_t *this);
+
+ /**
+ * Set the MTU for this TUN device
+ *
+ * @param mtu new MTU
+ * @return TRUE if operation successful
+ */
+ bool (*set_mtu)(tun_device_t *this, int mtu);
+
+ /**
+ * Get the current MTU for this TUN device
+ *
+ * @return current MTU
+ */
+ int (*get_mtu)(tun_device_t *this);
+
+ /**
+ * Get the interface name of this device
+ *
+ * @return interface name
+ */
+ char *(*get_name)(tun_device_t *this);
+
+ /**
+ * Destroy a tun_device_t
+ */
+ void (*destroy)(tun_device_t *this);
+
+};
+
+/**
+ * Create a TUN device using the given name template.
+ *
+ * @param name_tmpl name template, defaults to "tun%d" if not given
+ * @return TUN device
+ */
+tun_device_t *tun_device_create(const char *name_tmpl);
+
+#endif /** TUN_DEVICE_H_ @}*/
diff --git a/src/libtls/Makefile.am b/src/libtls/Makefile.am
index 4cc1a1bdb..772950606 100644
--- a/src/libtls/Makefile.am
+++ b/src/libtls/Makefile.am
@@ -3,15 +3,14 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan
ipseclib_LTLIBRARIES = libtls.la
libtls_la_SOURCES = \
- tls_protection.h tls_protection.c \
- tls_compression.h tls_compression.c \
- tls_fragmentation.h tls_fragmentation.c \
- tls_alert.h tls_alert.c \
- tls_crypto.h tls_crypto.c \
- tls_prf.h tls_prf.c \
- tls_socket.h tls_socket.c \
- tls_eap.h tls_eap.c \
- tls_cache.h tls_cache.c \
- tls_peer.h tls_peer.c \
- tls_server.h tls_server.c \
- tls_handshake.h tls_application.h tls.h tls.c
+ tls_protection.c tls_compression.c tls_fragmentation.c tls_alert.c \
+ tls_crypto.c tls_prf.c tls_socket.c tls_eap.c tls_cache.c tls_peer.c \
+ tls_server.c tls.c
+
+if USE_DEV_HEADERS
+tls_includedir = ${dev_headers}/tls
+nobase_tls_include_HEADERS = \
+ tls_protection.h tls_compression.h tls_fragmentation.h tls_alert.h \
+ tls_crypto.h tls_prf.h tls_socket.h tls_eap.h tls_cache.h tls_peer.h \
+ tls_server.h tls_handshake.h tls_application.h tls.h
+endif
diff --git a/src/libtls/Makefile.in b/src/libtls/Makefile.in
index 844b65156..fb1136ee0 100644
--- a/src/libtls/Makefile.in
+++ b/src/libtls/Makefile.in
@@ -15,6 +15,7 @@
@SET_MAKE@
+
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
@@ -35,7 +36,8 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = src/libtls
-DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+DIST_COMMON = $(am__nobase_tls_include_HEADERS_DIST) \
+ $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
$(top_srcdir)/m4/config/ltoptions.m4 \
@@ -49,6 +51,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -72,7 +75,8 @@ am__nobase_list = $(am__nobase_strip_setup); \
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
-am__installdirs = "$(DESTDIR)$(ipseclibdir)"
+am__installdirs = "$(DESTDIR)$(ipseclibdir)" \
+ "$(DESTDIR)$(tls_includedir)"
LTLIBRARIES = $(ipseclib_LTLIBRARIES)
libtls_la_LIBADD =
am_libtls_la_OBJECTS = tls_protection.lo tls_compression.lo \
@@ -80,7 +84,7 @@ am_libtls_la_OBJECTS = tls_protection.lo tls_compression.lo \
tls_socket.lo tls_eap.lo tls_cache.lo tls_peer.lo \
tls_server.lo tls.lo
libtls_la_OBJECTS = $(am_libtls_la_OBJECTS)
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -95,6 +99,11 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(libtls_la_SOURCES)
DIST_SOURCES = $(libtls_la_SOURCES)
+am__nobase_tls_include_HEADERS_DIST = tls_protection.h \
+ tls_compression.h tls_fragmentation.h tls_alert.h tls_crypto.h \
+ tls_prf.h tls_socket.h tls_eap.h tls_cache.h tls_peer.h \
+ tls_server.h tls_handshake.h tls_application.h tls.h
+HEADERS = $(nobase_tls_include_HEADERS)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -106,6 +115,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -200,11 +210,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -221,11 +234,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -241,6 +255,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -250,7 +265,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -281,18 +295,15 @@ xml_LIBS = @xml_LIBS@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
ipseclib_LTLIBRARIES = libtls.la
libtls_la_SOURCES = \
- tls_protection.h tls_protection.c \
- tls_compression.h tls_compression.c \
- tls_fragmentation.h tls_fragmentation.c \
- tls_alert.h tls_alert.c \
- tls_crypto.h tls_crypto.c \
- tls_prf.h tls_prf.c \
- tls_socket.h tls_socket.c \
- tls_eap.h tls_eap.c \
- tls_cache.h tls_cache.c \
- tls_peer.h tls_peer.c \
- tls_server.h tls_server.c \
- tls_handshake.h tls_application.h tls.h tls.c
+ tls_protection.c tls_compression.c tls_fragmentation.c tls_alert.c \
+ tls_crypto.c tls_prf.c tls_socket.c tls_eap.c tls_cache.c tls_peer.c \
+ tls_server.c tls.c
+
+@USE_DEV_HEADERS_TRUE@tls_includedir = ${dev_headers}/tls
+@USE_DEV_HEADERS_TRUE@nobase_tls_include_HEADERS = \
+@USE_DEV_HEADERS_TRUE@ tls_protection.h tls_compression.h tls_fragmentation.h tls_alert.h \
+@USE_DEV_HEADERS_TRUE@ tls_crypto.h tls_prf.h tls_socket.h tls_eap.h tls_cache.h tls_peer.h \
+@USE_DEV_HEADERS_TRUE@ tls_server.h tls_handshake.h tls_application.h tls.h
all: all-am
@@ -407,6 +418,29 @@ mostlyclean-libtool:
clean-libtool:
-rm -rf .libs _libs
+install-nobase_tls_includeHEADERS: $(nobase_tls_include_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(tls_includedir)" || $(MKDIR_P) "$(DESTDIR)$(tls_includedir)"
+ @list='$(nobase_tls_include_HEADERS)'; test -n "$(tls_includedir)" || list=; \
+ $(am__nobase_list) | while read dir files; do \
+ xfiles=; for file in $$files; do \
+ if test -f "$$file"; then xfiles="$$xfiles $$file"; \
+ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \
+ test -z "$$xfiles" || { \
+ test "x$$dir" = x. || { \
+ echo "$(MKDIR_P) '$(DESTDIR)$(tls_includedir)/$$dir'"; \
+ $(MKDIR_P) "$(DESTDIR)$(tls_includedir)/$$dir"; }; \
+ echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(tls_includedir)/$$dir'"; \
+ $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(tls_includedir)/$$dir" || exit $$?; }; \
+ done
+
+uninstall-nobase_tls_includeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(nobase_tls_include_HEADERS)'; test -n "$(tls_includedir)" || list=; \
+ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(tls_includedir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(tls_includedir)" && rm -f $$files
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
@@ -492,9 +526,9 @@ distdir: $(DISTFILES)
done
check-am: all-am
check: check-am
-all-am: Makefile $(LTLIBRARIES)
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
installdirs:
- for dir in "$(DESTDIR)$(ipseclibdir)"; do \
+ for dir in "$(DESTDIR)$(ipseclibdir)" "$(DESTDIR)$(tls_includedir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
@@ -545,7 +579,8 @@ info: info-am
info-am:
-install-data-am: install-ipseclibLTLIBRARIES
+install-data-am: install-ipseclibLTLIBRARIES \
+ install-nobase_tls_includeHEADERS
install-dvi: install-dvi-am
@@ -591,7 +626,8 @@ ps: ps-am
ps-am:
-uninstall-am: uninstall-ipseclibLTLIBRARIES
+uninstall-am: uninstall-ipseclibLTLIBRARIES \
+ uninstall-nobase_tls_includeHEADERS
.MAKE: install-am install-strip
@@ -602,12 +638,14 @@ uninstall-am: uninstall-ipseclibLTLIBRARIES
install install-am install-data install-data-am install-dvi \
install-dvi-am install-exec install-exec-am install-html \
install-html-am install-info install-info-am \
- install-ipseclibLTLIBRARIES install-man install-pdf \
- install-pdf-am install-ps install-ps-am install-strip \
- installcheck installcheck-am installdirs maintainer-clean \
+ install-ipseclibLTLIBRARIES install-man \
+ install-nobase_tls_includeHEADERS 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 uninstall uninstall-am uninstall-ipseclibLTLIBRARIES
+ tags uninstall uninstall-am uninstall-ipseclibLTLIBRARIES \
+ uninstall-nobase_tls_includeHEADERS
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libtls/tls.h b/src/libtls/tls.h
index e22b0facc..6b4876f73 100644
--- a/src/libtls/tls.h
+++ b/src/libtls/tls.h
@@ -26,6 +26,12 @@
#ifndef TLS_H_
#define TLS_H_
+/**
+ * Maximum size of a TLS fragment
+ * as defined by section 6.2.1. "Fragmentation" of RFC 5246 TLS 1.2
+ */
+#define TLS_MAX_FRAGMENT_LEN 16384
+
typedef enum tls_version_t tls_version_t;
typedef enum tls_content_type_t tls_content_type_t;
typedef enum tls_handshake_type_t tls_handshake_type_t;
diff --git a/src/libtls/tls_crypto.c b/src/libtls/tls_crypto.c
index 4d84876d0..f74984879 100644
--- a/src/libtls/tls_crypto.c
+++ b/src/libtls/tls_crypto.c
@@ -1196,12 +1196,12 @@ static bool hash_data(private_tls_crypto_t *this, chunk_t data, chunk_t *hash)
return FALSE;
}
hasher = lib->crypto->create_hasher(lib->crypto, alg->hash);
- if (!hasher)
+ if (!hasher || !hasher->allocate_hash(hasher, data, hash))
{
DBG1(DBG_TLS, "%N not supported", hash_algorithm_names, alg->hash);
+ DESTROY_IF(hasher);
return FALSE;
}
- hasher->allocate_hash(hasher, data, hash);
hasher->destroy(hasher);
}
else
@@ -1210,20 +1210,20 @@ static bool hash_data(private_tls_crypto_t *this, chunk_t data, chunk_t *hash)
char buf[HASH_SIZE_MD5 + HASH_SIZE_SHA1];
md5 = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
- if (!md5)
+ if (!md5 || !md5->get_hash(md5, data, buf))
{
DBG1(DBG_TLS, "%N not supported", hash_algorithm_names, HASH_MD5);
+ DESTROY_IF(md5);
return FALSE;
}
- md5->get_hash(md5, data, buf);
md5->destroy(md5);
sha1 = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
- if (!sha1)
+ if (!sha1 || !sha1->get_hash(sha1, data, buf + HASH_SIZE_MD5))
{
DBG1(DBG_TLS, "%N not supported", hash_algorithm_names, HASH_SHA1);
+ DESTROY_IF(sha1);
return FALSE;
}
- sha1->get_hash(sha1, data, buf + HASH_SIZE_MD5);
sha1->destroy(sha1);
*hash = chunk_clone(chunk_from_thing(buf));
@@ -1462,7 +1462,11 @@ METHOD(tls_crypto_t, calculate_finished, bool,
{
return FALSE;
}
- this->prf->get_bytes(this->prf, label, seed, 12, out);
+ if (!this->prf->get_bytes(this->prf, label, seed, 12, out))
+ {
+ free(seed.ptr);
+ return FALSE;
+ }
free(seed.ptr);
return TRUE;
}
@@ -1470,7 +1474,7 @@ METHOD(tls_crypto_t, calculate_finished, bool,
/**
* Derive master secret from premaster, optionally save session
*/
-static void derive_master(private_tls_crypto_t *this, chunk_t premaster,
+static bool derive_master(private_tls_crypto_t *this, chunk_t premaster,
chunk_t session, identification_t *id,
chunk_t client_random, chunk_t server_random)
{
@@ -1479,23 +1483,28 @@ static void derive_master(private_tls_crypto_t *this, chunk_t premaster,
/* derive master secret */
seed = chunk_cata("cc", client_random, server_random);
- this->prf->set_key(this->prf, premaster);
- this->prf->get_bytes(this->prf, "master secret", seed,
- sizeof(master), master);
- this->prf->set_key(this->prf, chunk_from_thing(master));
+ if (!this->prf->set_key(this->prf, premaster) ||
+ !this->prf->get_bytes(this->prf, "master secret", seed,
+ sizeof(master), master) ||
+ !this->prf->set_key(this->prf, chunk_from_thing(master)))
+ {
+ return FALSE;
+ }
+
if (this->cache && session.len)
{
this->cache->create(this->cache, session, id, chunk_from_thing(master),
this->suite);
}
memwipe(master, sizeof(master));
+ return TRUE;
}
/**
* Expand key material from master secret
*/
-static void expand_keys(private_tls_crypto_t *this,
+static bool expand_keys(private_tls_crypto_t *this,
chunk_t client_random, chunk_t server_random)
{
chunk_t seed, block, client_write, server_write;
@@ -1513,7 +1522,11 @@ static void expand_keys(private_tls_crypto_t *this,
}
seed = chunk_cata("cc", server_random, client_random);
block = chunk_alloca((mks + eks + ivs) * 2);
- this->prf->get_bytes(this->prf, "key expansion", seed, block.len, block.ptr);
+ if (!this->prf->get_bytes(this->prf, "key expansion", seed,
+ block.len, block.ptr))
+ {
+ return FALSE;
+ }
/* signer keys */
client_write = chunk_create(block.ptr, mks);
@@ -1522,13 +1535,19 @@ static void expand_keys(private_tls_crypto_t *this,
block = chunk_skip(block, mks);
if (this->tls->is_server(this->tls))
{
- this->signer_in->set_key(this->signer_in, client_write);
- this->signer_out->set_key(this->signer_out, server_write);
+ if (!this->signer_in->set_key(this->signer_in, client_write) ||
+ !this->signer_out->set_key(this->signer_out, server_write))
+ {
+ return FALSE;
+ }
}
else
{
- this->signer_out->set_key(this->signer_out, client_write);
- this->signer_in->set_key(this->signer_in, server_write);
+ if (!this->signer_out->set_key(this->signer_out, client_write) ||
+ !this->signer_in->set_key(this->signer_in, server_write))
+ {
+ return FALSE;
+ }
}
/* crypter keys, and IVs if < TLSv1.2 */
@@ -1541,13 +1560,19 @@ static void expand_keys(private_tls_crypto_t *this,
if (this->tls->is_server(this->tls))
{
- this->crypter_in->set_key(this->crypter_in, client_write);
- this->crypter_out->set_key(this->crypter_out, server_write);
+ if (!this->crypter_in->set_key(this->crypter_in, client_write) ||
+ !this->crypter_out->set_key(this->crypter_out, server_write))
+ {
+ return FALSE;
+ }
}
else
{
- this->crypter_out->set_key(this->crypter_out, client_write);
- this->crypter_in->set_key(this->crypter_in, server_write);
+ if (!this->crypter_out->set_key(this->crypter_out, client_write) ||
+ !this->crypter_in->set_key(this->crypter_in, server_write))
+ {
+ return FALSE;
+ }
}
if (ivs)
{
@@ -1574,17 +1599,22 @@ static void expand_keys(private_tls_crypto_t *this,
{
seed = chunk_cata("cc", client_random, server_random);
this->msk = chunk_alloc(64);
- this->prf->get_bytes(this->prf, this->msk_label, seed,
- this->msk.len, this->msk.ptr);
+ if (!this->prf->get_bytes(this->prf, this->msk_label, seed,
+ this->msk.len, this->msk.ptr))
+ {
+ return FALSE;
+ }
}
+ return TRUE;
}
-METHOD(tls_crypto_t, derive_secrets, void,
+METHOD(tls_crypto_t, derive_secrets, bool,
private_tls_crypto_t *this, chunk_t premaster, chunk_t session,
identification_t *id, chunk_t client_random, chunk_t server_random)
{
- derive_master(this, premaster, session, id, client_random, server_random);
- expand_keys(this, client_random, server_random);
+ return derive_master(this, premaster, session, id,
+ client_random, server_random) &&
+ expand_keys(this, client_random, server_random);
}
METHOD(tls_crypto_t, resume_session, tls_cipher_suite_t,
@@ -1601,8 +1631,11 @@ METHOD(tls_crypto_t, resume_session, tls_cipher_suite_t,
this->suite = select_cipher_suite(this, &this->suite, 1, KEY_ANY);
if (this->suite)
{
- this->prf->set_key(this->prf, master);
- expand_keys(this, client_random, server_random);
+ if (!this->prf->set_key(this->prf, master) ||
+ !expand_keys(this, client_random, server_random))
+ {
+ this->suite = 0;
+ }
}
chunk_clear(&master);
}
@@ -1719,11 +1752,14 @@ tls_crypto_t *tls_crypto_create(tls_t *tls, tls_cache_t *cache)
switch (tls->get_purpose(tls))
{
case TLS_PURPOSE_EAP_TLS:
- case TLS_PURPOSE_EAP_PEAP:
/* MSK PRF ASCII constant label according to EAP-TLS RFC 5216 */
this->msk_label = "client EAP encryption";
build_cipher_suite_list(this, FALSE);
break;
+ case TLS_PURPOSE_EAP_PEAP:
+ this->msk_label = "client EAP encryption";
+ build_cipher_suite_list(this, TRUE);
+ break;
case TLS_PURPOSE_EAP_TTLS:
/* MSK PRF ASCII constant label according to EAP-TTLS RFC 5281 */
this->msk_label = "ttls keying material";
diff --git a/src/libtls/tls_crypto.h b/src/libtls/tls_crypto.h
index 7430aea66..5512b1f48 100644
--- a/src/libtls/tls_crypto.h
+++ b/src/libtls/tls_crypto.h
@@ -515,8 +515,9 @@ struct tls_crypto_t {
* @param id identity the session is bound to
* @param client_random random data from client hello
* @param server_random random data from server hello
+ * @return TRUE if secrets derived successfully
*/
- void (*derive_secrets)(tls_crypto_t *this, chunk_t premaster,
+ bool (*derive_secrets)(tls_crypto_t *this, chunk_t premaster,
chunk_t session, identification_t *id,
chunk_t client_random, chunk_t server_random);
diff --git a/src/libtls/tls_eap.c b/src/libtls/tls_eap.c
index 685904fdf..928aadcb3 100644
--- a/src/libtls/tls_eap.c
+++ b/src/libtls/tls_eap.c
@@ -21,8 +21,11 @@
#include <debug.h>
#include <library.h>
-/** Size limit for a single TLS message */
-#define MAX_TLS_MESSAGE_LEN 65536
+/**
+ * Size limit for a TLS message allowing for worst-case protection overhead
+ * according to section 6.2.3. "Payload Protection" of RFC 5246 TLS 1.2
+ */
+#define TLS_MAX_MESSAGE_LEN 4 * (TLS_MAX_FRAGMENT_LEN + 2048)
typedef struct private_tls_eap_t private_tls_eap_t;
@@ -79,7 +82,7 @@ struct private_tls_eap_t {
int processed;
/**
- * Maximum number of processed EAP messages/fragments
+ * Maximum number of processed EAP messages/fragments
*/
int max_msg_count;
};
@@ -138,7 +141,7 @@ METHOD(tls_eap_t, initiate, status_t,
*out = chunk_clone(chunk_from_thing(pkt));
DBG2(DBG_TLS, "sending %N start packet (%u bytes)",
- eap_type_names, this->type, sizeof(eap_tls_packet_t));
+ eap_type_names, this->type, sizeof(eap_tls_packet_t));
DBG3(DBG_TLS, "%B", out);
return NEED_MORE;
}
@@ -150,10 +153,12 @@ METHOD(tls_eap_t, initiate, status_t,
*/
static status_t process_pkt(private_tls_eap_t *this, eap_tls_packet_t *pkt)
{
- u_int32_t msg_len;
u_int16_t pkt_len;
+ u_int32_t msg_len;
+ size_t msg_len_offset = 0;
pkt_len = untoh16(&pkt->length);
+
if (pkt->flags & EAP_TLS_LENGTH)
{
if (pkt_len < sizeof(eap_tls_packet_t) + sizeof(msg_len))
@@ -163,16 +168,17 @@ static status_t process_pkt(private_tls_eap_t *this, eap_tls_packet_t *pkt)
}
msg_len = untoh32(pkt + 1);
if (msg_len < pkt_len - sizeof(eap_tls_packet_t) - sizeof(msg_len) ||
- msg_len > MAX_TLS_MESSAGE_LEN)
+ msg_len > TLS_MAX_MESSAGE_LEN)
{
- DBG1(DBG_TLS, "invalid %N packet length", eap_type_names, this->type);
+ DBG1(DBG_TLS, "invalid %N packet length (%u bytes)", eap_type_names,
+ this->type, msg_len);
return FAILED;
}
- return this->tls->process(this->tls, (char*)(pkt + 1) + sizeof(msg_len),
- pkt_len - sizeof(eap_tls_packet_t) - sizeof(msg_len));
+ msg_len_offset = sizeof(msg_len);
}
- return this->tls->process(this->tls, (char*)(pkt + 1),
- pkt_len - sizeof(eap_tls_packet_t));
+
+ return this->tls->process(this->tls, (char*)(pkt + 1) + msg_len_offset,
+ pkt_len - sizeof(eap_tls_packet_t) - msg_len_offset);
}
/**
@@ -182,7 +188,7 @@ static status_t build_pkt(private_tls_eap_t *this, chunk_t *out)
{
char buf[this->frag_size];
eap_tls_packet_t *pkt;
- size_t len, reclen;
+ size_t len, reclen, msg_len_offset;
status_t status;
char *kind;
@@ -214,15 +220,16 @@ static status_t build_pkt(private_tls_eap_t *this, chunk_t *out)
if (this->first_fragment)
{
len = sizeof(buf) - sizeof(eap_tls_packet_t) - sizeof(u_int32_t);
- status = this->tls->build(this->tls, buf + sizeof(eap_tls_packet_t) +
- sizeof(u_int32_t), &len, &reclen);
+ msg_len_offset = sizeof(u_int32_t);
}
else
{
len = sizeof(buf) - sizeof(eap_tls_packet_t);
- status = this->tls->build(this->tls, buf + sizeof(eap_tls_packet_t),
- &len, &reclen);
+ msg_len_offset = 0;
}
+ status = this->tls->build(this->tls, buf + sizeof(eap_tls_packet_t) +
+ msg_len_offset, &len, &reclen);
+
switch (status)
{
case NEED_MORE:
@@ -230,7 +237,7 @@ static status_t build_pkt(private_tls_eap_t *this, chunk_t *out)
kind = "further fragment";
if (this->first_fragment)
{
- pkt->flags |= EAP_TLS_LENGTH;
+ pkt->flags |= EAP_TLS_LENGTH;
this->first_fragment = FALSE;
kind = "first fragment";
}
@@ -244,11 +251,15 @@ static status_t build_pkt(private_tls_eap_t *this, chunk_t *out)
}
kind = "packet";
}
- else
+ else if (this->type != EAP_TNC)
{
this->first_fragment = TRUE;
kind = "final fragment";
}
+ else
+ {
+ kind = "packet";
+ }
break;
default:
return status;
@@ -256,7 +267,7 @@ static status_t build_pkt(private_tls_eap_t *this, chunk_t *out)
if (reclen)
{
if (pkt->flags & EAP_TLS_LENGTH)
- {
+ {
htoun32(pkt + 1, reclen);
len += sizeof(u_int32_t);
pkt->flags |= EAP_TLS_LENGTH;
@@ -264,15 +275,15 @@ static status_t build_pkt(private_tls_eap_t *this, chunk_t *out)
else
{
/* get rid of the reserved length field */
- memcpy(buf+sizeof(eap_packet_t),
- buf+sizeof(eap_packet_t)+sizeof(u_int32_t), len);
+ memmove(buf + sizeof(eap_tls_packet_t),
+ buf + sizeof(eap_tls_packet_t) + sizeof(u_int32_t), len);
}
}
len += sizeof(eap_tls_packet_t);
htoun16(&pkt->length, len);
*out = chunk_clone(chunk_create(buf, len));
DBG2(DBG_TLS, "sending %N %s (%u bytes)",
- eap_type_names, this->type, kind, len);
+ eap_type_names, this->type, kind, len);
DBG3(DBG_TLS, "%B", out);
return NEED_MORE;
}
@@ -319,7 +330,7 @@ METHOD(tls_eap_t, process, status_t,
eap_tls_packet_t *pkt;
status_t status;
- if (++this->processed > this->max_msg_count)
+ if (this->max_msg_count && ++this->processed > this->max_msg_count)
{
DBG1(DBG_TLS, "%N packet count exceeded (%d > %d)",
eap_type_names, this->type,
@@ -441,7 +452,7 @@ tls_eap_t *tls_eap_create(eap_type_t type, tls_t *tls, size_t frag_size,
},
.type = type,
.is_server = tls->is_server(tls),
- .first_fragment = TRUE,
+ .first_fragment = (type != EAP_TNC),
.frag_size = frag_size,
.max_msg_count = max_msg_count,
.include_length = include_length,
diff --git a/src/libtls/tls_fragmentation.c b/src/libtls/tls_fragmentation.c
index 62e36aaec..f2fa77cfd 100644
--- a/src/libtls/tls_fragmentation.c
+++ b/src/libtls/tls_fragmentation.c
@@ -18,6 +18,11 @@
#include <bio/bio_reader.h>
#include <debug.h>
+/**
+ * Maximum size of a TLS handshake message we accept
+ */
+#define TLS_MAX_HANDSHAKE_LEN 65536
+
typedef struct private_tls_fragmentation_t private_tls_fragmentation_t;
/**
@@ -94,16 +99,6 @@ struct private_tls_fragmentation_t {
};
/**
- * Maximum size of a TLS fragment
- */
-#define MAX_TLS_FRAGMENT_LEN 16384
-
-/**
- * Maximum size of a TLS handshake message we accept
- */
-#define MAX_TLS_HANDSHAKE_LEN 65536
-
-/**
* Process a TLS alert
*/
static status_t process_alert(private_tls_fragmentation_t *this,
@@ -134,7 +129,7 @@ static status_t process_handshake(private_tls_fragmentation_t *this,
status_t status;
chunk_t data;
- if (reader->remaining(reader) > MAX_TLS_FRAGMENT_LEN)
+ if (reader->remaining(reader) > TLS_MAX_FRAGMENT_LEN)
{
DBG1(DBG_TLS, "TLS fragment has invalid length");
this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
@@ -151,7 +146,7 @@ static status_t process_handshake(private_tls_fragmentation_t *this,
return NEED_MORE;
}
this->type = type;
- if (len > MAX_TLS_HANDSHAKE_LEN)
+ if (len > TLS_MAX_HANDSHAKE_LEN)
{
DBG1(DBG_TLS, "TLS handshake exceeds maximum length");
this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
@@ -202,12 +197,18 @@ static status_t process_handshake(private_tls_fragmentation_t *this,
static status_t process_application(private_tls_fragmentation_t *this,
bio_reader_t *reader)
{
+ if (!this->handshake->finished(this->handshake))
+ {
+ DBG1(DBG_TLS, "received TLS application data, "
+ "but handshake not finished");
+ return FAILED;
+ }
while (reader->remaining(reader))
{
status_t status;
chunk_t data;
- if (reader->remaining(reader) > MAX_TLS_FRAGMENT_LEN)
+ if (reader->remaining(reader) > TLS_MAX_FRAGMENT_LEN)
{
DBG1(DBG_TLS, "TLS fragment has invalid length");
this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
@@ -427,14 +428,14 @@ METHOD(tls_fragmentation_t, build, status_t,
if (this->output.len)
{
*type = this->output_type;
- if (this->output.len <= MAX_TLS_FRAGMENT_LEN)
+ if (this->output.len <= TLS_MAX_FRAGMENT_LEN)
{
*data = this->output;
this->output = chunk_empty;
return NEED_MORE;
}
- *data = chunk_create(this->output.ptr, MAX_TLS_FRAGMENT_LEN);
- this->output = chunk_clone(chunk_skip(this->output, MAX_TLS_FRAGMENT_LEN));
+ *data = chunk_create(this->output.ptr, TLS_MAX_FRAGMENT_LEN);
+ this->output = chunk_clone(chunk_skip(this->output, TLS_MAX_FRAGMENT_LEN));
return NEED_MORE;
}
return status;
diff --git a/src/libtls/tls_peer.c b/src/libtls/tls_peer.c
index 6091702cf..65072d087 100644
--- a/src/libtls/tls_peer.c
+++ b/src/libtls/tls_peer.c
@@ -709,13 +709,15 @@ static status_t send_client_hello(private_tls_peer_t *this,
htoun32(&this->client_random, time(NULL));
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
- if (!rng)
+ if (!rng ||
+ !rng->get_bytes(rng, sizeof(this->client_random) - 4,
+ this->client_random + 4))
{
- DBG1(DBG_TLS, "no suitable RNG found to generate client random");
+ DBG1(DBG_TLS, "failed to generate client random");
this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
+ DESTROY_IF(rng);
return NEED_MORE;
}
- rng->get_bytes(rng, sizeof(this->client_random) - 4, this->client_random + 4);
rng->destroy(rng);
/* TLS version */
@@ -903,20 +905,24 @@ static status_t send_key_exchange_encrypt(private_tls_peer_t *this,
chunk_t encrypted;
rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
- if (!rng)
+ if (!rng || !rng->get_bytes(rng, sizeof(premaster) - 2, premaster + 2))
{
- DBG1(DBG_TLS, "no suitable RNG found for TLS premaster secret");
+ DBG1(DBG_TLS, "failed to generate TLS premaster secret");
this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
+ DESTROY_IF(rng);
return NEED_MORE;
}
- rng->get_bytes(rng, sizeof(premaster) - 2, premaster + 2);
rng->destroy(rng);
htoun16(premaster, TLS_1_2);
- this->crypto->derive_secrets(this->crypto, chunk_from_thing(premaster),
- this->session, this->server,
- chunk_from_thing(this->client_random),
- chunk_from_thing(this->server_random));
+ if (!this->crypto->derive_secrets(this->crypto, chunk_from_thing(premaster),
+ this->session, this->server,
+ chunk_from_thing(this->client_random),
+ chunk_from_thing(this->server_random)))
+ {
+ this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
+ return NEED_MORE;
+ }
public = find_public_key(this);
if (!public)
@@ -958,10 +964,15 @@ static status_t send_key_exchange_dhe(private_tls_peer_t *this,
this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
return NEED_MORE;
}
- this->crypto->derive_secrets(this->crypto, premaster,
- this->session, this->server,
- chunk_from_thing(this->client_random),
- chunk_from_thing(this->server_random));
+ if (!this->crypto->derive_secrets(this->crypto, premaster,
+ this->session, this->server,
+ chunk_from_thing(this->client_random),
+ chunk_from_thing(this->server_random)))
+ {
+ this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
+ chunk_clear(&premaster);
+ return NEED_MORE;
+ }
chunk_clear(&premaster);
this->dh->get_my_public_value(this->dh, &pub);
diff --git a/src/libtls/tls_prf.c b/src/libtls/tls_prf.c
index f181d01d3..918de1e50 100644
--- a/src/libtls/tls_prf.c
+++ b/src/libtls/tls_prf.c
@@ -33,16 +33,16 @@ struct private_tls_prf12_t {
prf_t *prf;
};
-METHOD(tls_prf_t, set_key12, void,
+METHOD(tls_prf_t, set_key12, bool,
private_tls_prf12_t *this, chunk_t key)
{
- this->prf->set_key(this->prf, key);
+ return this->prf->set_key(this->prf, key);
}
/**
* The P_hash function as in TLS 1.0/1.2
*/
-static void p_hash(prf_t *prf, char *label, chunk_t seed, size_t block_size,
+static bool p_hash(prf_t *prf, char *label, chunk_t seed, size_t block_size,
size_t bytes, char *out)
{
char buf[block_size], abuf[block_size];
@@ -56,11 +56,17 @@ static void p_hash(prf_t *prf, char *label, chunk_t seed, size_t block_size,
while (TRUE)
{
/* A(i) = HMAC_hash(secret, A(i-1)) */
- prf->get_bytes(prf, a, abuf);
+ if (!prf->get_bytes(prf, a, abuf))
+ {
+ return FALSE;
+ }
a = chunk_from_thing(abuf);
/* HMAC_hash(secret, A(i) + seed) */
- prf->get_bytes(prf, a, NULL);
- prf->get_bytes(prf, seed, buf);
+ if (!prf->get_bytes(prf, a, NULL) ||
+ !prf->get_bytes(prf, seed, buf))
+ {
+ return FALSE;
+ }
if (bytes <= block_size)
{
@@ -71,14 +77,15 @@ static void p_hash(prf_t *prf, char *label, chunk_t seed, size_t block_size,
out += block_size;
bytes -= block_size;
}
+ return TRUE;
}
-METHOD(tls_prf_t, get_bytes12, void,
+METHOD(tls_prf_t, get_bytes12, bool,
private_tls_prf12_t *this, char *label, chunk_t seed,
size_t bytes, char *out)
{
- p_hash(this->prf, label, seed, this->prf->get_block_size(this->prf),
- bytes, out);
+ return p_hash(this->prf, label, seed, this->prf->get_block_size(this->prf),
+ bytes, out);
}
METHOD(tls_prf_t, destroy12, void,
@@ -135,26 +142,31 @@ struct private_tls_prf10_t {
prf_t *sha1;
};
-METHOD(tls_prf_t, set_key10, void,
+METHOD(tls_prf_t, set_key10, bool,
private_tls_prf10_t *this, chunk_t key)
{
size_t len = key.len / 2 + key.len % 2;
- this->md5->set_key(this->md5, chunk_create(key.ptr, len));
- this->sha1->set_key(this->sha1, chunk_create(key.ptr + key.len - len, len));
+ return this->md5->set_key(this->md5, chunk_create(key.ptr, len)) &&
+ this->sha1->set_key(this->sha1, chunk_create(key.ptr + key.len - len,
+ len));
}
-METHOD(tls_prf_t, get_bytes10, void,
+METHOD(tls_prf_t, get_bytes10, bool,
private_tls_prf10_t *this, char *label, chunk_t seed,
size_t bytes, char *out)
{
char buf[bytes];
- p_hash(this->md5, label, seed, this->md5->get_block_size(this->md5),
- bytes, out);
- p_hash(this->sha1, label, seed, this->sha1->get_block_size(this->sha1),
- bytes, buf);
+ if (!p_hash(this->md5, label, seed, this->md5->get_block_size(this->md5),
+ bytes, out) ||
+ !p_hash(this->sha1, label, seed, this->sha1->get_block_size(this->sha1),
+ bytes, buf))
+ {
+ return FALSE;
+ }
memxor(out, buf, bytes);
+ return TRUE;
}
METHOD(tls_prf_t, destroy10, void,
diff --git a/src/libtls/tls_prf.h b/src/libtls/tls_prf.h
index 9fb9bc2de..095eaea3a 100644
--- a/src/libtls/tls_prf.h
+++ b/src/libtls/tls_prf.h
@@ -34,8 +34,9 @@ struct tls_prf_t {
* Set the key of the PRF function.
*
* @param key key to set
+ * @return TRUE if key set successfully
*/
- void (*set_key)(tls_prf_t *this, chunk_t key);
+ bool (*set_key)(tls_prf_t *this, chunk_t key);
/**
* Generate a series of bytes using a label and a seed.
@@ -44,8 +45,9 @@ struct tls_prf_t {
* @param seed seed input value
* @param bytes number of bytes to get
* @param out buffer receiving bytes
+ * @return TRUE if bytes generated successfully
*/
- void (*get_bytes)(tls_prf_t *this, char *label, chunk_t seed,
+ bool (*get_bytes)(tls_prf_t *this, char *label, chunk_t seed,
size_t bytes, char *out);
/**
diff --git a/src/libtls/tls_protection.c b/src/libtls/tls_protection.c
index dc734545c..8263728bb 100644
--- a/src/libtls/tls_protection.c
+++ b/src/libtls/tls_protection.c
@@ -93,7 +93,7 @@ struct private_tls_protection_t {
/**
* Create the header and feed it into a signer for MAC verification
*/
-static void sigheader(signer_t *signer, u_int32_t seq, u_int8_t type,
+static bool sigheader(signer_t *signer, u_int32_t seq, u_int8_t type,
u_int16_t version, u_int16_t length)
{
/* we only support 32 bit sequence numbers, but TLS uses 64 bit */
@@ -110,7 +110,7 @@ static void sigheader(signer_t *signer, u_int32_t seq, u_int8_t type,
htoun16(&header.version, version);
htoun16(&header.length, length);
- signer->get_signature(signer, chunk_from_thing(header), NULL);
+ return signer->get_signature(signer, chunk_from_thing(header), NULL);
}
METHOD(tls_protection_t, process, status_t,
@@ -150,7 +150,12 @@ METHOD(tls_protection_t, process, status_t,
return NEED_MORE;
}
}
- this->crypter_in->decrypt(this->crypter_in, data, iv, NULL);
+ if (!this->crypter_in->decrypt(this->crypter_in, data, iv, NULL))
+ {
+ free(next_iv.ptr);
+ this->alert->add(this->alert, TLS_FATAL, TLS_BAD_RECORD_MAC);
+ return NEED_MORE;
+ }
if (next_iv.len)
{ /* next record IV is last ciphertext block of this record */
@@ -180,8 +185,9 @@ METHOD(tls_protection_t, process, status_t,
mac = chunk_skip(data, data.len - bs);
data.len -= bs;
- sigheader(this->signer_in, this->seq_in, type, this->version, data.len);
- if (!this->signer_in->verify_signature(this->signer_in, data, mac))
+ if (!sigheader(this->signer_in, this->seq_in, type,
+ this->version, data.len) ||
+ !this->signer_in->verify_signature(this->signer_in, data, mac))
{
DBG1(DBG_TLS, "TLS record MAC verification failed");
this->alert->add(this->alert, TLS_FATAL, TLS_BAD_RECORD_MAC);
@@ -218,9 +224,13 @@ METHOD(tls_protection_t, build, status_t,
{
chunk_t mac;
- sigheader(this->signer_out, this->seq_out, *type,
- this->version, data->len);
- this->signer_out->allocate_signature(this->signer_out, *data, &mac);
+ if (!sigheader(this->signer_out, this->seq_out, *type,
+ this->version, data->len) ||
+ !this->signer_out->allocate_signature(this->signer_out,
+ *data, &mac))
+ {
+ return FAILED;
+ }
if (this->crypter_out)
{
chunk_t padding, iv;
@@ -238,20 +248,29 @@ METHOD(tls_protection_t, build, status_t,
}
else
{ /* TLSv1.1 uses random IVs, prepended to record */
- if (!this->rng)
+ iv.len = this->crypter_out->get_iv_size(this->crypter_out);
+ if (!this->rng ||
+ !this->rng->allocate_bytes(this->rng, iv.len, &iv))
{
- DBG1(DBG_TLS, "no RNG supported to generate TLS IV");
+ DBG1(DBG_TLS, "failed to generate TLS IV");
free(data->ptr);
return FAILED;
}
- iv.len = this->crypter_out->get_iv_size(this->crypter_out);
- this->rng->allocate_bytes(this->rng, iv.len, &iv);
}
*data = chunk_cat("mmcc", *data, mac, padding,
chunk_from_thing(padding_length));
/* encrypt inline */
- this->crypter_out->encrypt(this->crypter_out, *data, iv, NULL);
+ if (!this->crypter_out->encrypt(this->crypter_out, *data,
+ iv, NULL))
+ {
+ if (!this->iv_out.len)
+ {
+ free(iv.ptr);
+ }
+ free(data->ptr);
+ return FAILED;
+ }
if (this->iv_out.len)
{ /* next record IV is last ciphertext block of this record */
diff --git a/src/libtls/tls_server.c b/src/libtls/tls_server.c
index e3617dc9a..a66448d24 100644
--- a/src/libtls/tls_server.c
+++ b/src/libtls/tls_server.c
@@ -266,13 +266,15 @@ static status_t process_client_hello(private_tls_server_t *this,
htoun32(&this->server_random, time(NULL));
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
- if (!rng)
+ if (!rng ||
+ !rng->get_bytes(rng, sizeof(this->server_random) - 4,
+ this->server_random + 4))
{
- DBG1(DBG_TLS, "no suitable RNG found to generate server random");
+ DBG1(DBG_TLS, "failed to generate server random");
this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
+ DESTROY_IF(rng);
return NEED_MORE;
}
- rng->get_bytes(rng, sizeof(this->server_random) - 4, this->server_random + 4);
rng->destroy(rng);
if (!this->tls->set_version(this->tls, version))
@@ -311,11 +313,11 @@ static status_t process_client_hello(private_tls_server_t *this,
return NEED_MORE;
}
rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
- if (rng)
+ if (!rng || !rng->allocate_bytes(rng, SESSION_ID_SIZE, &this->session))
{
- rng->allocate_bytes(rng, SESSION_ID_SIZE, &this->session);
- rng->destroy(rng);
+ DBG1(DBG_TLS, "generating TLS session identifier failed, skipped");
}
+ DESTROY_IF(rng);
DBG1(DBG_TLS, "negotiated %N using suite %N",
tls_version_names, this->tls->get_version(this->tls),
tls_cipher_suite_names, this->suite);
@@ -407,13 +409,13 @@ static status_t process_key_exchange_encrypted(private_tls_server_t *this,
htoun16(premaster, this->client_version);
/* pre-randomize premaster for failure cases */
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
- if (!rng)
+ if (!rng || !rng->get_bytes(rng, sizeof(premaster) - 2, premaster + 2))
{
- DBG1(DBG_TLS, "creating RNG failed");
+ DBG1(DBG_TLS, "failed to generate premaster secret");
this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
+ DESTROY_IF(rng);
return NEED_MORE;
}
- rng->get_bytes(rng, sizeof(premaster) - 2, premaster + 2);
rng->destroy(rng);
if (this->private &&
@@ -436,10 +438,14 @@ static status_t process_key_exchange_encrypted(private_tls_server_t *this,
DBG1(DBG_TLS, "decrypting Client Key Exchange failed");
}
- this->crypto->derive_secrets(this->crypto, chunk_from_thing(premaster),
- this->session, this->peer,
- chunk_from_thing(this->client_random),
- chunk_from_thing(this->server_random));
+ if (!this->crypto->derive_secrets(this->crypto, chunk_from_thing(premaster),
+ this->session, this->peer,
+ chunk_from_thing(this->client_random),
+ chunk_from_thing(this->server_random)))
+ {
+ this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
+ return NEED_MORE;
+ }
this->state = STATE_KEY_EXCHANGE_RECEIVED;
return NEED_MORE;
@@ -485,10 +491,15 @@ static status_t process_key_exchange_dhe(private_tls_server_t *this,
return NEED_MORE;
}
- this->crypto->derive_secrets(this->crypto, premaster,
- this->session, this->peer,
- chunk_from_thing(this->client_random),
- chunk_from_thing(this->server_random));
+ if (!this->crypto->derive_secrets(this->crypto, premaster,
+ this->session, this->peer,
+ chunk_from_thing(this->client_random),
+ chunk_from_thing(this->server_random)))
+ {
+ this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
+ chunk_clear(&premaster);
+ return NEED_MORE;
+ }
chunk_clear(&premaster);
this->state = STATE_KEY_EXCHANGE_RECEIVED;
diff --git a/src/libtnccs/Makefile.in b/src/libtnccs/Makefile.in
index 61a51fb4c..5eac73ab0 100644
--- a/src/libtnccs/Makefile.in
+++ b/src/libtnccs/Makefile.in
@@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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'`;
@@ -78,7 +79,7 @@ libtnccs_la_DEPENDENCIES = $(top_builddir)/src/libtncif/libtncif.la
am_libtnccs_la_OBJECTS = tnc.lo imv_recommendations.lo tnccs.lo \
tnccs_manager.lo
libtnccs_la_OBJECTS = $(am_libtnccs_la_OBJECTS)
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -104,6 +105,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -198,11 +200,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -219,11 +224,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -239,6 +245,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -248,7 +255,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/libtnccs/tnc/imv/imv_recommendations.h b/src/libtnccs/tnc/imv/imv_recommendations.h
index d694e16ae..e7fe355f7 100644
--- a/src/libtnccs/tnc/imv/imv_recommendations.h
+++ b/src/libtnccs/tnc/imv/imv_recommendations.h
@@ -68,6 +68,11 @@ struct recommendations_t {
TNC_IMV_Evaluation_Result *eval);
/**
+ * Clear all recommendation information
+ */
+ void (*clear_recommendation)(recommendations_t *this);
+
+ /**
* Get the preferred language for remediation messages
*
* @return preferred language
@@ -110,11 +115,6 @@ struct recommendations_t {
enumerator_t* (*create_reason_enumerator)(recommendations_t *this);
/**
- * Clears all reason entries
- */
- void (*clear_reasons)(recommendations_t *this);
-
- /**
* Destroys an imv_t object.
*/
void (*destroy)(recommendations_t *this);
diff --git a/src/libtnccs/tnc/tnc.c b/src/libtnccs/tnc/tnc.c
index 652afc291..7c0ee4132 100644
--- a/src/libtnccs/tnc/tnc.c
+++ b/src/libtnccs/tnc/tnc.c
@@ -57,7 +57,7 @@ void libtnccs_init(void)
INIT(this,
.public = {
},
- );
+ );
tnc = &this->public;
}
@@ -75,6 +75,7 @@ void libtnccs_deinit(void)
static bool load_imcvs_from_config(char *filename, bool is_imc)
{
+ bool success = FALSE;
int fd, line_nr = 0;
chunk_t src, line;
struct stat sb;
@@ -110,7 +111,6 @@ static bool load_imcvs_from_config(char *filename, bool is_imc)
while (fetchline(&src, &line))
{
char *name, *path;
- bool success;
chunk_t token;
line_nr++;
@@ -126,7 +126,7 @@ static bool load_imcvs_from_config(char *filename, bool is_imc)
{
DBG1(DBG_TNC, "line %d: keyword must be followed by a space",
line_nr);
- return FALSE;
+ break;
}
/* only interested in IMCs or IMVs depending on label */
@@ -141,7 +141,7 @@ static bool load_imcvs_from_config(char *filename, bool is_imc)
{
DBG1(DBG_TNC, "line %d: %s name must be set in double quotes",
line_nr, label);
- return FALSE;
+ break;
}
/* copy the IMC/IMV name */
@@ -154,7 +154,7 @@ static bool load_imcvs_from_config(char *filename, bool is_imc)
{
DBG1(DBG_TNC, "line %d: %s path is missing", line_nr, label);
free(name);
- return FALSE;
+ break;
}
if (!extract_token(&token, ' ', &line))
{
@@ -177,12 +177,12 @@ static bool load_imcvs_from_config(char *filename, bool is_imc)
}
if (!success)
{
- return FALSE;
+ break;
}
}
munmap(addr, sb.st_size);
close(fd);
- return TRUE;
+ return success;
}
/**
diff --git a/src/libtnccs/tnc/tnccs/tnccs_manager.h b/src/libtnccs/tnc/tnccs/tnccs_manager.h
index 9ca450468..cbf2dc0e9 100644
--- a/src/libtnccs/tnc/tnccs/tnccs_manager.h
+++ b/src/libtnccs/tnc/tnccs/tnccs_manager.h
@@ -70,6 +70,7 @@ struct tnccs_manager_t {
* @param tnccs TNCCS connection instance
* @param send_message TNCCS callback function
* @param request_handshake_retry pointer to boolean variable
+ * @param max_msg_len maximum PA-TNC message size
* @param recs pointer to IMV recommendation set
* @return assigned connection ID
*/
@@ -77,6 +78,7 @@ struct tnccs_manager_t {
tnccs_type_t type, tnccs_t *tnccs,
tnccs_send_message_t send_message,
bool *request_handshake_retry,
+ u_int32_t max_msg_len,
recommendations_t **recs);
/**
diff --git a/src/libtncif/Makefile.in b/src/libtncif/Makefile.in
index 462b8bd3f..013266c20 100644
--- a/src/libtncif/Makefile.in
+++ b/src/libtncif/Makefile.in
@@ -49,13 +49,14 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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 =
LTLIBRARIES = $(noinst_LTLIBRARIES)
libtncif_la_LIBADD =
am_libtncif_la_OBJECTS = tncif_names.lo tncif_pa_subtypes.lo
libtncif_la_OBJECTS = $(am_libtncif_la_OBJECTS)
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -81,6 +82,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -175,11 +177,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -196,11 +201,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -216,6 +222,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -225,7 +232,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/manager/Makefile.in b/src/manager/Makefile.in
index 8ae5ebf36..e65328cfa 100644
--- a/src/manager/Makefile.in
+++ b/src/manager/Makefile.in
@@ -51,6 +51,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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__installdirs = "$(DESTDIR)$(managerdir)" \
@@ -72,7 +73,7 @@ am__DEPENDENCIES_1 =
manager_fcgi_DEPENDENCIES = \
$(top_builddir)/src/libstrongswan/libstrongswan.la \
$(top_builddir)/src/libfast/libfast.la $(am__DEPENDENCIES_1)
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -125,6 +126,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -219,11 +221,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -240,11 +245,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -260,6 +266,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -269,7 +276,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/manager/storage.c b/src/manager/storage.c
index 5461a4288..6a8e76e5e 100644
--- a/src/manager/storage.c
+++ b/src/manager/storage.c
@@ -58,7 +58,11 @@ METHOD(storage_t, login, int,
data = chunk_alloca(username_len + password_len);
memcpy(data.ptr, username, username_len);
memcpy(data.ptr + username_len, password, password_len);
- hasher->get_hash(hasher, data, hash.ptr);
+ if (!hasher->get_hash(hasher, data, hash.ptr))
+ {
+ hasher->destroy(hasher);
+ return 0;
+ }
hasher->destroy(hasher);
hex_str = chunk_to_hex(hash, NULL, FALSE);
diff --git a/src/medsrv/Makefile.in b/src/medsrv/Makefile.in
index 95f02c580..85b1f0d92 100644
--- a/src/medsrv/Makefile.in
+++ b/src/medsrv/Makefile.in
@@ -51,6 +51,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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__installdirs = "$(DESTDIR)$(medsrvdir)" \
@@ -66,7 +67,7 @@ medsrv_fcgi_OBJECTS = $(am_medsrv_fcgi_OBJECTS)
medsrv_fcgi_DEPENDENCIES = \
$(top_builddir)/src/libstrongswan/libstrongswan.la \
$(top_builddir)/src/libfast/libfast.la
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -115,6 +116,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -209,11 +211,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -230,11 +235,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -250,6 +256,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -259,7 +266,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/medsrv/controller/peer_controller.c b/src/medsrv/controller/peer_controller.c
index edcf653b2..edcf653b2 100755..100644
--- a/src/medsrv/controller/peer_controller.c
+++ b/src/medsrv/controller/peer_controller.c
diff --git a/src/medsrv/controller/peer_controller.h b/src/medsrv/controller/peer_controller.h
index f25c30281..f25c30281 100755..100644
--- a/src/medsrv/controller/peer_controller.h
+++ b/src/medsrv/controller/peer_controller.h
diff --git a/src/medsrv/controller/user_controller.c b/src/medsrv/controller/user_controller.c
index 12bd938fe..35c9d90c8 100755..100644
--- a/src/medsrv/controller/user_controller.c
+++ b/src/medsrv/controller/user_controller.c
@@ -64,7 +64,11 @@ static chunk_t hash_password(char *login, char *password)
}
data = chunk_cata("cc", chunk_create(login, strlen(login)),
chunk_create(password, strlen(password)));
- hasher->allocate_hash(hasher, data, &hash);
+ if (!hasher->allocate_hash(hasher, data, &hash))
+ {
+ hasher->destroy(hasher);
+ return chunk_empty;
+ }
hasher->destroy(hasher);
return hash;
}
diff --git a/src/medsrv/controller/user_controller.h b/src/medsrv/controller/user_controller.h
index 9d23795d7..9d23795d7 100755..100644
--- a/src/medsrv/controller/user_controller.h
+++ b/src/medsrv/controller/user_controller.h
diff --git a/src/medsrv/filter/auth_filter.c b/src/medsrv/filter/auth_filter.c
index d21abdc46..d21abdc46 100755..100644
--- a/src/medsrv/filter/auth_filter.c
+++ b/src/medsrv/filter/auth_filter.c
diff --git a/src/medsrv/filter/auth_filter.h b/src/medsrv/filter/auth_filter.h
index c46de40a5..c46de40a5 100755..100644
--- a/src/medsrv/filter/auth_filter.h
+++ b/src/medsrv/filter/auth_filter.h
diff --git a/src/medsrv/templates/footer.cs b/src/medsrv/templates/footer.cs
index db3601961..db3601961 100755..100644
--- a/src/medsrv/templates/footer.cs
+++ b/src/medsrv/templates/footer.cs
diff --git a/src/medsrv/templates/header.cs b/src/medsrv/templates/header.cs
index 4ab4afd1e..4ab4afd1e 100755..100644
--- a/src/medsrv/templates/header.cs
+++ b/src/medsrv/templates/header.cs
diff --git a/src/medsrv/templates/peer/add.cs b/src/medsrv/templates/peer/add.cs
index 28a994f7f..28a994f7f 100755..100644
--- a/src/medsrv/templates/peer/add.cs
+++ b/src/medsrv/templates/peer/add.cs
diff --git a/src/medsrv/templates/peer/edit.cs b/src/medsrv/templates/peer/edit.cs
index 76fb9dafc..76fb9dafc 100755..100644
--- a/src/medsrv/templates/peer/edit.cs
+++ b/src/medsrv/templates/peer/edit.cs
diff --git a/src/medsrv/templates/peer/list.cs b/src/medsrv/templates/peer/list.cs
index 205452641..205452641 100755..100644
--- a/src/medsrv/templates/peer/list.cs
+++ b/src/medsrv/templates/peer/list.cs
diff --git a/src/medsrv/templates/static/favicon.ico b/src/medsrv/templates/static/favicon.ico
index d00459196..d00459196 100755..100644
--- a/src/medsrv/templates/static/favicon.ico
+++ b/src/medsrv/templates/static/favicon.ico
Binary files differ
diff --git a/src/medsrv/templates/static/strongswan.png b/src/medsrv/templates/static/strongswan.png
index 869188cdf..869188cdf 100755..100644
--- a/src/medsrv/templates/static/strongswan.png
+++ b/src/medsrv/templates/static/strongswan.png
Binary files differ
diff --git a/src/medsrv/templates/static/style.css b/src/medsrv/templates/static/style.css
index e109ce278..e109ce278 100755..100644
--- a/src/medsrv/templates/static/style.css
+++ b/src/medsrv/templates/static/style.css
diff --git a/src/medsrv/templates/user/add.cs b/src/medsrv/templates/user/add.cs
index 8ba4e5c96..8ba4e5c96 100755..100644
--- a/src/medsrv/templates/user/add.cs
+++ b/src/medsrv/templates/user/add.cs
diff --git a/src/medsrv/templates/user/edit.cs b/src/medsrv/templates/user/edit.cs
index 1f168498b..1f168498b 100755..100644
--- a/src/medsrv/templates/user/edit.cs
+++ b/src/medsrv/templates/user/edit.cs
diff --git a/src/medsrv/templates/user/login.cs b/src/medsrv/templates/user/login.cs
index 1d6eadbbc..1d6eadbbc 100755..100644
--- a/src/medsrv/templates/user/login.cs
+++ b/src/medsrv/templates/user/login.cs
diff --git a/src/openac/Makefile.in b/src/openac/Makefile.in
index 95043350d..9b67a5667 100644
--- a/src/openac/Makefile.in
+++ b/src/openac/Makefile.in
@@ -51,6 +51,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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__installdirs = "$(DESTDIR)$(ipsecdir)" "$(DESTDIR)$(man8dir)"
@@ -59,7 +60,7 @@ am_openac_OBJECTS = openac.$(OBJEXT)
openac_OBJECTS = $(am_openac_OBJECTS)
openac_DEPENDENCIES = \
$(top_builddir)/src/libstrongswan/libstrongswan.la
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -109,6 +110,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -203,11 +205,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -224,11 +229,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -244,6 +250,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -253,7 +260,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/openac/openac.c b/src/openac/openac.c
index 745988750..745988750 100755..100644
--- a/src/openac/openac.c
+++ b/src/openac/openac.c
diff --git a/src/pki/Makefile.in b/src/pki/Makefile.in
index f9c417658..609ab345b 100644
--- a/src/pki/Makefile.in
+++ b/src/pki/Makefile.in
@@ -50,6 +50,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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__installdirs = "$(DESTDIR)$(ipsecdir)"
@@ -60,7 +61,7 @@ am_pki_OBJECTS = pki.$(OBJEXT) command.$(OBJEXT) gen.$(OBJEXT) \
verify.$(OBJEXT)
pki_OBJECTS = $(am_pki_OBJECTS)
pki_DEPENDENCIES = $(top_builddir)/src/libstrongswan/libstrongswan.la
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -86,6 +87,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -180,11 +182,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -201,11 +206,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -221,6 +227,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -230,7 +237,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/pki/command.c b/src/pki/command.c
index 07ba5bb1d..43328575c 100644
--- a/src/pki/command.c
+++ b/src/pki/command.c
@@ -144,7 +144,7 @@ void command_register(command_t command)
/* append default options, but not to --help */
if (!active)
{
- for (i = 0; i < countof(cmds[registered].options); i++)
+ for (i = 0; i < countof(cmds[registered].options) - 1; i++)
{
if (cmds[registered].options[i].name)
{
diff --git a/src/pki/commands/issue.c b/src/pki/commands/issue.c
index 20163edf2..47e668b6c 100644
--- a/src/pki/commands/issue.c
+++ b/src/pki/commands/issue.c
@@ -105,8 +105,8 @@ static int issue()
}
continue;
case 'g':
- digest = get_digest(arg);
- if (digest == HASH_UNKNOWN)
+ digest = enum_from_name(hash_algorithm_short_names, arg);
+ if (digest == -1)
{
error = "invalid --digest type";
goto usage;
@@ -229,6 +229,10 @@ static int issue()
{
flags |= X509_CLIENT_AUTH;
}
+ else if (streq(arg, "ikeIntermediate"))
+ {
+ flags |= X509_IKE_INTERMEDIATE;
+ }
else if (streq(arg, "crlSign"))
{
flags |= X509_CRL_SIGN;
@@ -352,11 +356,11 @@ static int issue()
error = "no random number generator found";
goto end;
}
- rng->allocate_bytes(rng, 8, &serial);
- while (*serial.ptr == 0x00)
+ if (!rng_allocate_bytes_not_zero(rng, 8, &serial, FALSE))
{
- /* we don't accept a serial number with leading zeroes */
- rng->get_bytes(rng, 1, serial.ptr);
+ error = "failed to generate serial number";
+ rng->destroy(rng);
+ goto end;
}
rng->destroy(rng);
}
diff --git a/src/pki/commands/print.c b/src/pki/commands/print.c
index a7f02bfac..90cf254c8 100644
--- a/src/pki/commands/print.c
+++ b/src/pki/commands/print.c
@@ -133,6 +133,10 @@ static void print_x509(x509_t *x509)
{
printf("clientAuth ");
}
+ if (flags & X509_IKE_INTERMEDIATE)
+ {
+ printf("iKEIntermediate ");
+ }
if (flags & X509_SELF_SIGNED)
{
printf("self-signed ");
diff --git a/src/pki/commands/req.c b/src/pki/commands/req.c
index 087a97b3e..d050c7032 100644
--- a/src/pki/commands/req.c
+++ b/src/pki/commands/req.c
@@ -63,8 +63,8 @@ static int req()
}
continue;
case 'g':
- digest = get_digest(arg);
- if (digest == HASH_UNKNOWN)
+ digest = enum_from_name(hash_algorithm_short_names, arg);
+ if (digest == -1)
{
error = "invalid --digest type";
goto usage;
diff --git a/src/pki/commands/self.c b/src/pki/commands/self.c
index c4508a671..4a50aa463 100644
--- a/src/pki/commands/self.c
+++ b/src/pki/commands/self.c
@@ -94,8 +94,8 @@ static int self()
}
continue;
case 'g':
- digest = get_digest(arg);
- if (digest == HASH_UNKNOWN)
+ digest = enum_from_name(hash_algorithm_short_names, arg);
+ if (digest == -1)
{
error = "invalid --digest type";
goto usage;
@@ -212,6 +212,10 @@ static int self()
{
flags |= X509_CLIENT_AUTH;
}
+ else if (streq(arg, "ikeIntermediate"))
+ {
+ flags |= X509_IKE_INTERMEDIATE;
+ }
else if (streq(arg, "crlSign"))
{
flags |= X509_CRL_SIGN;
@@ -294,11 +298,11 @@ static int self()
error = "no random number generator found";
goto end;
}
- rng->allocate_bytes(rng, 8, &serial);
- while (*serial.ptr == 0x00)
+ if (!rng_allocate_bytes_not_zero(rng, 8, &serial, FALSE))
{
- /* we don't accept a serial number with leading zeroes */
- rng->get_bytes(rng, 1, serial.ptr);
+ error = "failed to generate serial number";
+ rng->destroy(rng);
+ goto end;
}
rng->destroy(rng);
}
diff --git a/src/pki/commands/signcrl.c b/src/pki/commands/signcrl.c
index 153734f53..4ada120ed 100644
--- a/src/pki/commands/signcrl.c
+++ b/src/pki/commands/signcrl.c
@@ -141,8 +141,8 @@ static int sign_crl()
case 'h':
goto usage;
case 'g':
- digest = get_digest(arg);
- if (digest == HASH_UNKNOWN)
+ digest = enum_from_name(hash_algorithm_short_names, arg);
+ if (digest == -1)
{
error = "invalid --digest type";
goto usage;
diff --git a/src/pki/commands/verify.c b/src/pki/commands/verify.c
index bbcc53891..3e983d3ec 100644
--- a/src/pki/commands/verify.c
+++ b/src/pki/commands/verify.c
@@ -77,7 +77,7 @@ static int verify()
{
ca = cert;
}
- if (cert->issued_by(cert, ca))
+ if (cert->issued_by(cert, ca, NULL))
{
if (cert->get_validity(cert, NULL, NULL, NULL))
{
diff --git a/src/pki/pki.c b/src/pki/pki.c
index 3005d2fcd..e28bf1595 100644
--- a/src/pki/pki.c
+++ b/src/pki/pki.c
@@ -80,38 +80,6 @@ bool get_form(char *form, cred_encoding_type_t *enc, credential_type_t type)
}
/**
- * Convert a digest string to a hash algorithm
- */
-hash_algorithm_t get_digest(char *name)
-{
- if (streq(name, "md5"))
- {
- return HASH_MD5;
- }
- if (streq(name, "sha1"))
- {
- return HASH_SHA1;
- }
- if (streq(name, "sha224"))
- {
- return HASH_SHA224;
- }
- if (streq(name, "sha256"))
- {
- return HASH_SHA256;
- }
- if (streq(name, "sha384"))
- {
- return HASH_SHA384;
- }
- if (streq(name, "sha512"))
- {
- return HASH_SHA512;
- }
- return HASH_UNKNOWN;
-}
-
-/**
* Callback credential set pki uses
*/
static callback_cred_t *cb_set;
diff --git a/src/pki/pki.h b/src/pki/pki.h
index 9c145cdc0..f72b1804c 100644
--- a/src/pki/pki.h
+++ b/src/pki/pki.h
@@ -31,9 +31,4 @@
*/
bool get_form(char *form, cred_encoding_type_t *enc, credential_type_t type);
-/**
- * Convert a digest string to a hash algorithm
- */
-hash_algorithm_t get_digest(char *name);
-
#endif /** PKI_H_ @}*/
diff --git a/src/pluto/Android.mk b/src/pluto/Android.mk
deleted file mode 100644
index 618f79c42..000000000
--- a/src/pluto/Android.mk
+++ /dev/null
@@ -1,80 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-# copy-n-paste from Makefile.am
-LOCAL_SRC_FILES := \
-ac.c ac.h \
-alg_info.c alg_info.h \
-ca.c ca.h \
-certs.c certs.h \
-connections.c connections.h \
-constants.c constants.h \
-cookie.c cookie.h \
-crl.c crl.h \
-crypto.c crypto.h \
-db_ops.c db_ops.h \
-defs.c defs.h \
-demux.c demux.h \
-event_queue.c event_queue.h \
-fetch.c fetch.h \
-foodgroups.c foodgroups.h \
-ike_alg.c ike_alg.h \
-ipsec_doi.c ipsec_doi.h \
-kameipsec.h \
-kernel.c kernel.h \
-kernel_alg.c kernel_alg.h \
-kernel_pfkey.c kernel_pfkey.h \
-keys.c keys.h \
-lex.c lex.h \
-log.c log.h \
-myid.c myid.h \
-modecfg.c modecfg.h \
-nat_traversal.c nat_traversal.h \
-ocsp.c ocsp.h \
-packet.c packet.h \
-pkcs7.c pkcs7.h \
-plugin_list.c plugin_list.h \
-pluto.c pluto.h \
-plutomain.c \
-rcv_whack.c rcv_whack.h \
-server.c server.h \
-smartcard.c smartcard.h \
-spdb.c spdb.h \
-state.c state.h \
-timer.c timer.h \
-vendor.c vendor.h \
-virtual.c virtual.h \
-whack_attribute.c whack_attribute.h \
-xauth/xauth_manager.c xauth/xauth_manager.h \
-xauth/xauth_provider.h xauth/xauth_verifier.h \
-x509.c x509.h \
-builder.c builder.h \
-rsaref/pkcs11t.h rsaref/pkcs11.h rsaref/unix.h rsaref/pkcs11f.h
-
-LOCAL_SRC_FILES += $(call add_plugin, xauth)
-
-# build pluto ------------------------------------------------------------------
-
-LOCAL_C_INCLUDES += \
- $(libvstr_PATH) \
- $(strongswan_PATH)/src/libhydra \
- $(strongswan_PATH)/src/libstrongswan \
- $(strongswan_PATH)/src/libfreeswan \
- $(strongswan_PATH)/src/whack
-
-LOCAL_CFLAGS := $(strongswan_CFLAGS) \
- -DPLUTO -DVENDORID -DXAUTH_VID -DCISCO_QUIRKS \
- -DTHREADS -DKERNEL26_HAS_KAME_DUPLICATES \
- -DPLUGINS='"$(strongswan_PLUTO_PLUGINS)"'
-
-LOCAL_MODULE := pluto
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_ARM_MODE := arm
-
-LOCAL_PRELINK_MODULE := false
-
-LOCAL_SHARED_LIBRARIES += libstrongswan libhydra libfreeswan libcutils
-
-include $(BUILD_EXECUTABLE)
diff --git a/src/pluto/Makefile.am b/src/pluto/Makefile.am
deleted file mode 100644
index 3fd0e039c..000000000
--- a/src/pluto/Makefile.am
+++ /dev/null
@@ -1,155 +0,0 @@
-# Makefile.am was ported from the old Makefile the most
-# painless way. Only the most important options are included,
-# further work may be necessary here...
-
-ipsec_PROGRAMS = pluto
-
-if USE_ADNS
-ipsec_PROGRAMS += _pluto_adns
-endif
-
-pluto_SOURCES = \
-ac.c ac.h \
-alg_info.c alg_info.h \
-ca.c ca.h \
-certs.c certs.h \
-connections.c connections.h \
-constants.c constants.h \
-cookie.c cookie.h \
-crl.c crl.h \
-crypto.c crypto.h \
-db_ops.c db_ops.h \
-defs.c defs.h \
-demux.c demux.h \
-event_queue.c event_queue.h \
-fetch.c fetch.h \
-foodgroups.c foodgroups.h \
-ike_alg.c ike_alg.h \
-ipsec_doi.c ipsec_doi.h \
-kameipsec.h \
-kernel.c kernel.h \
-kernel_alg.c kernel_alg.h \
-kernel_pfkey.c kernel_pfkey.h \
-keys.c keys.h \
-lex.c lex.h \
-log.c log.h \
-myid.c myid.h \
-modecfg.c modecfg.h \
-nat_traversal.c nat_traversal.h \
-ocsp.c ocsp.h \
-packet.c packet.h \
-pkcs7.c pkcs7.h \
-plugin_list.c plugin_list.h \
-pluto.c pluto.h \
-plutomain.c \
-rcv_whack.c rcv_whack.h \
-server.c server.h \
-smartcard.c smartcard.h \
-spdb.c spdb.h \
-state.c state.h \
-timer.c timer.h \
-vendor.c vendor.h \
-virtual.c virtual.h \
-whack_attribute.c whack_attribute.h \
-xauth/xauth_manager.c xauth/xauth_manager.h \
-xauth/xauth_provider.h xauth/xauth_verifier.h \
-x509.c x509.h \
-builder.c builder.h \
-rsaref/pkcs11t.h rsaref/pkcs11.h rsaref/unix.h rsaref/pkcs11f.h
-
-if USE_ADNS
-pluto_SOURCES += \
-dnskey.c dnskey.h
-
-_pluto_adns_SOURCES = \
-adns.c adns.h
-endif
-
-plutomain.o : $(top_builddir)/config.status
-
-LIBSTRONGSWANDIR=$(top_builddir)/src/libstrongswan
-LIBFREESWANDIR=$(top_builddir)/src/libfreeswan
-LIBHYDRADIR=$(top_builddir)/src/libhydra
-
-INCLUDES = \
--I${linux_headers} \
--I$(top_srcdir)/src/libstrongswan \
--I$(top_srcdir)/src/libfreeswan \
--I$(top_srcdir)/src/libhydra \
--I$(top_srcdir)/src/whack
-
-AM_CFLAGS = -rdynamic \
--DIPSEC_DIR=\"${ipsecdir}\" \
--DIPSEC_CONFDIR=\"${sysconfdir}\" \
--DIPSEC_PIDDIR=\"${piddir}\" \
--DSHARED_SECRETS_FILE=\"${sysconfdir}/ipsec.secrets\" \
--DPLUGINS=\""${pluto_plugins}\"" \
--DPKCS11_DEFAULT_LIB=\"${default_pkcs11}\" \
--DKERNEL26_HAS_KAME_DUPLICATES \
--DPLUTO -DDEBUG
-
-pluto_LDADD = \
-$(LIBSTRONGSWANDIR)/libstrongswan.la \
-$(LIBFREESWANDIR)/libfreeswan.a \
-$(LIBHYDRADIR)/libhydra.la \
--lresolv $(PTHREADLIB) $(DLLIB)
-
-if USE_ADNS
-_pluto_adns_LDADD = \
-$(LIBFREESWANDIR)/libfreeswan.a \
--lresolv $(DLLIB)
-endif
-
-dist_man_MANS = pluto.8
-
-EXTRA_DIST = Android.mk
-
-# compile options
-#################
-
-# This compile option activates the sending of a strongSwan VID
-if USE_VENDORID
- AM_CFLAGS += -DVENDORID
-endif
-
-# This compile option activates the sending of the XAUTH VID
-if USE_XAUTH_VID
- AM_CFLAGS += -DXAUTH_VID
-endif
-
-# This compile option activates the support of the Cisco VPN client
-if USE_CISCO_QUIRKS
- AM_CFLAGS += -DCISCO_QUIRKS
-endif
-
-# This compile option activates NAT traversal with IPSec transport mode
-if USE_NAT_TRANSPORT
- AM_CFLAGS += -DI_KNOW_TRANSPORT_MODE_HAS_SECURITY_CONCERN_BUT_I_WANT_IT
-endif
-
-# This compile option activates smartcard support
-if USE_SMARTCARD
- AM_CFLAGS += -DSMARTCARD
-endif
-
-if USE_LIBCAP
- pluto_LDADD += -lcap
-endif
-
-if USE_THREADS
- AM_CFLAGS += -DTHREADS
-endif
-
-if USE_ADNS
- AM_CFLAGS += -DADNS
-endif
-
-# build optional plugins
-########################
-
-SUBDIRS = .
-
-if USE_XAUTH
- SUBDIRS += plugins/xauth
-endif
-
diff --git a/src/pluto/Makefile.in b/src/pluto/Makefile.in
deleted file mode 100644
index b055ba289..000000000
--- a/src/pluto/Makefile.in
+++ /dev/null
@@ -1,1001 +0,0 @@
-# Makefile.in generated by automake 1.11.1 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
-# Inc.
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-@SET_MAKE@
-
-# Makefile.am was ported from the old Makefile the most
-# painless way. Only the most important options are included,
-# further work may be necessary here...
-
-VPATH = @srcdir@
-pkgdatadir = $(datadir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkglibexecdir = $(libexecdir)/@PACKAGE@
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-build_triplet = @build@
-host_triplet = @host@
-ipsec_PROGRAMS = pluto$(EXEEXT) $(am__EXEEXT_1)
-@USE_ADNS_TRUE@am__append_1 = _pluto_adns
-@USE_ADNS_TRUE@am__append_2 = \
-@USE_ADNS_TRUE@dnskey.c dnskey.h
-
-
-# compile options
-#################
-
-# This compile option activates the sending of a strongSwan VID
-@USE_VENDORID_TRUE@am__append_3 = -DVENDORID
-
-# This compile option activates the sending of the XAUTH VID
-@USE_XAUTH_VID_TRUE@am__append_4 = -DXAUTH_VID
-
-# This compile option activates the support of the Cisco VPN client
-@USE_CISCO_QUIRKS_TRUE@am__append_5 = -DCISCO_QUIRKS
-
-# This compile option activates NAT traversal with IPSec transport mode
-@USE_NAT_TRANSPORT_TRUE@am__append_6 = -DI_KNOW_TRANSPORT_MODE_HAS_SECURITY_CONCERN_BUT_I_WANT_IT
-
-# This compile option activates smartcard support
-@USE_SMARTCARD_TRUE@am__append_7 = -DSMARTCARD
-@USE_LIBCAP_TRUE@am__append_8 = -lcap
-@USE_THREADS_TRUE@am__append_9 = -DTHREADS
-@USE_ADNS_TRUE@am__append_10 = -DADNS
-@USE_XAUTH_TRUE@am__append_11 = plugins/xauth
-subdir = src/pluto
-DIST_COMMON = $(dist_man_MANS) $(srcdir)/Makefile.am \
- $(srcdir)/Makefile.in
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
- $(top_srcdir)/m4/config/ltoptions.m4 \
- $(top_srcdir)/m4/config/ltsugar.m4 \
- $(top_srcdir)/m4/config/ltversion.m4 \
- $(top_srcdir)/m4/config/lt~obsolete.m4 \
- $(top_srcdir)/m4/macros/with.m4 \
- $(top_srcdir)/m4/macros/enable-disable.m4 \
- $(top_srcdir)/m4/macros/add-plugin.m4 \
- $(top_srcdir)/configure.in
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
- $(ACLOCAL_M4)
-mkinstalldirs = $(install_sh) -d
-CONFIG_CLEAN_FILES =
-CONFIG_CLEAN_VPATH_FILES =
-@USE_ADNS_TRUE@am__EXEEXT_1 = _pluto_adns$(EXEEXT)
-am__installdirs = "$(DESTDIR)$(ipsecdir)" "$(DESTDIR)$(man8dir)"
-PROGRAMS = $(ipsec_PROGRAMS)
-am___pluto_adns_SOURCES_DIST = adns.c adns.h
-@USE_ADNS_TRUE@am__pluto_adns_OBJECTS = adns.$(OBJEXT)
-_pluto_adns_OBJECTS = $(am__pluto_adns_OBJECTS)
-am__DEPENDENCIES_1 =
-@USE_ADNS_TRUE@_pluto_adns_DEPENDENCIES = \
-@USE_ADNS_TRUE@ $(LIBFREESWANDIR)/libfreeswan.a \
-@USE_ADNS_TRUE@ $(am__DEPENDENCIES_1)
-am__pluto_SOURCES_DIST = ac.c ac.h alg_info.c alg_info.h ca.c ca.h \
- certs.c certs.h connections.c connections.h constants.c \
- constants.h cookie.c cookie.h crl.c crl.h crypto.c crypto.h \
- db_ops.c db_ops.h defs.c defs.h demux.c demux.h event_queue.c \
- event_queue.h fetch.c fetch.h foodgroups.c foodgroups.h \
- ike_alg.c ike_alg.h ipsec_doi.c ipsec_doi.h kameipsec.h \
- kernel.c kernel.h kernel_alg.c kernel_alg.h kernel_pfkey.c \
- kernel_pfkey.h keys.c keys.h lex.c lex.h log.c log.h myid.c \
- myid.h modecfg.c modecfg.h nat_traversal.c nat_traversal.h \
- ocsp.c ocsp.h packet.c packet.h pkcs7.c pkcs7.h plugin_list.c \
- plugin_list.h pluto.c pluto.h plutomain.c rcv_whack.c \
- rcv_whack.h server.c server.h smartcard.c smartcard.h spdb.c \
- spdb.h state.c state.h timer.c timer.h vendor.c vendor.h \
- virtual.c virtual.h whack_attribute.c whack_attribute.h \
- xauth/xauth_manager.c xauth/xauth_manager.h \
- xauth/xauth_provider.h xauth/xauth_verifier.h x509.c x509.h \
- builder.c builder.h rsaref/pkcs11t.h rsaref/pkcs11.h \
- rsaref/unix.h rsaref/pkcs11f.h dnskey.c dnskey.h
-@USE_ADNS_TRUE@am__objects_1 = dnskey.$(OBJEXT)
-am_pluto_OBJECTS = ac.$(OBJEXT) alg_info.$(OBJEXT) ca.$(OBJEXT) \
- certs.$(OBJEXT) connections.$(OBJEXT) constants.$(OBJEXT) \
- cookie.$(OBJEXT) crl.$(OBJEXT) crypto.$(OBJEXT) \
- db_ops.$(OBJEXT) defs.$(OBJEXT) demux.$(OBJEXT) \
- event_queue.$(OBJEXT) fetch.$(OBJEXT) foodgroups.$(OBJEXT) \
- ike_alg.$(OBJEXT) ipsec_doi.$(OBJEXT) kernel.$(OBJEXT) \
- kernel_alg.$(OBJEXT) kernel_pfkey.$(OBJEXT) keys.$(OBJEXT) \
- lex.$(OBJEXT) log.$(OBJEXT) myid.$(OBJEXT) modecfg.$(OBJEXT) \
- nat_traversal.$(OBJEXT) ocsp.$(OBJEXT) packet.$(OBJEXT) \
- pkcs7.$(OBJEXT) plugin_list.$(OBJEXT) pluto.$(OBJEXT) \
- plutomain.$(OBJEXT) rcv_whack.$(OBJEXT) server.$(OBJEXT) \
- smartcard.$(OBJEXT) spdb.$(OBJEXT) state.$(OBJEXT) \
- timer.$(OBJEXT) vendor.$(OBJEXT) virtual.$(OBJEXT) \
- whack_attribute.$(OBJEXT) xauth_manager.$(OBJEXT) \
- x509.$(OBJEXT) builder.$(OBJEXT) $(am__objects_1)
-pluto_OBJECTS = $(am_pluto_OBJECTS)
-pluto_DEPENDENCIES = $(LIBSTRONGSWANDIR)/libstrongswan.la \
- $(LIBFREESWANDIR)/libfreeswan.a $(LIBHYDRADIR)/libhydra.la \
- $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1)
-DEFAULT_INCLUDES = -I.@am__isrc@
-depcomp = $(SHELL) $(top_srcdir)/depcomp
-am__depfiles_maybe = depfiles
-am__mv = mv -f
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
- --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
- $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-CCLD = $(CC)
-LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
- --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
- $(LDFLAGS) -o $@
-SOURCES = $(_pluto_adns_SOURCES) $(pluto_SOURCES)
-DIST_SOURCES = $(am___pluto_adns_SOURCES_DIST) \
- $(am__pluto_SOURCES_DIST)
-RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
- html-recursive info-recursive install-data-recursive \
- install-dvi-recursive install-exec-recursive \
- install-html-recursive install-info-recursive \
- install-pdf-recursive install-ps-recursive install-recursive \
- installcheck-recursive installdirs-recursive pdf-recursive \
- ps-recursive uninstall-recursive
-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'
-man8dir = $(mandir)/man8
-NROFF = nroff
-MANS = $(dist_man_MANS)
-RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
- distclean-recursive maintainer-clean-recursive
-AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
- $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
- distdir
-ETAGS = etags
-CTAGS = ctags
-DIST_SUBDIRS = . plugins/xauth
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-am__relativize = \
- dir0=`pwd`; \
- sed_first='s,^\([^/]*\)/.*$$,\1,'; \
- sed_rest='s,^[^/]*/*,,'; \
- sed_last='s,^.*/\([^/]*\)$$,\1,'; \
- sed_butlast='s,/*[^/]*$$,,'; \
- while test -n "$$dir1"; do \
- first=`echo "$$dir1" | sed -e "$$sed_first"`; \
- if test "$$first" != "."; then \
- if test "$$first" = ".."; then \
- dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
- dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
- else \
- first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
- if test "$$first2" = "$$first"; then \
- dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
- else \
- dir2="../$$dir2"; \
- fi; \
- dir0="$$dir0"/"$$first"; \
- fi; \
- fi; \
- dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
- done; \
- reldir="$$dir2"
-ACLOCAL = @ACLOCAL@
-ALLOCA = @ALLOCA@
-AMTAR = @AMTAR@
-AR = @AR@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-BTLIB = @BTLIB@
-CC = @CC@
-CCDEPMODE = @CCDEPMODE@
-CFLAGS = @CFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CYGPATH_W = @CYGPATH_W@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DLLIB = @DLLIB@
-DSYMUTIL = @DSYMUTIL@
-DUMPBIN = @DUMPBIN@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-EXEEXT = @EXEEXT@
-FGREP = @FGREP@
-GPERF = @GPERF@
-GREP = @GREP@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-LD = @LD@
-LDFLAGS = @LDFLAGS@
-LEX = @LEX@
-LEXLIB = @LEXLIB@
-LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LIBTOOL = @LIBTOOL@
-LIPO = @LIPO@
-LN_S = @LN_S@
-LTLIBOBJS = @LTLIBOBJS@
-MAKEINFO = @MAKEINFO@
-MKDIR_P = @MKDIR_P@
-MYSQLCFLAG = @MYSQLCFLAG@
-MYSQLCONFIG = @MYSQLCONFIG@
-MYSQLLIB = @MYSQLLIB@
-NM = @NM@
-NMEDIT = @NMEDIT@
-OBJDUMP = @OBJDUMP@
-OBJEXT = @OBJEXT@
-OTOOL = @OTOOL@
-OTOOL64 = @OTOOL64@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_URL = @PACKAGE_URL@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-PERL = @PERL@
-PKG_CONFIG = @PKG_CONFIG@
-PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
-PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
-PTHREADLIB = @PTHREADLIB@
-RANLIB = @RANLIB@
-RTLIB = @RTLIB@
-RUBY = @RUBY@
-RUBYINCLUDE = @RUBYINCLUDE@
-SED = @SED@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-SOCKLIB = @SOCKLIB@
-STRIP = @STRIP@
-VERSION = @VERSION@
-YACC = @YACC@
-YFLAGS = @YFLAGS@
-abs_builddir = @abs_builddir@
-abs_srcdir = @abs_srcdir@
-abs_top_builddir = @abs_top_builddir@
-abs_top_srcdir = @abs_top_srcdir@
-ac_ct_CC = @ac_ct_CC@
-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-attest_plugins = @attest_plugins@
-axis2c_CFLAGS = @axis2c_CFLAGS@
-axis2c_LIBS = @axis2c_LIBS@
-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@
-clearsilver_LIBS = @clearsilver_LIBS@
-datadir = @datadir@
-datarootdir = @datarootdir@
-dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
-docdir = @docdir@
-dvidir = @dvidir@
-exec_prefix = @exec_prefix@
-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@
-ipsecdir = @ipsecdir@
-ipsecgroup = @ipsecgroup@
-ipseclibdir = @ipseclibdir@
-ipsecuser = @ipsecuser@
-libcharon_plugins = @libcharon_plugins@
-libdir = @libdir@
-libexecdir = @libexecdir@
-linux_headers = @linux_headers@
-localedir = @localedir@
-localstatedir = @localstatedir@
-lt_ECHO = @lt_ECHO@
-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@
-oldincludedir = @oldincludedir@
-openac_plugins = @openac_plugins@
-p_plugins = @p_plugins@
-pcsclite_CFLAGS = @pcsclite_CFLAGS@
-pcsclite_LIBS = @pcsclite_LIBS@
-pdfdir = @pdfdir@
-piddir = @piddir@
-pki_plugins = @pki_plugins@
-plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
-pool_plugins = @pool_plugins@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-random_device = @random_device@
-resolv_conf = @resolv_conf@
-routing_table = @routing_table@
-routing_table_prio = @routing_table_prio@
-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@
-sysconfdir = @sysconfdir@
-systemdsystemunitdir = @systemdsystemunitdir@
-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@
-pluto_SOURCES = ac.c ac.h alg_info.c alg_info.h ca.c ca.h certs.c \
- certs.h connections.c connections.h constants.c constants.h \
- cookie.c cookie.h crl.c crl.h crypto.c crypto.h db_ops.c \
- db_ops.h defs.c defs.h demux.c demux.h event_queue.c \
- event_queue.h fetch.c fetch.h foodgroups.c foodgroups.h \
- ike_alg.c ike_alg.h ipsec_doi.c ipsec_doi.h kameipsec.h \
- kernel.c kernel.h kernel_alg.c kernel_alg.h kernel_pfkey.c \
- kernel_pfkey.h keys.c keys.h lex.c lex.h log.c log.h myid.c \
- myid.h modecfg.c modecfg.h nat_traversal.c nat_traversal.h \
- ocsp.c ocsp.h packet.c packet.h pkcs7.c pkcs7.h plugin_list.c \
- plugin_list.h pluto.c pluto.h plutomain.c rcv_whack.c \
- rcv_whack.h server.c server.h smartcard.c smartcard.h spdb.c \
- spdb.h state.c state.h timer.c timer.h vendor.c vendor.h \
- virtual.c virtual.h whack_attribute.c whack_attribute.h \
- xauth/xauth_manager.c xauth/xauth_manager.h \
- xauth/xauth_provider.h xauth/xauth_verifier.h x509.c x509.h \
- builder.c builder.h rsaref/pkcs11t.h rsaref/pkcs11.h \
- rsaref/unix.h rsaref/pkcs11f.h $(am__append_2)
-@USE_ADNS_TRUE@_pluto_adns_SOURCES = \
-@USE_ADNS_TRUE@adns.c adns.h
-
-LIBSTRONGSWANDIR = $(top_builddir)/src/libstrongswan
-LIBFREESWANDIR = $(top_builddir)/src/libfreeswan
-LIBHYDRADIR = $(top_builddir)/src/libhydra
-INCLUDES = \
--I${linux_headers} \
--I$(top_srcdir)/src/libstrongswan \
--I$(top_srcdir)/src/libfreeswan \
--I$(top_srcdir)/src/libhydra \
--I$(top_srcdir)/src/whack
-
-AM_CFLAGS = -rdynamic -DIPSEC_DIR=\"${ipsecdir}\" \
- -DIPSEC_CONFDIR=\"${sysconfdir}\" -DIPSEC_PIDDIR=\"${piddir}\" \
- -DSHARED_SECRETS_FILE=\"${sysconfdir}/ipsec.secrets\" \
- -DPLUGINS=\""${pluto_plugins}\"" \
- -DPKCS11_DEFAULT_LIB=\"${default_pkcs11}\" \
- -DKERNEL26_HAS_KAME_DUPLICATES -DPLUTO -DDEBUG $(am__append_3) \
- $(am__append_4) $(am__append_5) $(am__append_6) \
- $(am__append_7) $(am__append_9) $(am__append_10)
-pluto_LDADD = $(LIBSTRONGSWANDIR)/libstrongswan.la \
- $(LIBFREESWANDIR)/libfreeswan.a $(LIBHYDRADIR)/libhydra.la \
- -lresolv $(PTHREADLIB) $(DLLIB) $(am__append_8)
-@USE_ADNS_TRUE@_pluto_adns_LDADD = \
-@USE_ADNS_TRUE@$(LIBFREESWANDIR)/libfreeswan.a \
-@USE_ADNS_TRUE@-lresolv $(DLLIB)
-
-dist_man_MANS = pluto.8
-EXTRA_DIST = Android.mk
-
-# build optional plugins
-########################
-SUBDIRS = . $(am__append_11)
-all: all-recursive
-
-.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/pluto/Makefile'; \
- $(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --gnu src/pluto/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-ipsecPROGRAMS: $(ipsec_PROGRAMS)
- @$(NORMAL_INSTALL)
- test -z "$(ipsecdir)" || $(MKDIR_P) "$(DESTDIR)$(ipsecdir)"
- @list='$(ipsec_PROGRAMS)'; test -n "$(ipsecdir)" || list=; \
- for p in $$list; do echo "$$p $$p"; done | \
- sed 's/$(EXEEXT)$$//' | \
- while read p p1; do if test -f $$p || test -f $$p1; \
- then echo "$$p"; echo "$$p"; else :; fi; \
- done | \
- sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
- -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
- sed 'N;N;N;s,\n, ,g' | \
- $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
- { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
- if ($$2 == $$4) files[d] = files[d] " " $$1; \
- else { print "f", $$3 "/" $$4, $$1; } } \
- END { for (d in files) print "f", d, files[d] }' | \
- while read type dir files; do \
- if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
- test -z "$$files" || { \
- echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(ipsecdir)$$dir'"; \
- $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(ipsecdir)$$dir" || exit $$?; \
- } \
- ; done
-
-uninstall-ipsecPROGRAMS:
- @$(NORMAL_UNINSTALL)
- @list='$(ipsec_PROGRAMS)'; test -n "$(ipsecdir)" || list=; \
- files=`for p in $$list; do echo "$$p"; done | \
- sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
- -e 's/$$/$(EXEEXT)/' `; \
- test -n "$$list" || exit 0; \
- echo " ( cd '$(DESTDIR)$(ipsecdir)' && rm -f" $$files ")"; \
- cd "$(DESTDIR)$(ipsecdir)" && rm -f $$files
-
-clean-ipsecPROGRAMS:
- @list='$(ipsec_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
-_pluto_adns$(EXEEXT): $(_pluto_adns_OBJECTS) $(_pluto_adns_DEPENDENCIES)
- @rm -f _pluto_adns$(EXEEXT)
- $(LINK) $(_pluto_adns_OBJECTS) $(_pluto_adns_LDADD) $(LIBS)
-pluto$(EXEEXT): $(pluto_OBJECTS) $(pluto_DEPENDENCIES)
- @rm -f pluto$(EXEEXT)
- $(LINK) $(pluto_OBJECTS) $(pluto_LDADD) $(LIBS)
-
-mostlyclean-compile:
- -rm -f *.$(OBJEXT)
-
-distclean-compile:
- -rm -f *.tab.c
-
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ac.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/adns.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alg_info.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/builder.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ca.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/certs.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connections.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/constants.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cookie.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crl.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypto.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/db_ops.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/defs.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demux.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnskey.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/event_queue.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fetch.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/foodgroups.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_alg.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipsec_doi.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel_alg.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel_pfkey.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keys.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lex.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/modecfg.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/myid.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nat_traversal.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ocsp.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/packet.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pkcs7.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_list.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pluto.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plutomain.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rcv_whack.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/smartcard.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spdb.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/state.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timer.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vendor.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/virtual.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/whack_attribute.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/x509.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xauth_manager.Po@am__quote@
-
-.c.o:
-@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c $<
-
-.c.obj:
-@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
-
-.c.lo:
-@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
-
-xauth_manager.o: xauth/xauth_manager.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xauth_manager.o -MD -MP -MF $(DEPDIR)/xauth_manager.Tpo -c -o xauth_manager.o `test -f 'xauth/xauth_manager.c' || echo '$(srcdir)/'`xauth/xauth_manager.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/xauth_manager.Tpo $(DEPDIR)/xauth_manager.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='xauth/xauth_manager.c' object='xauth_manager.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xauth_manager.o `test -f 'xauth/xauth_manager.c' || echo '$(srcdir)/'`xauth/xauth_manager.c
-
-xauth_manager.obj: xauth/xauth_manager.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xauth_manager.obj -MD -MP -MF $(DEPDIR)/xauth_manager.Tpo -c -o xauth_manager.obj `if test -f 'xauth/xauth_manager.c'; then $(CYGPATH_W) 'xauth/xauth_manager.c'; else $(CYGPATH_W) '$(srcdir)/xauth/xauth_manager.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/xauth_manager.Tpo $(DEPDIR)/xauth_manager.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='xauth/xauth_manager.c' object='xauth_manager.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xauth_manager.obj `if test -f 'xauth/xauth_manager.c'; then $(CYGPATH_W) 'xauth/xauth_manager.c'; else $(CYGPATH_W) '$(srcdir)/xauth/xauth_manager.c'; fi`
-
-mostlyclean-libtool:
- -rm -f *.lo
-
-clean-libtool:
- -rm -rf .libs _libs
-install-man8: $(dist_man_MANS)
- @$(NORMAL_INSTALL)
- test -z "$(man8dir)" || $(MKDIR_P) "$(DESTDIR)$(man8dir)"
- @list=''; test -n "$(man8dir)" || exit 0; \
- { for i in $$list; do echo "$$i"; done; \
- l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \
- sed -n '/\.8[a-z]*$$/p'; \
- } | while read p; do \
- if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
- echo "$$d$$p"; echo "$$p"; \
- done | \
- sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
- -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
- sed 'N;N;s,\n, ,g' | { \
- list=; while read file base inst; do \
- if test "$$base" = "$$inst"; then list="$$list $$file"; else \
- echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
- $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \
- fi; \
- done; \
- for i in $$list; do echo "$$i"; done | $(am__base_list) | \
- while read files; do \
- test -z "$$files" || { \
- echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \
- $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \
- done; }
-
-uninstall-man8:
- @$(NORMAL_UNINSTALL)
- @list=''; test -n "$(man8dir)" || exit 0; \
- files=`{ for i in $$list; do echo "$$i"; done; \
- l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \
- sed -n '/\.8[a-z]*$$/p'; \
- } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
- -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
- test -z "$$files" || { \
- echo " ( cd '$(DESTDIR)$(man8dir)' && rm -f" $$files ")"; \
- cd "$(DESTDIR)$(man8dir)" && rm -f $$files; }
-
-# This directory's subdirectories are mostly independent; you can cd
-# into them and run `make' without going through this Makefile.
-# To change the values of `make' variables: instead of editing Makefiles,
-# (1) if the variable is set in `config.status', edit `config.status'
-# (which will cause the Makefiles to be regenerated when you run `make');
-# (2) otherwise, pass the desired values on the `make' command line.
-$(RECURSIVE_TARGETS):
- @fail= failcom='exit 1'; \
- for f in x $$MAKEFLAGS; do \
- case $$f in \
- *=* | --[!k]*);; \
- *k*) failcom='fail=yes';; \
- esac; \
- done; \
- dot_seen=no; \
- target=`echo $@ | sed s/-recursive//`; \
- list='$(SUBDIRS)'; for subdir in $$list; do \
- echo "Making $$target in $$subdir"; \
- if test "$$subdir" = "."; then \
- dot_seen=yes; \
- local_target="$$target-am"; \
- else \
- local_target="$$target"; \
- fi; \
- ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
- || eval $$failcom; \
- done; \
- if test "$$dot_seen" = "no"; then \
- $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
- fi; test -z "$$fail"
-
-$(RECURSIVE_CLEAN_TARGETS):
- @fail= failcom='exit 1'; \
- for f in x $$MAKEFLAGS; do \
- case $$f in \
- *=* | --[!k]*);; \
- *k*) failcom='fail=yes';; \
- esac; \
- done; \
- dot_seen=no; \
- case "$@" in \
- distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
- *) list='$(SUBDIRS)' ;; \
- esac; \
- rev=''; for subdir in $$list; do \
- if test "$$subdir" = "."; then :; else \
- rev="$$subdir $$rev"; \
- fi; \
- done; \
- rev="$$rev ."; \
- target=`echo $@ | sed s/-recursive//`; \
- for subdir in $$rev; do \
- echo "Making $$target in $$subdir"; \
- if test "$$subdir" = "."; then \
- local_target="$$target-am"; \
- else \
- local_target="$$target"; \
- fi; \
- ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
- || eval $$failcom; \
- done && test -z "$$fail"
-tags-recursive:
- list='$(SUBDIRS)'; for subdir in $$list; do \
- test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
- done
-ctags-recursive:
- list='$(SUBDIRS)'; for subdir in $$list; do \
- test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
- done
-
-ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
- END { if (nonempty) { for (i in files) print i; }; }'`; \
- mkid -fID $$unique
-tags: TAGS
-
-TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
- $(TAGS_FILES) $(LISP)
- set x; \
- here=`pwd`; \
- if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
- include_option=--etags-include; \
- empty_fix=.; \
- else \
- include_option=--include; \
- empty_fix=; \
- fi; \
- list='$(SUBDIRS)'; for subdir in $$list; do \
- if test "$$subdir" = .; then :; else \
- test ! -f $$subdir/TAGS || \
- set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
- fi; \
- done; \
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
- END { if (nonempty) { for (i in files) print i; }; }'`; \
- shift; \
- if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
- test -n "$$unique" || unique=$$empty_fix; \
- if test $$# -gt 0; then \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- "$$@" $$unique; \
- else \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- $$unique; \
- fi; \
- fi
-ctags: CTAGS
-CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
- $(TAGS_FILES) $(LISP)
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
- END { if (nonempty) { for (i in files) print i; }; }'`; \
- test -z "$(CTAGS_ARGS)$$unique" \
- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
- $$unique
-
-GTAGS:
- here=`$(am__cd) $(top_builddir) && pwd` \
- && $(am__cd) $(top_srcdir) \
- && gtags -i $(GTAGS_ARGS) "$$here"
-
-distclean-tags:
- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-
-distdir: $(DISTFILES)
- @list='$(MANS)'; if test -n "$$list"; then \
- list=`for p in $$list; do \
- if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
- if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \
- if test -n "$$list" && \
- grep 'ab help2man is required to generate this page' $$list >/dev/null; then \
- echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \
- grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \
- echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \
- echo " typically \`make maintainer-clean' will remove them" >&2; \
- exit 1; \
- else :; fi; \
- else :; fi
- @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
- @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
- if test "$$subdir" = .; then :; else \
- test -d "$(distdir)/$$subdir" \
- || $(MKDIR_P) "$(distdir)/$$subdir" \
- || exit 1; \
- fi; \
- done
- @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
- if test "$$subdir" = .; then :; else \
- dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
- $(am__relativize); \
- new_distdir=$$reldir; \
- dir1=$$subdir; dir2="$(top_distdir)"; \
- $(am__relativize); \
- new_top_distdir=$$reldir; \
- echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
- echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
- ($(am__cd) $$subdir && \
- $(MAKE) $(AM_MAKEFLAGS) \
- top_distdir="$$new_top_distdir" \
- distdir="$$new_distdir" \
- am__remove_distdir=: \
- am__skip_length_check=: \
- am__skip_mode_fix=: \
- distdir) \
- || exit 1; \
- fi; \
- done
-check-am: all-am
-check: check-recursive
-all-am: Makefile $(PROGRAMS) $(MANS)
-installdirs: installdirs-recursive
-installdirs-am:
- for dir in "$(DESTDIR)$(ipsecdir)" "$(DESTDIR)$(man8dir)"; do \
- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
- done
-install: install-recursive
-install-exec: install-exec-recursive
-install-data: install-data-recursive
-uninstall: uninstall-recursive
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-recursive
-install-strip:
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- `test -z '$(STRIP)' || \
- echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-
-maintainer-clean-generic:
- @echo "This command is intended for maintainers to use"
- @echo "it deletes files that may require special tools to rebuild."
-clean: clean-recursive
-
-clean-am: clean-generic clean-ipsecPROGRAMS clean-libtool \
- mostlyclean-am
-
-distclean: distclean-recursive
- -rm -rf ./$(DEPDIR)
- -rm -f Makefile
-distclean-am: clean-am distclean-compile distclean-generic \
- distclean-tags
-
-dvi: dvi-recursive
-
-dvi-am:
-
-html: html-recursive
-
-html-am:
-
-info: info-recursive
-
-info-am:
-
-install-data-am: install-ipsecPROGRAMS install-man
-
-install-dvi: install-dvi-recursive
-
-install-dvi-am:
-
-install-exec-am:
-
-install-html: install-html-recursive
-
-install-html-am:
-
-install-info: install-info-recursive
-
-install-info-am:
-
-install-man: install-man8
-
-install-pdf: install-pdf-recursive
-
-install-pdf-am:
-
-install-ps: install-ps-recursive
-
-install-ps-am:
-
-installcheck-am:
-
-maintainer-clean: maintainer-clean-recursive
- -rm -rf ./$(DEPDIR)
- -rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-recursive
-
-mostlyclean-am: mostlyclean-compile mostlyclean-generic \
- mostlyclean-libtool
-
-pdf: pdf-recursive
-
-pdf-am:
-
-ps: ps-recursive
-
-ps-am:
-
-uninstall-am: uninstall-ipsecPROGRAMS uninstall-man
-
-uninstall-man: uninstall-man8
-
-.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
- install-am install-strip tags-recursive
-
-.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
- all all-am check check-am clean clean-generic \
- clean-ipsecPROGRAMS clean-libtool ctags ctags-recursive \
- 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-ipsecPROGRAMS install-man install-man8 \
- install-pdf install-pdf-am install-ps install-ps-am \
- install-strip installcheck installcheck-am installdirs \
- installdirs-am maintainer-clean maintainer-clean-generic \
- mostlyclean mostlyclean-compile mostlyclean-generic \
- mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \
- uninstall uninstall-am uninstall-ipsecPROGRAMS uninstall-man \
- uninstall-man8
-
-
-plutomain.o : $(top_builddir)/config.status
-
-# 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/pluto/ac.c b/src/pluto/ac.c
deleted file mode 100644
index cd8007aea..000000000
--- a/src/pluto/ac.c
+++ /dev/null
@@ -1,298 +0,0 @@
-/* Support of X.509 attribute certificates
- * Copyright (C) 2002 Ueli Galizzi, Ariane Seiler
- * Copyright (C) 2003 Martin Berner, Lukas Suter
- * Copyright (C) 2009 Andreas Steffen
- *
- * 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 <sys/stat.h>
-#include <time.h>
-
-#include <debug.h>
-#include <utils/enumerator.h>
-#include <utils/linked_list.h>
-#include <credentials/certificates/ac.h>
-
-#include "ac.h"
-#include "ca.h"
-#include "certs.h"
-#include "fetch.h"
-#include "log.h"
-
-/**
- * Chained list of X.509 attribute certificates
- */
-static linked_list_t *acerts = NULL;
-
-/**
- * Initialize the linked list of attribute certificates
- */
-void ac_initialize(void)
-{
- acerts = linked_list_create();
-}
-
-/**
- * Free the linked list of attribute certificates
- */
-void ac_finalize(void)
-{
- if (acerts)
- {
- acerts->destroy_offset(acerts, offsetof(certificate_t, destroy));
- }
-}
-
-/**
- * Get a X.509 attribute certificate for a given holder
- */
-certificate_t* ac_get_cert(identification_t *issuer, chunk_t serial)
-{
- enumerator_t *enumerator;
- certificate_t *cert, *found = NULL;
-
- enumerator = acerts->create_enumerator(acerts);
- while (enumerator->enumerate(enumerator, &cert))
- {
- ac_t *ac = (ac_t*)cert;
-
- if (issuer->equals(issuer, ac->get_holderIssuer(ac)) &&
- chunk_equals(serial, ac->get_holderSerial(ac)))
- {
- found = cert;
- break;
- }
- }
- enumerator->destroy(enumerator);
- return found;
-}
-
-/**
- * Verifies a X.509 attribute certificate
- */
-bool ac_verify_cert(certificate_t *cert, bool strict)
-{
- ac_t *ac = (ac_t*)cert;
- identification_t *subject = cert->get_subject(cert);
- identification_t *issuer = cert->get_issuer(cert);
- chunk_t authKeyID = ac->get_authKeyIdentifier(ac);
- cert_t *aacert;
- time_t notBefore, valid_until;
-
- DBG1(DBG_LIB, "holder: '%Y'", subject);
- DBG1(DBG_LIB, "issuer: '%Y'", issuer);
-
- if (!cert->get_validity(cert, NULL, NULL, &valid_until))
- {
- DBG1(DBG_LIB, "attribute certificate is invalid (valid from %T to %T)",
- &notBefore, FALSE, &valid_until, FALSE);
- return FALSE;
- }
- DBG1(DBG_LIB, "attribute certificate is valid until %T", &valid_until,
- FALSE);
-
- lock_authcert_list("verify_x509acert");
- aacert = get_authcert(issuer, authKeyID, X509_AA);
- unlock_authcert_list("verify_x509acert");
-
- if (aacert == NULL)
- {
- DBG1(DBG_LIB, "issuer aacert not found");
- return FALSE;
- }
- DBG2(DBG_LIB, "issuer aacert found");
-
- if (!cert->issued_by(cert, aacert->cert))
- {
- DBG1(DBG_LIB, "attribute certificate signature is invalid");
- return FALSE;
- }
- DBG1(DBG_LIB, "attribute certificate signature is valid");
-
- return verify_x509cert(aacert, strict, &valid_until);
-}
-
-/**
- * Add a X.509 attribute certificate to the chained list
- */
-static void ac_add_cert(certificate_t *cert)
-{
- ac_t *ac = (ac_t*)cert;
- identification_t *hIssuer = ac->get_holderIssuer(ac);
- chunk_t hSerial = ac->get_holderSerial(ac);
-
- enumerator_t *enumerator;
- certificate_t *cert_old;
-
- enumerator = acerts->create_enumerator(acerts);
- while (enumerator->enumerate(enumerator, &cert_old))
- {
- ac_t *ac_old = (ac_t*)cert_old;
-
- if (hIssuer->equals(hIssuer, ac_old->get_holderIssuer(ac_old)) &&
- chunk_equals(hSerial, ac_old->get_holderSerial(ac_old)))
- {
- if (certificate_is_newer(cert, cert_old))
- {
- acerts->remove_at(acerts, enumerator);
- cert_old->destroy(cert_old);
- }
- else
- {
- cert->destroy(cert);
- cert = NULL;
- }
- break;
- }
- }
- enumerator->destroy(enumerator);
-
- if (cert)
- {
- acerts->insert_last(acerts, cert);
- }
-}
-
-/**
- * Check if at least one peer attribute matches a connection attribute
- */
-bool match_group_membership(ietf_attributes_t *peer_attributes, char *conn,
- ietf_attributes_t *conn_attributes)
-{
- bool match;
-
- if (conn_attributes == NULL)
- {
- return TRUE;
- }
-
- match = conn_attributes->matches(conn_attributes, peer_attributes);
- DBG1(DBG_LIB, "%s: peer with attributes '%s' is %sa member of the "
- "groups '%s'", conn, peer_attributes->get_string(peer_attributes),
- match ? "" : "not ", conn_attributes->get_string(conn_attributes));
-
- return match;
-}
-
-/**
- * Loads X.509 attribute certificates
- */
-void ac_load_certs(void)
-{
- enumerator_t *enumerator;
- struct stat st;
- char *file;
-
- DBG1(DBG_LIB, "loading attribute certificates from '%s'", A_CERT_PATH);
-
- enumerator = enumerator_create_directory(A_CERT_PATH);
- if (!enumerator)
- {
- return;
- }
-
- while (enumerator->enumerate(enumerator, NULL, &file, &st))
- {
- certificate_t *cert;
-
- if (!S_ISREG(st.st_mode))
- {
- /* skip special file */
- continue;
- }
- cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_AC,
- BUILD_FROM_FILE, file, BUILD_END);
- if (cert)
- {
- DBG1(DBG_LIB, " loaded attribute certificate from '%s'", file);
- ac_add_cert(cert);
- }
- }
- enumerator->destroy(enumerator);
-}
-
-/**
- * List all X.509 attribute certificates in the chained list
- */
-void ac_list_certs(bool utc)
-{
- enumerator_t *enumerator;
- certificate_t *cert;
- time_t now;
-
- /* determine the current time */
- time(&now);
-
- if (acerts->get_count(acerts) > 0)
- {
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, "List of X.509 Attribute Certificates:");
- }
-
- enumerator = acerts->create_enumerator(acerts);
- while (enumerator->enumerate(enumerator, &cert))
- {
- ac_t *ac = (ac_t*)cert;
- identification_t *entityName, *holderIssuer, *issuer;
- chunk_t holderSerial, serial, authKeyID;
- time_t notBefore, notAfter;
- ietf_attributes_t *groups;
-
- whack_log(RC_COMMENT, " ");
-
- entityName = cert->get_subject(cert);
- if (entityName)
- {
- whack_log(RC_COMMENT, " holder: \"%Y\"", entityName);
- }
-
- holderIssuer = ac->get_holderIssuer(ac);
- if (holderIssuer)
- {
- whack_log(RC_COMMENT, " hissuer: \"%Y\"", holderIssuer);
- }
-
- holderSerial = chunk_skip_zero(ac->get_holderSerial(ac));
- if (holderSerial.ptr)
- {
- whack_log(RC_COMMENT, " hserial: %#B", &holderSerial);
- }
-
- groups = ac->get_groups(ac);
- if (groups)
- {
- whack_log(RC_COMMENT, " groups: %s", groups->get_string(groups));
- groups->destroy(groups);
- }
-
- issuer = cert->get_issuer(cert);
- whack_log(RC_COMMENT, " issuer: \"%Y\"", issuer);
-
- serial = chunk_skip_zero(ac->get_serial(ac));
- whack_log(RC_COMMENT, " serial: %#B", &serial);
-
- cert->get_validity(cert, &now, &notBefore, &notAfter);
- whack_log(RC_COMMENT, " validity: not before %T %s",
- &notBefore, utc,
- (notBefore < now)?"ok":"fatal (not valid yet)");
- whack_log(RC_COMMENT, " not after %T %s", &notAfter, utc,
- check_expiry(notAfter, ACERT_WARNING_INTERVAL, TRUE));
-
- authKeyID = ac->get_authKeyIdentifier(ac);
- if (authKeyID.ptr)
- {
- whack_log(RC_COMMENT, " authkey: %#B", &authKeyID);
- }
- }
- enumerator->destroy(enumerator);
-}
-
diff --git a/src/pluto/ac.h b/src/pluto/ac.h
deleted file mode 100644
index d4e0c1590..000000000
--- a/src/pluto/ac.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* Support of X.509 attribute certificates
- * Copyright (C) 2002 Ueli Galizzi, Ariane Seiler
- * Copyright (C) 2003 Martin Berner, Lukas Suter
- * Copyright (C) 2009 Andreas Steffen
- *
- * 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.
- */
-
-#ifndef _AC_H
-#define _AC_H
-
-#include <utils/identification.h>
-#include <credentials/certificates/certificate.h>
-#include <credentials/ietf_attributes/ietf_attributes.h>
-
-/* access structure for an X.509 attribute certificate */
-
-extern void ac_initialize(void);
-extern void ac_finalize(void);
-extern void ac_load_certs(void);
-extern void ac_list_certs(bool utc);
-
-extern certificate_t* ac_get_cert(identification_t *issuer, chunk_t serial);
-
-extern bool ac_verify_cert(certificate_t *ac, bool strict);
-
-extern bool match_group_membership(ietf_attributes_t *peer_attributes,
- char *conn,
- ietf_attributes_t *conn_attributes);
-
-#endif /* _AC_H */
diff --git a/src/pluto/adns.c b/src/pluto/adns.c
deleted file mode 100644
index 76b459216..000000000
--- a/src/pluto/adns.c
+++ /dev/null
@@ -1,610 +0,0 @@
-/* Pluto Asynchronous DNS Helper Program -- for internal use only!
- * Copyright (C) 2002 D. Hugh Redelmeier.
- *
- * 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.
- */
-
-/* This program executes as multiple processes. The Master process
- * receives queries (struct adns_query messages) from Pluto and distributes
- * them amongst Worker processes. These Worker processes are created
- * by the Master whenever a query arrives and no existing Worker is free.
- * At most MAX_WORKERS will be created; after that, the Master will queue
- * queries until a Worker becomes free. When a Worker has an answer from
- * the resolver, it sends the answer as a struct adns_answer message to the
- * Master. The Master then forwards the answer to Pluto, noting that
- * the Worker is free to accept another query.
- *
- * The protocol is simple: Pluto sends a sequence of queries and receives
- * a sequence of answers. select(2) is used by Pluto and by the Master
- * process to decide when to read, but writes are done without checking
- * for readiness. Communications is via pipes. Since only one process
- * can write to each pipe, messages will not be interleaved. Fixed length
- * records are used for simplicity.
- *
- * Pluto needs a way to indicate to the Master when to shut down
- * and the Master needs to indicate this to each worker. EOF on the pipe
- * signifies this.
- *
- * The interfaces between these components are considered private to
- * Pluto. This allows us to get away with less checking. This is a
- * reason to use pipes instead of TCP/IP.
- *
- * Although the code uses plain old UNIX processes, it could be modified
- * to use threads. That might reduce resource requirements. It would
- * preclude running on systems without thread-safe resolvers.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <syslog.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <netinet/in.h>
-#include <arpa/nameser.h>
-#include <resolv.h>
-#include <netdb.h> /* ??? for h_errno */
-
-#include <freeswan.h>
-
-/* GCC magic! */
-#ifdef GCC_LINT
-# define UNUSED __attribute__ ((unused))
-#else
-# define UNUSED /* ignore */
-#endif
-
-#include "constants.h"
-#include "adns.h" /* needs <resolv.h> */
-
-/* shared by all processes */
-
-static const char *name; /* program name, for messages */
-
-static bool debug = FALSE;
-
-/* Read a variable-length record from a pipe (and no more!).
- * First bytes must be a size_t containing the length.
- * HES_CONTINUE if record read
- * HES_OK if EOF
- * HES_IO_ERROR_IN if errno tells the tale.
- * Others are errors.
- */
-static enum helper_exit_status
-read_pipe(int fd, unsigned char *stuff, size_t minlen, size_t maxlen)
-{
- size_t n = 0;
- size_t goal = minlen;
-
- do {
- ssize_t m = read(fd, stuff + n, goal - n);
-
- if (m == -1)
- {
- if (errno != EINTR)
- {
- syslog(LOG_ERR, "Input error on pipe: %s", strerror(errno));
- return HES_IO_ERROR_IN;
- }
- }
- else if (m == 0)
- {
- return HES_OK; /* treat empty message as EOF */
- }
- else
- {
- n += m;
- if (n >= sizeof(size_t))
- {
- goal = *(size_t *)(void *)stuff;
- if (goal < minlen || maxlen < goal)
- {
- if (debug)
- fprintf(stderr, "%lu : [%lu, %lu]\n"
- , (unsigned long)goal
- , (unsigned long)minlen, (unsigned long)maxlen);
- return HES_BAD_LEN;
- }
- }
- }
- } while (n < goal);
-
- return HES_CONTINUE;
-}
-
-/* Write a variable-length record to a pipe.
- * First bytes must be a size_t containing the length.
- * HES_CONTINUE if record written
- * Others are errors.
- */
-static enum helper_exit_status
-write_pipe(int fd, const unsigned char *stuff)
-{
- size_t len = *(const size_t *)(const void *)stuff;
- size_t n = 0;
-
- do {
- ssize_t m = write(fd, stuff + n, len - n);
-
- if (m == -1)
- {
- /* error, but ignore and retry if EINTR */
- if (errno != EINTR)
- {
- syslog(LOG_ERR, "Output error from master: %s", strerror(errno));
- return HES_IO_ERROR_OUT;
- }
- }
- else
- {
- n += m;
- }
- } while (n != len);
- return HES_CONTINUE;
-}
-
-/**************** worker process ****************/
-
-/* The interface in RHL6.x and BIND distribution 8.2.2 are different,
- * so we build some of our own :-(
- */
-
-/* Support deprecated interface to allow for older releases of the resolver.
- * Fake new interface!
- * See resolver(3) bind distribution (should be in RHL6.1, but isn't).
- * __RES was 19960801 in RHL6.2, an old resolver.
- */
-
-#if (__RES) <= 19960801
-# define OLD_RESOLVER 1
-#endif
-
-#ifdef OLD_RESOLVER
-
-# define res_ninit(statp) res_init()
-# define res_nquery(statp, dname, class, type, answer, anslen) \
- res_query(dname, class, type, answer, anslen)
-# define res_nclose(statp) res_close()
-
-static struct __res_state *statp = &_res;
-
-#else /* !OLD_RESOLVER */
-
-static struct __res_state my_res_state /* = { 0 } */;
-static res_state statp = &my_res_state;
-
-#endif /* !OLD_RESOLVER */
-
-static int
-worker(int qfd, int afd)
-{
- {
- int r = res_ninit(statp);
-
- if (r != 0)
- {
- syslog(LOG_ERR, "cannot initialize resolver");
- return HES_RES_INIT;
- }
-#ifndef OLD_RESOLVER
- statp->options |= RES_ROTATE;
-#endif
- statp->options |= RES_DEBUG;
- }
-
- for (;;)
- {
- struct adns_query q;
- struct adns_answer a;
-
- enum helper_exit_status r = read_pipe(qfd, (unsigned char *)&q
- , sizeof(q), sizeof(q));
-
- if (r != HES_CONTINUE)
- return r; /* some kind of exit */
-
- if (q.qmagic != ADNS_Q_MAGIC)
- {
- syslog(LOG_ERR, "error in input from master: bad magic");
- return HES_BAD_MAGIC;
- }
-
- a.amagic = ADNS_A_MAGIC;
- a.serial = q.serial;
- a.continuation = NULL;
-
- a.result = res_nquery(statp, q.name_buf, C_IN, q.type, a.ans, sizeof(a.ans));
- a.h_errno_val = h_errno;
-
- a.len = offsetof(struct adns_answer, ans) + (a.result < 0? 0 : a.result);
-
-#ifdef DEBUG
- if (((q.debugging & IMPAIR_DELAY_ADNS_KEY_ANSWER) && q.type == T_KEY)
- || ((q.debugging & IMPAIR_DELAY_ADNS_TXT_ANSWER) && q.type == T_TXT))
- sleep(30); /* delay the answer */
-#endif
-
- /* write answer, possibly a bit at a time */
- r = write_pipe(afd, (const unsigned char *)&a);
-
- if (r != HES_CONTINUE)
- return r; /* some kind of exit */
- }
-}
-
-/**************** master process ****************/
-
-bool eof_from_pluto = FALSE;
-#define PLUTO_QFD 0 /* queries come on stdin */
-#define PLUTO_AFD 1 /* answers go out on stdout */
-
-#ifndef MAX_WORKERS
-# define MAX_WORKERS 10 /* number of in-flight queries */
-#endif
-
-struct worker_info {
- int qfd; /* query pipe's file descriptor */
- int afd; /* answer pipe's file descriptor */
- pid_t pid;
- bool busy;
- void *continuation; /* of outstanding request */
-};
-
-static struct worker_info wi[MAX_WORKERS];
-static struct worker_info *wi_roof = wi;
-
-/* request FIFO */
-
-struct query_list {
- struct query_list *next;
- struct adns_query aq;
-};
-
-static struct query_list *oldest_query = NULL;
-static struct query_list *newest_query; /* undefined when oldest == NULL */
-static struct query_list *free_queries = NULL;
-
-static bool
-spawn_worker(void)
-{
- int qfds[2];
- int afds[2];
- pid_t p;
-
- if (pipe(qfds) != 0 || pipe(afds) != 0)
- {
- syslog(LOG_ERR, "pipe(2) failed: %s", strerror(errno));
- exit(HES_PIPE);
- }
-
- wi_roof->qfd = qfds[1]; /* write end of query pipe */
- wi_roof->afd = afds[0]; /* read end of answer pipe */
-
- p = fork();
- if (p == -1)
- {
- /* fork failed: ignore if at least one worker exists */
- if (wi_roof == wi)
- {
- syslog(LOG_ERR, "fork(2) error creating first worker: %s", strerror(errno));
- exit(HES_FORK);
- }
- close(qfds[0]);
- close(qfds[1]);
- close(afds[0]);
- close(afds[1]);
- return FALSE;
- }
- else if (p == 0)
- {
- /* child */
- struct worker_info *w;
-
- close(PLUTO_QFD);
- close(PLUTO_AFD);
- /* close all master pipes, including ours */
- for (w = wi; w <= wi_roof; w++)
- {
- close(w->qfd);
- close(w->afd);
- }
- exit(worker(qfds[0], afds[1]));
- }
- else
- {
- /* parent */
- struct worker_info *w = wi_roof++;
-
- w->pid = p;
- w->busy = FALSE;
- close(qfds[0]);
- close(afds[1]);
- return TRUE;
- }
-}
-
-static void
-send_eof(struct worker_info *w)
-{
- pid_t p;
- int status;
-
- close(w->qfd);
- w->qfd = NULL_FD;
-
- close(w->afd);
- w->afd = NULL_FD;
-
- /* reap child */
- p = waitpid(w->pid, &status, 0);
- /* ignore result -- what could we do with it? */
-}
-
-static void
-forward_query(struct worker_info *w)
-{
- struct query_list *q = oldest_query;
-
- if (q == NULL)
- {
- if (eof_from_pluto)
- send_eof(w);
- }
- else
- {
- enum helper_exit_status r
- = write_pipe(w->qfd, (const unsigned char *) &q->aq);
-
- if (r != HES_CONTINUE)
- exit(r);
-
- w->busy = TRUE;
-
- oldest_query = q->next;
- q->next = free_queries;
- free_queries = q;
- }
-}
-
-static void
-query(void)
-{
- struct query_list *q = free_queries;
- enum helper_exit_status r;
-
- /* find an unused queue entry */
- if (q == NULL)
- {
- q = malloc(sizeof(*q));
- if (q == NULL)
- {
- syslog(LOG_ERR, "malloc(3) failed");
- exit(HES_MALLOC);
- }
- }
- else
- {
- free_queries = q->next;
- }
-
- r = read_pipe(PLUTO_QFD, (unsigned char *)&q->aq
- , sizeof(q->aq), sizeof(q->aq));
-
- if (r == HES_OK)
- {
- /* EOF: we're done, except for unanswered queries */
- struct worker_info *w;
-
- eof_from_pluto = TRUE;
- q->next = free_queries;
- free_queries = q;
-
- /* Send bye-bye to unbusy processes.
- * Note that if there are queued queries, there won't be
- * any non-busy workers.
- */
- for (w = wi; w != wi_roof; w++)
- if (!w->busy)
- send_eof(w);
- }
- else if (r != HES_CONTINUE)
- {
- exit(r);
- }
- else if (q->aq.qmagic != ADNS_Q_MAGIC)
- {
- syslog(LOG_ERR, "error in query from Pluto: bad magic");
- exit(HES_BAD_MAGIC);
- }
- else
- {
- struct worker_info *w;
-
- /* got a query */
-
- /* add it to FIFO */
- q->next = NULL;
- if (oldest_query == NULL)
- oldest_query = q;
- else
- newest_query->next = q;
- newest_query = q;
-
- /* See if any worker available */
- for (w = wi; ; w++)
- {
- if (w == wi_roof)
- {
- /* no free worker */
- if (w == wi + MAX_WORKERS)
- break; /* no more to be created */
- /* make a new one */
- if (!spawn_worker())
- break; /* cannot create one at this time */
- }
- if (!w->busy)
- {
- /* assign first to free worker */
- forward_query(w);
- break;
- }
- }
- }
- return;
-}
-
-static void
-answer(struct worker_info *w)
-{
- struct adns_answer a;
- enum helper_exit_status r = read_pipe(w->afd, (unsigned char *)&a
- , offsetof(struct adns_answer, ans), sizeof(a));
-
- if (r == HES_OK)
- {
- /* unexpected EOF */
- syslog(LOG_ERR, "unexpected EOF from worker");
- exit(HES_IO_ERROR_IN);
- }
- else if (r != HES_CONTINUE)
- {
- exit(r);
- }
- else if (a.amagic != ADNS_A_MAGIC)
- {
- syslog(LOG_ERR, "Input from worker error: bad magic");
- exit(HES_BAD_MAGIC);
- }
- else if (a.continuation != w->continuation)
- {
- /* answer doesn't match query */
- syslog(LOG_ERR, "Input from worker error: continuation mismatch");
- exit(HES_SYNC);
- }
- else
- {
- /* pass the answer on to Pluto */
- enum helper_exit_status r
- = write_pipe(PLUTO_AFD, (const unsigned char *) &a);
-
- if (r != HES_CONTINUE)
- exit(r);
- w->busy = FALSE;
- forward_query(w);
- }
-}
-
-/* assumption: input limited; accept blocking on output */
-static int
-master(void)
-{
- for (;;)
- {
- fd_set readfds;
- int maxfd = PLUTO_QFD; /* approximate lower bound */
- int ndes = 0;
- struct worker_info *w;
-
- FD_ZERO(&readfds);
- if (!eof_from_pluto)
- {
- FD_SET(PLUTO_QFD, &readfds);
- ndes++;
- }
- for (w = wi; w != wi_roof; w++)
- {
- if (w->busy)
- {
- FD_SET(w->afd, &readfds);
- ndes++;
- if (maxfd < w->afd)
- maxfd = w->afd;
- }
- }
-
- if (ndes == 0)
- return HES_OK; /* done! */
-
- do {
- ndes = select(maxfd + 1, &readfds, NULL, NULL, NULL);
- } while (ndes == -1 && errno == EINTR);
- if (ndes == -1)
- {
- syslog(LOG_ERR, "select(2) error: %s", strerror(errno));
- exit(HES_IO_ERROR_SELECT);
- }
- else if (ndes > 0)
- {
- if (FD_ISSET(PLUTO_QFD, &readfds))
- {
- query();
- ndes--;
- }
- for (w = wi; ndes > 0 && w != wi_roof; w++)
- {
- if (w->busy && FD_ISSET(w->afd, &readfds))
- {
- answer(w);
- ndes--;
- }
- }
- }
- }
-}
-
-/* Not to be invoked by strangers -- user hostile.
- * Mandatory args: query-fd answer-fd
- * Optional arg: -d, signifying "debug".
- */
-
-static void
-adns_usage(const char *fmt, const char *arg)
-{
- const char **sp = ipsec_copyright_notice();
-
- fprintf(stderr, "INTERNAL TO PLUTO: DO NOT EXECUTE\n");
-
- fprintf(stderr, fmt, arg);
- fprintf(stderr, "\nstrongSwan "VERSION"\n");
-
- for (; *sp != NULL; sp++)
- fprintf(stderr, "%s\n", *sp);
-
- syslog(LOG_ERR, fmt, arg);
- exit(HES_INVOCATION);
-}
-
-int
-main(int argc UNUSED, char **argv)
-{
- int i = 1;
-
- name = argv[0];
-
- while (i < argc)
- {
- if (streq(argv[i], "-d"))
- {
- i++;
- debug = TRUE;
- }
- else
- {
- adns_usage("unexpected argument \"%s\"", argv[i]);
- /*NOTREACHED*/
- }
- }
-
- return master();
-}
diff --git a/src/pluto/adns.h b/src/pluto/adns.h
deleted file mode 100644
index dfbcbaf16..000000000
--- a/src/pluto/adns.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/* Pluto Asynchronous DNS Helper Program's Header
- * Copyright (C) 2002 D. Hugh Redelmeier.
- *
- * 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.
- */
-
-#ifndef ADNS
-
-/* dummy struct to make compilers happy */
-struct adns_query {
-};
-
-#else /* rest of file */
-
-/* The interface in RHL6.x and BIND distribution 8.2.2 are different,
- * so we build some of our own :-(
- */
-
-# ifndef NS_MAXDNAME
-# define NS_MAXDNAME MAXDNAME /* I hope this is long enough for IPv6 */
-# endif
-
-# ifndef NS_PACKETSZ
-# define NS_PACKETSZ PACKETSZ
-# endif
-
-/* protocol version */
-
-#define ADNS_Q_MAGIC (((((('d' << 8) + 'n') << 8) + 's') << 8) + 4)
-#define ADNS_A_MAGIC (((((('d' << 8) + 'n') << 8) + 's') << 8) + 128 + 4)
-
-/* note: both struct adns_query and struct adns_answer must start with
- * size_t len;
- */
-
-struct adns_query {
- size_t len;
- unsigned int qmagic;
- unsigned long serial;
- lset_t debugging; /* only used #ifdef DEBUG, but don't want layout to change */
- u_char name_buf[NS_MAXDNAME + 2];
- int type; /* T_KEY or T_TXT */
-};
-
-struct adns_answer {
- size_t len;
- unsigned int amagic;
- unsigned long serial;
- struct adns_continuation *continuation;
- int result;
- int h_errno_val;
- u_char ans[NS_PACKETSZ * 10]; /* very probably bigger than necessary */
-};
-
-enum helper_exit_status {
- HES_CONTINUE = -1, /* not an exit */
- HES_OK = 0, /* all's well that ends well (perhaps EOF) */
- HES_INVOCATION, /* improper invocation */
- HES_IO_ERROR_SELECT, /* IO error in select() */
- HES_MALLOC, /* malloc failed */
- HES_IO_ERROR_IN, /* error reading pipe */
- HES_IO_ERROR_OUT, /* error reading pipe */
- HES_PIPE, /* pipe(2) failed */
- HES_SYNC, /* answer from worker doesn't match query */
- HES_FORK, /* fork(2) failed */
- HES_RES_INIT, /* resolver initialization failed */
- HES_BAD_LEN, /* implausible .len field */
- HES_BAD_MAGIC, /* .magic field wrong */
-};
-#endif /* ADNS */
diff --git a/src/pluto/alg_info.c b/src/pluto/alg_info.c
deleted file mode 100644
index fe27c10b2..000000000
--- a/src/pluto/alg_info.c
+++ /dev/null
@@ -1,683 +0,0 @@
-/*
- * Algorithm info parsing and creation functions
- * Copyright (C) JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
- * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <stddef.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <ctype.h>
-#include <freeswan.h>
-#include <pfkeyv2.h>
-
-#include <utils.h>
-#include <utils/lexparser.h>
-#include <crypto/diffie_hellman.h>
-#include <crypto/transform.h>
-#include <crypto/proposal/proposal_keywords.h>
-
-
-#include "alg_info.h"
-#include "constants.h"
-#include "defs.h"
-#include "log.h"
-#include "whack.h"
-#include "crypto.h"
-#include "kernel_alg.h"
-#include "ike_alg.h"
-
-/*
- * sadb/ESP aa attrib converters
- */
-int alg_info_esp_aa2sadb(int auth)
-{
- int sadb_aalg = 0;
-
- switch(auth)
- {
- case AUTH_ALGORITHM_HMAC_MD5:
- case AUTH_ALGORITHM_HMAC_SHA1:
- sadb_aalg = auth + 1;
- break;
- default:
- sadb_aalg = auth;
- }
- return sadb_aalg;
-}
-
-int alg_info_esp_sadb2aa(int sadb_aalg)
-{
- int auth = 0;
-
- switch(sadb_aalg)
- {
- case SADB_AALG_MD5HMAC:
- case SADB_AALG_SHA1HMAC:
- auth = sadb_aalg - 1;
- break;
- default:
- auth = sadb_aalg;
- }
- return auth;
-}
-
-void alg_info_free(struct alg_info *alg_info)
-{
- free(alg_info);
-}
-
-/*
- * Raw add routine: only checks for no duplicates
- */
-static void __alg_info_esp_add(struct alg_info_esp *alg_info, int ealg_id,
- unsigned ek_bits, int aalg_id, unsigned ak_bits)
-{
- struct esp_info *esp_info = alg_info->esp;
- unsigned cnt = alg_info->alg_info_cnt, i;
-
- /* check for overflows */
- passert(cnt < countof(alg_info->esp));
-
- /* dont add duplicates */
- for (i = 0; i < cnt; i++)
- {
- if (esp_info[i].esp_ealg_id == ealg_id
- && (!ek_bits || esp_info[i].esp_ealg_keylen == ek_bits)
- && esp_info[i].esp_aalg_id == aalg_id
- && (!ak_bits || esp_info[i].esp_aalg_keylen == ak_bits))
- {
- return;
- }
- }
-
- esp_info[cnt].esp_ealg_id = ealg_id;
- esp_info[cnt].esp_ealg_keylen = ek_bits;
- esp_info[cnt].esp_aalg_id = aalg_id;
- esp_info[cnt].esp_aalg_keylen = ak_bits;
-
- /* sadb values */
- esp_info[cnt].encryptalg = ealg_id;
- esp_info[cnt].authalg = alg_info_esp_aa2sadb(aalg_id);
- alg_info->alg_info_cnt++;
-
- DBG(DBG_CRYPT,
- DBG_log("esp alg added: %s_%d/%s, cnt=%d",
- enum_show(&esp_transform_names, ealg_id), ek_bits,
- enum_show(&auth_alg_names, aalg_id),
- alg_info->alg_info_cnt)
- )
-}
-
-/**
- * Returns true if the given alg is an authenticated encryption algorithm
- */
-static bool is_authenticated_encryption(int ealg_id)
-{
- switch (ealg_id)
- {
- case ESP_AES_CCM_8:
- case ESP_AES_CCM_12:
- case ESP_AES_CCM_16:
- case ESP_AES_GCM_8:
- case ESP_AES_GCM_12:
- case ESP_AES_GCM_16:
- case ESP_AES_GMAC:
- return TRUE;
- }
- return FALSE;
-}
-
-/*
- * Add ESP alg info _with_ logic (policy):
- */
-static void alg_info_esp_add(struct alg_info *alg_info, int ealg_id,
- int ek_bits, int aalg_id, int ak_bits)
-{
- /* Policy: default to 3DES */
- if (ealg_id == 0)
- {
- ealg_id = ESP_3DES;
- }
- if (ealg_id > 0)
- {
- if (is_authenticated_encryption(ealg_id))
- {
- __alg_info_esp_add((struct alg_info_esp *)alg_info,
- ealg_id, ek_bits,
- AUTH_ALGORITHM_NONE, 0);
- }
- else if (aalg_id > 0)
- {
- __alg_info_esp_add((struct alg_info_esp *)alg_info,
- ealg_id, ek_bits,
- aalg_id, ak_bits);
- }
- else
- {
- /* Policy: default to SHA-1 and MD5 */
- __alg_info_esp_add((struct alg_info_esp *)alg_info,
- ealg_id, ek_bits,
- AUTH_ALGORITHM_HMAC_SHA1, ak_bits);
- __alg_info_esp_add((struct alg_info_esp *)alg_info,
- ealg_id, ek_bits,
- AUTH_ALGORITHM_HMAC_MD5, ak_bits);
- }
- }
-}
-
-static void __alg_info_ike_add (struct alg_info_ike *alg_info, int ealg_id,
- unsigned ek_bits, int aalg_id, unsigned ak_bits,
- int modp_id)
-{
- struct ike_info *ike_info = alg_info->ike;
- unsigned cnt = alg_info->alg_info_cnt;
- unsigned i;
-
- /* check for overflows */
- passert(cnt < countof(alg_info->ike));
-
- /* dont add duplicates */
- for (i = 0; i < cnt; i++)
- {
- if (ike_info[i].ike_ealg == ealg_id
- && (!ek_bits || ike_info[i].ike_eklen == ek_bits)
- && ike_info[i].ike_halg == aalg_id
- && (!ak_bits || ike_info[i].ike_hklen == ak_bits)
- && ike_info[i].ike_modp==modp_id)
- return;
- }
-
- ike_info[cnt].ike_ealg = ealg_id;
- ike_info[cnt].ike_eklen = ek_bits;
- ike_info[cnt].ike_halg = aalg_id;
- ike_info[cnt].ike_hklen = ak_bits;
- ike_info[cnt].ike_modp = modp_id;
- alg_info->alg_info_cnt++;
-
- DBG(DBG_CRYPT,
- DBG_log("ikg alg added: %s_%d/%s/%s, cnt=%d",
- enum_show(&oakley_enc_names, ealg_id), ek_bits,
- enum_show(&oakley_hash_names, aalg_id),
- enum_show(&oakley_group_names, modp_id),
- alg_info->alg_info_cnt)
- )
-}
-
-/*
- * Proposals will be built by looping over default_ike_groups array and
- * merging alg_info (ike_info) contents
- */
-
-static int default_ike_groups[] = {
- MODP_1536_BIT,
- MODP_1024_BIT
-};
-
-/*
- * Add IKE alg info _with_ logic (policy):
- */
-static void alg_info_ike_add (struct alg_info *alg_info, int ealg_id,
- int ek_bits, int aalg_id, int ak_bits, int modp_id)
-{
- int i = 0;
- int n_groups = countof(default_ike_groups);
-
- /* if specified modp_id avoid loop over default_ike_groups */
- if (modp_id)
- {
- n_groups=0;
- goto in_loop;
- }
-
- for (; n_groups--; i++)
- {
- modp_id = default_ike_groups[i];
-in_loop:
- /* Policy: default to 3DES */
- if (ealg_id == 0)
- {
- ealg_id = OAKLEY_3DES_CBC;
- }
- if (ealg_id > 0)
- {
- if (aalg_id > 0)
- {
- __alg_info_ike_add((struct alg_info_ike *)alg_info,
- ealg_id, ek_bits,
- aalg_id, ak_bits,
- modp_id);
- }
- else
- {
- /* Policy: default to MD5 and SHA */
- __alg_info_ike_add((struct alg_info_ike *)alg_info,
- ealg_id, ek_bits,
- OAKLEY_MD5, ak_bits,
- modp_id);
- __alg_info_ike_add((struct alg_info_ike *)alg_info,
- ealg_id, ek_bits,
- OAKLEY_SHA, ak_bits,
- modp_id);
- }
- }
- }
-}
-
-static status_t alg_info_add(chunk_t alg, unsigned protoid,
- int *ealg, size_t *ealg_keysize,
- int *aalg, size_t *aalg_keysize, int *dh_group)
-{
- const proposal_token_t *token = proposal_get_token(alg.ptr, alg.len);
-
- if (token == NULL)
- {
- return FAILED;
- }
- switch (token->type)
- {
- case ENCRYPTION_ALGORITHM:
- if (*ealg != 0)
- {
- return FAILED;
- }
- *ealg = (protoid == PROTO_ISAKMP) ?
- oakley_from_encryption_algorithm(token->algorithm) :
- esp_from_encryption_algorithm(token->algorithm);
- if (*ealg == 0)
- {
- return FAILED;
- }
- *ealg_keysize = token->keysize;
- break;
- case INTEGRITY_ALGORITHM:
- if (*aalg != 0)
- {
- return FAILED;
- }
- *aalg = (protoid == PROTO_ISAKMP) ?
- oakley_from_integrity_algorithm(token->algorithm) :
- esp_from_integrity_algorithm(token->algorithm);
- if (*aalg == 0)
- {
- return FAILED;
- }
- *aalg_keysize = token->keysize;
- break;
- case DIFFIE_HELLMAN_GROUP:
- if (protoid == PROTO_ISAKMP)
- {
- if (*dh_group != 0)
- {
- return FAILED;
- }
- *dh_group = token->algorithm;
- }
- break;
- default:
- return FAILED;
- }
- return SUCCESS;
-}
-
-
-static status_t alg_info_parse_str(struct alg_info *alg_info, char *alg_str)
-{
- char *strict, *single;
- status_t status = SUCCESS;
-
- strict = alg_str + strlen(alg_str) - 1;
- if (*strict == '!')
- {
- alg_info->alg_info_flags |= ALG_INFO_F_STRICT;
- *strict = '\0';
- }
- while ((single = strsep(&alg_str, ",")))
- {
- chunk_t string = { (u_char *)single, strlen(single) };
- int ealg = 0;
- int aalg = 0;
- int dh_group = 0;
- size_t ealg_keysize = 0;
- size_t aalg_keysize = 0;
-
- eat_whitespace(&string);
-
- if (string.len > 0)
- {
- chunk_t alg;
-
- /* get all token, separated by '-' */
- while (extract_token(&alg, '-', &string))
- {
- status |= alg_info_add(alg, alg_info->alg_info_protoid,
- &ealg, &ealg_keysize,
- &aalg, &aalg_keysize, &dh_group);
- }
- if (string.len)
- {
- status |= alg_info_add(string, alg_info->alg_info_protoid,
- &ealg, &ealg_keysize,
- &aalg, &aalg_keysize, &dh_group);
- }
- }
- if (status == SUCCESS)
-
- {
- switch (alg_info->alg_info_protoid)
- {
- case PROTO_IPSEC_ESP:
- alg_info_esp_add(alg_info, ealg, ealg_keysize,
- aalg, aalg_keysize);
- break;
- case PROTO_ISAKMP:
- alg_info_ike_add(alg_info, ealg, ealg_keysize,
- aalg, aalg_keysize,
- dh_group);
- break;
- default:
- break;
- }
- }
- }
- return status;
-}
-
-struct alg_info_esp *alg_info_esp_create_from_str(char *alg_str)
-{
- struct alg_info_esp *alg_info_esp;
- char esp_buf[BUF_LEN];
- char *pfs_name;
- status_t status = SUCCESS;
- /*
- * alg_info storage should be sized dynamically
- * but this may require 2passes to know
- * transform count in advance.
- */
- alg_info_esp = malloc_thing (struct alg_info_esp);
- zero(alg_info_esp);
-
- pfs_name=strchr(alg_str, ';');
- if (pfs_name)
- {
- memcpy(esp_buf, alg_str, pfs_name-alg_str);
- esp_buf[pfs_name-alg_str] = 0;
- alg_str = esp_buf;
- pfs_name++;
-
- /* if pfs strings AND first char is not '0' */
- if (*pfs_name && pfs_name[0] != '0')
- {
- const proposal_token_t *token;
-
- token = proposal_get_token(pfs_name, strlen(pfs_name));
- if (token == NULL || token->type != DIFFIE_HELLMAN_GROUP)
- {
- /* Bomb if pfsgroup not found */
- DBG(DBG_CRYPT,
- DBG_log("alg_info_esp_create_from_str(): pfsgroup \"%s\" not found"
- , pfs_name)
- )
- status = FAILED;
- goto out;
- }
- alg_info_esp->esp_pfsgroup = token->algorithm;
- }
- }
- else
- {
- alg_info_esp->esp_pfsgroup = 0;
- }
- alg_info_esp->alg_info_protoid = PROTO_IPSEC_ESP;
- status = alg_info_parse_str((struct alg_info *)alg_info_esp, alg_str);
-
-out:
- if (status == SUCCESS)
- {
- alg_info_esp->ref_cnt = 1;
- return alg_info_esp;
- }
- else
- {
- free(alg_info_esp);
- return NULL;
- }
-}
-
-struct alg_info_ike *alg_info_ike_create_from_str(char *alg_str)
-{
- struct alg_info_ike *alg_info_ike;
- /*
- * alg_info storage should be sized dynamically
- * but this may require 2passes to know
- * transform count in advance.
- */
- alg_info_ike = malloc_thing (struct alg_info_ike);
- zero(alg_info_ike);
- alg_info_ike->alg_info_protoid = PROTO_ISAKMP;
-
- if (alg_info_parse_str((struct alg_info *)alg_info_ike, alg_str) == SUCCESS)
- {
- alg_info_ike->ref_cnt = 1;
- return alg_info_ike;
- }
- else
- {
- free(alg_info_ike);
- return NULL;
- }
-}
-
-/*
- * alg_info struct can be shared by
- * several connections instances,
- * handle free() with ref_cnts
- */
-void
-alg_info_addref(struct alg_info *alg_info)
-{
- if (alg_info != NULL)
- {
- alg_info->ref_cnt++;
- }
-}
-
-void
-alg_info_delref(struct alg_info **alg_info_p)
-{
- struct alg_info *alg_info = *alg_info_p;
-
- if (alg_info != NULL)
- {
- passert(alg_info->ref_cnt != 0);
- alg_info->ref_cnt--;
- if (alg_info->ref_cnt == 0)
- {
- alg_info_free(alg_info);
- }
- *alg_info_p = NULL;
- }
-}
-
-/* snprint already parsed transform list (alg_info) */
-int
-alg_info_snprint(char *buf, int buflen, struct alg_info *alg_info)
-{
- char *ptr = buf;
- int np = 0;
- struct esp_info *esp_info;
- struct ike_info *ike_info;
- int cnt;
-
- switch (alg_info->alg_info_protoid) {
- case PROTO_IPSEC_ESP:
- {
- struct alg_info_esp *alg_info_esp = (struct alg_info_esp *)alg_info;
-
- ALG_INFO_ESP_FOREACH(alg_info_esp, esp_info, cnt)
- {
- np = snprintf(ptr, buflen, "%s",
- enum_show(&esp_transform_names, esp_info->esp_ealg_id));
- ptr += np;
- buflen -= np;
- if (esp_info->esp_ealg_keylen)
- {
- np = snprintf(ptr, buflen, "_%zu", esp_info->esp_ealg_keylen);
- ptr += np;
- buflen -= np;
- }
- np = snprintf(ptr, buflen, "/%s, ",
- enum_show(&auth_alg_names, esp_info->esp_aalg_id));
- ptr += np;
- buflen -= np;
- if (buflen < 0)
- goto out;
- }
- if (alg_info_esp->esp_pfsgroup)
- {
- np = snprintf(ptr, buflen, "; pfsgroup=%s; ",
- enum_show(&oakley_group_names, alg_info_esp->esp_pfsgroup));
- ptr += np;
- buflen -= np;
- if (buflen < 0)
- goto out;
- }
- break;
- }
-
- case PROTO_ISAKMP:
- ALG_INFO_IKE_FOREACH((struct alg_info_ike *)alg_info, ike_info, cnt)
- {
- np = snprintf(ptr, buflen, "%s",
- enum_show(&oakley_enc_names, ike_info->ike_ealg));
- ptr += np;
- buflen -= np;
- if (ike_info->ike_eklen)
- {
- np = snprintf(ptr, buflen, "_%zu", ike_info->ike_eklen);
- ptr += np;
- buflen -= np;
- }
- np = snprintf(ptr, buflen, "/%s/%s, ",
- enum_show(&oakley_hash_names, ike_info->ike_halg),
- enum_show(&oakley_group_names, ike_info->ike_modp));
- ptr += np;
- buflen -= np;
- if (buflen < 0)
- goto out;
- }
- break;
- default:
- np = snprintf(buf, buflen, "INVALID protoid=%d\n"
- , alg_info->alg_info_protoid);
- ptr += np;
- buflen -= np;
- goto out;
- }
-
- np = snprintf(ptr, buflen, "%s"
- , alg_info->alg_info_flags & ALG_INFO_F_STRICT?
- "strict":"");
- ptr += np;
- buflen -= np;
-out:
- if (buflen < 0)
- {
- loglog(RC_LOG_SERIOUS
- , "buffer space exhausted in alg_info_snprint_ike(), buflen=%d"
- , buflen);
- }
-
- return ptr - buf;
-}
-
-int alg_info_snprint_esp(char *buf, int buflen, struct alg_info_esp *alg_info)
-{
- char *ptr = buf;
-
- int cnt = alg_info->alg_info_cnt;
- struct esp_info *esp_info = alg_info->esp;
-
- while (cnt--)
- {
- if (kernel_alg_esp_enc_ok(esp_info->esp_ealg_id, 0, NULL)
- && kernel_alg_esp_auth_ok(esp_info->esp_aalg_id, NULL))
- {
- u_int eklen = (esp_info->esp_ealg_keylen)
- ? esp_info->esp_ealg_keylen
- : kernel_alg_esp_enc_keylen(esp_info->esp_ealg_id)
- * BITS_PER_BYTE;
-
- u_int aklen = esp_info->esp_aalg_keylen
- ? esp_info->esp_aalg_keylen
- : kernel_alg_esp_auth_keylen(esp_info->esp_aalg_id)
- * BITS_PER_BYTE;
-
- int ret = snprintf(ptr, buflen, "%d_%03d-%d_%03d, ",
- esp_info->esp_ealg_id, eklen,
- esp_info->esp_aalg_id, aklen);
- ptr += ret;
- buflen -= ret;
- if (buflen < 0)
- break;
- }
- esp_info++;
- }
- return ptr - buf;
-}
-
-int alg_info_snprint_ike(char *buf, int buflen, struct alg_info_ike *alg_info)
-{
- char *ptr = buf;
-
- int cnt = alg_info->alg_info_cnt;
- struct ike_info *ike_info = alg_info->ike;
-
- while (cnt--)
- {
- struct encrypt_desc *enc_desc = ike_alg_get_crypter(ike_info->ike_ealg);
- struct hash_desc *hash_desc = ike_alg_get_hasher(ike_info->ike_halg);
- struct dh_desc *dh_desc = ike_alg_get_dh_group(ike_info->ike_modp);
-
- if (enc_desc && hash_desc && dh_desc)
- {
-
- u_int eklen = (ike_info->ike_eklen)
- ? ike_info->ike_eklen
- : enc_desc->keydeflen;
-
- u_int aklen = (ike_info->ike_hklen)
- ? ike_info->ike_hklen
- : hash_desc->hash_digest_size * BITS_PER_BYTE;
-
- int ret = snprintf(ptr, buflen, "%d_%03d-%d_%03d-%d, ",
- ike_info->ike_ealg, eklen,
- ike_info->ike_halg, aklen,
- ike_info->ike_modp);
- ptr += ret;
- buflen -= ret;
- if (buflen < 0)
- break;
- }
- ike_info++;
- }
- return ptr - buf;
-}
-
diff --git a/src/pluto/alg_info.h b/src/pluto/alg_info.h
deleted file mode 100644
index 85b88ddff..000000000
--- a/src/pluto/alg_info.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* Algorithm info parsing and creation functions
- * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
- *
- * 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.
- */
-
-#ifndef ALG_INFO_H
-#define ALG_INFO_H
-
-struct esp_info {
- u_int8_t transid; /* ESP transform */
- u_int16_t auth; /* AUTH */
- size_t enckeylen; /* keylength for ESP transform */
- size_t authkeylen; /* keylength for AUTH */
- u_int8_t encryptalg; /* normally encryptalg=transid */
- u_int8_t authalg; /* normally authalg=auth+1 */
-};
-
-struct ike_info {
- u_int16_t ike_ealg; /* high 16 bit nums for reserved */
- u_int8_t ike_halg;
- size_t ike_eklen;
- size_t ike_hklen;
- u_int16_t ike_modp;
-};
-
-#define ALG_INFO_COMMON \
- int alg_info_cnt; \
- int ref_cnt; \
- unsigned alg_info_flags; \
- unsigned alg_info_protoid
-
-struct alg_info {
- ALG_INFO_COMMON;
-};
-
-struct alg_info_esp {
- ALG_INFO_COMMON;
- struct esp_info esp[64];
- int esp_pfsgroup;
-};
-
-struct alg_info_ike {
- ALG_INFO_COMMON;
- struct ike_info ike[64];
-};
-#define esp_ealg_id transid
-#define esp_aalg_id auth
-#define esp_ealg_keylen enckeylen /* bits */
-#define esp_aalg_keylen authkeylen /* bits */
-
-/* alg_info_flags bits */
-#define ALG_INFO_F_STRICT 0x01
-
-extern int alg_info_esp_aa2sadb(int auth);
-extern int alg_info_esp_sadb2aa(int sadb_aalg);
-extern void alg_info_free(struct alg_info *alg_info);
-extern void alg_info_addref(struct alg_info *alg_info);
-extern void alg_info_delref(struct alg_info **alg_info);
-extern struct alg_info_esp* alg_info_esp_create_from_str(char *alg_str);
-extern struct alg_info_ike* alg_info_ike_create_from_str(char *alg_str);
-extern int alg_info_parse(const char *str);
-extern int alg_info_snprint(char *buf, int buflen, struct alg_info *alg_info);
-extern int alg_info_snprint_esp(char *buf, int buflen
- , struct alg_info_esp *alg_info);
-extern int alg_info_snprint_ike(char *buf, int buflen
- , struct alg_info_ike *alg_info);
-#define ALG_INFO_ESP_FOREACH(ai, ai_esp, i) \
- for (i=(ai)->alg_info_cnt,ai_esp=(ai)->esp; i--; ai_esp++)
-#define ALG_INFO_IKE_FOREACH(ai, ai_ike, i) \
- for (i=(ai)->alg_info_cnt,ai_ike=(ai)->ike; i--; ai_ike++)
-#endif /* ALG_INFO_H */
diff --git a/src/pluto/builder.c b/src/pluto/builder.c
deleted file mode 100644
index a6e05a330..000000000
--- a/src/pluto/builder.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/* Pluto certificate/CRL/AC builder hooks.
- * Copyright (C) 2002-2009 Andreas Steffen
- * Copyright (C) 2009 Martin Willi
- * 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 "builder.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <time.h>
-
-#include <freeswan.h>
-
-#include <library.h>
-#include <credentials/certificates/certificate.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "log.h"
-#include "certs.h"
-#include "crl.h"
-
-/**
- * Load a certificate
- */
-static cert_t *builder_load_cert(certificate_type_t type, va_list args)
-{
- x509_flag_t flags = 0;
- chunk_t blob = chunk_empty;
- bool pgp = FALSE;
-
- while (TRUE)
- {
- switch (va_arg(args, builder_part_t))
- {
- case BUILD_BLOB_PGP:
- pgp = TRUE;
- /* FALL */
- case BUILD_BLOB_ASN1_DER:
- blob = va_arg(args, chunk_t);
- continue;
- case BUILD_X509_FLAG:
- flags |= va_arg(args, x509_flag_t);
- continue;
- case BUILD_END:
- break;
- default:
- return NULL;
- }
- break;
- }
- if (blob.ptr)
- {
- cert_t *cert = malloc_thing(cert_t);
-
- *cert = cert_empty;
-
- if (pgp)
- {
- cert->cert = lib->creds->create(lib->creds,
- CRED_CERTIFICATE, CERT_GPG,
- BUILD_BLOB_PGP, blob,
- BUILD_END);
- }
- else
- {
- cert->cert = lib->creds->create(lib->creds,
- CRED_CERTIFICATE, CERT_X509,
- BUILD_BLOB_ASN1_DER, blob,
- BUILD_X509_FLAG, flags,
- BUILD_END);
- }
- if (cert->cert)
- {
- return cert;
- }
- plog(" error in X.509 certificate");
- cert_free(cert);
- }
- return NULL;
-}
-
-/**
- * Load a CRL
- */
-static x509crl_t *builder_load_crl(certificate_type_t type, va_list args)
-{
- chunk_t blob = chunk_empty;
- x509crl_t *crl;
-
- while (TRUE)
- {
- switch (va_arg(args, builder_part_t))
- {
- case BUILD_BLOB_ASN1_DER:
- blob = va_arg(args, chunk_t);
- continue;
- case BUILD_END:
- break;
- default:
- return NULL;
- }
- break;
- }
- if (blob.ptr)
- {
- crl = malloc_thing(x509crl_t);
- crl->next = NULL;
- crl->distributionPoints = linked_list_create();
- crl->crl = lib->creds->create(lib->creds,
- CRED_CERTIFICATE, CERT_X509_CRL,
- BUILD_BLOB_ASN1_DER, blob,
- BUILD_END);
- if (crl->crl)
- {
- return crl;
- }
- plog(" error in X.509 crl");
- free_crl(crl);
- }
- return NULL;
-}
-
-void init_builder(void)
-{
- lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_PLUTO_CERT, FALSE,
- (builder_function_t)builder_load_cert);
- lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_PLUTO_CRL, FALSE,
- (builder_function_t)builder_load_crl);
-}
-
-void free_builder(void)
-{
- lib->creds->remove_builder(lib->creds, (builder_function_t)builder_load_cert);
- lib->creds->remove_builder(lib->creds, (builder_function_t)builder_load_crl);
-}
-
diff --git a/src/pluto/builder.h b/src/pluto/builder.h
deleted file mode 100644
index 784751b7c..000000000
--- a/src/pluto/builder.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* Pluto certificate/CRL/AC builder hooks.
- * Copyright (C) 2009 Martin Willi
- * 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.
- */
-
-#ifndef _BUILDER_H
-#define _BUILDER_H
-
-/* register credential builder hooks */
-extern void init_builder();
-/* unregister credential builder hooks */
-extern void free_builder();
-
-#endif /* _BUILDER_H */
diff --git a/src/pluto/ca.c b/src/pluto/ca.c
deleted file mode 100644
index 827b98121..000000000
--- a/src/pluto/ca.c
+++ /dev/null
@@ -1,712 +0,0 @@
-/* Certification Authority (CA) support for IKE authentication
- * Copyright (C) 2002-2004 Andreas Steffen, Zuercher Hochschule Winterthur
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <debug.h>
-#include <utils/enumerator.h>
-#include <credentials/certificates/x509.h>
-
-#include <freeswan.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "log.h"
-#include "x509.h"
-#include "ca.h"
-#include "certs.h"
-#include "whack.h"
-#include "fetch.h"
-#include "smartcard.h"
-
-/* chained list of X.509 authority certificates (ca, aa, and ocsp) */
-
-static cert_t *x509authcerts = NULL;
-
-/* chained list of X.509 certification authority information records */
-
-static ca_info_t *ca_infos = NULL;
-
-/*
- * Checks if CA a is trusted by CA b
- */
-bool trusted_ca(identification_t *a, identification_t *b, int *pathlen)
-{
- bool match = FALSE;
-
- /* no CA b specified -> any CA a is accepted */
- if (b == NULL)
- {
- *pathlen = (a == NULL) ? 0 : X509_MAX_PATH_LEN;
- return TRUE;
- }
-
- /* no CA a specified -> trust cannot be established */
- if (a == NULL)
- {
- *pathlen = X509_MAX_PATH_LEN;
- return FALSE;
- }
-
- *pathlen = 0;
-
- /* CA a equals CA b -> we have a match */
- if (a->equals(a, b))
- {
- return TRUE;
- }
-
- /* CA a might be a subordinate CA of b */
- lock_authcert_list("trusted_ca");
-
- while ((*pathlen)++ < X509_MAX_PATH_LEN)
- {
- certificate_t *certificate;
- identification_t *issuer;
- cert_t *cacert;
-
- cacert = get_authcert(a, chunk_empty, X509_CA);
- if (cacert == NULL)
- {
- break;
- }
- certificate = cacert->cert;
-
- /* is the certificate self-signed? */
- {
- x509_t *x509 = (x509_t*)certificate;
-
- if (x509->get_flags(x509) & X509_SELF_SIGNED)
- {
- break;
- }
- }
-
- /* does the issuer of CA a match CA b? */
- issuer = certificate->get_issuer(certificate);
- match = b->equals(b, issuer);
-
- /* we have a match and exit the loop */
- if (match)
- {
- break;
- }
- /* go one level up in the CA chain */
- a = issuer;
- }
-
- unlock_authcert_list("trusted_ca");
- return match;
-}
-
-/*
- * does our CA match one of the requested CAs?
- */
-bool match_requested_ca(linked_list_t *requested_ca, identification_t *our_ca,
- int *our_pathlen)
-{
- identification_t *ca;
- enumerator_t *enumerator;
-
- /* if no ca is requested than any ca will match */
- if (requested_ca == NULL || requested_ca->get_count(requested_ca) == 0)
- {
- *our_pathlen = 0;
- return TRUE;
- }
-
- *our_pathlen = X509_MAX_PATH_LEN + 1;
-
- enumerator = requested_ca->create_enumerator(requested_ca);
- while (enumerator->enumerate(enumerator, &ca))
- {
- int pathlen;
-
- if (trusted_ca(our_ca, ca, &pathlen) && pathlen < *our_pathlen)
- {
- *our_pathlen = pathlen;
- }
- }
- enumerator->destroy(enumerator);
-
- if (*our_pathlen > X509_MAX_PATH_LEN)
- {
- *our_pathlen = X509_MAX_PATH_LEN;
- return FALSE;
- }
- else
- {
- return TRUE;
- }
-}
-
-/*
- * free the first authority certificate in the chain
- */
-static void free_first_authcert(void)
-{
- cert_t *first = x509authcerts;
-
- x509authcerts = first->next;
- cert_free(first);
-}
-
-/*
- * free all CA certificates
- */
-void free_authcerts(void)
-{
- lock_authcert_list("free_authcerts");
-
- while (x509authcerts != NULL)
- {
- free_first_authcert();
- }
- unlock_authcert_list("free_authcerts");
-}
-
-/*
- * get a X.509 authority certificate with a given subject or keyid
- */
-cert_t* get_authcert(identification_t *subject, chunk_t keyid,
- x509_flag_t auth_flags)
-{
- cert_t *cert, *prev_cert = NULL;
-
- /* the authority certificate list is empty */
- if (x509authcerts == NULL)
- {
- return NULL;
- }
-
- for (cert = x509authcerts; cert != NULL; prev_cert = cert, cert = cert->next)
- {
- certificate_t *certificate = cert->cert;
- x509_t *x509 = (x509_t*)certificate;
-
- /* skip non-matching types of authority certificates */
- if (!(x509->get_flags(x509) & auth_flags))
- {
- continue;
- }
-
- /* compare the keyid with the certificate's subjectKeyIdentifier */
- if (keyid.ptr)
- {
- chunk_t subjectKeyId;
-
- subjectKeyId = x509->get_subjectKeyIdentifier(x509);
- if (subjectKeyId.ptr && !chunk_equals(keyid, subjectKeyId))
- {
- continue;
- }
- }
-
- /* compare the subjectDistinguishedNames */
- if (!(subject && certificate->has_subject(certificate, subject)) &&
- (subject || !keyid.ptr))
- {
- continue;
- }
-
- /* found the authcert */
- if (cert != x509authcerts)
- {
- /* bring the certificate up front */
- prev_cert->next = cert->next;
- cert->next = x509authcerts;
- x509authcerts = cert;
- }
- return cert;
- }
- return NULL;
-}
-
-/*
- * add an authority certificate to the chained list
- */
-cert_t* add_authcert(cert_t *cert, x509_flag_t auth_flags)
-{
- certificate_t *certificate = cert->cert;
- x509_t *x509 = (x509_t*)certificate;
- cert_t *old_cert;
-
- lock_authcert_list("add_authcert");
-
- old_cert = get_authcert(certificate->get_subject(certificate),
- x509->get_subjectKeyIdentifier(x509),
- auth_flags);
- if (old_cert)
- {
- if (certificate->equals(certificate, old_cert->cert))
- {
- DBG(DBG_CONTROL | DBG_PARSING ,
- DBG_log(" authcert is already present and identical")
- )
- unlock_authcert_list("add_authcert");
-
- cert_free(cert);
- return old_cert;
- }
- else
- {
- /* cert is already present but will be replaced by new cert */
- free_first_authcert();
- DBG(DBG_CONTROL | DBG_PARSING ,
- DBG_log(" existing authcert deleted")
- )
- }
- }
-
- /* add new authcert to chained list */
- cert->next = x509authcerts;
- x509authcerts = cert;
- cert_share(cert); /* set count to one */
- DBG(DBG_CONTROL | DBG_PARSING,
- DBG_log(" authcert inserted")
- )
- unlock_authcert_list("add_authcert");
- return cert;
-}
-
-/*
- * Loads authority certificates
- */
-void load_authcerts(char *type, char *path, x509_flag_t auth_flags)
-{
- enumerator_t *enumerator;
- struct stat st;
- char *file;
-
- DBG1(DBG_LIB, "loading %s certificates from '%s'", type, path);
-
- enumerator = enumerator_create_directory(path);
- if (!enumerator)
- {
- DBG1(DBG_LIB, " reading directory '%s' failed", path);
- return;
- }
-
- while (enumerator->enumerate(enumerator, NULL, &file, &st))
- {
- cert_t *cert;
-
- if (!S_ISREG(st.st_mode))
- {
- /* skip special file */
- continue;
- }
- cert = load_cert(file, type, auth_flags);
- if (cert)
- {
- add_authcert(cert, auth_flags);
- }
- }
- enumerator->destroy(enumerator);
-}
-
-/*
- * list all X.509 authcerts with given auth flags in a chained list
- */
-void list_authcerts(const char *caption, x509_flag_t auth_flags, bool utc)
-{
- lock_authcert_list("list_authcerts");
- list_x509cert_chain(caption, x509authcerts, auth_flags, utc);
- unlock_authcert_list("list_authcerts");
-}
-
-/*
- * get a cacert with a given subject or keyid from an alternative list
- */
-static const cert_t* get_alt_cacert(identification_t *subject, chunk_t keyid,
- const cert_t *cert)
-{
- if (cert == NULL)
- {
- return NULL;
- }
- for (; cert != NULL; cert = cert->next)
- {
- certificate_t *certificate = cert->cert;
-
- /* compare the keyid with the certificate's subjectKeyIdentifier */
- if (keyid.ptr)
- {
- x509_t *x509 = (x509_t*)certificate;
- chunk_t subjectKeyId;
-
- subjectKeyId = x509->get_subjectKeyIdentifier(x509);
- if (subjectKeyId.ptr && !chunk_equals(keyid, subjectKeyId))
- {
- continue;
- }
- }
-
- /* compare the subjectDistinguishedNames */
- if (!certificate->has_subject(certificate, subject))
- {
- continue;
- }
-
- /* we found the cacert */
- return cert;
- }
- return NULL;
-}
-
-/* establish trust into a candidate authcert by going up the trust chain.
- * validity and revocation status are not checked.
- */
-bool trust_authcert_candidate(const cert_t *cert, const cert_t *alt_chain)
-{
- int pathlen;
-
- lock_authcert_list("trust_authcert_candidate");
-
- for (pathlen = 0; pathlen < X509_MAX_PATH_LEN; pathlen++)
- {
- certificate_t *certificate = cert->cert;
- x509_t *x509 = (x509_t*)certificate;
- identification_t *subject = certificate->get_subject(certificate);
- identification_t *issuer = certificate->get_issuer(certificate);
- chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
- const cert_t *authcert = NULL;
-
- DBG(DBG_CONTROL,
- DBG_log("subject: '%Y'", subject);
- DBG_log("issuer: '%Y'", issuer);
- if (authKeyID.ptr != NULL)
- {
- DBG_log("authkey: %#B", &authKeyID);
- }
- )
-
- /* search in alternative chain first */
- authcert = get_alt_cacert(issuer, authKeyID, alt_chain);
-
- if (authcert != NULL)
- {
- DBG(DBG_CONTROL,
- DBG_log("issuer cacert found in alternative chain")
- )
- }
- else
- {
- /* search in trusted chain */
- authcert = get_authcert(issuer, authKeyID, X509_CA);
-
- if (authcert != NULL)
- {
- DBG(DBG_CONTROL,
- DBG_log("issuer cacert found")
- )
- }
- else
- {
- plog("issuer cacert not found");
- unlock_authcert_list("trust_authcert_candidate");
- return FALSE;
- }
- }
-
- if (!certificate->issued_by(certificate, authcert->cert))
- {
- plog("certificate signature is invalid");
- unlock_authcert_list("trust_authcert_candidate");
- return FALSE;
- }
- DBG(DBG_CONTROL,
- DBG_log("certificate signature is valid")
- )
-
- /* check if cert is a self-signed root ca */
- if (pathlen > 0 && (x509->get_flags(x509) & X509_SELF_SIGNED))
- {
- DBG(DBG_CONTROL,
- DBG_log("reached self-signed root ca")
- )
- unlock_authcert_list("trust_authcert_candidate");
- return TRUE;
- }
-
- /* go up one step in the trust chain */
- cert = authcert;
- }
- plog("maximum ca path length of %d levels exceeded", X509_MAX_PATH_LEN);
- unlock_authcert_list("trust_authcert_candidate");
- return FALSE;
-}
-
-/*
- * get a CA info record with a given authName or authKeyID
- */
-ca_info_t* get_ca_info(identification_t *name, chunk_t keyid)
-{
- ca_info_t *ca= ca_infos;
-
- while (ca != NULL)
- {
- if ((keyid.ptr) ? same_keyid(keyid, ca->authKeyID)
- : name->equals(name, ca->authName))
- {
- return ca;
- }
- ca = ca->next;
- }
- return NULL;
-}
-
-
-/*
- * free the dynamic memory used by a ca_info record
- */
-static void
-free_ca_info(ca_info_t* ca_info)
-{
- if (ca_info == NULL)
- {
- return;
- }
- ca_info->crluris->destroy_function(ca_info->crluris, free);
- DESTROY_IF(ca_info->authName);
- free(ca_info->name);
- free(ca_info->ldaphost);
- free(ca_info->ldapbase);
- free(ca_info->ocspuri);
- free(ca_info->authKeyID.ptr);
- free(ca_info);
-}
-
-/*
- * free all CA certificates
- */
-void free_ca_infos(void)
-{
- while (ca_infos != NULL)
- {
- ca_info_t *ca = ca_infos;
-
- ca_infos = ca_infos->next;
- free_ca_info(ca);
- }
-}
-
-/*
- * find a CA information record by name and optionally delete it
- */
-bool find_ca_info_by_name(const char *name, bool delete)
-{
- ca_info_t **ca_p = &ca_infos;
- ca_info_t *ca = *ca_p;
-
- while (ca != NULL)
- {
- /* is there already an entry? */
- if (streq(name, ca->name))
- {
- if (delete)
- {
- lock_ca_info_list("find_ca_info_by_name");
- *ca_p = ca->next;
- free_ca_info(ca);
- plog("deleting ca description \"%s\"", name);
- unlock_ca_info_list("find_ca_info_by_name");
- }
- return TRUE;
- }
- ca_p = &ca->next;
- ca = *ca_p;
- }
- return FALSE;
-}
-
-/*
- * Create an empty ca_info_t record
- */
-ca_info_t* create_ca_info(void)
-{
- ca_info_t *ca_info = malloc_thing(ca_info_t);
-
- memset(ca_info, 0, sizeof(ca_info_t));
- ca_info->crluris = linked_list_create();
-
- return ca_info;
-}
-
-/**
- * Adds a CA description to a chained list
- */
-void add_ca_info(const whack_message_t *msg)
-{
- smartcard_t *sc = NULL;
- cert_t *cert = NULL;
- bool cached_cert = FALSE;
-
- if (find_ca_info_by_name(msg->name, FALSE))
- {
- loglog(RC_DUPNAME, "attempt to redefine ca record \"%s\"", msg->name);
- return;
- }
-
- if (scx_on_smartcard(msg->cacert))
- {
- /* load CA cert from smartcard */
- cert = scx_load_cert(msg->cacert, &sc, &cached_cert);
- }
- else
- {
- /* load CA cert from file */
- cert = load_ca_cert(msg->cacert);
- }
-
- if (cert)
- {
- certificate_t *certificate = cert->cert;
- x509_t *x509 = (x509_t*)certificate;
- identification_t *subject = certificate->get_subject(certificate);
- chunk_t subjectKeyID = x509->get_subjectKeyIdentifier(x509);
- ca_info_t *ca = NULL;
-
- /* does the authname already exist? */
- ca = get_ca_info(subject, subjectKeyID);
-
- if (ca != NULL)
- {
- /* ca_info is already present */
- loglog(RC_DUPNAME, " duplicate ca information in record \"%s\" found,"
- "ignoring \"%s\"", ca->name, msg->name);
- cert_free(cert);
- return;
- }
-
- plog("added ca description \"%s\"", msg->name);
-
- /* create and initialize new ca_info record */
- ca = create_ca_info();
-
- /* name */
- ca->name = clone_str(msg->name);
-
- /* authName */
- ca->authName = subject->clone(subject);
- DBG(DBG_CONTROL,
- DBG_log("authname: '%Y'", subject)
- )
-
- /* authKeyID */
- if (subjectKeyID.ptr)
- {
- ca->authKeyID = chunk_clone(subjectKeyID);
- DBG(DBG_CONTROL | DBG_PARSING ,
- DBG_log("authkey: %#B", &subjectKeyID)
- )
- }
-
- /* ldaphost */
- ca->ldaphost = clone_str(msg->ldaphost);
-
- /* ldapbase */
- ca->ldapbase = clone_str(msg->ldapbase);
-
- /* ocspuri */
- if (msg->ocspuri != NULL)
- {
- if (strncasecmp(msg->ocspuri, "http", 4) == 0)
- ca->ocspuri = clone_str(msg->ocspuri);
- else
- plog(" ignoring ocspuri with unknown protocol");
- }
-
- /* add crl uris */
- add_distribution_point(ca->crluris, msg->crluri);
- add_distribution_point(ca->crluris, msg->crluri2);
-
- /* strictrlpolicy */
- ca->strictcrlpolicy = msg->whack_strict;
-
- /* insert ca_info record into the chained list */
- lock_ca_info_list("add_ca_info");
-
- ca->next = ca_infos;
- ca_infos = ca;
-
- unlock_ca_info_list("add_ca_info");
-
- /* add cacert to list of authcerts */
- cert = add_authcert(cert, X509_CA);
- if (!cached_cert && sc != NULL)
- {
- if (sc->last_cert != NULL)
- {
- sc->last_cert->count--;
- }
- sc->last_cert = cert;
- cert_share(sc->last_cert);
- }
- if (sc != NULL)
- time(&sc->last_load);
- }
-}
-
-/*
- * list all ca_info records in the chained list
- */
-void list_ca_infos(bool utc)
-{
- ca_info_t *ca = ca_infos;
-
- if (ca != NULL)
- {
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, "List of X.509 CA Information Records:");
- }
-
- while (ca != NULL)
- {
- /* strictpolicy per CA not supported yet
- *
- whack_log(RC_COMMENT, "%T, \"%s\", strictcrlpolicy: %s"
- , &ca->installed, utc, ca->name
- , ca->strictcrlpolicy? "yes":"no");
- */
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, " authname: \"%Y\"", ca->authName);
- if (ca->ldaphost)
- {
- whack_log(RC_COMMENT, " ldaphost: '%s'", ca->ldaphost);
- }
- if (ca->ldapbase)
- {
- whack_log(RC_COMMENT, " ldapbase: '%s'", ca->ldapbase);
- }
- if (ca->ocspuri)
- {
- whack_log(RC_COMMENT, " ocspuri: '%s'", ca->ocspuri);
- }
-
- list_distribution_points(ca->crluris);
-
- if (ca->authKeyID.ptr)
- {
- whack_log(RC_COMMENT, " authkey: %#B", &ca->authKeyID);
- }
- ca = ca->next;
- }
-}
-
diff --git a/src/pluto/ca.h b/src/pluto/ca.h
deleted file mode 100644
index d964a694a..000000000
--- a/src/pluto/ca.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/* Certification Authority (CA) support for IKE authentication
- * Copyright (C) 2002-2004 Andreas Steffen, Zuercher Hochschule Winterthur
- *
- * 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.
- */
-
-#ifndef _CA_H
-#define _CA_H
-
-#include <utils/linked_list.h>
-#include <utils/identification.h>
-
-#include "certs.h"
-#include "whack.h"
-
-/* CA info structures */
-
-typedef struct ca_info ca_info_t;
-
-struct ca_info {
- ca_info_t *next;
- char *name;
- identification_t *authName;
- chunk_t authKeyID;
- char *ldaphost;
- char *ldapbase;
- char *ocspuri;
- linked_list_t *crluris;
- bool strictcrlpolicy;
-};
-
-extern bool trusted_ca(identification_t *a, identification_t *b, int *pathlen);
-extern bool match_requested_ca(linked_list_t *requested_ca,
- identification_t *our_ca, int *our_pathlen);
-extern cert_t* get_authcert(identification_t *subject, chunk_t keyid,
- x509_flag_t auth_flags);
-extern void load_authcerts(char *type, char *path, x509_flag_t auth_flags);
-extern cert_t* add_authcert(cert_t *cert, x509_flag_t auth_flags);
-extern void free_authcerts(void);
-extern void list_authcerts(const char *caption, x509_flag_t auth_flags, bool utc);
-extern bool trust_authcert_candidate(const cert_t *cert, const cert_t *alt_chain);
-extern ca_info_t* get_ca_info(identification_t *name, chunk_t keyid);
-extern bool find_ca_info_by_name(const char *name, bool delete);
-extern void add_ca_info(const whack_message_t *msg);
-extern void delete_ca_info(const char *name);
-extern void free_ca_infos(void);
-extern void list_ca_infos(bool utc);
-
-#endif /* _CA_H */
-
diff --git a/src/pluto/certs.c b/src/pluto/certs.c
deleted file mode 100644
index e866022df..000000000
--- a/src/pluto/certs.c
+++ /dev/null
@@ -1,268 +0,0 @@
-/* Certificate support for IKE authentication
- * Copyright (C) 2002-2009 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 <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <time.h>
-
-#include <freeswan.h>
-
-#include <library.h>
-#include <asn1/asn1.h>
-#include <credentials/certificates/certificate.h>
-#include <credentials/certificates/pgp_certificate.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "log.h"
-#include "certs.h"
-#include "whack.h"
-#include "fetch.h"
-#include "keys.h"
-#include "builder.h"
-
-/**
- * Initialization
- */
-const cert_t cert_empty = {
- NULL , /* cert */
- NULL , /* *next */
- 0 , /* count */
- FALSE /* smartcard */
-};
-
-/**
- * Chained lists of X.509 and PGP end entity certificates
- */
-static cert_t *certs = NULL;
-
-/**
- * Free a pluto certificate
- */
-void cert_free(cert_t *cert)
-{
- if (cert)
- {
- certificate_t *certificate = cert->cert;
-
- if (certificate)
- {
- certificate->destroy(certificate);
- }
- free(cert);
- }
-}
-
-/**
- * Add a pluto end entity certificate to the chained list
- */
-cert_t* cert_add(cert_t *cert)
-{
- certificate_t *certificate = cert->cert;
- cert_t *c;
-
- lock_certs_and_keys("cert_add");
-
- for (c = certs; c != NULL; c = c->next)
- {
- if (certificate->equals(certificate, c->cert))
- { /* already in chain, free cert */
- unlock_certs_and_keys("cert_add");
- cert_free(cert);
- return c;
- }
- }
-
- /* insert new cert at the root of the chain */
- cert->next = certs;
- certs = cert;
- DBG(DBG_CONTROL | DBG_PARSING,
- DBG_log(" cert inserted")
- )
- unlock_certs_and_keys("cert_add");
- return cert;
-}
-
-/**
- * Loads a X.509 or OpenPGP certificate
- */
-cert_t* load_cert(char *filename, const char *label, x509_flag_t flags)
-{
- cert_t *cert;
-
- cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_PLUTO_CERT,
- BUILD_FROM_FILE, filename,
- BUILD_X509_FLAG, flags,
- BUILD_END);
- if (cert)
- {
- plog(" loaded %s certificate from '%s'", label, filename);
- }
- return cert;
-}
-
-/**
- * Loads a host certificate
- */
-cert_t* load_host_cert(char *filename)
-{
- char *path = concatenate_paths(HOST_CERT_PATH, filename);
-
- return load_cert(path, "host", X509_NONE);
-}
-
-/**
- * Loads a CA certificate
- */
-cert_t* load_ca_cert(char *filename)
-{
- char *path = concatenate_paths(CA_CERT_PATH, filename);
-
- return load_cert(path, "CA", X509_NONE);
-}
-
-/**
- * for each link pointing to the certificate increase the count by one
- */
-void cert_share(cert_t *cert)
-{
- if (cert != NULL)
- {
- cert->count++;
- }
-}
-
-/* release of a certificate decreases the count by one
- * the certificate is freed when the counter reaches zero
- */
-void cert_release(cert_t *cert)
-{
- if (cert && --cert->count == 0)
- {
- cert_t **pp = &certs;
- while (*pp != cert)
- {
- pp = &(*pp)->next;
- }
- *pp = cert->next;
- cert_free(cert);
- }
-}
-
-/**
- * Get a X.509 certificate with a given issuer found at a certain position
- */
-cert_t* get_x509cert(identification_t *issuer, chunk_t keyid, cert_t *chain)
-{
- cert_t *cert = chain ? chain->next : certs;
-
- while (cert)
- {
- certificate_t *certificate = cert->cert;
- x509_t *x509 = (x509_t*)certificate;
- chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
-
- if (keyid.ptr ? same_keyid(keyid, authKeyID) :
- certificate->has_issuer(certificate, issuer))
- {
- return cert;
- }
- cert = cert->next;
- }
- return NULL;
-}
-
-/**
- * List all PGP end certificates in a chained list
- */
-void list_pgp_end_certs(bool utc)
-{
- cert_t *cert = certs;
- time_t now = time(NULL);
- bool first = TRUE;
-
-
- while (cert != NULL)
- {
- certificate_t *certificate = cert->cert;
-
- if (certificate->get_type(certificate) == CERT_GPG)
- {
- time_t created, until;
- public_key_t *key;
- identification_t *userid = certificate->get_subject(certificate);
- pgp_certificate_t *pgp_cert = (pgp_certificate_t*)certificate;
- chunk_t fingerprint = pgp_cert->get_fingerprint(pgp_cert);
-
- if (first)
- {
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, "List of PGP End Entity Certificates:");
- first = false;
- }
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, " userid: '%Y'", userid);
- whack_log(RC_COMMENT, " digest: %#B", &fingerprint);
-
- /* list validity */
- certificate->get_validity(certificate, &now, &created, &until);
- whack_log(RC_COMMENT, " created: %T", &created, utc);
- whack_log(RC_COMMENT, " until: %T %s%s", &until, utc,
- check_expiry(until, CA_CERT_WARNING_INTERVAL, TRUE),
- (until == TIME_32_BIT_SIGNED_MAX) ? " (expires never)":"");
-
- key = certificate->get_public_key(certificate);
- if (key)
- {
- chunk_t keyid;
-
- whack_log(RC_COMMENT, " pubkey: %N %4d bits%s",
- key_type_names, key->get_type(key),
- key->get_keysize(key),
- has_private_key(cert)? ", has private key" : "");
- if (key->get_fingerprint(key, KEYID_PUBKEY_INFO_SHA1, &keyid))
- {
- whack_log(RC_COMMENT, " keyid: %#B", &keyid);
- }
- if (key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &keyid))
- {
- whack_log(RC_COMMENT, " subjkey: %#B", &keyid);
- }
- }
- }
- cert = cert->next;
- }
-}
-
-/**
- * List all X.509 end certificates in a chained list
- */
-void list_x509_end_certs(bool utc)
-{
- list_x509cert_chain("End Entity", certs, X509_NONE, utc);
-}
-
-/**
- * list all X.509 and OpenPGP end certificates
- */
-void cert_list(bool utc)
-{
- list_x509_end_certs(utc);
- list_pgp_end_certs(utc);
-}
-
diff --git a/src/pluto/certs.h b/src/pluto/certs.h
deleted file mode 100644
index b31c4c3ed..000000000
--- a/src/pluto/certs.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* Certificate support for IKE authentication
- * Copyright (C) 2002-2009 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.
- */
-
-#ifndef _CERTS_H
-#define _CERTS_H
-
-#include <credentials/keys/private_key.h>
-#include <credentials/certificates/certificate.h>
-#include <credentials/certificates/x509.h>
-
-#include <freeswan.h>
-
-#include "defs.h"
-
-/* path definitions for private keys, end certs,
- * cacerts, attribute certs and crls
- */
-#define PRIVATE_KEY_PATH IPSEC_CONFDIR "/ipsec.d/private"
-#define HOST_CERT_PATH IPSEC_CONFDIR "/ipsec.d/certs"
-#define CA_CERT_PATH IPSEC_CONFDIR "/ipsec.d/cacerts"
-#define A_CERT_PATH IPSEC_CONFDIR "/ipsec.d/acerts"
-#define AA_CERT_PATH IPSEC_CONFDIR "/ipsec.d/aacerts"
-#define OCSP_CERT_PATH IPSEC_CONFDIR "/ipsec.d/ocspcerts"
-#define CRL_PATH IPSEC_CONFDIR "/ipsec.d/crls"
-#define REQ_PATH IPSEC_CONFDIR "/ipsec.d/reqs"
-
-/* advance warning of imminent expiry of
- * cacerts, public keys, and crls
- */
-#define CA_CERT_WARNING_INTERVAL 30 /* days */
-#define OCSP_CERT_WARNING_INTERVAL 30 /* days */
-#define PUBKEY_WARNING_INTERVAL 7 /* days */
-#define CRL_WARNING_INTERVAL 7 /* days */
-#define ACERT_WARNING_INTERVAL 1 /* day */
-
-/* access structure for a pluto certificate */
-
-typedef struct cert_t cert_t;
-
-struct cert_t {
- certificate_t *cert;
- cert_t *next;
- int count;
- bool smartcard;
-};
-
-/* used for initialization */
-extern const cert_t cert_empty;
-
-/* do not send certificate requests
- * flag set in plutomain.c and used in ipsec_doi.c
- */
-extern bool no_cr_send;
-
-extern cert_t* load_cert(char *filename, const char *label, x509_flag_t flags);
-extern cert_t* load_host_cert(char *filename);
-extern cert_t* load_ca_cert(char *filename);
-extern cert_t* cert_add(cert_t *cert);
-extern void cert_free(cert_t *cert);
-extern void cert_share(cert_t *cert);
-extern void cert_release(cert_t *cert);
-extern void cert_list(bool utc);
-extern cert_t* get_x509cert(identification_t *issuer, chunk_t keyid, cert_t* chain);
-
-#endif /* _CERTS_H */
-
-
diff --git a/src/pluto/connections.c b/src/pluto/connections.c
deleted file mode 100644
index 27cec40fc..000000000
--- a/src/pluto/connections.c
+++ /dev/null
@@ -1,4507 +0,0 @@
-/* information about connections between hosts and clients
- * Copyright (C) 1998-2002 D. Hugh Redelmeier.
- * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <string.h>
-#include <stdio.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <resolv.h>
-#include <arpa/nameser.h> /* missing from <resolv.h> on old systems */
-#include <sys/queue.h>
-
-#include <freeswan.h>
-#include "kameipsec.h"
-
-#include <hydra.h>
-#include <credentials/certificates/ac.h>
-#include <credentials/keys/private_key.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "myid.h"
-#include "x509.h"
-#include "ca.h"
-#include "crl.h"
-#include "certs.h"
-#include "ac.h"
-#include "smartcard.h"
-#include "fetch.h"
-#include "connections.h"
-#include "foodgroups.h"
-#include "demux.h"
-#include "state.h"
-#include "timer.h"
-#include "ipsec_doi.h" /* needs demux.h and state.h */
-#include "server.h"
-#include "kernel.h"
-#include "log.h"
-#include "keys.h"
-#include "adns.h" /* needs <resolv.h> */
-#include "dnskey.h" /* needs keys.h and adns.h */
-#include "whack.h"
-#include "alg_info.h"
-#include "ike_alg.h"
-#include "kernel_alg.h"
-#include "nat_traversal.h"
-#include "virtual.h"
-#include "whack_attribute.h"
-#include "modecfg.h"
-
-static void flush_pending_by_connection(connection_t *c); /* forward */
-
-static connection_t *connections = NULL;
-
-/* struct host_pair: a nexus of information about a pair of hosts.
- * A host is an IP address, UDP port pair. This is a debatable choice:
- * - should port be considered (no choice of port in standard)?
- * - should ID be considered (hard because not always known)?
- * - should IP address matter on our end (we don't know our end)?
- * Only oriented connections are registered.
- * Unoriented connections are kept on the unoriented_connections
- * linked list (using hp_next). For them, host_pair is NULL.
- */
-
-struct host_pair {
- struct {
- ip_address addr;
- u_int16_t port; /* host order */
- } me, him;
- bool initial_connection_sent;
- connection_t *connections; /* connections with this pair */
- struct pending *pending; /* awaiting Keying Channel */
- struct host_pair *next;
-};
-
-static struct host_pair *host_pairs = NULL;
-
-static connection_t *unoriented_connections = NULL;
-
-/**
- * Check if an id was instantiated by assigning to it the current IP address
- */
-bool his_id_was_instantiated(const connection_t *c)
-{
- if (c->kind != CK_INSTANCE)
- {
- return FALSE;
- }
- if (id_is_ipaddr(c->spd.that.id))
- {
- identification_t *host;
- bool equal;
-
- host = identification_create_from_sockaddr((sockaddr_t*)&c->spd.that.host_addr);
- equal = host->equals(host, c->spd.that.id);
- host->destroy(host);
- return equal;
- }
- else
- {
- return TRUE;
- }
-}
-
-/**
- * Check to see that IDs of peers match
- */
-bool same_peer_ids(const connection_t *c, const connection_t *d,
- identification_t *his_id)
-{
- return d->spd.this.id->equals(d->spd.this.id, c->spd.this.id) &&
- d->spd.that.id->equals(d->spd.that.id,
- his_id ? his_id : c->spd.that.id);
-}
-
-static struct host_pair *find_host_pair(const ip_address *myaddr,
- u_int16_t myport,
- const ip_address *hisaddr,
- u_int16_t hisport)
-{
- struct host_pair *p, *prev;
-
- /* default hisaddr to an appropriate any */
- if (hisaddr == NULL)
- hisaddr = aftoinfo(addrtypeof(myaddr))->any;
-
- if (nat_traversal_enabled)
- {
- /**
- * port is not relevant in host_pair. with nat_traversal we
- * always use pluto_port (500)
- */
- myport = pluto_port;
- hisport = pluto_port;
- }
-
- for (prev = NULL, p = host_pairs; p != NULL; prev = p, p = p->next)
- {
- if (sameaddr(&p->me.addr, myaddr) && p->me.port == myport
- && sameaddr(&p->him.addr, hisaddr) && p->him.port == hisport)
- {
- if (prev)
- {
- prev->next = p->next; /* remove p from list */
- p->next = host_pairs; /* and stick it on front */
- host_pairs = p;
- }
- break;
- }
- }
- return p;
-}
-
-/* find head of list of connections with this pair of hosts */
-static connection_t *find_host_pair_connections(const ip_address *myaddr,
- u_int16_t myport,
- const ip_address *hisaddr,
- u_int16_t hisport)
-{
- struct host_pair *hp = find_host_pair(myaddr, myport, hisaddr, hisport);
-
- if (nat_traversal_enabled && hp && hisaddr)
- {
- connection_t *c;
-
- for (c = hp->connections; c != NULL; c = c->hp_next)
- {
- if (c->spd.this.host_port == myport && c->spd.that.host_port == hisport)
- return c;
- }
- return NULL;
- }
- return hp == NULL? NULL : hp->connections;
-}
-
-static void connect_to_host_pair(connection_t *c)
-{
- if (oriented(*c))
- {
- struct host_pair *hp;
-
- ip_address his_addr = (c->spd.that.allow_any)
- ? *aftoinfo(addrtypeof(&c->spd.that.host_addr))->any
- : c->spd.that.host_addr;
-
- hp = find_host_pair(&c->spd.this.host_addr, c->spd.this.host_port
- , &his_addr, c->spd.that.host_port);
-
- if (hp == NULL)
- {
- /* no suitable host_pair -- build one */
- hp = malloc_thing(struct host_pair);
- hp->me.addr = c->spd.this.host_addr;
- hp->him.addr = his_addr;
- hp->me.port = nat_traversal_enabled ? pluto_port : c->spd.this.host_port;
- hp->him.port = nat_traversal_enabled ? pluto_port : c->spd.that.host_port;
- hp->initial_connection_sent = FALSE;
- hp->connections = NULL;
- hp->pending = NULL;
- hp->next = host_pairs;
- host_pairs = hp;
- }
- c->host_pair = hp;
- c->hp_next = hp->connections;
- hp->connections = c;
- }
- else
- {
- /* since this connection isn't oriented, we place it
- * in the unoriented_connections list instead.
- */
- c->host_pair = NULL;
- c->hp_next = unoriented_connections;
- unoriented_connections = c;
- }
-}
-
-/* find a connection by name.
- * If strict, don't accept a CK_INSTANCE.
- * Move the winner (if any) to the front.
- * If none is found, and strict, a diagnostic is logged to whack.
- */
-connection_t *con_by_name(const char *nm, bool strict)
-{
- connection_t *p, *prev;
-
- for (prev = NULL, p = connections; ; prev = p, p = p->ac_next)
- {
- if (p == NULL)
- {
- if (strict)
- whack_log(RC_UNKNOWN_NAME
- , "no connection named \"%s\"", nm);
- break;
- }
- if (streq(p->name, nm)
- && (!strict || p->kind != CK_INSTANCE))
- {
- if (prev)
- {
- prev->ac_next = p->ac_next; /* remove p from list */
- p->ac_next = connections; /* and stick it on front */
- connections = p;
- }
- break;
- }
- }
- return p;
-}
-
-void release_connection(connection_t *c, bool relations)
-{
- if (c->kind == CK_INSTANCE)
- {
- /* This does everything we need.
- * Note that we will be called recursively by delete_connection,
- * but kind will be CK_GOING_AWAY.
- */
- delete_connection(c, relations);
- }
- else
- {
- flush_pending_by_connection(c);
- delete_states_by_connection(c, relations);
- unroute_connection(c);
- }
-}
-
-/* Delete a connection */
-
-#define list_rm(etype, enext, e, ehead) { \
- etype **ep; \
- for (ep = &(ehead); *ep != (e); ep = &(*ep)->enext) \
- passert(*ep != NULL); /* we must not come up empty-handed */ \
- *ep = (e)->enext; \
- }
-
-
-void delete_connection(connection_t *c, bool relations)
-{
- modecfg_attribute_t *ca;
- connection_t *old_cur_connection;
- identification_t *client_id;
-
- old_cur_connection = cur_connection == c? NULL : cur_connection;
-#ifdef DEBUG
- lset_t old_cur_debugging = cur_debugging;
-#endif
-
- set_cur_connection(c);
-
- /* Must be careful to avoid circularity:
- * we mark c as going away so it won't get deleted recursively.
- */
- passert(c->kind != CK_GOING_AWAY);
- if (c->kind == CK_INSTANCE)
- {
- plog("deleting connection \"%s\" instance with peer %s {isakmp=#%lu/ipsec=#%lu}"
- , c->name
- , ip_str(&c->spd.that.host_addr)
- , c->newest_isakmp_sa, c->newest_ipsec_sa);
- c->kind = CK_GOING_AWAY;
- }
- else
- {
- plog("deleting connection");
- }
- release_connection(c, relations); /* won't delete c */
-
- if (c->kind == CK_GROUP)
- {
- delete_group(c);
- }
-
- /* free up any logging resources */
- perpeer_logfree(c);
-
- /* find and delete c from connections list */
- list_rm(connection_t, ac_next, c, connections);
- cur_connection = old_cur_connection;
-
- /* find and delete c from the host pair list */
- if (c->host_pair == NULL)
- {
- if (c->ikev1)
- {
- list_rm(connection_t, hp_next, c, unoriented_connections);
- }
- }
- else
- {
- struct host_pair *hp = c->host_pair;
-
- list_rm(connection_t, hp_next, c, hp->connections);
- c->host_pair = NULL; /* redundant, but safe */
-
- /* if there are no more connections with this host_pair
- * and we haven't even made an initial contact, let's delete
- * this guy in case we were created by an attempted DOS attack.
- */
- if (hp->connections == NULL
- && !hp->initial_connection_sent)
- {
- passert(hp->pending == NULL); /* ??? must deal with this! */
- list_rm(struct host_pair, next, hp, host_pairs);
- free(hp);
- }
- }
- if (c->kind != CK_GOING_AWAY)
- {
- free(c->spd.that.virt);
- }
-
- client_id = (c->xauth_identity) ? c->xauth_identity : c->spd.that.id;
-
- /* release virtual IP address lease if any */
- if (c->spd.that.modecfg && c->spd.that.pool &&
- !c->spd.that.host_srcip->is_anyaddr(c->spd.that.host_srcip))
- {
- hydra->attributes->release_address(hydra->attributes, c->spd.that.pool,
- c->spd.that.host_srcip, client_id);
- }
-
- /* release requested attributes if any */
- if (c->requested)
- {
- c->requested->destroy_function(c->requested,
- (void*)modecfg_attribute_destroy);
- }
-
- /* release other attributes if any */
- if (c->attributes)
- {
- while (c->attributes->remove_last(c->attributes, (void **)&ca) == SUCCESS)
- {
- hydra->attributes->release(hydra->attributes, ca->handler,
- client_id, ca->type, ca->value);
- modecfg_attribute_destroy(ca);
- }
- c->attributes->destroy(c->attributes);
- }
-
- if (c->kind != CK_GOING_AWAY)
- {
- whack_attr->del_pool(whack_attr, c->name);
- }
-
- /* free internal data */
-#ifdef DEBUG
- cur_debugging = old_cur_debugging;
-#endif
- free(c->name);
- DESTROY_IF(c->xauth_identity);
- DESTROY_IF(c->spd.this.id);
- DESTROY_IF(c->spd.this.ca);
- DESTROY_IF(c->spd.this.groups);
- DESTROY_IF(c->spd.this.host_srcip);
- free(c->spd.this.updown);
- free(c->spd.this.pool);
- DESTROY_IF(c->spd.that.id);
- DESTROY_IF(c->spd.that.ca);
- DESTROY_IF(c->spd.that.groups);
- DESTROY_IF(c->spd.that.host_srcip);
- free(c->spd.that.updown);
- free(c->spd.that.pool);
- if (c->requested_ca)
- {
- c->requested_ca->destroy_offset(c->requested_ca,
- offsetof(identification_t, destroy));
- }
-#ifdef ADNS
- gw_delref(&c->gw_info);
-#endif
- lock_certs_and_keys("delete_connection");
- cert_release(c->spd.this.cert);
- scx_release(c->spd.this.sc);
- cert_release(c->spd.that.cert);
- scx_release(c->spd.that.sc);
- unlock_certs_and_keys("delete_connection");
-
- alg_info_delref((struct alg_info **)&c->alg_info_esp);
- alg_info_delref((struct alg_info **)&c->alg_info_ike);
-
- free(c);
-}
-
-/* Delete connections with the specified name */
-void delete_connections_by_name(const char *name, bool strict)
-{
- connection_t *c = con_by_name(name, strict);
-
- for (; c != NULL; c = con_by_name(name, FALSE))
- delete_connection(c, FALSE);
-}
-
-void delete_every_connection(void)
-{
- while (connections)
- {
- delete_connection(connections, TRUE);
- }
-}
-
-void release_dead_interfaces(void)
-{
- struct host_pair *hp;
-
- for (hp = host_pairs; hp != NULL; hp = hp->next)
- {
- connection_t **pp
- , *p;
-
- for (pp = &hp->connections; (p = *pp) != NULL; )
- {
- if (p->interface->change == IFN_DELETE)
- {
- /* this connection's interface is going away */
- enum connection_kind k = p->kind;
-
- release_connection(p, TRUE);
-
- if (k <= CK_PERMANENT)
- {
- /* The connection should have survived release:
- * move it to the unoriented_connections list.
- */
- passert(p == *pp);
-
- p->interface = NULL;
-
- *pp = p->hp_next; /* advance *pp */
- p->host_pair = NULL;
- p->hp_next = unoriented_connections;
- unoriented_connections = p;
- }
- else
- {
- /* The connection should have vanished,
- * but the previous connection remains.
- */
- passert(p != *pp);
- }
- }
- else
- {
- pp = &p->hp_next; /* advance pp */
- }
- }
- }
-}
-
-/* adjust orientations of connections to reflect newly added interfaces */
-void check_orientations(void)
-{
- /* try to orient all the unoriented connections */
- {
- connection_t *c = unoriented_connections;
-
- unoriented_connections = NULL;
-
- while (c)
- {
- connection_t *nxt = c->hp_next;
-
- (void)orient(c);
- connect_to_host_pair(c);
- c = nxt;
- }
- }
-
- /* Check that no oriented connection has become double-oriented.
- * In other words, the far side must not match one of our new interfaces.
- */
- {
- struct iface *i;
-
- for (i = interfaces; i != NULL; i = i->next)
- {
- if (i->change == IFN_ADD)
- {
- struct host_pair *hp;
-
- for (hp = host_pairs; hp != NULL; hp = hp->next)
- {
- if (sameaddr(&hp->him.addr, &i->addr)
- && hp->him.port == pluto_port)
- {
- /* bad news: the whole chain of connections
- * hanging off this host pair has both sides
- * matching an interface.
- * We'll get rid of them, using orient and
- * connect_to_host_pair. But we'll be lazy
- * and not ditch the host_pair itself (the
- * cost of leaving it is slight and cannot
- * be induced by a foe).
- */
- connection_t *c = hp->connections;
-
- hp->connections = NULL;
- while (c)
- {
- connection_t *nxt = c->hp_next;
-
- c->interface = NULL;
- (void)orient(c);
- connect_to_host_pair(c);
- c = nxt;
- }
- }
- }
- }
- }
- }
-}
-
-static err_t default_end(struct end *e, ip_address *dflt_nexthop)
-{
- err_t ugh = NULL;
- int af = addrtypeof(&e->host_addr);
-
- if (af != AF_INET && af != AF_INET6)
- {
- return "unknown address family in default_end";
- }
-
- /* default ID to IP (but only if not NO_IP -- WildCard) */
- if (e->id->get_type(e->id) == ID_ANY && !isanyaddr(&e->host_addr))
- {
- e->id->destroy(e->id);
- e->id = identification_create_from_sockaddr((sockaddr_t*)&e->host_addr);
- e->has_id_wildcards = FALSE;
- }
-
- /* default nexthop to other side */
- if (isanyaddr(&e->host_nexthop))
- {
- e->host_nexthop = *dflt_nexthop;
- }
-
- /* default client to subnet containing only self
- * XXX This may mean that the client's address family doesn't match
- * tunnel_addr_family.
- */
- if (!e->has_client)
- {
- ugh = addrtosubnet(&e->host_addr, &e->client);
- }
- return ugh;
-}
-
-/* Format the topology of a connection end, leaving out defaults.
- * Largest left end looks like: client === host : port [ host_id ] --- hop
- * Note: if that==NULL, skip nexthop
- * Returns strlen of formated result (length excludes NUL at end).
- */
-size_t format_end(char *buf, size_t buf_len, const struct end *this,
- const struct end *that, bool is_left, lset_t policy)
-{
- char client[BUF_LEN];
- const char *client_sep = "";
- char protoport[sizeof(":255/65535")];
- const char *host = NULL;
- char host_space[ADDRTOT_BUF];
- char host_port[sizeof(":65535")];
- char host_id[BUF_LEN + 2];
- char hop[ADDRTOT_BUF];
- const char *hop_sep = "";
- const char *open_brackets = "";
- const char *close_brackets = "";
-
- if (isanyaddr(&this->host_addr))
- {
- switch (policy & (POLICY_GROUP | POLICY_OPPO))
- {
- case POLICY_GROUP:
- host = "%group";
- break;
- case POLICY_OPPO:
- host = "%opportunistic";
- break;
- case POLICY_GROUP | POLICY_OPPO:
- host = "%opportunisticgroup";
- break;
- default:
- host = "%any";
- break;
- }
- }
-
- client[0] = '\0';
-
- if (is_virtual_end(this) && isanyaddr(&this->host_addr))
- {
- host = "%virtual";
- }
-
- /* [client===] */
- if (this->has_client)
- {
- ip_address client_net, client_mask;
-
- networkof(&this->client, &client_net);
- maskof(&this->client, &client_mask);
- client_sep = "===";
-
- /* {client_subnet_wildcard} */
- if (this->has_client_wildcard)
- {
- open_brackets = "{";
- close_brackets = "}";
- }
-
- if (isanyaddr(&client_net) && isanyaddr(&client_mask)
- && (policy & (POLICY_GROUP | POLICY_OPPO)))
- {
- client_sep = ""; /* boring case */
- }
- else if (subnetisnone(&this->client))
- {
- strncpy(client, "?", sizeof(client));
- }
- else
- {
- subnettot(&this->client, 0, client, sizeof(client));
- }
- }
- else if (this->modecfg && this->host_srcip->is_anyaddr(this->host_srcip))
- {
- /* we are mode config client, or a server with a pool */
- client_sep = "===";
- client[0] = '%';
- strncpy(client+1, this->pool ?: "modecfg", sizeof(client)-1);
- }
-
- /* host */
- if (host == NULL)
- {
- addrtot(&this->host_addr, 0, host_space, sizeof(host_space));
- host = host_space;
- }
-
- host_port[0] = '\0';
- if (this->host_port != IKE_UDP_PORT)
- {
- snprintf(host_port, sizeof(host_port), ":%u", this->host_port);
- }
-
- /* payload portocol and port */
- protoport[0] = '\0';
- if (this->has_port_wildcard)
- {
- snprintf(protoport, sizeof(protoport), ":%u/%%any", this->protocol);
- }
- else if (this->port || this->protocol)
- {
- snprintf(protoport, sizeof(protoport), ":%u/%u", this->protocol
- , this->port);
- }
-
- /* id */
- snprintf(host_id, sizeof(host_id), "[%Y]", this->id);
-
- /* [---hop] */
- hop[0] = '\0';
- hop_sep = "";
- if (that && !sameaddr(&this->host_nexthop, &that->host_addr))
- {
- addrtot(&this->host_nexthop, 0, hop, sizeof(hop));
- hop_sep = "---";
- }
-
- if (is_left)
- {
- snprintf(buf, buf_len, "%s%s%s%s%s%s%s%s%s%s%s"
- , open_brackets, client, close_brackets, client_sep
- , this->allow_any? "%":""
- , host, host_port, host_id, protoport
- , hop_sep, hop);
- }
- else
- {
- snprintf(buf, buf_len, "%s%s%s%s%s%s%s%s%s%s%s"
- , hop, hop_sep
- , this->allow_any? "%":""
- , host, host_port, host_id, protoport, client_sep
- , open_brackets, client, close_brackets);
- }
- return strlen(buf);
-}
-
-/* format topology of a connection.
- * Two symmetric ends separated by ...
- */
-#define CONNECTION_BUF (2 * (END_BUF - 1) + 4)
-
-static size_t format_connection(char *buf, size_t buf_len,
- const connection_t *c,
- struct spd_route *sr)
-{
- size_t w = format_end(buf, buf_len, &sr->this, &sr->that, TRUE, LEMPTY);
-
- w += snprintf(buf + w, buf_len - w, "...");
- return w + format_end(buf + w, buf_len - w, &sr->that, &sr->this, FALSE, c->policy);
-}
-
-static void unshare_connection_strings(connection_t *c)
-{
- c->name = clone_str(c->name);
- if (c->xauth_identity)
- {
- c->xauth_identity = c->xauth_identity->clone(c->xauth_identity);
- }
- c->spd.this.id = c->spd.this.id->clone(c->spd.this.id);
- c->spd.this.pool = clone_str(c->spd.this.pool);
- c->spd.this.updown = clone_str(c->spd.this.updown);
- c->spd.this.host_srcip = c->spd.this.host_srcip->clone(c->spd.this.host_srcip);
- scx_share(c->spd.this.sc);
- cert_share(c->spd.this.cert);
- if (c->spd.this.ca)
- {
- c->spd.this.ca = c->spd.this.ca->clone(c->spd.this.ca);
- }
- if (c->spd.this.groups)
- {
- c->spd.this.groups = c->spd.this.groups->get_ref(c->spd.this.groups);
- }
- c->spd.that.id = c->spd.that.id->clone(c->spd.that.id);
- c->spd.that.pool = clone_str(c->spd.that.pool);
- c->spd.that.updown = clone_str(c->spd.that.updown);
- c->spd.that.host_srcip = c->spd.that.host_srcip->clone(c->spd.that.host_srcip);
- scx_share(c->spd.that.sc);
- cert_share(c->spd.that.cert);
- if (c->spd.that.ca)
- {
- c->spd.that.ca = c->spd.that.ca->clone(c->spd.that.ca);
- }
- if (c->spd.that.groups)
- {
- c->spd.that.groups = c->spd.that.groups->get_ref(c->spd.that.groups);
- }
-
- /* increment references to algo's */
- alg_info_addref((struct alg_info *)c->alg_info_esp);
- alg_info_addref((struct alg_info *)c->alg_info_ike);
-}
-
-static void load_end_certificate(char *filename, struct end *dst)
-{
- time_t notBefore, notAfter;
- cert_t *cert = NULL;
- certificate_t *certificate;
- bool cached_cert = FALSE;
-
- /* initialize end certificate */
- dst->cert = NULL;
-
- /* initialize smartcard info record */
- dst->sc = NULL;
-
- if (filename)
- {
- if (scx_on_smartcard(filename))
- {
- /* load cert from smartcard */
- cert = scx_load_cert(filename, &dst->sc, &cached_cert);
- }
- else
- {
- /* load cert from file */
- cert = load_host_cert(filename);
- }
- }
-
- if (cert)
- {
- certificate = cert->cert;
-
- if (dst->id->get_type(dst->id) == ID_ANY ||
- !certificate->has_subject(certificate, dst->id))
- {
- plog( " id '%Y' not confirmed by certificate, defaulting to '%Y'",
- dst->id, certificate->get_subject(certificate));
- dst->id->destroy(dst->id);
- dst->id = certificate->get_subject(certificate);
- dst->id = dst->id->clone(dst->id);
- }
-
- if (cached_cert)
- {
- dst->cert = cert;
- }
- else
- {
- if (!certificate->get_validity(certificate, NULL, &notBefore, &notAfter))
- {
- plog("certificate is invalid (valid from %T to %T)",
- &notBefore, FALSE, &notAfter, FALSE);
- cert_free(cert);
- return;
- }
- DBG(DBG_CONTROL,
- DBG_log("certificate is valid")
- )
- add_public_key_from_cert(cert, notAfter, DAL_LOCAL);
- dst->cert = cert_add(cert);
- }
- certificate = dst->cert->cert;
-
- /* if no CA is defined, use issuer as default */
- if (dst->ca == NULL && certificate->get_type(certificate) == CERT_X509)
- {
- identification_t *issuer;
-
- issuer = certificate->get_issuer(certificate);
- dst->ca = issuer->clone(issuer);
- }
-
- /* cache the certificate that was last retrieved from the smartcard */
- if (dst->sc)
- {
- if (!dst->sc->last_cert ||
- !certificate->equals(certificate, dst->sc->last_cert->cert))
- {
- lock_certs_and_keys("load_end_certificates");
- cert_release(dst->sc->last_cert);
- dst->sc->last_cert = dst->cert;
- cert_share(dst->cert);
- unlock_certs_and_keys("load_end_certificates");
- }
- time(&dst->sc->last_load);
- }
- }
- scx_share(dst->sc);
- cert_share(dst->cert);
-}
-
-static bool extract_end(struct end *dst, const whack_end_t *src,
- const char *name, bool is_left)
-{
- bool same_ca = FALSE;
-
- dst->is_left = is_left;
- dst->id = identification_create_from_string(src->id);
- dst->ca = NULL;
-
- /* decode CA distinguished name, if any */
- if (src->ca)
- {
- if streq(src->ca, "%same")
- {
- same_ca = TRUE;
- }
- else if (!streq(src->ca, "%any"))
- {
- dst->ca = identification_create_from_string(src->ca);
- if (dst->ca->get_type(dst->ca) != ID_DER_ASN1_DN)
- {
- plog("bad CA string '%s', ignored", src->ca);
- dst->ca->destroy(dst->ca);
- dst->ca = NULL;
- }
- }
- }
-
- /* load local end certificate and extract ID, if any */
- load_end_certificate(src->cert, dst);
-
- /* does id has wildcards? */
- dst->has_id_wildcards = dst->id->contains_wildcards(dst->id);
-
- /* decode group attributes, if any */
- if (src->groups)
- {
- dst->groups = ietf_attributes_create_from_string(src->groups);
- }
-
- /* the rest is simple copying of corresponding fields */
- dst->host_addr = src->host_addr;
- dst->host_nexthop = src->host_nexthop;
- dst->host_srcip = host_create_from_sockaddr((sockaddr_t*)&src->host_srcip);
- dst->has_natip = src->has_natip;
- dst->client = src->client;
- dst->protocol = src->protocol;
- dst->port = src->port;
- dst->has_port_wildcard = src->has_port_wildcard;
- dst->key_from_DNS_on_demand = src->key_from_DNS_on_demand;
- dst->has_client = src->has_client;
- dst->has_client_wildcard = src->has_client_wildcard;
- dst->modecfg = src->modecfg;
- dst->hostaccess = src->hostaccess;
- dst->allow_any = src->allow_any;
- dst->sendcert = src->sendcert;
- dst->updown = clone_str(src->updown);
- dst->host_port = src->host_port;
-
- /* if the sourceip netmask is zero a named pool exists */
- if (src->sourceip_mask == 0)
- {
- dst->pool = clone_str(src->sourceip);
- }
-
- /* if host sourceip is defined but no client is present
- * behind the host then set client to sourceip/32
- */
- if (!dst->host_srcip->is_anyaddr(dst->host_srcip) &&
- !dst->has_natip && !dst->has_client)
- {
- ip_address addr;
- err_t ugh;
-
- addr = *(ip_address*)dst->host_srcip->get_sockaddr(dst->host_srcip);
- ugh = addrtosubnet(&addr, &dst->client);
-
- if (ugh)
- {
- plog("could not assign host sourceip to client subnet");
- }
- else
- {
- dst->has_client = TRUE;
- }
- }
- return same_ca;
-}
-
-static bool check_connection_end(const whack_end_t *this,
- const whack_end_t *that,
- const whack_message_t *wm)
-{
- if (wm->addr_family != addrtypeof(&this->host_addr)
- || wm->addr_family != addrtypeof(&this->host_nexthop)
- || (this->has_client? wm->tunnel_addr_family : wm->addr_family)
- != subnettypeof(&this->client)
- || subnettypeof(&this->client) != subnettypeof(&that->client))
- {
- /* this should have been diagnosed by whack, so we need not be clear
- * !!! overloaded use of RC_CLASH
- */
- loglog(RC_CLASH, "address family inconsistency in connection");
- return FALSE;
- }
-
- if (isanyaddr(&that->host_addr))
- {
- /* other side is wildcard: we must check if other conditions met */
- if (isanyaddr(&this->host_addr))
- {
- loglog(RC_ORIENT, "connection must specify host IP address for our side");
- return FALSE;
- }
- }
-
- if (this->virt && (!isanyaddr(&this->host_addr) || this->has_client))
- {
- loglog(RC_CLASH,
- "virtual IP must only be used with %%any and without client");
- return FALSE;
- }
-
- return TRUE; /* happy */
-}
-
-connection_t *find_connection_by_reqid(uint32_t reqid)
-{
- connection_t *c;
-
- reqid &= ~3;
- for (c = connections; c != NULL; c = c->ac_next)
- {
- if (c->spd.reqid == reqid)
- {
- return c;
- }
- }
-
- return NULL;
-}
-
-static uint32_t gen_reqid(void)
-{
- uint32_t start;
- static uint32_t reqid = IPSEC_MANUAL_REQID_MAX & ~3;
-
- start = reqid;
- do {
- reqid += 4;
- if (reqid == 0)
- {
- reqid = (IPSEC_MANUAL_REQID_MAX & ~3) + 4;
- }
- if (!find_connection_by_reqid(reqid))
- {
- return reqid;
- }
- } while (reqid != start);
-
- exit_log("unable to allocate reqid");
- return 0; /* never reached ... */
-}
-
-void add_connection(const whack_message_t *wm)
-{
- if (con_by_name(wm->name, FALSE) != NULL)
- {
- loglog(RC_DUPNAME, "attempt to redefine connection \"%s\"", wm->name);
- }
- else if (wm->right.protocol != wm->left.protocol)
- {
- /* this should haven been diagnosed by whack
- * !!! overloaded use of RC_CLASH
- */
- loglog(RC_CLASH, "the protocol must be the same for leftport and rightport");
- }
- else if (check_connection_end(&wm->right, &wm->left, wm)
- && check_connection_end(&wm->left, &wm->right, wm))
- {
- bool same_rightca, same_leftca;
- connection_t *c = malloc_thing(connection_t);
-
- zero(c);
- c->name = clone_str(wm->name);
- c->ikev1 = wm->ikev1;
- c->policy = wm->policy;
-
- if ((c->policy & POLICY_COMPRESS) && !can_do_IPcomp)
- {
- loglog(RC_COMMENT
- , "ignoring --compress in \"%s\" because kernel does not support IPCOMP"
- , c->name);
- }
-
- if (wm->esp)
- {
- DBG(DBG_CONTROL,
- DBG_log("from whack: got --esp=%s", wm->esp ? wm->esp: "NULL")
- )
- c->alg_info_esp = alg_info_esp_create_from_str(wm->esp? wm->esp : "");
-
- DBG(DBG_CRYPT|DBG_CONTROL,
- static char buf[BUF_LEN]="<NULL>";
-
- if (c->alg_info_esp)
- {
- alg_info_snprint(buf, sizeof(buf)
- ,(struct alg_info *)c->alg_info_esp);
- }
- DBG_log("esp proposal: %s", buf);
- )
- if (c->alg_info_esp)
- {
- if (c->alg_info_esp->alg_info_cnt == 0)
- {
- loglog(RC_LOG_SERIOUS, "got 0 esp transforms");
- }
- }
- else
- {
- loglog(RC_LOG_SERIOUS, "syntax error in esp string");
- }
- }
-
- if (wm->ike)
- {
- DBG(DBG_CONTROL,
- DBG_log("from whack: got --ike=%s", wm->ike ? wm->ike: "NULL")
- )
- c->alg_info_ike= alg_info_ike_create_from_str(wm->ike? wm->ike : "");
-
- DBG(DBG_CRYPT|DBG_CONTROL,
- static char buf[BUF_LEN]="<NULL>";
-
- if (c->alg_info_ike)
- {
- alg_info_snprint(buf, sizeof(buf)
- , (struct alg_info *)c->alg_info_ike);
- }
- DBG_log("ike proposal: %s", buf);
- )
- if (c->alg_info_ike)
- {
- if (c->alg_info_ike->alg_info_cnt == 0)
- {
- loglog(RC_LOG_SERIOUS, "got 0 ike transforms");
- }
- }
- else
- {
- loglog(RC_LOG_SERIOUS, "syntax error in ike string");
- }
- }
-
- if (wm->xauth_identity)
- {
- c->xauth_identity
- = identification_create_from_string(wm->xauth_identity);
- }
-
- c->sa_ike_life_seconds = wm->sa_ike_life_seconds;
- c->sa_ipsec_life_seconds = wm->sa_ipsec_life_seconds;
- c->sa_rekey_margin = wm->sa_rekey_margin;
- c->sa_rekey_fuzz = wm->sa_rekey_fuzz;
- c->sa_keying_tries = wm->sa_keying_tries;
-
- /* RFC 3706 DPD */
- c->dpd_delay = wm->dpd_delay;
- c->dpd_timeout = wm->dpd_timeout;
- c->dpd_action = wm->dpd_action;
-
- c->addr_family = wm->addr_family;
- c->tunnel_addr_family = wm->tunnel_addr_family;
-
- c->requested_ca = NULL;
- same_leftca = extract_end(&c->spd.this, &wm->left, wm->name, TRUE);
- same_rightca = extract_end(&c->spd.that, &wm->right, wm->name, FALSE);
-
- if (same_rightca && c->spd.this.ca)
- {
- c->spd.that.ca = c->spd.this.ca->clone(c->spd.this.ca);
- }
- else if (same_leftca && c->spd.that.ca)
- {
- c->spd.this.ca = c->spd.that.ca->clone(c->spd.that.ca);
- }
-
- default_end(&c->spd.this, &c->spd.that.host_addr);
- default_end(&c->spd.that, &c->spd.this.host_addr);
-
- /* force any wildcard host IP address, any wildcard subnet
- * or any wildcard ID to that end
- */
- if (isanyaddr(&c->spd.this.host_addr) || c->spd.this.has_client_wildcard
- || c->spd.this.has_port_wildcard || c->spd.this.has_id_wildcards
- || c->spd.this.allow_any)
- {
- struct end t = c->spd.this;
-
- c->spd.this = c->spd.that;
- c->spd.that = t;
- }
-
- c->spd.next = NULL;
- c->spd.reqid = wm->reqid ?: gen_reqid();
-
- c->spd.mark_in.value = wm->mark_in.value;
- c->spd.mark_in.mask = wm->mark_in.mask;
- c->spd.mark_out.value = wm->mark_out.value;
- c->spd.mark_out.mask = wm->mark_out.mask;
-
- /* set internal fields */
- c->instance_serial = 0;
- c->ac_next = connections;
- connections = c;
- c->interface = NULL;
- c->spd.routing = RT_UNROUTED;
- c->newest_isakmp_sa = SOS_NOBODY;
- c->newest_ipsec_sa = SOS_NOBODY;
- c->spd.eroute_owner = SOS_NOBODY;
-
- if (c->policy & POLICY_GROUP)
- {
- c->kind = CK_GROUP;
- add_group(c);
- }
- else if ((isanyaddr(&c->spd.that.host_addr) && !NEVER_NEGOTIATE(c->policy))
- || c->spd.that.has_client_wildcard || c->spd.that.has_port_wildcard
- || c->spd.that.has_id_wildcards || c->spd.that.allow_any)
- {
- /* Opportunistic or Road Warrior or wildcard client subnet
- * or wildcard ID */
- c->kind = CK_TEMPLATE;
- }
- else
- {
- c->kind = CK_PERMANENT;
- }
- set_policy_prio(c); /* must be after kind is set */
-
-#ifdef DEBUG
- c->extra_debugging = wm->debugging;
-#endif
-
- c->gw_info = NULL;
-
- passert(!(wm->left.virt && wm->right.virt));
- if (wm->left.virt || wm->right.virt)
- {
- passert(isanyaddr(&c->spd.that.host_addr));
- c->spd.that.virt = create_virtual(c,
- wm->left.virt ? wm->left.virt : wm->right.virt);
- if (c->spd.that.virt)
- c->spd.that.has_client = TRUE;
- }
-
- (void)orient(c);
-
- /* if rightsourceip defines a subnet then create an in-memory pool */
- if (whack_attr->add_pool(whack_attr, c->name,
- c->spd.this.is_left ? &wm->right : &wm->left))
- {
- c->spd.that.pool = clone_str(c->name);
- c->spd.that.modecfg = TRUE;
- c->spd.that.has_client = FALSE;
- /* reset the host_srcip so that it gets assigned in modecfg */
- DESTROY_IF(c->spd.that.host_srcip);
- c->spd.that.host_srcip = host_create_any(AF_INET);
- }
-
- if (c->ikev1)
- {
- connect_to_host_pair(c);
- }
-
- /* log all about this connection */
- plog("added connection description \"%s\"", c->name);
- DBG(DBG_CONTROL,
- char topo[BUF_LEN];
-
- (void) format_connection(topo, sizeof(topo), c, &c->spd);
-
- DBG_log("%s", topo);
-
- /* Make sure that address families can be correctly inferred
- * from printed ends.
- */
- passert(c->addr_family == addrtypeof(&c->spd.this.host_addr)
- && c->addr_family == addrtypeof(&c->spd.this.host_nexthop)
- && (c->spd.this.has_client? c->tunnel_addr_family : c->addr_family)
- == subnettypeof(&c->spd.this.client)
-
- && c->addr_family == addrtypeof(&c->spd.that.host_addr)
- && c->addr_family == addrtypeof(&c->spd.that.host_nexthop)
- && (c->spd.that.has_client? c->tunnel_addr_family : c->addr_family)
- == subnettypeof(&c->spd.that.client));
-
- DBG_log("ike_life: %lus; ipsec_life: %lus; rekey_margin: %lus;"
- " rekey_fuzz: %lu%%; keyingtries: %lu; policy: %s"
- , (unsigned long) c->sa_ike_life_seconds
- , (unsigned long) c->sa_ipsec_life_seconds
- , (unsigned long) c->sa_rekey_margin
- , (unsigned long) c->sa_rekey_fuzz
- , (unsigned long) c->sa_keying_tries
- , prettypolicy(c->policy));
- );
- }
-}
-
-/* Derive a template connection from a group connection and target.
- * Similar to instantiate(). Happens at whack --listen.
- * Returns name of new connection. May be NULL.
- * Caller is responsible for freeing.
- */
-char *add_group_instance(connection_t *group, const ip_subnet *target)
-{
- char namebuf[100], targetbuf[SUBNETTOT_BUF];
- connection_t *t;
- char *name = NULL;
-
- passert(group->kind == CK_GROUP);
- passert(oriented(*group));
-
- /* manufacture a unique name for this template */
- subnettot(target, 0, targetbuf, sizeof(targetbuf));
- snprintf(namebuf, sizeof(namebuf), "%s#%s", group->name, targetbuf);
-
- if (con_by_name(namebuf, FALSE) != NULL)
- {
- loglog(RC_DUPNAME, "group name + target yields duplicate name \"%s\""
- , namebuf);
- }
- else
- {
- t = clone_thing(*group);
- t->name = namebuf;
- unshare_connection_strings(t);
- name = clone_str(t->name);
- t->spd.that.client = *target;
- t->policy &= ~(POLICY_GROUP | POLICY_GROUTED);
- t->kind = isanyaddr(&t->spd.that.host_addr) && !NEVER_NEGOTIATE(t->policy)
- ? CK_TEMPLATE : CK_INSTANCE;
-
- /* reset log file info */
- t->log_file_name = NULL;
- t->log_file = NULL;
- t->log_file_err = FALSE;
-
- t->spd.reqid = gen_reqid();
-
- if (t->spd.that.virt)
- {
- DBG_log("virtual_ip not supported in group instance");
- t->spd.that.virt = NULL;
- }
-
- /* add to connections list */
- t->ac_next = connections;
- connections = t;
-
- /* same host_pair as parent: stick after parent on list */
- group->hp_next = t;
-
- /* route if group is routed */
- if (group->policy & POLICY_GROUTED)
- {
- if (!trap_connection(t))
- whack_log(RC_ROUTE, "could not route");
- }
- }
- return name;
-}
-
-/* an old target has disappeared for a group: delete instance */
-void remove_group_instance(const connection_t *group USED_BY_DEBUG,
- const char *name)
-{
- passert(group->kind == CK_GROUP);
- passert(oriented(*group));
-
- delete_connections_by_name(name, FALSE);
-}
-
-/* Common part of instantiating a Road Warrior or Opportunistic connection.
- * his_id can be used to carry over an ID discovered in Phase 1.
- * It must not disagree with the one in c, but if that is unspecified,
- * the new connection will use his_id.
- * If his_id is NULL, and c.that.id is uninstantiated (ID_ANY), the
- * new connection will continue to have an uninstantiated that.id.
- * Note: instantiation does not affect port numbers.
- *
- * Note that instantiate can only deal with a single SPD/eroute.
- */
-static connection_t *instantiate(connection_t *c, const ip_address *him,
- u_int16_t his_port, identification_t *his_id)
-{
- connection_t *d;
-
- passert(c->kind == CK_TEMPLATE);
- passert(c->spd.next == NULL);
-
- c->instance_serial++;
- d = clone_thing(*c);
- d->spd.that.allow_any = FALSE;
-
- if (his_id)
- {
- d->spd.that.id = his_id;
- d->spd.that.has_id_wildcards = FALSE;
- }
- unshare_connection_strings(d);
- if (d->spd.this.groups)
- {
- d->spd.this.groups = d->spd.this.groups->get_ref(d->spd.this.groups);
- }
- if (d->spd.that.groups)
- {
- d->spd.that.groups = d->spd.that.groups->get_ref(d->spd.that.groups);
- }
- d->kind = CK_INSTANCE;
-
- passert(oriented(*d));
- d->spd.that.host_addr = *him;
- setportof(htons(c->spd.that.port), &d->spd.that.host_addr);
-
- if (his_port) d->spd.that.host_port = his_port;
-
- default_end(&d->spd.that, &d->spd.this.host_addr);
-
- /* We cannot guess what our next_hop should be, but if it was
- * explicitly specified as 0.0.0.0, we set it to be him.
- * (whack will not allow nexthop to be elided in RW case.)
- */
- default_end(&d->spd.this, &d->spd.that.host_addr);
- d->spd.next = NULL;
- d->spd.reqid = gen_reqid();
-
- /* set internal fields */
- d->ac_next = connections;
- connections = d;
- d->spd.routing = RT_UNROUTED;
- d->newest_isakmp_sa = SOS_NOBODY;
- d->newest_ipsec_sa = SOS_NOBODY;
- d->spd.eroute_owner = SOS_NOBODY;
-
- /* reset log file info */
- d->log_file_name = NULL;
- d->log_file = NULL;
- d->log_file_err = FALSE;
-
- connect_to_host_pair(d);
-
- if (sameaddr(&d->spd.that.host_addr, &d->spd.this.host_nexthop))
- {
- d->spd.this.host_nexthop = *him;
- }
- return d;
-}
-
-connection_t *rw_instantiate(connection_t *c, const ip_address *him,
- u_int16_t his_port, const ip_subnet *his_net,
- identification_t *his_id)
-{
- connection_t *d = instantiate(c, him, his_port, his_id);
-
- if (d && his_net && is_virtual_connection(c))
- {
- d->spd.that.client = *his_net;
- d->spd.that.virt = NULL;
- if (subnetishost(his_net) && addrinsubnet(him, his_net))
- d->spd.that.has_client = FALSE;
- }
-
- if (d->policy & POLICY_OPPO)
- {
- /* This must be before we know the client addresses.
- * Fill in one that is impossible. This prevents anyone else from
- * trying to use this connection to get to a particular client
- */
- d->spd.that.client = *aftoinfo(subnettypeof(&d->spd.that.client))->none;
- }
- DBG(DBG_CONTROL
- , DBG_log("instantiated \"%s\" for %s" , d->name, ip_str(him)));
- return d;
-}
-
-#ifdef ADNS
-
-connection_t *oppo_instantiate(connection_t *c, const ip_address *him,
- identification_t *his_id, struct gw_info *gw,
- const ip_address *our_client USED_BY_DEBUG,
- const ip_address *peer_client)
-{
- connection_t *d = instantiate(c, him, 0, his_id);
-
- passert(d->spd.next == NULL);
-
- /* fill in our client side */
- if (d->spd.this.has_client)
- {
- /* there was a client in the abstract connection
- * so we demand that the required client is within that subnet.
- */
- passert(addrinsubnet(our_client, &d->spd.this.client));
- happy(addrtosubnet(our_client, &d->spd.this.client));
- /* opportunistic connections do not use port selectors */
- setportof(0, &d->spd.this.client.addr);
- }
- else
- {
- /* there was no client in the abstract connection
- * so we demand that the required client be the host
- */
- passert(sameaddr(our_client, &d->spd.this.host_addr));
- }
-
- /* fill in peer's client side.
- * If the client is the peer, excise the client from the connection.
- */
- passert((d->policy & POLICY_OPPO)
- && addrinsubnet(peer_client, &d->spd.that.client));
- happy(addrtosubnet(peer_client, &d->spd.that.client));
- /* opportunistic connections do not use port selectors */
- setportof(0, &d->spd.that.client.addr);
-
- if (sameaddr(peer_client, &d->spd.that.host_addr))
- d->spd.that.has_client = FALSE;
-
- passert(d->gw_info == NULL);
- gw_addref(gw);
- d->gw_info = gw;
-
- /* Adjust routing if something is eclipsing c.
- * It must be a %hold for us (hard to passert this).
- * If there was another instance eclipsing, we'd be using it.
- */
- if (c->spd.routing == RT_ROUTED_ECLIPSED)
- d->spd.routing = RT_ROUTED_PROSPECTIVE;
-
- /* Remember if the template is routed:
- * if so, this instance applies for initiation
- * even if it is created for responding.
- */
- if (routed(c->spd.routing))
- d->instance_initiation_ok = TRUE;
-
- DBG(DBG_CONTROL,
- char topo[BUF_LEN];
-
- (void) format_connection(topo, sizeof(topo), d, &d->spd);
- DBG_log("instantiated \"%s\": %s", d->name, topo);
- );
- return d;
-}
-
-#endif /* ADNS */
-
-/* priority formatting */
-void fmt_policy_prio(policy_prio_t pp, char buf[POLICY_PRIO_BUF])
-{
- if (pp == BOTTOM_PRIO)
- {
- snprintf(buf, POLICY_PRIO_BUF, "0");
- }
- else
- {
- snprintf(buf, POLICY_PRIO_BUF, "%lu,%lu"
- , pp>>16, (pp & ~(~(policy_prio_t)0 << 16)) >> 8);
- }
-}
-
-/* Format any information needed to identify an instance of a connection.
- * Fills any needed information into buf which MUST be big enough.
- * Road Warrior: peer's IP address
- * Opportunistic: [" " myclient "==="] " ..." peer ["===" hisclient] '\0'
- */
-static size_t fmt_client(const ip_subnet *client, const ip_address *gw,
- const char *prefix, char buf[ADDRTOT_BUF])
-{
- if (subnetisaddr(client, gw))
- {
- buf[0] = '\0'; /* compact denotation for "self" */
- }
- else
- {
- char *ap;
-
- strcpy(buf, prefix);
- ap = buf + strlen(prefix);
- if (subnetisnone(client))
- strcpy(ap, "?"); /* unknown */
- else
- subnettot(client, 0, ap, SUBNETTOT_BUF);
- }
- return strlen(buf);
-}
-
-void fmt_conn_instance(const connection_t *c, char buf[CONN_INST_BUF])
-{
- char *p = buf;
-
- *p = '\0';
-
- if (c->kind == CK_INSTANCE)
- {
- if (c->instance_serial != 0)
- {
- snprintf(p, CONN_INST_BUF, "[%lu]", c->instance_serial);
- p += strlen(p);
- }
-
- if (c->policy & POLICY_OPPO)
- {
- size_t w = fmt_client(&c->spd.this.client, &c->spd.this.host_addr, " ", p);
-
- p += w;
-
- strcpy(p, w == 0? " ..." : "=== ...");
- p += strlen(p);
-
- addrtot(&c->spd.that.host_addr, 0, p, ADDRTOT_BUF);
- p += strlen(p);
-
- (void) fmt_client(&c->spd.that.client, &c->spd.that.host_addr, "===", p);
- }
- else
- {
- *p++ = ' ';
- addrtot(&c->spd.that.host_addr, 0, p, ADDRTOT_BUF);
-#
- if (c->spd.that.host_port != pluto_port)
- {
- p += strlen(p);
- sprintf(p, ":%d", c->spd.that.host_port);
- }
- }
- }
-}
-
-/* Find an existing connection for a trapped outbound packet.
- * This is attempted before we bother with gateway discovery.
- * + this connection is routed or instance_of_routed_template
- * (i.e. approved for on-demand)
- * + this subnet contains our_client (or we are our_client)
- * + that subnet contains peer_client (or peer is peer_client)
- * + don't care about Phase 1 IDs (we don't know)
- * Note: result may still need to be instantiated.
- * The winner has the highest policy priority.
- *
- * If there are several with that priority, we give preference to
- * the first one that is an instance.
- *
- * See also build_outgoing_opportunistic_connection.
- */
-connection_t *find_connection_for_clients(struct spd_route **srp,
- const ip_address *our_client,
- const ip_address *peer_client,
- int transport_proto)
-{
- connection_t *c = connections, *best = NULL;
- policy_prio_t best_prio = BOTTOM_PRIO;
- struct spd_route *sr;
- struct spd_route *best_sr = NULL;
- int our_port = ntohs(portof(our_client));
- int peer_port = ntohs(portof(peer_client));
-
- passert(!isanyaddr(our_client) && !isanyaddr(peer_client));
-#ifdef DEBUG
- if (DBGP(DBG_CONTROL))
- {
- char ocb[ADDRTOT_BUF], pcb[ADDRTOT_BUF];
-
- addrtot(our_client, 0, ocb, sizeof(ocb));
- addrtot(peer_client, 0, pcb, sizeof(pcb));
- DBG_log("find_connection: "
- "looking for policy for connection: %s:%d/%d -> %s:%d/%d"
- , ocb, transport_proto, our_port, pcb, transport_proto, peer_port);
- }
-#endif /* DEBUG */
-
- for (c = connections; c != NULL; c = c->ac_next)
- {
- if (c->kind == CK_GROUP)
- {
- continue;
- }
-
- for (sr = &c->spd; best!=c && sr; sr = sr->next)
- {
- if ((routed(sr->routing) || c->instance_initiation_ok)
- && addrinsubnet(our_client, &sr->this.client)
- && addrinsubnet(peer_client, &sr->that.client)
- && addrinsubnet(peer_client, &sr->that.client)
- && (!sr->this.protocol || transport_proto == sr->this.protocol)
- && (!sr->this.port || our_port == sr->this.port)
- && (!sr->that.port || peer_port == sr->that.port))
- {
- char cib[CONN_INST_BUF];
- char cib2[CONN_INST_BUF];
-
- policy_prio_t prio = 8 * (c->prio + (c->kind == CK_INSTANCE))
- + 2 * (sr->this.port == our_port)
- + 2 * (sr->that.port == peer_port)
- + (sr->this.protocol == transport_proto);
-
-#ifdef DEBUG
- if (DBGP(DBG_CONTROL|DBG_CONTROLMORE))
- {
- char c_ocb[SUBNETTOT_BUF], c_pcb[SUBNETTOT_BUF];
-
- subnettot(&c->spd.this.client, 0, c_ocb, sizeof(c_ocb));
- subnettot(&c->spd.that.client, 0, c_pcb, sizeof(c_pcb));
- DBG_log("find_connection: conn \"%s\"%s has compatible peers: %s->%s [pri: %ld]"
- , c->name
- , (fmt_conn_instance(c, cib), cib)
- , c_ocb, c_pcb, prio);
- }
-#endif /* DEBUG */
-
- if (best == NULL)
- {
- best = c;
- best_sr = sr;
- best_prio = prio;
- }
-
- DBG(DBG_CONTROLMORE,
- DBG_log("find_connection: "
- "comparing best \"%s\"%s [pri:%ld]{%p} (child %s) to \"%s\"%s [pri:%ld]{%p} (child %s)"
- , best->name
- , (fmt_conn_instance(best, cib), cib)
- , best_prio
- , best
- , (best->policy_next ? best->policy_next->name : "none")
- , c->name
- , (fmt_conn_instance(c, cib2), cib2)
- , prio
- , c
- , (c->policy_next ? c->policy_next->name : "none")));
-
- if (prio > best_prio)
- {
- best = c;
- best_sr = sr;
- best_prio = prio;
- }
- }
- }
- }
-
- if (best && NEVER_NEGOTIATE(best->policy))
- {
- best = NULL;
- }
- if (srp && best)
- {
- *srp = best_sr;
- }
-
-#ifdef DEBUG
- if (DBGP(DBG_CONTROL))
- {
- if (best)
- {
- char cib[CONN_INST_BUF];
- DBG_log("find_connection: concluding with \"%s\"%s [pri:%ld]{%p} kind=%s"
- , best->name
- , (fmt_conn_instance(best, cib), cib)
- , best_prio
- , best
- , enum_name(&connection_kind_names, best->kind));
- } else {
- DBG_log("find_connection: concluding with empty");
- }
- }
-#endif /* DEBUG */
-
- return best;
-}
-
-#ifdef ADNS
-
-/* Find and instantiate a connection for an outgoing Opportunistic connection.
- * We've already discovered its gateway.
- * We look for a the connection such that:
- * + this is one of our interfaces
- * + this subnet contains our_client (or we are our_client)
- * (we will specialize the client). We prefer the smallest such subnet.
- * + that subnet contains peer_clent (we will specialize the client).
- * We prefer the smallest such subnet.
- * + is opportunistic
- * + that peer is NO_IP
- * + don't care about Phase 1 IDs (probably should be default)
- * We could look for a connection that already had the desired peer
- * (rather than NO_IP) specified, but it doesn't seem worth the
- * bother.
- *
- * We look for the routed policy applying to the narrowest subnets.
- * We only succeed if we find such a policy AND it is satisfactory.
- *
- * The body of the inner loop is a lot like that in
- * find_connection_for_clients. In this case, we know the gateways
- * that we need to instantiate an opportunistic connection.
- */
-connection_t *build_outgoing_opportunistic_connection(struct gw_info *gw,
- const ip_address *our_client,
- const ip_address *peer_client)
-{
- struct iface *p;
- connection_t *best = NULL;
- struct spd_route *sr, *bestsr;
- char ocb[ADDRTOT_BUF], pcb[ADDRTOT_BUF];
-
- addrtot(our_client, 0, ocb, sizeof(ocb));
- addrtot(peer_client, 0, pcb, sizeof(pcb));
-
- /* for each of our addresses... */
- for (p = interfaces; p != NULL; p = p->next)
- {
- /* go through those connections with our address and NO_IP as hosts
- * We cannot know what port the peer would use, so we assume
- * that it is pluto_port (makes debugging easier).
- */
- connection_t *c = find_host_pair_connections(&p->addr, pluto_port,
- (ip_address *)NULL, pluto_port);
-
- for (; c != NULL; c = c->hp_next)
- {
- DBG(DBG_OPPO,
- DBG_log("checking %s", c->name));
- if (c->kind == CK_GROUP)
- {
- continue;
- }
-
- for (sr = &c->spd; best!=c && sr; sr = sr->next)
- {
- if (routed(sr->routing)
- && addrinsubnet(our_client, &sr->this.client)
- && addrinsubnet(peer_client, &sr->that.client))
- {
- if (best == NULL)
- {
- best = c;
- break;
- }
-
- DBG(DBG_OPPO,
- DBG_log("comparing best %s to %s"
- , best->name, c->name));
-
- for (bestsr = &best->spd; best!=c && bestsr; bestsr=bestsr->next)
- {
- if (!subnetinsubnet(&bestsr->this.client, &sr->this.client)
- || (samesubnet(&bestsr->this.client, &sr->this.client)
- && !subnetinsubnet(&bestsr->that.client
- , &sr->that.client)))
- {
- best = c;
- }
- }
- }
- }
- }
- }
-
- if (best == NULL || NEVER_NEGOTIATE(best->policy) ||
- (best->policy & POLICY_OPPO) == LEMPTY || best->kind != CK_TEMPLATE)
- {
- return NULL;
- }
- else
- {
- chunk_t encoding = gw->gw_id->get_encoding(gw->gw_id);
- id_type_t type = gw->gw_id->get_type(gw->gw_id);
- ip_address ip_addr;
-
- initaddr(encoding.ptr, encoding.len,
- (type == ID_IPV4_ADDR) ? AF_INET : AF_INET6, &ip_addr);
-
- return oppo_instantiate(best, &ip_addr, NULL, gw, our_client, peer_client);
- }
-}
-
-#endif /* ADNS */
-
-bool orient(connection_t *c)
-{
- struct spd_route *sr;
-
- if (!oriented(*c))
- {
- struct iface *p;
-
- for (sr = &c->spd; sr; sr = sr->next)
- {
- /* Note: this loop does not stop when it finds a match:
- * it continues checking to catch any ambiguity.
- */
- for (p = interfaces; p != NULL; p = p->next)
- {
- if (p->ike_float)
- {
- continue;
- }
-
- for (;;)
- {
- /* check if this interface matches this end */
- if (sameaddr(&sr->this.host_addr, &p->addr)
- && sr->this.host_port == pluto_port)
- {
- if (oriented(*c))
- {
- if (c->interface == p)
- loglog(RC_LOG_SERIOUS
- , "both sides of \"%s\" are our interface %s!"
- , c->name, p->rname);
- else
- loglog(RC_LOG_SERIOUS, "two interfaces match \"%s\" (%s, %s)"
- , c->name, c->interface->rname, p->rname);
- c->interface = NULL; /* withdraw orientation */
- return FALSE;
- }
- c->interface = p;
- }
-
- /* done with this interface if it doesn't match that end */
- if (!(sameaddr(&sr->that.host_addr, &p->addr)
- && sr->that.host_port == pluto_port))
- break;
-
- /* swap ends and try again.
- * It is a little tricky to see that this loop will stop.
- * Only continue if the far side matches.
- * If both sides match, there is an error-out.
- */
- {
- struct end t = sr->this;
-
- sr->this = sr->that;
- sr->that = t;
- }
- }
- }
- }
- }
- return oriented(*c);
-}
-
-void initiate_connection(const char *name, int whackfd)
-{
- connection_t *c = con_by_name(name, TRUE);
-
- if (c && c->ikev1)
- {
- set_cur_connection(c);
- if (!oriented(*c))
- {
- loglog(RC_ORIENT, "we have no ipsecN interface for either end of this connection");
- }
- else if (NEVER_NEGOTIATE(c->policy))
- {
- loglog(RC_INITSHUNT
- , "cannot initiate an authby=never connection");
- }
- else if (c->kind != CK_PERMANENT && !c->spd.that.allow_any)
- {
- if (isanyaddr(&c->spd.that.host_addr))
- loglog(RC_NOPEERIP, "cannot initiate connection without knowing peer IP address");
- else
- loglog(RC_WILDCARD, "cannot initiate connection with ID wildcards");
- }
- else
- {
- /* do we have to prompt for a PIN code? */
- if (c->spd.this.sc && !c->spd.this.sc->valid && whackfd != NULL_FD)
- {
- scx_get_pin(c->spd.this.sc, whackfd);
- }
- if (c->spd.this.sc && !c->spd.this.sc->valid)
- {
- loglog(RC_NOVALIDPIN, "cannot initiate connection without valid PIN");
- }
- else
- {
-
- if (c->spd.that.allow_any)
- {
- c = instantiate(c, &c->spd.that.host_addr,
- c->spd.that.host_port, c->spd.that.id);
- }
-
- /* We will only request an IPsec SA if policy isn't empty
- * (ignoring Main Mode items).
- * This is a fudge, but not yet important.
- * If we are to proceed asynchronously, whackfd will be NULL_FD.
- */
- c->policy |= POLICY_UP;
- ipsecdoi_initiate(whackfd, c, c->policy, 1, SOS_NOBODY);
- whackfd = NULL_FD; /* protect from close */
- }
- }
- reset_cur_connection();
- }
- close_any(whackfd);
-}
-
-/* (Possibly) Opportunistic Initiation:
- * Knowing clients (single IP addresses), try to build an tunnel.
- * This may involve discovering a gateway and instantiating an
- * Opportunistic connection. Called when a packet is caught by
- * a %trap, or when whack --oppohere --oppothere is used.
- * It may turn out that an existing or non-opporunistic connnection
- * can handle the traffic.
- *
- * Most of the code will be restarted if an ADNS request is made
- * to discover the gateway. The only difference between the first
- * and second entry is whether gateways_from_dns is NULL or not.
- * initiate_opportunistic: initial entrypoint
- * continue_oppo: where we pickup when ADNS result arrives
- * initiate_opportunistic_body: main body shared by above routines
- * cannot_oppo: a helper function to log a diagnostic
- * This structure repeats a lot of code when the ADNS result arrives.
- * This seems like a waste, but anything learned the first time through
- * may no longer be true!
- *
- * After the first IKE message is sent, the regular state machinery
- * carries negotiation forward.
- */
-
-enum find_oppo_step {
- fos_start,
- fos_myid_ip_txt,
- fos_myid_hostname_txt,
- fos_myid_ip_key,
- fos_myid_hostname_key,
- fos_our_client,
- fos_our_txt,
-#ifdef USE_KEYRR
- fos_our_key,
-#endif /* USE_KEYRR */
- fos_his_client,
- fos_done
-};
-
-#ifdef DEBUG
-static const char *const oppo_step_name[] = {
- "fos_start",
- "fos_myid_ip_txt",
- "fos_myid_hostname_txt",
- "fos_myid_ip_key",
- "fos_myid_hostname_key",
- "fos_our_client",
- "fos_our_txt",
-#ifdef USE_KEYRR
- "fos_our_key",
-#endif /* USE_KEYRR */
- "fos_his_client",
- "fos_done"
-};
-#endif /* DEBUG */
-
-struct find_oppo_bundle {
- enum find_oppo_step step;
- err_t want;
- bool failure_ok; /* if true, continue_oppo should not die on DNS failure */
- ip_address our_client; /* not pointer! */
- ip_address peer_client;
- int transport_proto;
- bool held;
- policy_prio_t policy_prio;
- ipsec_spi_t failure_shunt; /* in host order! 0 for delete. */
- int whackfd;
-};
-
-struct find_oppo_continuation {
- struct adns_continuation ac; /* common prefix */
- struct find_oppo_bundle b;
-};
-
-static void cannot_oppo(connection_t *c, struct find_oppo_bundle *b, err_t ugh)
-{
- char pcb[ADDRTOT_BUF];
- char ocb[ADDRTOT_BUF];
-
- addrtot(&b->peer_client, 0, pcb, sizeof(pcb));
- addrtot(&b->our_client, 0, ocb, sizeof(ocb));
-
- DBG(DBG_DNS | DBG_OPPO, DBG_log("Can't Opportunistically initiate for %s to %s: %s"
- , ocb, pcb, ugh));
-
- whack_log(RC_OPPOFAILURE
- , "Can't Opportunistically initiate for %s to %s: %s"
- , ocb, pcb, ugh);
-
- if (c && c->policy_next)
- {
- /* there is some policy that comes afterwards */
- struct spd_route *shunt_spd;
- connection_t *nc = c->policy_next;
- struct state *st;
-
- passert(c->kind == CK_TEMPLATE);
- passert(c->policy_next->kind == CK_PERMANENT);
-
- DBG(DBG_OPPO, DBG_log("OE failed for %s to %s, but %s overrides shunt"
- , ocb, pcb, c->policy_next->name));
-
- /*
- * okay, here we need add to the "next" policy, which is ought
- * to be an instance.
- * We will add another entry to the spd_route list for the specific
- * situation that we have.
- */
-
- shunt_spd = clone_thing(nc->spd);
-
- shunt_spd->next = nc->spd.next;
- nc->spd.next = shunt_spd;
-
- happy(addrtosubnet(&b->peer_client, &shunt_spd->that.client));
-
- if (sameaddr(&b->peer_client, &shunt_spd->that.host_addr))
- shunt_spd->that.has_client = FALSE;
-
- /*
- * override the tunnel destination with the one from the secondaried
- * policy
- */
- shunt_spd->that.host_addr = nc->spd.that.host_addr;
-
- /* now, lookup the state, and poke it up.
- */
-
- st = state_with_serialno(nc->newest_ipsec_sa);
-
- /* XXX what to do if the IPSEC SA has died? */
- passert(st != NULL);
-
- /* link the new connection instance to the state's list of
- * connections
- */
-
- DBG(DBG_OPPO, DBG_log("installing state: %ld for %s to %s"
- , nc->newest_ipsec_sa
- , ocb, pcb));
-
-#ifdef DEBUG
- if (DBGP(DBG_OPPO | DBG_CONTROLMORE))
- {
- char state_buf[LOG_WIDTH];
- char state_buf2[LOG_WIDTH];
- time_t n = now();
-
- fmt_state(FALSE, st, n
- , state_buf, sizeof(state_buf)
- , state_buf2, sizeof(state_buf2));
- DBG_log("cannot_oppo, failure SA1: %s", state_buf);
- DBG_log("cannot_oppo, failure SA2: %s", state_buf2);
- }
-#endif /* DEBUG */
-
- if (!route_and_eroute(c, shunt_spd, st))
- {
- whack_log(RC_OPPOFAILURE
- , "failed to instantiate shunt policy %s for %s to %s"
- , c->name
- , ocb, pcb);
- }
- return;
- }
-}
-
-static void initiate_opportunistic_body(struct find_oppo_bundle *b
- , struct adns_continuation *ac, err_t ac_ugh); /* forward */
-
-void initiate_opportunistic(const ip_address *our_client,
- const ip_address *peer_client, int transport_proto,
- bool held, int whackfd)
-{
- struct find_oppo_bundle b;
-
- b.want = (whackfd == NULL_FD ? "whack" : "acquire");
- b.failure_ok = FALSE;
- b.our_client = *our_client;
- b.peer_client = *peer_client;
- b.transport_proto = transport_proto;
- b.held = held;
- b.policy_prio = BOTTOM_PRIO;
- b.failure_shunt = 0;
- b.whackfd = whackfd;
- b.step = fos_start;
- initiate_opportunistic_body(&b, NULL, NULL);
-}
-
-#ifdef ADNS
-
-static void continue_oppo(struct adns_continuation *acr, err_t ugh)
-{
- struct find_oppo_continuation *cr = (void *)acr; /* inherit, damn you! */
- connection_t *c;
- bool was_held = cr->b.held;
- int whackfd = cr->b.whackfd;
-
- /* note: cr->id has no resources; cr->sgw_id is ID_ANY:
- * neither need freeing.
- */
- whack_log_fd = whackfd;
-
-#ifdef DEBUG
- /* if we're going to ignore the error, at least note it in debugging log */
- if (cr->b.failure_ok && ugh)
- {
- DBG(DBG_CONTROL | DBG_DNS,
- {
- char ocb[ADDRTOT_BUF];
- char pcb[ADDRTOT_BUF];
-
- addrtot(&cr->b.our_client, 0, ocb, sizeof(ocb));
- addrtot(&cr->b.peer_client, 0, pcb, sizeof(pcb));
- DBG_log("continuing from failed DNS lookup for %s, %s to %s: %s"
- , cr->b.want, ocb, pcb, ugh);
- });
- }
-#endif
-
- if (!cr->b.failure_ok && ugh)
- {
- c = find_connection_for_clients(NULL, &cr->b.our_client, &cr->b.peer_client
- , cr->b.transport_proto);
- cannot_oppo(c, &cr->b
- , builddiag("%s: %s", cr->b.want, ugh));
- }
- else if (was_held && !cr->b.held)
- {
- /* was_held indicates we were started due to a %trap firing
- * (as opposed to a "whack --oppohere --oppothere").
- * Since the %hold has gone, we can assume that somebody else
- * has beaten us to the punch. We can go home. But lets log it.
- */
- char ocb[ADDRTOT_BUF];
- char pcb[ADDRTOT_BUF];
-
- addrtot(&cr->b.our_client, 0, ocb, sizeof(ocb));
- addrtot(&cr->b.peer_client, 0, pcb, sizeof(pcb));
-
- loglog(RC_COMMENT
- , "%%hold otherwise handled during DNS lookup for Opportunistic Initiation for %s to %s"
- , ocb, pcb);
- }
- else
- {
- initiate_opportunistic_body(&cr->b, &cr->ac, ugh);
- whackfd = NULL_FD; /* was handed off */
- }
-
- whack_log_fd = NULL_FD;
- close_any(whackfd);
-}
-
-#endif /* ADNS */
-
-#ifdef USE_KEYRR
-static err_t check_key_recs(enum myid_state try_state, const connection_t *c,
- struct adns_continuation *ac)
-{
- /* Check if KEY lookup yielded good results.
- * Looking up based on our ID. Used if
- * client is ourself, or if TXT had no public key.
- * Note: if c is different this time, there is
- * a chance that we did the wrong query.
- * If so, treat as a kind of failure.
- */
- enum myid_state old_myid_state = myid_state;
- private_key_t *private;
- err_t ugh = NULL;
-
- myid_state = try_state;
-
- if (old_myid_state != myid_state && old_myid_state == MYID_SPECIFIED)
- {
- ugh = "%myid was specified while we were guessing";
- }
- else if ((private = get_private_key(c)) == NULL)
- {
- ugh = "we don't know our own RSA key";
- }
- else if (!same_id(&ac->id, &c->spd.this.id))
- {
- ugh = "our ID changed underfoot";
- }
- else
- {
- /* Similar to code in RSA_check_signature
- * for checking the other side.
- */
- pubkey_list_t *kr;
-
- ugh = "no KEY RR found for us";
- for (kr = ac->keys_from_dns; kr != NULL; kr = kr->next)
- {
- ugh = "all our KEY RRs have the wrong public key";
- if (kr->key->alg == PUBKEY_ALG_RSA
- && private->belongs_to(private, &kr->key->public_key))
- {
- ugh = NULL; /* good! */
- break;
- }
- }
- }
- if (ugh)
- {
- myid_state = old_myid_state;
- }
- return ugh;
-}
-#endif /* USE_KEYRR */
-
-#ifdef ADNS
-
-static err_t check_txt_recs(enum myid_state try_state, const connection_t *c,
- struct adns_continuation *ac)
-{
- /* Check if TXT lookup yielded good results.
- * Looking up based on our ID. Used if
- * client is ourself, or if TXT had no public key.
- * Note: if c is different this time, there is
- * a chance that we did the wrong query.
- * If so, treat as a kind of failure.
- */
- enum myid_state old_myid_state = myid_state;
- private_key_t *private;
- err_t ugh = NULL;
-
- myid_state = try_state;
-
- if (old_myid_state != myid_state
- && old_myid_state == MYID_SPECIFIED)
- {
- ugh = "%myid was specified while we were guessing";
- }
- else if ((private = get_private_key(c)) == NULL)
- {
- ugh = "we don't know our own RSA key";
- }
- else if (!ac->id->equals(ac->id, c->spd.this.id))
- {
- ugh = "our ID changed underfoot";
- }
- else
- {
- /* Similar to code in RSA_check_signature
- * for checking the other side.
- */
- struct gw_info *gwp;
-
- ugh = "no TXT RR found for us";
- for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next)
- {
- public_key_t *pub_key = gwp->key->public_key;
-
- ugh = "all our TXT RRs have the wrong public key";
- if (pub_key->get_type(pub_key) == KEY_RSA &&
- private->belongs_to(private, pub_key))
- {
- ugh = NULL; /* good! */
- break;
- }
- }
- }
- if (ugh)
- {
- myid_state = old_myid_state;
- }
- return ugh;
-}
-
-#endif /* ADNS */
-
-
-/* note: gateways_from_dns must be NULL iff this is the first call */
-static void initiate_opportunistic_body(struct find_oppo_bundle *b,
- struct adns_continuation *ac,
- err_t ac_ugh)
-{
- connection_t *c;
- struct spd_route *sr;
-
- /* What connection shall we use?
- * First try for one that explicitly handles the clients.
- */
- DBG(DBG_CONTROL,
- {
- char ours[ADDRTOT_BUF];
- char his[ADDRTOT_BUF];
- int ourport;
- int hisport;
-
- addrtot(&b->our_client, 0, ours, sizeof(ours));
- addrtot(&b->peer_client, 0, his, sizeof(his));
- ourport = ntohs(portof(&b->our_client));
- hisport = ntohs(portof(&b->peer_client));
- DBG_log("initiate on demand from %s:%d to %s:%d proto=%d state: %s because: %s"
- , ours, ourport, his, hisport, b->transport_proto
- , oppo_step_name[b->step], b->want);
- });
- if (isanyaddr(&b->our_client) || isanyaddr(&b->peer_client))
- {
- cannot_oppo(NULL, b, "impossible IP address");
- }
- else if ((c = find_connection_for_clients(&sr
- , &b->our_client
- , &b->peer_client
- , b->transport_proto)) == NULL)
- {
- /* No connection explicitly handles the clients and there
- * are no Opportunistic connections -- whine and give up.
- * The failure policy cannot be gotten from a connection; we pick %pass.
- */
- cannot_oppo(NULL, b, "no routed Opportunistic template covers this pair");
- }
- else if (c->kind != CK_TEMPLATE)
- {
- /* We've found a connection that can serve.
- * Do we have to initiate it?
- * Not if there is currently an IPSEC SA.
- * But if there is an IPSEC SA, then the kernel would not
- * have generated the acquire. So we assume that there isn't one.
- * This may be redundant if a non-opportunistic
- * negotiation is already being attempted.
- */
-
- /* If we are to proceed asynchronously, b->whackfd will be NULL_FD. */
-
- if(c->kind == CK_INSTANCE)
- {
- char cib[CONN_INST_BUF];
- /* there is already an instance being negotiated, no nothing */
- DBG(DBG_CONTROL, DBG_log("found existing instance \"%s\"%s, rekeying it"
- , c->name
- , (fmt_conn_instance(c, cib), cib)));
- /* XXX-mcr - return; */
- }
-
- /* otherwise, there is some kind of static conn that can handle
- * this connection, so we initiate it */
-
- if (b->held)
- {
- /* what should we do on failure? */
- (void) assign_hold(c, sr, b->transport_proto, &b->our_client, &b->peer_client);
- }
- ipsecdoi_initiate(b->whackfd, c, c->policy, 1, SOS_NOBODY);
- b->whackfd = NULL_FD; /* protect from close */
- }
-#ifdef ADNS
- else
- {
- /* We are handling an opportunistic situation.
- * This involves several DNS lookup steps that require suspension.
- * Note: many facts might change while we're suspended.
- * Here be dragons.
- *
- * The first chunk of code handles the result of the previous
- * DNS query (if any). It also selects the kind of the next step.
- * The second chunk initiates the next DNS query (if any).
- */
- enum find_oppo_step next_step = fos_myid_ip_txt;
- err_t ugh = ac_ugh;
- char mycredentialstr[BUF_LEN];
- char cib[CONN_INST_BUF];
-
- DBG(DBG_CONTROL, DBG_log("creating new instance from \"%s\"%s",
- c->name, (fmt_conn_instance(c, cib), cib)));
- snprintf(mycredentialstr, BUF_LEN, "%Y", sr->this.id);
-
- /* handle any DNS answer; select next step */
- switch (b->step)
- {
- case fos_start:
- /* just starting out: select first query step */
- next_step = fos_myid_ip_txt;
- break;
-
- case fos_myid_ip_txt: /* TXT for our default IP address as %myid */
- ugh = check_txt_recs(MYID_IP, c, ac);
- if (ugh)
- {
- /* cannot use our IP as OE identitiy for initiation */
- DBG(DBG_OPPO,
- DBG_log("can not use our IP (%Y:TXT) as identity: %s",
- myids[MYID_IP], ugh));
- if (!logged_myid_ip_txt_warning)
- {
- loglog(RC_LOG_SERIOUS,
- "can not use our IP (%Y:TXT) as identity: %s",
- myids[MYID_IP], ugh);
- logged_myid_ip_txt_warning = TRUE;
- }
-
- next_step = fos_myid_hostname_txt;
- ugh = NULL; /* failure can be recovered from */
- }
- else
- {
- /* we can use our IP as OE identity for initiation */
- if (!logged_myid_ip_txt_warning)
- {
- loglog(RC_LOG_SERIOUS,
- "using our IP (%Y:TXT) as identity!",
- myids[MYID_IP]);
- logged_myid_ip_txt_warning = TRUE;
- }
-
- next_step = fos_our_client;
- }
- break;
-
- case fos_myid_hostname_txt: /* TXT for our hostname as %myid */
- ugh = check_txt_recs(MYID_HOSTNAME, c, ac);
- if (ugh)
- {
- /* cannot use our hostname as OE identitiy for initiation */
- DBG(DBG_OPPO,
- DBG_log("can not use our hostname (%Y:TXT) as identity: %s",
- myids[MYID_HOSTNAME], ugh));
- if (!logged_myid_fqdn_txt_warning)
- {
- loglog(RC_LOG_SERIOUS,
- "can not use our hostname (%Y:TXT) as identity: %s",
- myids[MYID_HOSTNAME], ugh);
- logged_myid_fqdn_txt_warning = TRUE;
- }
-#ifdef USE_KEYRR
- next_step = fos_myid_ip_key;
- ugh = NULL; /* failure can be recovered from */
-#endif
- }
- else
- {
- /* we can use our hostname as OE identity for initiation */
- if (!logged_myid_fqdn_txt_warning)
- {
- loglog(RC_LOG_SERIOUS,
- "using our hostname (%Y:TXT) as identity!",
- myids[MYID_HOSTNAME]);
- logged_myid_fqdn_txt_warning = TRUE;
- }
- next_step = fos_our_client;
- }
- break;
-
-#ifdef USE_KEYRR
- case fos_myid_ip_key: /* KEY for our default IP address as %myid */
- ugh = check_key_recs(MYID_IP, c, ac);
- if (ugh)
- {
- /* cannot use our IP as OE identitiy for initiation */
- DBG(DBG_OPPO,
- DBG_log("can not use our IP (%Y:KEY) as identity: %s",
- myids[MYID_IP], ugh));
- if (!logged_myid_ip_key_warning)
- {
- loglog(RC_LOG_SERIOUS,
- "can not use our IP (%Y:KEY) as identity: %s",
- myids[MYID_IP], ugh);
- logged_myid_ip_key_warning = TRUE;
- }
-
- next_step = fos_myid_hostname_key;
- ugh = NULL; /* failure can be recovered from */
- }
- else
- {
- /* we can use our IP as OE identity for initiation */
- if (!logged_myid_ip_key_warning)
- {
- loglog(RC_LOG_SERIOUS,
- "using our IP (%Y:KEY) as identity!",
- myids[MYID_IP]);
- logged_myid_ip_key_warning = TRUE;
- }
- next_step = fos_our_client;
- }
- break;
-
- case fos_myid_hostname_key: /* KEY for our hostname as %myid */
- ugh = check_key_recs(MYID_HOSTNAME, c, ac);
- if (ugh)
- {
- /* cannot use our IP as OE identitiy for initiation */
- DBG(DBG_OPPO,
- DBG_log("can not use our hostname (%Y:KEY) as identity: %s",
- myids[MYID_HOSTNAME], ugh));
- if (!logged_myid_fqdn_key_warning)
- {
- loglog(RC_LOG_SERIOUS,
- "can not use our hostname (%Y:KEY) as identity: %s",
- myids[MYID_HOSTNAME], ugh);
- logged_myid_fqdn_key_warning = TRUE;
- }
- next_step = fos_myid_hostname_key;
- ugh = NULL; /* failure can be recovered from */
- }
- else
- {
- /* we can use our IP as OE identity for initiation */
- if (!logged_myid_fqdn_key_warning)
- {
- loglog(RC_LOG_SERIOUS,
- "using our hostname (%Y:KEY) as identity!",
- myids[MYID_HOSTNAME]);
- logged_myid_fqdn_key_warning = TRUE;
- }
- next_step = fos_our_client;
- }
- break;
-#endif
-
- case fos_our_client: /* TXT for our client */
- {
- /* Our client is not us: we must check the TXT records.
- * Note: if c is different this time, there is
- * a chance that we did the wrong query.
- * If so, treat as a kind of failure.
- */
- private_key_t *private = get_private_key(c);
-
- next_step = fos_his_client; /* normal situation */
-
- if (private == NULL)
- {
- ugh = "we don't know our own RSA key";
- }
- else if (sameaddr(&sr->this.host_addr, &b->our_client))
- {
- /* this wasn't true when we started -- bail */
- ugh = "our IP address changed underfoot";
- }
- else if (!ac->sgw_id->equals(ac->sgw_id, sr->this.id))
- {
- /* this wasn't true when we started -- bail */
- ugh = "our ID changed underfoot";
- }
- else
- {
- /* Similar to code in quick_inI1_outR1_tail
- * for checking the other side.
- */
- struct gw_info *gwp;
-
- ugh = "no TXT RR for our client delegates us";
- for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next)
- {
- ugh = "TXT RR for our client has wrong key";
- /* If there is a key from the TXT record,
- * we count it as a win if we match the key.
- * If there was no key, we have a tentative win:
- * we need to check our KEY record to be sure.
- */
- if (!gwp->gw_key_present)
- {
- /* Success, but the TXT had no key
- * so we must check our our own KEY records.
- */
- next_step = fos_our_txt;
- ugh = NULL; /* good! */
- break;
- }
- if (private->belongs_to(private, gwp->key->public_key))
- {
- ugh = NULL; /* good! */
- break;
- }
- }
- }
- }
- break;
-
- case fos_our_txt: /* TXT for us */
- {
- /* Check if TXT lookup yielded good results.
- * Looking up based on our ID. Used if
- * client is ourself, or if TXT had no public key.
- * Note: if c is different this time, there is
- * a chance that we did the wrong query.
- * If so, treat as a kind of failure.
- */
- private_key_t *private = get_private_key(c);
-
- next_step = fos_his_client; /* unless we decide to look for KEY RR */
-
- if (private == NULL)
- {
- ugh = "we don't know our own RSA key";
- }
- else if (!ac->id->equals(ac->id, c->spd.this.id))
- {
- ugh = "our ID changed underfoot";
- }
- else
- {
- /* Similar to code in RSA_check_signature
- * for checking the other side.
- */
- struct gw_info *gwp;
-
- ugh = "no TXT RR for us";
- for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next)
- {
- ugh = "TXT RR for us has wrong key";
- if (gwp->gw_key_present &&
- private->belongs_to(private, gwp->key->public_key))
- {
- DBG(DBG_CONTROL,
- DBG_log("initiate on demand found TXT with right public key at: %s"
- , mycredentialstr));
- ugh = NULL;
- break;
- }
- }
-#ifdef USE_KEYRR
- if (ugh)
- {
- /* if no TXT with right key, try KEY */
- DBG(DBG_CONTROL,
- DBG_log("will try for KEY RR since initiate on demand found %s: %s"
- , ugh, mycredentialstr));
- next_step = fos_our_key;
- ugh = NULL;
- }
-#endif
- }
- }
- break;
-
-#ifdef USE_KEYRR
- case fos_our_key: /* KEY for us */
- {
- /* Check if KEY lookup yielded good results.
- * Looking up based on our ID. Used if
- * client is ourself, or if TXT had no public key.
- * Note: if c is different this time, there is
- * a chance that we did the wrong query.
- * If so, treat as a kind of failure.
- */
- private_key_t *private = get_private_key(c);
-
- next_step = fos_his_client; /* always */
-
- if (private == NULL)
- {
- ugh = "we don't know our own RSA key";
- }
- else if (!same_id(&ac->id, &c->spd.this.id))
- {
- ugh = "our ID changed underfoot";
- }
- else
- {
- /* Similar to code in RSA_check_signature
- * for checking the other side.
- */
- pubkey_list_t *kr;
-
- ugh = "no KEY RR found for us (and no good TXT RR)";
- for (kr = ac->keys_from_dns; kr != NULL; kr = kr->next)
- {
- ugh = "all our KEY RRs have the wrong public key (and no good TXT RR)";
- if (kr->key->alg == PUBKEY_ALG_RSA
- && private->belongs_to(private, kr->key->public_key))
- {
- /* do this only once a day */
- if (!logged_txt_warning)
- {
- loglog(RC_LOG_SERIOUS
- , "found KEY RR but not TXT RR for %s. See http://www.freeswan.org/err/txt-change.html."
- , mycredentialstr);
- logged_txt_warning = TRUE;
- }
- ugh = NULL; /* good! */
- break;
- }
- }
- }
- }
- break;
-#endif /* USE_KEYRR */
-
- case fos_his_client: /* TXT for his client */
- {
- /* We've finished last DNS queries: TXT for his client.
- * Using the information, try to instantiate a connection
- * and start negotiating.
- * We now know the peer. The chosing of "c" ignored this,
- * so we will disregard its current value.
- * !!! We need to randomize the entry in gw that we choose.
- */
- next_step = fos_done; /* no more queries */
-
- c = build_outgoing_opportunistic_connection(ac->gateways_from_dns
- , &b->our_client
- , &b->peer_client);
-
- if (c == NULL)
- {
- /* We cannot seem to instantiate a suitable connection:
- * complain clearly.
- */
- char ocb[ADDRTOT_BUF], pcb[ADDRTOT_BUF];
-
- addrtot(&b->our_client, 0, ocb, sizeof(ocb));
- addrtot(&b->peer_client, 0, pcb, sizeof(pcb));
- loglog(RC_OPPOFAILURE,
- "no suitable connection for opportunism "
- "between %s and %s with %Y as peer",
- ocb, pcb, ac->gateways_from_dns->gw_id);
- }
- else
- {
- /* If we are to proceed asynchronously, b->whackfd will be NULL_FD. */
- passert(c->kind == CK_INSTANCE);
- passert(c->gw_info != NULL);
- passert(HAS_IPSEC_POLICY(c->policy));
- passert(LHAS(LELEM(RT_UNROUTED) | LELEM(RT_ROUTED_PROSPECTIVE), c->spd.routing));
- if (b->held)
- {
- /* what should we do on failure? */
- (void) assign_hold(c, &c->spd
- , b->transport_proto
- , &b->our_client, &b->peer_client);
- }
- c->gw_info->key->last_tried_time = now();
- ipsecdoi_initiate(b->whackfd, c, c->policy, 1, SOS_NOBODY);
- b->whackfd = NULL_FD; /* protect from close */
- }
- }
- break;
-
- default:
- bad_case(b->step);
- }
-
- /* the second chunk: initiate the next DNS query (if any) */
- DBG(DBG_CONTROL,
- {
- char ours[ADDRTOT_BUF];
- char his[ADDRTOT_BUF];
-
- addrtot(&b->our_client, 0, ours, sizeof(ours));
- addrtot(&b->peer_client, 0, his, sizeof(his));
- DBG_log("initiate on demand from %s to %s new state: %s with ugh: %s"
- , ours, his, oppo_step_name[b->step], ugh ? ugh : "ok");
- });
-
- if (ugh)
- {
- b->policy_prio = c->prio;
- b->failure_shunt = shunt_policy_spi(c, FALSE);
- cannot_oppo(c, b, ugh);
- }
- else if (next_step == fos_done)
- {
- /* nothing to do */
- }
- else
- {
- /* set up the next query */
- struct find_oppo_continuation *cr = malloc_thing(struct find_oppo_continuation);
- identification_t *id;
-
- b->policy_prio = c->prio;
- b->failure_shunt = shunt_policy_spi(c, FALSE);
- cr->b = *b; /* copy; start hand off of whackfd */
- cr->b.failure_ok = FALSE;
- cr->b.step = next_step;
-
- for (sr = &c->spd
- ; sr!=NULL && !sameaddr(&sr->this.host_addr, &b->our_client)
- ; sr = sr->next)
- ;
-
- if (sr == NULL)
- sr = &c->spd;
-
- /* If a %hold shunt has replaced the eroute for this template,
- * record this fact.
- */
- if (b->held
- && sr->routing == RT_ROUTED_PROSPECTIVE && eclipsable(sr))
- {
- sr->routing = RT_ROUTED_ECLIPSED;
- eclipse_count++;
- }
-
- /* Switch to issue next query.
- * A case may turn out to be unnecessary. If so, it falls
- * through to the next case.
- * Figuring out what %myid can stand for must be done before
- * our client credentials are looked up: we must know what
- * the client credentials may use to identify us.
- * On the other hand, our own credentials should be looked
- * up after our clients in case our credentials are not
- * needed at all.
- * XXX this is a wasted effort if we don't have credentials
- * BUT they are not needed.
- */
- switch (next_step)
- {
- case fos_myid_ip_txt:
- if (c->spd.this.id->get_type(c->spd.this.id) == ID_MYID
- && myid_state != MYID_SPECIFIED)
- {
- cr->b.failure_ok = TRUE;
- cr->b.want = b->want = "TXT record for IP address as %myid";
- ugh = start_adns_query(myids[MYID_IP], myids[MYID_IP],
- T_TXT, continue_oppo, &cr->ac);
- break;
- }
- cr->b.step = fos_myid_hostname_txt;
- /* fall through */
-
- case fos_myid_hostname_txt:
- if (c->spd.this.id->get_type(c->spd.this.id) == ID_MYID
- && myid_state != MYID_SPECIFIED)
- {
-#ifdef USE_KEYRR
- cr->b.failure_ok = TRUE;
-#else
- cr->b.failure_ok = FALSE;
-#endif
- cr->b.want = b->want = "TXT record for hostname as %myid";
- ugh = start_adns_query(myids[MYID_HOSTNAME],
- myids[MYID_HOSTNAME],
- T_TXT, continue_oppo, &cr->ac);
- break;
- }
-
-#ifdef USE_KEYRR
- cr->b.step = fos_myid_ip_key;
- /* fall through */
-
- case fos_myid_ip_key:
- if (c->spd.this.id.kind == ID_MYID
- && myid_state != MYID_SPECIFIED)
- {
- cr->b.failure_ok = TRUE;
- cr->b.want = b->want = "KEY record for IP address as %myid (no good TXT)";
- ugh = start_adns_query(myids[MYID_IP], NULL, /* security gateway meaningless */
- T_KEY, continue_oppo, &cr->ac);
- break;
- }
- cr->b.step = fos_myid_hostname_key;
- /* fall through */
-
- case fos_myid_hostname_key:
- if (c->spd.this.id.kind == ID_MYID
- && myid_state != MYID_SPECIFIED)
- {
- cr->b.failure_ok = FALSE; /* last attempt! */
- cr->b.want = b->want = "KEY record for hostname as %myid (no good TXT)";
- ugh = start_adns_query(myids[MYID_HOSTNAME], NULL, /* security gateway meaningless */
- T_KEY, continue_oppo, &cr->ac);
- break;
- }
-#endif
- cr->b.step = fos_our_client;
- /* fall through */
-
- case fos_our_client: /* TXT for our client */
- if (!sameaddr(&c->spd.this.host_addr, &b->our_client))
- {
- /* Check that at least one TXT(reverse(b->our_client)) is workable.
- * Note: {unshare|free}_id_content not needed for id: ephemeral.
- */
- cr->b.want = b->want = "our client's TXT record";
- id = identification_create_from_sockaddr((sockaddr_t*)&b->our_client);
- ugh = start_adns_query(id, c->spd.this.id, /* we are the security gateway */
- T_TXT, continue_oppo, &cr->ac);
- id->destroy(id);
- break;
- }
- cr->b.step = fos_our_txt;
- /* fall through */
-
- case fos_our_txt: /* TXT for us */
- cr->b.failure_ok = b->failure_ok = TRUE;
- cr->b.want = b->want = "our TXT record";
- ugh = start_adns_query(sr->this.id, sr->this.id, /* we are the security gateway */
- T_TXT, continue_oppo, &cr->ac);
- break;
-
-#ifdef USE_KEYRR
- case fos_our_key: /* KEY for us */
- cr->b.want = b->want = "our KEY record";
- cr->b.failure_ok = b->failure_ok = FALSE;
- ugh = start_adns_query(sr->this.id, NULL, /* security gateway meaningless */
- T_KEY, continue_oppo, &cr->ac);
- break;
-#endif /* USE_KEYRR */
-
- case fos_his_client: /* TXT for his client */
- /* note: {unshare|free}_id_content not needed for id: ephemeral */
- cr->b.want = b->want = "target's TXT record";
- cr->b.failure_ok = b->failure_ok = FALSE;
- id = identification_create_from_sockaddr((sockaddr_t*)&b->peer_client);
- ugh = start_adns_query(id, NULL, /* security gateway unconstrained */
- T_TXT, continue_oppo, &cr->ac);
- id->destroy(id);
- break;
-
- default:
- bad_case(next_step);
- }
-
- if (ugh == NULL)
- b->whackfd = NULL_FD; /* complete hand-off */
- else
- cannot_oppo(c, b, ugh);
- }
- }
-#endif /* ADNS */
- close_any(b->whackfd);
-}
-
-void terminate_connection(const char *nm)
-{
- /* Loop because more than one may match (master and instances)
- * But at least one is required (enforced by con_by_name).
- */
- connection_t *c = con_by_name(nm, TRUE);
-
- if (c == NULL || !c->ikev1)
- return;
-
- do
- {
- connection_t *n = c->ac_next; /* grab this before c might disappear */
-
- if (streq(c->name, nm)
- && c->kind >= CK_PERMANENT
- && !NEVER_NEGOTIATE(c->policy))
- {
- set_cur_connection(c);
- plog("terminating SAs using this connection");
- c->policy &= ~POLICY_UP;
- flush_pending_by_connection(c);
- delete_states_by_connection(c, FALSE);
- if (c->kind == CK_INSTANCE)
- delete_connection(c, FALSE);
- reset_cur_connection();
- }
- c = n;
- } while (c);
-}
-
-/* an ISAKMP SA has been established.
- * Note the serial number, and release any connections with
- * the same peer ID but different peer IP address.
- */
-bool uniqueIDs = FALSE; /* --uniqueids? */
-
-void ISAKMP_SA_established(connection_t *c, so_serial_t serial)
-{
- c->newest_isakmp_sa = serial;
-
- /* the connection is now oriented so that we are able to determine
- * whether we are a mode config server with a virtual IP to send.
- */
- if (!c->spd.that.host_srcip->is_anyaddr(c->spd.that.host_srcip) &&
- !c->spd.that.has_natip)
- {
- c->spd.that.modecfg = TRUE;
- }
-
- if (uniqueIDs)
- {
- /* for all connections: if the same Phase 1 IDs are used
- * for a different IP address, unorient that connection.
- */
- connection_t *d;
-
- for (d = connections; d != NULL; )
- {
- connection_t *next = d->ac_next; /* might move underneath us */
-
- if (d->kind >= CK_PERMANENT &&
- c->spd.this.id->equals(c->spd.this.id, d->spd.this.id) &&
- c->spd.that.id->equals(c->spd.that.id, d->spd.that.id) &&
- !sameaddr(&c->spd.that.host_addr, &d->spd.that.host_addr))
- {
- release_connection(d, FALSE);
- }
- d = next;
- }
- }
-}
-
-/* Find the connection to connection c's peer's client with the
- * largest value of .routing. All other things being equal,
- * preference is given to c. If none is routed, return NULL.
- *
- * If erop is non-null, set *erop to a connection sharing both
- * our client subnet and peer's client subnet with the largest value
- * of .routing. If none is erouted, set *erop to NULL.
- *
- * The return value is used to find other connections sharing a route.
- * *erop is used to find other connections sharing an eroute.
- */
-connection_t *route_owner(connection_t *c, struct spd_route **srp,
- connection_t **erop, struct spd_route **esrp)
-{
- connection_t *d
- , *best_ro = c
- , *best_ero = c;
- struct spd_route *srd, *src;
- struct spd_route *best_sr, *best_esr;
- enum routing_t best_routing, best_erouting;
-
- passert(oriented(*c));
- best_sr = NULL;
- best_esr = NULL;
- best_routing = c->spd.routing;
- best_erouting = best_routing;
-
- for (d = connections; d != NULL; d = d->ac_next)
- {
- for (srd = &d->spd; srd; srd = srd->next)
- {
- if (srd->routing == RT_UNROUTED)
- continue;
-
- for (src = &c->spd; src; src=src->next)
- {
- if (!samesubnet(&src->that.client, &srd->that.client))
- {
- continue;
- }
- if (src->that.protocol != srd->that.protocol)
- {
- continue;
- }
- if (src->that.port != srd->that.port)
- {
- continue;
- }
- if (src->mark_out.value != srd->mark_out.value)
- {
- continue;
- }
- passert(oriented(*d));
- if (srd->routing > best_routing)
- {
- best_ro = d;
- best_sr = srd;
- best_routing = srd->routing;
- }
-
- if (!samesubnet(&src->this.client, &srd->this.client))
- {
- continue;
- }
- if (src->this.protocol != srd->this.protocol)
- {
- continue;
- }
- if (src->this.port != srd->this.port)
- {
- continue;
- }
- if (src->mark_in.value != srd->mark_in.value)
- {
- continue;
- }
- if (srd->routing > best_erouting)
- {
- best_ero = d;
- best_esr = srd;
- best_erouting = srd->routing;
- }
- }
- }
- }
-
- DBG(DBG_CONTROL,
- {
- char cib[CONN_INST_BUF];
- err_t m = builddiag("route owner of \"%s\"%s %s:"
- , c->name
- , (fmt_conn_instance(c, cib), cib)
- , enum_name(&routing_story, c->spd.routing));
-
- if (!routed(best_ro->spd.routing))
- m = builddiag("%s NULL", m);
- else if (best_ro == c)
- m = builddiag("%s self", m);
- else
- m = builddiag("%s \"%s\"%s %s", m
- , best_ro->name
- , (fmt_conn_instance(best_ro, cib), cib)
- , enum_name(&routing_story, best_ro->spd.routing));
-
- if (erop)
- {
- m = builddiag("%s; eroute owner:", m);
- if (!erouted(best_ero->spd.routing))
- m = builddiag("%s NULL", m);
- else if (best_ero == c)
- m = builddiag("%s self", m);
- else
- m = builddiag("%s \"%s\"%s %s", m
- , best_ero->name
- , (fmt_conn_instance(best_ero, cib), cib)
- , enum_name(&routing_story, best_ero->spd.routing));
- }
-
- DBG_log("%s", m);
- });
-
- if (erop)
- {
- *erop = erouted(best_erouting)? best_ero : NULL;
- }
- if (srp)
- {
- *srp = best_sr;
- if (esrp)
- {
- *esrp = best_esr;
- }
- }
-
- return routed(best_routing)? best_ro : NULL;
-}
-
-/* Find a connection that owns the shunt eroute between subnets.
- * There ought to be only one.
- * This might get to be a bottleneck -- try hashing if it does.
- */
-connection_t *shunt_owner(const ip_subnet *ours, const ip_subnet *his)
-{
- connection_t *c;
- struct spd_route *sr;
-
- for (c = connections; c != NULL; c = c->ac_next)
- {
- for (sr = &c->spd; sr; sr = sr->next)
- {
- if (shunt_erouted(sr->routing)
- && samesubnet(ours, &sr->this.client)
- && samesubnet(his, &sr->that.client))
- return c;
- }
- }
- return NULL;
-}
-
-/* Find some connection with this pair of hosts.
- * We don't know enough to chose amongst those available.
- * ??? no longer usefully different from find_host_pair_connections
- */
-connection_t *find_host_connection(const ip_address *me, u_int16_t my_port,
- const ip_address *him, u_int16_t his_port,
- lset_t policy)
-{
- connection_t *c = find_host_pair_connections(me, my_port, him, his_port);
-
- if (policy != LEMPTY)
- {
- lset_t auth_requested = policy & POLICY_ID_AUTH_MASK;
-
- /* if we have requirements for the policy,
- * choose the first matching connection.
- */
- while (c)
- {
- if (c->policy & auth_requested)
- {
- break;
- }
- c = c->hp_next;
- }
- }
- return c;
-}
-
-/* given an up-until-now satisfactory connection, find the best connection
- * now that we just got the Phase 1 Id Payload from the peer.
- *
- * Comments in the code describe the (tricky!) matching criteria.
- * Although this routine could handle the initiator case,
- * it isn't currently called in this case.
- * If it were, it could "upgrade" an Opportunistic Connection
- * to a Road Warrior Connection if a suitable Peer ID were found.
- *
- * In RFC 2409 "The Internet Key Exchange (IKE)",
- * in 5.1 "IKE Phase 1 Authenticated With Signatures", describing Main
- * Mode:
- *
- * Initiator Responder
- * ----------- -----------
- * HDR, SA -->
- * <-- HDR, SA
- * HDR, KE, Ni -->
- * <-- HDR, KE, Nr
- * HDR*, IDii, [ CERT, ] SIG_I -->
- * <-- HDR*, IDir, [ CERT, ] SIG_R
- *
- * In 5.4 "Phase 1 Authenticated With a Pre-Shared Key":
- *
- * HDR, SA -->
- * <-- HDR, SA
- * HDR, KE, Ni -->
- * <-- HDR, KE, Nr
- * HDR*, IDii, HASH_I -->
- * <-- HDR*, IDir, HASH_R
- *
- * refine_host_connection could be called in two case:
- *
- * - the Responder receives the IDii payload:
- * + [PSK] after using PSK to decode this message
- * + before sending its IDir payload
- * + before using its ID in HASH_R computation
- * + [DSig] before using its private key to sign SIG_R
- * + before using the Initiator's ID in HASH_I calculation
- * + [DSig] before using the Initiator's public key to check SIG_I
- *
- * - the Initiator receives the IDir payload:
- * + [PSK] after using PSK to encode previous message and decode this message
- * + after sending its IDii payload
- * + after using its ID in HASH_I computation
- * + [DSig] after using its private key to sign SIG_I
- * + before using the Responder's ID to compute HASH_R
- * + [DSig] before using Responder's public key to check SIG_R
- *
- * refine_host_connection can choose a different connection, as long as
- * nothing already used is changed.
- *
- * In the Initiator case, the particular connection might have been
- * specified by whatever provoked Pluto to initiate. For example:
- * whack --initiate connection-name
- * The advantages of switching connections when we're the Initiator seem
- * less important than the disadvantages, so after FreeS/WAN 1.9, we
- * don't do this.
- */
-#define PRIO_NO_MATCH_FOUND 2048
-
-connection_t *refine_host_connection(const struct state *st,
- identification_t *peer_id,
- identification_t *peer_ca)
-{
- connection_t *c = st->st_connection;
- connection_t *d;
- connection_t *best_found = NULL;
- u_int16_t auth = st->st_oakley.auth;
- lset_t auth_policy = POLICY_PSK;
- const chunk_t *psk = NULL;
- bool wcpip; /* wildcard Peer IP? */
- int best_prio = PRIO_NO_MATCH_FOUND;
- int our_pathlen, peer_pathlen;
-
- if (c->spd.that.id->equals(c->spd.that.id, peer_id) &&
- trusted_ca(peer_ca, c->spd.that.ca, &peer_pathlen) &&
- peer_pathlen == 0 &&
- match_requested_ca(c->requested_ca, c->spd.this.ca, &our_pathlen) &&
- our_pathlen == 0)
- {
- DBG(DBG_CONTROL,
- DBG_log("current connection is a full match"
- " -- no need to look further");
- )
- return c;
- }
-
- switch (auth)
- {
- case OAKLEY_PRESHARED_KEY:
- auth_policy = POLICY_PSK;
- psk = get_preshared_secret(c);
- /* It should be virtually impossible to fail to find PSK:
- * we just used it to decode the current message!
- */
- if (psk == NULL)
- {
- return NULL; /* cannot determine PSK! */
- }
- break;
- case XAUTHInitPreShared:
- case XAUTHRespPreShared:
- auth_policy = POLICY_XAUTH_PSK;
- psk = get_preshared_secret(c);
- if (psk == NULL)
- {
- return NULL; /* cannot determine PSK! */
- }
- break;
- case OAKLEY_RSA_SIG:
- case OAKLEY_ECDSA_256:
- case OAKLEY_ECDSA_384:
- case OAKLEY_ECDSA_521:
- auth_policy = POLICY_PUBKEY;
- break;
- case XAUTHInitRSA:
- case XAUTHRespRSA:
- auth_policy = POLICY_XAUTH_RSASIG;
- break;
- default:
- bad_case(auth);
- }
-
- /* The current connection won't do: search for one that will.
- * First search for one with the same pair of hosts.
- * If that fails, search for a suitable Road Warrior or Opportunistic
- * connection (i.e. wildcard peer IP).
- * We need to match:
- * - peer_id (slightly complicated by instantiation)
- * - if PSK auth, the key must not change (we used it to decode message)
- * - policy-as-used must be acceptable to new connection
- */
- d = c->host_pair->connections;
- for (wcpip = FALSE; ; wcpip = TRUE)
- {
- for (; d != NULL; d = d->hp_next)
- {
- const char *match_name[] = {"no", "ok"};
-
- id_match_t match_level = peer_id->matches(peer_id, d->spd.that.id);
-
- bool matching_id = match_level > ID_MATCH_NONE;
-
- bool matching_auth = (d->policy & auth_policy) != LEMPTY;
-
- bool matching_trust = trusted_ca(peer_ca
- , d->spd.that.ca, &peer_pathlen);
- bool matching_request = match_requested_ca(c->requested_ca
- , d->spd.this.ca, &our_pathlen);
- bool match = matching_id && matching_auth && matching_trust;
-
- int prio = (ID_MATCH_PERFECT) * !matching_request +
- ID_MATCH_PERFECT - match_level;
-
- prio = (X509_MAX_PATH_LEN + 1) * prio + peer_pathlen;
- prio = (X509_MAX_PATH_LEN + 1) * prio + our_pathlen;
-
- DBG(DBG_CONTROLMORE,
- DBG_log("%s: %s match (id: %s, auth: %s, trust: %s, request: %s, prio: %4d)"
- , d->name
- , match ? "full":" no"
- , match_name[matching_id]
- , match_name[matching_auth]
- , match_name[matching_trust]
- , match_name[matching_request]
- , match ? prio:PRIO_NO_MATCH_FOUND)
- )
-
- /* do we have a match? */
- if (!match)
- {
- continue;
- }
-
- /* ignore group connections */
- if (d->policy & POLICY_GROUP)
- {
- continue;
- }
-
- if (c->spd.that.host_port != d->spd.that.host_port
- && d->kind == CK_INSTANCE)
- {
- continue;
- }
-
- switch (auth)
- {
- case OAKLEY_PRESHARED_KEY:
- case XAUTHInitPreShared:
- case XAUTHRespPreShared:
- /* secret must match the one we already used */
- {
- const chunk_t *dpsk = get_preshared_secret(d);
-
- if (dpsk == NULL)
- {
- continue; /* no secret */
- }
- if (psk != dpsk)
- {
- if (psk->len != dpsk->len
- || memcmp(psk->ptr, dpsk->ptr, psk->len) != 0)
- {
- continue; /* different secret */
- }
- }
- }
- break;
-
- case OAKLEY_RSA_SIG:
- case OAKLEY_ECDSA_256:
- case OAKLEY_ECDSA_384:
- case OAKLEY_ECDSA_521:
- case XAUTHInitRSA:
- case XAUTHRespRSA:
- /*
- * We must at least be able to find our private key
- .*/
- if (d->spd.this.sc == NULL /* no smartcard */
- && get_private_key(d) == NULL) /* no private key */
- {
- continue;
- }
- break;
-
- default:
- bad_case(auth);
- }
-
- /* d has passed all the tests.
- * We'll go with it if the Peer ID was an exact match.
- */
- if (prio == 0)
- {
- return d;
- }
-
- /* We'll remember it as best_found in case an exact
- * match doesn't come along.
- */
- if (prio < best_prio)
- {
- best_found = d;
- best_prio = prio;
- }
- }
- if (wcpip)
- return best_found; /* been around twice already */
-
- /* Starting second time around.
- * We're willing to settle for a connection that needs Peer IP
- * instantiated: Road Warrior or Opportunistic.
- * Look on list of connections for host pair with wildcard Peer IP
- */
- d = find_host_pair_connections(&c->spd.this.host_addr, c->spd.this.host_port
- , (ip_address *)NULL, c->spd.that.host_port);
- }
-}
-
-/**
- * With virtual addressing, we must not allow someone to use an already
- * used (by another id) addr/net.
- */
-static bool is_virtual_net_used(const ip_subnet *peer_net,
- identification_t *peer_id)
-{
- connection_t *d;
-
- for (d = connections; d != NULL; d = d->ac_next)
- {
- switch (d->kind)
- {
- case CK_PERMANENT:
- case CK_INSTANCE:
- if ((subnetinsubnet(peer_net,&d->spd.that.client) ||
- subnetinsubnet(&d->spd.that.client,peer_net))
- && !d->spd.that.id->equals(d->spd.that.id, peer_id))
- {
- char client[SUBNETTOT_BUF];
-
- subnettot(peer_net, 0, client, sizeof(client));
- plog("Virtual IP %s is already used by '%Y'",
- client, d->spd.that.id);
- plog("Your ID is '%Y'", peer_id);
-
- return TRUE; /* already used by another one */
- }
- break;
- case CK_GOING_AWAY:
- default:
- break;
- }
- }
- return FALSE; /* you can safely use it */
-}
-
-/* find_client_connection: given a connection suitable for ISAKMP
- * (i.e. the hosts match), find a one suitable for IPSEC
- * (i.e. with matching clients).
- *
- * If we don't find an exact match (not even our current connection),
- * we try for one that still needs instantiation. Try Road Warrior
- * abstract connections and the Opportunistic abstract connections.
- * This requires inverse instantiation: abstraction.
- *
- * After failing to find an exact match, we abstract the peer
- * to be NO_IP (the wildcard value). This enables matches with
- * Road Warrior and Opportunistic abstract connections.
- *
- * After failing that search, we also abstract the Phase 1 peer ID
- * if possible. If the peer's ID was the peer's IP address, we make
- * it NO_ID; instantiation will make it the peer's IP address again.
- *
- * If searching for a Road Warrior abstract connection fails,
- * and conditions are suitable, we search for the best Opportunistic
- * abstract connection.
- *
- * Note: in the end, both Phase 1 IDs must be preserved, after any
- * instantiation. They are the IDs that have been authenticated.
- */
-
-#define PATH_WEIGHT 1
-#define WILD_WEIGHT (X509_MAX_PATH_LEN+1)
-#define PRIO_WEIGHT (ID_MATCH_PERFECT+1) * WILD_WEIGHT
-
-/* fc_try: a helper function for find_client_connection */
-static connection_t *fc_try(const connection_t *c, struct host_pair *hp,
- identification_t *peer_id,
- const ip_subnet *our_net,
- const ip_subnet *peer_net,
- const u_int8_t our_protocol,
- const u_int16_t our_port,
- const u_int8_t peer_protocol,
- const u_int16_t peer_port,
- identification_t *peer_ca,
- ietf_attributes_t *peer_attributes)
-{
- connection_t *d;
- connection_t *best = NULL;
- policy_prio_t best_prio = BOTTOM_PRIO;
- id_match_t match_level;
- int pathlen;
-
-
- const bool peer_net_is_host = subnetisaddr(peer_net, &c->spd.that.host_addr);
-
- for (d = hp->connections; d != NULL; d = d->hp_next)
- {
- struct spd_route *sr;
-
- if (d->policy & POLICY_GROUP)
- {
- continue;
- }
-
- match_level = c->spd.that.id->matches(c->spd.that.id, d->spd.that.id);
-
- if (!(c->spd.this.id->equals(c->spd.this.id, d->spd.this.id) &&
- (match_level > ID_MATCH_NONE) &&
- trusted_ca(peer_ca, d->spd.that.ca, &pathlen) &&
- match_group_membership(peer_attributes, d->name, d->spd.that.groups)))
- {
- continue;
- }
-
- /* compare protocol and ports */
- if (d->spd.this.protocol != our_protocol
- || d->spd.this.port != our_port
- || d->spd.that.protocol != peer_protocol
- || (d->spd.that.port != peer_port && !d->spd.that.has_port_wildcard))
- {
- continue;
- }
-
- /* non-Opportunistic case:
- * our_client must match.
- *
- * So must peer_client, but the testing is complicated
- * by the fact that the peer might be a wildcard
- * and if so, the default value of that.client
- * won't match the default peer_net. The appropriate test:
- *
- * If d has a peer client, it must match peer_net.
- * If d has no peer client, peer_net must just have peer itself.
- */
-
- for (sr = &d->spd; best != d && sr != NULL; sr = sr->next)
- {
- policy_prio_t prio;
-#ifdef DEBUG
- if (DBGP(DBG_CONTROLMORE))
- {
- char s1[SUBNETTOT_BUF],d1[SUBNETTOT_BUF];
- char s3[SUBNETTOT_BUF],d3[SUBNETTOT_BUF];
-
- subnettot(our_net, 0, s1, sizeof(s1));
- subnettot(peer_net, 0, d1, sizeof(d1));
- subnettot(&sr->this.client, 0, s3, sizeof(s3));
- subnettot(&sr->that.client, 0, d3, sizeof(d3));
- DBG_log(" fc_try trying "
- "%s:%s:%d/%d -> %s:%d/%d vs %s:%s:%d/%d -> %s:%d/%d"
- , c->name, s1, c->spd.this.protocol, c->spd.this.port
- , d1, c->spd.that.protocol, c->spd.that.port
- , d->name, s3, sr->this.protocol, sr->this.port
- , d3, sr->that.protocol, sr->that.port);
- }
-#endif /* DEBUG */
-
- if (!samesubnet(&sr->this.client, our_net))
- {
- continue;
- }
- if (sr->that.has_client)
- {
- if (sr->that.has_client_wildcard)
- {
- if (!subnetinsubnet(peer_net, &sr->that.client))
- {
- continue;
- }
- }
- else
- {
- if (!samesubnet(&sr->that.client, peer_net) && !is_virtual_connection(d))
- {
- continue;
- }
- if (is_virtual_connection(d)
- && (!is_virtual_net_allowed(d, peer_net, &c->spd.that.host_addr)
- || is_virtual_net_used(peer_net, peer_id?peer_id:c->spd.that.id)))
- {
- continue;
- }
- }
- }
- else
- {
- host_t *vip = c->spd.that.host_srcip;
-
- if (!peer_net_is_host && !(sr->that.modecfg && c->spd.that.modecfg &&
- subnetisaddr(peer_net, (ip_address*)vip->get_sockaddr(vip))))
- {
- continue;
- }
- }
-
- /* We've run the gauntlet -- success:
- * We've got an exact match of subnets.
- * The connection is feasible, but we continue looking for the best.
- * The highest priority wins, implementing eroute-like rule.
- * - a routed connection is preferrred
- * - given that, the smallest number of ID wildcards are preferred
- * - given that, the shortest CA pathlength is preferred
- */
- prio = PRIO_WEIGHT * routed(sr->routing)
- + WILD_WEIGHT * match_level
- + PATH_WEIGHT * (X509_MAX_PATH_LEN - pathlen)
- + 1;
- if (prio > best_prio)
- {
- best = d;
- best_prio = prio;
- }
- }
- }
-
- if (best && NEVER_NEGOTIATE(best->policy))
- {
- best = NULL;
- }
- DBG(DBG_CONTROLMORE,
- DBG_log(" fc_try concluding with %s [%ld]"
- , (best ? best->name : "none"), best_prio)
- )
- return best;
-}
-
-static connection_t *fc_try_oppo(const connection_t *c,
- struct host_pair *hp,
- const ip_subnet *our_net,
- const ip_subnet *peer_net,
- const u_int8_t our_protocol,
- const u_int16_t our_port,
- const u_int8_t peer_protocol,
- const u_int16_t peer_port,
- identification_t *peer_ca,
- ietf_attributes_t *peer_attributes)
-{
- connection_t *d;
- connection_t *best = NULL;
- policy_prio_t best_prio = BOTTOM_PRIO;
- id_match_t match_level;
- int pathlen;
-
- for (d = hp->connections; d != NULL; d = d->hp_next)
- {
- struct spd_route *sr;
- policy_prio_t prio;
-
- if (d->policy & POLICY_GROUP)
- {
- continue;
- }
- match_level = c->spd.that.id->matches(c->spd.that.id, c->spd.that.id);
-
- if (!(c->spd.this.id->equals(c->spd.this.id, d->spd.this.id) &&
- (match_level > ID_MATCH_NONE) &&
- trusted_ca(peer_ca, d->spd.that.ca, &pathlen) &&
- match_group_membership(peer_attributes, d->name, d->spd.that.groups)))
- {
- continue;
- }
-
- /* compare protocol and ports */
- if (d->spd.this.protocol != our_protocol
- || d->spd.this.port != our_port
- || d->spd.that.protocol != peer_protocol
- || (d->spd.that.port != peer_port && !d->spd.that.has_port_wildcard))
- {
- continue;
- }
-
- /* Opportunistic case:
- * our_net must be inside d->spd.this.client
- * and peer_net must be inside d->spd.that.client
- * Note: this host_pair chain also has shunt
- * eroute conns (clear, drop), but they won't
- * be marked as opportunistic.
- */
- for (sr = &d->spd; sr != NULL; sr = sr->next)
- {
-#ifdef DEBUG
- if (DBGP(DBG_CONTROLMORE))
- {
- char s1[SUBNETTOT_BUF],d1[SUBNETTOT_BUF];
- char s3[SUBNETTOT_BUF],d3[SUBNETTOT_BUF];
-
- subnettot(our_net, 0, s1, sizeof(s1));
- subnettot(peer_net, 0, d1, sizeof(d1));
- subnettot(&sr->this.client, 0, s3, sizeof(s3));
- subnettot(&sr->that.client, 0, d3, sizeof(d3));
- DBG_log(" fc_try_oppo trying %s:%s -> %s vs %s:%s -> %s"
- , c->name, s1, d1, d->name, s3, d3);
- }
-#endif /* DEBUG */
-
- if (!subnetinsubnet(our_net, &sr->this.client)
- || !subnetinsubnet(peer_net, &sr->that.client))
- {
- continue;
- }
-
- /* The connection is feasible, but we continue looking for the best.
- * The highest priority wins, implementing eroute-like rule.
- * - our smallest client subnet is preferred (longest mask)
- * - given that, his smallest client subnet is preferred
- * - given that, a routed connection is preferrred
- * - given that, the smallest number of ID wildcards are preferred
- * - given that, the shortest CA pathlength is preferred
- */
- prio = PRIO_WEIGHT * (d->prio + routed(sr->routing))
- + WILD_WEIGHT * match_level
- + PATH_WEIGHT * (X509_MAX_PATH_LEN - pathlen);
- if (prio > best_prio)
- {
- best = d;
- best_prio = prio;
- }
- }
- }
-
- /* if the best wasn't opportunistic, we fail: it must be a shunt */
- if (best && (NEVER_NEGOTIATE(best->policy) ||
- (best->policy & POLICY_OPPO) == LEMPTY))
- {
- best = NULL;
- }
-
- DBG(DBG_CONTROLMORE,
- DBG_log(" fc_try_oppo concluding with %s [%ld]"
- , (best ? best->name : "none"), best_prio)
- )
- return best;
-
-}
-
-/*
- * get the peer's CA and group attributes
- */
-void get_peer_ca_and_groups(connection_t *c,
- identification_t **peer_ca,
- ietf_attributes_t **peer_attributes)
-{
- struct state *p1st;
-
- *peer_ca = NULL;
- *peer_attributes = NULL;
-
- p1st = find_phase1_state(c, ISAKMP_SA_ESTABLISHED_STATES);
- if (p1st && p1st->st_peer_pubkey && p1st->st_peer_pubkey->issuer)
- {
- certificate_t *cert;
-
- cert = ac_get_cert(p1st->st_peer_pubkey->issuer,
- p1st->st_peer_pubkey->serial);
- if (cert && ac_verify_cert(cert, strict_crl_policy))
- {
- ac_t *ac = (ac_t*)cert;
-
- *peer_attributes = ac->get_groups(ac);
- }
- else
- {
- DBG(DBG_CONTROL,
- DBG_log("no valid attribute cert found")
- )
- }
- *peer_ca = p1st->st_peer_pubkey->issuer;
- }
-}
-
-connection_t *find_client_connection(connection_t *c,
- const ip_subnet *our_net,
- const ip_subnet *peer_net,
- const u_int8_t our_protocol,
- const u_int16_t our_port,
- const u_int8_t peer_protocol,
- const u_int16_t peer_port)
-{
- connection_t *d;
- struct spd_route *sr;
- ietf_attributes_t *peer_attributes = NULL;
- identification_t *peer_ca;
-
- get_peer_ca_and_groups(c, &peer_ca, &peer_attributes);
-
-#ifdef DEBUG
- if (DBGP(DBG_CONTROLMORE))
- {
- char s1[SUBNETTOT_BUF],d1[SUBNETTOT_BUF];
-
- subnettot(our_net, 0, s1, sizeof(s1));
- subnettot(peer_net, 0, d1, sizeof(d1));
-
- DBG_log("find_client_connection starting with %s"
- , (c ? c->name : "(none)"));
- DBG_log(" looking for %s:%d/%d -> %s:%d/%d"
- , s1, our_protocol, our_port
- , d1, peer_protocol, peer_port);
- }
-#endif /* DEBUG */
-
- /* give priority to current connection
- * but even greater priority to a routed concrete connection
- */
- {
- connection_t *unrouted = NULL;
- int srnum = -1;
-
- for (sr = &c->spd; unrouted == NULL && sr != NULL; sr = sr->next)
- {
- srnum++;
-
-#ifdef DEBUG
- if (DBGP(DBG_CONTROLMORE))
- {
- char s2[SUBNETTOT_BUF],d2[SUBNETTOT_BUF];
-
- subnettot(&sr->this.client, 0, s2, sizeof(s2));
- subnettot(&sr->that.client, 0, d2, sizeof(d2));
- DBG_log(" concrete checking against sr#%d %s -> %s"
- , srnum, s2, d2);
- }
-#endif /* DEBUG */
-
- if (samesubnet(&sr->this.client, our_net)
- && samesubnet(&sr->that.client, peer_net)
- && sr->this.protocol == our_protocol
- && sr->this.port == our_port
- && sr->that.protocol == peer_protocol
- && sr->that.port == peer_port
- && match_group_membership(peer_attributes, c->name, sr->that.groups))
- {
- passert(oriented(*c));
- if (routed(sr->routing))
- {
- DESTROY_IF(peer_attributes);
- return c;
- }
- unrouted = c;
- }
- }
-
- /* exact match? */
- d = fc_try(c, c->host_pair, NULL, our_net, peer_net
- , our_protocol, our_port, peer_protocol, peer_port
- , peer_ca, peer_attributes);
-
- DBG(DBG_CONTROLMORE,
- DBG_log(" fc_try %s gives %s"
- , c->name
- , (d ? d->name : "none"))
- )
-
- if (d == NULL)
- {
- d = unrouted;
- }
- }
-
- if (d == NULL)
- {
- /* look for an abstract connection to match */
- struct spd_route *sr;
- struct host_pair *hp = NULL;
-
- for (sr = &c->spd; hp==NULL && sr != NULL; sr = sr->next)
- {
- hp = find_host_pair(&sr->this.host_addr
- , sr->this.host_port
- , NULL
- , sr->that.host_port);
-#ifdef DEBUG
- if (DBGP(DBG_CONTROLMORE))
- {
- char s2[SUBNETTOT_BUF],d2[SUBNETTOT_BUF];
-
- subnettot(&sr->this.client, 0, s2, sizeof(s2));
- subnettot(&sr->that.client, 0, d2, sizeof(d2));
-
- DBG_log(" checking hostpair %s -> %s is %s"
- , s2, d2
- , (hp ? "found" : "not found"));
- }
-#endif /* DEBUG */
- }
-
- if (hp)
- {
- /* RW match with actual peer_id or abstract peer_id? */
- d = fc_try(c, hp, NULL, our_net, peer_net
- , our_protocol, our_port, peer_protocol, peer_port
- , peer_ca, peer_attributes);
-
- if (d == NULL
- && subnetishost(our_net)
- && subnetishost(peer_net))
- {
- /* Opportunistic match?
- * Always use abstract peer_id.
- * Note that later instantiation will result in the same peer_id.
- */
- d = fc_try_oppo(c, hp, our_net, peer_net
- , our_protocol, our_port, peer_protocol, peer_port
- , peer_ca, peer_attributes);
- }
- }
- }
-
- DBG(DBG_CONTROLMORE,
- DBG_log(" concluding with d = %s"
- , (d ? d->name : "none"))
- )
- DESTROY_IF(peer_attributes);
- return d;
-}
-
-int connection_compare(const connection_t *ca, const connection_t *cb)
-{
- int ret;
-
- /* DBG_log("comparing %s to %s", ca->name, cb->name); */
-
- ret = strcasecmp(ca->name, cb->name);
- if (ret)
- {
- return ret;
- }
-
- ret = ca->kind - cb->kind; /* note: enum connection_kind behaves like int */
- if (ret)
- {
- return ret;
- }
-
- /* same name, and same type */
- switch (ca->kind)
- {
- case CK_INSTANCE:
- return ca->instance_serial < cb->instance_serial ? -1
- : ca->instance_serial > cb->instance_serial ? 1
- : 0;
-
- default:
- return ca->prio < cb->prio ? -1
- : ca->prio > cb->prio ? 1
- : 0;
- }
-}
-
-static int connection_compare_qsort(const void *a, const void *b)
-{
- return connection_compare(*(const connection_t *const *)a
- , *(const connection_t *const *)b);
-}
-
-void show_connections_status(bool all, const char *name)
-{
- connection_t *c;
- int count, i;
- connection_t **array;
-
- /* make an array of connections, and sort it */
- count = 0;
- for (c = connections; c != NULL; c = c->ac_next)
- {
- if (c->ikev1 && (name == NULL || streq(c->name, name)))
- count++;
- }
- array = malloc(sizeof(connection_t *)*count);
-
- count=0;
- for (c = connections; c != NULL; c = c->ac_next)
- {
- if (c->ikev1 && (name == NULL || streq(c->name, name)))
- array[count++]=c;
- }
-
- /* sort it! */
- qsort(array, count, sizeof(connection_t *), connection_compare_qsort);
-
- for (i = 0; i < count; i++)
- {
- const char *ifn;
- char instance[1 + 10 + 1];
- char prio[POLICY_PRIO_BUF];
-
- c = array[i];
-
- ifn = oriented(*c)? c->interface->rname : "";
-
- instance[0] = '\0';
- if (c->kind == CK_INSTANCE && c->instance_serial != 0)
- snprintf(instance, sizeof(instance), "[%lu]", c->instance_serial);
-
- /* show topology */
- {
- char topo[BUF_LEN];
- struct spd_route *sr = &c->spd;
- int num=0;
-
- while (sr)
- {
- (void) format_connection(topo, sizeof(topo), c, sr);
- whack_log(RC_COMMENT, "\"%s\"%s: %s; %s; eroute owner: #%lu"
- , c->name, instance, topo
- , enum_name(&routing_story, sr->routing)
- , sr->eroute_owner);
- sr = sr->next;
- num++;
- }
- }
-
- if (all)
- {
- /* show CAs if defined */
- if (c->spd.this.ca && c->spd.that.ca)
- {
- whack_log(RC_COMMENT, "\"%s\"%s: CAs: \"%Y\"...\"%Y\"",
- c->name, instance, c->spd.this.ca, c->spd.that.ca);
- }
- else if (c->spd.this.ca)
- {
- whack_log(RC_COMMENT, "\"%s\"%s: CAs: \"%Y\"...%%any",
- c->name, instance, c->spd.this.ca);
-
- }
- else if (c->spd.that.ca)
- {
- whack_log(RC_COMMENT, "\"%s\"%s: CAs: %%any...\"%Y\"",
- c->name, instance, c->spd.that.ca);
- }
-
- /* show group attributes if defined */
- if (c->spd.that.groups)
- {
- whack_log(RC_COMMENT, "\"%s\"%s: groups: %s"
- , c->name
- , instance
- , c->spd.that.groups->get_string(c->spd.that.groups));
- }
-
- whack_log(RC_COMMENT
- , "\"%s\"%s: ike_life: %lus; ipsec_life: %lus;"
- " rekey_margin: %lus; rekey_fuzz: %lu%%; keyingtries: %lu"
- , c->name
- , instance
- , (unsigned long) c->sa_ike_life_seconds
- , (unsigned long) c->sa_ipsec_life_seconds
- , (unsigned long) c->sa_rekey_margin
- , (unsigned long) c->sa_rekey_fuzz
- , (unsigned long) c->sa_keying_tries);
-
- /* show DPD parameters if defined */
-
- if (c->dpd_action != DPD_ACTION_NONE)
- whack_log(RC_COMMENT
- , "\"%s\"%s: dpd_action: %N;"
- " dpd_delay: %lus; dpd_timeout: %lus;"
- , c->name
- , instance
- , dpd_action_names, c->dpd_action
- , (unsigned long) c->dpd_delay
- , (unsigned long) c->dpd_timeout);
-
- if (c->policy_next)
- {
- whack_log(RC_COMMENT
- , "\"%s\"%s: policy_next: %s"
- , c->name, instance, c->policy_next->name);
- }
-
- /* Note: we display key_from_DNS_on_demand as if policy [lr]KOD */
- fmt_policy_prio(c->prio, prio);
- whack_log(RC_COMMENT
- , "\"%s\"%s: policy: %s%s%s; prio: %s; interface: %s; "
- , c->name
- , instance
- , prettypolicy(c->policy)
- , c->spd.this.key_from_DNS_on_demand? "+lKOD" : ""
- , c->spd.that.key_from_DNS_on_demand? "+rKOD" : ""
- , prio
- , ifn);
- }
-
- whack_log(RC_COMMENT
- , "\"%s\"%s: newest ISAKMP SA: #%ld; newest IPsec SA: #%ld; "
- , c->name
- , instance
- , c->newest_isakmp_sa
- , c->newest_ipsec_sa);
-
- if (all)
- {
- ike_alg_show_connection(c, instance);
- kernel_alg_show_connection(c, instance);
- }
- }
- if (count > 0)
- whack_log(RC_COMMENT, BLANK_FORMAT); /* spacer */
-
- free(array);
-}
-
-/* struct pending, the structure representing Quick Mode
- * negotiations delayed until a Keying Channel has been negotiated.
- * Essentially, a pending call to quick_outI1.
- */
-
-struct pending {
- int whack_sock;
- struct state *isakmp_sa;
- connection_t *connection;
- lset_t policy;
- unsigned long try;
- so_serial_t replacing;
-
- struct pending *next;
-};
-
-/* queue a Quick Mode negotiation pending completion of a suitable Main Mode */
-void add_pending(int whack_sock, struct state *isakmp_sa, connection_t *c,
- lset_t policy, unsigned long try, so_serial_t replacing)
-{
- bool already_queued = FALSE;
- struct pending *p = c->host_pair->pending;
-
- while (p)
- {
- if (streq(c->name, p->connection->name))
- {
- already_queued = TRUE;
- break;
- }
- p = p->next;
- }
- DBG(DBG_CONTROL,
- DBG_log("Queuing pending Quick Mode with %s \"%s\"%s"
- , ip_str(&c->spd.that.host_addr)
- , c->name
- , already_queued? " already done" : "")
- )
- if (already_queued)
- return;
-
- p = malloc_thing(struct pending);
- p->whack_sock = whack_sock;
- p->isakmp_sa = isakmp_sa;
- p->connection = c;
- p->policy = policy;
- p->try = try;
- p->replacing = replacing;
- p->next = c->host_pair->pending;
- c->host_pair->pending = p;
-}
-
-/* Release all the whacks awaiting the completion of this state.
- * This is accomplished by closing all the whack socket file descriptors.
- * We go to a lot of trouble to tell each whack, but to not tell it twice.
- */
-void release_pending_whacks(struct state *st, err_t story)
-{
- struct pending *p;
- struct stat stst;
-
- if (st->st_whack_sock == NULL_FD || fstat(st->st_whack_sock, &stst) != 0)
- zero(&stst); /* resulting st_dev/st_ino ought to be distinct */
-
- release_whack(st);
-
- for (p = st->st_connection->host_pair->pending; p != NULL; p = p->next)
- {
- if (p->isakmp_sa == st && p->whack_sock != NULL_FD)
- {
- struct stat pst;
-
- if (fstat(p->whack_sock, &pst) == 0
- && (stst.st_dev != pst.st_dev || stst.st_ino != pst.st_ino))
- {
- passert(whack_log_fd == NULL_FD);
- whack_log_fd = p->whack_sock;
- whack_log(RC_COMMENT
- , "%s for ISAKMP SA, but releasing whack for pending IPSEC SA"
- , story);
- whack_log_fd = NULL_FD;
- }
- close(p->whack_sock);
- p->whack_sock = NULL_FD;
- }
- }
-}
-
-static void delete_pending(struct pending **pp)
-{
- struct pending *p = *pp;
-
- *pp = p->next;
- if (p->connection)
- {
- connection_discard(p->connection);
- }
- close_any(p->whack_sock);
- free(p);
-}
-
-void unpend(struct state *st)
-{
- struct pending **pp
- , *p;
-
- for (pp = &st->st_connection->host_pair->pending; (p = *pp) != NULL; )
- {
- if (p->isakmp_sa == st)
- {
- DBG(DBG_CONTROL, DBG_log("unqueuing pending Quick Mode with %s \"%s\""
- , ip_str(&p->connection->spd.that.host_addr)
- , p->connection->name));
- (void) quick_outI1(p->whack_sock, st, p->connection, p->policy
- , p->try, p->replacing);
- p->whack_sock = NULL_FD; /* ownership transferred */
- p->connection = NULL; /* ownership transferred */
- delete_pending(pp);
- }
- else
- {
- pp = &p->next;
- }
- }
-}
-
-/* a Main Mode negotiation has been replaced; update any pending */
-void update_pending(struct state *os, struct state *ns)
-{
- struct pending *p;
-
- for (p = os->st_connection->host_pair->pending; p != NULL; p = p->next)
- {
- if (p->isakmp_sa == os)
- p->isakmp_sa = ns;
- if (p->connection->spd.this.host_port != ns->st_connection->spd.this.host_port)
- {
- p->connection->spd.this.host_port = ns->st_connection->spd.this.host_port;
- p->connection->spd.that.host_port = ns->st_connection->spd.that.host_port;
- }
- }
-}
-
-/* a Main Mode negotiation has failed; discard any pending */
-void flush_pending_by_state(struct state *st)
-{
- struct host_pair *hp = st->st_connection->host_pair;
-
- if (hp)
- {
- struct pending **pp
- , *p;
-
- for (pp = &hp->pending; (p = *pp) != NULL; )
- {
- if (p->isakmp_sa == st)
- delete_pending(pp);
- else
- pp = &p->next;
- }
- }
-}
-
-/* a connection has been deleted; discard any related pending */
-static void flush_pending_by_connection(connection_t *c)
-{
- if (c->host_pair)
- {
- struct pending **pp
- , *p;
-
- for (pp = &c->host_pair->pending; (p = *pp) != NULL; )
- {
- if (p->connection == c)
- {
- p->connection = NULL; /* prevent delete_pending from releasing */
- delete_pending(pp);
- }
- else
- {
- pp = &p->next;
- }
- }
- }
-}
-
-void show_pending_phase2(const struct host_pair *hp, const struct state *st)
-{
- const struct pending *p;
-
- for (p = hp->pending; p != NULL; p = p->next)
- {
- if (p->isakmp_sa == st)
- {
- /* connection-name state-number [replacing state-number] */
- char cip[CONN_INST_BUF];
-
- fmt_conn_instance(p->connection, cip);
- whack_log(RC_COMMENT, "#%lu: pending Phase 2 for \"%s\"%s replacing #%lu"
- , p->isakmp_sa->st_serialno
- , p->connection->name
- , cip
- , p->replacing);
- }
- }
-}
-
-/* Delete a connection if it is an instance and it is no longer in use.
- * We must be careful to avoid circularity:
- * we don't touch it if it is CK_GOING_AWAY.
- */
-void connection_discard(connection_t *c)
-{
- if (c->kind == CK_INSTANCE)
- {
- /* see if it is being used by a pending */
- struct pending *p;
-
- for (p = c->host_pair->pending; p != NULL; p = p->next)
- if (p->connection == c)
- return; /* in use, so we're done */
-
- if (!states_use_connection(c))
- delete_connection(c, FALSE);
- }
-}
-
-
-/* A template connection's eroute can be eclipsed by
- * either a %hold or an eroute for an instance iff
- * the template is a /32 -> /32. This requires some special casing.
- */
-
-long eclipse_count = 0;
-
-connection_t *eclipsed(connection_t *c, struct spd_route **esrp)
-{
- connection_t *ue;
- struct spd_route *sr1 = &c->spd;
-
- ue = NULL;
-
- while (sr1 && ue)
- {
- for (ue = connections; ue != NULL; ue = ue->ac_next)
- {
- struct spd_route *srue = &ue->spd;
-
- while (srue && srue->routing == RT_ROUTED_ECLIPSED
- && !(samesubnet(&sr1->this.client, &srue->this.client)
- && samesubnet(&sr1->that.client, &srue->that.client)))
- {
- srue = srue->next;
- }
- if (srue && srue->routing == RT_ROUTED_ECLIPSED)
- {
- *esrp = srue;
- break;
- }
- }
- }
- return ue;
-}
-
-/*
- * Local Variables:
- * c-basic-offset:4
- * c-style: pluto
- * End:
- */
diff --git a/src/pluto/connections.h b/src/pluto/connections.h
deleted file mode 100644
index e3775fcb0..000000000
--- a/src/pluto/connections.h
+++ /dev/null
@@ -1,366 +0,0 @@
-/* information about connections between hosts and clients
- * Copyright (C) 1998-2001 D. Hugh Redelmeier
- * Copyright (C) 2009-2010 Andreas Steffen - Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#ifndef _CONNECTIONS_H
-#define _CONNECTIONS_H
-
-#include <sys/queue.h>
-
-#include <utils/host.h>
-#include <utils/linked_list.h>
-#include <utils/identification.h>
-#include <credentials/ietf_attributes/ietf_attributes.h>
-
-#include "certs.h"
-#include "smartcard.h"
-#include "whack.h"
-
-/* There are two kinds of connections:
- * - ISAKMP connections, between hosts (for IKE communication)
- * - IPsec connections, between clients (for secure IP communication)
- *
- * An ISAKMP connection looks like:
- * host<--->host
- *
- * An IPsec connection looks like:
- * client-subnet<-->host<->nexthop<--->nexthop<->host<-->client-subnet
- *
- * For the connection to be relevant to this instance of Pluto,
- * exactly one of the hosts must be a public interface of our machine
- * known to this instance.
- *
- * The client subnet might simply be the host -- this is a
- * representation of "host mode".
- *
- * Each nexthop defaults to the neighbouring host's IP address.
- * The nexthop is a property of the pair of hosts, not each
- * individually. It is only needed for IPsec because of the
- * way IPsec is mixed into the kernel routing logic. Furthermore,
- * only this end's nexthop is actually used. Eventually, nexthop
- * will be unnecessary.
- *
- * Other information represented:
- * - each connection has a name: a chunk of uninterpreted text
- * that is unique for each connection.
- * - security requirements (currently just the "policy" flags from
- * the whack command to initiate the connection, but eventually
- * much more. Different for ISAKMP and IPsec connections.
- * - rekeying parameters:
- * + time an SA may live
- * + time before SA death that a rekeying should be attempted
- * (only by the initiator)
- * + number of times to attempt rekeying
- * - With the current KLIPS, we must route packets for a client
- * subnet through the ipsec interface (ipsec0). Only one
- * gateway can get traffic for a specific (client) subnet.
- * Furthermore, if the routing isn't in place, packets will
- * be sent in the clear.
- * "routing" indicates whether the routing has been done for
- * this connection. Note that several connections may claim
- * the same routing, as long as they agree about where the
- * packets are to be sent.
- * - With the current KLIPS, only one outbound IPsec SA bundle can be
- * used for a particular client. This is due to a limitation
- * of using only routing for selection. So only one IPsec state (SA)
- * may "own" the eroute. "eroute_owner" is the serial number of
- * this state, SOS_NOBODY if there is none. "routing" indicates
- * what kind of erouting has been done for this connection, if any.
- *
- * Details on routing is in constants.h
- *
- * Operations on Connections:
- *
- * - add a new connection (with all details) [whack command]
- * - delete a connection (by name) [whack command]
- * - initiate a connection (by name) [whack command]
- * - find a connection (by IP addresses of hosts)
- * [response to peer request; finding ISAKMP connection for IPsec connection]
- *
- * Some connections are templates, missing the address of the peer
- * (represented by INADDR_ANY). These are always arranged so that the
- * missing end is "that" (there can only be one missing end). These can
- * be instantiated (turned into real connections) by Pluto in one of two
- * different ways: Road Warrior Instantiation or Opportunistic
- * Instantiation. A template connection is marked for Opportunistic
- * Instantiation by specifying the peer client as 0.0.0.0/32 (or the IPV6
- * equivalent). Otherwise, it is suitable for Road Warrior Instantiation.
- *
- * Instantiation creates a new temporary connection, with the missing
- * details filled in. The resulting template lasts only as long as there
- * is a state that uses it.
- */
-
-/* connection policy priority: how important this policy is
- * - used to implement eroute-like precedence (augmented by a small
- * bonus for a routed connection).
- * - a whole number
- * - larger is more important
- * - three subcomponents. In order of decreasing significance:
- * + length of source subnet mask (8 bits)
- * + length of destination subnet mask (8 bits)
- * + bias (8 bit)
- * - a bias of 1 is added to allow prio BOTTOM_PRIO to be less than all
- * normal priorities
- * - other bias values are created on the fly to give mild preference
- * to certaion conditions (eg. routedness)
- * - priority is inherited -- an instance of a policy has the same priority
- * as the original policy, even though its subnets might be smaller.
- * - display format: n,m
- */
-typedef unsigned long policy_prio_t;
-#define BOTTOM_PRIO ((policy_prio_t)0) /* smaller than any real prio */
-#define set_policy_prio(c) { (c)->prio = \
- ((policy_prio_t)(c)->spd.this.client.maskbits << 16) \
- | ((policy_prio_t)(c)->spd.that.client.maskbits << 8) \
- | (policy_prio_t)1; }
-#define POLICY_PRIO_BUF (3+1+3+1)
-extern void fmt_policy_prio(policy_prio_t pp, char buf[POLICY_PRIO_BUF]);
-
-struct virtual_t;
-
-struct end {
- identification_t *id;
- ip_address host_addr, host_nexthop;
- host_t *host_srcip;
- ip_subnet client;
-
- bool is_left;
- bool key_from_DNS_on_demand;
- bool has_client;
- bool has_client_wildcard;
- bool has_port_wildcard;
- bool has_id_wildcards;
- bool has_natip;
- char *updown;
- u_int16_t host_port; /* host order */
- u_int16_t port; /* host order */
- u_int8_t protocol;
- cert_t *cert; /* end certificate */
- identification_t *ca; /* CA distinguished name */
- ietf_attributes_t *groups; /* access control groups */
- smartcard_t *sc; /* smartcard reader and key info */
- struct virtual_t *virt;
- bool modecfg; /* this end: request local address from server */
- /* that end: give local addresses to clients */
- char *pool; /* name of an associated virtual IP address pool */
- bool hostaccess; /* allow access to host via iptables INPUT/OUTPUT */
- /* rules if client behind host is a subnet */
- bool allow_any; /* IP address is subject to change */
- certpolicy_t sendcert; /* whether or not to send the certificate */
-};
-
-struct spd_route {
- struct spd_route *next;
- struct end this;
- struct end that;
- so_serial_t eroute_owner;
- enum routing_t routing; /* level of routing in place */
- uint32_t reqid;
- mark_t mark_in;
- mark_t mark_out;
-};
-
-typedef struct connection connection_t;
-
-struct connection {
- char *name;
- bool ikev1;
-
- lset_t policy;
- time_t sa_ike_life_seconds;
- time_t sa_ipsec_life_seconds;
- time_t sa_rekey_margin;
- unsigned long sa_rekey_fuzz;
- unsigned long sa_keying_tries;
-
- identification_t *xauth_identity; /* XAUTH identity */
-
- /* RFC 3706 DPD */
- time_t dpd_delay;
- time_t dpd_timeout;
- dpd_action_t dpd_action;
-
- char *log_file_name; /* name of log file */
- FILE *log_file; /* possibly open FILE */
- TAILQ_ENTRY(connection) log_link; /* linked list of open conns */
- bool log_file_err; /* only bitch once */
-
- struct spd_route spd;
-
- /* internal fields: */
-
- unsigned long instance_serial;
- policy_prio_t prio;
- bool instance_initiation_ok; /* this is an instance of a policy that mandates initiate */
- enum connection_kind kind;
- const struct iface *interface; /* filled in iff oriented */
-
- so_serial_t /* state object serial number */
- newest_isakmp_sa,
- newest_ipsec_sa;
-
-
-#ifdef DEBUG
- lset_t extra_debugging;
-#endif
-
- /* note: if the client is the gateway, the following must be equal */
- sa_family_t addr_family; /* between gateways */
- sa_family_t tunnel_addr_family; /* between clients */
-
- connection_t *policy_next; /* if multiple policies,
- next one to apply */
- struct gw_info *gw_info;
- struct alg_info_esp *alg_info_esp;
- struct alg_info_ike *alg_info_ike;
- struct host_pair *host_pair;
- connection_t *hp_next; /* host pair list link */
- connection_t *ac_next; /* all connections list link */
- linked_list_t *requested_ca; /* collected certificate requests */
- linked_list_t *requested; /* requested attributes with handlers */
- linked_list_t *attributes; /* configuration attributes with handlers */
- bool got_certrequest;
-};
-
-#define oriented(c) ((c).interface != NULL)
-extern bool orient(connection_t *c);
-
-extern bool same_peer_ids(const connection_t *c, const connection_t *d,
- identification_t *his_id);
-
-/* Format the topology of a connection end, leaving out defaults.
- * Largest left end looks like: client === host : port [ host_id ] --- hop
- * Note: if that==NULL, skip nexthop
- */
-#define END_BUF (SUBNETTOT_BUF + ADDRTOT_BUF + IDTOA_BUF + ADDRTOT_BUF + 10)
-extern size_t format_end(char *buf, size_t buf_len, const struct end *this,
- const struct end *that, bool is_left, lset_t policy);
-
-extern void add_connection(const whack_message_t *wm);
-extern void initiate_connection(const char *name, int whackfd);
-extern void initiate_opportunistic(const ip_address *our_client,
- const ip_address *peer_client,
- int transport_proto, bool held, int whackfd);
-extern void terminate_connection(const char *nm);
-extern void release_connection(connection_t *c, bool relations);
-extern void delete_connection(connection_t *c, bool relations);
-extern void delete_connections_by_name(const char *name, bool strict);
-extern void delete_every_connection(void);
-extern char *add_group_instance(connection_t *group, const ip_subnet *target);
-extern void remove_group_instance(const connection_t *group, const char *name);
-extern void release_dead_interfaces(void);
-extern void check_orientations(void);
-extern connection_t *route_owner(connection_t *c, struct spd_route **srp,
- connection_t **erop, struct spd_route **esrp);
-extern connection_t *shunt_owner(const ip_subnet *ours, const ip_subnet *his);
-
-extern bool uniqueIDs; /* --uniqueids? */
-extern void ISAKMP_SA_established(connection_t *c, so_serial_t serial);
-
-#define id_is_ipaddr(id) ((id)->get_type(id) == ID_IPV4_ADDR || \
- (id)->get_type(id) == ID_IPV6_ADDR)
-extern bool his_id_was_instantiated(const connection_t *c);
-
-struct state; /* forward declaration of tag (defined in state.h) */
-
-extern connection_t* con_by_name(const char *nm, bool strict);
-extern connection_t* find_host_connection(const ip_address *me,
- u_int16_t my_port,
- const ip_address *him,
- u_int16_t his_port, lset_t policy);
-extern connection_t* refine_host_connection(const struct state *st,
- identification_t *id,
- identification_t *peer_ca);
-extern connection_t* find_client_connection(connection_t *c,
- const ip_subnet *our_net,
- const ip_subnet *peer_net,
- const u_int8_t our_protocol,
- const u_int16_t out_port,
- const u_int8_t peer_protocol,
- const u_int16_t peer_port);
-extern connection_t* find_connection_by_reqid(uint32_t reqid);
-extern connection_t* find_connection_for_clients(struct spd_route **srp,
- const ip_address *our_client,
- const ip_address *peer_client,
- int transport_proto);
-extern void get_peer_ca_and_groups(connection_t *c,
- identification_t **peer_ca,
- ietf_attributes_t **peer_attributes);
-
-/* instantiating routines
- * Note: connection_discard() is in state.h because all its work
- * is looking through state objects.
- */
-struct gw_info; /* forward declaration of tag (defined in dnskey.h) */
-struct alg_info; /* forward declaration of tag (defined in alg_info.h) */
-extern connection_t *rw_instantiate(connection_t *c,
- const ip_address *him,
- u_int16_t his_port,
- const ip_subnet *his_net,
- identification_t *his_id);
-
-extern connection_t *oppo_instantiate(connection_t *c,
- const ip_address *him,
- identification_t *his_id,
- struct gw_info *gw,
- const ip_address *our_client,
- const ip_address *peer_client);
-
-extern connection_t
- *build_outgoing_opportunistic_connection(struct gw_info *gw,
- const ip_address *our_client,
- const ip_address *peer_client);
-
-#define CONN_INST_BUF BUF_LEN
-
-extern void fmt_conn_instance(const connection_t *c, char buf[CONN_INST_BUF]);
-
-/* operations on "pending", the structure representing Quick Mode
- * negotiations delayed until a Keying Channel has been negotiated.
- */
-
-struct pending; /* forward declaration (opaque outside connections.c) */
-
-extern void add_pending(int whack_sock, struct state *isakmp_sa,
- connection_t *c, lset_t policy, unsigned long try,
- so_serial_t replacing);
-
-extern void release_pending_whacks(struct state *st, err_t story);
-extern void unpend(struct state *st);
-extern void update_pending(struct state *os, struct state *ns);
-extern void flush_pending_by_state(struct state *st);
-extern void show_pending_phase2(const struct host_pair *hp, const struct state *st);
-
-extern void connection_discard(connection_t *c);
-
-/* A template connection's eroute can be eclipsed by
- * either a %hold or an eroute for an instance iff
- * the template is a /32 -> /32. This requires some special casing.
- */
-#define eclipsable(sr) (subnetishost(&(sr)->this.client) && subnetishost(&(sr)->that.client))
-extern long eclipse_count;
-extern connection_t *eclipsed(connection_t *c, struct spd_route **);
-
-
-/* print connection status */
-
-extern void show_connections_status(bool all, const char *name);
-extern int connection_compare(const connection_t *ca
- , const connection_t *cb);
-extern void update_host_pair(const char *why, connection_t *c
- , const ip_address *myaddr, u_int16_t myport
- , const ip_address *hisaddr, u_int16_t hisport);
-
-#endif /* _CONNECTIONS_H */
diff --git a/src/pluto/constants.c b/src/pluto/constants.c
deleted file mode 100644
index 73ec0bc54..000000000
--- a/src/pluto/constants.c
+++ /dev/null
@@ -1,1401 +0,0 @@
-/* tables of names for values defined in constants.h
- * Copyright (C) 1998-2002 D. Hugh Redelmeier.
- * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/*
- * Note that the array sizes are all specified; this is to enable range
- * checking by code that only includes constants.h.
- */
-
-#include <stddef.h>
-#include <string.h>
-#include <stdio.h>
-#include <netinet/in.h>
-
-#include <freeswan.h>
-
-#include <attributes/attributes.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "log.h"
-#include "packet.h"
-
-/* string naming compile-time options that have interop implications */
-
-const char compile_time_interop_options[] = ""
-#ifdef THREADS
- " THREADS"
-#endif
-#ifdef SMARTCARD
- " SMARTCARD"
-#endif
-#ifdef VENDORID
- " VENDORID"
-#endif
-#ifdef CISCO_QUIRKS
- " CISCO_QUIRKS"
-#endif
-#ifdef USE_KEYRR
- " KEYRR"
-#endif
- ;
-
-/* version */
-
-static const char *const version_name[] = {
- "ISAKMP Version 1.0",
-};
-
-enum_names version_names =
- { ISAKMP_MAJOR_VERSION<<ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION,
- ISAKMP_MAJOR_VERSION<<ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION,
- version_name, NULL };
-
-/* RFC 3706 Dead Peer Detection */
-
-ENUM(dpd_action_names, DPD_ACTION_NONE, DPD_ACTION_RESTART,
- "none",
- "clear",
- "hold",
- "restart"
-);
-
-/* Timer events */
-
-ENUM(timer_event_names, EVENT_NULL, EVENT_LOG_DAILY,
- "EVENT_NULL",
- "EVENT_REINIT_SECRET",
- "EVENT_SO_DISCARD",
- "EVENT_RETRANSMIT",
- "EVENT_SA_REPLACE",
- "EVENT_SA_REPLACE_IF_USED",
- "EVENT_SA_EXPIRE",
- "EVENT_NAT_T_KEEPALIVE",
- "EVENT_DPD",
- "EVENT_DPD_TIMEOUT",
- "EVENT_LOG_DAILY"
-);
-
-/* Domain of Interpretation */
-
-static const char *const doi_name[] = {
- "ISAKMP_DOI_ISAKMP",
- "ISAKMP_DOI_IPSEC",
-};
-
-enum_names doi_names = { ISAKMP_DOI_ISAKMP, ISAKMP_DOI_IPSEC, doi_name, NULL };
-
-/* debugging settings: a set of selections for reporting
- * These would be more naturally situated in log.h,
- * but they are shared with whack.
- * It turns out that "debug-" is clutter in all contexts this is used,
- * so we leave it off.
- */
-#ifdef DEBUG
-const char *const debug_bit_names[] = {
- "raw",
- "crypt",
- "parsing",
- "emitting",
- "control",
- "lifecycle",
- "kernel",
- "dns",
- "natt",
- "oppo",
- "controlmore",
-
- "private",
-
- "impair-delay-adns-key-answer",
- "impair-delay-adns-txt-answer",
- "impair-bust-mi2",
- "impair-bust-mr2",
-
- NULL
-};
-#endif
-
-/* State of exchanges */
-
-static const char *const state_name[] = {
- "STATE_UNDEFINED",
-
- "STATE_MAIN_R0",
- "STATE_MAIN_I1",
- "STATE_MAIN_R1",
- "STATE_MAIN_I2",
- "STATE_MAIN_R2",
- "STATE_MAIN_I3",
- "STATE_MAIN_R3",
- "STATE_MAIN_I4",
-
- "STATE_QUICK_R0",
- "STATE_QUICK_I1",
- "STATE_QUICK_R1",
- "STATE_QUICK_I2",
- "STATE_QUICK_R2",
-
- "STATE_INFO",
- "STATE_INFO_PROTECTED",
-
- "STATE_XAUTH_I0",
- "STATE_XAUTH_R1",
- "STATE_XAUTH_I1",
- "STATE_XAUTH_R2",
- "STATE_XAUTH_I2",
- "STATE_XAUTH_R3",
-
- "STATE_MODE_CFG_R0",
- "STATE_MODE_CFG_I1",
- "STATE_MODE_CFG_R1",
- "STATE_MODE_CFG_I2",
-
- "STATE_MODE_CFG_I0",
- "STATE_MODE_CFG_R3",
- "STATE_MODE_CFG_I3",
- "STATE_MODE_CFG_R4",
-
- "STATE_IKE_ROOF"
-};
-
-enum_names state_names =
- { STATE_UNDEFINED, STATE_IKE_ROOF-1, state_name, NULL };
-
-/* story for state */
-
-const char *const state_story[] = {
- "undefined state after error", /* STATE_UNDEFINED */
- "expecting MI1", /* STATE_MAIN_R0 */
- "sent MI1, expecting MR1", /* STATE_MAIN_I1 */
- "sent MR1, expecting MI2", /* STATE_MAIN_R1 */
- "sent MI2, expecting MR2", /* STATE_MAIN_I2 */
- "sent MR2, expecting MI3", /* STATE_MAIN_R2 */
- "sent MI3, expecting MR3", /* STATE_MAIN_I3 */
- "sent MR3, ISAKMP SA established", /* STATE_MAIN_R3 */
- "ISAKMP SA established", /* STATE_MAIN_I4 */
-
- "expecting QI1", /* STATE_QUICK_R0 */
- "sent QI1, expecting QR1", /* STATE_QUICK_I1 */
- "sent QR1, inbound IPsec SA installed, expecting QI2", /* STATE_QUICK_R1 */
- "sent QI2, IPsec SA established", /* STATE_QUICK_I2 */
- "IPsec SA established", /* STATE_QUICK_R2 */
-
- "got Informational Message in clear", /* STATE_INFO */
- "got encrypted Informational Message", /* STATE_INFO_PROTECTED */
-
- "expecting XAUTH request", /* STATE_XAUTH_I0 */
- "sent XAUTH request, expecting reply", /* STATE_XAUTH_R1 */
- "sent XAUTH reply, expecting status", /* STATE_XAUTH_I1 */
- "sent XAUTH status, expecting ack", /* STATE_XAUTH_R2 */
- "sent XAUTH ack, established", /* STATE_XAUTH_I2 */
- "received XAUTH ack, established", /* STATE_XAUTH_R3 */
-
- "expecting ModeCfg request", /* STATE_MODE_CFG_R0 */
- "sent ModeCfg request, expecting reply", /* STATE_MODE_CFG_I1 */
- "sent ModeCfg reply, established", /* STATE_MODE_CFG_R1 */
- "received ModeCfg reply, established", /* STATE_MODE_CFG_I2 */
-
- "expecting ModeCfg set", /* STATE_MODE_CFG_I0 */
- "sent ModeCfg set, expecting ack", /* STATE_MODE_CFG_R3 */
- "sent ModeCfg ack, established", /* STATE_MODE_CFG_I3 */
- "received ModeCfg ack, established", /* STATE_MODE_CFG_R4 */
-};
-
-/* kind of struct connection */
-
-static const char *const connection_kind_name[] = {
- "CK_GROUP", /* policy group: instantiates to template */
- "CK_TEMPLATE", /* abstract connection, with wildcard */
- "CK_PERMANENT", /* normal connection */
- "CK_INSTANCE", /* instance of template, created for a particular attempt */
- "CK_GOING_AWAY" /* instance being deleted -- don't delete again */
-};
-
-enum_names connection_kind_names =
- { CK_GROUP, CK_GOING_AWAY, connection_kind_name, NULL };
-
-/* routing status names */
-
-static const char *const routing_story_strings[] = {
- "unrouted", /* RT_UNROUTED: unrouted */
- "unrouted HOLD", /* RT_UNROUTED_HOLD: unrouted, but HOLD shunt installed */
- "eroute eclipsed", /* RT_ROUTED_ECLIPSED: RT_ROUTED_PROSPECTIVE except bare HOLD or instance has eroute */
- "prospective erouted", /* RT_ROUTED_PROSPECTIVE: routed, and prospective shunt installed */
- "erouted HOLD", /* RT_ROUTED_HOLD: routed, and HOLD shunt installed */
- "fail erouted", /* RT_ROUTED_FAILURE: routed, and failure-context shunt eroute installed */
- "erouted", /* RT_ROUTED_TUNNEL: routed, and erouted to an IPSEC SA group */
- "keyed, unrouted", /* RT_UNROUTED_KEYED: was routed+keyed, but it got turned into an outer policy */
-};
-
-enum_names routing_story =
- { RT_UNROUTED, RT_ROUTED_TUNNEL, routing_story_strings, NULL};
-
-/* Payload types (RFC 2408 "ISAKMP" section 3.1) */
-
-const char *const payload_name[] = {
- "ISAKMP_NEXT_NONE",
- "ISAKMP_NEXT_SA",
- "ISAKMP_NEXT_P",
- "ISAKMP_NEXT_T",
- "ISAKMP_NEXT_KE",
- "ISAKMP_NEXT_ID",
- "ISAKMP_NEXT_CERT",
- "ISAKMP_NEXT_CR",
- "ISAKMP_NEXT_HASH",
- "ISAKMP_NEXT_SIG",
- "ISAKMP_NEXT_NONCE",
- "ISAKMP_NEXT_N",
- "ISAKMP_NEXT_D",
- "ISAKMP_NEXT_VID",
- "ISAKMP_NEXT_MODECFG",
- "ISAKMP_NEXT_15",
- "ISAKMP_NEXT_16",
- "ISAKMP_NEXT_17",
- "ISAKMP_NEXT_18",
- "ISAKMP_NEXT_19",
- "ISAKMP_NEXT_NAT-D",
- "ISAKMP_NEXT_NAT-OA",
- NULL
-};
-
-const char *const payload_name_nat_d[] = {
- "ISAKMP_NEXT_NAT-D",
- "ISAKMP_NEXT_NAT-OA", NULL
-};
-
-static enum_names payload_names_nat_d =
- { ISAKMP_NEXT_NATD_DRAFTS, ISAKMP_NEXT_NATOA_DRAFTS, payload_name_nat_d, NULL };
-
-enum_names payload_names =
- { ISAKMP_NEXT_NONE, ISAKMP_NEXT_NATOA_RFC, payload_name, &payload_names_nat_d };
-
-/* Exchange types (note: two discontinuous ranges) */
-
-static const char *const exchange_name[] = {
- "ISAKMP_XCHG_NONE",
- "ISAKMP_XCHG_BASE",
- "ISAKMP_XCHG_IDPROT",
- "ISAKMP_XCHG_AO",
- "ISAKMP_XCHG_AGGR",
- "ISAKMP_XCHG_INFO",
- "ISAKMP_XCHG_MODE_CFG",
-};
-
-static const char *const exchange_name2[] = {
- "ISAKMP_XCHG_QUICK",
- "ISAKMP_XCHG_NGRP",
- "ISAKMP_XCHG_ACK_INFO",
-};
-
-static enum_names exchange_desc2 =
- { ISAKMP_XCHG_QUICK, ISAKMP_XCHG_ACK_INFO, exchange_name2, NULL };
-
-enum_names exchange_names =
- { ISAKMP_XCHG_NONE, ISAKMP_XCHG_MODE_CFG, exchange_name, &exchange_desc2 };
-
-/* Flag BITS */
-const char *const flag_bit_names[] = {
- "ISAKMP_FLAG_ENCRYPTION",
- "ISAKMP_FLAG_COMMIT",
- NULL
-};
-
-/* Situation BITS definition for IPsec DOI */
-
-const char *const sit_bit_names[] = {
- "SIT_IDENTITY_ONLY",
- "SIT_SECRECY",
- "SIT_INTEGRITY",
- NULL
-};
-
-/* Protocol IDs (RFC 2407 "IPsec DOI" section 4.4.1) */
-
-static const char *const protocol_name[] = {
- "PROTO_ISAKMP",
- "PROTO_IPSEC_AH",
- "PROTO_IPSEC_ESP",
- "PROTO_IPCOMP",
-};
-
-enum_names protocol_names =
- { PROTO_ISAKMP, PROTO_IPCOMP, protocol_name, NULL };
-
-/* IPsec ISAKMP transform values */
-
-static const char *const isakmp_transform_name[] = {
- "KEY_IKE",
-};
-
-enum_names isakmp_transformid_names =
- { KEY_IKE, KEY_IKE, isakmp_transform_name, NULL };
-
-/* IPsec AH transform values */
-
-static const char *const ah_transform_name[] = {
- "HMAC_MD5",
- "HMAC_SHA1",
- "DES_MAC",
- "HMAC_SHA2_256",
- "HMAC_SHA2_384",
- "HMAC_SHA2_512",
- "HMAC_RIPEMD",
- "AES_XCBC_96",
- "SIG_RSA",
- "AES_128_GMAC",
- "AES_192_GMAC",
- "AES_256_GMAC"
-};
-
-static const char *const ah_transform_name_high[] = {
- "HMAC_SHA2_256_96"
-};
-
-enum_names ah_transform_names_high =
- { AH_SHA2_256_96, AH_SHA2_256_96, ah_transform_name_high, NULL };
-
-enum_names ah_transform_names =
- { AH_MD5, AH_AES_256_GMAC, ah_transform_name, &ah_transform_names_high };
-
-/* IPsec ESP transform values */
-
-static const char *const esp_transform_name[] = {
- "DES_IV64",
- "DES_CBC",
- "3DES_CBC",
- "RC5_CBC",
- "IDEA_CBC",
- "CAST_CBC",
- "BLOWFISH_CBC",
- "3IDEA",
- "DES_IV32",
- "RC4",
- "NULL",
- "AES_CBC",
- "AES_CTR",
- "AES_CCM_8",
- "AES_CCM_12",
- "AES_CCM_16",
- "UNASSIGNED_17",
- "AES_GCM_8",
- "AES_GCM_12",
- "AES_GCM_16",
- "SEED_CBC",
- "CAMELLIA_CBC",
- "AES_GMAC"
-};
-
-static const char *const esp_transform_name_high[] = {
- "SERPENT_CBC",
- "TWOFISH_CBC"
-};
-
-enum_names esp_transform_names_high =
- { ESP_SERPENT, ESP_TWOFISH, esp_transform_name_high, NULL };
-
-enum_names esp_transform_names =
- { ESP_DES_IV64, ESP_AES_GMAC, esp_transform_name, &esp_transform_names_high };
-
-/* IPCOMP transform values */
-
-static const char *const ipcomp_transform_name[] = {
- "IPCOMP_OUI",
- "IPCOMP_DEFLATE",
- "IPCOMP_LZS",
- "IPCOMP_LZJH",
-};
-
-enum_names ipcomp_transformid_names =
- { IPCOMP_OUI, IPCOMP_LZJH, ipcomp_transform_name, NULL };
-
-/* Identification type values */
-
-static const char *const ident_name[] = {
- "ID_IPV4_ADDR",
- "ID_FQDN",
- "ID_USER_FQDN",
- "ID_IPV4_ADDR_SUBNET",
- "ID_IPV6_ADDR",
- "ID_IPV6_ADDR_SUBNET",
- "ID_IPV4_ADDR_RANGE",
- "ID_IPV6_ADDR_RANGE",
- "ID_DER_ASN1_DN",
- "ID_DER_ASN1_GN",
- "ID_KEY_ID",
-};
-
-enum_names ident_names =
- { ID_IPV4_ADDR, ID_KEY_ID, ident_name, NULL };
-
-/* Certificate type values */
-
-static const char *const cert_type_name[] = {
- "CERT_NONE",
- "CERT_PKCS7_WRAPPED_X509",
- "CERT_PGP",
- "CERT_DNS_SIGNED_KEY",
- "CERT_X509_SIGNATURE",
- "CERT_X509_KEY_EXCHANGE",
- "CERT_KERBEROS_TOKENS",
- "CERT_CRL",
- "CERT_ARL",
- "CERT_SPKI",
- "CERT_X509_ATTRIBUTE",
-};
-
-enum_names cert_type_names =
- { CERT_NONE, CERT_X509_ATTRIBUTE, cert_type_name, NULL };
-
-/* Certificate policy names */
-
-ENUM(cert_policy_names, CERT_ALWAYS_SEND, CERT_NEVER_SEND,
- "ALWAYS_SEND",
- "SEND_IF_ASKED",
- "NEVER_SEND",
-);
-
-/* Goal BITs for establishing an SA
- * Note: we drop the POLICY_ prefix so that logs are more concise.
- */
-
-const char *const sa_policy_bit_names[] = {
- "PSK",
- "PUBKEY",
- "ENCRYPT",
- "AUTHENTICATE",
- "COMPRESS",
- "TUNNEL",
- "PFS",
- "DISABLEARRIVALCHECK",
- "SHUNT0",
- "SHUNT1",
- "FAILSHUNT0",
- "FAILSHUNT1",
- "DONTREKEY",
- "OPPORTUNISTIC",
- "GROUP",
- "GROUTED",
- "UP",
- "MODECFGPUSH",
- "XAUTHPSK",
- "XAUTHRSASIG",
- "XAUTHSERVER",
- "DONTREAUTH",
- "BEET",
- "MOBIKE",
- "PROXY",
- NULL
-};
-
-const char *const policy_shunt_names[4] = {
- "TRAP",
- "PASS",
- "DROP",
- "REJECT",
-};
-
-const char *const policy_fail_names[4] = {
- "NONE",
- "PASS",
- "DROP",
- "REJECT",
-};
-
-/* Oakley transform attributes
- * oakley_attr_bit_names does double duty: it is used for enum names
- * and bit names.
- */
-
-const char *const oakley_attr_bit_names[] = {
- "OAKLEY_ENCRYPTION_ALGORITHM",
- "OAKLEY_HASH_ALGORITHM",
- "OAKLEY_AUTHENTICATION_METHOD",
- "OAKLEY_GROUP_DESCRIPTION",
- "OAKLEY_GROUP_TYPE",
- "OAKLEY_GROUP_PRIME",
- "OAKLEY_GROUP_GENERATOR_ONE",
- "OAKLEY_GROUP_GENERATOR_TWO",
- "OAKLEY_GROUP_CURVE_A",
- "OAKLEY_GROUP_CURVE_B",
- "OAKLEY_LIFE_TYPE",
- "OAKLEY_LIFE_DURATION",
- "OAKLEY_PRF",
- "OAKLEY_KEY_LENGTH",
- "OAKLEY_FIELD_SIZE",
- "OAKLEY_GROUP_ORDER",
- "OAKLEY_BLOCK_SIZE",
- NULL
-};
-
-static const char *const oakley_var_attr_name[] = {
- "OAKLEY_GROUP_PRIME (variable length)",
- "OAKLEY_GROUP_GENERATOR_ONE (variable length)",
- "OAKLEY_GROUP_GENERATOR_TWO (variable length)",
- "OAKLEY_GROUP_CURVE_A (variable length)",
- "OAKLEY_GROUP_CURVE_B (variable length)",
- NULL,
- "OAKLEY_LIFE_DURATION (variable length)",
- NULL,
- NULL,
- NULL,
- "OAKLEY_GROUP_ORDER (variable length)",
-};
-
-static enum_names oakley_attr_desc_tv = {
- OAKLEY_ENCRYPTION_ALGORITHM + ISAKMP_ATTR_AF_TV,
- OAKLEY_GROUP_ORDER + ISAKMP_ATTR_AF_TV, oakley_attr_bit_names, NULL };
-
-enum_names oakley_attr_names = {
- OAKLEY_GROUP_PRIME, OAKLEY_GROUP_ORDER,
- oakley_var_attr_name, &oakley_attr_desc_tv };
-
-/* for each Oakley attribute, which enum_names describes its values? */
-enum_names *oakley_attr_val_descs[] = {
- NULL, /* (none) */
- &oakley_enc_names, /* OAKLEY_ENCRYPTION_ALGORITHM */
- &oakley_hash_names, /* OAKLEY_HASH_ALGORITHM */
- &oakley_auth_names, /* OAKLEY_AUTHENTICATION_METHOD */
- &oakley_group_names, /* OAKLEY_GROUP_DESCRIPTION */
- &oakley_group_type_names,/* OAKLEY_GROUP_TYPE */
- NULL, /* OAKLEY_GROUP_PRIME */
- NULL, /* OAKLEY_GROUP_GENERATOR_ONE */
- NULL, /* OAKLEY_GROUP_GENERATOR_TWO */
- NULL, /* OAKLEY_GROUP_CURVE_A */
- NULL, /* OAKLEY_GROUP_CURVE_B */
- &oakley_lifetime_names, /* OAKLEY_LIFE_TYPE */
- NULL, /* OAKLEY_LIFE_DURATION */
- &oakley_prf_names, /* OAKLEY_PRF */
- NULL, /* OAKLEY_KEY_LENGTH */
- NULL, /* OAKLEY_FIELD_SIZE */
- NULL, /* OAKLEY_GROUP_ORDER */
-};
-
-/* IPsec DOI attributes (RFC 2407 "IPsec DOI" section 4.5) */
-
-static const char *const ipsec_attr_name[] = {
- "SA_LIFE_TYPE",
- "SA_LIFE_DURATION",
- "GROUP_DESCRIPTION",
- "ENCAPSULATION_MODE",
- "AUTH_ALGORITHM",
- "KEY_LENGTH",
- "KEY_ROUNDS",
- "COMPRESS_DICT_SIZE",
- "COMPRESS_PRIVATE_ALG",
-};
-
-static const char *const ipsec_var_attr_name[] = {
- "SA_LIFE_DURATION (variable length)",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "COMPRESS_PRIVATE_ALG (variable length)",
-};
-
-static enum_names ipsec_attr_desc_tv = {
- SA_LIFE_TYPE + ISAKMP_ATTR_AF_TV,
- COMPRESS_PRIVATE_ALG + ISAKMP_ATTR_AF_TV,
- ipsec_attr_name, NULL };
-
-enum_names ipsec_attr_names = {
- SA_LIFE_DURATION, COMPRESS_PRIVATE_ALG,
- ipsec_var_attr_name, &ipsec_attr_desc_tv };
-
-/* for each IPsec attribute, which enum_names describes its values? */
-enum_names *ipsec_attr_val_descs[] = {
- NULL, /* (none) */
- &sa_lifetime_names, /* SA_LIFE_TYPE */
- NULL, /* SA_LIFE_DURATION */
- &oakley_group_names, /* GROUP_DESCRIPTION */
- &enc_mode_names, /* ENCAPSULATION_MODE */
- &auth_alg_names, /* AUTH_ALGORITHM */
- NULL, /* KEY_LENGTH */
- NULL, /* KEY_ROUNDS */
- NULL, /* COMPRESS_DICT_SIZE */
- NULL, /* COMPRESS_PRIVATE_ALG */
-};
-
-/* SA Lifetime Type attribute */
-
-static const char *const sa_lifetime_name[] = {
- "SA_LIFE_TYPE_SECONDS",
- "SA_LIFE_TYPE_KBYTES",
-};
-
-enum_names sa_lifetime_names =
- { SA_LIFE_TYPE_SECONDS, SA_LIFE_TYPE_KBYTES, sa_lifetime_name, NULL };
-
-/* Encapsulation Mode attribute */
-
-static const char *const enc_mode_name[] = {
- "ENCAPSULATION_MODE_TUNNEL",
- "ENCAPSULATION_MODE_TRANSPORT",
- "ENCAPSULATION_MODE_UDP_TUNNEL",
- "ENCAPSULATION_MODE_UDP_TRANSPORT",
-};
-
-static const char *const enc_udp_mode_name[] = {
- "ENCAPSULATION_MODE_UDP_TUNNEL",
- "ENCAPSULATION_MODE_UDP_TRANSPORT",
- };
-
-static enum_names enc_udp_mode_names =
- { ENCAPSULATION_MODE_UDP_TUNNEL_DRAFTS, ENCAPSULATION_MODE_UDP_TRANSPORT_DRAFTS, enc_udp_mode_name, NULL };
-
-enum_names enc_mode_names =
- { ENCAPSULATION_MODE_TUNNEL, ENCAPSULATION_MODE_UDP_TRANSPORT_RFC, enc_mode_name, &enc_udp_mode_names };
-
-/* Auth Algorithm attribute */
-
-static const char *const auth_alg_name[] = {
- "AUTH_NONE",
- "HMAC_MD5",
- "HMAC_SHA1",
- "DES_MAC",
- "KPDK",
- "HMAC_SHA2_256",
- "HMAC_SHA2_384",
- "HMAC_SHA2_512",
- "HMAC_RIPEMD",
- "AES_XCBC_96",
- "SIG_RSA"
-};
-
-static const char *const extended_auth_alg_name[] = {
- "NULL",
- "HMAC_SHA2_256_96"
-};
-
-enum_names extended_auth_alg_names =
- { AUTH_ALGORITHM_NULL, AUTH_ALGORITHM_HMAC_SHA2_256_96,
- extended_auth_alg_name, NULL };
-
-enum_names auth_alg_names =
- { AUTH_ALGORITHM_NONE, AUTH_ALGORITHM_SIG_RSA,
- auth_alg_name, &extended_auth_alg_names };
-
-/* From draft-beaulieu-ike-xauth */
-static const char *const xauth_type_name[] = {
- "Generic",
- "RADIUS-CHAP",
- "OTP",
- "S/KEY",
-};
-
-enum_names xauth_type_names =
- { XAUTH_TYPE_GENERIC, XAUTH_TYPE_SKEY, xauth_type_name, NULL};
-
-/* From draft-beaulieu-ike-xauth */
-static const char *const xauth_attr_tv_name[] = {
- "XAUTH_TYPE",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "XAUTH_STATUS",
-};
-
-enum_names xauth_attr_tv_names = {
- XAUTH_TYPE + ISAKMP_ATTR_AF_TV,
- XAUTH_STATUS + ISAKMP_ATTR_AF_TV, xauth_attr_tv_name, NULL };
-
-static const char *const unity_attr_name[] = {
- "UNITY_BANNER",
- "UNITY_SAVE_PASSWD",
- "UNITY_DEF_DOMAIN",
- "UNITY_SPLITDNS_NAME",
- "UNITY_SPLIT_INCLUDE",
- "UNITY_NATT_PORT",
- "UNITY_LOCAL_LAN",
- "UNITY_PFS",
- "UNITY_FW_TYPE",
- "UNITY_BACKUP_SERVERS",
- "UNITY_DDNS_HOSTNAME",
-};
-
-enum_names unity_attr_names =
- { UNITY_BANNER , UNITY_DDNS_HOSTNAME, unity_attr_name , &xauth_attr_tv_names };
-
-static const char *const microsoft_attr_name[] = {
- "INTERNAL_IP4_SERVER",
- "INTERNAL_IP6_SERVER",
-};
-
-enum_names microsoft_attr_names =
- { INTERNAL_IP4_SERVER, INTERNAL_IP6_SERVER, microsoft_attr_name , &unity_attr_names };
-
-static const char *const xauth_attr_name[] = {
- "XAUTH_USER_NAME",
- "XAUTH_USER_PASSWORD",
- "XAUTH_PASSCODE",
- "XAUTH_MESSAGE",
- "XAUTH_CHALLENGE",
- "XAUTH_DOMAIN",
- "XAUTH_STATUS (wrong TLV syntax, should be TV)",
- "XAUTH_NEXT_PIN",
- "XAUTH_ANSWER",
-};
-
-enum_names xauth_attr_names =
- { XAUTH_USER_NAME , XAUTH_ANSWER, xauth_attr_name , &microsoft_attr_names };
-
-static const char *const modecfg_attr_name[] = {
- "INTERNAL_IP4_ADDRESS",
- "INTERNAL_IP4_NETMASK",
- "INTERNAL_IP4_DNS",
- "INTERNAL_IP4_NBNS",
- "INTERNAL_ADDRESS_EXPIRY",
- "INTERNAL_IP4_DHCP",
- "APPLICATION_VERSION",
- "INTERNAL_IP6_ADDRESS",
- "INTERNAL_IP6_NETMASK",
- "INTERNAL_IP6_DNS",
- "INTERNAL_IP6_NBNS",
- "INTERNAL_IP6_DHCP",
- "INTERNAL_IP4_SUBNET",
- "SUPPORTED_ATTRIBUTES",
- "INTERNAL_IP6_SUBNET",
-};
-
-enum_names modecfg_attr_names =
- { INTERNAL_IP4_ADDRESS, INTERNAL_IP6_SUBNET, modecfg_attr_name , &xauth_attr_names };
-
-/* Oakley Lifetime Type attribute */
-
-static const char *const oakley_lifetime_name[] = {
- "OAKLEY_LIFE_SECONDS",
- "OAKLEY_LIFE_KILOBYTES",
-};
-
-enum_names oakley_lifetime_names =
- { OAKLEY_LIFE_SECONDS, OAKLEY_LIFE_KILOBYTES, oakley_lifetime_name, NULL };
-
-/* Oakley PRF attribute (none defined) */
-
-enum_names oakley_prf_names =
- { 1, 0, NULL, NULL };
-
-/* Oakley Encryption Algorithm attribute */
-
-static const char *const oakley_enc_name[] = {
- "DES_CBC",
- "IDEA_CBC",
- "BLOWFISH_CBC",
- "RC5_R16_B64_CBC",
- "3DES_CBC",
- "CAST_CBC",
- "AES_CBC",
- "CAMELLIA_CBC"
-};
-
-#ifdef NO_EXTRA_IKE
-enum_names oakley_enc_names =
- { OAKLEY_DES_CBC, OAKLEY_CAMELLIA_CBC, oakley_enc_name, NULL };
-#else
-static const char *const oakley_enc_name_draft_aes_cbc_02[] = {
- "MARS_CBC" /* 65001 */,
- "RC6_CBC" /* 65002 */,
- "ID_65003" /* 65003 */,
- "SERPENT_CBC" /* 65004 */,
- "TWOFISH_CBC" /* 65005 */,
-};
-
-static const char *const oakley_enc_name_ssh[] = {
- "TWOFISH_CBC_SSH",
-};
-
-enum_names oakley_enc_names_ssh =
- { OAKLEY_TWOFISH_CBC_SSH, OAKLEY_TWOFISH_CBC_SSH, oakley_enc_name_ssh
- , NULL };
-
-enum_names oakley_enc_names_draft_aes_cbc_02 =
- { OAKLEY_MARS_CBC, OAKLEY_TWOFISH_CBC, oakley_enc_name_draft_aes_cbc_02
- , &oakley_enc_names_ssh };
-
-enum_names oakley_enc_names =
- { OAKLEY_DES_CBC, OAKLEY_CAMELLIA_CBC, oakley_enc_name
- , &oakley_enc_names_draft_aes_cbc_02 };
-#endif
-
-/* Oakley Hash Algorithm attribute */
-
-static const char *const oakley_hash_name[] = {
- "HMAC_MD5",
- "HMAC_SHA1",
- "HMAC_TIGER",
- "HMAC_SHA2_256",
- "HMAC_SHA2_384",
- "HMAC_SHA2_512",
-};
-
-enum_names oakley_hash_names =
- { OAKLEY_MD5, OAKLEY_SHA2_512, oakley_hash_name, NULL };
-
-/* Oakley Authentication Method attribute */
-
-static const char *const oakley_auth_name1[] = {
- "pre-shared key",
- "DSS signature",
- "RSA signature",
- "RSA encryption",
- "RSA encryption revised",
- "ElGamal encryption",
- "ELGamal encryption revised",
- "ECDSA signature",
- "ECDSA-256 signature",
- "ECDSA-384 signature",
- "ECDSA-521-signature",
-};
-
-static const char *const oakley_auth_name2[] = {
- "HybridInitRSA",
- "HybridRespRSA",
- "HybridInitDSS",
- "HybridRespDSS",
-};
-
-static const char *const oakley_auth_name3[] = {
- "XAUTHInitPreShared",
- "XAUTHRespPreShared",
- "XAUTHInitDSS",
- "XAUTHRespDSS",
- "XAUTHInitRSA",
- "XAUTHRespRSA",
- "XAUTHInitRSAEncryption",
- "XAUTHRespRSAEncryption",
- "XAUTHInitRSARevisedEncryption",
- "XAUTHRespRSARevisedEncryption",
-};
-
-static enum_names oakley_auth_names1 =
- { OAKLEY_PRESHARED_KEY, OAKLEY_ECDSA_521
- , oakley_auth_name1, NULL };
-
-static enum_names oakley_auth_names2 =
- { HybridInitRSA, HybridRespDSS
- , oakley_auth_name2, &oakley_auth_names1 };
-
-enum_names oakley_auth_names =
- { XAUTHInitPreShared, XAUTHRespRSARevisedEncryption
- , oakley_auth_name3, &oakley_auth_names2 };
-
-/* Oakley Group Description attribute */
-
-static const char *const oakley_group_name[] = {
- "MODP_768",
- "MODP_1024",
- "GP_155",
- "GP_185",
- "MODP_1536",
-};
-
-static const char *const oakley_group_name_rfc3526[] = {
- "MODP_2048",
- "MODP_3072",
- "MODP_4096",
- "MODP_6144",
- "MODP_8192"
-};
-
-static const char *const oakley_group_name_rfc4753[] = {
- "ECP_256",
- "ECP_384",
- "ECP_521"
-};
-
-static const char *const oakley_group_name_rfc5114[] = {
- "MODP_1024_160",
- "MODP_2048_224",
- "MODP_2048_256",
- "ECP_192",
- "ECP_224"
-};
-
-enum_names oakley_group_names_rfc5114 =
- { MODP_1024_160, ECP_224_BIT,
- oakley_group_name_rfc5114, NULL };
-
-enum_names oakley_group_names_rfc4753 =
- { ECP_256_BIT, ECP_521_BIT,
- oakley_group_name_rfc4753, &oakley_group_names_rfc5114 };
-
-enum_names oakley_group_names_rfc3526 =
- { MODP_2048_BIT, MODP_8192_BIT,
- oakley_group_name_rfc3526, &oakley_group_names_rfc4753 };
-
-enum_names oakley_group_names =
- { MODP_768_BIT, MODP_1536_BIT,
- oakley_group_name, &oakley_group_names_rfc3526 };
-
-/* Oakley Group Type attribute */
-
-static const char *const oakley_group_type_name[] = {
- "OAKLEY_GROUP_TYPE_MODP",
- "OAKLEY_GROUP_TYPE_ECP",
- "OAKLEY_GROUP_TYPE_EC2N",
-};
-
-enum_names oakley_group_type_names =
- { OAKLEY_GROUP_TYPE_MODP, OAKLEY_GROUP_TYPE_EC2N, oakley_group_type_name, NULL };
-
-/* Notify messages -- error types */
-
-static const char *const notification_name[] = {
- "INVALID_PAYLOAD_TYPE",
- "DOI_NOT_SUPPORTED",
- "SITUATION_NOT_SUPPORTED",
- "INVALID_COOKIE",
- "INVALID_MAJOR_VERSION",
- "INVALID_MINOR_VERSION",
- "INVALID_EXCHANGE_TYPE",
- "INVALID_FLAGS",
- "INVALID_MESSAGE_ID",
- "INVALID_PROTOCOL_ID",
- "INVALID_SPI",
- "INVALID_TRANSFORM_ID",
- "ATTRIBUTES_NOT_SUPPORTED",
- "NO_PROPOSAL_CHOSEN",
- "BAD_PROPOSAL_SYNTAX",
- "PAYLOAD_MALFORMED",
- "INVALID_KEY_INFORMATION",
- "INVALID_ID_INFORMATION",
- "INVALID_CERT_ENCODING",
- "INVALID_CERTIFICATE",
- "CERT_TYPE_UNSUPPORTED",
- "INVALID_CERT_AUTHORITY",
- "INVALID_HASH_INFORMATION",
- "AUTHENTICATION_FAILED",
- "INVALID_SIGNATURE",
- "ADDRESS_NOTIFICATION",
- "NOTIFY_SA_LIFETIME",
- "CERTIFICATE_UNAVAILABLE",
- "UNSUPPORTED_EXCHANGE_TYPE",
- "UNEQUAL_PAYLOAD_LENGTHS",
-};
-
-static const char *const notification_status_name[] = {
- "CONNECTED",
-};
-
-static const char *const ipsec_notification_name[] = {
- "IPSEC_RESPONDER_LIFETIME",
- "IPSEC_REPLAY_STATUS",
- "IPSEC_INITIAL_CONTACT",
-};
-
-static const char *const notification_dpd_name[] = {
- "R_U_THERE",
- "R_U_THERE_ACK",
-};
-
-static const char *const notification_juniper_name[] = {
- "NS_NHTB_INFORM",
-};
-
-enum_names notification_juniper_names =
- { NS_NHTB_INFORM, NS_NHTB_INFORM,
- notification_juniper_name, NULL };
-
-enum_names notification_dpd_names =
- { R_U_THERE, R_U_THERE_ACK,
- notification_dpd_name, &notification_juniper_names };
-
-enum_names ipsec_notification_names =
- { IPSEC_RESPONDER_LIFETIME, IPSEC_INITIAL_CONTACT,
- ipsec_notification_name, &notification_dpd_names };
-
-enum_names notification_status_names =
- { ISAKMP_CONNECTED, ISAKMP_CONNECTED,
- notification_status_name, &ipsec_notification_names };
-
-enum_names notification_names =
- { ISAKMP_INVALID_PAYLOAD_TYPE, ISAKMP_UNEQUAL_PAYLOAD_LENGTHS,
- notification_name, &notification_status_names };
-
-/* MODECFG
- * From draft-dukes-ike-mode-cfg
- */
-const char *const attr_msg_type_name[] = {
- "ISAKMP_CFG_RESERVED",
- "ISAKMP_CFG_REQUEST",
- "ISAKMP_CFG_REPLY",
- "ISAKMP_CFG_SET",
- "ISAKMP_CFG_ACK",
- NULL
-};
-
-enum_names attr_msg_type_names =
- { 0 , ISAKMP_CFG_ACK, attr_msg_type_name , NULL };
-
-/* socket address family info */
-
-static const char *const af_inet_name[] = {
- "AF_INET",
-};
-
-static const char *const af_inet6_name[] = {
- "AF_INET6",
-};
-
-static enum_names af_names6 = { AF_INET6, AF_INET6, af_inet6_name, NULL };
-
-enum_names af_names = { AF_INET, AF_INET, af_inet_name, &af_names6 };
-
-static ip_address ipv4_any, ipv6_any;
-static ip_subnet ipv4_wildcard, ipv6_wildcard;
-static ip_subnet ipv4_all, ipv6_all;
-
-const struct af_info af_inet4_info = {
- AF_INET,
- "AF_INET",
- sizeof(struct in_addr),
- sizeof(struct sockaddr_in),
- 32,
- ID_IPV4_ADDR, ID_IPV4_ADDR_SUBNET, ID_IPV4_ADDR_RANGE,
- &ipv4_any, &ipv4_wildcard, &ipv4_all,
-};
-
-const struct af_info af_inet6_info = {
- AF_INET6,
- "AF_INET6",
- sizeof(struct in6_addr),
- sizeof(struct sockaddr_in6),
- 128,
- ID_IPV6_ADDR, ID_IPV6_ADDR_SUBNET, ID_IPV6_ADDR_RANGE,
- &ipv6_any, &ipv6_wildcard, &ipv6_all,
-};
-
-const struct af_info *
-aftoinfo(int af)
-{
- switch (af)
- {
- case AF_INET:
- return &af_inet4_info;
- case AF_INET6:
- return &af_inet6_info;
- default:
- return NULL;
- }
-}
-
-bool subnetisnone(const ip_subnet *sn)
-{
- ip_address base;
-
- networkof(sn, &base);
- return isanyaddr(&base) && subnetishost(sn);
-}
-
-#ifdef ADNS
-
-/* BIND enumerated types */
-
-#include <arpa/nameser.h>
-
-static const char *const rr_type_name[] = {
- "T_A", /* 1 host address */
- "T_NS", /* 2 authoritative server */
- "T_MD", /* 3 mail destination */
- "T_MF", /* 4 mail forwarder */
- "T_CNAME", /* 5 canonical name */
- "T_SOA", /* 6 start of authority zone */
- "T_MB", /* 7 mailbox domain name */
- "T_MG", /* 8 mail group member */
- "T_MR", /* 9 mail rename name */
- "T_NULL", /* 10 null resource record */
- "T_WKS", /* 11 well known service */
- "T_PTR", /* 12 domain name pointer */
- "T_HINFO", /* 13 host information */
- "T_MINFO", /* 14 mailbox information */
- "T_MX", /* 15 mail routing information */
- "T_TXT", /* 16 text strings */
- "T_RP", /* 17 responsible person */
- "T_AFSDB", /* 18 AFS cell database */
- "T_X25", /* 19 X_25 calling address */
- "T_ISDN", /* 20 ISDN calling address */
- "T_RT", /* 21 router */
- "T_NSAP", /* 22 NSAP address */
- "T_NSAP_PTR", /* 23 reverse NSAP lookup (deprecated) */
- "T_SIG", /* 24 security signature */
- "T_KEY", /* 25 security key */
- "T_PX", /* 26 X.400 mail mapping */
- "T_GPOS", /* 27 geographical position (withdrawn) */
- "T_AAAA", /* 28 IP6 Address */
- "T_LOC", /* 29 Location Information */
- "T_NXT", /* 30 Next Valid Name in Zone */
- "T_EID", /* 31 Endpoint identifier */
- "T_NIMLOC", /* 32 Nimrod locator */
- "T_SRV", /* 33 Server selection */
- "T_ATMA", /* 34 ATM Address */
- "T_NAPTR", /* 35 Naming Authority PoinTeR */
- NULL
-};
-
-enum_names rr_type_names = { T_A, T_NAPTR, rr_type_name, NULL };
-
-/* Query type values which do not appear in resource records */
-static const char *const rr_qtype_name[] = {
- "T_IXFR", /* 251 incremental zone transfer */
- "T_AXFR", /* 252 transfer zone of authority */
- "T_MAILB", /* 253 transfer mailbox records */
- "T_MAILA", /* 254 transfer mail agent records */
- "T_ANY", /* 255 wildcard match */
- NULL
-};
-
-enum_names rr_qtype_names = { T_IXFR, T_ANY, rr_qtype_name, &rr_type_names };
-
-static const char *const rr_class_name[] = {
- "C_IN", /* 1 the arpa internet */
- NULL
-};
-
-enum_names rr_class_names = { C_IN, C_IN, rr_class_name, NULL };
-
-#endif /* ADNS */
-
-/*
- * NAT-Traversal defines for nat_traveral type from nat_traversal.h
- *
- */
-const char *const natt_type_bitnames[] = {
- "draft-ietf-ipsec-nat-t-ike-00/01", /* 0 */
- "draft-ietf-ipsec-nat-t-ike-02/03",
- "RFC 3947",
- "3", /* 3 */
- "4", "5", "6", "7",
- "8", "9", "10", "11",
- "12", "13", "14", "15",
- "16", "17", "18", "19",
- "20", "21", "22", "23",
- "24", "25", "26", "27",
- "28", "29",
- "nat is behind me",
- "nat is behind peer"
-};
-
-/* look up enum names in an enum_names */
-
-const char* enum_name(enum_names *ed, unsigned long val)
-{
- enum_names *p;
-
- for (p = ed; p != NULL; p = p->en_next_range)
- {
- if (p->en_first <= val && val <= p->en_last)
- return p->en_names[val - p->en_first];
- }
- return NULL;
-}
-
-/* find or construct a string to describe an enum value
- * Result may be in STATIC buffer!
- */
-const char *
-enum_show(enum_names *ed, unsigned long val)
-{
- const char *p = enum_name(ed, val);
-
- if (p == NULL)
- {
- static char buf[12]; /* only one! I hope that it is big enough */
-
- snprintf(buf, sizeof(buf), "%lu??", val);
- p = buf;
- }
- return p;
-}
-
-
-static char bitnamesbuf[200]; /* only one! I hope that it is big enough! */
-
-int
-enum_search(enum_names *ed, const char *str)
-{
- enum_names *p;
- const char *ptr;
- unsigned en;
-
- for (p = ed; p != NULL; p = p->en_next_range)
- {
- for (en = p->en_first; en <= p->en_last ;en++)
- {
- ptr = p->en_names[en - p->en_first];
- if (ptr == 0)
- {
- continue;
- }
- if (streq(ptr, str))
- {
- return en;
- }
- }
- }
- return -1;
-}
-
-/* construct a string to name the bits on in a set
- * Result may be in STATIC buffer!
- * Note: prettypolicy depends on internal details.
- */
-const char* bitnamesof(const char *const table[], lset_t val)
-{
- char *p = bitnamesbuf;
- lset_t bit;
- const char *const *tp;
-
- if (val == 0)
- return "none";
-
- for (tp = table, bit = 01; val != 0; bit <<= 1)
- {
- if (val & bit)
- {
- const char *n = *tp;
- size_t nl;
-
- if (n == NULL || *n == '\0')
- {
- /* no name for this bit, so use hex */
- static char flagbuf[sizeof("0x80000000")];
-
- snprintf(flagbuf, sizeof(flagbuf), "0x%llx", bit);
- n = flagbuf;
- }
-
- nl = strlen(n);
-
- if (p != bitnamesbuf && p < bitnamesbuf+sizeof(bitnamesbuf) - 1)
- *p++ = '+';
-
- if (bitnamesbuf+sizeof(bitnamesbuf) - p > (ptrdiff_t)nl)
- {
- strcpy(p, n);
- p += nl;
- }
- val -= bit;
- }
- if (*tp != NULL)
- tp++; /* move on, but not past end */
- }
- *p = '\0';
- return bitnamesbuf;
-}
-
-/* print a policy: like bitnamesof, but it also does the non-bitfields.
- * Suppress the shunt and fail fields if 0.
- */
-const char* prettypolicy(lset_t policy)
-{
- const char *bn = bitnamesof(sa_policy_bit_names
- , policy & ~(POLICY_SHUNT_MASK | POLICY_FAIL_MASK));
- size_t len;
- lset_t shunt = (policy & POLICY_SHUNT_MASK) >> POLICY_SHUNT_SHIFT;
- lset_t fail = (policy & POLICY_FAIL_MASK) >> POLICY_FAIL_SHIFT;
-
- if (bn != bitnamesbuf)
- bitnamesbuf[0] = '\0';
- len = strlen(bitnamesbuf);
- if (shunt != 0)
- {
- snprintf(bitnamesbuf + len, sizeof(bitnamesbuf) - len, "+%s"
- , policy_shunt_names[shunt]);
- len += strlen(bitnamesbuf + len);
- }
- if (fail != 0)
- {
- snprintf(bitnamesbuf + len, sizeof(bitnamesbuf) - len, "+failure%s"
- , policy_fail_names[fail]);
- len += strlen(bitnamesbuf + len);
- }
- if (NEVER_NEGOTIATE(policy))
- {
- snprintf(bitnamesbuf + len, sizeof(bitnamesbuf) - len, "+NEVER_NEGOTIATE");
- len += strlen(bitnamesbuf + len);
- }
- return bitnamesbuf;
-}
-
-/* test a set by seeing if all bits have names */
-
-bool testset(const char *const table[], lset_t val)
-{
- lset_t bit;
- const char *const *tp;
-
- for (tp = table, bit = 01; val != 0; bit <<= 1, tp++)
- {
- const char *n = *tp;
-
- if (n == NULL || ((val & bit) && *n == '\0'))
- return FALSE;
- val &= ~bit;
- }
- return TRUE;
-}
-
-
-const char sparse_end[] = "end of sparse names";
-
-/* look up enum names in a sparse_names */
-const char *sparse_name(sparse_names sd, unsigned long val)
-{
- const struct sparse_name *p;
-
- for (p = sd; p->name != sparse_end; p++)
- if (p->val == val)
- return p->name;
- return NULL;
-}
-
-/* find or construct a string to describe an sparse value
- * Result may be in STATIC buffer!
- */
-const char* sparse_val_show(sparse_names sd, unsigned long val)
-{
- const char *p = sparse_name(sd, val);
-
- if (p == NULL)
- {
- static char buf[12]; /* only one! I hope that it is big enough */
-
- snprintf(buf, sizeof(buf), "%lu??", val);
- p = buf;
- }
- return p;
-}
-
-void init_constants(void)
-{
- happy(anyaddr(AF_INET, &ipv4_any));
- happy(anyaddr(AF_INET6, &ipv6_any));
-
- happy(addrtosubnet(&ipv4_any, &ipv4_wildcard));
- happy(addrtosubnet(&ipv6_any, &ipv6_wildcard));
-
- happy(initsubnet(&ipv4_any, 0, '0', &ipv4_all));
- happy(initsubnet(&ipv6_any, 0, '0', &ipv6_all));
-}
-
-u_char secret_of_the_day[HASH_SIZE_SHA1];
-
-
diff --git a/src/pluto/constants.h b/src/pluto/constants.h
deleted file mode 100644
index c931f1782..000000000
--- a/src/pluto/constants.h
+++ /dev/null
@@ -1,1099 +0,0 @@
-/* manifest constants
- * Copyright (C) 1997 Angelos D. Keromytis.
- * Copyright (C) 1998-2002 D. Hugh Redelmeier.
- *
- * 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.
- */
-
-#ifndef _CONSTANTS_H
-#define _CONSTANTS_H
-
-#include <freeswan.h>
-
-#include <kernel/kernel_ipsec.h>
-
-#include <utils.h>
-#include <utils/identification.h>
-#include <crypto/hashers/hasher.h>
-
-extern const char compile_time_interop_options[];
-
-extern void init_constants(void);
-
-/*
- * NOTE:For debugging purposes, constants.c has tables to map numbers back to names.
- * Any changes here should be reflected there.
- */
-
-/* Many routines return only success or failure, but wish to describe
- * the failure in a message. We use the convention that they return
- * a NULL on success and a pointer to constant string on failure.
- * The fact that the string is a constant is limiting, but it
- * avoids storage management issues: the recipient is allowed to assume
- * that the string will live "long enough" (usually forever).
- * <freeswan.h> defines err_t for this return type.
- */
-
-#define NULL_FD (-1) /* NULL file descriptor */
-#define dup_any(fd) ((fd) == NULL_FD? NULL_FD : dup(fd))
-#define close_any(fd) { if ((fd) != NULL_FD) { close(fd); (fd) = NULL_FD; } }
-
-/* set type with room for at least 64 elements for ALG opts (was 32 in stock FS) */
-
-typedef unsigned long long lset_t;
-#define LEMPTY 0ULL
-#define LELEM(opt) (1ULL << (opt))
-#define LRANGE(lwb, upb) LRANGES(LELEM(lwb), LELEM(upb))
-#define LRANGES(first, last) (last - first + last)
-#define LHAS(set, elem) ((LELEM(elem) & (set)) != LEMPTY)
-#define LIN(subset, set) (((subset) & (set)) == (subset))
-#define LDISJOINT(a, b) (((a) & (b)) == LEMPTY)
-
-/* Control and lock pathnames */
-#ifndef IPSEC_PIDDIR
-# define IPSEC_PIDDIR "/var/run"
-#endif
-#ifndef DEFAULT_CTLBASE
-# define DEFAULT_CTLBASE IPSEC_PIDDIR "/pluto"
-#endif
-
-#define CTL_SUFFIX ".ctl" /* for UNIX domain socket pathname */
-#define LOCK_SUFFIX ".pid" /* for pluto's lock */
-#define INFO_SUFFIX ".info" /* for UNIX domain socket for apps */
-
-/* Routines to check and display values.
- *
- * An enum_names describes an enumeration.
- * enum_name() returns the name of an enum value, or NULL if invalid.
- * enum_show() is like enum_name, except it formats a numeric representation
- * for any invalid value (in a static area!)
- *
- * bitnames() formats a display of a set of named bits (in a static area)
- */
-
-struct enum_names {
- unsigned long en_first; /* first value in range */
- unsigned long en_last; /* last value in range (inclusive) */
- const char *const *en_names;
- const struct enum_names *en_next_range; /* descriptor of next range */
-};
-
-typedef const struct enum_names enum_names;
-
-extern const char *enum_name(enum_names *ed, unsigned long val);
-extern const char *enum_show(enum_names *ed, unsigned long val);
-extern int enum_search(enum_names *ed, const char *string);
-
-extern bool testset(const char *const table[], lset_t val);
-extern const char *bitnamesof(const char *const table[], lset_t val);
-
-/* sparse_names is much like enum_names, except values are
- * not known to be contiguous or ordered.
- * The array of names is ended with one with the name sparse_end
- * (this avoids having to reserve a value to signify the end).
- * Often appropriate for enums defined by others.
- */
-struct sparse_name {
- unsigned long val;
- const char *const name;
-};
-typedef const struct sparse_name sparse_names[];
-
-extern const char *sparse_name(sparse_names sd, unsigned long val);
-extern const char *sparse_val_show(sparse_names sd, unsigned long val);
-extern const char sparse_end[];
-
-#define FULL_INET_ADDRESS_SIZE 6
-
-/* limits on nonce sizes. See RFC2409 "The internet key exchange (IKE)" 5 */
-#define MINIMUM_NONCE_SIZE 8 /* bytes */
-#define DEFAULT_NONCE_SIZE 16 /* bytes */
-#define MAXIMUM_NONCE_SIZE 256 /* bytes */
-
-#define COOKIE_SIZE 8
-#define MAX_ISAKMP_SPI_SIZE 16
-
-#define DES_CBC_BLOCK_SIZE (64 / BITS_PER_BYTE)
-
-/* Maximum is required for SHA2_512 */
-#define MAX_DIGEST_LEN HASH_SIZE_SHA512
-
-/* RFC 2404 "HMAC-SHA-1-96" section 3 */
-#define HMAC_SHA1_KEY_LEN HASH_SIZE_SHA1
-
-/* RFC 2403 "HMAC-MD5-96" section 3 */
-#define HMAC_MD5_KEY_LEN HASH_SIZE_MD5
-
-#define IKE_UDP_PORT 500
-
-/* IPsec AH transform values
- * RFC2407 The Internet IP security Domain of Interpretation for ISAKMP 4.4.3
- * and in http://www.iana.org/assignments/isakmp-registry
- */
-enum ipsec_authentication_algo {
- AH_NONE = 0,
- AH_MD5 = 2,
- AH_SHA = 3,
- AH_DES = 4,
- AH_SHA2_256 = 5,
- AH_SHA2_384 = 6,
- AH_SHA2_512 = 7,
- AH_RIPEMD = 8,
- AH_AES_XCBC_MAC = 9,
- AH_RSA = 10,
- AH_AES_128_GMAC = 11,
- AH_AES_192_GMAC = 12,
- AH_AES_256_GMAC = 13,
- AH_SHA2_256_96 = 252
-};
-
-extern enum_names ah_transform_names;
-
-/* IPsec ESP transform values
- * RFC2407 The Internet IP security Domain of Interpretation for ISAKMP 4.4.4
- * and from http://www.iana.org/assignments/isakmp-registry
- */
-
-enum ipsec_cipher_algo {
- ESP_NONE = 0,
- ESP_DES_IV64 = 1,
- ESP_DES = 2,
- ESP_3DES = 3,
- ESP_RC5 = 4,
- ESP_IDEA = 5,
- ESP_CAST = 6,
- ESP_BLOWFISH = 7,
- ESP_3IDEA = 8,
- ESP_DES_IV32 = 9,
- ESP_RC4 = 10,
- ESP_NULL = 11,
- ESP_AES = 12,
- ESP_AES_CTR = 13,
- ESP_AES_CCM_8 = 14,
- ESP_AES_CCM_12 = 15,
- ESP_AES_CCM_16 = 16,
- ESP_UNASSIGNED_17 = 17,
- ESP_AES_GCM_8 = 18,
- ESP_AES_GCM_12 = 19,
- ESP_AES_GCM_16 = 20,
- ESP_SEED_CBC = 21,
- ESP_CAMELLIA = 22,
- ESP_AES_GMAC = 23,
- ESP_SERPENT = 252,
- ESP_TWOFISH = 253
-};
-
-extern enum_names esp_transform_names;
-
-/* IPCOMP transform values
- * RFC2407 The Internet IP security Domain of Interpretation for ISAKMP 4.4.5
- * now defined in kernel/kernel_ipsec.h
- */
-
-extern enum_names ipcomp_transformid_names;
-
-/* Certificate type values
- * RFC 2408 ISAKMP, chapter 3.9
- */
-enum ipsec_cert_type {
- CERT_NONE= 0,
- CERT_PKCS7_WRAPPED_X509= 1,
- CERT_PGP= 2,
- CERT_DNS_SIGNED_KEY= 3,
- CERT_X509_SIGNATURE= 4,
- CERT_X509_KEY_EXCHANGE= 5,
- CERT_KERBEROS_TOKENS= 6,
- CERT_CRL= 7,
- CERT_ARL= 8,
- CERT_SPKI= 9,
- CERT_X509_ATTRIBUTE= 10,
- CERT_RAW_RSA_KEY= 11
-};
-
-/* RFC 2560 OCSP - certificate status */
-
-typedef enum {
- CERT_GOOD = 0,
- CERT_REVOKED = 1,
- CERT_UNKNOWN = 2,
- CERT_UNDEFINED = 3
-} cert_status_t;
-
-/* RFC 3706 Dead Peer Detection */
-
-extern enum_name_t *dpd_action_names;
-
-typedef enum {
- DPD_ACTION_NONE = 0,
- DPD_ACTION_CLEAR = 1,
- DPD_ACTION_HOLD = 2,
- DPD_ACTION_RESTART = 3,
- DPD_ACTION_UNKNOWN = 4
-} dpd_action_t;
-
-/* Timer events */
-
-extern enum_name_t *timer_event_names;
-
-enum event_type {
- EVENT_NULL, /* non-event */
- EVENT_REINIT_SECRET, /* Refresh cookie secret */
- EVENT_SO_DISCARD, /* discard unfinished state object */
- EVENT_RETRANSMIT, /* Retransmit packet */
- EVENT_SA_REPLACE, /* SA replacement event */
- EVENT_SA_REPLACE_IF_USED, /* SA replacement event */
- EVENT_SA_EXPIRE, /* SA expiration event */
- EVENT_NAT_T_KEEPALIVE, /* NAT Traversal Keepalive */
- EVENT_DPD, /* dead peer detection */
- EVENT_DPD_TIMEOUT, /* dead peer detection timeout */
- EVENT_LOG_DAILY /* reset certain log events/stats */
-};
-
-#define EVENT_REINIT_SECRET_DELAY 3600 /* 1 hour */
-#define EVENT_RETRANSMIT_DELAY_0 10 /* 10 seconds */
-
-/* Misc. stuff */
-
-#define MAXIMUM_RETRANSMISSIONS 2
-#define MAXIMUM_RETRANSMISSIONS_INITIAL 20
-
-#define MAX_INPUT_UDP_SIZE 65536
-#define MAX_OUTPUT_UDP_SIZE 65536
-
-/* Version numbers */
-
-#define ISAKMP_MAJOR_VERSION 0x1
-#define ISAKMP_MINOR_VERSION 0x0
-
-extern enum_names version_names;
-
-/* Domain of Interpretation */
-
-extern enum_names doi_names;
-
-#define ISAKMP_DOI_ISAKMP 0
-#define ISAKMP_DOI_IPSEC 1
-
-/* IPsec DOI things */
-
-#define IPSEC_DOI_SITUATION_LENGTH 4
-#define IPSEC_DOI_LDI_LENGTH 4
-#define IPSEC_DOI_SPI_SIZE 4
-
-/* SPI value 0 is invalid and values 1-255 are reserved to IANA.
- * ESP: RFC 2402 2.4; AH: RFC 2406 2.1
- * IPComp RFC 2393 substitutes a CPI in the place of an SPI.
- * see also draft-shacham-ippcp-rfc2393bis-05.txt.
- * We (FreeS/WAN) reserve 0x100 to 0xFFF for manual keying, so
- * Pluto won't generate these values.
- */
-#define IPSEC_DOI_SPI_MIN 0x100
-#define IPSEC_DOI_SPI_OUR_MIN 0x1000
-
-/* debugging settings: a set of selections for reporting
- * These would be more naturally situated in log.h,
- * but they are shared with whack.
- * IMPAIR_* actually change behaviour, usually badly,
- * to aid in testing. Naturally, these are not included in ALL.
- *
- * NOTE: changes here must be done in concert with changes to DBGOPT_*
- * in whack.c. A change to WHACK_MAGIC in whack.h will be required too.
- */
-#ifdef DEBUG
-extern const char *const debug_bit_names[];
-#endif
-
-#define DBG_RAW LELEM(0) /* raw packet I/O */
-#define DBG_CRYPT LELEM(1) /* encryption/decryption of messages */
-#define DBG_PARSING LELEM(2) /* show decoding of messages */
-#define DBG_EMITTING LELEM(3) /* show encoding of messages */
-#define DBG_CONTROL LELEM(4) /* control flow within Pluto */
-#define DBG_LIFECYCLE LELEM(5) /* SA lifecycle */
-#define DBG_KERNEL LELEM(6) /* messages to kernel */
-#define DBG_DNS LELEM(7) /* DNS activity */
-#define DBG_NATT LELEM(8) /* NAT-T */
-#define DBG_OPPO LELEM(9) /* opportunism */
-#define DBG_CONTROLMORE LELEM(10) /* more detailed debugging */
-
-#define DBG_PRIVATE LELEM(11) /* private information: DANGER! */
-
-#define IMPAIR0 12 /* first bit for IMPAIR_* */
-
-#define IMPAIR_DELAY_ADNS_KEY_ANSWER LELEM(IMPAIR0+0) /* sleep before answering */
-#define IMPAIR_DELAY_ADNS_TXT_ANSWER LELEM(IMPAIR0+1) /* sleep before answering */
-#define IMPAIR_BUST_MI2 LELEM(IMPAIR0+2) /* make MI2 really large */
-#define IMPAIR_BUST_MR2 LELEM(IMPAIR0+3) /* make MI2 really large */
-
-#define DBG_NONE 0 /* no options on, including impairments */
-#define DBG_ALL LRANGES(DBG_RAW, DBG_CONTROLMORE) /* all logging options on EXCEPT DBG_PRIVATE */
-
-/* State of exchanges
- *
- * The name of the state describes the last message sent, not the
- * message currently being input or output (except during retry).
- * In effect, the state represents the last completed action.
- *
- * Messages are named [MQ][IR]n where
- * - M stands for Main Mode (Phase 1);
- * Q stands for Quick Mode (Phase 2)
- * - I stands for Initiator;
- * R stands for Responder
- * - n, a digit, stands for the number of the message
- *
- * It would be more convenient if each state accepted a message
- * and produced one. This is the case for states at the start
- * or end of an exchange. To fix this, we pretend that there are
- * MR0 and QR0 messages before the MI1 and QR1 messages. Similarly,
- * we pretend that there are MR4 and QR2 messages.
- *
- * STATE_MAIN_R0 and STATE_QUICK_R0 are intermediate states (not
- * retained between messages) representing the state that accepts the
- * first message of an exchange has been read but not processed.
- *
- * state_microcode state_microcode_table in demux.c describes
- * other important details.
- */
-
-extern enum_names state_names;
-extern const char *const state_story[];
-
-enum state_kind {
- STATE_UNDEFINED, /* 0 -- most likely accident */
-
- /* IKE states */
-
- STATE_MAIN_R0,
- STATE_MAIN_I1,
- STATE_MAIN_R1,
- STATE_MAIN_I2,
- STATE_MAIN_R2,
- STATE_MAIN_I3,
- STATE_MAIN_R3,
- STATE_MAIN_I4,
-
- STATE_QUICK_R0,
- STATE_QUICK_I1,
- STATE_QUICK_R1,
- STATE_QUICK_I2,
- STATE_QUICK_R2,
-
- STATE_INFO,
- STATE_INFO_PROTECTED,
-
- /* XAUTH states */
-
- STATE_XAUTH_I0, /* initiator state (client) */
- STATE_XAUTH_R1, /* responder state (server) */
- STATE_XAUTH_I1,
- STATE_XAUTH_R2,
- STATE_XAUTH_I2,
- STATE_XAUTH_R3,
-
- /* Mode Config pull states */
-
- STATE_MODE_CFG_R0, /* responder state (server) */
- STATE_MODE_CFG_I1, /* initiator state (client) */
- STATE_MODE_CFG_R1,
- STATE_MODE_CFG_I2,
-
- /* Mode Config push states */
-
- STATE_MODE_CFG_I0, /* initiator state (client) */
- STATE_MODE_CFG_R3, /* responder state (server) */
- STATE_MODE_CFG_I3,
- STATE_MODE_CFG_R4,
-
- STATE_IKE_ROOF
-};
-
-#define STATE_IKE_FLOOR STATE_MAIN_R0
-
-#define PHASE1_INITIATOR_STATES (LELEM(STATE_MAIN_I1) | LELEM(STATE_MAIN_I2) \
- | LELEM(STATE_MAIN_I3) | LELEM(STATE_MAIN_I4))
-#define ISAKMP_SA_ESTABLISHED_STATES ( \
- LELEM(STATE_MAIN_R3) | LELEM(STATE_MAIN_I4) \
- | LELEM(STATE_XAUTH_R1) | LELEM(STATE_XAUTH_R2) | LELEM(STATE_XAUTH_R3) \
- | LELEM(STATE_XAUTH_I1) | LELEM(STATE_XAUTH_I2) \
- | LELEM(STATE_MODE_CFG_I1) | LELEM(STATE_MODE_CFG_R1) | LELEM(STATE_MODE_CFG_I2) \
- | LELEM(STATE_MODE_CFG_R3) | LELEM(STATE_MODE_CFG_I3) | LELEM(STATE_MODE_CFG_R4))
-
-#define IS_PHASE1(s) ((STATE_MAIN_R0 <= (s) && (s) <= STATE_MAIN_I4) \
- || (STATE_XAUTH_I0 <= (s) && (s) <= STATE_XAUTH_R3) \
- || (STATE_MODE_CFG_R0 <= (s) && (s) <= STATE_MODE_CFG_R4))
-
-#define IS_QUICK(s) (STATE_QUICK_R0 <= (s) && (s) <= STATE_QUICK_R2)
-#define IS_ISAKMP_ENCRYPTED(s) (STATE_MAIN_I2 <= (s))
-
-#define IS_ISAKMP_SA_ESTABLISHED(s) ( \
- (s) == STATE_MAIN_R3 \
- || (s) == STATE_MAIN_I4 \
- || (s) == STATE_XAUTH_I2 \
- || (s) == STATE_XAUTH_R3 \
- || (s) == STATE_MODE_CFG_R1 \
- || (s) == STATE_MODE_CFG_I2 \
- || (s) == STATE_MODE_CFG_I3 \
- || (s) == STATE_MODE_CFG_R4)
-
-#define IS_IPSEC_SA_ESTABLISHED(s) ((s) == STATE_QUICK_I2 || (s) == STATE_QUICK_R2)
-#define IS_ONLY_INBOUND_IPSEC_SA_ESTABLISHED(s) ((s) == STATE_QUICK_R1)
-
-/* kind of struct connection
- * Ordered (mostly) by concreteness. Order is exploited.
- */
-
-extern enum_names connection_kind_names;
-
-enum connection_kind {
- CK_GROUP, /* policy group: instantiates to template */
- CK_TEMPLATE, /* abstract connection, with wildcard */
- CK_PERMANENT, /* normal connection */
- CK_INSTANCE, /* instance of template, created for a particular attempt */
- CK_GOING_AWAY /* instance being deleted -- don't delete again */
-};
-
-
-/* routing status.
- * Note: routing ignores source address, but erouting does not!
- * Note: a connection can only be routed if it is NEVER_NEGOTIATE
- * or HAS_IPSEC_POLICY.
- */
-
-extern enum_names routing_story;
-
-/* note that this is assumed to be ordered! */
-enum routing_t {
- RT_UNROUTED, /* unrouted */
- RT_UNROUTED_HOLD, /* unrouted, but HOLD shunt installed */
- RT_ROUTED_ECLIPSED, /* RT_ROUTED_PROSPECTIVE except bare HOLD or instance has eroute */
- RT_ROUTED_PROSPECTIVE, /* routed, and prospective shunt installed */
- RT_ROUTED_HOLD, /* routed, and HOLD shunt installed */
- RT_ROUTED_FAILURE, /* routed, and failure-context shunt installed */
- RT_ROUTED_TUNNEL, /* routed, and erouted to an IPSEC SA group */
- RT_UNROUTED_KEYED /* keyed, but not routed, on purpose */
-};
-
-#define routed(rs) ((rs) > RT_UNROUTED_HOLD)
-#define erouted(rs) ((rs) != RT_UNROUTED)
-#define shunt_erouted(rs) (erouted(rs) && (rs) != RT_ROUTED_TUNNEL)
-
-/* Payload types
- * RFC2408 Internet Security Association and Key Management Protocol (ISAKMP)
- * section 3.1
- *
- * RESERVED 14-127
- * Private USE 128-255
- */
-
-extern enum_names payload_names;
-extern const char *const payload_name[];
-
-#define ISAKMP_NEXT_NONE 0 /* No other payload following */
-#define ISAKMP_NEXT_SA 1 /* Security Association */
-#define ISAKMP_NEXT_P 2 /* Proposal */
-#define ISAKMP_NEXT_T 3 /* Transform */
-#define ISAKMP_NEXT_KE 4 /* Key Exchange */
-#define ISAKMP_NEXT_ID 5 /* Identification */
-#define ISAKMP_NEXT_CERT 6 /* Certificate */
-#define ISAKMP_NEXT_CR 7 /* Certificate Request */
-#define ISAKMP_NEXT_HASH 8 /* Hash */
-#define ISAKMP_NEXT_SIG 9 /* Signature */
-#define ISAKMP_NEXT_NONCE 10 /* Nonce */
-#define ISAKMP_NEXT_N 11 /* Notification */
-#define ISAKMP_NEXT_D 12 /* Delete */
-#define ISAKMP_NEXT_VID 13 /* Vendor ID */
-#define ISAKMP_NEXT_ATTR 14 /* Mode config Attribute */
-
-#define ISAKMP_NEXT_NATD_RFC 20 /* NAT-Traversal: NAT-D (rfc) */
-#define ISAKMP_NEXT_NATOA_RFC 21 /* NAT-Traversal: NAT-OA (rfc) */
-#define ISAKMP_NEXT_ROOF 22 /* roof on payload types */
-
-#define ISAKMP_NEXT_NATD_DRAFTS 130 /* NAT-Traversal: NAT-D (drafts) */
-#define ISAKMP_NEXT_NATOA_DRAFTS 131 /* NAT-Traversal: NAT-OA (drafts) */
-
-/* These values are to be used within the Type field of an Attribute (14)
- * ISAKMP payload.
- */
-#define ISAKMP_CFG_REQUEST 1
-#define ISAKMP_CFG_REPLY 2
-#define ISAKMP_CFG_SET 3
-#define ISAKMP_CFG_ACK 4
-
-extern enum_names attr_msg_type_names;
-
-extern enum_names modecfg_attr_names;
-
-/* XAUTH authentication types */
-#define XAUTH_TYPE_GENERIC 0
-#define XAUTH_TYPE_CHAP 1
-#define XAUTH_TYPE_OTP 2
-#define XAUTH_TYPE_SKEY 3
-
-/* Values for XAUTH_STATUS */
-#define XAUTH_STATUS_FAIL 0
-#define XAUTH_STATUS_OK 1
-
-extern enum_names xauth_type_names;
-
-/* Exchange types
- * RFC2408 "Internet Security Association and Key Management Protocol (ISAKMP)"
- * section 3.1
- *
- * ISAKMP Future Use 6 - 31
- * DOI Specific Use 32 - 239
- * Private Use 240 - 255
- *
- * Note: draft-ietf-ipsec-dhless-enc-mode-00.txt Appendix A
- * defines "DHless RSA Encryption" as 6.
- */
-
-extern enum_names exchange_names;
-
-#define ISAKMP_XCHG_NONE 0
-#define ISAKMP_XCHG_BASE 1
-#define ISAKMP_XCHG_IDPROT 2 /* ID Protection */
-#define ISAKMP_XCHG_AO 3 /* Authentication Only */
-#define ISAKMP_XCHG_AGGR 4 /* Aggressive */
-#define ISAKMP_XCHG_INFO 5 /* Informational */
-#define ISAKMP_XCHG_MODE_CFG 6 /* Mode Config */
-
-/* Extra exchange types, defined by Oakley
- * RFC2409 "The Internet Key Exchange (IKE)", near end of Appendix A
- */
-#define ISAKMP_XCHG_QUICK 32 /* Oakley Quick Mode */
-#define ISAKMP_XCHG_NGRP 33 /* Oakley New Group Mode */
-/* added in draft-ietf-ipsec-ike-01.txt, near end of Appendix A */
-#define ISAKMP_XCHG_ACK_INFO 34 /* Oakley Acknowledged Informational */
-
-/* Flag bits */
-
-extern const char *const flag_bit_names[];
-
-#define ISAKMP_FLAG_ENCRYPTION 0x1
-#define ISAKMP_FLAG_COMMIT 0x2
-
-/* Situation definition for IPsec DOI */
-
-extern const char *const sit_bit_names[];
-
-#define SIT_IDENTITY_ONLY 0x01
-#define SIT_SECRECY 0x02
-#define SIT_INTEGRITY 0x04
-
-/* Protocol IDs
- * RFC2407 The Internet IP security Domain of Interpretation for ISAKMP 4.4.1
- */
-
-extern enum_names protocol_names;
-
-#define PROTO_ISAKMP 1
-#define PROTO_IPSEC_AH 2
-#define PROTO_IPSEC_ESP 3
-#define PROTO_IPCOMP 4
-
-/* warning: trans_show uses enum_show, so same static buffer is used */
-#define trans_show(p, t) \
- ((p)==PROTO_IPSEC_AH ? enum_show(&ah_transformid_names, (t)) \
- : (p)==PROTO_IPSEC_ESP ? enum_show(&esp_transformid_names, (t)) \
- : (p)==PROTO_IPCOMP ? enum_show(&ipcomp_transformid_names, (t)) \
- : "??")
-
-#define KEY_IKE 1
-
-extern enum_names isakmp_transformid_names;
-
-/* the following are from RFC 2393/draft-shacham-ippcp-rfc2393bis-05.txt 3.3 */
-typedef u_int16_t cpi_t;
-#define IPCOMP_CPI_SIZE 2
-#define IPCOMP_FIRST_NEGOTIATED 256
-#define IPCOMP_LAST_NEGOTIATED 61439
-
-/* Identification type values
- * RFC 2407 The Internet IP security Domain of Interpretation for ISAKMP 4.6.2.1
- */
-
-extern enum_names ident_names;
-extern enum_names cert_type_names;
-
-extern enum_name_t *cert_policy_names;
-
-typedef enum certpolicy {
- CERT_ALWAYS_SEND = 0,
- CERT_SEND_IF_ASKED = 1,
- CERT_NEVER_SEND = 2,
-
- CERT_YES_SEND = 3, /* synonym for CERT_ALWAYS_SEND */
- CERT_NO_SEND = 4 /* synonym for CERT_NEVER_SEND */
-} certpolicy_t;
-
-/* Policies for establishing an SA
- *
- * These are used to specify attributes (eg. encryption) and techniques
- * (eg PFS) for an SA.
- * Note: certain CD_ definitions in whack.c parallel these -- keep them
- * in sync!
- */
-
-extern const char *const sa_policy_bit_names[];
-extern const char *prettypolicy(lset_t policy);
-
-/* ISAKMP auth techniques (none means never negotiate) */
-#define POLICY_PSK LELEM(0)
-#define POLICY_PUBKEY LELEM(1)
-
-#define POLICY_ISAKMP_SHIFT 0 /* log2(POLICY_PSK) */
-#define POLICY_ID_AUTH_MASK (POLICY_PSK | POLICY_PUBKEY | POLICY_XAUTH_PSK | POLICY_XAUTH_RSASIG)
-#define POLICY_ISAKMP_MASK POLICY_ID_AUTH_MASK /* all so far */
-
-/* Quick Mode (IPSEC) attributes */
-#define POLICY_ENCRYPT LELEM(2) /* must be first of IPSEC policies */
-#define POLICY_AUTHENTICATE LELEM(3) /* must be second */
-#define POLICY_COMPRESS LELEM(4) /* must be third */
-#define POLICY_TUNNEL LELEM(5)
-#define POLICY_PFS LELEM(6)
-#define POLICY_DISABLEARRIVALCHECK LELEM(7) /* suppress tunnel egress address checking */
-
-#define POLICY_IPSEC_SHIFT 2 /* log2(POLICY_ENCRYPT) */
-#define POLICY_IPSEC_MASK LRANGES(POLICY_ENCRYPT, POLICY_DISABLEARRIVALCHECK)
-
-/* shunt attributes: what to do when routed without tunnel (2 bits) */
-#define POLICY_SHUNT_SHIFT 8 /* log2(POLICY_SHUNT_PASS) */
-#define POLICY_SHUNT_MASK (03ul << POLICY_SHUNT_SHIFT)
-
-#define POLICY_SHUNT_TRAP (0ul << POLICY_SHUNT_SHIFT) /* default: negotiate */
-#define POLICY_SHUNT_PASS (1ul << POLICY_SHUNT_SHIFT)
-#define POLICY_SHUNT_DROP (2ul << POLICY_SHUNT_SHIFT)
-#define POLICY_SHUNT_REJECT (3ul << POLICY_SHUNT_SHIFT)
-
-/* fail attributes: what to do with failed negotiation (2 bits) */
-
-#define POLICY_FAIL_SHIFT 10 /* log2(POLICY_FAIL_PASS) */
-#define POLICY_FAIL_MASK (03ul << POLICY_FAIL_SHIFT)
-
-#define POLICY_FAIL_NONE (0ul << POLICY_FAIL_SHIFT) /* default */
-#define POLICY_FAIL_PASS (1ul << POLICY_FAIL_SHIFT)
-#define POLICY_FAIL_DROP (2ul << POLICY_FAIL_SHIFT)
-#define POLICY_FAIL_REJECT (3ul << POLICY_FAIL_SHIFT)
-
-/* connection policy
- * Other policies could vary per state object. These live in connection.
- */
-#define POLICY_DONT_REKEY LELEM(12) /* don't rekey state either Phase */
-#define POLICY_OPPO LELEM(13) /* is this opportunistic? */
-#define POLICY_GROUP LELEM(14) /* is this a group template? */
-#define POLICY_GROUTED LELEM(15) /* do we want this group routed? */
-#define POLICY_UP LELEM(16) /* do we want this up? */
-#define POLICY_MODECFG_PUSH LELEM(17) /* is modecfg pushed by server? */
-#define POLICY_XAUTH_PSK LELEM(18) /* do we support XAUTH????PreShared? */
-#define POLICY_XAUTH_RSASIG LELEM(19) /* do we support XAUTH????RSA? */
-#define POLICY_XAUTH_SERVER LELEM(20) /* are we an XAUTH server? */
-#define POLICY_DONT_REAUTH LELEM(21) /* don't reauthenticate on rekeying, IKEv2 only */
-#define POLICY_BEET LELEM(22) /* bound end2end tunnel, IKEv2 */
-#define POLICY_MOBIKE LELEM(23) /* enable MOBIKE for IKEv2 */
-#define POLICY_FORCE_ENCAP LELEM(24) /* force UDP encapsulation (IKEv2) */
-#define POLICY_PROXY LELEM(25) /* proxy transport mode (MIPv6) */
-
-/* Any IPsec policy? If not, a connection description
- * is only for ISAKMP SA, not IPSEC SA. (A pun, I admit.)
- * Note: a connection can only be routed if it is NEVER_NEGOTIATE
- * or HAS_IPSEC_POLICY.
- */
-#define HAS_IPSEC_POLICY(p) (((p) & POLICY_IPSEC_MASK) != 0)
-
-/* Don't allow negotiation? */
-#define NEVER_NEGOTIATE(p) (LDISJOINT((p), POLICY_ID_AUTH_MASK))
-
-
-/* Oakley transform attributes
- * draft-ietf-ipsec-ike-01.txt appendix A
- */
-
-extern enum_names oakley_attr_names;
-extern const char *const oakley_attr_bit_names[];
-
-#define OAKLEY_ENCRYPTION_ALGORITHM 1
-#define OAKLEY_HASH_ALGORITHM 2
-#define OAKLEY_AUTHENTICATION_METHOD 3
-#define OAKLEY_GROUP_DESCRIPTION 4
-#define OAKLEY_GROUP_TYPE 5
-#define OAKLEY_GROUP_PRIME 6 /* B/V */
-#define OAKLEY_GROUP_GENERATOR_ONE 7 /* B/V */
-#define OAKLEY_GROUP_GENERATOR_TWO 8 /* B/V */
-#define OAKLEY_GROUP_CURVE_A 9 /* B/V */
-#define OAKLEY_GROUP_CURVE_B 10 /* B/V */
-#define OAKLEY_LIFE_TYPE 11
-#define OAKLEY_LIFE_DURATION 12 /* B/V */
-#define OAKLEY_PRF 13
-#define OAKLEY_KEY_LENGTH 14
-#define OAKLEY_FIELD_SIZE 15
-#define OAKLEY_GROUP_ORDER 16 /* B/V */
-#define OAKLEY_BLOCK_SIZE 17
-
-/* for each Oakley attribute, which enum_names describes its values? */
-extern enum_names *oakley_attr_val_descs[];
-
-/* IPsec DOI attributes
- * RFC2407 The Internet IP security Domain of Interpretation for ISAKMP 4.5
- */
-
-extern enum_names ipsec_attr_names;
-
-#define SA_LIFE_TYPE 1
-#define SA_LIFE_DURATION 2 /* B/V */
-#define GROUP_DESCRIPTION 3
-#define ENCAPSULATION_MODE 4
-#define AUTH_ALGORITHM 5
-#define KEY_LENGTH 6
-#define KEY_ROUNDS 7
-#define COMPRESS_DICT_SIZE 8
-#define COMPRESS_PRIVATE_ALG 9 /* B/V */
-
-/* for each IPsec attribute, which enum_names describes its values? */
-extern enum_names *ipsec_attr_val_descs[];
-
-/* SA Lifetime Type attribute
- * RFC2407 The Internet IP security Domain of Interpretation for ISAKMP 4.5
- * Default time specified in 4.5
- *
- * There are two defaults for IPSEC SA lifetime, SA_LIFE_DURATION_DEFAULT,
- * and PLUTO_SA_LIFE_DURATION_DEFAULT.
- * SA_LIFE_DURATION_DEFAULT is specified in RFC2407 "The Internet IP
- * Security Domain of Interpretation for ISAKMP" 4.5. It applies when
- * an ISAKMP negotiation does not explicitly specify a life duration.
- * PLUTO_SA_LIFE_DURATION_DEFAULT is specified in pluto(8). It applies
- * when a connection description does not specify --ipseclifetime.
- * The value of SA_LIFE_DURATION_MAXIMUM is our local policy.
- */
-
-extern enum_names sa_lifetime_names;
-
-#define SA_LIFE_TYPE_SECONDS 1
-#define SA_LIFE_TYPE_KBYTES 2
-
-#define SA_LIFE_DURATION_DEFAULT 28800 /* eight hours (RFC2407 4.5) */
-#define PLUTO_SA_LIFE_DURATION_DEFAULT 3600 /* one hour (pluto(8)) */
-#define SA_LIFE_DURATION_MAXIMUM 86400 /* one day */
-
-#define SA_REPLACEMENT_MARGIN_DEFAULT 540 /* (IPSEC & IKE) nine minutes */
-#define SA_REPLACEMENT_FUZZ_DEFAULT 100 /* (IPSEC & IKE) 100% of MARGIN */
-#define SA_REPLACEMENT_RETRIES_DEFAULT 3 /* (IPSEC & IKE) */
-
-#define SA_LIFE_DURATION_K_DEFAULT 0xFFFFFFFFlu
-
-/* Encapsulation Mode attribute */
-
-extern enum_names enc_mode_names;
-
-#define ENCAPSULATION_MODE_UNSPECIFIED 0 /* not legal -- used internally */
-#define ENCAPSULATION_MODE_TUNNEL 1
-#define ENCAPSULATION_MODE_TRANSPORT 2
-
-#define ENCAPSULATION_MODE_UDP_TUNNEL_RFC 3
-#define ENCAPSULATION_MODE_UDP_TRANSPORT_RFC 4
-
-#define ENCAPSULATION_MODE_UDP_TUNNEL_DRAFTS 61443
-#define ENCAPSULATION_MODE_UDP_TRANSPORT_DRAFTS 61444
-
-/* Auth Algorithm attribute */
-
-extern enum_names auth_alg_names, extended_auth_alg_names;
-
-#define AUTH_ALGORITHM_NONE 0 /* our private designation */
-#define AUTH_ALGORITHM_HMAC_MD5 1
-#define AUTH_ALGORITHM_HMAC_SHA1 2
-#define AUTH_ALGORITHM_DES_MAC 3
-#define AUTH_ALGORITHM_KPDK 4
-#define AUTH_ALGORITHM_HMAC_SHA2_256 5
-#define AUTH_ALGORITHM_HMAC_SHA2_384 6
-#define AUTH_ALGORITHM_HMAC_SHA2_512 7
-#define AUTH_ALGORITHM_HMAC_RIPEMD 8
-#define AUTH_ALGORITHM_AES_XCBC_MAC 9
-#define AUTH_ALGORITHM_SIG_RSA 10
-#define AUTH_ALGORITHM_AES_128_GMAC 11
-#define AUTH_ALGORITHM_AES_192_GMAC 12
-#define AUTH_ALGORITHM_AES_256_GMAC 13
-#define AUTH_ALGORITHM_NULL 251
-#define AUTH_ALGORITHM_HMAC_SHA2_256_96 252
-
-/* Oakley Lifetime Type attribute
- * draft-ietf-ipsec-ike-01.txt appendix A
- * As far as I can see, there is not specification for
- * OAKLEY_ISAKMP_SA_LIFETIME_DEFAULT. This could lead to interop problems!
- * For no particular reason, we chose three hours.
- * The value of OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM is our local policy.
- */
-extern enum_names oakley_lifetime_names;
-
-#define OAKLEY_LIFE_SECONDS 1
-#define OAKLEY_LIFE_KILOBYTES 2
-
-#define OAKLEY_ISAKMP_SA_LIFETIME_DEFAULT 10800 /* three hours */
-#define OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM 86400 /* one day */
-
-/* Oakley PRF attribute (none defined)
- * draft-ietf-ipsec-ike-01.txt appendix A
- */
-extern enum_names oakley_prf_names;
-
-/* HMAC (see rfc2104.txt) */
-
-#define HMAC_IPAD 0x36
-#define HMAC_OPAD 0x5C
-
-/* Oakley Encryption Algorithm attribute
- * draft-ietf-ipsec-ike-01.txt appendix A
- * and from http://www.isi.edu/in-notes/iana/assignments/ipsec-registry
- */
-
-extern enum_names oakley_enc_names;
-
-#define OAKLEY_DES_CBC 1
-#define OAKLEY_IDEA_CBC 2
-#define OAKLEY_BLOWFISH_CBC 3
-#define OAKLEY_RC5_R16_B64_CBC 4
-#define OAKLEY_3DES_CBC 5
-#define OAKLEY_CAST_CBC 6
-#define OAKLEY_AES_CBC 7
-#define OAKLEY_CAMELLIA_CBC 8
-
-#define OAKLEY_MARS_CBC 65001
-#define OAKLEY_RC6_CBC 65002
-#define OAKLEY_ID_65003 65003
-#define OAKLEY_SERPENT_CBC 65004
-#define OAKLEY_TWOFISH_CBC 65005
-
-#define OAKLEY_TWOFISH_CBC_SSH 65289
-
-#define OAKLEY_ENCRYPT_MAX 65535 /* pretty useless :) */
-
-/* Oakley Hash Algorithm attribute
- * draft-ietf-ipsec-ike-01.txt appendix A
- * and from http://www.isi.edu/in-notes/iana/assignments/ipsec-registry
- */
-
-extern enum_names oakley_hash_names;
-
-#define OAKLEY_MD5 1
-#define OAKLEY_SHA 2
-#define OAKLEY_TIGER 3
-#define OAKLEY_SHA2_256 4
-#define OAKLEY_SHA2_384 5
-#define OAKLEY_SHA2_512 6
-
-#define OAKLEY_HASH_MAX 7
-
-/* Oakley Authentication Method attribute
- * draft-ietf-ipsec-ike-01.txt appendix A
- * Goofy Hybrid extensions from draft-ietf-ipsec-isakmp-hybrid-auth-05.txt
- * Goofy XAUTH extensions from draft-ietf-ipsec-isakmp-xauth-06.txt
- */
-
-extern enum_names oakley_auth_names;
-
-#define OAKLEY_PRESHARED_KEY 1
-#define OAKLEY_DSS_SIG 2
-#define OAKLEY_RSA_SIG 3
-#define OAKLEY_RSA_ENC 4
-#define OAKLEY_RSA_ENC_REV 5
-#define OAKLEY_ELGAMAL_ENC 6
-#define OAKLEY_ELGAMAL_ENC_REV 7
-#define OAKLEY_ECDSA_SIG 8
-#define OAKLEY_ECDSA_256 9
-#define OAKLEY_ECDSA_384 10
-#define OAKLEY_ECDSA_521 11
-
-#define OAKLEY_AUTH_ROOF 12 /* roof on auth values THAT WE SUPPORT */
-
-#define HybridInitRSA 64221
-#define HybridRespRSA 64222
-#define HybridInitDSS 64223
-#define HybridRespDSS 64224
-
-#define XAUTHInitPreShared 65001
-#define XAUTHRespPreShared 65002
-#define XAUTHInitDSS 65003
-#define XAUTHRespDSS 65004
-#define XAUTHInitRSA 65005
-#define XAUTHRespRSA 65006
-#define XAUTHInitRSAEncryption 65007
-#define XAUTHRespRSAEncryption 65008
-#define XAUTHInitRSARevisedEncryption 65009
-#define XAUTHRespRSARevisedEncryption 65010
-
-/* Oakley Group Description attribute
- * draft-ietf-ipsec-ike-01.txt appendix A
- */
-extern enum_names oakley_group_names;
-
-/* you must also touch: constants.c, crypto.c */
-
-/* Oakley Group Type attribute
- * draft-ietf-ipsec-ike-01.txt appendix A
- */
-extern enum_names oakley_group_type_names;
-
-#define OAKLEY_GROUP_TYPE_MODP 1
-#define OAKLEY_GROUP_TYPE_ECP 2
-#define OAKLEY_GROUP_TYPE_EC2N 3
-
-
-/* Notify messages -- error types
- * See RFC2408 ISAKMP 3.14.1
- */
-
-extern enum_names notification_names;
-extern enum_names ipsec_notification_names;
-
-typedef enum {
- ISAKMP_NOTHING_WRONG = 0, /* unofficial! */
-
- ISAKMP_INVALID_PAYLOAD_TYPE = 1,
- ISAKMP_DOI_NOT_SUPPORTED = 2,
- ISAKMP_SITUATION_NOT_SUPPORTED = 3,
- ISAKMP_INVALID_COOKIE = 4,
- ISAKMP_INVALID_MAJOR_VERSION = 5,
- ISAKMP_INVALID_MINOR_VERSION = 6,
- ISAKMP_INVALID_EXCHANGE_TYPE = 7,
- ISAKMP_INVALID_FLAGS = 8,
- ISAKMP_INVALID_MESSAGE_ID = 9,
- ISAKMP_INVALID_PROTOCOL_ID = 10,
- ISAKMP_INVALID_SPI = 11,
- ISAKMP_INVALID_TRANSFORM_ID = 12,
- ISAKMP_ATTRIBUTES_NOT_SUPPORTED = 13,
- ISAKMP_NO_PROPOSAL_CHOSEN = 14,
- ISAKMP_BAD_PROPOSAL_SYNTAX = 15,
- ISAKMP_PAYLOAD_MALFORMED = 16,
- ISAKMP_INVALID_KEY_INFORMATION = 17,
- ISAKMP_INVALID_ID_INFORMATION = 18,
- ISAKMP_INVALID_CERT_ENCODING = 19,
- ISAKMP_INVALID_CERTIFICATE = 20,
- ISAKMP_CERT_TYPE_UNSUPPORTED = 21,
- ISAKMP_INVALID_CERT_AUTHORITY = 22,
- ISAKMP_INVALID_HASH_INFORMATION = 23,
- ISAKMP_AUTHENTICATION_FAILED = 24,
- ISAKMP_INVALID_SIGNATURE = 25,
- ISAKMP_ADDRESS_NOTIFICATION = 26,
- ISAKMP_NOTIFY_SA_LIFETIME = 27,
- ISAKMP_CERTIFICATE_UNAVAILABLE = 28,
- ISAKMP_UNSUPPORTED_EXCHANGE_TYPE = 29,
- ISAKMP_UNEQUAL_PAYLOAD_LENGTHS = 30,
-
- /* ISAKMP status type */
- ISAKMP_CONNECTED = 16384,
-
- /* IPSEC DOI additions; status types (RFC2407 IPSEC DOI 4.6.3)
- * These must be sent under the protection of an ISAKMP SA.
- */
- IPSEC_RESPONDER_LIFETIME = 24576,
- IPSEC_REPLAY_STATUS = 24577,
- IPSEC_INITIAL_CONTACT = 24578,
-
- /* RFC 3706 DPD */
- R_U_THERE = 36136,
- R_U_THERE_ACK = 36137,
-
- /* Juniper SRX private use */
- NS_NHTB_INFORM = 40001
-
- } notification_t;
-
-
-/* Public key algorithm number
- * Same numbering as used in DNSsec
- * See RFC 2535 DNSsec 3.2 The KEY Algorithm Number Specification.
- * Also found in BIND 8.2.2 include/isc/dst.h as DST algorithm codes.
- */
-
-enum pubkey_alg
-{
- PUBKEY_ALG_RSA = 1,
- PUBKEY_ALG_DSA = 3,
-};
-
-/* Limits on size of RSA moduli.
- * The upper bound matches that of DNSsec (see RFC 2537).
- * The lower bound must be more than 11 octets for certain
- * the encoding to work, but it must be much larger for any
- * real security. For now, we require 512 bits.
- */
-
-#define RSA_MIN_OCTETS_RFC 12
-
-#define RSA_MIN_OCTETS (512 / BITS_PER_BYTE)
-#define RSA_MIN_OCTETS_UGH "RSA modulus too small for security: less than 512 bits"
-
-#define RSA_MAX_OCTETS (8192 / BITS_PER_BYTE)
-#define RSA_MAX_OCTETS_UGH "RSA modulus too large: more than 8192 bits"
-
-/* Note: RFC 2537 encoding adds a few bytes. If you use a small
- * modulus like 3, the overhead is only 2 bytes
- */
-#define RSA_MAX_ENCODING_BYTES (RSA_MAX_OCTETS + 2)
-
-/* socket address family info */
-
-struct af_info
-{
- int af;
- const char *name;
- size_t ia_sz;
- size_t sa_sz;
- int mask_cnt;
- u_int8_t id_addr, id_subnet, id_range;
- const ip_address *any;
- const ip_subnet *none; /* 0.0.0.0/32 or IPv6 equivalent */
- const ip_subnet *all; /* 0.0.0.0/0 or IPv6 equivalent */
-};
-
-extern const struct af_info
- af_inet4_info,
- af_inet6_info;
-
-extern const struct af_info *aftoinfo(int af);
-
-extern enum_names af_names;
-
-#define subnetisaddr(sn, a) (subnetishost(sn) && addrinsubnet((a), (sn)))
-extern bool subnetisnone(const ip_subnet *sn);
-
-/* BIND enumerated types */
-
-extern enum_names
- rr_qtype_names,
- rr_type_names,
- rr_class_names;
-
-/* How authenticated is info that might have come from DNS?
- * In order of increasing confidence.
- */
-enum dns_auth_level {
- DAL_UNSIGNED, /* AD in response, but no signature: no authentication */
- DAL_NOTSEC, /* no AD in response: authentication impossible */
- DAL_SIGNED, /* AD and signature in response: authentic */
- DAL_LOCAL /* locally provided (pretty good) */
-};
-
-/*
- * define a macro for use in error messages
- */
-
-#ifdef USE_KEYRR
-#define RRNAME "TXT or KEY"
-#else
-#define RRNAME "TXT"
-#endif
-
-/* natt traversal types */
-extern const char *const natt_type_bitnames[];
-
-/* secret value for responder cookies */
-extern u_char secret_of_the_day[HASH_SIZE_SHA1];
-
-#endif /* _CONSTANTS_H */
diff --git a/src/pluto/cookie.c b/src/pluto/cookie.c
deleted file mode 100644
index 00c863f18..000000000
--- a/src/pluto/cookie.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/* cookie generation/verification routines.
- * Copyright (C) 1997 Angelos D. Keromytis.
- * Copyright (C) 1998-2002 D. Hugh Redelmeier.
- * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-
-#include <freeswan.h>
-
-#include <library.h>
-#include <crypto/rngs/rng.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "cookie.h"
-
-const u_char zero_cookie[COOKIE_SIZE]; /* guaranteed 0 */
-
-/* Generate a cookie.
- * First argument is true if we're to create an Initiator cookie.
- * Length SHOULD be a multiple of sizeof(u_int32_t).
- */
-void get_cookie(bool initiator, u_int8_t *cookie, int length, ip_address *addr)
-{
- hasher_t *hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
- u_char buffer[HASH_SIZE_SHA1];
-
- do {
- if (initiator)
- {
- rng_t *rng;
-
- rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
- rng->get_bytes(rng, length, cookie);
- rng->destroy(rng);
- }
- else /* Responder cookie */
- {
- chunk_t addr_chunk, secret_chunk, counter_chunk;
- size_t addr_len;
- static u_int32_t counter = 0;
- unsigned char addr_buf[
- sizeof(union {struct in_addr A; struct in6_addr B;})];
-
- addr_len = addrbytesof(addr, addr_buf, sizeof(addr_buf));
- addr_chunk = chunk_create(addr_buf, addr_len);
- secret_chunk = chunk_create(secret_of_the_day, HASH_SIZE_SHA1);
- counter++;
- counter_chunk = chunk_create((void *) &counter, sizeof(counter));
- hasher->get_hash(hasher, addr_chunk, NULL);
- hasher->get_hash(hasher, secret_chunk, NULL);
- hasher->get_hash(hasher, counter_chunk, buffer);
- memcpy(cookie, buffer, length);
- }
- } while (is_zero_cookie(cookie)); /* probably never loops */
-
- hasher->destroy(hasher);
-}
diff --git a/src/pluto/crl.c b/src/pluto/crl.c
deleted file mode 100644
index c49b09e19..000000000
--- a/src/pluto/crl.c
+++ /dev/null
@@ -1,541 +0,0 @@
-/* Support of X.509 certificate revocation lists (CRLs)
- * Copyright (C) 2000-2009 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 <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <time.h>
-#include <sys/types.h>
-
-#include <freeswan.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "log.h"
-#include "x509.h"
-#include "crl.h"
-#include "ca.h"
-#include "certs.h"
-#include "keys.h"
-#include "whack.h"
-#include "fetch.h"
-#include "builder.h"
-
-
-/* chained lists of X.509 crls */
-
-static x509crl_t *x509crls = NULL;
-
-/**
- * Get the X.509 CRL with a given issuer
- */
-static x509crl_t* get_x509crl(identification_t *issuer, chunk_t keyid)
-{
- x509crl_t *x509crl = x509crls;
- x509crl_t *prev_crl = NULL;
-
- while (x509crl != NULL)
- {
- certificate_t *cert_crl = x509crl->crl;
- crl_t *crl = (crl_t*)cert_crl;
- identification_t *crl_issuer = cert_crl->get_issuer(cert_crl);
- chunk_t authKeyID = crl->get_authKeyIdentifier(crl);
-
- if ((keyid.ptr && authKeyID.ptr)? same_keyid(keyid, authKeyID) :
- issuer->equals(issuer, crl_issuer))
- {
- if (x509crl != x509crls)
- {
- /* bring the CRL up front */
- prev_crl->next = x509crl->next;
- x509crl->next = x509crls;
- x509crls = x509crl;
- }
- return x509crl;
- }
- prev_crl = x509crl;
- x509crl = x509crl->next;
- }
- return NULL;
-}
-
-/**
- * Free the dynamic memory used to store CRLs
- */
-void free_crl(x509crl_t *crl)
-{
- DESTROY_IF(crl->crl);
- crl->distributionPoints->destroy_function(crl->distributionPoints, free);
- free(crl);
-}
-
-static void free_first_crl(void)
-{
- x509crl_t *crl = x509crls;
-
- x509crls = crl->next;
- free_crl(crl);
-}
-
-void free_crls(void)
-{
- lock_crl_list("free_crls");
-
- while (x509crls != NULL)
- {
- free_first_crl();
- }
-
- unlock_crl_list("free_crls");
-}
-
-/**
- * Insert X.509 CRL into chained list
- */
-bool insert_crl(x509crl_t *x509crl, char *crl_uri, bool cache_crl)
-{
- certificate_t *cert_crl = x509crl->crl;
- crl_t *crl = (crl_t*)cert_crl;
- identification_t *issuer = cert_crl->get_issuer(cert_crl);
- chunk_t authKeyID = crl->get_authKeyIdentifier(crl);
- cert_t *issuer_cert;
- x509crl_t *oldcrl;
- time_t now, nextUpdate;
- bool valid_sig;
-
- /* add distribution point */
- add_distribution_point(x509crl->distributionPoints, crl_uri);
-
- lock_authcert_list("insert_crl");
-
- /* get the issuer cacert */
- issuer_cert = get_authcert(issuer, authKeyID, X509_CA);
- if (issuer_cert == NULL)
- {
- plog("crl issuer cacert not found");
- free_crl(x509crl);
- unlock_authcert_list("insert_crl");
- return FALSE;
- }
- DBG(DBG_CONTROL,
- DBG_log("crl issuer cacert found")
- )
-
- /* check the issuer's signature of the crl */
- valid_sig = cert_crl->issued_by(cert_crl, issuer_cert->cert);
- unlock_authcert_list("insert_crl");
-
- if (!valid_sig)
- {
- free_crl(x509crl);
- return FALSE;
- }
- DBG(DBG_CONTROL,
- DBG_log("crl signature is valid")
- )
-
- /* note the current time */
- time(&now);
-
- lock_crl_list("insert_crl");
- oldcrl = get_x509crl(issuer, authKeyID);
-
- if (oldcrl != NULL)
- {
- certificate_t *old_cert_crl = oldcrl->crl;
-
- if (crl_is_newer((crl_t*)cert_crl, (crl_t*)old_cert_crl))
- {
- /* keep any known CRL distribution points */
- add_distribution_points(x509crl->distributionPoints,
- oldcrl->distributionPoints);
-
- /* now delete the old CRL */
- free_first_crl();
- DBG(DBG_CONTROL,
- DBG_log("thisUpdate is newer - existing crl deleted")
- )
- }
- else
- {
- unlock_crl_list("insert_crls");
- DBG(DBG_CONTROL,
- DBG_log("thisUpdate is not newer - existing crl not replaced");
- )
- free_crl(x509crl);
- old_cert_crl->get_validity(old_cert_crl, &now, NULL, &nextUpdate);
- return nextUpdate - now > 2*crl_check_interval;
- }
- }
-
- /* insert new CRL */
- x509crl->next = x509crls;
- x509crls = x509crl;
-
- unlock_crl_list("insert_crl");
-
- /* If crl caching is enabled then the crl is saved locally.
- * Only http or ldap URIs are cached but not local file URIs.
- * The CRL's authorityKeyIdentifier is used as a unique filename
- */
- if (cache_crl && strncasecmp(crl_uri, "file", 4) != 0)
- {
- char buf[BUF_LEN];
- chunk_t hex, encoding;
-
- hex = chunk_to_hex(crl->get_authKeyIdentifier(crl), NULL, FALSE);
- snprintf(buf, sizeof(buf), "%s/%s.crl", CRL_PATH, hex.ptr);
- free(hex.ptr);
-
- if (cert_crl->get_encoding(cert_crl, CERT_ASN1_DER, &encoding))
- {
- chunk_write(encoding, buf, "crl", 022, TRUE);
- free(encoding.ptr);
- }
- }
-
- /* is the fetched crl valid? */
- cert_crl->get_validity(cert_crl, &now, NULL, &nextUpdate);
- return nextUpdate - now > 2*crl_check_interval;
-}
-
-/**
- * Loads CRLs
- */
-void load_crls(void)
-{
- struct dirent **filelist;
- u_char buf[BUF_LEN];
- u_char *save_dir;
- int n;
-
- /* change directory to specified path */
- save_dir = getcwd(buf, BUF_LEN);
- if (chdir(CRL_PATH))
- {
- plog("Could not change to directory '%s'", CRL_PATH);
- }
- else
- {
- plog("Changing to directory '%s'", CRL_PATH);
- n = scandir(CRL_PATH, &filelist, file_select, alphasort);
-
- if (n < 0)
- plog(" scandir() error");
- else
- {
- while (n--)
- {
- char *filename = filelist[n]->d_name;
- x509crl_t *x509crl;
-
- x509crl = lib->creds->create(lib->creds, CRED_CERTIFICATE,
- CERT_PLUTO_CRL,
- BUILD_FROM_FILE, filename, BUILD_END);
- if (x509crl)
- {
- char crl_uri[BUF_LEN];
-
- plog(" loaded crl from '%s'", filename);
- snprintf(crl_uri, BUF_LEN, "file://%s/%s", CRL_PATH, filename);
- insert_crl(x509crl, crl_uri, FALSE);
- }
- free(filelist[n]);
- }
- free(filelist);
- }
- }
- /* restore directory path */
- ignore_result(chdir(save_dir));
-}
-
-
-/* Checks if the current certificate is revoked. It goes through the
- * list of revoked certificates of the corresponding crl. Either the
- * status CERT_GOOD or CERT_REVOKED is returned
- */
-static cert_status_t check_revocation(crl_t *crl, chunk_t cert_serial,
- time_t *revocationDate,
- crl_reason_t *revocationReason)
-{
- enumerator_t *enumerator;
- cert_status_t status;
- chunk_t serial;
-
- DBG(DBG_CONTROL,
- DBG_log("serial number: %#B", &cert_serial)
- )
- *revocationDate = UNDEFINED_TIME;
- *revocationReason = CRL_REASON_UNSPECIFIED;
- status = CERT_GOOD;
-
- enumerator = crl->create_enumerator(crl);
- while (enumerator->enumerate(enumerator, &serial,
- revocationDate, revocationReason))
- {
- if (chunk_equals(serial, cert_serial))
- {
- status = CERT_REVOKED;
- break;
- }
- }
- enumerator->destroy(enumerator);
- return status;
-}
-
-/*
- * check if any crls are about to expire
- */
-void check_crls(void)
-{
- x509crl_t *x509crl;
- time_t now, nextUpdate, time_left;
-
- lock_crl_list("check_crls");
- time(&now);
- x509crl = x509crls;
-
- while (x509crl != NULL)
- {
- certificate_t *cert_crl = x509crl->crl;
- crl_t *crl = (crl_t*)cert_crl;
- identification_t *issuer = cert_crl->get_issuer(cert_crl);
- chunk_t authKeyID = crl->get_authKeyIdentifier(crl);
-
- cert_crl->get_validity(cert_crl, &now, NULL, &nextUpdate);
- time_left = nextUpdate - now;
-
- DBG(DBG_CONTROL,
- DBG_log("issuer: '%Y'", issuer);
- if (authKeyID.ptr)
- {
- DBG_log("authkey: %#B", &authKeyID);
- }
- DBG_log("%ld seconds left", time_left)
- )
- if (time_left < 2*crl_check_interval)
- {
- fetch_req_t *req = build_crl_fetch_request(issuer, authKeyID,
- x509crl->distributionPoints);
- add_crl_fetch_request(req);
- }
- x509crl = x509crl->next;
- }
- unlock_crl_list("check_crls");
-}
-
-/*
- * verify if a cert hasn't been revoked by a crl
- */
-cert_status_t verify_by_crl(cert_t *cert, time_t *until, time_t *revocationDate,
- crl_reason_t *revocationReason)
-{
- certificate_t *certificate = cert->cert;
- x509_t *x509 = (x509_t*)certificate;
- identification_t *issuer = certificate->get_issuer(certificate);
- chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
- x509crl_t *x509crl;
- ca_info_t *ca;
- enumerator_t *enumerator;
- x509_cdp_t *cdp;
-
- ca = get_ca_info(issuer, authKeyID);
-
- *revocationDate = UNDEFINED_TIME;
- *revocationReason = CRL_REASON_UNSPECIFIED;
-
- lock_crl_list("verify_by_crl");
- x509crl = get_x509crl(issuer, authKeyID);
-
- if (x509crl == NULL)
- {
- linked_list_t *crluris;
-
- unlock_crl_list("verify_by_crl");
- plog("crl not found");
-
- crluris = linked_list_create();
- if (ca)
- {
- add_distribution_points(crluris, ca->crluris);
- }
-
- enumerator = x509->create_crl_uri_enumerator(x509);
- while (enumerator->enumerate(enumerator, &cdp))
- {
- add_distribution_point(crluris, cdp->uri);
- }
- enumerator->destroy(enumerator);
-
- if (crluris->get_count(crluris) > 0)
- {
- fetch_req_t *req;
-
- req = build_crl_fetch_request(issuer, authKeyID, crluris);
- crluris->destroy_function(crluris, free);
- add_crl_fetch_request(req);
- wake_fetch_thread("verify_by_crl");
- return CERT_UNKNOWN;
- }
- else
- {
- crluris->destroy(crluris);
- return CERT_UNDEFINED;
- }
- }
- else
- {
- certificate_t *cert_crl = x509crl->crl;
- crl_t *crl = (crl_t*)cert_crl;
- chunk_t authKeyID = crl->get_authKeyIdentifier(crl);
- cert_t *issuer_cert;
- bool trusted, valid;
-
- DBG(DBG_CONTROL,
- DBG_log("crl found")
- )
-
- if (ca)
- {
- add_distribution_points(x509crl->distributionPoints, ca->crluris);
- }
-
- enumerator = x509->create_crl_uri_enumerator(x509);
- while (enumerator->enumerate(enumerator, &cdp))
- {
- add_distribution_point(x509crl->distributionPoints, cdp->uri);
- }
- enumerator->destroy(enumerator);
-
- lock_authcert_list("verify_by_crl");
-
- issuer_cert = get_authcert(issuer, authKeyID, X509_CA);
- trusted = issuer_cert ? cert_crl->issued_by(cert_crl, issuer_cert->cert)
- : FALSE;
-
- unlock_authcert_list("verify_by_crl");
-
- if (trusted)
- {
- cert_status_t status;
-
- DBG(DBG_CONTROL,
- DBG_log("crl signature is valid")
- )
-
- /* return the expiration date */
- valid = cert_crl->get_validity(cert_crl, NULL, NULL, until);
-
- /* has the certificate been revoked? */
- status = check_revocation(crl, x509->get_serial(x509), revocationDate
- , revocationReason);
-
- if (valid)
- {
- unlock_crl_list("verify_by_crl");
- DBG(DBG_CONTROL,
- DBG_log("crl is valid: until %T", until, FALSE)
- )
- }
- else
- {
- fetch_req_t *req;
-
- DBG(DBG_CONTROL,
- DBG_log("crl is stale: since %T", until, FALSE)
- )
-
- /* try to fetch a crl update */
- req = build_crl_fetch_request(issuer, authKeyID,
- x509crl->distributionPoints);
- unlock_crl_list("verify_by_crl");
-
- add_crl_fetch_request(req);
- wake_fetch_thread("verify_by_crl");
- }
- return status;
- }
- else
- {
- unlock_crl_list("verify_by_crl");
- plog("crl signature is invalid");
- return CERT_UNKNOWN;
- }
- }
-}
-
-/*
- * list all X.509 crls in the chained list
- */
-void list_crls(bool utc, bool strict)
-{
- x509crl_t *x509crl;
-
- lock_crl_list("list_crls");
- x509crl = x509crls;
-
- if (x509crl)
- {
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, "List of X.509 CRLs:");
- }
-
- while (x509crl)
- {
- certificate_t *cert_crl = x509crl->crl;
- crl_t *crl = (crl_t*)cert_crl;
- chunk_t serial, authKeyID;
- time_t thisUpdate, nextUpdate;
- u_int revoked = 0;
- enumerator_t *enumerator;
-
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, " issuer: \"%Y\"",
- cert_crl->get_issuer(cert_crl));
- serial = chunk_skip_zero(crl->get_serial(crl));
- if (serial.ptr)
- {
- whack_log(RC_COMMENT, " serial: %#B", &serial);
- }
-
- /* count number of revoked certificates in CRL */
- enumerator = crl->create_enumerator(crl);
- while (enumerator->enumerate(enumerator, NULL, NULL, NULL))
- {
- revoked++;
- }
- enumerator->destroy(enumerator);
- whack_log(RC_COMMENT, " revoked: %d certificates", revoked);
-
- list_distribution_points(x509crl->distributionPoints);
-
- cert_crl->get_validity(cert_crl, NULL, &thisUpdate, &nextUpdate);
- whack_log(RC_COMMENT, " updates: this %T", &thisUpdate, utc);
- whack_log(RC_COMMENT, " next %T %s", &nextUpdate, utc,
- check_expiry(nextUpdate, CRL_WARNING_INTERVAL, strict));
- authKeyID = crl->get_authKeyIdentifier(crl);
- if (authKeyID.ptr)
- {
- whack_log(RC_COMMENT, " authkey: %#B", &authKeyID);
- }
-
- x509crl = x509crl->next;
- }
- unlock_crl_list("list_crls");
-}
-
diff --git a/src/pluto/crl.h b/src/pluto/crl.h
deleted file mode 100644
index 43bafe145..000000000
--- a/src/pluto/crl.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* Support of X.509 certificate revocation lists (CRLs)
- * Copyright (C) 2000-2004 Andreas Steffen, Zuercher Hochschule Winterthur
- *
- * 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 "constants.h"
-
-#include <utils/linked_list.h>
-#include <credentials/certificates/certificate.h>
-#include <credentials/certificates/crl.h>
-
-/* storage structure for an X.509 CRL */
-
-typedef struct x509crl x509crl_t;
-
-struct x509crl {
- certificate_t *crl;
- x509crl_t *next;
- linked_list_t *distributionPoints;
-};
-
-/* apply a strict CRL policy
- * flag set in plutomain.c and used in ipsec_doi.c and rcv_whack.c
- */
-extern bool strict_crl_policy;
-
-/*
- * cache the retrieved CRLs by storing them locally as a file
- */
-extern bool cache_crls;
-
-/*
- * check periodically for expired crls
- */
-extern long crl_check_interval;
-extern void load_crls(void);
-extern void check_crls(void);
-extern bool insert_crl(x509crl_t *crl, char *crl_uri, bool cache_crl);
-extern cert_status_t verify_by_crl(cert_t *cert, time_t *until,
- time_t *revocationDate,
- crl_reason_t *revocationReason);
-extern void list_crls(bool utc, bool strict);
-extern void free_crls(void);
-extern void free_crl(x509crl_t *crl);
diff --git a/src/pluto/crypto.c b/src/pluto/crypto.c
deleted file mode 100644
index a4f678222..000000000
--- a/src/pluto/crypto.c
+++ /dev/null
@@ -1,698 +0,0 @@
-/* crypto interfaces
- *
- * Copyright (C) 2010 Tobias Brunner
- * Copyright (C) 2007-2009 Andreas Steffen
- * Hochschule fuer Technik Rapperswil
- *
- * Copyright (C) 1998-2001 D. Hugh Redelmeier
- *
- * 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 <freeswan.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "crypto.h"
-#include "log.h"
-
-static struct encrypt_desc encrypt_desc_3des =
-{
- algo_type: IKE_ALG_ENCRYPT,
- algo_id: OAKLEY_3DES_CBC,
- plugin_name: NULL,
- algo_next: NULL,
-
- enc_blocksize: DES_BLOCK_SIZE,
- keydeflen: DES_BLOCK_SIZE * 3 * BITS_PER_BYTE,
- keyminlen: DES_BLOCK_SIZE * 3 * BITS_PER_BYTE,
- keymaxlen: DES_BLOCK_SIZE * 3 * BITS_PER_BYTE,
-};
-
-#define AES_KEY_MIN_LEN 128
-#define AES_KEY_DEF_LEN 128
-#define AES_KEY_MAX_LEN 256
-
-static struct encrypt_desc encrypt_desc_aes =
-{
- algo_type: IKE_ALG_ENCRYPT,
- algo_id: OAKLEY_AES_CBC,
- plugin_name: NULL,
- algo_next: NULL,
-
- enc_blocksize: AES_BLOCK_SIZE,
- keyminlen: AES_KEY_MIN_LEN,
- keydeflen: AES_KEY_DEF_LEN,
- keymaxlen: AES_KEY_MAX_LEN,
-};
-
-#define CAMELLIA_KEY_MIN_LEN 128
-#define CAMELLIA_KEY_DEF_LEN 128
-#define CAMELLIA_KEY_MAX_LEN 256
-
-static struct encrypt_desc encrypt_desc_camellia =
-{
- algo_type: IKE_ALG_ENCRYPT,
- algo_id: OAKLEY_CAMELLIA_CBC,
- plugin_name: NULL,
- algo_next: NULL,
-
- enc_blocksize: CAMELLIA_BLOCK_SIZE,
- keyminlen: CAMELLIA_KEY_MIN_LEN,
- keydeflen: CAMELLIA_KEY_DEF_LEN,
- keymaxlen: CAMELLIA_KEY_MAX_LEN,
-};
-
-#define BLOWFISH_KEY_MIN_LEN 128
-#define BLOWFISH_KEY_MAX_LEN 448
-
-static struct encrypt_desc encrypt_desc_blowfish =
-{
- algo_type: IKE_ALG_ENCRYPT,
- algo_id: OAKLEY_BLOWFISH_CBC,
- plugin_name: NULL,
- algo_next: NULL,
-
- enc_blocksize: BLOWFISH_BLOCK_SIZE,
- keyminlen: BLOWFISH_KEY_MIN_LEN,
- keydeflen: BLOWFISH_KEY_MIN_LEN,
- keymaxlen: BLOWFISH_KEY_MAX_LEN,
-};
-
-#define SERPENT_KEY_MIN_LEN 128
-#define SERPENT_KEY_DEF_LEN 128
-#define SERPENT_KEY_MAX_LEN 256
-
-static struct encrypt_desc encrypt_desc_serpent =
-{
- algo_type: IKE_ALG_ENCRYPT,
- algo_id: OAKLEY_SERPENT_CBC,
- plugin_name: NULL,
- algo_next: NULL,
-
- enc_blocksize: SERPENT_BLOCK_SIZE,
- keyminlen: SERPENT_KEY_MIN_LEN,
- keydeflen: SERPENT_KEY_DEF_LEN,
- keymaxlen: SERPENT_KEY_MAX_LEN,
-};
-
-#define TWOFISH_KEY_MIN_LEN 128
-#define TWOFISH_KEY_DEF_LEN 128
-#define TWOFISH_KEY_MAX_LEN 256
-
-static struct encrypt_desc encrypt_desc_twofish =
-{
- algo_type: IKE_ALG_ENCRYPT,
- algo_id: OAKLEY_TWOFISH_CBC,
- plugin_name: NULL,
- algo_next: NULL,
-
- enc_blocksize: TWOFISH_BLOCK_SIZE,
- keydeflen: TWOFISH_KEY_MIN_LEN,
- keyminlen: TWOFISH_KEY_DEF_LEN,
- keymaxlen: TWOFISH_KEY_MAX_LEN,
-};
-
-static struct encrypt_desc encrypt_desc_twofish_ssh =
-{
- algo_type: IKE_ALG_ENCRYPT,
- algo_id: OAKLEY_TWOFISH_CBC_SSH,
- plugin_name: NULL,
- algo_next: NULL,
-
- enc_blocksize: TWOFISH_BLOCK_SIZE,
- keydeflen: TWOFISH_KEY_MIN_LEN,
- keyminlen: TWOFISH_KEY_DEF_LEN,
- keymaxlen: TWOFISH_KEY_MAX_LEN,
-};
-
-static struct hash_desc hash_desc_md5 =
-{
- algo_type: IKE_ALG_HASH,
- algo_id: OAKLEY_MD5,
- plugin_name: NULL,
- algo_next: NULL,
- hash_digest_size: HASH_SIZE_MD5,
-};
-
-static struct hash_desc hash_desc_sha1 =
-{
- algo_type: IKE_ALG_HASH,
- algo_id: OAKLEY_SHA,
- plugin_name: NULL,
- algo_next: NULL,
- hash_digest_size: HASH_SIZE_SHA1,
-};
-
-static struct hash_desc hash_desc_sha2_256 = {
- algo_type: IKE_ALG_HASH,
- algo_id: OAKLEY_SHA2_256,
- plugin_name: NULL,
- algo_next: NULL,
- hash_digest_size: HASH_SIZE_SHA256,
-};
-
-static struct hash_desc hash_desc_sha2_384 = {
- algo_type: IKE_ALG_HASH,
- algo_id: OAKLEY_SHA2_384,
- plugin_name: NULL,
- algo_next: NULL,
- hash_digest_size: HASH_SIZE_SHA384,
-};
-
-static struct hash_desc hash_desc_sha2_512 = {
- algo_type: IKE_ALG_HASH,
- algo_id: OAKLEY_SHA2_512,
- plugin_name: NULL,
- algo_next: NULL,
- hash_digest_size: HASH_SIZE_SHA512,
-};
-
-const struct dh_desc unset_group = {
- algo_type: IKE_ALG_DH_GROUP,
- algo_id: MODP_NONE,
- plugin_name: NULL,
- algo_next: NULL,
- ke_size: 0
-};
-
-static struct dh_desc dh_desc_modp_1024 = {
- algo_type: IKE_ALG_DH_GROUP,
- algo_id: MODP_1024_BIT,
- plugin_name: NULL,
- algo_next: NULL,
- ke_size: 1024 / BITS_PER_BYTE
-};
-
-static struct dh_desc dh_desc_modp_1536 = {
- algo_type: IKE_ALG_DH_GROUP,
- algo_id: MODP_1536_BIT,
- plugin_name: NULL,
- algo_next: NULL,
- ke_size: 1536 / BITS_PER_BYTE
-};
-
-static struct dh_desc dh_desc_modp_2048 = {
- algo_type: IKE_ALG_DH_GROUP,
- algo_id: MODP_2048_BIT,
- algo_next: NULL,
- ke_size: 2048 / BITS_PER_BYTE
-};
-
-static struct dh_desc dh_desc_modp_3072 = {
- algo_type: IKE_ALG_DH_GROUP,
- algo_id: MODP_3072_BIT,
- plugin_name: NULL,
- algo_next: NULL,
- ke_size: 3072 / BITS_PER_BYTE
-};
-
-static struct dh_desc dh_desc_modp_4096 = {
- algo_type: IKE_ALG_DH_GROUP,
- algo_id: MODP_4096_BIT,
- plugin_name: NULL,
- algo_next: NULL,
- ke_size: 4096 / BITS_PER_BYTE
-};
-
-static struct dh_desc dh_desc_modp_6144 = {
- algo_type: IKE_ALG_DH_GROUP,
- algo_id: MODP_6144_BIT,
- plugin_name: NULL,
- algo_next: NULL,
- ke_size: 6144 / BITS_PER_BYTE
-};
-
-static struct dh_desc dh_desc_modp_8192 = {
- algo_type: IKE_ALG_DH_GROUP,
- algo_id: MODP_8192_BIT,
- plugin_name: NULL,
- algo_next: NULL,
- ke_size: 8192 / BITS_PER_BYTE
-};
-
-static struct dh_desc dh_desc_ecp_256 = {
- algo_type: IKE_ALG_DH_GROUP,
- algo_id: ECP_256_BIT,
- plugin_name: NULL,
- algo_next: NULL,
- ke_size: 2*256 / BITS_PER_BYTE
-};
-
-static struct dh_desc dh_desc_ecp_384 = {
- algo_type: IKE_ALG_DH_GROUP,
- algo_id: ECP_384_BIT,
- plugin_name: NULL,
- algo_next: NULL,
- ke_size: 2*384 / BITS_PER_BYTE
-};
-
-static struct dh_desc dh_desc_ecp_521 = {
- algo_type: IKE_ALG_DH_GROUP,
- algo_id: ECP_521_BIT,
- plugin_name: NULL,
- algo_next: NULL,
- ke_size: 2*528 / BITS_PER_BYTE
-};
-
-static struct dh_desc dh_desc_modp_1024_160 = {
- algo_type: IKE_ALG_DH_GROUP,
- algo_id: MODP_1024_160,
- plugin_name: NULL,
- algo_next: NULL,
- ke_size: 1024 / BITS_PER_BYTE
-};
-
-static struct dh_desc dh_desc_modp_2048_224 = {
- algo_type: IKE_ALG_DH_GROUP,
- algo_id: MODP_2048_224,
- plugin_name: NULL,
- algo_next: NULL,
- ke_size: 2048 / BITS_PER_BYTE
-};
-
-static struct dh_desc dh_desc_modp_2048_256 = {
- algo_type: IKE_ALG_DH_GROUP,
- algo_id: MODP_2048_256,
- plugin_name: NULL,
- algo_next: NULL,
- ke_size: 2048 / BITS_PER_BYTE
-};
-
-static struct dh_desc dh_desc_ecp_192 = {
- algo_type: IKE_ALG_DH_GROUP,
- algo_id: ECP_192_BIT,
- plugin_name: NULL,
- algo_next: NULL,
- ke_size: 2*192 / BITS_PER_BYTE
-};
-
-static struct dh_desc dh_desc_ecp_224 = {
- algo_type: IKE_ALG_DH_GROUP,
- algo_id: ECP_224_BIT,
- plugin_name: NULL,
- algo_next: NULL,
- ke_size: 2*224 / BITS_PER_BYTE
-};
-
-bool init_crypto(void)
-{
- enumerator_t *enumerator;
- encryption_algorithm_t encryption_alg;
- hash_algorithm_t hash_alg;
- diffie_hellman_group_t dh_group;
- const char *plugin_name;
- bool no_md5 = TRUE;
- bool no_sha1 = TRUE;
-
- enumerator = lib->crypto->create_hasher_enumerator(lib->crypto);
- while (enumerator->enumerate(enumerator, &hash_alg, &plugin_name))
- {
- const struct hash_desc *desc;
-
- switch (hash_alg)
- {
- case HASH_SHA1:
- desc = &hash_desc_sha1;
- no_sha1 = FALSE;
- break;
- case HASH_SHA256:
- desc = &hash_desc_sha2_256;
- break;
- case HASH_SHA384:
- desc = &hash_desc_sha2_384;
- break;
- case HASH_SHA512:
- desc = &hash_desc_sha2_512;
- break;
- case HASH_MD5:
- desc = &hash_desc_md5;
- no_md5 = FALSE;
- break;
- default:
- continue;
- }
- ike_alg_add((struct ike_alg *)desc, plugin_name);
- }
- enumerator->destroy(enumerator);
-
- if (no_sha1 || no_md5)
- {
- plog("pluto cannot run without a %s%s%s hasher",
- (no_sha1) ? "SHA-1" : "",
- (no_sha1 && no_md5) ? " and " : "",
- (no_md5) ? "MD5" : "");
- return FALSE;
- }
-
- enumerator = lib->crypto->create_crypter_enumerator(lib->crypto);
- while (enumerator->enumerate(enumerator, &encryption_alg, &plugin_name))
- {
- const struct encrypt_desc *desc;
-
- switch (encryption_alg)
- {
- case ENCR_3DES:
- desc = &encrypt_desc_3des;
- break;
- case ENCR_BLOWFISH:
- desc = &encrypt_desc_blowfish;
- break;
- case ENCR_AES_CBC:
- desc = &encrypt_desc_aes;
- break;
- case ENCR_CAMELLIA_CBC:
- desc = &encrypt_desc_camellia;
- break;
- case ENCR_TWOFISH_CBC:
- desc = &encrypt_desc_twofish;
- ike_alg_add((struct ike_alg *)&encrypt_desc_twofish_ssh,
- plugin_name);
- break;
- case ENCR_SERPENT_CBC:
- desc = &encrypt_desc_serpent;
- break;
- default:
- continue;
- }
- ike_alg_add((struct ike_alg *)desc, plugin_name);
- }
- enumerator->destroy(enumerator);
-
- enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
- while (enumerator->enumerate(enumerator, &dh_group, &plugin_name))
- {
- const struct dh_desc *desc;
-
- switch (dh_group)
- {
- case MODP_1024_BIT:
- desc = &dh_desc_modp_1024;
- break;
- case MODP_1536_BIT:
- desc = &dh_desc_modp_1536;
- break;
- case MODP_2048_BIT:
- desc = &dh_desc_modp_2048;
- break;
- case MODP_3072_BIT:
- desc = &dh_desc_modp_3072;
- break;
- case MODP_4096_BIT:
- desc = &dh_desc_modp_4096;
- break;
- case MODP_6144_BIT:
- desc = &dh_desc_modp_6144;
- break;
- case MODP_8192_BIT:
- desc = &dh_desc_modp_8192;
- break;
- case ECP_256_BIT:
- desc = &dh_desc_ecp_256;
- break;
- case ECP_384_BIT:
- desc = &dh_desc_ecp_384;
- break;
- case ECP_521_BIT:
- desc = &dh_desc_ecp_521;
- break;
- case MODP_1024_160:
- desc = &dh_desc_modp_1024_160;
- break;
- case MODP_2048_224:
- desc = &dh_desc_modp_2048_224;
- break;
- case MODP_2048_256:
- desc = &dh_desc_modp_2048_256;
- break;
- case ECP_192_BIT:
- desc = &dh_desc_ecp_192;
- break;
- case ECP_224_BIT:
- desc = &dh_desc_ecp_224;
- break;
- default:
- continue;
- }
- ike_alg_add((struct ike_alg *)desc, plugin_name);
- }
- enumerator->destroy(enumerator);
- return TRUE;
-}
-
-void free_crypto(void)
-{
- /* currently nothing to do */
-}
-
-/**
- * Converts IKEv1 encryption algorithm name to crypter name
- */
-encryption_algorithm_t oakley_to_encryption_algorithm(int alg)
-{
- switch (alg)
- {
- case OAKLEY_DES_CBC:
- return ENCR_DES;
- case OAKLEY_IDEA_CBC:
- return ENCR_IDEA;
- case OAKLEY_BLOWFISH_CBC:
- return ENCR_BLOWFISH;
- case OAKLEY_RC5_R16_B64_CBC:
- return ENCR_RC5;
- case OAKLEY_3DES_CBC:
- return ENCR_3DES;
- case OAKLEY_CAST_CBC:
- return ENCR_CAST;
- case OAKLEY_AES_CBC:
- return ENCR_AES_CBC;
- case OAKLEY_CAMELLIA_CBC:
- return ENCR_CAMELLIA_CBC;
- case OAKLEY_SERPENT_CBC:
- return ENCR_SERPENT_CBC;
- case OAKLEY_TWOFISH_CBC:
- case OAKLEY_TWOFISH_CBC_SSH:
- return ENCR_TWOFISH_CBC;
- default:
- return ENCR_UNDEFINED;
- }
-}
-
-/**
- * Converts IKEv1 hash algorithm name to hasher name
- */
-hash_algorithm_t oakley_to_hash_algorithm(int alg)
-{
- switch (alg)
- {
- case OAKLEY_MD5:
- return HASH_MD5;
- case OAKLEY_SHA:
- return HASH_SHA1;
- case OAKLEY_SHA2_256:
- return HASH_SHA256;
- case OAKLEY_SHA2_384:
- return HASH_SHA384;
- case OAKLEY_SHA2_512:
- return HASH_SHA512;
- default:
- return HASH_UNKNOWN;
- }
-}
-
-/**
- * Converts IKEv1 hash algorithm name to IKEv2 prf name
- */
-pseudo_random_function_t oakley_to_prf(int alg)
-{
- switch (alg)
- {
- case OAKLEY_MD5:
- return PRF_HMAC_MD5;
- case OAKLEY_SHA:
- return PRF_HMAC_SHA1;
- case OAKLEY_SHA2_256:
- return PRF_HMAC_SHA2_256;
- case OAKLEY_SHA2_384:
- return PRF_HMAC_SHA2_384;
- case OAKLEY_SHA2_512:
- return PRF_HMAC_SHA2_512;
- default:
- return PRF_UNDEFINED;
- }
-}
-
-/**
- * Maps IKEv1 authentication method to IKEv2 signature scheme
- */
-signature_scheme_t oakley_to_signature_scheme(int method)
-{
- switch (method)
- {
- case OAKLEY_RSA_SIG:
- case XAUTHInitRSA:
- case XAUTHRespRSA:
- return SIGN_RSA_EMSA_PKCS1_NULL;
- case OAKLEY_ECDSA_256:
- case OAKLEY_ECDSA_384:
- case OAKLEY_ECDSA_521:
- return SIGN_ECDSA_WITH_NULL;
- default:
- return SIGN_UNKNOWN;
- }
-}
-
-/**
- * Table to map IKEv2 encryption algorithms to IKEv1 (or IKEv1 ESP) and back
- */
-struct {
- encryption_algorithm_t alg;
- int oakley;
- int esp;
-} encr_map[] = {
- {ENCR_DES, OAKLEY_DES_CBC, ESP_DES },
- {ENCR_3DES, OAKLEY_3DES_CBC, ESP_3DES },
- {ENCR_RC5, OAKLEY_RC5_R16_B64_CBC, ESP_RC5 },
- {ENCR_IDEA, OAKLEY_IDEA_CBC, ESP_IDEA },
- {ENCR_CAST, OAKLEY_CAST_CBC, ESP_CAST },
- {ENCR_BLOWFISH, OAKLEY_BLOWFISH_CBC, ESP_BLOWFISH },
- {ENCR_AES_CBC, OAKLEY_AES_CBC, ESP_AES },
- {ENCR_CAMELLIA_CBC, OAKLEY_CAMELLIA_CBC, ESP_CAMELLIA },
- {ENCR_SERPENT_CBC, OAKLEY_SERPENT_CBC, ESP_SERPENT },
- {ENCR_TWOFISH_CBC, OAKLEY_TWOFISH_CBC, ESP_TWOFISH },
- {ENCR_NULL, 0, ESP_NULL },
- {ENCR_AES_CTR, 0, ESP_AES_CTR },
- {ENCR_AES_CCM_ICV8, 0, ESP_AES_CCM_8 },
- {ENCR_AES_CCM_ICV12, 0, ESP_AES_CCM_12},
- {ENCR_AES_CCM_ICV16, 0, ESP_AES_CCM_16},
- {ENCR_AES_GCM_ICV8, 0, ESP_AES_GCM_8 },
- {ENCR_AES_GCM_ICV12, 0, ESP_AES_GCM_12},
- {ENCR_AES_GCM_ICV16, 0, ESP_AES_GCM_16},
- {ENCR_NULL_AUTH_AES_GMAC, 0, ESP_AES_GMAC },
-};
-
-/**
- * Converts IKEv2 encryption to IKEv1 encryption algorithm
- */
-int oakley_from_encryption_algorithm(encryption_algorithm_t alg)
-{
- int i;
- for (i = 0; i < countof(encr_map); i++)
- {
- if (encr_map[i].alg == alg)
- {
- return encr_map[i].oakley;
- }
- }
- return 0;
-}
-
-/**
- * Converts IKEv2 encryption to IKEv1 ESP encryption algorithm
- */
-int esp_from_encryption_algorithm(encryption_algorithm_t alg)
-{
- int i;
- for (i = 0; i < countof(encr_map); i++)
- {
- if (encr_map[i].alg == alg)
- {
- return encr_map[i].esp;
- }
- }
- return 0;
-}
-
-/**
- * Converts IKEv1 ESP encryption to IKEv2 algorithm
- */
-encryption_algorithm_t encryption_algorithm_from_esp(int esp)
-{
- int i;
- for (i = 0; i < countof(encr_map); i++)
- {
- if (encr_map[i].esp == esp)
- {
- return encr_map[i].alg;
- }
- }
- return 0;
-}
-
-/**
- * Table to map IKEv2 integrity algorithms to IKEv1 (or IKEv1 ESP) and back
- */
-struct {
- integrity_algorithm_t alg;
- int oakley;
- int esp;
-} auth_map[] = {
- {AUTH_HMAC_MD5_96, OAKLEY_MD5, AUTH_ALGORITHM_HMAC_MD5 },
- {AUTH_HMAC_SHA1_96, OAKLEY_SHA, AUTH_ALGORITHM_HMAC_SHA1 },
- {AUTH_HMAC_SHA2_256_96, 0, AUTH_ALGORITHM_HMAC_SHA2_256_96},
- {AUTH_HMAC_SHA2_256_128, OAKLEY_SHA2_256, AUTH_ALGORITHM_HMAC_SHA2_256 },
- {AUTH_HMAC_SHA2_384_192, OAKLEY_SHA2_384, AUTH_ALGORITHM_HMAC_SHA2_384 },
- {AUTH_HMAC_SHA2_512_256, OAKLEY_SHA2_512, AUTH_ALGORITHM_HMAC_SHA2_512 },
- {AUTH_AES_XCBC_96, 0, AUTH_ALGORITHM_AES_XCBC_MAC },
- {AUTH_AES_128_GMAC, 0, AUTH_ALGORITHM_AES_128_GMAC },
- {AUTH_AES_192_GMAC, 0, AUTH_ALGORITHM_AES_192_GMAC },
- {AUTH_AES_256_GMAC, 0, AUTH_ALGORITHM_AES_256_GMAC },
-};
-
-
-/**
- * Converts IKEv2 integrity to IKEv1 hash algorithm
- */
-int oakley_from_integrity_algorithm(integrity_algorithm_t alg)
-{
- int i;
- for (i = 0; i < countof(auth_map); i++)
- {
- if (auth_map[i].alg == alg)
- {
- return auth_map[i].oakley;
- }
- }
- return 0;
-}
-
-/**
- * Converts IKEv2 integrity to IKEv1 ESP authentication algorithm
- */
-int esp_from_integrity_algorithm(integrity_algorithm_t alg)
-{
- int i;
- for (i = 0; i < countof(auth_map); i++)
- {
- if (auth_map[i].alg == alg)
- {
- return auth_map[i].esp;
- }
- }
- return 0;
-}
-
-/**
- * Converts IKEv1 ESP authentication to IKEv2 integrity algorithm
- */
-integrity_algorithm_t integrity_algorithm_from_esp(int esp)
-{
- int i;
- for (i = 0; i < countof(auth_map); i++)
- {
- if (auth_map[i].esp == esp)
- {
- return auth_map[i].alg;
- }
- }
- return 0;
-}
-
diff --git a/src/pluto/crypto.h b/src/pluto/crypto.h
deleted file mode 100644
index 16ad12780..000000000
--- a/src/pluto/crypto.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* crypto interfaces
- *
- * Copyright (C) 2010 Tobias Brunner
- * Copyright (C) 2009 Andreas Steffen
- * Hochschule fuer Technik Rapperswil
- *
- * Copyright (C) 1998, 1999 D. Hugh Redelmeier.
- *
- * 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 <crypto/crypters/crypter.h>
-#include <crypto/signers/signer.h>
-#include <crypto/hashers/hasher.h>
-#include <crypto/prfs/prf.h>
-#include <credentials/keys/public_key.h>
-
-#include "ike_alg.h"
-
-extern bool init_crypto(void);
-extern void free_crypto(void);
-
-extern const struct dh_desc unset_group; /* magic signifier */
-
-/* unification of cryptographic encoding/decoding algorithms
- * The IV is taken from and returned to st->st_new_iv.
- * This allows the old IV to be retained.
- * Use update_iv to commit to the new IV (for example, once a packet has
- * been validated).
- */
-
-#define MAX_OAKLEY_KEY_LEN0 (3 * DES_CBC_BLOCK_SIZE)
-#define MAX_OAKLEY_KEY_LEN (256/BITS_PER_BYTE)
-
-struct state; /* forward declaration, dammit */
-
-#define update_iv(st) memcpy((st)->st_iv, (st)->st_new_iv \
- , (st)->st_iv_len = (st)->st_new_iv_len)
-
-#define set_ph1_iv(st, iv) \
- passert((st)->st_ph1_iv_len <= sizeof((st)->st_ph1_iv)); \
- memcpy((st)->st_ph1_iv, (iv), (st)->st_ph1_iv_len);
-
-/* unification of cryptographic hashing mechanisms */
-
-extern encryption_algorithm_t oakley_to_encryption_algorithm(int alg);
-extern hash_algorithm_t oakley_to_hash_algorithm(int alg);
-extern pseudo_random_function_t oakley_to_prf(int alg);
-extern signature_scheme_t oakley_to_signature_scheme(int method);
-extern int oakley_from_encryption_algorithm(encryption_algorithm_t alg);
-extern int oakley_from_integrity_algorithm(integrity_algorithm_t alg);
-extern int esp_from_encryption_algorithm(encryption_algorithm_t alg);
-extern int esp_from_integrity_algorithm(integrity_algorithm_t alg);
-extern encryption_algorithm_t encryption_algorithm_from_esp(int esp);
-extern integrity_algorithm_t integrity_algorithm_from_esp(int esp);
-
diff --git a/src/pluto/db_ops.c b/src/pluto/db_ops.c
deleted file mode 100644
index 547ea5f22..000000000
--- a/src/pluto/db_ops.c
+++ /dev/null
@@ -1,412 +0,0 @@
-/* Dynamic db (proposal, transforms, attributes) handling.
- * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
- *
- * 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.
- */
-
-/*
- * The stratedy is to have (full contained) struct db_prop in db_context
- * pointing to ONE dynamically sizable transform vector (trans0).
- * Each transform stores attrib. in ONE dyn. sizable attribute vector (attrs0)
- * in a "serialized" way (attributes storage is used in linear sequence for
- * subsecuent transforms).
- *
- * Resizing for both trans0 and attrs0 is supported:
- * - For trans0: quite simple, just allocate and copy trans. vector content
- * also update trans_cur (by offset)
- * - For attrs0: after allocating and copying attrs, I must rewrite each
- * trans->attrs present in trans0; to achieve this, calculate
- * attrs pointer offset (new minus old) and iterate over
- * each transform "adding" this difference.
- * also update attrs_cur (by offset)
- *
- * db_context structure:
- * +---------------------+
- * | prop |
- * | .protoid |
- * | .trans | --+
- * | .trans_cnt | |
- * +---------------------+ <-+
- * | trans0 | ----> { trans#1 | ... | trans#i | ... }
- * +---------------------+ ^
- * | trans_cur | ----------------------' current transf.
- * +---------------------+
- * | attrs0 | ----> { attr#1 | ... | attr#j | ... }
- * +---------------------+ ^
- * | attrs_cur | ---------------------' current attr.
- * +---------------------+
- * | max_trans,max_attrs | max_trans/attrs: number of elem. of each vector
- * +---------------------+
- *
- * See testing examples at end for interface usage.
- */
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <malloc.h>
-#include <sys/types.h>
-
-#include <freeswan.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "state.h"
-#include "packet.h"
-#include "spdb.h"
-#include "db_ops.h"
-#include "log.h"
-#include "whack.h"
-
-#include <assert.h>
-
-#ifdef NOT_YET
-/*
- * Allocator cache:
- * Because of the single-threaded nature of pluto/spdb.c,
- * alloc()/free() is exercised many times with very small
- * lifetime objects.
- * Just caching last object (currently it will select the
- * largest) will avoid this allocation mas^Wperturbations
- *
- */
-struct db_ops_alloc_cache {
- void *ptr;
- int size;
-};
-#endif
-
-#ifndef NO_DB_OPS_STATS
-/*
- * stats: do account for allocations
- * displayed in db_ops_show_status()
- */
-struct db_ops_stats {
- int st_curr_cnt; /* current number of allocations */
- int st_total_cnt; /* total allocations so far */
- size_t st_maxsz; /* max. size requested */
-};
-#define DB_OPS_ZERO { 0, 0, 0};
-#define DB_OPS_STATS_DESC "{curr_cnt, total_cnt, maxsz}"
-#define DB_OPS_STATS_STR(name) name "={%d,%d,%d} "
-#define DB_OPS_STATS_F(st) (st).st_curr_cnt, (st).st_total_cnt, (int)(st).st_maxsz
-static struct db_ops_stats db_context_st = DB_OPS_ZERO;
-static struct db_ops_stats db_trans_st = DB_OPS_ZERO;
-static struct db_ops_stats db_attrs_st = DB_OPS_ZERO;
-static __inline__ void *malloc_bytes_st(size_t size, struct db_ops_stats *st)
-{
- void *ptr = malloc(size);
- if (ptr)
- {
- st->st_curr_cnt++;
- st->st_total_cnt++;
- if (size > st->st_maxsz) st->st_maxsz=size;
- }
- return ptr;
-}
-#define ALLOC_BYTES_ST(z,st) malloc_bytes_st(z, &st);
-#define PFREE_ST(p,st) do { st.st_curr_cnt--; free(p); } while (0);
-
-#else
-
-#define ALLOC_BYTES_ST(z,n) malloc(z);
-#define PFREE_ST(p,n) free(p);
-
-#endif /* NO_DB_OPS_STATS */
-/* Initialize db object
- * max_trans and max_attrs can be 0, will be dynamically expanded
- * as a result of "add" operations
- */
-int
-db_prop_init(struct db_context *ctx, u_int8_t protoid, int max_trans, int max_attrs)
-{
- ctx->trans0 = NULL;
- ctx->attrs0 = NULL;
-
- if (max_trans > 0) { /* quite silly if not */
- ctx->trans0 = ALLOC_BYTES_ST ( sizeof(struct db_trans) * max_trans,
- db_trans_st);
- memset(ctx->trans0, '\0', sizeof(struct db_trans) * max_trans);
- }
-
- if (max_attrs > 0) { /* quite silly if not */
- ctx->attrs0 = ALLOC_BYTES_ST (sizeof(struct db_attr) * max_attrs,
- db_attrs_st);
- memset(ctx->attrs0, '\0', sizeof(struct db_attr) * max_attrs);
- }
-
- ctx->max_trans = max_trans;
- ctx->max_attrs = max_attrs;
- ctx->trans_cur = ctx->trans0;
- ctx->attrs_cur = ctx->attrs0;
- ctx->prop.protoid = protoid;
- ctx->prop.trans = ctx->trans0;
- ctx->prop.trans_cnt = 0;
- return 0;
-}
-
-/* Expand storage for transforms by number delta_trans */
-static int
-db_trans_expand(struct db_context *ctx, int delta_trans)
-{
- int ret = -1;
- struct db_trans *new_trans, *old_trans;
- int max_trans = ctx->max_trans + delta_trans;
- int offset;
-
- old_trans = ctx->trans0;
- new_trans = ALLOC_BYTES_ST ( sizeof (struct db_trans) * max_trans,
- db_trans_st);
- if (!new_trans)
- goto out;
- memcpy(new_trans, old_trans, ctx->max_trans * sizeof(struct db_trans));
-
- /* update trans0 (obviously) */
- ctx->trans0 = ctx->prop.trans = new_trans;
- /* update trans_cur (by offset) */
- offset = (char *)(new_trans) - (char *)(old_trans);
-
- {
- char *cctx = (char *)(ctx->trans_cur);
-
- cctx += offset;
- ctx->trans_cur = (struct db_trans *)cctx;
- }
- /* update elem count */
- ctx->max_trans = max_trans;
- PFREE_ST(old_trans, db_trans_st);
- ret = 0;
-out:
- return ret;
-}
-/*
- * Expand storage for attributes by delta_attrs number AND
- * rewrite trans->attr pointers
- */
-static int
-db_attrs_expand(struct db_context *ctx, int delta_attrs)
-{
- int ret = -1;
- struct db_attr *new_attrs, *old_attrs;
- struct db_trans *t;
- int ti;
- int max_attrs = ctx->max_attrs + delta_attrs;
- int offset;
-
- old_attrs = ctx->attrs0;
- new_attrs = ALLOC_BYTES_ST ( sizeof (struct db_attr) * max_attrs,
- db_attrs_st);
- if (!new_attrs)
- goto out;
-
- memcpy(new_attrs, old_attrs, ctx->max_attrs * sizeof(struct db_attr));
-
- /* update attrs0 and attrs_cur (obviously) */
- offset = (char *)(new_attrs) - (char *)(old_attrs);
-
- {
- char *actx = (char *)(ctx->attrs0);
-
- actx += offset;
- ctx->attrs0 = (struct db_attr *)actx;
-
- actx = (char *)ctx->attrs_cur;
- actx += offset;
- ctx->attrs_cur = (struct db_attr *)actx;
- }
-
- /* for each transform, rewrite attrs pointer by offsetting it */
- for (t=ctx->prop.trans, ti=0; ti < ctx->prop.trans_cnt; t++, ti++) {
- char *actx = (char *)(t->attrs);
-
- actx += offset;
- t->attrs = (struct db_attr *)actx;
- }
- /* update elem count */
- ctx->max_attrs = max_attrs;
- PFREE_ST(old_attrs, db_attrs_st);
- ret = 0;
-out:
- return ret;
-}
-/* Allocate a new db object */
-struct db_context *
-db_prop_new(u_int8_t protoid, int max_trans, int max_attrs)
-{
- struct db_context *ctx;
- ctx = ALLOC_BYTES_ST ( sizeof (struct db_context), db_context_st);
- if (!ctx) goto out;
-
- if (db_prop_init(ctx, protoid, max_trans, max_attrs) < 0) {
- PFREE_ST(ctx, db_context_st);
- ctx=NULL;
- }
-out:
- return ctx;
-}
-/* Free a db object */
-void
-db_destroy(struct db_context *ctx)
-{
- if (ctx->trans0) PFREE_ST(ctx->trans0, db_trans_st);
- if (ctx->attrs0) PFREE_ST(ctx->attrs0, db_attrs_st);
- PFREE_ST(ctx, db_context_st);
-}
-/* Start a new transform, expand trans0 is needed */
-int
-db_trans_add(struct db_context *ctx, u_int8_t transid)
-{
- /* skip incrementing current trans pointer the 1st time*/
- if (ctx->trans_cur && ctx->trans_cur->attr_cnt)
- ctx->trans_cur++;
- /*
- * Strategy: if more space is needed, expand by
- * <current_size>/2 + 1
- *
- * This happens to produce a "reasonable" sequence
- * after few allocations, eg.:
- * 0,1,2,4,8,13,20,31,47
- */
- if ((ctx->trans_cur - ctx->trans0) >= ctx->max_trans) {
- /* XXX:jjo if fails should shout and flag it */
- if (db_trans_expand(ctx, ctx->max_trans/2 + 1)<0)
- return -1;
- }
- ctx->trans_cur->transid = transid;
- ctx->trans_cur->attrs=ctx->attrs_cur;
- ctx->trans_cur->attr_cnt = 0;
- ctx->prop.trans_cnt++;
- return 0;
-}
-/* Add attr copy to current transform, expanding attrs0 if needed */
-int
-db_attr_add(struct db_context *ctx, const struct db_attr *a)
-{
- /*
- * Strategy: if more space is needed, expand by
- * <current_size>/2 + 1
- */
- if ((ctx->attrs_cur - ctx->attrs0) >= ctx->max_attrs) {
- /* XXX:jjo if fails should shout and flag it */
- if (db_attrs_expand(ctx, ctx->max_attrs/2 + 1) < 0)
- return -1;
- }
- *ctx->attrs_cur++=*a;
- ctx->trans_cur->attr_cnt++;
- return 0;
-}
-/* Add attr copy (by value) to current transform,
- * expanding attrs0 if needed, just calls db_attr_add().
- */
-int
-db_attr_add_values(struct db_context *ctx, u_int16_t type, u_int16_t val)
-{
- struct db_attr attr;
- attr.type = type;
- attr.val = val;
- return db_attr_add (ctx, &attr);
-}
-#ifndef NO_DB_OPS_STATS
-int
-db_ops_show_status(void)
-{
- whack_log(RC_COMMENT, "stats " __FILE__ ": "
- DB_OPS_STATS_DESC " :"
- DB_OPS_STATS_STR("context")
- DB_OPS_STATS_STR("trans")
- DB_OPS_STATS_STR("attrs"),
- DB_OPS_STATS_F(db_context_st),
- DB_OPS_STATS_F(db_trans_st),
- DB_OPS_STATS_F(db_attrs_st)
- );
- return 0;
-}
-#endif /* NO_DB_OPS_STATS */
-/*
- * From below to end just testing stuff ....
- */
-#ifdef TEST
-static void db_prop_print(struct db_prop *p)
-{
- struct db_trans *t;
- struct db_attr *a;
- int ti, ai;
- enum_names *n, *n_at, *n_av;
- printf("protoid=\"%s\"\n", enum_name(&protocol_names, p->protoid));
- for (ti=0, t=p->trans; ti< p->trans_cnt; ti++, t++) {
- switch( t->transid) {
- case PROTO_ISAKMP:
- n=&isakmp_transformid_names;break;
- case PROTO_IPSEC_ESP:
- n=&esp_transformid_names;break;
- default:
- continue;
- }
- printf(" transid=\"%s\"\n",
- enum_name(n, t->transid));
- for (ai=0, a=t->attrs; ai < t->attr_cnt; ai++, a++) {
- int i;
- switch( t->transid) {
- case PROTO_ISAKMP:
- n_at=&oakley_attr_names;
- i=a->type|ISAKMP_ATTR_AF_TV;
- n_av=oakley_attr_val_descs[(i)&ISAKMP_ATTR_RTYPE_MASK];
- break;
- case PROTO_IPSEC_ESP:
- n_at=&ipsec_attr_names;
- i=a->type|ISAKMP_ATTR_AF_TV;
- n_av=ipsec_attr_val_descs[(i)&ISAKMP_ATTR_RTYPE_MASK];
- break;
- default:
- continue;
- }
- printf(" type=\"%s\" value=\"%s\"\n",
- enum_name(n_at, i),
- enum_name(n_av, a->val));
- }
- }
-
-}
-static void db_print(struct db_context *ctx)
-{
- printf("trans_cur diff=%d, attrs_cur diff=%d\n",
- ctx->trans_cur - ctx->trans0,
- ctx->attrs_cur - ctx->attrs0);
- db_prop_print(&ctx->prop);
-}
-
-void
-passert_fail(const char *pred_str, const char *file_str, unsigned long line_no);
-void abort(void);
-void
-passert_fail(const char *pred_str, const char *file_str, unsigned long line_no)
-{
- fprintf(stderr, "ASSERTION FAILED at %s:%lu: %s", file_str, line_no, pred_str);
- abort(); /* exiting correctly doesn't always work */
-}
-int main(void) {
- struct db_context *ctx=db_prop_new(PROTO_ISAKMP, 0, 0);
- db_trans_add(ctx, KEY_IKE);
- db_attr_add_values(ctx, OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC);
- db_attr_add_values(ctx, OAKLEY_HASH_ALGORITHM, OAKLEY_MD5);
- db_attr_add_values(ctx, OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG);
- db_attr_add_values(ctx, OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024);
- db_trans_add(ctx, KEY_IKE);
- db_attr_add_values(ctx, OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_AES_CBC);
- db_attr_add_values(ctx, OAKLEY_HASH_ALGORITHM, OAKLEY_MD5);
- db_attr_add_values(ctx, OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY);
- db_attr_add_values(ctx, OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536);
- db_trans_add(ctx, ESP_3DES);
- db_attr_add_values(ctx, AUTH_ALGORITHM, AUTH_ALGORITHM_HMAC_SHA1);
- db_print(ctx);
- db_destroy(ctx);
- return 0;
-}
-#endif
diff --git a/src/pluto/db_ops.h b/src/pluto/db_ops.h
deleted file mode 100644
index 464c245dd..000000000
--- a/src/pluto/db_ops.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* Dynamic db (proposal, transforms, attributes) handling.
- * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
- *
- * 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.
- */
-
-#ifndef _DB_OPS_H
-#define _DB_OPS_H
-
-/*
- * Main db object, (quite proposal "oriented")
- */
-#ifndef NO_DB_CONTEXT
-struct db_context {
- struct db_prop prop; /* proposal buffer (not pointer) */
- struct db_trans *trans0; /* transf. list, dynamically sized */
- struct db_trans *trans_cur; /* current transform ptr */
- struct db_attr *attrs0; /* attr. list, dynamically sized */
- struct db_attr *attrs_cur; /* current attribute ptr */
- int max_trans; /* size of trans list */
- int max_attrs; /* size of attrs list */
-};
-/*
- * Allocate a new db object
- */
-struct db_context * db_prop_new(u_int8_t protoid, int max_trans, int max_attrs);
-/* Initialize object for proposal building */
-int db_prop_init(struct db_context *ctx, u_int8_t protoid, int max_trans, int max_attrs);
-/* Free all resourses for this db */
-void db_destroy(struct db_context *ctx);
-
-/* Start a new transform */
-int db_trans_add(struct db_context *ctx, u_int8_t transid);
-/* Add a new attribute by copying db_attr content */
-int db_attr_add(struct db_context *db_ctx, const struct db_attr *attr);
-/* Add a new attribute by value */
-int db_attr_add_values(struct db_context *ctx, u_int16_t type, u_int16_t val);
-
-/* Get proposal from db object */
-static __inline__ struct db_prop *db_prop_get(struct db_context *ctx) {
- return &ctx->prop;
-}
-/* Show stats (allocation, etc) */
-#endif /* NO_DB_CONTEXT */
-int db_ops_show_status(void);
-#endif /* _DB_OPS_H */
diff --git a/src/pluto/defs.c b/src/pluto/defs.c
deleted file mode 100644
index 7f3a819de..000000000
--- a/src/pluto/defs.c
+++ /dev/null
@@ -1,145 +0,0 @@
-/* misc. universal things
- * Copyright (C) 1998-2001 D. Hugh Redelmeier.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <dirent.h>
-#include <inttypes.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <freeswan.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "log.h"
-#include "whack.h" /* for RC_LOG_SERIOUS */
-
-bool
-all_zero(const unsigned char *m, size_t len)
-{
- size_t i;
-
- for (i = 0; i != len; i++)
- if (m[i] != '\0')
- return FALSE;
- return TRUE;
-}
-
-/* Note that there may be as many as six IDs that are temporary at
- * one time before unsharing the two ends of a connection. So we need
- * at least six temporary buffers for DER_ASN1_DN IDs.
- * We rotate them. Be careful!
- */
-#define MAX_BUF 10
-
-char*
-temporary_cyclic_buffer(void)
-{
- static char buf[MAX_BUF][BUF_LEN]; /* MAX_BUF internal buffers */
- static int counter = 0; /* cyclic counter */
-
- if (++counter == MAX_BUF) counter = 0; /* next internal buffer */
- return buf[counter]; /* assign temporary buffer */
-}
-
-/* concatenates two sub paths into a string with a maximum size of BUF_LEN
- * use for temporary storage only
- */
-char* concatenate_paths(char *a, char *b)
-{
- char *c;
-
- if (*b == '/' || *b == '.')
- return b;
-
- c = temporary_cyclic_buffer();
- snprintf(c, BUF_LEN, "%s/%s", a, b);
- return c;
-}
-
-/* moves a chunk to a memory position, chunk is freed afterwards
- * position pointer is advanced after the insertion point
- */
-void
-mv_chunk(u_char **pos, chunk_t content)
-{
- if (content.len > 0)
- {
- chunkcpy(*pos, content);
- free(content.ptr);
- }
-}
-
-/* checks if the expiration date has been reached and
- * warns during the warning_interval of the imminent
- * expiry. strict=TRUE declares a fatal error,
- * strict=FALSE issues a warning upon expiry.
- */
-const char*
-check_expiry(time_t expiration_date, int warning_interval, bool strict)
-{
- time_t now, time_left;
-
- if (expiration_date == UNDEFINED_TIME)
- return "ok (expires never)";
-
- /* determine the current time */
- time(&now);
-
- time_left = (expiration_date - now);
- if (time_left < 0)
- return strict? "fatal (expired)" : "warning (expired)";
-
- if (time_left > 86400*warning_interval)
- return "ok";
- {
- static char buf[35]; /* temporary storage */
- const char* unit = "second";
-
- if (time_left > 172800)
- {
- time_left /= 86400;
- unit = "day";
- }
- else if (time_left > 7200)
- {
- time_left /= 3600;
- unit = "hour";
- }
- else if (time_left > 120)
- {
- time_left /= 60;
- unit = "minute";
- }
- snprintf(buf, 35, "warning (expires in %" PRIu64 " %s%s)",
- (u_int64_t)time_left, unit, (time_left == 1) ? "" : "s");
- return buf;
- }
-}
-
-
-/*
- * Filter eliminating the directory entries '.' and '..'
- */
-int
-file_select(const struct dirent *entry)
-{
- return strcmp(entry->d_name, "." ) &&
- strcmp(entry->d_name, "..");
-}
-
-
diff --git a/src/pluto/defs.h b/src/pluto/defs.h
deleted file mode 100644
index 532652e5b..000000000
--- a/src/pluto/defs.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* misc. universal things
- * Copyright (C) 1997 Angelos D. Keromytis.
- * Copyright (C) 1998-2001 D. Hugh Redelmeier.
- *
- * 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.
- */
-
-#ifndef _DEFS_H
-#define _DEFS_H
-
-#include <string.h>
-#include <sys/types.h>
-
-#include <chunk.h>
-
-#ifdef DEBUG
-# define USED_BY_DEBUG /* ignore */
-#else
-# define USED_BY_DEBUG UNUSED
-#endif
-
-/* type of serial number of a state object
- * Needed in connections.h and state.h; here to simplify dependencies.
- */
-typedef unsigned long so_serial_t;
-#define SOS_NOBODY 0 /* null serial number */
-#define SOS_FIRST 1 /* first normal serial number */
-
-/* memory allocation */
-
-#define clone_thing(orig) clalloc((void *)&(orig), sizeof(orig))
-
-#define clone_str(str) \
- ((str) == NULL? NULL : strdup(str))
-
-#define replace(p, q) \
- { free(p); (p) = (q); }
-
-#define chunkcpy(dst, chunk) \
- { memcpy(dst, chunk.ptr, chunk.len); dst += chunk.len;}
-
-extern char* temporary_cyclic_buffer(void);
-extern char* concatenate_paths(char *a, char *b);
-
-/* move a chunk to a memory position and free it after insertion */
-extern void mv_chunk(u_char **pos, chunk_t content);
-
-/* warns a predefined interval before expiry */
-extern const char* check_expiry(time_t expiration_date,
- int warning_interval, bool strict);
-
-#define MAX_PROMPT_PASS_TRIALS 5
-#define PROMPT_PASS_LEN 64
-
-/* filter eliminating the directory entries '.' and '..' */
-typedef struct dirent dirent_t;
-extern int file_select(const dirent_t *entry);
-
-/* cleanly exit Pluto */
-extern void exit_pluto(int /*status*/) NEVER_RETURNS;
-
-/* zero all bytes */
-#define zero(x) memset((x), '\0', sizeof(*(x)))
-
-/* are all bytes 0? */
-extern bool all_zero(const unsigned char *m, size_t len);
-
-/* pad_up(n, m) is the amount to add to n to make it a multiple of m */
-#define pad_up(n, m) (((m) - 1) - (((n) + (m) - 1) % (m)))
-
-#endif /* _DEFS_H */
diff --git a/src/pluto/demux.c b/src/pluto/demux.c
deleted file mode 100644
index 612e0813c..000000000
--- a/src/pluto/demux.c
+++ /dev/null
@@ -1,2527 +0,0 @@
-/* demultiplex incoming IKE messages
- * Copyright (C) 1997 Angelos D. Keromytis.
- * Copyright (C) 1998-2002 D. Hugh Redelmeier.
- *
- * 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.
- */
-
-/* Ordering Constraints on Payloads
- *
- * rfc2409: The Internet Key Exchange (IKE)
- *
- * 5 Exchanges:
- * "The SA payload MUST precede all other payloads in a phase 1 exchange."
- *
- * "Except where otherwise noted, there are no requirements for ISAKMP
- * payloads in any message to be in any particular order."
- *
- * 5.3 Phase 1 Authenticated With a Revised Mode of Public Key Encryption:
- *
- * "If the HASH payload is sent it MUST be the first payload of the
- * second message exchange and MUST be followed by the encrypted
- * nonce. If the HASH payload is not sent, the first payload of the
- * second message exchange MUST be the encrypted nonce."
- *
- * "Save the requirements on the location of the optional HASH payload
- * and the mandatory nonce payload there are no further payload
- * requirements. All payloads-- in whatever order-- following the
- * encrypted nonce MUST be encrypted with Ke_i or Ke_r depending on the
- * direction."
- *
- * 5.5 Phase 2 - Quick Mode
- *
- * "In Quick Mode, a HASH payload MUST immediately follow the ISAKMP
- * header and a SA payload MUST immediately follow the HASH."
- * [NOTE: there may be more than one SA payload, so this is not
- * totally reasonable. Probably all SAs should be so constrained.]
- *
- * "If ISAKMP is acting as a client negotiator on behalf of another
- * party, the identities of the parties MUST be passed as IDci and
- * then IDcr."
- *
- * "With the exception of the HASH, SA, and the optional ID payloads,
- * there are no payload ordering restrictions on Quick Mode."
- */
-
-/* Unfolding of Identity -- a central mystery
- *
- * This concerns Phase 1 identities, those of the IKE hosts.
- * These are the only ones that are authenticated. Phase 2
- * identities are for IPsec SAs.
- *
- * There are three case of interest:
- *
- * (1) We initiate, based on a whack command specifying a Connection.
- * We know the identity of the peer from the Connection.
- *
- * (2) (to be implemented) we initiate based on a flow from our client
- * to some IP address.
- * We immediately know one of the peer's client IP addresses from
- * the flow. We must use this to figure out the peer's IP address
- * and Id. To be solved.
- *
- * (3) We respond to an IKE negotiation.
- * We immediately know the peer's IP address.
- * We get an ID Payload in Main I2.
- *
- * Unfortunately, this is too late for a number of things:
- * - the ISAKMP SA proposals have already been made (Main I1)
- * AND one accepted (Main R1)
- * - the SA includes a specification of the type of ID
- * authentication so this is negotiated without being told the ID.
- * - with Preshared Key authentication, Main I2 is encrypted
- * using the key, so it cannot be decoded to reveal the ID
- * without knowing (or guessing) which key to use.
- *
- * There are three reasonable choices here for the responder:
- * + assume that the initiator is making wise offers since it
- * knows the IDs involved. We can balk later (but not gracefully)
- * when we find the actual initiator ID
- * + attempt to infer identity by IP address. Again, we can balk
- * when the true identity is revealed. Actually, it is enough
- * to infer properties of the identity (eg. SA properties and
- * PSK, if needed).
- * + make all properties universal so discrimination based on
- * identity isn't required. For example, always accept the same
- * kinds of encryption. Accept Public Key Id authentication
- * since the Initiator presumably has our public key and thinks
- * we must have / can find his. This approach is weakest
- * for preshared key since the actual key must be known to
- * decrypt the Initiator's ID Payload.
- * These choices can be blended. For example, a class of Identities
- * can be inferred, sufficient to select a preshared key but not
- * sufficient to infer a unique identity.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/time.h> /* only used for belt-and-suspenders select call */
-#include <sys/poll.h> /* only used for forensic poll call */
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/queue.h>
-
-#if defined(IP_RECVERR) && defined(MSG_ERRQUEUE)
-# include <asm/types.h> /* for __u8, __u32 */
-# include <linux/errqueue.h>
-# include <sys/uio.h> /* struct iovec */
-#endif
-
-#include <freeswan.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "cookie.h"
-#include "connections.h"
-#include "state.h"
-#include "packet.h"
-#include "crypto.h"
-#include "ike_alg.h"
-#include "log.h"
-#include "demux.h" /* needs packet.h */
-#include "ipsec_doi.h" /* needs demux.h and state.h */
-#include "timer.h"
-#include "whack.h" /* requires connections.h */
-#include "server.h"
-#include "nat_traversal.h"
-#include "vendor.h"
-#include "modecfg.h"
-
-/* This file does basic header checking and demux of
- * incoming packets.
- */
-
-/* forward declarations */
-static bool read_packet(struct msg_digest *md);
-static void process_packet(struct msg_digest **mdp);
-
-/* Reply messages are built in this buffer.
- * Only one state transition function can be using it at a time
- * so suspended STFs must save and restore it.
- * It could be an auto variable of complete_state_transition except for the fact
- * that when a suspended STF resumes, its reply message buffer
- * must be at the same location -- there are pointers into it.
- */
-u_int8_t reply_buffer[MAX_OUTPUT_UDP_SIZE];
-
-/* state_microcode is a tuple of information parameterizing certain
- * centralized processing of a packet. For example, it roughly
- * specifies what payloads are expected in this message.
- * The microcode is selected primarily based on the state.
- * In Phase 1, the payload structure often depends on the
- * authentication technique, so that too plays a part in selecting
- * the state_microcode to use.
- */
-
-struct state_microcode {
- enum state_kind state, next_state;
- lset_t flags;
- lset_t req_payloads; /* required payloads (allows just one) */
- lset_t opt_payloads; /* optional payloads (any mumber) */
- /* if not ISAKMP_NEXT_NONE, process_packet will emit HDR with this as np */
- u_int8_t first_out_payload;
- enum event_type timeout_event;
- state_transition_fn *processor;
-};
-
-/* State Microcode Flags, in several groups */
-
-/* Oakley Auth values: to which auth values does this entry apply?
- * Most entries will use SMF_ALL_AUTH because they apply to all.
- * Note: SMF_ALL_AUTH matches 0 for those circumstances when no auth
- * has been set.
- */
-#define SMF_ALL_AUTH LRANGE(0, OAKLEY_AUTH_ROOF-1)
-#define SMF_PSK_AUTH LELEM(OAKLEY_PRESHARED_KEY)
-#define SMF_DS_AUTH (LELEM(OAKLEY_DSS_SIG) | LELEM(OAKLEY_RSA_SIG) | \
- LELEM(OAKLEY_ECDSA_SIG) | LELEM(OAKLEY_ECDSA_256) | \
- LELEM(OAKLEY_ECDSA_384) | LELEM(OAKLEY_ECDSA_521))
-#define SMF_PKE_AUTH (LELEM(OAKLEY_RSA_ENC) | LELEM(OAKLEY_ELGAMAL_ENC))
-#define SMF_RPKE_AUTH (LELEM(OAKLEY_RSA_ENC_REV) | LELEM(OAKLEY_ELGAMAL_ENC_REV))
-
-/* misc flags */
-
-#define SMF_INITIATOR LELEM(OAKLEY_AUTH_ROOF + 0)
-#define SMF_FIRST_ENCRYPTED_INPUT LELEM(OAKLEY_AUTH_ROOF + 1)
-#define SMF_INPUT_ENCRYPTED LELEM(OAKLEY_AUTH_ROOF + 2)
-#define SMF_OUTPUT_ENCRYPTED LELEM(OAKLEY_AUTH_ROOF + 3)
-#define SMF_RETRANSMIT_ON_DUPLICATE LELEM(OAKLEY_AUTH_ROOF + 4)
-
-#define SMF_ENCRYPTED (SMF_INPUT_ENCRYPTED | SMF_OUTPUT_ENCRYPTED)
-
-/* this state generates a reply message */
-#define SMF_REPLY LELEM(OAKLEY_AUTH_ROOF + 5)
-
-/* this state completes P1, so any pending P2 negotiations should start */
-#define SMF_RELEASE_PENDING_P2 LELEM(OAKLEY_AUTH_ROOF + 6)
-
-/* end of flags */
-
-
-static state_transition_fn /* forward declaration */
- unexpected,
- informational;
-
-/* state_microcode_table is a table of all state_microcode tuples.
- * It must be in order of state (the first element).
- * After initialization, ike_microcode_index[s] points to the
- * first entry in state_microcode_table for state s.
- * Remember that each state name in Main or Quick Mode describes
- * what has happened in the past, not what this message is.
- */
-
-static const struct state_microcode
- *ike_microcode_index[STATE_IKE_ROOF - STATE_IKE_FLOOR];
-
-static const struct state_microcode state_microcode_table[] = {
-#define PT(n) ISAKMP_NEXT_##n
-#define P(n) LELEM(PT(n))
-
- /***** Phase 1 Main Mode *****/
-
- /* No state for main_outI1: --> HDR, SA */
-
- /* STATE_MAIN_R0: I1 --> R1
- * HDR, SA --> HDR, SA
- */
- { STATE_MAIN_R0, STATE_MAIN_R1
- , SMF_ALL_AUTH | SMF_REPLY
- , P(SA), P(VID) | P(CR), PT(NONE)
- , EVENT_RETRANSMIT, main_inI1_outR1},
-
- /* STATE_MAIN_I1: R1 --> I2
- * HDR, SA --> auth dependent
- * SMF_PSK_AUTH, SMF_DS_AUTH: --> HDR, KE, Ni
- * SMF_PKE_AUTH:
- * --> HDR, KE, [ HASH(1), ] <IDi1_b>PubKey_r, <Ni_b>PubKey_r
- * SMF_RPKE_AUTH:
- * --> HDR, [ HASH(1), ] <Ni_b>Pubkey_r, <KE_b>Ke_i, <IDi1_b>Ke_i [,<<Cert-I_b>Ke_i]
- * Note: since we don't know auth at start, we cannot differentiate
- * microcode entries based on it.
- */
- { STATE_MAIN_I1, STATE_MAIN_I2
- , SMF_ALL_AUTH | SMF_INITIATOR | SMF_REPLY
- , P(SA), P(VID) | P(CR), PT(NONE) /* don't know yet */
- , EVENT_RETRANSMIT, main_inR1_outI2 },
-
- /* STATE_MAIN_R1: I2 --> R2
- * SMF_PSK_AUTH, SMF_DS_AUTH: HDR, KE, Ni --> HDR, KE, Nr
- * SMF_PKE_AUTH: HDR, KE, [ HASH(1), ] <IDi1_b>PubKey_r, <Ni_b>PubKey_r
- * --> HDR, KE, <IDr1_b>PubKey_i, <Nr_b>PubKey_i
- * SMF_RPKE_AUTH:
- * HDR, [ HASH(1), ] <Ni_b>Pubkey_r, <KE_b>Ke_i, <IDi1_b>Ke_i [,<<Cert-I_b>Ke_i]
- * --> HDR, <Nr_b>PubKey_i, <KE_b>Ke_r, <IDr1_b>Ke_r
- */
- { STATE_MAIN_R1, STATE_MAIN_R2
- , SMF_PSK_AUTH | SMF_DS_AUTH | SMF_REPLY
- , P(KE) | P(NONCE), P(VID) | P(CR) | P(NATD_RFC), PT(KE)
- , EVENT_RETRANSMIT, main_inI2_outR2 },
-
- { STATE_MAIN_R1, STATE_UNDEFINED
- , SMF_PKE_AUTH | SMF_REPLY
- , P(KE) | P(ID) | P(NONCE), P(VID) | P(CR) | P(HASH), PT(KE)
- , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ },
-
- { STATE_MAIN_R1, STATE_UNDEFINED
- , SMF_RPKE_AUTH | SMF_REPLY
- , P(NONCE) | P(KE) | P(ID), P(VID) | P(CR) | P(HASH) | P(CERT), PT(NONCE)
- , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ },
-
- /* for states from here on, output message must be encrypted */
-
- /* STATE_MAIN_I2: R2 --> I3
- * SMF_PSK_AUTH: HDR, KE, Nr --> HDR*, IDi1, HASH_I
- * SMF_DS_AUTH: HDR, KE, Nr --> HDR*, IDi1, [ CERT, ] SIG_I
- * SMF_PKE_AUTH: HDR, KE, <IDr1_b>PubKey_i, <Nr_b>PubKey_i
- * --> HDR*, HASH_I
- * SMF_RPKE_AUTH: HDR, <Nr_b>PubKey_i, <KE_b>Ke_r, <IDr1_b>Ke_r
- * --> HDR*, HASH_I
- */
- { STATE_MAIN_I2, STATE_MAIN_I3
- , SMF_PSK_AUTH | SMF_DS_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED | SMF_REPLY
- , P(KE) | P(NONCE), P(VID) | P(CR) | P(NATD_RFC), PT(ID)
- , EVENT_RETRANSMIT, main_inR2_outI3 },
-
- { STATE_MAIN_I2, STATE_UNDEFINED
- , SMF_PKE_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED | SMF_REPLY
- , P(KE) | P(ID) | P(NONCE), P(VID) | P(CR), PT(HASH)
- , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ },
-
- { STATE_MAIN_I2, STATE_UNDEFINED
- , SMF_ALL_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED | SMF_REPLY
- , P(NONCE) | P(KE) | P(ID), P(VID) | P(CR), PT(HASH)
- , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ },
-
- /* for states from here on, input message must be encrypted */
-
- /* STATE_MAIN_R2: I3 --> R3
- * SMF_PSK_AUTH: HDR*, IDi1, HASH_I --> HDR*, IDr1, HASH_R
- * SMF_DS_AUTH: HDR*, IDi1, [ CERT, ] SIG_I --> HDR*, IDr1, [ CERT, ] SIG_R
- * SMF_PKE_AUTH, SMF_RPKE_AUTH: HDR*, HASH_I --> HDR*, HASH_R
- */
- { STATE_MAIN_R2, STATE_MAIN_R3
- , SMF_PSK_AUTH | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED
- | SMF_REPLY | SMF_RELEASE_PENDING_P2
- , P(ID) | P(HASH), P(VID) | P(CR), PT(NONE)
- , EVENT_SA_REPLACE, main_inI3_outR3 },
-
- { STATE_MAIN_R2, STATE_MAIN_R3
- , SMF_DS_AUTH | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED
- | SMF_REPLY | SMF_RELEASE_PENDING_P2
- , P(ID) | P(SIG), P(VID) | P(CR) | P(CERT), PT(NONE)
- , EVENT_SA_REPLACE, main_inI3_outR3 },
-
- { STATE_MAIN_R2, STATE_UNDEFINED
- , SMF_PKE_AUTH | SMF_RPKE_AUTH | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED
- | SMF_REPLY | SMF_RELEASE_PENDING_P2
- , P(HASH), P(VID) | P(CR), PT(NONE)
- , EVENT_SA_REPLACE, unexpected /* ??? not yet implemented */ },
-
- /* STATE_MAIN_I3: R3 --> done
- * SMF_PSK_AUTH: HDR*, IDr1, HASH_R --> done
- * SMF_DS_AUTH: HDR*, IDr1, [ CERT, ] SIG_R --> done
- * SMF_PKE_AUTH, SMF_RPKE_AUTH: HDR*, HASH_R --> done
- * May initiate quick mode by calling quick_outI1
- */
- { STATE_MAIN_I3, STATE_MAIN_I4
- , SMF_PSK_AUTH | SMF_INITIATOR
- | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2
- , P(ID) | P(HASH), P(VID) | P(CR), PT(NONE)
- , EVENT_SA_REPLACE, main_inR3 },
-
- { STATE_MAIN_I3, STATE_MAIN_I4
- , SMF_DS_AUTH | SMF_INITIATOR
- | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2
- , P(ID) | P(SIG), P(VID) | P(CR) | P(CERT), PT(NONE)
- , EVENT_SA_REPLACE, main_inR3 },
-
- { STATE_MAIN_I3, STATE_UNDEFINED
- , SMF_PKE_AUTH | SMF_RPKE_AUTH | SMF_INITIATOR
- | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2
- , P(HASH), P(VID) | P(CR), PT(NONE)
- , EVENT_SA_REPLACE, unexpected /* ??? not yet implemented */ },
-
- /* STATE_MAIN_R3: can only get here due to packet loss */
- { STATE_MAIN_R3, STATE_UNDEFINED
- , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RETRANSMIT_ON_DUPLICATE
- , LEMPTY, LEMPTY
- , PT(NONE), EVENT_NULL, unexpected },
-
- /* STATE_MAIN_I4: can only get here due to packet loss */
- { STATE_MAIN_I4, STATE_UNDEFINED
- , SMF_ALL_AUTH | SMF_INITIATOR | SMF_ENCRYPTED
- , LEMPTY, LEMPTY
- , PT(NONE), EVENT_NULL, unexpected },
-
-
- /***** Phase 2 Quick Mode *****/
-
- /* No state for quick_outI1:
- * --> HDR*, HASH(1), SA, Nr [, KE ] [, IDci, IDcr ]
- */
-
- /* STATE_QUICK_R0:
- * HDR*, HASH(1), SA, Ni [, KE ] [, IDci, IDcr ] -->
- * HDR*, HASH(2), SA, Nr [, KE ] [, IDci, IDcr ]
- * Installs inbound IPsec SAs.
- * Because it may suspend for asynchronous DNS, first_out_payload
- * is set to NONE to suppress early emission of HDR*.
- * ??? it is legal to have multiple SAs, but we don't support it yet.
- */
- { STATE_QUICK_R0, STATE_QUICK_R1
- , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY
- , P(HASH) | P(SA) | P(NONCE), /* P(SA) | */ P(KE) | P(ID) | P(NATOA_RFC), PT(NONE)
- , EVENT_RETRANSMIT, quick_inI1_outR1 },
-
- /* STATE_QUICK_I1:
- * HDR*, HASH(2), SA, Nr [, KE ] [, IDci, IDcr ] -->
- * HDR*, HASH(3)
- * Installs inbound and outbound IPsec SAs, routing, etc.
- * ??? it is legal to have multiple SAs, but we don't support it yet.
- */
- { STATE_QUICK_I1, STATE_QUICK_I2
- , SMF_ALL_AUTH | SMF_INITIATOR | SMF_ENCRYPTED | SMF_REPLY
- , P(HASH) | P(SA) | P(NONCE), /* P(SA) | */ P(KE) | P(ID) | P(NATOA_RFC), PT(HASH)
- , EVENT_SA_REPLACE, quick_inR1_outI2 },
-
- /* STATE_QUICK_R1: HDR*, HASH(3) --> done
- * Installs outbound IPsec SAs, routing, etc.
- */
- { STATE_QUICK_R1, STATE_QUICK_R2
- , SMF_ALL_AUTH | SMF_ENCRYPTED
- , P(HASH), LEMPTY, PT(NONE)
- , EVENT_SA_REPLACE, quick_inI2 },
-
- /* STATE_QUICK_I2: can only happen due to lost packet */
- { STATE_QUICK_I2, STATE_UNDEFINED
- , SMF_ALL_AUTH | SMF_INITIATOR | SMF_ENCRYPTED | SMF_RETRANSMIT_ON_DUPLICATE
- , LEMPTY, LEMPTY, PT(NONE)
- , EVENT_NULL, unexpected },
-
- /* STATE_QUICK_R2: can only happen due to lost packet */
- { STATE_QUICK_R2, STATE_UNDEFINED
- , SMF_ALL_AUTH | SMF_ENCRYPTED
- , LEMPTY, LEMPTY, PT(NONE)
- , EVENT_NULL, unexpected },
-
-
- /***** informational messages *****/
-
- /* STATE_INFO: */
- { STATE_INFO, STATE_UNDEFINED
- , SMF_ALL_AUTH
- , LEMPTY, LEMPTY, PT(NONE)
- , EVENT_NULL, informational },
-
- /* STATE_INFO_PROTECTED: */
- { STATE_INFO_PROTECTED, STATE_UNDEFINED
- , SMF_ALL_AUTH | SMF_ENCRYPTED
- , P(HASH), LEMPTY, PT(NONE)
- , EVENT_NULL, informational },
-
- /* XAUTH state transitions */
- { STATE_XAUTH_I0, STATE_XAUTH_I1
- , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY
- , P(ATTR) | P(HASH), P(VID), PT(HASH)
- , EVENT_RETRANSMIT, xauth_inI0 },
-
- { STATE_XAUTH_R1, STATE_XAUTH_R2
- , SMF_ALL_AUTH | SMF_ENCRYPTED
- , P(ATTR) | P(HASH), P(VID), PT(HASH)
- , EVENT_RETRANSMIT, xauth_inR1 },
-
- { STATE_XAUTH_I1, STATE_XAUTH_I2
- , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2
- , P(ATTR) | P(HASH), P(VID), PT(HASH)
- , EVENT_SA_REPLACE, xauth_inI1 },
-
- { STATE_XAUTH_R2, STATE_XAUTH_R3
- , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2
- , P(ATTR) | P(HASH), P(VID), PT(NONE)
- , EVENT_SA_REPLACE, xauth_inR2 },
-
- { STATE_XAUTH_I2, STATE_UNDEFINED
- , SMF_ALL_AUTH | SMF_ENCRYPTED
- , LEMPTY, LEMPTY, PT(NONE)
- , EVENT_NULL, unexpected },
-
- { STATE_XAUTH_R3, STATE_UNDEFINED
- , SMF_ALL_AUTH | SMF_ENCRYPTED
- , LEMPTY, LEMPTY, PT(NONE)
- , EVENT_NULL, unexpected },
-
- /* ModeCfg pull mode state transitions */
-
- { STATE_MODE_CFG_R0, STATE_MODE_CFG_R1
- , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2
- , P(ATTR) | P(HASH), P(VID), PT(HASH)
- , EVENT_SA_REPLACE, modecfg_inR0 },
-
- { STATE_MODE_CFG_I1, STATE_MODE_CFG_I2
- , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2
- , P(ATTR) | P(HASH), P(VID), PT(HASH)
- , EVENT_SA_REPLACE, modecfg_inI1 },
-
- { STATE_MODE_CFG_R1, STATE_UNDEFINED
- , SMF_ALL_AUTH | SMF_ENCRYPTED
- , LEMPTY, LEMPTY, PT(NONE)
- , EVENT_NULL, unexpected },
-
- { STATE_MODE_CFG_I2, STATE_UNDEFINED
- , SMF_ALL_AUTH | SMF_ENCRYPTED
- , LEMPTY, LEMPTY, PT(NONE)
- , EVENT_NULL, unexpected },
-
- /* ModeCfg push mode state transitions */
-
- { STATE_MODE_CFG_I0, STATE_MODE_CFG_I3
- , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2
- , P(ATTR) | P(HASH), P(VID), PT(HASH)
- , EVENT_SA_REPLACE, modecfg_inI0 },
-
- { STATE_MODE_CFG_R3, STATE_MODE_CFG_R4
- , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2
- , P(ATTR) | P(HASH), P(VID), PT(HASH)
- , EVENT_SA_REPLACE, modecfg_inR3 },
-
- { STATE_MODE_CFG_I3, STATE_UNDEFINED
- , SMF_ALL_AUTH | SMF_ENCRYPTED
- , LEMPTY, LEMPTY, PT(NONE)
- , EVENT_NULL, unexpected },
-
- { STATE_MODE_CFG_R4, STATE_UNDEFINED
- , SMF_ALL_AUTH | SMF_ENCRYPTED
- , LEMPTY, LEMPTY, PT(NONE)
- , EVENT_NULL, unexpected },
-
-#undef P
-#undef PT
-};
-
-void
-init_demux(void)
-{
- /* fill ike_microcode_index:
- * make ike_microcode_index[s] point to first entry in
- * state_microcode_table for state s (backward scan makes this easier).
- * Check that table is in order -- catch coding errors.
- * For what it's worth, this routine is idempotent.
- */
- const struct state_microcode *t;
-
- for (t = &state_microcode_table[countof(state_microcode_table) - 1];;)
- {
- passert(STATE_IKE_FLOOR <= t->state && t->state < STATE_IKE_ROOF);
- ike_microcode_index[t->state - STATE_IKE_FLOOR] = t;
- if (t == state_microcode_table)
- break;
- t--;
- passert(t[0].state <= t[1].state);
- }
-}
-
-/* Process any message on the MSG_ERRQUEUE
- *
- * This information is generated because of the IP_RECVERR socket option.
- * The API is sparsely documented, and may be LINUX-only, and only on
- * fairly recent versions at that (hence the conditional compilation).
- *
- * - ip(7) describes IP_RECVERR
- * - recvmsg(2) describes MSG_ERRQUEUE
- * - readv(2) describes iovec
- * - cmsg(3) describes how to process auxiliary messages
- *
- * ??? we should link this message with one we've sent
- * so that the diagnostic can refer to that negotiation.
- *
- * ??? how long can the messge be?
- *
- * ??? poll(2) has a very incomplete description of the POLL* events.
- * We assume that POLLIN, POLLOUT, and POLLERR are all we need to deal with
- * and that POLLERR will be on iff there is a MSG_ERRQUEUE message.
- *
- * We have to code around a couple of surprises:
- *
- * - Select can say that a socket is ready to read from, and
- * yet a read will hang. It turns out that a message available on the
- * MSG_ERRQUEUE will cause select to say something is pending, but
- * a normal read will hang. poll(2) can tell when a MSG_ERRQUEUE
- * message is pending.
- *
- * This is dealt with by calling check_msg_errqueue after select
- * has indicated that there is something to read, but before the
- * read is performed. check_msg_errqueue will return TRUE if there
- * is something left to read.
- *
- * - A write to a socket may fail because there is a pending MSG_ERRQUEUE
- * message, without there being anything wrong with the write. This
- * makes for confusing diagnostics.
- *
- * To avoid this, we call check_msg_errqueue before a write. True,
- * there is a race condition (a MSG_ERRQUEUE message might arrive
- * between the check and the write), but we should eliminate many
- * of the problematic events. To narrow the window, the poll(2)
- * will await until an event happens (in the case or a write,
- * POLLOUT; this should be benign for POLLIN).
- */
-
-#if defined(IP_RECVERR) && defined(MSG_ERRQUEUE)
-static bool
-check_msg_errqueue(const struct iface *ifp, short interest)
-{
- struct pollfd pfd;
-
- pfd.fd = ifp->fd;
- pfd.events = interest | POLLPRI | POLLOUT;
-
- while (pfd.revents = 0
- , poll(&pfd, 1, -1) > 0 && (pfd.revents & POLLERR))
- {
- u_int8_t buffer[3000]; /* hope that this is big enough */
- union
- {
- struct sockaddr sa;
- struct sockaddr_in sa_in4;
- struct sockaddr_in6 sa_in6;
- } from;
-
- int from_len = sizeof(from);
-
- int packet_len;
-
- struct msghdr emh;
- struct iovec eiov;
- union {
- /* force alignment (not documented as necessary) */
- struct cmsghdr ecms;
-
- /* how much space is enough? */
- unsigned char space[256];
- } ecms_buf;
-
- struct cmsghdr *cm;
- char fromstr[sizeof(" for message to port 65536") + INET6_ADDRSTRLEN];
- struct state *sender = NULL;
-
- zero(&from.sa);
- from_len = sizeof(from);
-
- emh.msg_name = &from.sa; /* ??? filled in? */
- emh.msg_namelen = sizeof(from);
- emh.msg_iov = &eiov;
- emh.msg_iovlen = 1;
- emh.msg_control = &ecms_buf;
- emh.msg_controllen = sizeof(ecms_buf);
- emh.msg_flags = 0;
-
- eiov.iov_base = buffer; /* see readv(2) */
- eiov.iov_len = sizeof(buffer);
-
- packet_len = recvmsg(ifp->fd, &emh, MSG_ERRQUEUE);
-
- if (packet_len == -1)
- {
- log_errno((e, "recvmsg(,, MSG_ERRQUEUE) on %s failed in comm_handle"
- , ifp->rname));
- break;
- }
- else if (packet_len == sizeof(buffer))
- {
- plog("MSG_ERRQUEUE message longer than %lu bytes; truncated"
- , (unsigned long) sizeof(buffer));
- }
- else
- {
- sender = find_sender((size_t) packet_len, buffer);
- }
-
- DBG_cond_dump(DBG_ALL, "rejected packet:\n", buffer, packet_len);
- DBG_cond_dump(DBG_ALL, "control:\n", emh.msg_control, emh.msg_controllen);
- /* ??? Andi Kleen <ak@suse.de> and misc documentation
- * suggests that name will have the original destination
- * of the packet. We seem to see msg_namelen == 0.
- * Andi says that this is a kernel bug and has fixed it.
- * Perhaps in 2.2.18/2.4.0.
- */
- passert(emh.msg_name == &from.sa);
- DBG_cond_dump(DBG_ALL, "name:\n", emh.msg_name
- , emh.msg_namelen);
-
- fromstr[0] = '\0'; /* usual case :-( */
- switch (from.sa.sa_family)
- {
- char as[INET6_ADDRSTRLEN];
-
- case AF_INET:
- if (emh.msg_namelen == sizeof(struct sockaddr_in))
- snprintf(fromstr, sizeof(fromstr)
- , " for message to %s port %u"
- , inet_ntop(from.sa.sa_family
- , &from.sa_in4.sin_addr, as, sizeof(as))
- , ntohs(from.sa_in4.sin_port));
- break;
- case AF_INET6:
- if (emh.msg_namelen == sizeof(struct sockaddr_in6))
- snprintf(fromstr, sizeof(fromstr)
- , " for message to %s port %u"
- , inet_ntop(from.sa.sa_family
- , &from.sa_in6.sin6_addr, as, sizeof(as))
- , ntohs(from.sa_in6.sin6_port));
- break;
- }
-
- for (cm = CMSG_FIRSTHDR(&emh)
- ; cm != NULL
- ; cm = CMSG_NXTHDR(&emh,cm))
- {
- if (cm->cmsg_level == SOL_IP
- && cm->cmsg_type == IP_RECVERR)
- {
- /* ip(7) and recvmsg(2) specify:
- * ee_origin is SO_EE_ORIGIN_ICMP for ICMP
- * or SO_EE_ORIGIN_LOCAL for locally generated errors.
- * ee_type and ee_code are from the ICMP header.
- * ee_info is the discovered MTU for EMSGSIZE errors
- * ee_data is not used.
- *
- * ??? recvmsg(2) says "SOCK_EE_OFFENDER" but
- * means "SO_EE_OFFENDER". The OFFENDER is really
- * the router that complained. As such, the port
- * is meaningless.
- */
-
- /* ??? cmsg(3) claims that CMSG_DATA returns
- * void *, but RFC 2292 and /usr/include/bits/socket.h
- * say unsigned char *. The manual is being fixed.
- */
- struct sock_extended_err *ee = (void *)CMSG_DATA(cm);
- const char *offstr = "unspecified";
- char offstrspace[INET6_ADDRSTRLEN];
- char orname[50];
-
- if (cm->cmsg_len > CMSG_LEN(sizeof(struct sock_extended_err)))
- {
- const struct sockaddr *offender = SO_EE_OFFENDER(ee);
-
- switch (offender->sa_family)
- {
- case AF_INET:
- offstr = inet_ntop(offender->sa_family
- , &((const struct sockaddr_in *)offender)->sin_addr
- , offstrspace, sizeof(offstrspace));
- break;
- case AF_INET6:
- offstr = inet_ntop(offender->sa_family
- , &((const struct sockaddr_in6 *)offender)->sin6_addr
- , offstrspace, sizeof(offstrspace));
- break;
- default:
- offstr = "unknown";
- break;
- }
- }
-
- switch (ee->ee_origin)
- {
- case SO_EE_ORIGIN_NONE:
- snprintf(orname, sizeof(orname), "none");
- break;
- case SO_EE_ORIGIN_LOCAL:
- snprintf(orname, sizeof(orname), "local");
- break;
- case SO_EE_ORIGIN_ICMP:
- snprintf(orname, sizeof(orname)
- , "ICMP type %d code %d (not authenticated)"
- , ee->ee_type, ee->ee_code
- );
- break;
- case SO_EE_ORIGIN_ICMP6:
- snprintf(orname, sizeof(orname)
- , "ICMP6 type %d code %d (not authenticated)"
- , ee->ee_type, ee->ee_code
- );
- break;
- default:
- snprintf(orname, sizeof(orname), "invalid origin %lu"
- , (unsigned long) ee->ee_origin);
- break;
- }
-
- {
- struct state *old_state = cur_state;
-
- cur_state = sender;
-
- /* note dirty trick to suppress ~ at start of format
- * if we know what state to blame.
- */
- if ((packet_len == 1) && (buffer[0] == 0xff)
-#ifdef DEBUG
- && ((cur_debugging & DBG_NATT) == 0)
-#endif
- ) {
- /* don't log NAT-T keepalive related errors unless NATT debug is
- * enabled
- */
- }
- else
- plog((sender != NULL) + "~"
- "ERROR: asynchronous network error report on %s"
- "%s"
- ", complainant %s"
- ": %s"
- " [errno %lu, origin %s"
- /* ", pad %d, info %ld" */
- /* ", data %ld" */
- "]"
- , ifp->rname
- , fromstr
- , offstr
- , strerror(ee->ee_errno)
- , (unsigned long) ee->ee_errno
- , orname
- /* , ee->ee_pad, (unsigned long)ee->ee_info */
- /* , (unsigned long)ee->ee_data */
- );
- cur_state = old_state;
- }
- }
- else
- {
- /* .cmsg_len is a kernel_size_t(!), but the value
- * certainly ought to fit in an unsigned long.
- */
- plog("unknown cmsg: level %d, type %d, len %lu"
- , cm->cmsg_level, cm->cmsg_type
- , (unsigned long) cm->cmsg_len);
- }
- }
- }
- return (pfd.revents & interest) != 0;
-}
-#endif /* defined(IP_RECVERR) && defined(MSG_ERRQUEUE) */
-
-bool
-send_packet(struct state *st, const char *where)
-{
- connection_t *c = st->st_connection;
- int port_buf;
- bool err;
- u_int8_t ike_pkt[MAX_OUTPUT_UDP_SIZE];
- u_int8_t *ptr;
- unsigned long len;
-
- if (c->interface->ike_float && st->st_tpacket.len != 1)
- {
- if ((unsigned long) st->st_tpacket.len > (MAX_OUTPUT_UDP_SIZE-sizeof(u_int32_t)))
- {
- DBG_log("send_packet(): really too big");
- return FALSE;
- }
- ptr = ike_pkt;
- /** Add Non-ESP marker **/
- memset(ike_pkt, 0, sizeof(u_int32_t));
- memcpy(ike_pkt + sizeof(u_int32_t), st->st_tpacket.ptr,
- (unsigned long)st->st_tpacket.len);
- len = (unsigned long) st->st_tpacket.len + sizeof(u_int32_t);
- }
- else
- {
- ptr = st->st_tpacket.ptr;
- len = (unsigned long) st->st_tpacket.len;
- }
-
- DBG(DBG_RAW,
- {
- DBG_log("sending %lu bytes for %s through %s to %s:%u:"
- , (unsigned long) st->st_tpacket.len
- , where
- , c->interface->rname
- , ip_str(&c->spd.that.host_addr)
- , (unsigned)c->spd.that.host_port);
- DBG_dump_chunk(NULL, st->st_tpacket);
- });
-
- /* XXX: Not very clean. We manipulate the port of the ip_address to
- * have a port in the sockaddr*, but we retain the original port
- * and restore it afterwards.
- */
-
- port_buf = portof(&c->spd.that.host_addr);
- setportof(htons(c->spd.that.host_port), &c->spd.that.host_addr);
-
-#if defined(IP_RECVERR) && defined(MSG_ERRQUEUE)
- (void) check_msg_errqueue(c->interface, POLLOUT);
-#endif /* defined(IP_RECVERR) && defined(MSG_ERRQUEUE) */
-
- err = sendto(c->interface->fd
- , ptr, len, 0
- , sockaddrof(&c->spd.that.host_addr)
- , sockaddrlenof(&c->spd.that.host_addr)) != (ssize_t)len;
-
- /* restore port */
- setportof(port_buf, &c->spd.that.host_addr);
-
- if (err)
- {
- /* do not log NAT-T Keep Alive packets */
- if (streq(where, "NAT-T Keep Alive"))
- return FALSE;
- log_errno((e, "sendto on %s to %s:%u failed in %s"
- , c->interface->rname
- , ip_str(&c->spd.that.host_addr)
- , (unsigned)c->spd.that.host_port
- , where));
- return FALSE;
- }
- else
- {
- return TRUE;
- }
-}
-
-static stf_status
-unexpected(struct msg_digest *md)
-{
- loglog(RC_LOG_SERIOUS, "unexpected message received in state %s"
- , enum_name(&state_names, md->st->st_state));
- return STF_IGNORE;
-}
-
-static stf_status
-informational(struct msg_digest *md UNUSED)
-{
- struct payload_digest *const n_pld = md->chain[ISAKMP_NEXT_N];
-
- /* If the Notification Payload is not null... */
- if (n_pld != NULL)
- {
- pb_stream *const n_pbs = &n_pld->pbs;
- struct isakmp_notification *const n = &n_pld->payload.notification;
- int disp_len;
- char disp_buf[200];
-
- /* Switch on Notification Type (enum) */
- switch (n->isan_type)
- {
- case R_U_THERE:
- return dpd_inI_outR(md->st, n, n_pbs);
-
- case R_U_THERE_ACK:
- return dpd_inR(md->st, n, n_pbs);
- default:
- if (pbs_left(n_pbs) >= sizeof(disp_buf)-1)
- disp_len = sizeof(disp_buf)-1;
- else
- disp_len = pbs_left(n_pbs);
- memcpy(disp_buf, n_pbs->cur, disp_len);
- disp_buf[disp_len] = '\0';
- break;
- }
- }
- return STF_IGNORE;
-}
-
-/* message digest allocation and deallocation */
-
-static struct msg_digest *md_pool = NULL;
-
-/* free_md_pool is only used to avoid leak reports */
-void
-free_md_pool(void)
-{
- for (;;)
- {
- struct msg_digest *md = md_pool;
-
- if (md == NULL)
- break;
- md_pool = md->next;
- free(md);
- }
-}
-
-static struct msg_digest *
-malloc_md(void)
-{
- struct msg_digest *md = md_pool;
-
- /* convenient initializer:
- * - all pointers NULL
- * - .note = NOTHING_WRONG
- * - .encrypted = FALSE
- */
- static const struct msg_digest blank_md = {
- .next = NULL,
- };
-
- if (md == NULL)
- {
- md = malloc_thing(struct msg_digest);
- zero(md);
- }
- else
- md_pool = md->next;
-
- *md = blank_md;
- md->digest_roof = md->digest;
-
- /* note: although there may be multiple msg_digests at once
- * (due to suspended state transitions), there is a single
- * global reply_buffer. It will need to be saved and restored.
- */
- init_pbs(&md->reply, reply_buffer, sizeof(reply_buffer), "reply packet");
-
- return md;
-}
-
-void
-release_md(struct msg_digest *md)
-{
- chunk_free(&md->raw_packet);
- free(md->packet_pbs.start);
- md->packet_pbs.start = NULL;
- md->next = md_pool;
- md_pool = md;
-}
-
-/* wrapper for read_packet and process_packet
- *
- * The main purpose of this wrapper is to factor out teardown code
- * from the many return points in process_packet. This amounts to
- * releasing the msg_digest and resetting global variables.
- *
- * When processing of a packet is suspended (STF_SUSPEND),
- * process_packet sets md to NULL to prevent the msg_digest being freed.
- * Someone else must ensure that msg_digest is freed eventually.
- *
- * read_packet is broken out to minimize the lifetime of the
- * enormous input packet buffer, an auto.
- */
-void
-comm_handle(const struct iface *ifp)
-{
- static struct msg_digest *md;
-
-#if defined(IP_RECVERR) && defined(MSG_ERRQUEUE)
- /* Even though select(2) says that there is a message,
- * it might only be a MSG_ERRQUEUE message. At least
- * sometimes that leads to a hanging recvfrom. To avoid
- * what appears to be a kernel bug, check_msg_errqueue
- * uses poll(2) and tells us if there is anything for us
- * to read.
- *
- * This is early enough that teardown isn't required:
- * just return on failure.
- */
- if (!check_msg_errqueue(ifp, POLLIN))
- return; /* no normal message to read */
-#endif /* defined(IP_RECVERR) && defined(MSG_ERRQUEUE) */
-
- md = malloc_md();
- md->iface = ifp;
-
- if (read_packet(md))
- process_packet(&md);
-
- if (md != NULL)
- release_md(md);
-
- cur_state = NULL;
- reset_cur_connection();
- cur_from = NULL;
-}
-
-/* read the message.
- * Since we don't know its size, we read it into
- * an overly large buffer and then copy it to a
- * new, properly sized buffer.
- */
-static bool
-read_packet(struct msg_digest *md)
-{
- const struct iface *ifp = md->iface;
- int packet_len;
- u_int8_t *buffer;
- u_int8_t *buffer_nat;
- union
- {
- struct sockaddr sa;
- struct sockaddr_in sa_in4;
- struct sockaddr_in6 sa_in6;
- } from;
- int from_len = sizeof(from);
- err_t from_ugh = NULL;
- static const char undisclosed[] = "unknown source";
-
- happy(anyaddr(addrtypeof(&ifp->addr), &md->sender));
- zero(&from.sa);
- ioctl(ifp->fd, FIONREAD, &packet_len);
- buffer = malloc(packet_len);
- packet_len = recvfrom(ifp->fd, buffer, packet_len, 0
- , &from.sa, &from_len);
-
- /* First: digest the from address.
- * We presume that nothing here disturbs errno.
- */
- if (packet_len == -1
- && from_len == sizeof(from)
- && all_zero((const void *)&from.sa, sizeof(from)))
- {
- /* "from" is untouched -- not set by recvfrom */
- from_ugh = undisclosed;
- }
- else if (from_len
- < (int) (offsetof(struct sockaddr, sa_family) + sizeof(from.sa.sa_family)))
- {
- from_ugh = "truncated";
- }
- else
- {
- const struct af_info *afi = aftoinfo(from.sa.sa_family);
-
- if (afi == NULL)
- {
- from_ugh = "unexpected Address Family";
- }
- else if (from_len != (int)afi->sa_sz)
- {
- from_ugh = "wrong length";
- }
- else
- {
- switch (from.sa.sa_family)
- {
- case AF_INET:
- from_ugh = initaddr((void *) &from.sa_in4.sin_addr
- , sizeof(from.sa_in4.sin_addr), AF_INET, &md->sender);
- md->sender_port = ntohs(from.sa_in4.sin_port);
- break;
- case AF_INET6:
- from_ugh = initaddr((void *) &from.sa_in6.sin6_addr
- , sizeof(from.sa_in6.sin6_addr), AF_INET6, &md->sender);
- md->sender_port = ntohs(from.sa_in6.sin6_port);
- break;
- }
- }
- }
-
- /* now we report any actual I/O error */
- if (packet_len == -1)
- {
- if (from_ugh == undisclosed
- && errno == ECONNREFUSED)
- {
- /* Tone down scary message for vague event:
- * We get "connection refused" in response to some
- * datagram we sent, but we cannot tell which one.
- */
- plog("some IKE message we sent has been rejected with ECONNREFUSED (kernel supplied no details)");
- }
- else if (from_ugh != NULL)
- {
- log_errno((e, "recvfrom on %s failed; Pluto cannot decode source sockaddr in rejection: %s"
- , ifp->rname, from_ugh));
- }
- else
- {
- log_errno((e, "recvfrom on %s from %s:%u failed"
- , ifp->rname
- , ip_str(&md->sender), (unsigned)md->sender_port));
- }
- free(buffer);
- return FALSE;
- }
- else if (from_ugh != NULL)
- {
- plog("recvfrom on %s returned malformed source sockaddr: %s"
- , ifp->rname, from_ugh);
- free(buffer);
- return FALSE;
- }
- cur_from = &md->sender;
- cur_from_port = md->sender_port;
-
- if (ifp->ike_float == TRUE)
- {
- u_int32_t non_esp;
-
- if (packet_len < (int)sizeof(u_int32_t))
- {
- plog("recvfrom %s:%u too small packet (%d)"
- , ip_str(cur_from), (unsigned) cur_from_port, packet_len);
- free(buffer);
- return FALSE;
- }
- memcpy(&non_esp, buffer, sizeof(u_int32_t));
- if (non_esp != 0)
- {
- plog("recvfrom %s:%u has no Non-ESP marker"
- , ip_str(cur_from), (unsigned) cur_from_port);
- free(buffer);
- return FALSE;
- }
- packet_len -= sizeof(u_int32_t);
- buffer_nat = malloc(packet_len);
- memcpy(buffer_nat, buffer + sizeof(u_int32_t), packet_len);
- free(buffer);
- buffer = buffer_nat;
- }
-
- /* Clone actual message contents
- * and set up md->packet_pbs to describe it.
- */
- init_pbs(&md->packet_pbs, buffer, packet_len, "packet");
-
- DBG(DBG_RAW | DBG_CRYPT | DBG_PARSING | DBG_CONTROL,
- {
- DBG_log(BLANK_FORMAT);
- DBG_log("*received %d bytes from %s:%u on %s"
- , (int) pbs_room(&md->packet_pbs)
- , ip_str(cur_from), (unsigned) cur_from_port
- , ifp->rname);
- });
-
- DBG(DBG_RAW,
- DBG_dump("", md->packet_pbs.start, pbs_room(&md->packet_pbs)));
-
- if ((pbs_room(&md->packet_pbs)==1) && (md->packet_pbs.start[0]==0xff))
- {
- /**
- * NAT-T Keep-alive packets should be discarded by kernel ESPinUDP
- * layer. But bogus keep-alive packets (sent with a non-esp marker)
- * can reach this point. Complain and discard them.
- */
- DBG(DBG_NATT,
- DBG_log("NAT-T keep-alive (bogus ?) should not reach this point. "
- "Ignored. Sender: %s:%u", ip_str(cur_from),
- (unsigned) cur_from_port);
- )
- return FALSE;
- }
-
-#define IKEV2_VERSION_OFFSET 17
-#define IKEV2_VERSION 0x20
-
- /* ignore IKEv2 packets - they will be handled by charon */
- if (pbs_room(&md->packet_pbs) > IKEV2_VERSION_OFFSET
- && (md->packet_pbs.start[IKEV2_VERSION_OFFSET] & 0xF0) == IKEV2_VERSION)
- {
- DBG(DBG_CONTROLMORE,
- DBG_log(" ignoring IKEv2 packet")
- )
- return FALSE;
- }
-
- return TRUE;
-}
-
-/* process an input packet, possibly generating a reply.
- *
- * If all goes well, this routine eventually calls a state-specific
- * transition function.
- */
-static void
-process_packet(struct msg_digest **mdp)
-{
- struct msg_digest *md = *mdp;
- const struct state_microcode *smc;
- bool new_iv_set = FALSE;
- bool restore_iv = FALSE;
- u_char new_iv[MAX_DIGEST_LEN];
- u_int new_iv_len = 0;
-
- struct state *st = NULL;
- enum state_kind from_state = STATE_UNDEFINED; /* state we started in */
-
-#define SEND_NOTIFICATION(t) { \
- if (st) send_notification_from_state(st, from_state, t); \
- else send_notification_from_md(md, t); }
-
- if (!in_struct(&md->hdr, &isakmp_hdr_desc, &md->packet_pbs, &md->message_pbs))
- {
- /* Identify specific failures:
- * - bad ISAKMP major/minor version numbers
- */
- if (md->packet_pbs.roof - md->packet_pbs.cur >= (ptrdiff_t)isakmp_hdr_desc.size)
- {
- struct isakmp_hdr *hdr = (struct isakmp_hdr *)md->packet_pbs.cur;
- if ((hdr->isa_version >> ISA_MAJ_SHIFT) != ISAKMP_MAJOR_VERSION)
- {
- SEND_NOTIFICATION(ISAKMP_INVALID_MAJOR_VERSION);
- return;
- }
- else if ((hdr->isa_version & ISA_MIN_MASK) != ISAKMP_MINOR_VERSION)
- {
- SEND_NOTIFICATION(ISAKMP_INVALID_MINOR_VERSION);
- return;
- }
- }
- SEND_NOTIFICATION(ISAKMP_PAYLOAD_MALFORMED);
- return;
- }
-
- if (md->packet_pbs.roof != md->message_pbs.roof)
- {
- plog("size (%u) differs from size specified in ISAKMP HDR (%u)"
- , (unsigned) pbs_room(&md->packet_pbs), md->hdr.isa_length);
-#ifdef CISCO_QUIRKS
- if (pbs_room(&md->packet_pbs) - md->hdr.isa_length == 16)
- plog("Cisco VPN client appends 16 surplus NULL bytes");
- else
-#endif
- return;
- }
-
- switch (md->hdr.isa_xchg)
- {
-#ifdef NOTYET
- case ISAKMP_XCHG_NONE:
- case ISAKMP_XCHG_BASE:
-#endif
-
- case ISAKMP_XCHG_IDPROT: /* part of a Main Mode exchange */
- if (md->hdr.isa_msgid != MAINMODE_MSGID)
- {
- plog("Message ID was 0x%08lx but should be zero in Main Mode",
- (unsigned long) md->hdr.isa_msgid);
- SEND_NOTIFICATION(ISAKMP_INVALID_MESSAGE_ID);
- return;
- }
-
- if (is_zero_cookie(md->hdr.isa_icookie))
- {
- plog("Initiator Cookie must not be zero in Main Mode message");
- SEND_NOTIFICATION(ISAKMP_INVALID_COOKIE);
- return;
- }
-
- if (is_zero_cookie(md->hdr.isa_rcookie))
- {
- /* initial message from initiator
- * ??? what if this is a duplicate of another message?
- */
- if (md->hdr.isa_flags & ISAKMP_FLAG_ENCRYPTION)
- {
- plog("initial Main Mode message is invalid:"
- " its Encrypted Flag is on");
- SEND_NOTIFICATION(ISAKMP_INVALID_FLAGS);
- return;
- }
-
- /* don't build a state until the message looks tasty */
- from_state = STATE_MAIN_R0;
- }
- else
- {
- /* not an initial message */
-
- st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie
- , &md->sender, md->hdr.isa_msgid);
-
- if (st == NULL)
- {
- /* perhaps this is a first message from the responder
- * and contains a responder cookie that we've not yet seen.
- */
- st = find_state(md->hdr.isa_icookie, zero_cookie
- , &md->sender, md->hdr.isa_msgid);
-
- if (st == NULL)
- {
- plog("Main Mode message is part of an unknown exchange");
- /* XXX Could send notification back */
- return;
- }
- }
- set_cur_state(st);
- from_state = st->st_state;
- }
- break;
-
-#ifdef NOTYET
- case ISAKMP_XCHG_AO:
- case ISAKMP_XCHG_AGGR:
-#endif
-
- case ISAKMP_XCHG_INFO: /* an informational exchange */
- st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie
- , &md->sender, MAINMODE_MSGID);
-
- if (st != NULL)
- set_cur_state(st);
-
- if (md->hdr.isa_flags & ISAKMP_FLAG_ENCRYPTION)
- {
- if (st == NULL)
- {
- plog("Informational Exchange is for an unknown (expired?) SA");
- /* XXX Could send notification back */
- return;
- }
-
- if (!IS_ISAKMP_ENCRYPTED(st->st_state))
- {
- loglog(RC_LOG_SERIOUS, "encrypted Informational Exchange message is invalid"
- " because no key is known");
- /* XXX Could send notification back */
- return;
- }
-
- if (md->hdr.isa_msgid == MAINMODE_MSGID)
- {
- loglog(RC_LOG_SERIOUS, "Informational Exchange message is invalid because"
- " it has a Message ID of 0");
- /* XXX Could send notification back */
- return;
- }
-
- if (!reserve_msgid(st, md->hdr.isa_msgid))
- {
- loglog(RC_LOG_SERIOUS, "Informational Exchange message is invalid because"
- " it has a previously used Message ID (0x%08lx)"
- , (unsigned long)md->hdr.isa_msgid);
- /* XXX Could send notification back */
- return;
- }
-
- if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state))
- {
- memcpy(st->st_ph1_iv, st->st_new_iv, st->st_new_iv_len);
- st->st_ph1_iv_len = st->st_new_iv_len;
-
- /* backup new_iv */
- new_iv_len = st->st_new_iv_len;
- passert(new_iv_len <= MAX_DIGEST_LEN)
- memcpy(new_iv, st->st_new_iv, new_iv_len);
- restore_iv = TRUE;
- }
- init_phase2_iv(st, &md->hdr.isa_msgid);
- new_iv_set = TRUE;
-
- from_state = STATE_INFO_PROTECTED;
- }
- else
- {
- if (st != NULL && IS_ISAKMP_ENCRYPTED(st->st_state))
- {
- loglog(RC_LOG_SERIOUS, "Informational Exchange message"
- " must be encrypted");
- /* XXX Could send notification back */
- return;
- }
- from_state = STATE_INFO;
- }
- break;
-
- case ISAKMP_XCHG_QUICK: /* part of a Quick Mode exchange */
- if (is_zero_cookie(md->hdr.isa_icookie))
- {
- plog("Quick Mode message is invalid because"
- " it has an Initiator Cookie of 0");
- SEND_NOTIFICATION(ISAKMP_INVALID_COOKIE);
- return;
- }
-
- if (is_zero_cookie(md->hdr.isa_rcookie))
- {
- plog("Quick Mode message is invalid because"
- " it has a Responder Cookie of 0");
- SEND_NOTIFICATION(ISAKMP_INVALID_COOKIE);
- return;
- }
-
- if (md->hdr.isa_msgid == MAINMODE_MSGID)
- {
- plog("Quick Mode message is invalid because"
- " it has a Message ID of 0");
- SEND_NOTIFICATION(ISAKMP_INVALID_MESSAGE_ID);
- return;
- }
-
- st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie
- , &md->sender, md->hdr.isa_msgid);
-
- if (st == NULL)
- {
- /* No appropriate Quick Mode state.
- * See if we have a Main Mode state.
- * ??? what if this is a duplicate of another message?
- */
- st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie
- , &md->sender, MAINMODE_MSGID);
-
- if (st == NULL)
- {
- plog("Quick Mode message is for a non-existent (expired?)"
- " ISAKMP SA");
- /* XXX Could send notification back */
- return;
- }
-
- set_cur_state(st);
-
- if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state))
- {
- loglog(RC_LOG_SERIOUS, "Quick Mode message is unacceptable because"
- " it is for an incomplete ISAKMP SA");
- SEND_NOTIFICATION(ISAKMP_PAYLOAD_MALFORMED /* XXX ? */);
- return;
- }
-
- /* only accept this new Quick Mode exchange if it has a unique message ID */
- if (!reserve_msgid(st, md->hdr.isa_msgid))
- {
- loglog(RC_LOG_SERIOUS, "Quick Mode I1 message is unacceptable because"
- " it uses a previously used Message ID 0x%08lx"
- " (perhaps this is a duplicated packet)"
- , (unsigned long) md->hdr.isa_msgid);
- SEND_NOTIFICATION(ISAKMP_INVALID_MESSAGE_ID);
- return;
- }
-
- /* Quick Mode Initial IV */
- init_phase2_iv(st, &md->hdr.isa_msgid);
- new_iv_set = TRUE;
-
- from_state = STATE_QUICK_R0;
- }
- else
- {
- set_cur_state(st);
- from_state = st->st_state;
- }
-
- break;
-
- case ISAKMP_XCHG_MODE_CFG:
- if (is_zero_cookie(md->hdr.isa_icookie))
- {
- plog("ModeCfg message is invalid because"
- " it has an Initiator Cookie of 0");
- /* XXX Could send notification back */
- return;
- }
-
- if (is_zero_cookie(md->hdr.isa_rcookie))
- {
- plog("ModeCfg message is invalid because"
- " it has a Responder Cookie of 0");
- /* XXX Could send notification back */
- return;
- }
-
- if (md->hdr.isa_msgid == 0)
- {
- plog("ModeCfg message is invalid because"
- " it has a Message ID of 0");
- /* XXX Could send notification back */
- return;
- }
-
- st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie
- , &md->sender, md->hdr.isa_msgid);
-
- if (st == NULL)
- {
- bool has_xauth_policy;
-
- /* No appropriate ModeCfg state.
- * See if we have a Main Mode state.
- * ??? what if this is a duplicate of another message?
- */
- st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie
- , &md->sender, 0);
-
- if (st == NULL)
- {
- plog("ModeCfg message is for a non-existent (expired?)"
- " ISAKMP SA");
- /* XXX Could send notification back */
- return;
- }
-
- set_cur_state(st);
-
- /* the XAUTH_STATUS message might have a new msgid */
- if (st->st_state == STATE_XAUTH_I1)
- {
- init_phase2_iv(st, &md->hdr.isa_msgid);
- new_iv_set = TRUE;
- from_state = st->st_state;
- break;
- }
-
- if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state))
- {
- loglog(RC_LOG_SERIOUS, "ModeCfg message is unacceptable because"
- " it is for an incomplete ISAKMP SA (state=%s)"
- , enum_name(&state_names, st->st_state));
- /* XXX Could send notification back */
- return;
- }
- init_phase2_iv(st, &md->hdr.isa_msgid);
- new_iv_set = TRUE;
-
- /*
- * okay, now we have to figure out if we are receiving a bogus
- * new message in an outstanding XAUTH server conversation
- * (i.e. a reply to our challenge)
- * (this occurs with some broken other implementations).
- *
- * or if receiving for the first time, an XAUTH challenge.
- *
- * or if we are getting a MODECFG request.
- *
- * we distinguish these states because we can not both be an
- * XAUTH server and client, and our policy tells us which
- * one we are.
- *
- * to complicate further, it is normal to start a new msgid
- * when going from one state to another, or when restarting
- * the challenge.
- *
- */
-
- has_xauth_policy = (st->st_connection->policy
- & (POLICY_XAUTH_RSASIG | POLICY_XAUTH_PSK))
- != LEMPTY;
-
- if (has_xauth_policy && !st->st_xauth.started
- && IS_PHASE1(st->st_state))
- {
- from_state = STATE_XAUTH_I0;
- }
- else if (st->st_connection->spd.that.modecfg
- && IS_PHASE1(st->st_state))
- {
- from_state = STATE_MODE_CFG_R0;
- }
- else if (st->st_connection->spd.this.modecfg
- && IS_PHASE1(st->st_state))
- {
- from_state = STATE_MODE_CFG_I0;
- }
- else
- {
- /* XXX check if we are being a mode config server here */
- plog("received ModeCfg message when in state %s, and we aren't mode config client"
- , enum_name(&state_names, st->st_state));
- return;
- }
- }
- else
- {
- set_cur_state(st);
- from_state = st->st_state;
- }
- break;
-
-#ifdef NOTYET
- case ISAKMP_XCHG_NGRP:
- case ISAKMP_XCHG_ACK_INFO:
-#endif
-
- default:
- plog("unsupported exchange type %s in message"
- , enum_show(&exchange_names, md->hdr.isa_xchg));
- SEND_NOTIFICATION(ISAKMP_UNSUPPORTED_EXCHANGE_TYPE);
- return;
- }
-
- /* We have found a from_state, and perhaps a state object.
- * If we need to build a new state object,
- * we wait until the packet has been sanity checked.
- */
-
- /* We don't support the Commit Flag. It is such a bad feature.
- * It isn't protected -- neither encrypted nor authenticated.
- * A man in the middle turns it on, leading to DoS.
- * We just ignore it, with a warning.
- * By placing the check here, we could easily add a policy bit
- * to a connection to suppress the warning. This might be useful
- * because the Commit Flag is expected from some peers.
- */
- if (md->hdr.isa_flags & ISAKMP_FLAG_COMMIT)
- {
- plog("IKE message has the Commit Flag set but Pluto doesn't implement this feature; ignoring flag");
- }
-
- /* Set smc to describe this state's properties.
- * Look up the appropriate microcode based on state and
- * possibly Oakley Auth type.
- */
- passert(STATE_IKE_FLOOR <= from_state && from_state < STATE_IKE_ROOF);
- smc = ike_microcode_index[from_state - STATE_IKE_FLOOR];
-
- if (st != NULL)
- {
- u_int16_t auth;
-
- switch (st->st_oakley.auth)
- {
- case XAUTHInitPreShared:
- case XAUTHRespPreShared:
- auth = OAKLEY_PRESHARED_KEY;
- break;
- case XAUTHInitRSA:
- case XAUTHRespRSA:
- auth = OAKLEY_RSA_SIG;
- break;
- default:
- auth = st->st_oakley.auth;
- }
-
- while (!LHAS(smc->flags, auth))
- {
- smc++;
- passert(smc->state == from_state);
- }
- }
-
- /* Ignore a packet if the state has a suspended state transition
- * Probably a duplicated packet but the original packet is not yet
- * recorded in st->st_rpacket, so duplicate checking won't catch.
- * ??? Should the packet be recorded earlier to improve diagnosis?
- */
- if (st != NULL && st->st_suspended_md != NULL)
- {
- loglog(RC_LOG, "discarding packet received during DNS lookup in %s"
- , enum_name(&state_names, st->st_state));
- return;
- }
-
- /* Detect and handle duplicated packets.
- * This won't work for the initial packet of an exchange
- * because we won't have a state object to remember it.
- * If we are in a non-receiving state (terminal), and the preceding
- * state did transmit, then the duplicate may indicate that that
- * transmission wasn't received -- retransmit it.
- * Otherwise, just discard it.
- * ??? Notification packets are like exchanges -- I hope that
- * they are idempotent!
- */
- if (st != NULL
- && st->st_rpacket.ptr != NULL
- && st->st_rpacket.len == pbs_room(&md->packet_pbs)
- && memeq(st->st_rpacket.ptr, md->packet_pbs.start, st->st_rpacket.len))
- {
- if (smc->flags & SMF_RETRANSMIT_ON_DUPLICATE)
- {
- if (st->st_retransmit < MAXIMUM_RETRANSMISSIONS)
- {
- st->st_retransmit++;
- loglog(RC_RETRANSMISSION
- , "retransmitting in response to duplicate packet; already %s"
- , enum_name(&state_names, st->st_state));
- send_packet(st, "retransmit in response to duplicate");
- }
- else
- {
- loglog(RC_LOG_SERIOUS, "discarding duplicate packet -- exhausted retransmission; already %s"
- , enum_name(&state_names, st->st_state));
- }
- }
- else
- {
- loglog(RC_LOG_SERIOUS, "discarding duplicate packet; already %s"
- , enum_name(&state_names, st->st_state));
- }
- return;
- }
-
- if (md->hdr.isa_flags & ISAKMP_FLAG_ENCRYPTION)
- {
- DBG(DBG_CRYPT, DBG_log("received encrypted packet from %s:%u"
- , ip_str(&md->sender), (unsigned)md->sender_port));
-
- if (st == NULL)
- {
- plog("discarding encrypted message for an unknown ISAKMP SA");
- SEND_NOTIFICATION(ISAKMP_PAYLOAD_MALFORMED /* XXX ? */);
- return;
- }
- if (st->st_skeyid_e.ptr == (u_char *) NULL)
- {
- loglog(RC_LOG_SERIOUS, "discarding encrypted message"
- " because we haven't yet negotiated keying materiel");
- SEND_NOTIFICATION(ISAKMP_INVALID_FLAGS);
- return;
- }
-
- /* Mark as encrypted */
- md->encrypted = TRUE;
-
- DBG(DBG_CRYPT, DBG_log("decrypting %u bytes using algorithm %s"
- , (unsigned) pbs_left(&md->message_pbs)
- , enum_show(&oakley_enc_names, st->st_oakley.encrypt)));
-
- /* do the specified decryption
- *
- * IV is from st->st_iv or (if new_iv_set) st->st_new_iv.
- * The new IV is placed in st->st_new_iv
- *
- * See RFC 2409 "IKE" Appendix B
- *
- * XXX The IV should only be updated really if the packet
- * is successfully processed.
- * We should keep this value, check for a success return
- * value from the parsing routines and then replace.
- *
- * Each post phase 1 exchange generates IVs from
- * the last phase 1 block, not the last block sent.
- */
- {
- size_t crypter_block_size, crypter_iv_size;
- encryption_algorithm_t enc_alg;
- crypter_t *crypter;
- chunk_t data, iv;
- char *new_iv;
-
- enc_alg = oakley_to_encryption_algorithm(st->st_oakley.encrypt);
- crypter = lib->crypto->create_crypter(lib->crypto, enc_alg, st->st_enc_key.len);
- crypter_block_size = crypter->get_block_size(crypter);
- crypter_iv_size = crypter->get_iv_size(crypter);
-
- if (pbs_left(&md->message_pbs) % crypter_block_size != 0)
- {
- loglog(RC_LOG_SERIOUS, "malformed message: not a multiple of encryption blocksize");
- SEND_NOTIFICATION(ISAKMP_PAYLOAD_MALFORMED);
- return;
- }
-
- /* XXX Detect weak keys */
-
- /* grab a copy of raw packet (for duplicate packet detection) */
- md->raw_packet = chunk_create(md->packet_pbs.start, pbs_room(&md->packet_pbs));
- md->raw_packet = chunk_clone(md->raw_packet);
-
- data = chunk_create(md->message_pbs.cur, pbs_left(&md->message_pbs));
-
- /* Decrypt everything after header */
- if (!new_iv_set)
- {
- /* use old IV */
- passert(st->st_iv_len <= sizeof(st->st_new_iv));
- st->st_new_iv_len = st->st_iv_len;
- memcpy(st->st_new_iv, st->st_iv, st->st_new_iv_len);
- }
-
- /* form iv by truncation */
- st->st_new_iv_len = crypter_iv_size;
- iv = chunk_create(st->st_new_iv, st->st_new_iv_len);
- new_iv = alloca(crypter_iv_size);
- memcpy(new_iv, data.ptr + data.len - crypter_iv_size,
- crypter_iv_size);
-
- crypter->set_key(crypter, st->st_enc_key);
- crypter->decrypt(crypter, data, iv, NULL);
- crypter->destroy(crypter);
-
- memcpy(st->st_new_iv, new_iv, crypter_iv_size);
- if (restore_iv)
- {
- memcpy(st->st_new_iv, new_iv, new_iv_len);
- st->st_new_iv_len = new_iv_len;
- }
- }
-
- DBG_cond_dump(DBG_CRYPT, "decrypted:\n", md->message_pbs.cur
- , md->message_pbs.roof - md->message_pbs.cur);
-
- DBG_cond_dump(DBG_CRYPT, "next IV:"
- , st->st_new_iv, st->st_new_iv_len);
- }
- else
- {
- /* packet was not encryped -- should it have been? */
-
- if (smc->flags & SMF_INPUT_ENCRYPTED)
- {
- loglog(RC_LOG_SERIOUS, "packet rejected: should have been encrypted");
- SEND_NOTIFICATION(ISAKMP_INVALID_FLAGS);
- return;
- }
- }
-
- /* Digest the message.
- * Padding must be removed to make hashing work.
- * Padding comes from encryption (so this code must be after decryption).
- * Padding rules are described before the definition of
- * struct isakmp_hdr in packet.h.
- */
- {
- struct payload_digest *pd = md->digest;
- int np = md->hdr.isa_np;
- lset_t needed = smc->req_payloads;
- const char *excuse
- = LIN(SMF_PSK_AUTH | SMF_FIRST_ENCRYPTED_INPUT, smc->flags)
- ? "probable authentication failure (mismatch of preshared secrets?): "
- : "";
-
- while (np != ISAKMP_NEXT_NONE)
- {
- struct_desc *sd = np < ISAKMP_NEXT_ROOF? payload_descs[np] : NULL;
-
- if (pd == &md->digest[PAYLIMIT])
- {
- loglog(RC_LOG_SERIOUS, "more than %d payloads in message; ignored", PAYLIMIT);
- SEND_NOTIFICATION(ISAKMP_PAYLOAD_MALFORMED);
- return;
- }
-
- switch (np)
- {
- case ISAKMP_NEXT_NATD_RFC:
- case ISAKMP_NEXT_NATOA_RFC:
- if (!st || !(st->nat_traversal & NAT_T_WITH_RFC_VALUES))
- {
- /*
- * don't accept NAT-D/NAT-OA reloc directly in message, unless
- * we're using NAT-T RFC
- */
- sd = NULL;
- }
- break;
- }
-
- if (sd == NULL)
- {
- /* payload type is out of range or requires special handling */
- switch (np)
- {
- case ISAKMP_NEXT_ID:
- sd = IS_PHASE1(from_state)
- ? &isakmp_identification_desc : &isakmp_ipsec_identification_desc;
- break;
- case ISAKMP_NEXT_NATD_DRAFTS:
- np = ISAKMP_NEXT_NATD_RFC; /* NAT-D relocated */
- sd = payload_descs[np];
- break;
- case ISAKMP_NEXT_NATOA_DRAFTS:
- np = ISAKMP_NEXT_NATOA_RFC; /* NAT-OA relocated */
- sd = payload_descs[np];
- break;
- default:
- loglog(RC_LOG_SERIOUS, "%smessage ignored because it contains an unknown or"
- " unexpected payload type (%s) at the outermost level"
- , excuse, enum_show(&payload_names, np));
- SEND_NOTIFICATION(ISAKMP_INVALID_PAYLOAD_TYPE);
- return;
- }
- }
-
- {
- lset_t s = LELEM(np);
-
- if (LDISJOINT(s
- , needed | smc->opt_payloads| LELEM(ISAKMP_NEXT_N) | LELEM(ISAKMP_NEXT_D)))
- {
- loglog(RC_LOG_SERIOUS, "%smessage ignored because it "
- "contains an unexpected payload type (%s)"
- , excuse, enum_show(&payload_names, np));
- SEND_NOTIFICATION(ISAKMP_INVALID_PAYLOAD_TYPE);
- return;
- }
- needed &= ~s;
- }
-
- if (!in_struct(&pd->payload, sd, &md->message_pbs, &pd->pbs))
- {
- loglog(RC_LOG_SERIOUS, "%smalformed payload in packet", excuse);
- if (md->hdr.isa_xchg != ISAKMP_XCHG_INFO)
- SEND_NOTIFICATION(ISAKMP_PAYLOAD_MALFORMED);
- return;
- }
-
- /* place this payload at the end of the chain for this type */
- {
- struct payload_digest **p;
-
- for (p = &md->chain[np]; *p != NULL; p = &(*p)->next)
- ;
- *p = pd;
- pd->next = NULL;
- }
-
- np = pd->payload.generic.isag_np;
- pd++;
-
- /* since we've digested one payload happily, it is probably
- * the case that any decryption worked. So we will not suggest
- * encryption failure as an excuse for subsequent payload
- * problems.
- */
- excuse = "";
- }
-
- md->digest_roof = pd;
-
- DBG(DBG_PARSING,
- if (pbs_left(&md->message_pbs) != 0)
- DBG_log("removing %d bytes of padding", (int) pbs_left(&md->message_pbs)));
-
- md->message_pbs.roof = md->message_pbs.cur;
-
- /* check that all mandatory payloads appeared */
-
- if (needed != 0)
- {
- loglog(RC_LOG_SERIOUS, "message for %s is missing payloads %s"
- , enum_show(&state_names, from_state)
- , bitnamesof(payload_name, needed));
- SEND_NOTIFICATION(ISAKMP_PAYLOAD_MALFORMED);
- return;
- }
- }
-
- /* more sanity checking: enforce most ordering constraints */
-
- if (IS_PHASE1(from_state))
- {
- /* rfc2409: The Internet Key Exchange (IKE), 5 Exchanges:
- * "The SA payload MUST precede all other payloads in a phase 1 exchange."
- */
- if (md->chain[ISAKMP_NEXT_SA] != NULL
- && md->hdr.isa_np != ISAKMP_NEXT_SA)
- {
- loglog(RC_LOG_SERIOUS, "malformed Phase 1 message: does not start with an SA payload");
- SEND_NOTIFICATION(ISAKMP_PAYLOAD_MALFORMED);
- return;
- }
- }
- else if (IS_QUICK(from_state))
- {
- /* rfc2409: The Internet Key Exchange (IKE), 5.5 Phase 2 - Quick Mode
- *
- * "In Quick Mode, a HASH payload MUST immediately follow the ISAKMP
- * header and a SA payload MUST immediately follow the HASH."
- * [NOTE: there may be more than one SA payload, so this is not
- * totally reasonable. Probably all SAs should be so constrained.]
- *
- * "If ISAKMP is acting as a client negotiator on behalf of another
- * party, the identities of the parties MUST be passed as IDci and
- * then IDcr."
- *
- * "With the exception of the HASH, SA, and the optional ID payloads,
- * there are no payload ordering restrictions on Quick Mode."
- */
-
- if (md->hdr.isa_np != ISAKMP_NEXT_HASH)
- {
- loglog(RC_LOG_SERIOUS, "malformed Quick Mode message: does not start with a HASH payload");
- SEND_NOTIFICATION(ISAKMP_PAYLOAD_MALFORMED);
- return;
- }
-
- {
- struct payload_digest *p;
- int i;
-
- for (p = md->chain[ISAKMP_NEXT_SA], i = 1; p != NULL
- ; p = p->next, i++)
- {
- if (p != &md->digest[i])
- {
- loglog(RC_LOG_SERIOUS, "malformed Quick Mode message: SA payload is in wrong position");
- SEND_NOTIFICATION(ISAKMP_PAYLOAD_MALFORMED);
- return;
- }
- }
- }
-
- /* rfc2409: The Internet Key Exchange (IKE), 5.5 Phase 2 - Quick Mode:
- * "If ISAKMP is acting as a client negotiator on behalf of another
- * party, the identities of the parties MUST be passed as IDci and
- * then IDcr."
- */
- {
- struct payload_digest *id = md->chain[ISAKMP_NEXT_ID];
-
- if (id != NULL)
- {
- if (id->next == NULL || id->next->next != NULL)
- {
- loglog(RC_LOG_SERIOUS, "malformed Quick Mode message:"
- " if any ID payload is present,"
- " there must be exactly two");
- SEND_NOTIFICATION(ISAKMP_PAYLOAD_MALFORMED);
- return;
- }
- if (id+1 != id->next)
- {
- loglog(RC_LOG_SERIOUS, "malformed Quick Mode message:"
- " the ID payloads are not adjacent");
- SEND_NOTIFICATION(ISAKMP_PAYLOAD_MALFORMED);
- return;
- }
- }
- }
- }
-
- /* Ignore payloads that we don't handle:
- * Delete, Notification, VendorID
- */
- /* XXX Handle deletions */
- /* XXX Handle Notifications */
- /* XXX Handle VID payloads */
- {
- struct payload_digest *p;
-
- for (p = md->chain[ISAKMP_NEXT_N]; p != NULL; p = p->next)
- {
- if (p->payload.notification.isan_type != R_U_THERE
- && p->payload.notification.isan_type != R_U_THERE_ACK)
- {
- loglog(RC_LOG_SERIOUS, "ignoring informational payload, type %s"
- , enum_show(&notification_names, p->payload.notification.isan_type));
- }
- DBG_cond_dump(DBG_PARSING, "info:", p->pbs.cur, pbs_left(&p->pbs));
- }
-
- for (p = md->chain[ISAKMP_NEXT_D]; p != NULL; p = p->next)
- {
- accept_delete(st, md, p);
- DBG_cond_dump(DBG_PARSING, "del:", p->pbs.cur, pbs_left(&p->pbs));
- }
-
- for (p = md->chain[ISAKMP_NEXT_VID]; p != NULL; p = p->next)
- {
- handle_vendorid(md, p->pbs.cur, pbs_left(&p->pbs));
- }
- }
- md->from_state = from_state;
- md->smc = smc;
- md->st = st;
-
- /* possibly fill in hdr */
- if (smc->first_out_payload != ISAKMP_NEXT_NONE)
- echo_hdr(md, (smc->flags & SMF_OUTPUT_ENCRYPTED) != 0
- , smc->first_out_payload);
-
- complete_state_transition(mdp, smc->processor(md));
-}
-
-/* complete job started by the state-specific state transition function */
-
-void
-complete_state_transition(struct msg_digest **mdp, stf_status result)
-{
- bool has_xauth_policy;
- bool is_xauth_server;
- struct msg_digest *md = *mdp;
- const struct state_microcode *smc = md->smc;
- enum state_kind from_state = md->from_state;
- struct state *st;
-
- cur_state = st = md->st; /* might have changed */
-
- /* If state has DPD support, import it */
- if (st && md->dpd)
- st->st_dpd = TRUE;
-
- switch (result)
- {
- case STF_IGNORE:
- break;
-
- case STF_SUSPEND:
- /* the stf didn't complete its job: don't relase md */
- *mdp = NULL;
- break;
-
- case STF_OK:
- /* advance the state */
- st->st_state = smc->next_state;
-
- /* Delete previous retransmission event.
- * New event will be scheduled below.
- */
- delete_event(st);
-
- /* replace previous receive packet with latest */
-
- free(st->st_rpacket.ptr);
-
- if (md->encrypted)
- {
- /* if encrypted, duplication already done */
- st->st_rpacket = md->raw_packet;
- md->raw_packet.ptr = NULL;
- }
- else
- {
- st->st_rpacket = chunk_create(md->packet_pbs.start,
- pbs_room(&md->packet_pbs));
- st->st_rpacket = chunk_clone(st->st_rpacket);
- }
-
- /* free previous transmit packet */
- chunk_free(&st->st_tpacket);
-
- /* if requested, send the new reply packet */
- if (smc->flags & SMF_REPLY)
- {
- close_output_pbs(&md->reply); /* good form, but actually a no-op */
-
- st->st_tpacket = chunk_create(md->reply.start, pbs_offset(&md->reply));
- st->st_tpacket = chunk_clone(st->st_tpacket);
-
- if (nat_traversal_enabled)
- nat_traversal_change_port_lookup(md, md->st);
-
- /* actually send the packet
- * Note: this is a great place to implement "impairments"
- * for testing purposes. Suppress or duplicate the
- * send_packet call depending on st->st_state.
- */
- send_packet(st, enum_name(&state_names, from_state));
- }
-
- /* Schedule for whatever timeout is specified */
- {
- time_t delay = UNDEFINED_TIME;
- enum event_type kind = smc->timeout_event;
- bool agreed_time = FALSE;
- connection_t *c = st->st_connection;
-
- switch (kind)
- {
- case EVENT_RETRANSMIT: /* Retransmit packet */
- delay = EVENT_RETRANSMIT_DELAY_0;
- break;
-
- case EVENT_SA_REPLACE: /* SA replacement event */
- if (IS_PHASE1(st->st_state))
- {
- /* Note: we will defer to the "negotiated" (dictated)
- * lifetime if we are POLICY_DONT_REKEY.
- * This allows the other side to dictate
- * a time we would not otherwise accept
- * but it prevents us from having to initiate
- * rekeying. The negative consequences seem
- * minor.
- */
- delay = c->sa_ike_life_seconds;
- if ((c->policy & POLICY_DONT_REKEY)
- || delay >= st->st_oakley.life_seconds)
- {
- agreed_time = TRUE;
- delay = st->st_oakley.life_seconds;
- }
- }
- else
- {
- /* Delay is min of up to four things:
- * each can limit the lifetime.
- */
- delay = c->sa_ipsec_life_seconds;
- if (st->st_ah.present
- && delay >= st->st_ah.attrs.life_seconds)
- {
- agreed_time = TRUE;
- delay = st->st_ah.attrs.life_seconds;
- }
- if (st->st_esp.present
- && delay >= st->st_esp.attrs.life_seconds)
- {
- agreed_time = TRUE;
- delay = st->st_esp.attrs.life_seconds;
- }
- if (st->st_ipcomp.present
- && delay >= st->st_ipcomp.attrs.life_seconds)
- {
- agreed_time = TRUE;
- delay = st->st_ipcomp.attrs.life_seconds;
- }
- }
-
- /* By default, we plan to rekey.
- *
- * If there isn't enough time to rekey, plan to
- * expire.
- *
- * If we are --dontrekey, a lot more rules apply.
- * If we are the Initiator, use REPLACE_IF_USED.
- * If we are the Responder, and the dictated time
- * was unacceptable (too large), plan to REPLACE
- * (the only way to ratchet down the time).
- * If we are the Responder, and the dictated time
- * is acceptable, plan to EXPIRE.
- *
- * Important policy lies buried here.
- * For example, we favour the initiator over the
- * responder by making the initiator start rekeying
- * sooner. Also, fuzz is only added to the
- * initiator's margin.
- *
- * Note: for ISAKMP SA, we let the negotiated
- * time stand (implemented by earlier logic).
- */
- if (agreed_time
- && (c->policy & POLICY_DONT_REKEY))
- {
- kind = (smc->flags & SMF_INITIATOR)
- ? EVENT_SA_REPLACE_IF_USED
- : EVENT_SA_EXPIRE;
- }
- if (kind != EVENT_SA_EXPIRE)
- {
- unsigned long marg = c->sa_rekey_margin;
-
- if (smc->flags & SMF_INITIATOR)
- marg += marg
- * c->sa_rekey_fuzz / 100.E0
- * (rand() / (RAND_MAX + 1.E0));
- else
- marg /= 2;
-
- if ((unsigned long)delay > marg)
- {
- delay -= marg;
- st->st_margin = marg;
- }
- else
- {
- kind = EVENT_SA_EXPIRE;
- }
- }
- break;
-
- case EVENT_NULL: /* non-event */
- case EVENT_REINIT_SECRET: /* Refresh cookie secret */
- default:
- bad_case(kind);
- }
- event_schedule(kind, delay, st);
- }
-
- /* tell whack and log of progress */
- {
- const char *story = state_story[st->st_state];
- enum rc_type w = RC_NEW_STATE + st->st_state;
- char sadetails[128];
-
- sadetails[0]='\0';
-
- if (IS_IPSEC_SA_ESTABLISHED(st->st_state))
- {
- char *b = sadetails;
- const char *ini = " {";
- const char *fin = "";
-
- /* -1 is to leave space for "fin" */
-
- if (st->st_esp.present)
- {
- snprintf(b, sizeof(sadetails)-(b-sadetails)-1
- , "%sESP=>0x%08x <0x%08x"
- , ini
- , ntohl(st->st_esp.attrs.spi)
- , ntohl(st->st_esp.our_spi));
- ini = " ";
- fin = "}";
- }
- /* advance b to end of string */
- b = b + strlen(b);
-
- if (st->st_ah.present)
- {
- snprintf(b, sizeof(sadetails)-(b-sadetails)-1
- , "%sAH=>0x%08x <0x%08x"
- , ini
- , ntohl(st->st_ah.attrs.spi)
- , ntohl(st->st_ah.our_spi));
- ini = " ";
- fin = "}";
- }
- /* advance b to end of string */
- b = b + strlen(b);
-
- if (st->st_ipcomp.present)
- {
- snprintf(b, sizeof(sadetails)-(b-sadetails)-1
- , "%sIPCOMP=>0x%08x <0x%08x"
- , ini
- , ntohl(st->st_ipcomp.attrs.spi)
- , ntohl(st->st_ipcomp.our_spi));
- ini = " ";
- fin = "}";
- }
- /* advance b to end of string */
- b = b + strlen(b);
-
- if (st->nat_traversal)
- {
- char oa[ADDRTOT_BUF];
- addrtot(&st->nat_oa, 0, oa, sizeof(oa));
- snprintf(b, sizeof(sadetails)-(b-sadetails)-1
- , "%sNATOA=%s"
- , ini, oa);
- ini = " ";
- fin = "}";
- }
-
- /* advance b to end of string */
- b = b + strlen(b);
-
- if (st->st_dpd)
- {
- snprintf(b, sizeof(sadetails)-(b-sadetails)-1
- , "%sDPD"
- , ini);
- ini = " ";
- fin = "}";
- }
-
- strcat(b, fin);
- }
-
- if (IS_ISAKMP_SA_ESTABLISHED(st->st_state)
- || IS_IPSEC_SA_ESTABLISHED(st->st_state))
- {
- /* log our success */
- plog("%s%s", story, sadetails);
- w = RC_SUCCESS;
- }
-
- /* tell whack our progress */
- whack_log(w
- , "%s: %s%s"
- , enum_name(&state_names, st->st_state)
- , story, sadetails);
- }
-
- has_xauth_policy = (st->st_connection->policy
- & (POLICY_XAUTH_RSASIG | POLICY_XAUTH_PSK))
- != LEMPTY;
- is_xauth_server = (st->st_connection->policy
- & POLICY_XAUTH_SERVER)
- != LEMPTY;
-
- /* Should we start XAUTH as a server */
- if (has_xauth_policy && is_xauth_server
- && IS_ISAKMP_SA_ESTABLISHED(st->st_state)
- && !st->st_xauth.started)
- {
- DBG(DBG_CONTROL,
- DBG_log("starting XAUTH server")
- )
- xauth_send_request(st);
- break;
- }
-
- /* Wait for XAUTH request from server */
- if (has_xauth_policy && !is_xauth_server
- && IS_ISAKMP_SA_ESTABLISHED(st->st_state)
- && !st->st_xauth.started)
- {
- DBG(DBG_CONTROL,
- DBG_log("waiting for XAUTH request from server")
- )
- break;
- }
-
- /* Should we start ModeConfig as a client? */
- if (st->st_connection->spd.this.modecfg
- && IS_ISAKMP_SA_ESTABLISHED(st->st_state)
- && !(st->st_connection->policy & POLICY_MODECFG_PUSH)
- && !st->st_modecfg.started)
- {
- DBG(DBG_CONTROL,
- DBG_log("starting ModeCfg client in pull mode")
- )
- modecfg_send_request(st);
- break;
- }
-
- /* Should we start ModeConfig as a server? */
- if (st->st_connection->spd.that.modecfg
- && IS_ISAKMP_SA_ESTABLISHED(st->st_state)
- && !st->st_modecfg.started
- && (st->st_connection->policy & POLICY_MODECFG_PUSH))
- {
- DBG(DBG_CONTROL,
- DBG_log("starting ModeCfg server in push mode")
- )
- modecfg_send_set(st);
- break;
- }
-
- /* Wait for ModeConfig set from server */
- if (st->st_connection->spd.this.modecfg
- && IS_ISAKMP_SA_ESTABLISHED(st->st_state)
- && !st->st_modecfg.vars_set)
- {
- DBG(DBG_CONTROL,
- DBG_log("waiting for ModeCfg set from server")
- )
- break;
- }
-
- if (smc->flags & SMF_RELEASE_PENDING_P2)
- {
- /* Initiate any Quick Mode negotiations that
- * were waiting to piggyback on this Keying Channel.
- *
- * ??? there is a potential race condition
- * if we are the responder: the initial Phase 2
- * message might outrun the final Phase 1 message.
- * I think that retransmission will recover.
- */
- unpend(st);
- }
-
- if (IS_ISAKMP_SA_ESTABLISHED(st->st_state)
- || IS_IPSEC_SA_ESTABLISHED(st->st_state))
- release_whack(st);
- break;
-
- case STF_INTERNAL_ERROR:
- whack_log(RC_INTERNALERR + md->note
- , "%s: internal error"
- , enum_name(&state_names, st->st_state));
-
- DBG(DBG_CONTROL,
- DBG_log("state transition function for %s had internal error"
- , enum_name(&state_names, from_state)));
- break;
-
- default: /* a shortcut to STF_FAIL, setting md->note */
- passert(result > STF_FAIL);
- md->note = result - STF_FAIL;
- result = STF_FAIL;
- /* FALL THROUGH ... */
- case STF_FAIL:
- /* As it is, we act as if this message never happened:
- * whatever retrying was in place, remains in place.
- */
- whack_log(RC_NOTIFICATION + md->note
- , "%s: %s"
- , enum_name(&state_names, (st == NULL)? STATE_MAIN_R0:st->st_state)
- , enum_name(&notification_names, md->note));
-
- SEND_NOTIFICATION(md->note);
-
- DBG(DBG_CONTROL,
- DBG_log("state transition function for %s failed: %s"
- , enum_name(&state_names, from_state)
- , enum_name(&notification_names, md->note)));
- break;
- }
-}
diff --git a/src/pluto/demux.h b/src/pluto/demux.h
deleted file mode 100644
index 6ce53c14f..000000000
--- a/src/pluto/demux.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/* demultiplex incoming IKE messages
- * Copyright (C) 1998-2002 D. Hugh Redelmeier.
- *
- * 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.
- */
-
-#ifndef _DEMUX_H
-#define _DEMUX_H
-
-#include "packet.h"
-#include "state.h"
-
-extern void init_demux(void);
-extern bool send_packet(struct state *st, const char *where);
-extern void comm_handle(const struct iface *ifp);
-
-extern u_int8_t reply_buffer[MAX_OUTPUT_UDP_SIZE];
-
-/* State transition function infrastructure
- *
- * com_handle parses a message, decides what state object it applies to,
- * and calls the appropriate state transition function (STF).
- * These declarations define the interface to these functions.
- *
- * Each STF must be able to be restarted up to any failure point:
- * a later message will cause the state to be re-entered. This
- * explains the use of the replace macro and the care in handling
- * MP_INT members of struct state.
- */
-
-struct payload_digest {
- pb_stream pbs;
- union payload payload;
- struct payload_digest *next; /* of same kind */
-};
-
-/* message digest
- * Note: raw_packet and packet_pbs are "owners" of space on heap.
- */
-
-struct msg_digest {
- struct msg_digest *next; /* for free list */
- chunk_t raw_packet; /* if encrypted, received packet before decryption */
- const struct iface *iface; /* interface on which message arrived */
- ip_address sender; /* where message came from */
- u_int16_t sender_port; /* host order */
- pb_stream packet_pbs; /* whole packet */
- pb_stream message_pbs; /* message to be processed */
- struct isakmp_hdr hdr; /* message's header */
- bool encrypted; /* was it encrypted? */
- enum state_kind from_state; /* state we started in */
- const struct state_microcode *smc; /* microcode for initial state */
- struct state *st; /* current state object */
- pb_stream reply; /* room for reply */
- pb_stream rbody; /* room for reply body (after header) */
- notification_t note; /* reason for failure */
- bool dpd; /* peer supports RFC 3706 DPD */
- bool openpgp; /* peer supports OpenPGP certificates */
- bool ms_nt5; /* peer is a windows 2000+ host */
-
-# define PAYLIMIT 40
- struct payload_digest
- digest[PAYLIMIT],
- *digest_roof,
- *chain[ISAKMP_NEXT_ROOF];
- unsigned short nat_traversal_vid;
-};
-
-extern void release_md(struct msg_digest *md);
-
-/* status for state-transition-function
- * Note: STF_FAIL + notification_t means fail with that notification
- */
-
-typedef enum {
- STF_IGNORE, /* don't respond */
- STF_SUSPEND, /* unfinished -- don't release resources */
- STF_OK, /* success */
- STF_INTERNAL_ERROR, /* discard everything, we failed */
- STF_FAIL /* discard everything, something failed. notification_t added. */
-} stf_status;
-
-typedef stf_status state_transition_fn(struct msg_digest *md);
-
-extern void complete_state_transition(struct msg_digest **mdp, stf_status result);
-
-extern void free_md_pool(void);
-
-#endif /* _DEMUX_H */
diff --git a/src/pluto/dnskey.c b/src/pluto/dnskey.c
deleted file mode 100644
index 91b1b6ac1..000000000
--- a/src/pluto/dnskey.c
+++ /dev/null
@@ -1,1590 +0,0 @@
-/* Find public key in DNS
- * Copyright (C) 2000-2002 D. Hugh Redelmeier.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/nameser.h>
-#include <resolv.h>
-#include <netdb.h> /* ??? for h_errno */
-#include <sys/queue.h>
-
-#include <freeswan.h>
-
-#include <utils/identification.h>
-#include <credentials/keys/public_key.h>
-
-#include "constants.h"
-#include "adns.h" /* needs <resolv.h> */
-#include "defs.h"
-#include "log.h"
-#include "myid.h"
-#include "connections.h"
-#include "keys.h" /* needs connections.h */
-#include "dnskey.h"
-#include "packet.h"
-#include "timer.h"
-
-/* somebody has to decide */
-#define MAX_TXT_RDATA ((MAX_KEY_BYTES * 8 / 6) + 40) /* somewhat arbitrary overkill */
-
-/* ADNS stuff */
-
-int adns_qfd = NULL_FD, /* file descriptor for sending queries to adns (O_NONBLOCK) */
- adns_afd = NULL_FD; /* file descriptor for receiving answers from adns */
-static pid_t adns_pid = 0;
-const char *pluto_adns_option = NULL; /* path from --pluto_adns */
-
-int adns_restart_count;
-#define ADNS_RESTART_MAX 20
-
-void
-init_adns(void)
-{
- const char *adns_path = pluto_adns_option;
- static const char adns_name[] = "_pluto_adns";
- const char *helper_bin_dir = getenv("IPSEC_LIBDIR");
- char adns_path_space[4096]; /* plenty long? */
- int qfds[2];
- int afds[2];
-
- /* find a pathname to the ADNS program */
- if (adns_path == NULL)
- {
- /* pathname was not specified as an option: build it.
- * First, figure out the directory to be used.
- */
- ssize_t n;
-
- if (helper_bin_dir != NULL)
- {
- n = strlen(helper_bin_dir);
- if ((size_t)n <= sizeof(adns_path_space) - sizeof(adns_name))
- {
- strcpy(adns_path_space, helper_bin_dir);
- if (n > 0 && adns_path_space[n -1] != '/')
- {
- adns_path_space[n++] = '/';
- }
- }
- }
- else
- {
- /* The program will be in the same directory as Pluto,
- * so we use the sympolic link /proc/self/exe to
- * tell us of the path prefix.
- */
- n = readlink("/proc/self/exe", adns_path_space, sizeof(adns_path_space));
-
- if (n < 0)
- {
- exit_log_errno((e
- , "readlink(\"/proc/self/exe\") failed in init_adns()"));
- }
- }
-
- if ((size_t)n > sizeof(adns_path_space) - sizeof(adns_name))
- {
- exit_log("path to %s is too long", adns_name);
- }
-
- while (n > 0 && adns_path_space[n - 1] != '/')
- {
- n--;
- }
- strcpy(adns_path_space + n, adns_name);
- adns_path = adns_path_space;
- }
- if (access(adns_path, X_OK) < 0)
- {
- exit_log_errno((e, "%s missing or not executable", adns_path));
- }
-
- if (pipe(qfds) != 0 || pipe(afds) != 0)
- {
- exit_log_errno((e, "pipe(2) failed in init_adns()"));
- }
-
- adns_pid = fork();
- switch (adns_pid)
- {
- case -1:
- exit_log_errno((e, "fork() failed in init_adns()"));
-
- case 0:
- /* child */
- {
- /* Make stdin and stdout our pipes.
- * Take care to handle case where pipes already use these fds.
- */
- if (afds[1] == 0)
- {
- afds[1] = dup(afds[1]); /* avoid being overwritten */
- }
- if (qfds[0] != 0)
- {
- dup2(qfds[0], 0);
- close(qfds[0]);
- }
- if (afds[1] != 1)
- {
- dup2(afds[1], 1);
- close(qfds[1]);
- }
- if (afds[0] > 1)
- {
- close(afds[0]);
- }
- if (afds[1] > 1)
- {
- close(afds[1]);
- }
- DBG(DBG_DNS, execlp(adns_path, adns_name, "-d", NULL));
-
- execlp(adns_path, adns_name, NULL);
- exit_log_errno((e, "execlp of %s failed", adns_path));
- }
- default:
- /* parent */
- close(qfds[0]);
- adns_qfd = qfds[1];
- adns_afd = afds[0];
- close(afds[1]);
- fcntl(adns_qfd, F_SETFD, FD_CLOEXEC);
- fcntl(adns_afd, F_SETFD, FD_CLOEXEC);
- fcntl(adns_qfd, F_SETFL, O_NONBLOCK);
- break;
- }
-}
-
-void
-stop_adns(void)
-{
- close_any(adns_qfd);
- adns_qfd = NULL_FD;
- close_any(adns_afd);
- adns_afd = NULL_FD;
-
- if (adns_pid != 0)
- {
- int status;
- pid_t p = waitpid(adns_pid, &status, 0);
-
- if (p == -1)
- {
- log_errno((e, "waitpid for ADNS process failed"));
- }
- else if (WIFEXITED(status))
- {
- if (WEXITSTATUS(status) != 0)
- {
- plog("ADNS process exited with status %d"
- , (int) WEXITSTATUS(status));
- }
- }
- else if (WIFSIGNALED(status))
- {
- plog("ADNS process terminated by signal %d", (int)WTERMSIG(status));
- }
- else
- {
- plog("wait for end of ADNS process returned odd status 0x%x\n"
- , status);
- }
- }
-}
-
-
-
-/* tricky macro to pass any hot potato */
-#define TRY(x) { err_t ugh = x; if (ugh != NULL) return ugh; }
-
-
-/* Process TXT X-IPsec-Server record, accumulating relevant ones
- * in cr->gateways_from_dns, a list sorted by "preference".
- *
- * Format of TXT record body: X-IPsec-Server ( nnn ) = iii kkk
- * nnn is a 16-bit unsigned integer preference
- * iii is @FQDN or dotted-decimal IPv4 address or colon-hex IPv6 address
- * kkk is an optional RSA public signing key in base 64.
- *
- * NOTE: we've got to be very wary of anything we find -- bad guys
- * might have prepared it.
- */
-
-#define our_TXT_attr_string "X-IPsec-Server"
-static const char our_TXT_attr[] = our_TXT_attr_string;
-
-identification_t* decode_iii(u_char **pp)
-{
- identification_t *gw_id;
- u_char *p = *pp + strspn(*pp, " \t");
- u_char *e = p + strcspn(p, " \t");
- u_char under = *e;
-
- if (p == e)
- {
- return NULL;
- }
- *e = '\0';
- gw_id = identification_create_from_string(p);
- *e = under;
- *pp = e + strspn(e, " \t");
-
- return gw_id;
-}
-
-static err_t process_txt_rr_body(u_char *str, bool doit,
- enum dns_auth_level dns_auth_level,
- struct adns_continuation *const cr)
-{
- identification_t *client_id = cr->id; /* subject of query */
- u_char *p = str;
- unsigned long pref = 0;
- struct gw_info gi;
-
- p += strspn(p, " \t"); /* ignore leading whitespace */
-
- /* is this for us? */
- if (strncasecmp(p, our_TXT_attr, sizeof(our_TXT_attr)-1) != 0)
- {
- return NULL; /* neither interesting nor bad */
- }
-
- p += sizeof(our_TXT_attr) - 1; /* ignore our attribute name */
- p += strspn(p, " \t"); /* ignore leading whitespace */
-
- /* decode '(' nnn ')' */
- if (*p != '(')
- {
- return "X-IPsec-Server missing '('";
- }
-
- {
- char *e;
-
- p++;
- pref = strtoul(p, &e, 0);
- if ((u_char *)e == p)
- {
- return "malformed X-IPsec-Server priority";
- }
- p = e + strspn(e, " \t");
-
- if (*p != ')')
- {
- return "X-IPsec-Server priority missing ')'";
- }
- p++;
- p += strspn(p, " \t");
-
- if (pref > 0xFFFF)
- {
- return "X-IPsec-Server priority larger than 0xFFFF";
- }
- }
-
- /* time for '=' */
-
- if (*p != '=')
- {
- return "X-IPsec-Server priority missing '='";
- }
- p++;
- p += strspn(p, " \t");
-
- /* Decode iii (Security Gateway ID). */
- zero(&gi); /* before first use */
-
- gi.gw_id = decode_iii(&p);
- if (gi.gw_id == NULL)
- {
- return "TXT " our_TXT_attr_string " badly formed (no gateway specified)";
- }
-
- if (!cr->sgw_specified)
- {
- /* we don't know the peer's ID (because we are initiating
- * and we don't know who to initiate with.
- * So we're looking for gateway specs with an IP address
- */
- if (gi.gw_id->get_type(gi.gw_id) != ID_IPV4_ADDR &&
- gi.gw_id->get_type(gi.gw_id) != ID_IPV6_ADDR)
- {
- DBG(DBG_DNS,
- DBG_log("TXT %s record for '%Y': security gateway '%Y';"
- " ignored because gateway's IP is unspecified",
- our_TXT_attr, client_id, gi.gw_id);
- )
- return NULL; /* we cannot use this record, but it isn't wrong */
- }
- }
- else
- {
- /* We do know the peer's ID (because we are responding)
- * So we're looking for gateway specs specifying this known ID.
- */
- identification_t *peer_id = cr->sgw_id;
-
- if (!peer_id->equals(peer_id, gi.gw_id))
- {
- DBG(DBG_DNS,
- DBG_log("TXT %s record for '%Y': security gateway '%Y';"
- " ignored -- looking to confirm '%Y' as gateway",
- our_TXT_attr, client_id, gi.gw_id, peer_id);
- )
- return NULL; /* we cannot use this record, but it isn't wrong */
- }
- }
-
- if (doit)
- {
- /* really accept gateway */
- struct gw_info **gwip; /* gateway insertion point */
-
- gi.client_id = client_id; /* will need to unshare_id_content */
-
- /* decode optional kkk: base 64 encoding of key */
-
- gi.gw_key_present = *p != '\0';
- if (gi.gw_key_present)
- {
- /* Decode base 64 encoding of key.
- * Similar code is in process_lwdnsq_key.
- */
- u_char buf[RSA_MAX_ENCODING_BYTES]; /* plenty of space for binary form of public key */
- size_t sz;
- err_t ugh;
- chunk_t rfc3110_chunk;
- public_key_t *key;
-
- ugh = ttodatav(p, 0, 64, buf, sizeof(buf), &sz,
- diag_space, sizeof(diag_space), TTODATAV_SPACECOUNTS);
- if (ugh)
- {
- return builddiag("malformed key data: %s", ugh);
- }
- if (sz > sizeof(buf))
- {
- return builddiag("key data larger than %lu bytes",
- (unsigned long) sizeof(buf));
- }
- rfc3110_chunk = chunk_create(buf, sz);
- key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
- BUILD_BLOB_DNSKEY, rfc3110_chunk,
- BUILD_END);
- if (key == NULL)
- {
- return builddiag("invalid key data");
- }
-
- /* now find a key entry to put it in */
- gi.key = public_key_from_rsa(key);
-
- unreference_key(&cr->last_info);
- cr->last_info = reference_key(gi.key);
- }
-
- /* we're home free! Allocate everything and add to gateways list. */
- gi.refcnt = 1;
- gi.pref = pref;
- gi.key->dns_auth_level = dns_auth_level;
- gi.key->last_tried_time = gi.key->last_worked_time = NO_TIME;
-
- /* find insertion point */
- for (gwip = &cr->gateways_from_dns; *gwip != NULL && (*gwip)->pref < pref; gwip = &(*gwip)->next)
- ;
-
- DBG(DBG_DNS,
- {
- chunk_t keyid;
- public_key_t *key = gi.key->public_key;
-
- if (gi.gw_key_present &&
- key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &keyid))
- {
- DBG_log("gateway for %s is %s with key %#B",
- client_id, gi.gw_id, &keyid);
- }
- else
- {
- DBG_log("gateway for '%Y' is '%Y'; no key specified",
- client_id, gi.gw_id);
- }
- });
-
- gi.next = *gwip;
- *gwip = clone_thing(gi);
- (*gwip)->gw_id = (*gwip)->gw_id->clone((*gwip)->gw_id);
- (*gwip)->client_id = (*gwip)->client_id->clone((*gwip)->client_id);
- }
-
- return NULL;
-}
-
-static const char *
-rr_typename(int type)
-{
- switch (type)
- {
- case T_TXT:
- return "TXT";
- case T_KEY:
- return "KEY";
- default:
- return "???";
- }
-}
-
-
-/* structure of Query Reply (RFC 1035 4.1.1):
- *
- * +---------------------+
- * | Header |
- * +---------------------+
- * | Question | the question for the name server
- * +---------------------+
- * | Answer | RRs answering the question
- * +---------------------+
- * | Authority | RRs pointing toward an authority
- * +---------------------+
- * | Additional | RRs holding additional information
- * +---------------------+
- */
-
-/* Header section format (as modified by RFC 2535 6.1):
- * 1 1 1 1 1 1
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- * | ID |
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- * |QR| Opcode |AA|TC|RD|RA| Z|AD|CD| RCODE |
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- * | QDCOUNT |
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- * | ANCOUNT |
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- * | NSCOUNT |
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- * | ARCOUNT |
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- */
-struct qr_header {
- u_int16_t id; /* 16-bit identifier to match query */
-
- u_int16_t stuff; /* packed crud: */
-
-#define QRS_QR 0x8000 /* QR: on if this is a response */
-
-#define QRS_OPCODE_SHIFT 11 /* OPCODE field */
-#define QRS_OPCODE_MASK 0xF
-#define QRSO_QUERY 0 /* standard query */
-#define QRSO_IQUERY 1 /* inverse query */
-#define QRSO_STATUS 2 /* server status request query */
-
-#define QRS_AA 0x0400 /* AA: on if Authoritative Answer */
-#define QRS_TC 0x0200 /* TC: on if truncation happened */
-#define QRS_RD 0x0100 /* RD: on if recursion desired */
-#define QRS_RA 0x0080 /* RA: on if recursion available */
-#define QRS_Z 0x0040 /* Z: reserved; must be zero */
-#define QRS_AD 0x0020 /* AD: on if authentic data (RFC 2535) */
-#define QRS_CD 0x0010 /* AD: on if checking disabled (RFC 2535) */
-
-#define QRS_RCODE_SHIFT 0 /* RCODE field: response code */
-#define QRS_RCODE_MASK 0xF
-#define QRSR_OK 0
-
-
- u_int16_t qdcount; /* number of entries in question section */
- u_int16_t ancount; /* number of resource records in answer section */
- u_int16_t nscount; /* number of name server resource records in authority section */
- u_int16_t arcount; /* number of resource records in additional records section */
-};
-
-static field_desc qr_header_fields[] = {
- { ft_nat, 16/BITS_PER_BYTE, "ID", NULL },
- { ft_nat, 16/BITS_PER_BYTE, "stuff", NULL },
- { ft_nat, 16/BITS_PER_BYTE, "QD Count", NULL },
- { ft_nat, 16/BITS_PER_BYTE, "Answer Count", NULL },
- { ft_nat, 16/BITS_PER_BYTE, "Authority Count", NULL },
- { ft_nat, 16/BITS_PER_BYTE, "Additional Count", NULL },
- { ft_end, 0, NULL, NULL }
-};
-
-static struct_desc qr_header_desc = {
- "Query Response Header",
- qr_header_fields,
- sizeof(struct qr_header)
-};
-
-/* Messages for codes in RCODE (see RFC 1035 4.1.1) */
-static const err_t rcode_text[QRS_RCODE_MASK + 1] = {
- NULL, /* not an error */
- "Format error - The name server was unable to interpret the query",
- "Server failure - The name server was unable to process this query"
- " due to a problem with the name server",
- "Name Error - Meaningful only for responses from an authoritative name"
- " server, this code signifies that the domain name referenced in"
- " the query does not exist",
- "Not Implemented - The name server does not support the requested"
- " kind of query",
- "Refused - The name server refuses to perform the specified operation"
- " for policy reasons",
- /* the rest are reserved for future use */
- };
-
-/* throw away a possibly compressed domain name */
-
-static err_t
-eat_name(pb_stream *pbs)
-{
- u_char name_buf[NS_MAXDNAME + 2];
- u_char *ip = pbs->cur;
- unsigned oi = 0;
- unsigned jump_count = 0;
-
- for (;;)
- {
- u_int8_t b;
-
- if (ip >= pbs->roof)
- return "ran out of message while skipping domain name";
-
- b = *ip++;
- if (jump_count == 0)
- pbs->cur = ip;
-
- if (b == 0)
- break;
-
- switch (b & 0xC0)
- {
- case 0x00:
- /* we grab the next b characters */
- if (oi + b > NS_MAXDNAME)
- return "domain name too long";
-
- if (pbs->roof - ip <= b)
- return "domain name falls off end of message";
-
- if (oi != 0)
- name_buf[oi++] = '.';
-
- memcpy(name_buf + oi, ip, b);
- oi += b;
- ip += b;
- if (jump_count == 0)
- pbs->cur = ip;
- break;
-
- case 0xC0:
- {
- unsigned ix;
-
- if (ip >= pbs->roof)
- return "ran out of message in middle of compressed domain name";
-
- ix = ((b & ~0xC0u) << 8) | *ip++;
- if (jump_count == 0)
- pbs->cur = ip;
-
- if (ix >= pbs_room(pbs))
- return "impossible compressed domain name";
-
- /* Avoid infinite loop.
- * There can be no more jumps than there are bytes
- * in the packet. Not a tight limit, but good enough.
- */
- jump_count++;
- if (jump_count > pbs_room(pbs))
- return "loop in compressed domain name";
-
- ip = pbs->start + ix;
- }
- break;
-
- default:
- return "invalid code in label";
- }
- }
-
- name_buf[oi++] = '\0';
-
- DBG(DBG_DNS, DBG_log("skipping name %s", name_buf));
-
- return NULL;
-}
-
-static err_t
-eat_name_helpfully(pb_stream *pbs, const char *context)
-{
- err_t ugh = eat_name(pbs);
-
- return ugh == NULL? ugh
- : builddiag("malformed name within DNS record of %s: %s", context, ugh);
-}
-
-/* non-variable part of 4.1.2 Question Section entry:
- * 1 1 1 1 1 1
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- * | |
- * / QNAME /
- * / /
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- * | QTYPE |
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- * | QCLASS |
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- */
-
-struct qs_fixed {
- u_int16_t qtype;
- u_int16_t qclass;
-};
-
-static field_desc qs_fixed_fields[] = {
- { ft_loose_enum, 16/BITS_PER_BYTE, "QTYPE", &rr_qtype_names },
- { ft_loose_enum, 16/BITS_PER_BYTE, "QCLASS", &rr_class_names },
- { ft_end, 0, NULL, NULL }
-};
-
-static struct_desc qs_fixed_desc = {
- "Question Section entry fixed part",
- qs_fixed_fields,
- sizeof(struct qs_fixed)
-};
-
-/* 4.1.3. Resource record format:
- * 1 1 1 1 1 1
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- * | |
- * / /
- * / NAME /
- * | |
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- * | TYPE |
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- * | CLASS |
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- * | TTL |
- * | |
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- * | RDLENGTH |
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
- * / RDATA /
- * / /
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- */
-
-struct rr_fixed {
- u_int16_t type;
- u_int16_t class;
- u_int32_t ttl; /* actually signed */
- u_int16_t rdlength;
-};
-
-
-static field_desc rr_fixed_fields[] = {
- { ft_loose_enum, 16/BITS_PER_BYTE, "type", &rr_type_names },
- { ft_loose_enum, 16/BITS_PER_BYTE, "class", &rr_class_names },
- { ft_nat, 32/BITS_PER_BYTE, "TTL", NULL },
- { ft_nat, 16/BITS_PER_BYTE, "RD length", NULL },
- { ft_end, 0, NULL, NULL }
-};
-
-static struct_desc rr_fixed_desc = {
- "Resource Record fixed part",
- rr_fixed_fields,
- /* note: following is tricky: avoids padding problems */
- offsetof(struct rr_fixed, rdlength) + sizeof(u_int16_t)
-};
-
-/* RFC 1035 3.3.14: TXT RRs have text in the RDATA field.
- * It is in the form of a sequence of <character-string>s as described in 3.3.
- * unpack_txt_rdata() deals with this peculiar representation.
- */
-
-/* RFC 2535 3.1 KEY RDATA format:
- *
- * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 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
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | flags | protocol | algorithm |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | /
- * / public key /
- * / /
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
- */
-
-struct key_rdata {
- u_int16_t flags;
- u_int8_t protocol;
- u_int8_t algorithm;
-};
-
-static field_desc key_rdata_fields[] = {
- { ft_nat, 16/BITS_PER_BYTE, "flags", NULL },
- { ft_nat, 8/BITS_PER_BYTE, "protocol", NULL },
- { ft_nat, 8/BITS_PER_BYTE, "algorithm", NULL },
- { ft_end, 0, NULL, NULL }
-};
-
-static struct_desc key_rdata_desc = {
- "KEY RR RData fixed part",
- key_rdata_fields,
- sizeof(struct key_rdata)
-};
-
-/* RFC 2535 4.1 SIG RDATA format:
- *
- * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 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
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | type covered | algorithm | labels |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | original TTL |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | signature expiration |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | signature inception |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | key tag | |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ signer's name +
- * | /
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-/
- * / /
- * / signature /
- * / /
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-
-struct sig_rdata {
- u_int16_t type_covered;
- u_int8_t algorithm;
- u_int8_t labels;
- u_int32_t original_ttl;
- u_int32_t sig_expiration;
- u_int32_t sig_inception;
- u_int16_t key_tag;
-};
-
-static field_desc sig_rdata_fields[] = {
- { ft_nat, 16/BITS_PER_BYTE, "type_covered", NULL},
- { ft_nat, 8/BITS_PER_BYTE, "algorithm", NULL},
- { ft_nat, 8/BITS_PER_BYTE, "labels", NULL},
- { ft_nat, 32/BITS_PER_BYTE, "original ttl", NULL},
- { ft_nat, 32/BITS_PER_BYTE, "sig expiration", NULL},
- { ft_nat, 32/BITS_PER_BYTE, "sig inception", NULL},
- { ft_nat, 16/BITS_PER_BYTE, "key tag", NULL},
- { ft_end, 0, NULL, NULL }
-};
-
-static struct_desc sig_rdata_desc = {
- "SIG RR RData fixed part",
- sig_rdata_fields,
- sizeof(struct sig_rdata)
-};
-
-/* handle a KEY Resource Record. */
-
-#ifdef USE_KEYRR
-static err_t
-process_key_rr(u_char *ptr, size_t len
-, bool doit /* should we capture information? */
-, enum dns_auth_level dns_auth_level
-, struct adns_continuation *const cr)
-{
- pb_stream pbs;
- struct key_rdata kr;
-
- if (len < sizeof(struct key_rdata))
- return "KEY Resource Record's RD Length is too small";
-
- init_pbs(&pbs, ptr, len, "KEY RR");
-
- if (!in_struct(&kr, &key_rdata_desc, &pbs, NULL))
- return "failed to get fixed part of KEY Resource Record RDATA";
-
- if (kr.protocol == 4 /* IPSEC (RFC 2535 3.1.3) */
- && kr.algorithm == 1 /* RSA/MD5 (RFC 2535 3.2) */
- && (kr.flags & 0x8000) == 0 /* use for authentication (3.1.2) */
- && (kr.flags & 0x2CF0) == 0) /* must be zero */
- {
- /* we have what seems to be a tasty key */
-
- if (doit)
- {
- chunk_t k = { pbs.cur, pbs_left(&pbs) };
-
- TRY(add_public_key(&cr->id, dns_auth_level, PUBKEY_ALG_RSA, &k
- , &cr->keys_from_dns));
- }
- }
- return NULL;
-}
-#endif /* USE_KEYRR */
-
-
-/* unpack TXT rr RDATA into C string.
- * A sequence of <character-string>s as described in RFC 1035 3.3.
- * We concatenate them.
- */
-static err_t
-unpack_txt_rdata(u_char *d, size_t dlen, const u_char *s, size_t slen)
-{
- size_t i = 0
- , o = 0;
-
- while (i < slen)
- {
- size_t cl = s[i++];
-
- if (i + cl > slen)
- return "TXT rr RDATA representation malformed";
-
- if (o + cl >= dlen)
- return "TXT rr RDATA too large";
-
- memcpy(d + o, s + i, cl);
- i += cl;
- o += cl;
- }
- d[o] = '\0';
- if (strlen(d) != o)
- return "TXT rr RDATA contains a NUL";
-
- return NULL;
-}
-
-static err_t
-process_txt_rr(u_char *rdata, size_t rdlen
-, bool doit /* should we capture information? */
-, enum dns_auth_level dns_auth_level
-, struct adns_continuation *const cr)
-{
- u_char str[RSA_MAX_ENCODING_BYTES * 8 / 6 + 20]; /* space for unpacked RDATA */
-
- TRY(unpack_txt_rdata(str, sizeof(str), rdata, rdlen));
- return process_txt_rr_body(str, doit, dns_auth_level, cr);
-}
-
-static err_t
-process_answer_section(pb_stream *pbs
-, bool doit /* should we capture information? */
-, enum dns_auth_level *dns_auth_level
-, u_int16_t ancount /* number of RRs in the answer section */
-, struct adns_continuation *const cr)
-{
- const int type = cr->query.type; /* type of RR of interest */
- unsigned c;
-
- DBG(DBG_DNS, DBG_log("*Answer Section:"));
-
- for (c = 0; c != ancount; c++)
- {
- struct rr_fixed rrf;
- size_t tail;
-
- /* ??? do we need to match the name? */
-
- TRY(eat_name_helpfully(pbs, "Answer Section"));
-
- if (!in_struct(&rrf, &rr_fixed_desc, pbs, NULL))
- return "failed to get fixed part of Answer Section Resource Record";
-
- if (rrf.rdlength > pbs_left(pbs))
- return "RD Length extends beyond end of message";
-
- /* ??? should we care about ttl? */
-
- tail = rrf.rdlength;
-
- if (rrf.type == type && rrf.class == C_IN)
- {
- err_t ugh = NULL;
-
- switch (type)
- {
-#ifdef USE_KEYRR
- case T_KEY:
- ugh = process_key_rr(pbs->cur, tail, doit, *dns_auth_level, cr);
- break;
-#endif /* USE_KEYRR */
- case T_TXT:
- ugh = process_txt_rr(pbs->cur, tail, doit, *dns_auth_level, cr);
- break;
- case T_SIG:
- /* Check if SIG RR authenticates what we are learning.
- * The RRset covered by a SIG must have the same owner,
- * class, and type.
- * For us, the class is always C_IN, so that matches.
- * We decode the SIG RR's fixed part to check
- * that the type_covered field matches our query type
- * (this may be redundant).
- * We don't check the owner (apparently this is the
- * name on the record) -- we assume that it matches
- * or we would not have been given this SIG in the
- * Answer Section.
- *
- * We only look on first pass, and only if we've something
- * to learn. This cuts down on useless decoding.
- */
- if (!doit && *dns_auth_level == DAL_UNSIGNED)
- {
- struct sig_rdata sr;
-
- if (!in_struct(&sr, &sig_rdata_desc, pbs, NULL))
- ugh = "failed to get fixed part of SIG Resource Record RDATA";
- else if (sr.type_covered == type)
- *dns_auth_level = DAL_SIGNED;
- }
- break;
- default:
- ugh = builddiag("unexpected RR type %d", type);
- break;
- }
- if (ugh != NULL)
- return ugh;
- }
- in_raw(NULL, tail, pbs, "RR RDATA");
- }
-
- return doit
- && cr->gateways_from_dns == NULL
-#ifdef USE_KEYRR
- && cr->keys_from_dns == NULL
-#endif /* USE_KEYRR */
- ? builddiag("no suitable %s record found in DNS", rr_typename(type))
- : NULL;
-}
-
-/* process DNS answer -- TXT or KEY query */
-
-static err_t
-process_dns_answer(struct adns_continuation *const cr
-, u_char ans[], int anslen)
-{
- const int type = cr->query.type; /* type of record being sought */
- int r; /* all-purpose return value holder */
- u_int16_t c; /* number of current RR in current answer section */
- pb_stream pbs;
- u_int8_t *ans_start; /* saved position of answer section */
- struct qr_header qr_header;
- enum dns_auth_level dns_auth_level;
-
- init_pbs(&pbs, ans, anslen, "Query Response Message");
-
- /* decode and check header */
-
- if (!in_struct(&qr_header, &qr_header_desc, &pbs, NULL))
- return "malformed header";
-
- /* ID: nothing to do with us */
-
- /* stuff -- lots of things */
- if ((qr_header.stuff & QRS_QR) == 0)
- return "not a response?!?";
-
- if (((qr_header.stuff >> QRS_OPCODE_SHIFT) & QRS_OPCODE_MASK) != QRSO_QUERY)
- return "unexpected opcode";
-
- /* I don't think we care about AA */
-
- if (qr_header.stuff & QRS_TC)
- return "response truncated";
-
- /* I don't think we care about RD, RA, or CD */
-
- /* AD means "authentic data" */
- dns_auth_level = qr_header.stuff & QRS_AD? DAL_UNSIGNED : DAL_NOTSEC;
-
- if (qr_header.stuff & QRS_Z)
- return "Z bit is not zero";
-
- r = (qr_header.stuff >> QRS_RCODE_SHIFT) & QRS_RCODE_MASK;
- if (r != 0)
- return r < (int)countof(rcode_text)? rcode_text[r] : "unknown rcode";
-
- if (qr_header.ancount == 0)
- return builddiag("no %s RR found by DNS", rr_typename(type));
-
- /* end of header checking */
-
- /* Question Section processing */
-
- /* 4.1.2. Question section format:
- * 1 1 1 1 1 1
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- * | |
- * / QNAME /
- * / /
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- * | QTYPE |
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- * | QCLASS |
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- */
-
- DBG(DBG_DNS, DBG_log("*Question Section:"));
-
- for (c = 0; c != qr_header.qdcount; c++)
- {
- struct qs_fixed qsf;
-
- TRY(eat_name_helpfully(&pbs, "Question Section"));
-
- if (!in_struct(&qsf, &qs_fixed_desc, &pbs, NULL))
- return "failed to get fixed part of Question Section";
-
- if (qsf.qtype != type)
- return "unexpected QTYPE in Question Section";
-
- if (qsf.qclass != C_IN)
- return "unexpected QCLASS in Question Section";
- }
-
- /* rest of sections are made up of Resource Records */
-
- /* Answer Section processing -- error checking, noting T_SIG */
-
- ans_start = pbs.cur; /* remember start of answer section */
-
- TRY(process_answer_section(&pbs, FALSE, &dns_auth_level
- , qr_header.ancount, cr));
-
- /* Authority Section processing (just sanity checking) */
-
- DBG(DBG_DNS, DBG_log("*Authority Section:"));
-
- for (c = 0; c != qr_header.nscount; c++)
- {
- struct rr_fixed rrf;
- size_t tail;
-
- TRY(eat_name_helpfully(&pbs, "Authority Section"));
-
- if (!in_struct(&rrf, &rr_fixed_desc, &pbs, NULL))
- return "failed to get fixed part of Authority Section Resource Record";
-
- if (rrf.rdlength > pbs_left(&pbs))
- return "RD Length extends beyond end of message";
-
- /* ??? should we care about ttl? */
-
- tail = rrf.rdlength;
-
- in_raw(NULL, tail, &pbs, "RR RDATA");
- }
-
- /* Additional Section processing (just sanity checking) */
-
- DBG(DBG_DNS, DBG_log("*Additional Section:"));
-
- for (c = 0; c != qr_header.arcount; c++)
- {
- struct rr_fixed rrf;
- size_t tail;
-
- TRY(eat_name_helpfully(&pbs, "Additional Section"));
-
- if (!in_struct(&rrf, &rr_fixed_desc, &pbs, NULL))
- return "failed to get fixed part of Additional Section Resource Record";
-
- if (rrf.rdlength > pbs_left(&pbs))
- return "RD Length extends beyond end of message";
-
- /* ??? should we care about ttl? */
-
- tail = rrf.rdlength;
-
- in_raw(NULL, tail, &pbs, "RR RDATA");
- }
-
- /* done all sections */
-
- /* ??? is padding legal, or can we complain if more left in record? */
-
- /* process Answer Section again -- accept contents */
-
- pbs.cur = ans_start; /* go back to start of answer section */
-
- return process_answer_section(&pbs, TRUE, &dns_auth_level
- , qr_header.ancount, cr);
-}
-
-/****************************************************************/
-
-static err_t build_dns_name(u_char name_buf[NS_MAXDNAME + 2],
- unsigned long serial USED_BY_DEBUG,
- identification_t *id,
- const char *typename USED_BY_DEBUG,
- identification_t *gw USED_BY_DEBUG)
-{
- /* note: all end in "." to suppress relative searches */
- id = resolve_myid(id);
-
- switch (id->get_type(id))
- {
- case ID_IPV4_ADDR:
- {
- chunk_t b = id->get_encoding(id);
-
- snprintf(name_buf, NS_MAXDNAME + 2, "%d.%d.%d.%d.in-addr.arpa.",
- b.ptr[3], b.ptr[2], b.ptr[1], b.ptr[0]);
- break;
- }
- case ID_IPV6_ADDR:
- {
- chunk_t b = id->get_encoding(id);
- size_t bl;
- u_char *op = name_buf;
- static const char suffix[] = "IP6.INT.";
-
- for (bl = b.len; bl-- != 0; )
- {
- if (op + 4 + sizeof(suffix) >= name_buf + NS_MAXDNAME + 1)
- {
- return "IPv6 reverse name too long";
- }
- op += sprintf(op, "%x.%x.", b.ptr[bl] & 0xF, b.ptr[bl] >> 4);
- }
- strcpy(op, suffix);
- break;
- }
- case ID_FQDN:
- {
- if (snprintf(name_buf, NS_MAXDNAME + 2, "%Y.", id) > NS_MAXDNAME + 1)
- {
- return "FQDN too long for domain name";
- }
- break;
- }
- default:
- return "can only query DNS for key for ID that is a FQDN, IPV4_ADDR, or IPV6_ADDR";
- }
-
- DBG(DBG_CONTROL | DBG_DNS,
- DBG_log("DNS query %lu for %s for %s (gw: %Y)", serial, typename, name_buf, gw)
- )
- return NULL;
-}
-
-void gw_addref(struct gw_info *gw)
-{
- if (gw != NULL)
- {
- DBG(DBG_DNS, DBG_log("gw_addref: %p refcnt: %d++", gw, gw->refcnt))
- gw->refcnt++;
- }
-}
-
-void gw_delref(struct gw_info **gwp)
-{
- struct gw_info *gw = *gwp;
-
- if (gw != NULL)
- {
- DBG(DBG_DNS, DBG_log("gw_delref: %p refcnt: %d--", gw, gw->refcnt));
-
- passert(gw->refcnt != 0);
- gw->refcnt--;
- if (gw->refcnt == 0)
- {
- DESTROY_IF(gw->client_id);
- DESTROY_IF(gw->gw_id);
- if (gw->gw_key_present)
- {
- unreference_key(&gw->key);
- }
- gw_delref(&gw->next);
- free(gw); /* trickery could make this a tail-call */
- }
- *gwp = NULL;
- }
-}
-
-static int adns_in_flight = 0; /* queries outstanding */
-
-/* Start an asynchronous DNS query.
- *
- * For KEY record, the result will be a list in cr->keys_from_dns.
- * For TXT records, the result will be a list in cr->gateways_from_dns.
- *
- * If sgw_id is null, only consider TXT records that specify an
- * IP address for the gatway: we need this in the initiation case.
- *
- * If sgw_id is non-null, only consider TXT records that specify
- * this id as the security gatway; this is useful to the Responder
- * for confirming claims of gateways.
- *
- * Continuation cr gives information for continuing when the result shows up.
- *
- * Two kinds of errors must be handled: synchronous (immediate)
- * and asynchronous. Synchronous errors are indicated by the returned
- * value of start_adns_query; in this case, the continuation will
- * have been freed and the continuation routine will not be called.
- * Asynchronous errors are indicated by the ugh parameter passed to the
- * continuation routine.
- *
- * After the continuation routine has completed, handle_adns_answer
- * will free the continuation. The continuation routine should have
- * freed any axiliary resources.
- *
- * Note: in the synchronous error case, start_adns_query will have
- * freed the continuation; this means that the caller will have to
- * be very careful to release any auxiliary resources that were in
- * the continuation record without using the continuation record.
- *
- * Either there will be an error result passed to the continuation routine,
- * or the results will be in cr->keys_from_dns or cr->gateways_from_dns.
- * The result variables must by left NULL by the continutation routine.
- * The continuation routine is responsible for establishing and
- * disestablishing any logging context (whack_log_fd, cur_*).
- */
-
-static struct adns_continuation *continuations = NULL; /* newest of queue */
-static struct adns_continuation *next_query = NULL; /* oldest not sent */
-
-static struct adns_continuation *continuation_for_qtid(unsigned long qtid)
-{
- struct adns_continuation *cr = NULL;
-
- if (qtid != 0)
- {
- for (cr = continuations; cr != NULL && cr->qtid != qtid; cr = cr->previous)
- ;
- }
- return cr;
-}
-
-static void release_adns_continuation(struct adns_continuation *cr)
-{
- passert(cr != next_query);
- gw_delref(&cr->gateways_from_dns);
-#ifdef USE_KEYRR
- free_public_keys(&cr->keys_from_dns);
-#endif /* USE_KEYRR */
- cr->id = cr->id->clone(cr->id);
- cr->sgw_id = cr->sgw_id->clone(cr->sgw_id);
-
- /* unlink from doubly-linked list */
- if (cr->next == NULL)
- {
- continuations = cr->previous;
- }
- else
- {
- cr->next->previous = cr->previous;
- }
-
- if (cr->previous != NULL)
- {
- cr->previous->next = cr->next;
- }
-
- free(cr);
-}
-
-err_t start_adns_query(identification_t *id, /* domain to query */
- identification_t *sgw_id, /* if non-null, any accepted gw_info must match */
- int type, /* T_TXT or T_KEY, selecting rr type of interest */
- cont_fn_t cont_fn,
- struct adns_continuation *cr)
-{
- static unsigned long qtid = 1; /* query transaction id; NOTE: static */
- const char *typename = rr_typename(type);
-
- if(adns_pid == 0 && adns_restart_count < ADNS_RESTART_MAX)
- {
- plog("ADNS helper was not running. Restarting attempt %d",adns_restart_count);
- init_adns();
- }
-
- /* Splice this in at head of doubly-linked list of continuations.
- * Note: this must be done before any release_adns_continuation().
- */
- cr->next = NULL;
- cr->previous = continuations;
- if (continuations != NULL)
- {
- continuations->next = cr;
- }
- continuations = cr;
-
- cr->qtid = qtid++;
- cr->type = type;
- cr->cont_fn = cont_fn;
- cr->id = id->clone(id);
- cr->sgw_specified = (sgw_id != NULL);
- cr->sgw_id = cr->sgw_specified ?
- sgw_id->clone(sgw_id) :
- identification_create_from_string("%any");
- cr->gateways_from_dns = NULL;
-#ifdef USE_KEYRR
- cr->keys_from_dns = NULL;
-#endif /* USE_KEYRR */
-
-#ifdef DEBUG
- cr->debugging = cur_debugging;
-#else
- cr->debugging = LEMPTY;
-#endif
-
- zero(&cr->query);
- {
- err_t ugh = build_dns_name(cr->query.name_buf, cr->qtid, id,
- typename, cr->sgw_id);
-
- if (ugh)
- {
- release_adns_continuation(cr);
- return ugh;
- }
- }
-
- if (next_query == NULL)
- next_query = cr;
-
- unsent_ADNS_queries = TRUE;
-
- return NULL;
-}
-
-/* send remaining ADNS queries (until pipe full or none left)
- *
- * This is a co-routine, so it uses static variables to
- * preserve state across calls.
- */
-bool unsent_ADNS_queries = FALSE;
-
-void
-send_unsent_ADNS_queries(void)
-{
- static const unsigned char *buf_end = NULL; /* NOTE STATIC */
- static const unsigned char *buf_cur = NULL; /* NOTE STATIC */
-
- if (adns_qfd == NULL_FD)
- return; /* nothing useful to do */
-
- for (;;)
- {
- if (buf_cur != buf_end)
- {
- static int try = 0; /* NOTE STATIC */
- size_t n = buf_end - buf_cur;
- ssize_t r = write(adns_qfd, buf_cur, n);
-
- if (r == -1)
- {
- switch (errno)
- {
- case EINTR:
- continue; /* try again now */
- case EAGAIN:
- DBG(DBG_DNS, DBG_log("EAGAIN writing to ADNS"));
- break; /* try again later */
- default:
- try++;
- log_errno((e, "error %d writing DNS query", try));
- break; /* try again later */
- }
- unsent_ADNS_queries = TRUE;
- break; /* done! */
- }
- else
- {
- passert(r >= 0);
- try = 0;
- buf_cur += r;
- }
- }
- else
- {
- if (next_query == NULL)
- {
- unsent_ADNS_queries = FALSE;
- break; /* done! */
- }
-
- next_query->query.debugging = next_query->debugging;
- next_query->query.serial = next_query->qtid;
- next_query->query.len = sizeof(next_query->query);
- next_query->query.qmagic = ADNS_Q_MAGIC;
- next_query->query.type = next_query->type;
- buf_cur = (const void *)&next_query->query;
- buf_end = buf_cur + sizeof(next_query->query);
-
- next_query = next_query->next;
- adns_in_flight++;
- }
- }
-}
-
-static void recover_adns_die(void)
-{
- struct adns_continuation *cr = NULL;
-
- adns_pid = 0;
- if(adns_restart_count < ADNS_RESTART_MAX) {
- adns_restart_count++;
-
- /* next DNS query will restart it */
-
- /* we have to walk the list of the outstanding requests,
- * and redo them!
- */
-
- cr = continuations;
-
- /* find the head of the list */
- if(continuations != NULL) {
- for (; cr->previous != NULL; cr = cr->previous);
- }
-
- next_query = cr;
-
- if(next_query != NULL) {
- unsent_ADNS_queries = TRUE;
- }
- }
-}
-
-void reset_adns_restart_count(void)
-{
- adns_restart_count=0;
-}
-
-void handle_adns_answer(void)
-{
- /* These are retained across calls to handle_adns_answer. */
- static size_t buflen = 0; /* bytes in answer buffer */
- static struct adns_answer buf;
-
- ssize_t n;
-
- passert(buflen < sizeof(buf));
- n = read(adns_afd, (unsigned char *)&buf + buflen, sizeof(buf) - buflen);
-
- if (n < 0)
- {
- if (errno != EINTR)
- {
- log_errno((e, "error reading answer from adns"));
- /* ??? how can we recover? */
- }
- n = 0; /* now n reflects amount read */
- }
- else if (n == 0)
- {
- /* EOF */
- if (adns_in_flight != 0)
- {
- plog("EOF from ADNS with %d queries outstanding (restarts %d)"
- , adns_in_flight, adns_restart_count);
- recover_adns_die();
- }
- if (buflen != 0)
- {
- plog("EOF from ADNS with %lu bytes of a partial answer outstanding"
- "(restarts %d)"
- , (unsigned long)buflen
- , adns_restart_count);
- recover_adns_die();
- }
- stop_adns();
- return;
- }
- else
- {
- passert(adns_in_flight > 0);
- }
-
- buflen += n;
- while (buflen >= offsetof(struct adns_answer, ans) && buflen >= buf.len)
- {
- /* we've got a tasty answer -- process it */
- err_t ugh;
- struct adns_continuation *cr = continuation_for_qtid(buf.serial); /* assume it works */
- const char *typename = rr_typename(cr->query.type);
- const char *name_buf = cr->query.name_buf;
-
-#ifdef USE_KEYRR
- passert(cr->keys_from_dns == NULL);
-#endif /* USE_KEYRR */
- passert(cr->gateways_from_dns == NULL);
- adns_in_flight--;
- if (buf.result == -1)
- {
- /* newer resolvers support statp->res_h_errno as well as h_errno.
- * That might be better, but older resolvers don't.
- * See resolver(3), if you have it.
- * The undocumented(!) h_errno values are defined in
- * /usr/include/netdb.h.
- */
- switch (buf.h_errno_val)
- {
- case NO_DATA:
- ugh = builddiag("no %s record for %s", typename, name_buf);
- break;
- case HOST_NOT_FOUND:
- ugh = builddiag("no host %s for %s record", name_buf, typename);
- break;
- default:
- ugh = builddiag("failure querying DNS for %s of %s: %s"
- , typename, name_buf, hstrerror(buf.h_errno_val));
- break;
- }
- }
- else if (buf.result > (int) sizeof(buf.ans))
- {
- ugh = builddiag("(INTERNAL ERROR) answer too long (%ld) for buffer"
- , (long)buf.result);
- }
- else
- {
- ugh = process_dns_answer(cr, buf.ans, buf.result);
- if (ugh != NULL)
- ugh = builddiag("failure processing %s record of DNS answer for %s: %s"
- , typename, name_buf, ugh);
- }
- DBG(DBG_RAW | DBG_CRYPT | DBG_PARSING | DBG_CONTROL | DBG_DNS,
- DBG_log(BLANK_FORMAT);
- if (ugh == NULL)
- DBG_log("asynch DNS answer %lu for %s of %s"
- , cr->query.serial, typename, name_buf);
- else
- DBG_log("asynch DNS answer %lu %s", cr->query.serial, ugh);
- );
-
- passert(GLOBALS_ARE_RESET());
- cr->cont_fn(cr, ugh);
- reset_globals();
- release_adns_continuation(cr);
-
- /* shift out answer that we've consumed */
- buflen -= buf.len;
- memmove((unsigned char *)&buf, (unsigned char *)&buf + buf.len, buflen);
- }
-}
diff --git a/src/pluto/dnskey.h b/src/pluto/dnskey.h
deleted file mode 100644
index 39a406cbd..000000000
--- a/src/pluto/dnskey.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/* Find public key in DNS
- * Copyright (C) 2000-2002 D. Hugh Redelmeier.
- *
- * 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/identification.h>
-
-extern int adns_qfd; /* file descriptor for sending queries to adns */
-extern int adns_afd; /* file descriptor for receiving answers from adns */
-extern const char *pluto_adns_option; /* path from --pluto_adns */
-extern void init_adns(void);
-extern void stop_adns(void);
-extern void handle_adns_answer(void);
-
-extern bool unsent_ADNS_queries;
-extern void send_unsent_ADNS_queries(void);
-
-/* (common prefix of) stuff remembered between async query and answer.
- * Filled in by start_adns_query.
- * Freed by call to release_adns_continuation.
- */
-
-struct adns_continuation; /* forward declaration (not far!) */
-
-typedef void (*cont_fn_t)(struct adns_continuation *cr, err_t ugh);
-
-struct adns_continuation {
- unsigned long qtid; /* query transaction id number */
- int type; /* T_TXT or T_KEY, selecting rr type of interest */
- cont_fn_t cont_fn; /* function to carry on suspended work */
- identification_t *id; /* subject of query */
- bool sgw_specified;
- identification_t *sgw_id; /* peer, if constrained */
- lset_t debugging; /* only used #ifdef DEBUG, but don't want layout to change */
- struct gw_info *gateways_from_dns; /* answer, if looking for our TXT rrs */
-#ifdef USE_KEYRR
- struct pubkey_list *keys_from_dns; /* answer, if looking for KEY rrs */
-#endif
- struct adns_continuation *previous, *next;
- struct pubkey *last_info; /* the last structure we accumulated */
- struct adns_query query;
-};
-
-extern err_t start_adns_query(identification_t *id /* domain to query */
- , identification_t *sgw_id /* if non-null, any accepted gw_info must match */
- , int type /* T_TXT or T_KEY, selecting rr type of interest */
- , cont_fn_t cont_fn /* continuation function */
- , struct adns_continuation *cr);
-
-
-/* Gateway info gleaned from reverse DNS of client */
-struct gw_info {
- unsigned refcnt; /* reference counted! */
- unsigned pref; /* preference: lower is better */
-#define NO_TIME ((time_t) -2) /* time_t value meaning "not_yet" */
- identification_t* client_id; /* id of client of peer */
- identification_t* gw_id; /* id of peer (if id_is_ipaddr, .ip_addr is address) */
- bool gw_key_present;
- struct pubkey *key;
- struct gw_info *next;
-};
-
-extern void gw_addref(struct gw_info *gw);
-extern void gw_delref(struct gw_info **gwp);
-extern void reset_adns_restart_count(void);
-
diff --git a/src/pluto/event_queue.c b/src/pluto/event_queue.c
deleted file mode 100644
index 602a013ee..000000000
--- a/src/pluto/event_queue.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright (C) 2010 Tobias Brunner
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <unistd.h>
-#include <fcntl.h>
-
-#include "event_queue.h"
-
-#include <debug.h>
-#include <threading/mutex.h>
-#include <utils/linked_list.h>
-
-typedef struct private_event_queue_t private_event_queue_t;
-
-/**
- * Private data of event_queue_t class.
- */
-struct private_event_queue_t {
- /**
- * Public event_queue_t interface.
- */
- event_queue_t public;
-
- /**
- * List of queued events (event_t*).
- */
- linked_list_t *events;
-
- /**
- * Mutex for event list.
- */
- mutex_t *mutex;
-
- /**
- * Read end of the notification pipe.
- */
- int read_fd;
-
- /**
- * Write end of the notification pipe.
- */
- int write_fd;
-
-};
-
-typedef struct event_t event_t;
-
-struct event_t {
- /**
- * Callback function.
- */
- void (*callback)(void *data);
-
- /**
- * Data to supply to the callback.
- */
- void *data;
-
- /**
- * Cleanup function.
- */
- void (*cleanup)(void *data);
-};
-
-static event_t *event_create(void (*callback)(void *data), void *data,
- void (*cleanup)(void *data))
-{
- event_t *this;
- INIT(this,
- .callback = callback,
- .data = data,
- .cleanup = cleanup,
- );
- return this;
-}
-
-static void event_destroy(event_t *this)
-{
- if (this->cleanup)
- {
- this->cleanup(this->data);
- }
- free(this);
-}
-
-METHOD(event_queue_t, get_event_fd, int,
- private_event_queue_t *this)
-{
- return this->read_fd;
-}
-
-METHOD(event_queue_t, handle, void,
- private_event_queue_t *this)
-{
- char buf[10];
- linked_list_t *events;
- event_t *event;
- this->mutex->lock(this->mutex);
- /* flush pipe */
- while (read(this->read_fd, &buf, sizeof(buf)) == sizeof(buf));
- /* replace the list, so we can unlock the mutex while executing the jobs */
- events = this->events;
- this->events = linked_list_create();
- this->mutex->unlock(this->mutex);
-
- while (events->remove_first(events, (void**)&event) == SUCCESS)
- {
- event->callback(event->data);
- event_destroy(event);
- }
- events->destroy(events);
-}
-
-METHOD(event_queue_t, queue, void,
- private_event_queue_t *this, void (*callback)(void *data), void *data,
- void (*cleanup)(void *data))
-{
- event_t *event = event_create(callback, data, cleanup);
- char c = 0;
- this->mutex->lock(this->mutex);
- this->events->insert_last(this->events, event);
- ignore_result(write(this->write_fd, &c, 1));
- this->mutex->unlock(this->mutex);
-}
-
-METHOD(event_queue_t, destroy, void,
- private_event_queue_t *this)
-{
- this->mutex->lock(this->mutex);
- this->events->destroy_function(this->events, (void*)event_destroy);
- this->mutex->unlock(this->mutex);
- this->mutex->destroy(this->mutex);
- close(this->read_fd);
- close(this->write_fd);
- free(this);
-}
-
-static bool set_nonblock(int socket)
-{
- int flags = fcntl(socket, F_GETFL);
- return flags != -1 && fcntl(socket, F_SETFL, flags | O_NONBLOCK) != -1;
-}
-
-static bool set_cloexec(int socket)
-{
- int flags = fcntl(socket, F_GETFD);
- return flags != -1 && fcntl(socket, F_SETFD, flags | FD_CLOEXEC) != -1;
-}
-
-/*
- * Described in header.
- */
-event_queue_t *event_queue_create()
-{
- private_event_queue_t *this;
- int fd[2];
-
- INIT(this,
- .public = {
- .get_event_fd = _get_event_fd,
- .handle = _handle,
- .queue = _queue,
- .destroy = _destroy,
- },
- .events = linked_list_create(),
- .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
- );
-
- if (pipe(fd) == -1 ||
- !set_nonblock(fd[0]) || !set_cloexec(fd[0]) ||
- !set_nonblock(fd[1]) || !set_cloexec(fd[1]))
- {
- DBG1(DBG_JOB, "failed to create pipe for job queue");
- _destroy(this);
- return NULL;
- }
-
- this->read_fd = fd[0];
- this->write_fd = fd[1];
-
- return &this->public;
-}
-
diff --git a/src/pluto/event_queue.h b/src/pluto/event_queue.h
deleted file mode 100644
index 343729e25..000000000
--- a/src/pluto/event_queue.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2010 Tobias Brunner
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup event_queue event_queue
- * @{ @ingroup pluto
- */
-
-#ifndef EVENT_QUEUE_H_
-#define EVENT_QUEUE_H_
-
-typedef struct event_queue_t event_queue_t;
-
-/**
- * The event queue facility can be used to synchronize thread-pool threads
- * with the pluto main thread. That is, all queued callbacks are executed
- * asynchronously by the pluto main thread.
- */
-struct event_queue_t {
-
- /**
- * Returns the file descriptor used to notify the main thread.
- *
- * @return fd to use in the main thread
- */
- int (*get_event_fd) (event_queue_t *this);
-
- /**
- * Handle all queued events.
- */
- void (*handle) (event_queue_t *this);
-
- /**
- * Add an event to the queue.
- *
- * @param callback callback function to add to the queue
- * @param data data supplied to the callback function
- * @param cleanup optional cleanup function
- */
- void (*queue) (event_queue_t *this, void (*callback)(void *data),
- void *data, void (*cleanup)(void *data));
-
- /**
- * Destroy this instance.
- */
- void (*destroy) (event_queue_t *this);
-
-};
-
-/**
- * Create the event queue.
- *
- * @return created object
- */
-event_queue_t *event_queue_create();
-
-#endif /** EVENT_QUEUE_H_ @}*/
diff --git a/src/pluto/fetch.c b/src/pluto/fetch.c
deleted file mode 100644
index 3dfc1386f..000000000
--- a/src/pluto/fetch.c
+++ /dev/null
@@ -1,766 +0,0 @@
-/* Dynamic fetching of X.509 CRLs
- * Copyright (C) 2002 Stephane Laroche <stephane.laroche@colubris.com>
- * Copyright (C) 2002-2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/time.h>
-#include <time.h>
-#include <string.h>
-
-#ifdef THREADS
-#include <pthread.h>
-#endif
-
-#include <freeswan.h>
-
-#include <library.h>
-#include <debug.h>
-#include <asn1/asn1.h>
-#include <credentials/certificates/certificate.h>
-#ifdef THREADS
-#include <threading/thread.h>
-#endif
-
-#include "constants.h"
-#include "defs.h"
-#include "log.h"
-#include "x509.h"
-#include "ca.h"
-#include "whack.h"
-#include "ocsp.h"
-#include "crl.h"
-#include "fetch.h"
-#include "builder.h"
-
-fetch_req_t empty_fetch_req = {
- NULL , /* next */
- 0 , /* trials */
- NULL , /* issuer */
- { NULL, 0}, /* authKeyID */
- NULL /* distributionPoints */
-};
-
-/* chained list of crl fetch requests */
-static fetch_req_t *crl_fetch_reqs = NULL;
-
-/* chained list of ocsp fetch requests */
-static ocsp_location_t *ocsp_fetch_reqs = NULL;
-
-#ifdef THREADS
-static thread_t *thread;
-static pthread_mutex_t certs_and_keys_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t authcert_list_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t crl_list_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t ocsp_cache_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t ca_info_list_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t crl_fetch_list_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t ocsp_fetch_list_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t fetch_wake_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t fetch_wake_cond = PTHREAD_COND_INITIALIZER;
-
-/**
- * lock access to my certs and keys
- */
-void lock_certs_and_keys(const char *who)
-{
- pthread_mutex_lock(&certs_and_keys_mutex);
- DBG(DBG_CONTROLMORE,
- DBG_log("certs and keys locked by '%s'", who)
- )
-}
-
-/**
- * Unlock access to my certs and keys
- */
-void unlock_certs_and_keys(const char *who)
-{
- DBG(DBG_CONTROLMORE,
- DBG_log("certs and keys unlocked by '%s'", who)
- )
- pthread_mutex_unlock(&certs_and_keys_mutex);
-}
-
-/**
- * Lock access to the chained authcert list
- */
-void lock_authcert_list(const char *who)
-{
- pthread_mutex_lock(&authcert_list_mutex);
- DBG(DBG_CONTROLMORE,
- DBG_log("authcert list locked by '%s'", who)
- )
-}
-
-/**
- * Unlock access to the chained authcert list
- */
-void unlock_authcert_list(const char *who)
-{
- DBG(DBG_CONTROLMORE,
- DBG_log("authcert list unlocked by '%s'", who)
- )
- pthread_mutex_unlock(&authcert_list_mutex);
-}
-
-/**
- * Lock access to the chained crl list
- */
-void lock_crl_list(const char *who)
-{
- pthread_mutex_lock(&crl_list_mutex);
- DBG(DBG_CONTROLMORE,
- DBG_log("crl list locked by '%s'", who)
- )
-}
-
-/**
- * Unlock access to the chained crl list
- */
-void unlock_crl_list(const char *who)
-{
- DBG(DBG_CONTROLMORE,
- DBG_log("crl list unlocked by '%s'", who)
- )
- pthread_mutex_unlock(&crl_list_mutex);
-}
-
-/**
- * Lock access to the ocsp cache
- */
-extern void lock_ocsp_cache(const char *who)
-{
- pthread_mutex_lock(&ocsp_cache_mutex);
- DBG(DBG_CONTROLMORE,
- DBG_log("ocsp cache locked by '%s'", who)
- )
-}
-
-/**
- * Unlock access to the ocsp cache
- */
-extern void unlock_ocsp_cache(const char *who)
-{
- DBG(DBG_CONTROLMORE,
- DBG_log("ocsp cache unlocked by '%s'", who)
- )
- pthread_mutex_unlock(&ocsp_cache_mutex);
-}
-
-/**
- * Lock access to the ca info list
- */
-extern void lock_ca_info_list(const char *who)
-{
- pthread_mutex_lock(&ca_info_list_mutex);
- DBG(DBG_CONTROLMORE,
- DBG_log("ca info list locked by '%s'", who)
- )
-}
-
-/**
- * Unlock access to the ca info list
- */
-extern void unlock_ca_info_list(const char *who)
-{
- DBG(DBG_CONTROLMORE,
- DBG_log("ca info list unlocked by '%s'", who)
- )
- pthread_mutex_unlock(&ca_info_list_mutex);
-}
-
-/**
- * Lock access to the chained crl fetch request list
- */
-static void lock_crl_fetch_list(const char *who)
-{
- pthread_mutex_lock(&crl_fetch_list_mutex);
- DBG(DBG_CONTROLMORE,
- DBG_log("crl fetch request list locked by '%s'", who)
- )
-}
-
-/**
- * Unlock access to the chained crl fetch request list
- */
-static void unlock_crl_fetch_list(const char *who)
-{
- DBG(DBG_CONTROLMORE,
- DBG_log("crl fetch request list unlocked by '%s'", who)
- )
- pthread_mutex_unlock(&crl_fetch_list_mutex);
-}
-
-/**
- * Lock access to the chained ocsp fetch request list
- */
-static void lock_ocsp_fetch_list(const char *who)
-{
- pthread_mutex_lock(&ocsp_fetch_list_mutex);
- DBG(DBG_CONTROLMORE,
- DBG_log("ocsp fetch request list locked by '%s'", who)
- )
-}
-
-/**
- * Unlock access to the chained ocsp fetch request list
- */
-static void unlock_ocsp_fetch_list(const char *who)
-{
- DBG(DBG_CONTROLMORE,
- DBG_log("ocsp fetch request list unlocked by '%s'", who)
- )
- pthread_mutex_unlock(&ocsp_fetch_list_mutex);
-}
-
-/**
- * Wakes up the sleeping fetch thread
- */
-void wake_fetch_thread(const char *who)
-{
- if (crl_check_interval > 0)
- {
- DBG(DBG_CONTROLMORE,
- DBG_log("fetch thread wake call by '%s'", who)
- )
- pthread_mutex_lock(&fetch_wake_mutex);
- pthread_cond_signal(&fetch_wake_cond);
- pthread_mutex_unlock(&fetch_wake_mutex);
- }
-}
-#else /* !THREADS */
-#define lock_crl_fetch_list(who) /* do nothing */
-#define unlock_crl_fetch_list(who) /* do nothing */
-#define lock_ocsp_fetch_list(who) /* do nothing */
-#define unlock_ocsp_fetch_list(who) /* do nothing */
-#endif /* !THREADS */
-
-/**
- * Free the dynamic memory used to store fetch requests
- */
-static void free_fetch_request(fetch_req_t *req)
-{
- req->distributionPoints->destroy_function(req->distributionPoints, free);
- DESTROY_IF(req->issuer);
- free(req->authKeyID.ptr);
- free(req);
-}
-
-#ifdef THREADS
-/**
- * Fetch an ASN.1 blob coded in PEM or DER format from a URL
- */
-x509crl_t* fetch_crl(char *url)
-{
- x509crl_t *crl;
- chunk_t blob;
-
- DBG1(DBG_LIB, " fetching crl from '%s' ...", url);
- if (lib->fetcher->fetch(lib->fetcher, url, &blob, FETCH_END) != SUCCESS)
- {
- DBG1(DBG_LIB, "crl fetching failed");
- return FALSE;
- }
- crl = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_PLUTO_CRL,
- BUILD_BLOB_PEM, blob, BUILD_END);
- free(blob.ptr);
- if (!crl)
- {
- DBG1(DBG_LIB, "crl fetched successfully but data coded in unknown "
- "format");
- }
- return crl;
-}
-
-/**
- * Complete a distributionPoint URI with ca information
- */
-static char* complete_uri(char *distPoint, const char *ldaphost)
-{
- char *symbol = strchr(distPoint, ':');
-
- if (symbol)
- {
- int type_len = symbol - distPoint;
-
- if (type_len >= 4 && strncasecmp(distPoint, "ldap", 4) == 0)
- {
- char *ptr = symbol + 1;
- int len = strlen(distPoint) - (type_len + 1);
-
- if (len > 2 && *ptr++ == '/' && *ptr++ == '/')
- {
- len -= 2;
- symbol = strchr(ptr, '/');
-
- if (symbol && symbol - ptr == 0 && ldaphost)
- {
- char uri[BUF_LEN];
-
- /* insert the ldaphost into the uri */
- snprintf(uri, BUF_LEN, "%.*s%s%.*s",
- (int)strlen(distPoint) - len, distPoint, ldaphost,
- len, symbol);
- return strdup(uri);
- }
- }
- }
- }
-
- /* default action: copy distributionPoint without change */
- return strdup(distPoint);
-}
-
-/**
- * Try to fetch the crls defined by the fetch requests
- */
-static void fetch_crls(bool cache_crls)
-{
- fetch_req_t *req;
- fetch_req_t **reqp;
-
- lock_crl_fetch_list("fetch_crls");
- req = crl_fetch_reqs;
- reqp = &crl_fetch_reqs;
-
- while (req != NULL)
- {
- enumerator_t *enumerator;
- char *point;
- bool valid_crl = FALSE;
- const char *ldaphost;
- ca_info_t *ca;
-
- lock_ca_info_list("fetch_crls");
-
- ca = get_ca_info(req->issuer, req->authKeyID);
- ldaphost = (ca == NULL)? NULL : ca->ldaphost;
-
- enumerator = req->distributionPoints->create_enumerator(req->distributionPoints);
- while (enumerator->enumerate(enumerator, &point))
- {
- x509crl_t *crl;
- char *uri;
-
- uri = complete_uri(point, ldaphost);
- crl = fetch_crl(uri);
- free(uri);
-
- if (crl)
- {
- if (insert_crl(crl, point, cache_crls))
- {
- DBG(DBG_CONTROL,
- DBG_log("we have a valid crl")
- )
- valid_crl = TRUE;
- break;
- }
- }
- }
- enumerator->destroy(enumerator);
- unlock_ca_info_list("fetch_crls");
-
- if (valid_crl)
- {
- /* delete fetch request */
- fetch_req_t *req_free = req;
-
- req = req->next;
- *reqp = req;
- free_fetch_request(req_free);
- }
- else
- {
- /* try again next time */
- req->trials++;
- reqp = &req->next;
- req = req->next;
- }
- }
- unlock_crl_fetch_list("fetch_crls");
-}
-
-static void fetch_ocsp_status(ocsp_location_t* location)
-{
- chunk_t request = build_ocsp_request(location);
- chunk_t response = chunk_empty;
-
- DBG1(DBG_LIB, " requesting ocsp status from '%s' ...", location->uri);
- if (lib->fetcher->fetch(lib->fetcher, location->uri, &response,
- FETCH_REQUEST_DATA, request,
- FETCH_REQUEST_TYPE, "application/ocsp-request",
- FETCH_END) == SUCCESS)
- {
- parse_ocsp(location, response);
- }
- else
- {
- DBG1(DBG_LIB, "ocsp request to %s failed", location->uri);
- }
-
- free(request.ptr);
- chunk_free(&location->nonce);
-
- /* increment the trial counter of the unresolved fetch requests */
- {
- ocsp_certinfo_t *certinfo = location->certinfo;
-
- while (certinfo != NULL)
- {
- certinfo->trials++;
- certinfo = certinfo->next;
- }
- }
-}
-
-/**
- * Try to fetch the necessary ocsp information
- */
-static void fetch_ocsp(void)
-{
- ocsp_location_t *location;
-
- lock_ocsp_fetch_list("fetch_ocsp");
- location = ocsp_fetch_reqs;
-
- /* fetch the ocps status for all locations */
- while (location != NULL)
- {
- if (location->certinfo != NULL)
- {
- fetch_ocsp_status(location);
- }
- location = location->next;
- }
-
- unlock_ocsp_fetch_list("fetch_ocsp");
-}
-
-static void* fetch_thread(void *arg)
-{
- struct timespec wait_interval;
-
- /* the fetching thread is only cancellable while waiting for new events */
- thread_cancelability(FALSE);
-
- DBG(DBG_CONTROL,
- DBG_log("fetch thread started")
- )
-
- pthread_mutex_lock(&fetch_wake_mutex);
-
- while(1)
- {
- int status;
-
- wait_interval.tv_nsec = 0;
- wait_interval.tv_sec = time(NULL) + crl_check_interval;
-
- DBG(DBG_CONTROL,
- DBG_log("next regular crl check in %ld seconds", crl_check_interval)
- )
-
- thread_cancelability(TRUE);
- status = pthread_cond_timedwait(&fetch_wake_cond, &fetch_wake_mutex
- , &wait_interval);
- thread_cancelability(FALSE);
-
- if (status == ETIMEDOUT)
- {
- DBG(DBG_CONTROL,
- DBG_log(" ");
- DBG_log("*time to check crls and the ocsp cache")
- )
- check_ocsp();
- check_crls();
- }
- else
- {
- DBG(DBG_CONTROL,
- DBG_log("fetch thread was woken up")
- )
- }
- fetch_ocsp();
- fetch_crls(cache_crls);
- }
- return NULL;
-}
-#endif /* THREADS*/
-
-/**
- * Initializes curl and starts the fetching thread
- */
-void fetch_initialize(void)
-{
- if (crl_check_interval > 0)
- {
-#ifdef THREADS
- thread = thread_create((thread_main_t)fetch_thread, NULL);
- if (thread == NULL)
- {
- plog("fetching thread could not be started");
- }
-#else /* !THREADS */
- plog("warning: not compiled with pthread support");
-#endif /* !THREADS */
- }
-}
-
-/**
- * Terminates the fetching thread
- */
-void fetch_finalize(void)
-{
- if (crl_check_interval > 0)
- {
-#ifdef THREADS
- if (thread)
- {
- thread->cancel(thread);
- thread->join(thread);
- }
-#endif
- }
-}
-
-void free_crl_fetch(void)
-{
- lock_crl_fetch_list("free_crl_fetch");
-
- while (crl_fetch_reqs != NULL)
- {
- fetch_req_t *req = crl_fetch_reqs;
- crl_fetch_reqs = req->next;
- free_fetch_request(req);
- }
-
- unlock_crl_fetch_list("free_crl_fetch");
-}
-
-/**
- * Free the chained list of ocsp requests
- */
-void free_ocsp_fetch(void)
-{
- lock_ocsp_fetch_list("free_ocsp_fetch");
- free_ocsp_locations(&ocsp_fetch_reqs);
- unlock_ocsp_fetch_list("free_ocsp_fetch");
-}
-
-
-/**
- * Add an additional distribution point
- */
-void add_distribution_point(linked_list_t *points, char *new_point)
-{
- char *point;
- bool add = TRUE;
- enumerator_t *enumerator;
-
- if (new_point == NULL || *new_point == '\0')
- {
- return;
- }
-
- enumerator = points->create_enumerator(points);
- while (enumerator->enumerate(enumerator, &point))
- {
- if (streq(point, new_point))
- {
- add = FALSE;
- break;
- }
- }
- enumerator->destroy(enumerator);
-
- if (add)
- {
- points->insert_last(points, strdup(new_point));
- }
-}
-
-/**
- * Add additional distribution points
- */
-void add_distribution_points(linked_list_t *points, linked_list_t *new_points)
-{
- char *new_point;
- enumerator_t *enumerator;
-
- enumerator = new_points->create_enumerator(new_points);
- while (enumerator->enumerate(enumerator, &new_point))
- {
- bool add = TRUE;
- char *point;
- enumerator_t *enumerator;
-
- enumerator = points->create_enumerator(points);
- while (enumerator->enumerate(enumerator, &point))
- {
- if (streq(point, new_point))
- {
- add = FALSE;
- break;
- }
- }
- enumerator->destroy(enumerator);
-
- if (add)
- {
- points->insert_last(points, strdup(new_point));
- }
- }
- enumerator->destroy(enumerator);
-}
-
-fetch_req_t* build_crl_fetch_request(identification_t *issuer,
- chunk_t authKeyID,
- linked_list_t *distributionPoints)
-{
- char *point;
- enumerator_t *enumerator;
- fetch_req_t *req = malloc_thing(fetch_req_t);
-
- memset(req, 0, sizeof(fetch_req_t));
- req->distributionPoints = linked_list_create();
-
- /* clone fields */
- req->issuer = issuer->clone(issuer);
- req->authKeyID = chunk_clone(authKeyID);
-
- /* copy distribution points */
- enumerator = distributionPoints->create_enumerator(distributionPoints);
- while (enumerator->enumerate(enumerator, &point))
- {
- req->distributionPoints->insert_last(req->distributionPoints,
- strdup(point));
- }
- enumerator->destroy(enumerator);
-
- return req;
-}
-
-/**
- * Add a crl fetch request to the chained list
- */
-void add_crl_fetch_request(fetch_req_t *req)
-{
- fetch_req_t *r;
-
- lock_crl_fetch_list("add_crl_fetch_request");
- r = crl_fetch_reqs;
-
- while (r != NULL)
- {
- if (req->authKeyID.ptr ? same_keyid(req->authKeyID, r->authKeyID) :
- req->issuer->equals(req->issuer, r->issuer))
- {
- /* there is already a fetch request */
- DBG(DBG_CONTROL,
- DBG_log("crl fetch request already exists")
- )
-
- /* there might be new distribution points */
- add_distribution_points(r->distributionPoints,
- req->distributionPoints);
-
- unlock_crl_fetch_list("add_crl_fetch_request");
- free_fetch_request(req);
- return;
- }
- r = r->next;
- }
-
- /* insert new fetch request at the head of the queue */
- req->next = crl_fetch_reqs;
- crl_fetch_reqs = req;
-
- DBG(DBG_CONTROL,
- DBG_log("crl fetch request added")
- )
- unlock_crl_fetch_list("add_crl_fetch_request");
-}
-
-/**
- * Add an ocsp fetch request to the chained list
- */
-void add_ocsp_fetch_request(ocsp_location_t *location, chunk_t serialNumber)
-{
- ocsp_certinfo_t certinfo;
-
- certinfo.serialNumber = serialNumber;
-
- lock_ocsp_fetch_list("add_ocsp_fetch_request");
- add_certinfo(location, &certinfo, &ocsp_fetch_reqs, TRUE);
- unlock_ocsp_fetch_list("add_ocsp_fetch_request");
-}
-
-/**
- * List all distribution points
- */
-void list_distribution_points(linked_list_t *distributionPoints)
-{
- char *point;
- bool first_point = TRUE;
- enumerator_t *enumerator;
-
- enumerator = distributionPoints->create_enumerator(distributionPoints);
- while (enumerator->enumerate(enumerator, &point))
- {
- whack_log(RC_COMMENT, " %s '%s'",
- (first_point)? "distPts: " : " ", point);
- first_point = FALSE;
- }
- enumerator->destroy(enumerator);
-}
-
-/**
- * List all fetch requests in the chained list
- */
-void list_crl_fetch_requests(bool utc)
-{
- fetch_req_t *req;
-
- lock_crl_fetch_list("list_crl_fetch_requests");
- req = crl_fetch_reqs;
-
- if (req != NULL)
- {
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, "List of CRL Fetch Requests:");
- }
-
- while (req != NULL)
- {
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, " trials: %d", req->trials);
- whack_log(RC_COMMENT, " issuer: \"%Y\"", req->issuer);
- if (req->authKeyID.ptr)
- {
- whack_log(RC_COMMENT, " authkey: %#B", &req->authKeyID);
- }
- list_distribution_points(req->distributionPoints);
- req = req->next;
- }
- unlock_crl_fetch_list("list_crl_fetch_requests");
-}
-
-void list_ocsp_fetch_requests(bool utc)
-{
- lock_ocsp_fetch_list("list_ocsp_fetch_requests");
- list_ocsp_locations(ocsp_fetch_reqs, TRUE, utc, FALSE);
- unlock_ocsp_fetch_list("list_ocsp_fetch_requests");
-
-}
diff --git a/src/pluto/fetch.h b/src/pluto/fetch.h
deleted file mode 100644
index 265dc5fe7..000000000
--- a/src/pluto/fetch.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/* Dynamic fetching of X.509 CRLs
- * Copyright (C) 2002 Stephane Laroche <stephane.laroche@colubris.com>
- * Copyright (C) 2002-2004 Andreas Steffen, Zuercher Hochschule Winterthur
- *
- * 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/linked_list.h>
-#include <utils/identification.h>
-
-#include "x509.h"
-
-#define FETCH_CMD_TIMEOUT 10 /* seconds */
-
-struct ocsp_location; /* forward declaration of ocsp_location defined in ocsp.h */
-
-typedef enum {
- FETCH_GET = 1,
- FETCH_POST = 2
-} fetch_request_t;
-
-typedef struct fetch_req fetch_req_t;
-
-struct fetch_req {
- fetch_req_t *next;
- int trials;
- identification_t *issuer;
- chunk_t authKeyID;
- linked_list_t *distributionPoints;
-};
-
-#ifdef THREADS
-extern void lock_crl_list(const char *who);
-extern void unlock_crl_list(const char *who);
-extern void lock_ocsp_cache(const char *who);
-extern void unlock_ocsp_cache(const char *who);
-extern void lock_ca_info_list(const char *who);
-extern void unlock_ca_info_list(const char *who);
-extern void lock_authcert_list(const char *who);
-extern void unlock_authcert_list(const char *who);
-extern void lock_certs_and_keys(const char *who);
-extern void unlock_certs_and_keys(const char *who);
-extern void wake_fetch_thread(const char *who);
-#else
-#define lock_crl_list(who) /* do nothing */
-#define unlock_crl_list(who) /* do nothing */
-#define lock_ocsp_cache(who) /* do nothing */
-#define unlock_ocsp_cache(who) /* do nothing */
-#define lock_ca_info_list(who) /* do nothing */
-#define unlock_ca_info_list(who) /* do nothing */
-#define lock_authcert_list(who) /* do nothing */
-#define unlock_authcert_list(who) /* do nothing */
-#define lock_certs_and_keys(who) /* do nothing */
-#define unlock_certs_and_keys(who) /* do nothing */
-#define wake_fetch_thread(who) /* do nothing */
-#endif
-extern void fetch_initialize(void);
-extern void fetch_finalize(void);
-extern void free_crl_fetch(void);
-extern void free_ocsp_fetch(void);
-extern void add_distribution_point(linked_list_t *points, char* new_point);
-extern void add_distribution_points(linked_list_t *points,
- linked_list_t *new_points);
-extern fetch_req_t* build_crl_fetch_request(identification_t *issuer,
- chunk_t authKeyID,
- linked_list_t *distributionPoints);
-extern void add_crl_fetch_request(fetch_req_t *req);
-extern void add_ocsp_fetch_request(struct ocsp_location *location,
- chunk_t serialNumber);
-extern void list_distribution_points(linked_list_t *distributionPoints);
-extern void list_crl_fetch_requests(bool utc);
-extern void list_ocsp_fetch_requests(bool utc);
-extern size_t write_buffer(void *ptr, size_t size, size_t nmemb, void *data);
-
diff --git a/src/pluto/foodgroups.c b/src/pluto/foodgroups.c
deleted file mode 100644
index e4f9a1d01..000000000
--- a/src/pluto/foodgroups.c
+++ /dev/null
@@ -1,450 +0,0 @@
-/* Implement policy groups-style control files (aka "foodgroups")
- * Copyright (C) 2002 D. Hugh Redelmeier.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <string.h>
-#include <stdio.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <sys/queue.h>
-
-#include <freeswan.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "connections.h"
-#include "foodgroups.h"
-#include "kernel.h"
-#include "lex.h"
-#include "log.h"
-#include "whack.h"
-
-
-/* Food group config files are found in directory fg_path */
-
-#ifndef POLICYGROUPSDIR
-#define POLICYGROUPSDIR IPSEC_CONFDIR "/ipsec.d/policies"
-#endif
-
-const char *policygroups_dir = POLICYGROUPSDIR;
-
-static char *fg_path = NULL;
-static size_t fg_path_space = 0;
-
-
-/* Groups is a list of connections that are policy groups.
- * The list is updated as group connections are added and deleted.
- */
-
-struct fg_groups {
- struct fg_groups *next;
- connection_t *connection;
-};
-
-static struct fg_groups *groups = NULL;
-
-
-/* Targets is a list of pairs: subnet and its policy group.
- * This list is bulk-updated on whack --listen and
- * incrementally updated when group connections are deleted.
- *
- * It is ordered by source subnet, and if those are equal, then target subnet.
- * A subnet is compared by comparing the network, and if those are equal,
- * comparing the mask.
- */
-
-struct fg_targets {
- struct fg_targets *next;
- struct fg_groups *group;
- ip_subnet subnet;
- char *name; /* name of instance of group conn */
-};
-
-static struct fg_targets *targets = NULL;
-
-struct fg_targets *new_targets;
-
-/* ipcmp compares the two ip_address values a and b.
- * It returns -1, 0, or +1 if a is, respectively,
- * less than, equal to, or greater than b.
- */
-static int ipcmp(ip_address *a, ip_address *b)
-{
- if (addrtypeof(a) != addrtypeof(b))
- {
- return addrtypeof(a) < addrtypeof(b)? -1 : 1;
- }
- else if (sameaddr(a, b))
- {
- return 0;
- }
- else
- {
- const struct sockaddr *sa = sockaddrof(a)
- , *sb = sockaddrof(b);
-
- passert(addrtypeof(a) == AF_INET); /* not yet implemented IPv6 version :-( */
- return (ntohl(((const struct sockaddr_in *)sa)->sin_addr.s_addr)
- < ntohl(((const struct sockaddr_in *)sb)->sin_addr.s_addr))
- ? -1 : 1;
- }
-}
-
-/* subnetcmp compares the two ip_subnet values a and b.
- * It returns -1, 0, or +1 if a is, respectively,
- * less than, equal to, or greater than b.
- */
-static int subnetcmp(const ip_subnet *a, const ip_subnet *b)
-{
- ip_address neta, maska, netb, maskb;
- int r;
-
- networkof(a, &neta);
- maskof(a, &maska);
- networkof(b, &netb);
- maskof(b, &maskb);
- r = ipcmp(&neta, &netb);
- if (r == 0)
- r = ipcmp(&maska, &maskb);
- return r;
-}
-
-static void read_foodgroup(struct fg_groups *g)
-{
- const char *fgn = g->connection->name;
- const ip_subnet *lsn = &g->connection->spd.this.client;
- size_t plen = strlen(policygroups_dir) + 1 + strlen(fgn) + 1;
- struct file_lex_position flp_space;
-
- if (plen > fg_path_space)
- {
- free(fg_path);
- fg_path_space = plen + 10;
- fg_path = malloc(fg_path_space);
- }
- snprintf(fg_path, fg_path_space, "%s/%s", policygroups_dir, fgn);
- if (!lexopen(&flp_space, fg_path, TRUE))
- {
- DBG(DBG_CONTROL, DBG_log("no group file \"%s\"", fg_path));
- }
- else
- {
- plog("loading group \"%s\"", fg_path);
- for (;;)
- {
- switch (flp->bdry)
- {
- case B_none:
- {
- /* !!! this test is not sufficient for distinguishing address families.
- * We need a notation to specify that a FQDN is to be resolved to IPv6.
- */
- const struct af_info *afi = strchr(tok, ':') == NULL
- ? &af_inet4_info: &af_inet6_info;
- ip_subnet sn;
- err_t ugh;
-
- if (strchr(tok, '/') == NULL)
- {
- /* no /, so treat as /32 or V6 equivalent */
- ip_address t;
-
- ugh = ttoaddr(tok, 0, afi->af, &t);
- if (ugh == NULL)
- ugh = addrtosubnet(&t, &sn);
- }
- else
- {
- ugh = ttosubnet(tok, 0, afi->af, &sn);
- }
-
- if (ugh != NULL)
- {
- loglog(RC_LOG_SERIOUS, "\"%s\" line %d: %s \"%s\""
- , flp->filename, flp->lino, ugh, tok);
- }
- else if (afi->af != AF_INET)
- {
- loglog(RC_LOG_SERIOUS
- , "\"%s\" line %d: unsupported Address Family \"%s\""
- , flp->filename, flp->lino, tok);
- }
- else
- {
- /* Find where new entry ought to go in new_targets. */
- struct fg_targets **pp;
- int r;
-
- for (pp = &new_targets; ; pp = &(*pp)->next)
- {
- if (*pp == NULL)
- {
- r = -1; /* end of list is infinite */
- break;
- }
- r = subnetcmp(lsn, &(*pp)->group->connection->spd.this.client);
- if (r == 0)
- r = subnetcmp(&sn, &(*pp)->subnet);
- if (r <= 0)
- break;
- }
-
- if (r == 0)
- {
- char source[SUBNETTOT_BUF];
-
- subnettot(lsn, 0, source, sizeof(source));
- loglog(RC_LOG_SERIOUS
- , "\"%s\" line %d: subnet \"%s\", source %s, already \"%s\""
- , flp->filename
- , flp->lino
- , tok
- , source
- , (*pp)->group->connection->name);
- }
- else
- {
- struct fg_targets *f = malloc_thing(struct fg_targets);
-
- f->next = *pp;
- f->group = g;
- f->subnet = sn;
- f->name = NULL;
- *pp = f;
- }
- }
- }
- (void)shift(); /* next */
- continue;
-
- case B_record:
- flp->bdry = B_none; /* eat the Record Boundary */
- (void)shift(); /* get real first token */
- continue;
-
- case B_file:
- break; /* done */
- }
- break; /* if we reach here, out of loop */
- }
- lexclose();
- }
-}
-
-static void free_targets(void)
-{
- while (targets != NULL)
- {
- struct fg_targets *t = targets;
-
- targets = t->next;
- free(t->name);
- free(t);
- }
-}
-
-void load_groups(void)
-{
- passert(new_targets == NULL);
-
- /* for each group, add config file targets into new_targets */
- {
- struct fg_groups *g;
-
- for (g = groups; g != NULL; g = g->next)
- if (oriented(*g->connection))
- read_foodgroup(g);
- }
-
- /* dump new_targets */
- DBG(DBG_CONTROL,
- {
- struct fg_targets *t;
-
- for (t = new_targets; t != NULL; t = t->next)
- {
- char asource[SUBNETTOT_BUF];
- char atarget[SUBNETTOT_BUF];
-
- subnettot(&t->group->connection->spd.this.client
- , 0, asource, sizeof(asource));
- subnettot(&t->subnet, 0, atarget, sizeof(atarget));
- DBG_log("%s->%s %s"
- , asource, atarget
- , t->group->connection->name);
- }
- });
-
- /* determine and deal with differences between targets and new_targets.
- * structured like a merge.
- */
- {
- struct fg_targets *op = targets
- , *np = new_targets;
-
- while (op != NULL && np != NULL)
- {
- int r = subnetcmp(&op->group->connection->spd.this.client
- , &np->group->connection->spd.this.client);
-
- if (r == 0)
- r = subnetcmp(&op->subnet, &np->subnet);
-
- if (r == 0 && op->group == np->group)
- {
- /* unchanged -- steal name & skip over */
- np->name = op->name;
- op->name = NULL;
- op = op->next;
- np = np->next;
- }
- else
- {
- /* note: following cases overlap! */
- if (r <= 0)
- {
- remove_group_instance(op->group->connection, op->name);
- op = op->next;
- }
- if (r >= 0)
- {
- np->name = add_group_instance(np->group->connection, &np->subnet);
- np = np->next;
- }
- }
- }
- for (; op != NULL; op = op->next)
- remove_group_instance(op->group->connection, op->name);
- for (; np != NULL; np = np->next)
- np->name = add_group_instance(np->group->connection, &np->subnet);
-
- /* update: new_targets replaces targets */
- free_targets();
- targets = new_targets;
- new_targets = NULL;
- }
-}
-
-
-void add_group(connection_t *c)
-{
- struct fg_groups *g = malloc_thing(struct fg_groups);
-
- g->next = groups;
- groups = g;
-
- g->connection = c;
-}
-
-static struct fg_groups *find_group(const connection_t *c)
-{
- struct fg_groups *g;
-
- for (g = groups; g != NULL && g->connection != c; g = g->next)
- ;
- return g;
-}
-
-void route_group(connection_t *c)
-{
- /* it makes no sense to route a connection that is ISAKMP-only */
- if (!NEVER_NEGOTIATE(c->policy) && !HAS_IPSEC_POLICY(c->policy))
- {
- loglog(RC_ROUTE, "cannot route an ISAKMP-only group connection");
- }
- else
- {
- struct fg_groups *g = find_group(c);
- struct fg_targets *t;
-
- passert(g != NULL);
- g->connection->policy |= POLICY_GROUTED;
- for (t = targets; t != NULL; t = t->next)
- {
- if (t->group == g)
- {
- connection_t *ci = con_by_name(t->name, FALSE);
-
- if (ci != NULL)
- {
- set_cur_connection(ci);
- if (!trap_connection(ci))
- whack_log(RC_ROUTE, "could not route");
- set_cur_connection(c);
- }
- }
- }
- }
-}
-
-void unroute_group(connection_t *c)
-{
- struct fg_groups *g = find_group(c);
- struct fg_targets *t;
-
- passert(g != NULL);
- g->connection->policy &= ~POLICY_GROUTED;
- for (t = targets; t != NULL; t = t->next)
- {
- if (t->group == g)
- {
- connection_t *ci = con_by_name(t->name, FALSE);
-
- if (ci != NULL)
- {
- set_cur_connection(ci);
- unroute_connection(ci);
- set_cur_connection(c);
- }
- }
- }
-}
-
-void delete_group(const connection_t *c)
-{
- struct fg_groups *g;
-
- /* find and remove from groups */
- {
- struct fg_groups **pp;
-
- for (pp = &groups; (g = *pp)->connection != c; pp = &(*pp)->next)
- ;
-
- *pp = g->next;
- }
-
- /* find and remove from targets */
- {
- struct fg_targets **pp;
-
- for (pp = &targets; *pp != NULL; )
- {
- struct fg_targets *t = *pp;
-
- if (t->group == g)
- {
- *pp = t->next;
- remove_group_instance(t->group->connection, t->name);
- free(t);
- /* pp is ready for next iteration */
- }
- else
- {
- pp = &t->next;
- }
- }
- }
-
- free(g);
-}
diff --git a/src/pluto/foodgroups.h b/src/pluto/foodgroups.h
deleted file mode 100644
index b6d3386ae..000000000
--- a/src/pluto/foodgroups.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* Implement policygroups-style control files (aka "foodgroups")
- * Copyright (C) 2002 D. Hugh Redelmeier.
- *
- * 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.
- */
-
-struct connection; /* forward declaration */
-extern void add_group(struct connection *c);
-extern void route_group(struct connection *c);
-extern void unroute_group(struct connection *c);
-extern void delete_group(const struct connection *c);
-
-extern const char *policygroups_dir;
-extern void load_groups(void);
diff --git a/src/pluto/ike_alg.c b/src/pluto/ike_alg.c
deleted file mode 100644
index 3061630e0..000000000
--- a/src/pluto/ike_alg.c
+++ /dev/null
@@ -1,452 +0,0 @@
-/* IKE modular algorithm handling interface
- * Copyright (C) JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
- * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/queue.h>
-
-#include <freeswan.h>
-
-#include <library.h>
-#include <debug.h>
-#include <credentials/keys/public_key.h>
-#include <credentials/keys/private_key.h>
-#include <crypto/hashers/hasher.h>
-#include <crypto/crypters/crypter.h>
-#include <crypto/prfs/prf.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "crypto.h"
-#include "state.h"
-#include "packet.h"
-#include "keys.h"
-#include "log.h"
-#include "whack.h"
-#include "spdb.h"
-#include "alg_info.h"
-#include "ike_alg.h"
-#include "db_ops.h"
-#include "connections.h"
-#include "kernel.h"
-
-#define return_on(var, val) do { var=val;goto return_out; } while(0);
-
-/**
- * IKE algorithm list handling - registration and lookup
- */
-
-/* Modular IKE algorithm storage structure */
-
-static struct ike_alg *ike_alg_base[IKE_ALG_MAX+1] = {NULL, NULL};
-
-/**
- * Return ike_algo object by {type, id}
- */
-static struct ike_alg *ike_alg_find(u_int algo_type, u_int algo_id,
- u_int keysize __attribute__((unused)))
-{
- struct ike_alg *e = ike_alg_base[algo_type];
-
- while (e != NULL && algo_id > e->algo_id)
- {
- e = e->algo_next;
- }
- return (e != NULL && e->algo_id == algo_id) ? e : NULL;
-}
-
-/**
- * "raw" ike_alg list adding function
- */
-int ike_alg_add(struct ike_alg* a, const char *plugin_name)
-{
- if (a->algo_type > IKE_ALG_MAX)
- {
- plog("ike_alg: Not added, invalid algorithm type");
- return -EINVAL;
- }
-
- if (ike_alg_find(a->algo_type, a->algo_id, 0) != NULL)
- {
- plog("ike_alg: Not added, algorithm already exists");
- return -EEXIST;
- }
-
- {
- struct ike_alg **ep = &ike_alg_base[a->algo_type];
- struct ike_alg *e = *ep;
-
- while (e != NULL && a->algo_id > e->algo_id)
- {
- ep = &e->algo_next;
- e = *ep;
- }
- *ep = a;
- a->plugin_name = plugin_name;
- a->algo_next = e;
- return 0;
- }
-}
-
-/**
- * Get IKE hash algorithm
- */
-struct hash_desc *ike_alg_get_hasher(u_int alg)
-{
- return (struct hash_desc *) ike_alg_find(IKE_ALG_HASH, alg, 0);
-}
-
-/**
- * Get IKE encryption algorithm
- */
-struct encrypt_desc *ike_alg_get_crypter(u_int alg)
-{
- return (struct encrypt_desc *) ike_alg_find(IKE_ALG_ENCRYPT, alg, 0);
-}
-
-/**
- * Get IKE dh group
- */
-struct dh_desc *ike_alg_get_dh_group(u_int alg)
-{
- return (struct dh_desc *) ike_alg_find(IKE_ALG_DH_GROUP, alg, 0);
-}
-
-/**
- * Get pfsgroup for this connection
- */
-const struct dh_desc *ike_alg_pfsgroup(connection_t *c, lset_t policy)
-{
- const struct dh_desc *ret = NULL;
-
- if ((policy & POLICY_PFS) &&
- c->alg_info_esp && c->alg_info_esp->esp_pfsgroup)
- {
- ret = ike_alg_get_dh_group(c->alg_info_esp->esp_pfsgroup);
- }
- return ret;
-}
-
-/**
- * Create an OAKLEY proposal based on alg_info and policy
- */
-struct db_context *ike_alg_db_new(connection_t *c, lset_t policy)
-{
- struct alg_info_ike *ai = c->alg_info_ike;
- struct db_context *db_ctx = NULL;
- struct ike_info *ike_info;
- u_int ealg, halg, modp, eklen = 0;
- int i;
-
- bool is_xauth_server = (policy & POLICY_XAUTH_SERVER) != LEMPTY;
-
- if (!ai)
- {
- whack_log(RC_LOG_SERIOUS, "no IKE algorithms "
- "for this connection "
- "(check ike algorithm string)");
- goto fail;
- }
- policy &= POLICY_ID_AUTH_MASK;
- db_ctx = db_prop_new(PROTO_ISAKMP, 8, 8 * 5);
-
- /* for each group */
- ALG_INFO_IKE_FOREACH(ai, ike_info, i)
- {
- ealg = ike_info->ike_ealg;
- halg = ike_info->ike_halg;
- modp = ike_info->ike_modp;
- eklen= ike_info->ike_eklen;
-
- if (!ike_alg_get_crypter(ealg))
- {
- plog("ike alg: crypter %s not present",
- enum_show(&oakley_enc_names, ealg));
- continue;
- }
- if (!ike_alg_get_hasher(halg))
- {
- plog("ike alg: hasher %s not present",
- enum_show(&oakley_hash_names, halg));
- continue;
- }
- if (!ike_alg_get_dh_group(modp))
- {
- plog("ike alg: dh group %s not present",
- enum_show(&oakley_group_names, modp));
- continue;
- }
-
- if (policy & POLICY_PUBKEY)
- {
- int auth_method = 0, key_size = 0;
- key_type_t key_type = KEY_ANY;
-
- if (c->spd.this.cert)
- {
- certificate_t *certificate = c->spd.this.cert->cert;
- public_key_t *key = certificate->get_public_key(certificate);
-
- if (key == NULL)
- {
- plog("ike alg: unable to retrieve my public key");
- continue;
- }
- key_type = key->get_type(key);
- key_size = key->get_keysize(key);
- key->destroy(key);
- }
- else
- {
- private_key_t *key = get_private_key(c);
-
- if (key == NULL)
- {
- plog("ike alg: unable to retrieve my private key");
- continue;
- }
- key_type = key->get_type(key);
- key_size = key->get_keysize(key);
- }
- switch (key_type)
- {
- case KEY_RSA:
- auth_method = OAKLEY_RSA_SIG;
- break;
- case KEY_ECDSA:
- switch (key_size)
- {
- case 256:
- auth_method = OAKLEY_ECDSA_256;
- break;
- case 384:
- auth_method = OAKLEY_ECDSA_384;
- break;
- case 521:
- auth_method = OAKLEY_ECDSA_521;
- break;
- default:
- continue;
- }
- break;
- default:
- continue;
- }
- db_trans_add(db_ctx, KEY_IKE);
- db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg);
- db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg);
- if (eklen)
- {
- db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen);
- }
- db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD, auth_method);
- db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp);
- }
-
- if (policy & POLICY_PSK)
- {
- db_trans_add(db_ctx, KEY_IKE);
- db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg);
- db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg);
- if (eklen)
- {
- db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen);
- }
- db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY);
- db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp);
- }
-
- if (policy & POLICY_XAUTH_RSASIG)
- {
- db_trans_add(db_ctx, KEY_IKE);
- db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg);
- db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg);
- if (eklen)
- {
- db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen);
- }
- db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD
- , is_xauth_server ? XAUTHRespRSA : XAUTHInitRSA);
- db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp);
- }
-
- if (policy & POLICY_XAUTH_PSK)
- {
- db_trans_add(db_ctx, KEY_IKE);
- db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg);
- db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg);
- if (eklen)
- {
- db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen);
- }
- db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD
- , is_xauth_server ? XAUTHRespPreShared : XAUTHInitPreShared);
- db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp);
- }
- }
-fail:
- return db_ctx;
-}
-
-/**
- * Print the name of an algorithm plus the name of the plugin that registered it
- */
-static void print_alg(char *buf, int *len, enum_names *alg_names, int alg_type,
- const char *plugin_name)
-{
- char alg_name[BUF_LEN];
- int alg_name_len;
-
- alg_name_len = sprintf(alg_name, " %s[%s]", enum_name(alg_names, alg_type),
- plugin_name);
- if (*len + alg_name_len > CRYPTO_MAX_ALG_LINE)
- {
- whack_log(RC_COMMENT, "%s", buf);
- *len = sprintf(buf, " ");
- }
- sprintf(buf + *len, "%s", alg_name);
- *len += alg_name_len;
-}
-
-/**
- * Show registered IKE algorithms
- */
-void ike_alg_list(void)
-{
- rng_quality_t quality;
- enumerator_t *enumerator;
- const char *plugin_name;
- char buf[BUF_LEN];
- int len;
- struct ike_alg *a;
-
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, "List of registered IKEv1 Algorithms:");
- whack_log(RC_COMMENT, " ");
-
- len = sprintf(buf, " encryption:");
- for (a = ike_alg_base[IKE_ALG_ENCRYPT]; a != NULL; a = a->algo_next)
- {
- print_alg(buf, &len, &oakley_enc_names, a->algo_id, a->plugin_name);
- }
- whack_log(RC_COMMENT, "%s", buf);
-
- len = sprintf(buf, " integrity: ");
- for (a = ike_alg_base[IKE_ALG_HASH]; a != NULL; a = a->algo_next)
- {
- print_alg(buf, &len, &oakley_hash_names, a->algo_id, a->plugin_name);
- }
- whack_log(RC_COMMENT, "%s", buf);
-
- len = sprintf(buf, " dh-group: ");
- for (a = ike_alg_base[IKE_ALG_DH_GROUP]; a != NULL; a = a->algo_next)
- {
- print_alg(buf, &len, &oakley_group_names, a->algo_id, a->plugin_name);
- }
- whack_log(RC_COMMENT, "%s", buf);
-
- len = sprintf(buf, " random-gen:");
- enumerator = lib->crypto->create_rng_enumerator(lib->crypto);
- while (enumerator->enumerate(enumerator, &quality, &plugin_name))
- {
- len += sprintf(buf + len, " %N[%s]", rng_quality_names, quality,
- plugin_name);
- }
- enumerator->destroy(enumerator);
- whack_log(RC_COMMENT, "%s", buf);
-}
-
-/**
- * Show IKE algorithms for this connection (result from ike= string)
- * and newest SA
- */
-void ike_alg_show_connection(connection_t *c, const char *instance)
-{
- struct state *st = state_with_serialno(c->newest_isakmp_sa);
-
- if (st)
- {
- if (st->st_oakley.encrypt == OAKLEY_3DES_CBC)
- {
- whack_log(RC_COMMENT,
- "\"%s\"%s: IKE proposal: %s/%s/%s",
- c->name, instance,
- enum_show(&oakley_enc_names, st->st_oakley.encrypt),
- enum_show(&oakley_hash_names, st->st_oakley.hash),
- enum_show(&oakley_group_names, st->st_oakley.group->algo_id)
- );
- }
- else
- {
- whack_log(RC_COMMENT,
- "\"%s\"%s: IKE proposal: %s_%u/%s/%s",
- c->name, instance,
- enum_show(&oakley_enc_names, st->st_oakley.encrypt),
- st->st_oakley.enckeylen,
- enum_show(&oakley_hash_names, st->st_oakley.hash),
- enum_show(&oakley_group_names, st->st_oakley.group->algo_id)
- );
- }
- }
-}
-
-/**
- * ML: make F_STRICT logic consider enc,hash/auth,modp algorithms
- */
-bool ike_alg_ok_final(u_int ealg, u_int key_len, u_int aalg, u_int group,
- struct alg_info_ike *alg_info_ike)
-{
- /*
- * simple test to discard low key_len, will accept it only
- * if specified in "esp" string
- */
- bool ealg_insecure = (key_len < 128);
-
- if (ealg_insecure
- || (alg_info_ike && alg_info_ike->alg_info_flags & ALG_INFO_F_STRICT))
- {
- int i;
- struct ike_info *ike_info;
-
- if (alg_info_ike)
- {
- ALG_INFO_IKE_FOREACH(alg_info_ike, ike_info, i)
- {
- if (ike_info->ike_ealg == ealg
- && (ike_info->ike_eklen == 0 || key_len == 0 || ike_info->ike_eklen == key_len)
- && ike_info->ike_halg == aalg
- && ike_info->ike_modp == group)
- {
- if (ealg_insecure)
- loglog(RC_LOG_SERIOUS, "You should NOT use insecure IKE algorithms (%s)!"
- , enum_name(&oakley_enc_names, ealg));
- return TRUE;
- }
- }
- }
- plog("Oakley Transform [%s (%d), %s, %s] refused due to %s"
- , enum_name(&oakley_enc_names, ealg), key_len
- , enum_name(&oakley_hash_names, aalg)
- , enum_name(&oakley_group_names, group)
- , ealg_insecure ?
- "insecure key_len and enc. alg. not listed in \"ike\" string" : "strict flag"
- );
- return FALSE;
- }
- return TRUE;
-}
-
diff --git a/src/pluto/ike_alg.h b/src/pluto/ike_alg.h
deleted file mode 100644
index c3ce8bb38..000000000
--- a/src/pluto/ike_alg.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/* IKE modular algorithm handling interface
- * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
- *
- * 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.
- */
-
-#ifndef _IKE_ALG_H
-#define _IKE_ALG_H
-
-#include <freeswan.h>
-
-#include "connections.h"
-
-struct ike_alg {
- u_int16_t algo_type;
- u_int16_t algo_id;
- const char *plugin_name;
- struct ike_alg *algo_next;
-};
-
-struct encrypt_desc {
- u_int16_t algo_type;
- u_int16_t algo_id;
- const char *plugin_name;
- struct ike_alg *algo_next;
-
- size_t enc_blocksize;
- u_int keydeflen;
- u_int keymaxlen;
- u_int keyminlen;
-};
-
-struct hash_desc {
- u_int16_t algo_type;
- u_int16_t algo_id;
- const char *plugin_name;
- struct ike_alg *algo_next;
-
- size_t hash_digest_size;
-};
-
-struct dh_desc {
- u_int16_t algo_type;
- u_int16_t algo_id;
- const char *plugin_name;
- struct ike_alg *algo_next;
-
- size_t ke_size;
-};
-
-#define IKE_ALG_ENCRYPT 0
-#define IKE_ALG_HASH 1
-#define IKE_ALG_DH_GROUP 2
-#define IKE_ALG_MAX IKE_ALG_DH_GROUP
-
-extern int ike_alg_add(struct ike_alg *a, const char *plugin_name);
-extern struct hash_desc *ike_alg_get_hasher(u_int alg);
-extern struct encrypt_desc *ike_alg_get_crypter(u_int alg);
-extern struct dh_desc *ike_alg_get_dh_group(u_int alg);
-extern const struct dh_desc* ike_alg_pfsgroup(struct connection *c, lset_t policy);
-extern struct db_context * ike_alg_db_new(struct connection *c, lset_t policy);
-extern void ike_alg_list(void);
-extern void ike_alg_show_connection(struct connection *c, const char *instance);
-extern bool ike_alg_ok_final(u_int ealg, u_int key_len, u_int aalg, u_int group
- , struct alg_info_ike *alg_info_ike);
-extern int ike_alg_init(void);
-
-#endif /* _IKE_ALG_H */
diff --git a/src/pluto/ipsec_doi.c b/src/pluto/ipsec_doi.c
deleted file mode 100644
index 3e7adcc40..000000000
--- a/src/pluto/ipsec_doi.c
+++ /dev/null
@@ -1,5921 +0,0 @@
-/* IPsec DOI and Oakley resolution routines
- * Copyright (C) 1997 Angelos D. Keromytis.
- * Copyright (C) 1998-2002 D. Hugh Redelmeier.
- * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <resolv.h>
-#include <arpa/nameser.h> /* missing from <resolv.h> on old systems */
-#include <sys/queue.h>
-
-#include <freeswan.h>
-
-#include <library.h>
-#include <asn1/asn1.h>
-#include <crypto/hashers/hasher.h>
-#include <crypto/prfs/prf.h>
-#include <crypto/rngs/rng.h>
-#include <credentials/keys/private_key.h>
-#include <credentials/keys/public_key.h>
-#include <utils/identification.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "myid.h"
-#include "state.h"
-#include "x509.h"
-#include "ac.h"
-#include "crl.h"
-#include "ca.h"
-#include "certs.h"
-#include "smartcard.h"
-#include "connections.h"
-#include "keys.h"
-#include "packet.h"
-#include "demux.h" /* needs packet.h */
-#include "adns.h" /* needs <resolv.h> */
-#include "dnskey.h" /* needs keys.h and adns.h */
-#include "kernel.h"
-#include "log.h"
-#include "cookie.h"
-#include "server.h"
-#include "spdb.h"
-#include "timer.h"
-#include "ipsec_doi.h" /* needs demux.h and state.h */
-#include "whack.h"
-#include "fetch.h"
-#include "pkcs7.h"
-#include "crypto.h"
-#include "vendor.h"
-#include "alg_info.h"
-#include "ike_alg.h"
-#include "kernel_alg.h"
-#include "nat_traversal.h"
-#include "virtual.h"
-
-/*
- * are we sending Pluto's Vendor ID?
- */
-#ifdef VENDORID
-#define SEND_PLUTO_VID 1
-#else /* !VENDORID */
-#define SEND_PLUTO_VID 0
-#endif /* !VENDORID */
-
-/*
- * are we sending an XAUTH VID?
- */
-#ifdef XAUTH_VID
-#define SEND_XAUTH_VID 1
-#else /* !XAUTH_VID */
-#define SEND_XAUTH_VID 0
-#endif /* !XAUTH_VID */
-
-/*
- * are we sending a Cisco Unity VID?
- */
-#ifdef CISCO_QUIRKS
-#define SEND_CISCO_UNITY_VID 1
-#else /* !CISCO_QUIRKS */
-#define SEND_CISCO_UNITY_VID 0
-#endif /* !CISCO_QUIRKS */
-
-/* MAGIC: perform f, a function that returns notification_t
- * and return from the ENCLOSING stf_status returning function if it fails.
- */
-#define RETURN_STF_FAILURE(f) \
- { int r = (f); if (r != ISAKMP_NOTHING_WRONG) return STF_FAIL + r; }
-
-/* The endpoint(s) for which an SA is getting installed, so keying material
- * can be properly wiped.
- */
-enum endpoint {
- EP_LOCAL = 1,
- EP_REMOTE = 1 << 1,
-};
-
-/* create output HDR as replica of input HDR */
-void echo_hdr(struct msg_digest *md, bool enc, u_int8_t np)
-{
- struct isakmp_hdr r_hdr = md->hdr; /* mostly same as incoming header */
-
- r_hdr.isa_flags &= ~ISAKMP_FLAG_COMMIT; /* we won't ever turn on this bit */
- if (enc)
- {
- r_hdr.isa_flags |= ISAKMP_FLAG_ENCRYPTION;
- }
- /* some day, we may have to set r_hdr.isa_version */
- r_hdr.isa_np = np;
- if (!out_struct(&r_hdr, &isakmp_hdr_desc, &md->reply, &md->rbody))
- {
- impossible(); /* surely must have room and be well-formed */
- }
-}
-
-/* Compute DH shared secret from our local secret and the peer's public value.
- * We make the leap that the length should be that of the group
- * (see quoted passage at start of ACCEPT_KE).
- */
-static void compute_dh_shared(struct state *st, const chunk_t g)
-{
- passert(st->st_dh);
- st->st_dh->set_other_public_value(st->st_dh, g);
- st->st_dh->get_shared_secret(st->st_dh, &st->st_shared);
- DBG_cond_dump_chunk(DBG_CRYPT, "DH shared secret:\n", st->st_shared);
-}
-
-/* if we haven't already done so, compute a local DH secret (st->st_sec) and
- * the corresponding public value (g). This is emitted as a KE payload.
- */
-static bool build_and_ship_KE(struct state *st, chunk_t *g,
- const struct dh_desc *group,
- pb_stream *outs, u_int8_t np)
-{
- if (st->st_dh == NULL)
- {
- st->st_dh = lib->crypto->create_dh(lib->crypto, group->algo_id);
- if (st->st_dh == NULL)
- {
- plog("Diffie Hellman group %N is not available",
- diffie_hellman_group_names, group->algo_id);
- return FALSE;
- }
- }
- st->st_dh->get_my_public_value(st->st_dh, g);
- DBG(DBG_CRYPT,
- DBG_dump_chunk("Public DH value sent:\n", *g)
- )
- return out_generic_chunk(np, &isakmp_keyex_desc, outs, *g, "keyex value");
-}
-
-/* accept_ke
- *
- * Check and accept DH public value (Gi or Gr) from peer's message.
- * According to RFC2409 "The Internet key exchange (IKE)" 5:
- * The Diffie-Hellman public value passed in a KE payload, in either
- * a phase 1 or phase 2 exchange, MUST be the length of the negotiated
- * Diffie-Hellman group enforced, if necessary, by pre-pending the
- * value with zeros.
- */
-static notification_t accept_KE(chunk_t *dest, const char *val_name,
- const struct dh_desc *gr,
- pb_stream *pbs)
-{
- if (pbs_left(pbs) != gr->ke_size)
- {
- loglog(RC_LOG_SERIOUS, "KE has %u byte DH public value; %u required"
- , (unsigned) pbs_left(pbs), gr->ke_size);
- /* XXX Could send notification back */
- return ISAKMP_INVALID_KEY_INFORMATION;
- }
- free(dest->ptr);
- *dest = chunk_create(pbs->cur, pbs_left(pbs));
- *dest = chunk_clone(*dest);
- DBG_cond_dump_chunk(DBG_CRYPT, "DH public value received:\n", *dest);
- return ISAKMP_NOTHING_WRONG;
-}
-
-/* accept_PFS_KE
- *
- * Check and accept optional Quick Mode KE payload for PFS.
- * Extends ACCEPT_PFS to check whether KE is allowed or required.
- */
-static notification_t accept_PFS_KE(struct msg_digest *md, chunk_t *dest,
- const char *val_name, const char *msg_name)
-{
- struct state *st = md->st;
- struct payload_digest *const ke_pd = md->chain[ISAKMP_NEXT_KE];
-
- if (ke_pd == NULL)
- {
- if (st->st_pfs_group != NULL)
- {
- loglog(RC_LOG_SERIOUS, "missing KE payload in %s message", msg_name);
- return ISAKMP_INVALID_KEY_INFORMATION;
- }
- }
- else
- {
- if (st->st_pfs_group == NULL)
- {
- loglog(RC_LOG_SERIOUS, "%s message KE payload requires a GROUP_DESCRIPTION attribute in SA"
- , msg_name);
- return ISAKMP_INVALID_KEY_INFORMATION;
- }
- if (ke_pd->next != NULL)
- {
- loglog(RC_LOG_SERIOUS, "%s message contains several KE payloads; we accept at most one", msg_name);
- return ISAKMP_INVALID_KEY_INFORMATION; /* ??? */
- }
- return accept_KE(dest, val_name, st->st_pfs_group, &ke_pd->pbs);
- }
- return ISAKMP_NOTHING_WRONG;
-}
-
-static bool build_and_ship_nonce(chunk_t *n, pb_stream *outs, u_int8_t np,
- const char *name)
-{
- rng_t *rng;
-
- free(n->ptr);
- *n = chunk_create(malloc(DEFAULT_NONCE_SIZE), DEFAULT_NONCE_SIZE);
- rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
- rng->get_bytes(rng, DEFAULT_NONCE_SIZE, n->ptr);
- rng->destroy(rng);
- return out_generic_chunk(np, &isakmp_nonce_desc, outs, *n, name);
-}
-
-static linked_list_t* collect_rw_ca_candidates(struct msg_digest *md)
-{
- linked_list_t *list = linked_list_create();
- connection_t *d;
-
- d = find_host_connection(&md->iface->addr, pluto_port, (ip_address*)NULL,
- md->sender_port, LEMPTY);
-
- for (; d != NULL; d = d->hp_next)
- {
- /* must be a road warrior connection */
- if (d->kind == CK_TEMPLATE && !(d->policy & POLICY_OPPO) &&
- d->spd.that.ca)
- {
- enumerator_t *enumerator;
- identification_t *ca;
- bool new_entry = TRUE;
-
- enumerator = list->create_enumerator(list);
- while (enumerator->enumerate(enumerator, &ca))
- {
- if (ca->equals(ca, d->spd.that.ca))
- {
- new_entry = FALSE;
- break;
- }
- }
- enumerator->destroy(enumerator);
-
- if (new_entry)
- {
- list->insert_last(list, d->spd.that.ca->clone(d->spd.that.ca));
- }
- }
- }
- return list;
-}
-
-static bool build_and_ship_CR(u_int8_t type, chunk_t ca, pb_stream *outs,
- u_int8_t np)
-{
- pb_stream cr_pbs;
- struct isakmp_cr cr_hd;
- cr_hd.isacr_np = np;
- cr_hd.isacr_type = type;
-
- /* build CR header */
- if (!out_struct(&cr_hd, &isakmp_ipsec_cert_req_desc, outs, &cr_pbs))
- {
- return FALSE;
- }
- if (ca.ptr != NULL)
- {
- /* build CR body containing the distinguished name of the CA */
- if (!out_chunk(ca, &cr_pbs, "CA"))
- return FALSE;
- }
- close_output_pbs(&cr_pbs);
- return TRUE;
-}
-
-/* Send a notification to the peer. We could decide
- * whether to send the notification, based on the type and the
- * destination, if we care to.
- */
-static void send_notification(struct state *sndst, u_int16_t type,
- struct state *encst, msgid_t msgid,
- u_char *icookie, u_char *rcookie,
- u_char *spi, size_t spisize, u_char protoid)
-{
- u_char buffer[1024];
- pb_stream pbs, r_hdr_pbs;
- u_char *r_hashval = NULL; /* where in reply to jam hash value */
- u_char *r_hash_start = NULL; /* start of what is to be hashed */
-
- passert((sndst) && (sndst->st_connection));
-
- plog("sending %snotification %s to %s:%u"
- , encst ? "encrypted " : ""
- , enum_name(&notification_names, type)
- , ip_str(&sndst->st_connection->spd.that.host_addr)
- , (unsigned)sndst->st_connection->spd.that.host_port);
-
- memset(buffer, 0, sizeof(buffer));
- init_pbs(&pbs, buffer, sizeof(buffer), "ISAKMP notify");
-
- /* HDR* */
- {
- struct isakmp_hdr hdr;
-
- hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION;
- hdr.isa_np = encst ? ISAKMP_NEXT_HASH : ISAKMP_NEXT_N;
- hdr.isa_xchg = ISAKMP_XCHG_INFO;
- hdr.isa_msgid = msgid;
- hdr.isa_flags = encst ? ISAKMP_FLAG_ENCRYPTION : 0;
- if (icookie)
- {
- memcpy(hdr.isa_icookie, icookie, COOKIE_SIZE);
- }
- if (rcookie)
- {
- memcpy(hdr.isa_rcookie, rcookie, COOKIE_SIZE);
- }
- if (!out_struct(&hdr, &isakmp_hdr_desc, &pbs, &r_hdr_pbs))
- {
- impossible();
- }
- }
-
- /* HASH -- value to be filled later */
- if (encst)
- {
- pb_stream hash_pbs;
- if (!out_generic(ISAKMP_NEXT_N, &isakmp_hash_desc, &r_hdr_pbs, &hash_pbs))
- {
- impossible();
- }
- r_hashval = hash_pbs.cur; /* remember where to plant value */
- if (!out_zero(
- encst->st_oakley.hasher->hash_digest_size, &hash_pbs, "HASH"))
- {
- impossible();
- }
- close_output_pbs(&hash_pbs);
- r_hash_start = r_hdr_pbs.cur; /* hash from after HASH */
- }
-
- /* Notification Payload */
- {
- pb_stream not_pbs;
- struct isakmp_notification isan;
-
- isan.isan_doi = ISAKMP_DOI_IPSEC;
- isan.isan_np = ISAKMP_NEXT_NONE;
- isan.isan_type = type;
- isan.isan_spisize = spisize;
- isan.isan_protoid = protoid;
-
- if (!out_struct(&isan, &isakmp_notification_desc, &r_hdr_pbs, &not_pbs)
- || !out_raw(spi, spisize, &not_pbs, "spi"))
- {
- impossible();
- }
- close_output_pbs(&not_pbs);
- }
-
- /* calculate hash value and patch into Hash Payload */
- if (encst)
- {
- chunk_t msgid_chunk = chunk_from_thing(msgid);
- chunk_t msg_chunk = { r_hash_start, r_hdr_pbs.cur-r_hash_start };
- pseudo_random_function_t prf_alg;
- prf_t *prf;
-
- prf_alg = oakley_to_prf(encst->st_oakley.hash);
- prf = lib->crypto->create_prf(lib->crypto, prf_alg);
- prf->set_key(prf, encst->st_skeyid_a);
- prf->get_bytes(prf, msgid_chunk, NULL);
- prf->get_bytes(prf, msg_chunk, r_hashval);
-
- DBG(DBG_CRYPT,
- DBG_log("HASH computed:");
- DBG_dump("", r_hashval, prf->get_block_size(prf));
- )
- prf->destroy(prf);
- }
-
- /* Encrypt message (preserve st_iv and st_new_iv) */
- if (encst)
- {
- u_char old_iv[MAX_DIGEST_LEN];
- u_char new_iv[MAX_DIGEST_LEN];
-
- u_int old_iv_len = encst->st_iv_len;
- u_int new_iv_len = encst->st_new_iv_len;
-
- if (old_iv_len > MAX_DIGEST_LEN || new_iv_len > MAX_DIGEST_LEN)
- {
- impossible();
- }
- memcpy(old_iv, encst->st_iv, old_iv_len);
- memcpy(new_iv, encst->st_new_iv, new_iv_len);
-
- if (!IS_ISAKMP_SA_ESTABLISHED(encst->st_state))
- {
- memcpy(encst->st_ph1_iv, encst->st_new_iv, encst->st_new_iv_len);
- encst->st_ph1_iv_len = encst->st_new_iv_len;
- }
- init_phase2_iv(encst, &msgid);
- if (!encrypt_message(&r_hdr_pbs, encst))
- {
- impossible();
- }
-
- /* restore preserved st_iv and st_new_iv */
- memcpy(encst->st_iv, old_iv, old_iv_len);
- memcpy(encst->st_new_iv, new_iv, new_iv_len);
- encst->st_iv_len = old_iv_len;
- encst->st_new_iv_len = new_iv_len;
- }
- else
- {
- close_output_pbs(&r_hdr_pbs);
- }
-
- /* Send packet (preserve st_tpacket) */
- {
- chunk_t saved_tpacket = sndst->st_tpacket;
-
- sndst->st_tpacket = chunk_create(pbs.start, pbs_offset(&pbs));
- send_packet(sndst, "ISAKMP notify");
- sndst->st_tpacket = saved_tpacket;
- }
-}
-
-void send_notification_from_state(struct state *st, enum state_kind state,
- u_int16_t type)
-{
- struct state *p1st;
-
- passert(st);
-
- if (state == STATE_UNDEFINED)
- state = st->st_state;
-
- if (IS_QUICK(state))
- {
- p1st = find_phase1_state(st->st_connection, ISAKMP_SA_ESTABLISHED_STATES);
- if ((p1st == NULL) || (!IS_ISAKMP_SA_ESTABLISHED(p1st->st_state)))
- {
- loglog(RC_LOG_SERIOUS,
- "no Phase1 state for Quick mode notification");
- return;
- }
- send_notification(st, type, p1st, generate_msgid(p1st),
- st->st_icookie, st->st_rcookie, NULL, 0, PROTO_ISAKMP);
- }
- else if (IS_ISAKMP_ENCRYPTED(state) && st->st_enc_key.ptr != NULL)
- {
- send_notification(st, type, st, generate_msgid(st),
- st->st_icookie, st->st_rcookie, NULL, 0, PROTO_ISAKMP);
- }
- else
- {
- /* no ISAKMP SA established - don't encrypt notification */
- send_notification(st, type, NULL, 0,
- st->st_icookie, st->st_rcookie, NULL, 0, PROTO_ISAKMP);
- }
-}
-
-void send_notification_from_md(struct msg_digest *md, u_int16_t type)
-{
- /**
- * Create a dummy state to be able to use send_packet in
- * send_notification
- *
- * we need to set:
- * st_connection->that.host_addr
- * st_connection->that.host_port
- * st_connection->interface
- */
- struct state st;
- connection_t cnx;
-
- passert(md);
-
- memset(&st, 0, sizeof(st));
- memset(&cnx, 0, sizeof(cnx));
- st.st_connection = &cnx;
- cnx.spd.that.host_addr = md->sender;
- cnx.spd.that.host_port = md->sender_port;
- cnx.interface = md->iface;
-
- send_notification(&st, type, NULL, 0,
- md->hdr.isa_icookie, md->hdr.isa_rcookie, NULL, 0, PROTO_ISAKMP);
-}
-
-/* Send a Delete Notification to announce deletion of ISAKMP SA or
- * inbound IPSEC SAs. Does nothing if no such SAs are being deleted.
- * Delete Notifications cannot announce deletion of outbound IPSEC/ISAKMP SAs.
- */
-void send_delete(struct state *st)
-{
- pb_stream reply_pbs;
- pb_stream r_hdr_pbs;
- msgid_t msgid;
- u_char buffer[8192];
- struct state *p1st;
- ip_said said[EM_MAXRELSPIS];
- ip_said *ns = said;
- u_char
- *r_hashval, /* where in reply to jam hash value */
- *r_hash_start; /* start of what is to be hashed */
- bool isakmp_sa = FALSE;
-
- if (IS_IPSEC_SA_ESTABLISHED(st->st_state))
- {
- p1st = find_phase1_state(st->st_connection, ISAKMP_SA_ESTABLISHED_STATES);
- if (p1st == NULL)
- {
- DBG(DBG_CONTROL, DBG_log("no Phase 1 state for Delete"));
- return;
- }
-
- if (st->st_ah.present)
- {
- ns->spi = st->st_ah.our_spi;
- ns->dst = st->st_connection->spd.this.host_addr;
- ns->proto = PROTO_IPSEC_AH;
- ns++;
- }
- if (st->st_esp.present)
- {
- ns->spi = st->st_esp.our_spi;
- ns->dst = st->st_connection->spd.this.host_addr;
- ns->proto = PROTO_IPSEC_ESP;
- ns++;
- }
-
- passert(ns != said); /* there must be some SAs to delete */
- }
- else if (IS_ISAKMP_SA_ESTABLISHED(st->st_state))
- {
- p1st = st;
- isakmp_sa = TRUE;
- }
- else
- {
- return; /* nothing to do */
- }
-
- msgid = generate_msgid(p1st);
-
- zero(buffer);
- init_pbs(&reply_pbs, buffer, sizeof(buffer), "delete msg");
-
- /* HDR* */
- {
- struct isakmp_hdr hdr;
-
- hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION;
- hdr.isa_np = ISAKMP_NEXT_HASH;
- hdr.isa_xchg = ISAKMP_XCHG_INFO;
- hdr.isa_msgid = msgid;
- hdr.isa_flags = ISAKMP_FLAG_ENCRYPTION;
- memcpy(hdr.isa_icookie, p1st->st_icookie, COOKIE_SIZE);
- memcpy(hdr.isa_rcookie, p1st->st_rcookie, COOKIE_SIZE);
- if (!out_struct(&hdr, &isakmp_hdr_desc, &reply_pbs, &r_hdr_pbs))
- impossible();
- }
-
- /* HASH -- value to be filled later */
- {
- pb_stream hash_pbs;
-
- if (!out_generic(ISAKMP_NEXT_D, &isakmp_hash_desc, &r_hdr_pbs, &hash_pbs))
- {
- impossible();
- }
- r_hashval = hash_pbs.cur; /* remember where to plant value */
- if (!out_zero(p1st->st_oakley.hasher->hash_digest_size, &hash_pbs, "HASH(1)"))
- {
- impossible();
- }
- close_output_pbs(&hash_pbs);
- r_hash_start = r_hdr_pbs.cur; /* hash from after HASH(1) */
- }
-
- /* Delete Payloads */
- if (isakmp_sa)
- {
- pb_stream del_pbs;
- struct isakmp_delete isad;
- u_char isakmp_spi[2*COOKIE_SIZE];
-
- isad.isad_doi = ISAKMP_DOI_IPSEC;
- isad.isad_np = ISAKMP_NEXT_NONE;
- isad.isad_spisize = (2 * COOKIE_SIZE);
- isad.isad_protoid = PROTO_ISAKMP;
- isad.isad_nospi = 1;
-
- memcpy(isakmp_spi, st->st_icookie, COOKIE_SIZE);
- memcpy(isakmp_spi+COOKIE_SIZE, st->st_rcookie, COOKIE_SIZE);
-
- if (!out_struct(&isad, &isakmp_delete_desc, &r_hdr_pbs, &del_pbs)
- || !out_raw(&isakmp_spi, (2*COOKIE_SIZE), &del_pbs, "delete payload"))
- {
- impossible();
- }
- close_output_pbs(&del_pbs);
- }
- else
- {
- while (ns != said)
- {
-
- pb_stream del_pbs;
- struct isakmp_delete isad;
-
- ns--;
- isad.isad_doi = ISAKMP_DOI_IPSEC;
- isad.isad_np = ns == said? ISAKMP_NEXT_NONE : ISAKMP_NEXT_D;
- isad.isad_spisize = sizeof(ipsec_spi_t);
- isad.isad_protoid = ns->proto;
-
- isad.isad_nospi = 1;
- if (!out_struct(&isad, &isakmp_delete_desc, &r_hdr_pbs, &del_pbs)
- || !out_raw(&ns->spi, sizeof(ipsec_spi_t), &del_pbs, "delete payload"))
- {
- impossible();
- }
- close_output_pbs(&del_pbs);
- }
- }
-
- /* calculate hash value and patch into Hash Payload */
- {
- chunk_t msgid_chunk = chunk_from_thing(msgid);
- chunk_t msg_chunk = { r_hash_start, r_hdr_pbs.cur-r_hash_start };
- pseudo_random_function_t prf_alg;
- prf_t *prf;
-
- prf_alg = oakley_to_prf(p1st->st_oakley.hash);
- prf = lib->crypto->create_prf(lib->crypto, prf_alg);
- prf->set_key(prf, p1st->st_skeyid_a);
- prf->get_bytes(prf, msgid_chunk, NULL);
- prf->get_bytes(prf, msg_chunk, r_hashval);
-
- DBG(DBG_CRYPT,
- DBG_log("HASH(1) computed:");
- DBG_dump("", r_hashval, prf->get_block_size(prf));
- )
-
- prf->destroy(prf);
- }
-
- /* Do a dance to avoid needing a new state object.
- * We use the Phase 1 State. This is the one with right
- * IV, for one thing.
- * The tricky bits are:
- * - we need to preserve (save/restore) st_iv (but not st_iv_new)
- * - we need to preserve (save/restore) st_tpacket.
- */
- {
- u_char old_iv[MAX_DIGEST_LEN];
- chunk_t saved_tpacket = p1st->st_tpacket;
-
- memcpy(old_iv, p1st->st_iv, p1st->st_iv_len);
- init_phase2_iv(p1st, &msgid);
-
- if (!encrypt_message(&r_hdr_pbs, p1st))
- {
- impossible();
- }
- p1st->st_tpacket = chunk_create(reply_pbs.start, pbs_offset(&reply_pbs));
- send_packet(p1st, "delete notify");
- p1st->st_tpacket = saved_tpacket;
-
- /* get back old IV for this state */
- memcpy(p1st->st_iv, old_iv, p1st->st_iv_len);
- }
-}
-
-void accept_delete(struct state *st, struct msg_digest *md,
- struct payload_digest *p)
-{
- struct isakmp_delete *d = &(p->payload.delete);
- identification_t *this_id = NULL, *that_id = NULL;
- ip_address peer_addr;
- size_t sizespi;
- int i;
-
- if (!md->encrypted)
- {
- loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload: not encrypted");
- return;
- }
-
- if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state))
- {
- /* can't happen (if msg is encrypt), but just to be sure */
- loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload: "
- "ISAKMP SA not established");
- return;
- }
-
- if (d->isad_nospi == 0)
- {
- loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload: no SPI");
- return;
- }
-
- switch (d->isad_protoid)
- {
- case PROTO_ISAKMP:
- sizespi = 2 * COOKIE_SIZE;
- break;
- case PROTO_IPSEC_AH:
- case PROTO_IPSEC_ESP:
- sizespi = sizeof(ipsec_spi_t);
- break;
- case PROTO_IPCOMP:
- /* nothing interesting to delete */
- return;
- default:
- loglog(RC_LOG_SERIOUS
- , "ignoring Delete SA payload: unknown Protocol ID (%s)"
- , enum_show(&protocol_names, d->isad_protoid));
- return;
- }
-
- if (d->isad_spisize != sizespi)
- {
- loglog(RC_LOG_SERIOUS
- , "ignoring Delete SA payload: bad SPI size (%d) for %s"
- , d->isad_spisize, enum_show(&protocol_names, d->isad_protoid));
- return;
- }
-
- if (pbs_left(&p->pbs) != d->isad_nospi * sizespi)
- {
- loglog(RC_LOG_SERIOUS
- , "ignoring Delete SA payload: invalid payload size");
- return;
- }
-
- if (d->isad_protoid == PROTO_ISAKMP)
- {
- struct end *this = &st->st_connection->spd.this;
- struct end *that = &st->st_connection->spd.that;
- this_id = this->id->clone(this->id);
- that_id = that->id->clone(that->id);
- peer_addr = st->st_connection->spd.that.host_addr;
- }
-
- for (i = 0; i < d->isad_nospi; i++)
- {
- u_char *spi = p->pbs.cur + (i * sizespi);
-
- if (d->isad_protoid == PROTO_ISAKMP)
- {
- /**
- * ISAKMP
- */
- struct state *dst = find_state(spi /*iCookie*/
- , spi+COOKIE_SIZE /*rCookie*/
- , &peer_addr
- , MAINMODE_MSGID);
-
- if (dst == NULL)
- {
- loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload: "
- "ISAKMP SA not found (maybe expired)");
- }
- else if (! this_id->equals(this_id, dst->st_connection->spd.this.id) ||
- ! that_id->equals(that_id, dst->st_connection->spd.that.id))
- {
- /* we've not authenticated the relevant identities */
- loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload: "
- "ISAKMP SA used to convey Delete has different IDs from ISAKMP SA it deletes");
- }
- else
- {
- connection_t *oldc;
-
- oldc = cur_connection;
- set_cur_connection(dst->st_connection);
-
- if (nat_traversal_enabled)
- {
- nat_traversal_change_port_lookup(md, dst);
- }
- loglog(RC_LOG_SERIOUS, "received Delete SA payload: "
- "deleting ISAKMP State #%lu", dst->st_serialno);
- delete_state(dst);
- set_cur_connection(oldc);
- }
- }
- else
- {
- /**
- * IPSEC (ESP/AH)
- */
- bool bogus;
- struct state *dst = find_phase2_state_to_delete(st
- , d->isad_protoid
- , *(ipsec_spi_t *)spi /* network order */
- , &bogus);
-
- if (dst == NULL)
- {
- loglog(RC_LOG_SERIOUS
- , "ignoring Delete SA payload: %s SA(0x%08lx) not found (%s)"
- , enum_show(&protocol_names, d->isad_protoid)
- , (unsigned long)ntohl((unsigned long)*(ipsec_spi_t *)spi)
- , bogus ? "our SPI - bogus implementation" : "maybe expired");
- }
- else
- {
- connection_t *rc = dst->st_connection;
- connection_t *oldc;
-
- oldc = cur_connection;
- set_cur_connection(rc);
-
- if (nat_traversal_enabled)
- {
- nat_traversal_change_port_lookup(md, dst);
- }
- if (rc->newest_ipsec_sa == dst->st_serialno
- && (rc->policy & POLICY_UP))
- {
- /* Last IPSec SA for a permanent connection that we
- * have initiated. Replace it in a few seconds.
- *
- * Useful if the other peer is rebooting.
- */
-#define DELETE_SA_DELAY EVENT_RETRANSMIT_DELAY_0
- if (dst->st_event != NULL
- && dst->st_event->ev_type == EVENT_SA_REPLACE
- && dst->st_event->ev_time <= DELETE_SA_DELAY + now())
- {
- /* Patch from Angus Lees to ignore retransmited
- * Delete SA.
- */
- loglog(RC_LOG_SERIOUS, "received Delete SA payload: "
- "already replacing IPSEC State #%lu in %d seconds"
- , dst->st_serialno, (int)(dst->st_event->ev_time - now()));
- }
- else
- {
- loglog(RC_LOG_SERIOUS, "received Delete SA payload: "
- "replace IPSEC State #%lu in %d seconds"
- , dst->st_serialno, DELETE_SA_DELAY);
- dst->st_margin = DELETE_SA_DELAY;
- delete_event(dst);
- event_schedule(EVENT_SA_REPLACE, DELETE_SA_DELAY, dst);
- }
- }
- else
- {
- loglog(RC_LOG_SERIOUS, "received Delete SA(0x%08lx) payload: "
- "deleting IPSEC State #%lu"
- , (unsigned long)ntohl((unsigned long)*(ipsec_spi_t *)spi)
- , dst->st_serialno);
- delete_state(dst);
- }
-
- /* reset connection */
- set_cur_connection(oldc);
- }
- }
- }
-
- if (d->isad_protoid == PROTO_ISAKMP)
- {
- this_id->destroy(this_id);
- that_id->destroy(that_id);
- }
-}
-
-/* The whole message must be a multiple of 4 octets.
- * I'm not sure where this is spelled out, but look at
- * rfc2408 3.6 Transform Payload.
- * Note: it talks about 4 BYTE boundaries!
- */
-void close_message(pb_stream *pbs)
-{
- size_t padding = pad_up(pbs_offset(pbs), 4);
-
- if (padding != 0)
- {
- (void) out_zero(padding, pbs, "message padding");
- }
- close_output_pbs(pbs);
-}
-
-/* Initiate an Oakley Main Mode exchange.
- * --> HDR;SA
- * Note: this is not called from demux.c
- */
-static stf_status
-main_outI1(int whack_sock, connection_t *c, struct state *predecessor
- , lset_t policy, unsigned long try)
-{
- struct state *st = new_state();
- pb_stream reply; /* not actually a reply, but you know what I mean */
- pb_stream rbody;
- int vids_to_send = 0;
-
- /* set up new state */
- st->st_connection = c;
- set_cur_state(st); /* we must reset before exit */
- st->st_policy = policy & ~POLICY_IPSEC_MASK;
- st->st_whack_sock = whack_sock;
- st->st_try = try;
- st->st_state = STATE_MAIN_I1;
-
- /* determine how many Vendor ID payloads we will be sending */
- if (SEND_PLUTO_VID)
- {
- vids_to_send++;
- }
- if (SEND_CISCO_UNITY_VID)
- {
- vids_to_send++;
- }
- if (c->spd.this.cert &&
- c->spd.this.cert->cert->get_type(c->spd.this.cert->cert) == CERT_GPG)
- {
- vids_to_send++;
- }
- if (SEND_XAUTH_VID)
- {
- vids_to_send++;
- }
-
- /* always send DPD Vendor ID */
- vids_to_send++;
-
- if (nat_traversal_enabled)
- {
- vids_to_send++;
- }
-
- get_cookie(TRUE, st->st_icookie, COOKIE_SIZE, &c->spd.that.host_addr);
-
- insert_state(st); /* needs cookies, connection, and msgid (0) */
-
- if (HAS_IPSEC_POLICY(policy))
- {
- add_pending(dup_any(whack_sock), st, c, policy, 1
- , predecessor == NULL? SOS_NOBODY : predecessor->st_serialno);
- }
- if (predecessor == NULL)
- {
- plog("initiating Main Mode");
- }
- else
- {
- plog("initiating Main Mode to replace #%lu", predecessor->st_serialno);
- }
-
- /* set up reply */
- init_pbs(&reply, reply_buffer, sizeof(reply_buffer), "reply packet");
-
- /* HDR out */
- {
- struct isakmp_hdr hdr;
-
- zero(&hdr); /* default to 0 */
- hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION;
- hdr.isa_np = ISAKMP_NEXT_SA;
- hdr.isa_xchg = ISAKMP_XCHG_IDPROT;
- memcpy(hdr.isa_icookie, st->st_icookie, COOKIE_SIZE);
- /* R-cookie, flags and MessageID are left zero */
-
- if (!out_struct(&hdr, &isakmp_hdr_desc, &reply, &rbody))
- {
- reset_cur_state();
- return STF_INTERNAL_ERROR;
- }
- }
-
- /* SA out */
- {
- u_char *sa_start = rbody.cur;
-
- if (!out_sa(&rbody, &oakley_sadb, st, TRUE
- , vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE))
- {
- reset_cur_state();
- return STF_INTERNAL_ERROR;
- }
-
- /* save initiator SA for later HASH */
- passert(st->st_p1isa.ptr == NULL); /* no leak! (MUST be first time) */
- st->st_p1isa = chunk_create(sa_start, rbody.cur - sa_start);
- st->st_p1isa = chunk_clone(st->st_p1isa);
- }
-
- /* if enabled send Pluto Vendor ID */
- if (SEND_PLUTO_VID)
- {
- if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
- , &rbody, VID_STRONGSWAN))
- {
- reset_cur_state();
- return STF_INTERNAL_ERROR;
- }
- }
-
- /* if enabled send Cisco Unity Vendor ID */
- if (SEND_CISCO_UNITY_VID)
- {
- if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
- , &rbody, VID_CISCO_UNITY))
- {
- reset_cur_state();
- return STF_INTERNAL_ERROR;
- }
- }
- /* if we have an OpenPGP certificate we assume an
- * OpenPGP peer and have to send the Vendor ID
- */
- if (c->spd.this.cert &&
- c->spd.this.cert->cert->get_type(c->spd.this.cert->cert) == CERT_GPG)
- {
- if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
- , &rbody, VID_OPENPGP))
- {
- reset_cur_state();
- return STF_INTERNAL_ERROR;
- }
- }
-
- /* Announce our ability to do eXtended AUTHentication to the peer */
- if (SEND_XAUTH_VID)
- {
- if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
- , &rbody, VID_MISC_XAUTH))
- {
- reset_cur_state();
- return STF_INTERNAL_ERROR;
- }
- }
-
- /* Announce our ability to do Dead Peer Detection to the peer */
- {
- if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
- , &rbody, VID_MISC_DPD))
- {
- reset_cur_state();
- return STF_INTERNAL_ERROR;
- }
- }
-
- if (nat_traversal_enabled)
- {
- /* Add supported NAT-Traversal VID */
- if (!nat_traversal_add_vid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
- , &rbody))
- {
- reset_cur_state();
- return STF_INTERNAL_ERROR;
- }
- }
-
- close_message(&rbody);
- close_output_pbs(&reply);
- st->st_tpacket = chunk_create(reply.start, pbs_offset(&reply));
- st->st_tpacket = chunk_clone(st->st_tpacket);
-
- /* Transmit */
-
- send_packet(st, "main_outI1");
-
- /* Set up a retransmission event, half a minute henceforth */
- delete_event(st);
- event_schedule(EVENT_RETRANSMIT, EVENT_RETRANSMIT_DELAY_0, st);
-
- if (predecessor != NULL)
- {
- update_pending(predecessor, st);
- whack_log(RC_NEW_STATE + STATE_MAIN_I1
- , "%s: initiate, replacing #%lu"
- , enum_name(&state_names, st->st_state)
- , predecessor->st_serialno);
- }
- else
- {
- whack_log(RC_NEW_STATE + STATE_MAIN_I1
- , "%s: initiate", enum_name(&state_names, st->st_state));
- }
- reset_cur_state();
- return STF_OK;
-}
-
-void ipsecdoi_initiate(int whack_sock, connection_t *c, lset_t policy,
- unsigned long try, so_serial_t replacing)
-{
- /* If there's already an ISAKMP SA established, use that and
- * go directly to Quick Mode. We are even willing to use one
- * that is still being negotiated, but only if we are the Initiator
- * (thus we can be sure that the IDs are not going to change;
- * other issues around intent might matter).
- * Note: there is no way to initiate with a Road Warrior.
- */
- struct state *st = find_phase1_state(c
- , ISAKMP_SA_ESTABLISHED_STATES | PHASE1_INITIATOR_STATES);
-
- if (st == NULL)
- {
- (void) main_outI1(whack_sock, c, NULL, policy, try);
- }
- else if (HAS_IPSEC_POLICY(policy))
- {
- if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state))
- {
- /* leave our Phase 2 negotiation pending */
- add_pending(whack_sock, st, c, policy, try, replacing);
- }
- else
- {
- /* ??? we assume that peer_nexthop_sin isn't important:
- * we already have it from when we negotiated the ISAKMP SA!
- * It isn't clear what to do with the error return.
- */
- (void) quick_outI1(whack_sock, st, c, policy, try, replacing);
- }
- }
- else
- {
- close_any(whack_sock);
- }
-}
-
-/* Replace SA with a fresh one that is similar
- *
- * Shares some logic with ipsecdoi_initiate, but not the same!
- * - we must not reuse the ISAKMP SA if we are trying to replace it!
- * - if trying to replace IPSEC SA, use ipsecdoi_initiate to build
- * ISAKMP SA if needed.
- * - duplicate whack fd, if live.
- * Does not delete the old state -- someone else will do that.
- */
-void ipsecdoi_replace(struct state *st, unsigned long try)
-{
- int whack_sock = dup_any(st->st_whack_sock);
- lset_t policy = st->st_policy;
-
- if (IS_PHASE1(st->st_state))
- {
- passert(!HAS_IPSEC_POLICY(policy));
- (void) main_outI1(whack_sock, st->st_connection, st, policy, try);
- }
- else
- {
- /* Add features of actual old state to policy. This ensures
- * that rekeying doesn't downgrade security. I admit that
- * this doesn't capture everything.
- */
- if (st->st_pfs_group != NULL)
- policy |= POLICY_PFS;
- if (st->st_ah.present)
- {
- policy |= POLICY_AUTHENTICATE;
- if (st->st_ah.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL)
- policy |= POLICY_TUNNEL;
- }
- if (st->st_esp.present && st->st_esp.attrs.transid != ESP_NULL)
- {
- policy |= POLICY_ENCRYPT;
- if (st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL)
- policy |= POLICY_TUNNEL;
- }
- if (st->st_ipcomp.present)
- {
- policy |= POLICY_COMPRESS;
- if (st->st_ipcomp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL)
- policy |= POLICY_TUNNEL;
- }
- passert(HAS_IPSEC_POLICY(policy));
- ipsecdoi_initiate(whack_sock, st->st_connection, policy, try
- , st->st_serialno);
- }
-}
-
-/* SKEYID for preshared keys.
- * See draft-ietf-ipsec-ike-01.txt 4.1
- */
-static bool skeyid_preshared(struct state *st)
-{
- const chunk_t *pss = get_preshared_secret(st->st_connection);
-
- if (pss == NULL)
- {
- loglog(RC_LOG_SERIOUS, "preshared secret disappeared!");
- return FALSE;
- }
- else
- {
- pseudo_random_function_t prf_alg;
- prf_t *prf;
-
- prf_alg = oakley_to_prf(st->st_oakley.hash);
- prf = lib->crypto->create_prf(lib->crypto, prf_alg);
- if (prf == NULL)
- {
- loglog(RC_LOG_SERIOUS, "%N not available to compute skeyid",
- pseudo_random_function_names, prf_alg);
- return FALSE;
- }
- free(st->st_skeyid.ptr);
- prf->set_key(prf, *pss);
- prf->allocate_bytes(prf, st->st_ni, NULL);
- prf->allocate_bytes(prf, st->st_nr, &st->st_skeyid);
- prf->destroy(prf);
- return TRUE;
- }
-}
-
-static bool skeyid_digisig(struct state *st)
-{
- chunk_t nir;
- pseudo_random_function_t prf_alg;
- prf_t *prf;
-
- prf_alg = oakley_to_prf(st->st_oakley.hash);
- prf = lib->crypto->create_prf(lib->crypto, prf_alg);
- if (prf == NULL)
- {
- loglog(RC_LOG_SERIOUS, "%N not available to compute skeyid",
- pseudo_random_function_names, prf_alg);
- return FALSE;
- }
- free(st->st_skeyid.ptr);
- nir = chunk_cat("cc", st->st_ni, st->st_nr);
- prf->set_key(prf, nir);
- prf->allocate_bytes(prf, st->st_shared, &st->st_skeyid);
- prf->destroy(prf);
- free(nir.ptr);
- return TRUE;
-}
-
-/* Generate the SKEYID_* and new IV
- * See draft-ietf-ipsec-ike-01.txt 4.1
- */
-static bool generate_skeyids_iv(struct state *st)
-{
- /* Generate the SKEYID */
- switch (st->st_oakley.auth)
- {
- case OAKLEY_PRESHARED_KEY:
- case XAUTHInitPreShared:
- case XAUTHRespPreShared:
- if (!skeyid_preshared(st))
- {
- return FALSE;
- }
- break;
-
- case OAKLEY_RSA_SIG:
- case OAKLEY_ECDSA_256:
- case OAKLEY_ECDSA_384:
- case OAKLEY_ECDSA_521:
- case XAUTHInitRSA:
- case XAUTHRespRSA:
- if (!skeyid_digisig(st))
- {
- return FALSE;
- }
- break;
-
- case OAKLEY_DSS_SIG:
- /* XXX */
-
- case OAKLEY_RSA_ENC:
- case OAKLEY_RSA_ENC_REV:
- case OAKLEY_ELGAMAL_ENC:
- case OAKLEY_ELGAMAL_ENC_REV:
- /* XXX */
-
- default:
- bad_case(st->st_oakley.auth);
- }
-
- /* generate SKEYID_* from SKEYID */
- {
- chunk_t seed_skeyid_d = chunk_from_chars(0x00);
- chunk_t seed_skeyid_a = chunk_from_chars(0x01);
- chunk_t seed_skeyid_e = chunk_from_chars(0x02);
- chunk_t icookie = { st->st_icookie, COOKIE_SIZE };
- chunk_t rcookie = { st->st_rcookie, COOKIE_SIZE };
- pseudo_random_function_t prf_alg;
- prf_t *prf;
-
- prf_alg = oakley_to_prf(st->st_oakley.hash);
- prf = lib->crypto->create_prf(lib->crypto, prf_alg);
- prf->set_key(prf, st->st_skeyid);
-
- /* SKEYID_D */
- free(st->st_skeyid_d.ptr);
- prf->allocate_bytes(prf, st->st_shared, NULL);
- prf->allocate_bytes(prf, icookie, NULL);
- prf->allocate_bytes(prf, rcookie, NULL);
- prf->allocate_bytes(prf, seed_skeyid_d, &st->st_skeyid_d);
-
- /* SKEYID_A */
- free(st->st_skeyid_a.ptr);
- prf->allocate_bytes(prf, st->st_skeyid_d, NULL);
- prf->allocate_bytes(prf, st->st_shared, NULL);
- prf->allocate_bytes(prf, icookie, NULL);
- prf->allocate_bytes(prf, rcookie, NULL);
- prf->allocate_bytes(prf, seed_skeyid_a, &st->st_skeyid_a);
-
- /* SKEYID_E */
- free(st->st_skeyid_e.ptr);
- prf->allocate_bytes(prf, st->st_skeyid_a, NULL);
- prf->allocate_bytes(prf, st->st_shared, NULL);
- prf->allocate_bytes(prf, icookie, NULL);
- prf->allocate_bytes(prf, rcookie, NULL);
- prf->allocate_bytes(prf, seed_skeyid_e, &st->st_skeyid_e);
-
- prf->destroy(prf);
- }
-
- /* generate IV */
- {
- hash_algorithm_t hash_alg;
- hasher_t *hasher;
-
- hash_alg = oakley_to_hash_algorithm(st->st_oakley.hash);
- hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
- st->st_new_iv_len = hasher->get_hash_size(hasher);
- passert(st->st_new_iv_len <= sizeof(st->st_new_iv));
-
- DBG(DBG_CRYPT,
- DBG_dump_chunk("DH_i:", st->st_gi);
- DBG_dump_chunk("DH_r:", st->st_gr);
- );
-
- hasher->get_hash(hasher, st->st_gi, NULL);
- hasher->get_hash(hasher, st->st_gr, st->st_new_iv);
- hasher->destroy(hasher);
- }
-
- /* Oakley Keying Material
- * Derived from Skeyid_e: if it is not big enough, generate more
- * using the PRF.
- * See RFC 2409 "IKE" Appendix B
- */
- {
- size_t keysize = st->st_oakley.enckeylen/BITS_PER_BYTE;
-
- /* free any existing key */
- free(st->st_enc_key.ptr);
-
- if (keysize > st->st_skeyid_e.len)
- {
- u_char keytemp[MAX_OAKLEY_KEY_LEN + MAX_DIGEST_LEN];
- chunk_t seed = chunk_from_chars(0x00);
- size_t prf_block_size, i;
- pseudo_random_function_t prf_alg;
- prf_t *prf;
-
- prf_alg = oakley_to_prf(st->st_oakley.hash);
- prf = lib->crypto->create_prf(lib->crypto, prf_alg);
- prf->set_key(prf, st->st_skeyid_e);
- prf_block_size = prf->get_block_size(prf);
-
- for (i = 0;;)
- {
- prf->get_bytes(prf, seed, &keytemp[i]);
- i += prf_block_size;
- if (i >= keysize)
- {
- break;
- }
- seed = chunk_create(&keytemp[i-prf_block_size], prf_block_size);
- }
- prf->destroy(prf);
- st->st_enc_key = chunk_create(keytemp, keysize);
- }
- else
- {
- st->st_enc_key = chunk_create(st->st_skeyid_e.ptr, keysize);
- }
- st->st_enc_key = chunk_clone(st->st_enc_key);
- }
-
- DBG(DBG_CRYPT,
- DBG_dump_chunk("Skeyid: ", st->st_skeyid);
- DBG_dump_chunk("Skeyid_d:", st->st_skeyid_d);
- DBG_dump_chunk("Skeyid_a:", st->st_skeyid_a);
- DBG_dump_chunk("Skeyid_e:", st->st_skeyid_e);
- DBG_dump_chunk("enc key:", st->st_enc_key);
- DBG_dump("IV:", st->st_new_iv, st->st_new_iv_len));
- return TRUE;
-}
-
-/* Generate HASH_I or HASH_R for ISAKMP Phase I.
- * This will *not* generate other hash payloads (eg. Phase II or Quick Mode,
- * New Group Mode, or ISAKMP Informational Exchanges).
- * If the hashi argument is TRUE, generate HASH_I; if FALSE generate HASH_R.
- * If hashus argument is TRUE, we're generating a hash for our end.
- * See RFC2409 IKE 5.
- */
- static void main_mode_hash(struct state *st, chunk_t *hash, bool hashi,
- const pb_stream *idpl)
-{
- chunk_t icookie = { st->st_icookie, COOKIE_SIZE };
- chunk_t rcookie = { st->st_rcookie, COOKIE_SIZE };
- chunk_t sa_body = { st->st_p1isa.ptr + sizeof(struct isakmp_generic),
- st->st_p1isa.len - sizeof(struct isakmp_generic) };
- chunk_t id_body = { idpl->start + sizeof(struct isakmp_generic),
- pbs_offset(idpl) - sizeof(struct isakmp_generic) };
- pseudo_random_function_t prf_alg;
- prf_t *prf;
-
- switch (st->st_oakley.auth)
- {
- case OAKLEY_ECDSA_256:
- prf_alg = PRF_HMAC_SHA2_256;
- break;
- case OAKLEY_ECDSA_384:
- prf_alg = PRF_HMAC_SHA2_384;
- break;
- case OAKLEY_ECDSA_521:
- prf_alg = PRF_HMAC_SHA2_512;
- break;
- default:
- prf_alg = oakley_to_prf(st->st_oakley.hash);
- }
- prf = lib->crypto->create_prf(lib->crypto, prf_alg);
- prf->set_key(prf, st->st_skeyid);
-
- if (hashi)
- {
- prf->get_bytes(prf, st->st_gi, NULL);
- prf->get_bytes(prf, st->st_gr, NULL);
- prf->get_bytes(prf, icookie, NULL);
- prf->get_bytes(prf, rcookie, NULL);
- }
- else
- {
- prf->get_bytes(prf, st->st_gr, NULL);
- prf->get_bytes(prf, st->st_gi, NULL);
- prf->get_bytes(prf, rcookie, NULL);
- prf->get_bytes(prf, icookie, NULL);
- }
-
- DBG(DBG_CRYPT,
- DBG_log("hashing %u bytes of SA", sa_body.len)
- )
- prf->get_bytes(prf, sa_body, NULL);
-
- /* Hash identification payload, without generic payload header.
- * We used to reconstruct ID Payload for this purpose, but now
- * we use the bytes as they appear on the wire to avoid
- * "spelling problems".
- */
- prf->get_bytes(prf, id_body, hash->ptr);
- hash->len = prf->get_block_size(prf);
- prf->destroy(prf);
-}
-
-/* Create a public key signature of a hash.
- * Poorly specified in draft-ietf-ipsec-ike-01.txt 6.1.1.2.
- * Use PKCS#1 version 1.5 encryption of hash (called
- * RSAES-PKCS1-V1_5) in PKCS#2.
- */
-static size_t sign_hash(signature_scheme_t scheme, connection_t *c,
- u_char sig_val[RSA_MAX_OCTETS], chunk_t hash)
-{
- size_t sz = 0;
- smartcard_t *sc = c->spd.this.sc;
-
- if (sc == NULL) /* no smartcard */
- {
- chunk_t sig;
- private_key_t *private = get_private_key(c);
-
- if (private == NULL)
- {
- return 0; /* failure: no key to use */
- }
- if (!private->sign(private, scheme, hash, &sig))
- {
- return 0;
- }
- memcpy(sig_val, sig.ptr, sig.len);
- sz = sig.len;
- free(sig.ptr);
- }
- else if (sc->valid) /* if valid pin then sign hash on the smartcard */
- {
- lock_certs_and_keys("sign_hash");
- if (!scx_establish_context(sc) || !scx_login(sc))
- {
- scx_release_context(sc);
- unlock_certs_and_keys("sign_hash");
- return 0;
- }
-
- sz = scx_get_keylength(sc);
- if (sz == 0)
- {
- plog("failed to get keylength from smartcard");
- scx_release_context(sc);
- unlock_certs_and_keys("sign_hash");
- return 0;
- }
-
- DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log("signing hash with private key from smartcard (slot: %d, id: %s)"
- , (int)sc->slot, sc->id)
- )
- sz = scx_sign_hash(sc, hash.ptr, hash.len, sig_val, sz) ? sz : 0;
- if (!pkcs11_keep_state)
- {
- scx_release_context(sc);
- }
- unlock_certs_and_keys("sign_hash");
- }
- return sz;
-}
-
-/* Check signature against all public keys we can find.
- * If we need keys from DNS KEY records, and they haven't been fetched,
- * return STF_SUSPEND to ask for asynch DNS lookup.
- *
- * Note: parameter keys_from_dns contains results of DNS lookup for key
- * or is NULL indicating lookup not yet tried.
- *
- * take_a_crack is a helper function. Mostly forensic.
- * If only we had coroutines.
- */
-struct tac_state {
- struct state *st;
- chunk_t hash;
- chunk_t sig;
- int tried_cnt; /* number of keys tried */
-};
-
-static bool take_a_crack(struct tac_state *s, pubkey_t *kr)
-{
- public_key_t *pub_key = kr->public_key;
- chunk_t keyid = chunk_empty;
- signature_scheme_t scheme;
-
- s->tried_cnt++;
- scheme = oakley_to_signature_scheme(s->st->st_oakley.auth);
- pub_key->get_fingerprint(pub_key, KEYID_PUBKEY_INFO_SHA1, &keyid);
-
- if (pub_key->verify(pub_key, scheme, s->hash, s->sig))
- {
- DBG(DBG_CRYPT | DBG_CONTROL,
- DBG_log("%s check passed with keyid %#B",
- enum_show(&oakley_auth_names, s->st->st_oakley.auth), &keyid)
- )
- unreference_key(&s->st->st_peer_pubkey);
- s->st->st_peer_pubkey = reference_key(kr);
- return TRUE;
- }
- else
- {
- DBG(DBG_CRYPT,
- DBG_log("%s check failed with keyid %#B",
- enum_show(&oakley_auth_names, s->st->st_oakley.auth), &keyid)
- )
- return FALSE;
- }
-}
-
-static stf_status check_signature(key_type_t key_type, identification_t* peer,
- struct state *st, chunk_t hash,
- const pb_stream *sig_pbs,
-#ifdef USE_KEYRR
- const pubkey_list_t *keys_from_dns,
-#endif /* USE_KEYRR */
- const struct gw_info *gateways_from_dns)
-{
- const connection_t *c = st->st_connection;
- struct tac_state s;
-
- s.st = st;
- s.hash = hash;
- s.sig = chunk_create(sig_pbs->cur, pbs_left(sig_pbs));
- s.tried_cnt = 0;
-
- /* try all gateway records hung off c */
- if (c->policy & POLICY_OPPO)
- {
- struct gw_info *gw;
-
- for (gw = c->gw_info; gw != NULL; gw = gw->next)
- {
- /* only consider entries that have a key and are for our peer */
- if (gw->gw_key_present &&
- gw->gw_id->equals(gw->gw_id, c->spd.that.id) &&
- take_a_crack(&s, gw->key))
- {
- return STF_OK;
- }
- }
- }
-
- /* try all appropriate Public keys */
- {
- pubkey_list_t *p, **pp;
-
- pp = &pubkeys;
-
- for (p = pubkeys; p != NULL; p = *pp)
- {
- pubkey_t *key = p->key;
- key_type_t type = key->public_key->get_type(key->public_key);
-
- if (type == key_type && peer->equals(peer, key->id))
- {
- time_t now = time(NULL);
-
- /* check if found public key has expired */
- if (key->until_time != UNDEFINED_TIME && key->until_time < now)
- {
- loglog(RC_LOG_SERIOUS,
- "cached public key has expired and has been deleted");
- *pp = free_public_keyentry(p);
- continue; /* continue with next public key */
- }
- if (take_a_crack(&s, key))
- {
- return STF_OK;
- }
- }
- pp = &p->next;
- }
- }
-
- /* if no key was found and that side of connection is
- * key_from_DNS_on_demand then go search DNS for keys for peer.
- */
- if (s.tried_cnt == 0 && c->spd.that.key_from_DNS_on_demand)
- {
- if (gateways_from_dns != NULL)
- {
- /* TXT keys */
- const struct gw_info *gwp;
-
- for (gwp = gateways_from_dns; gwp != NULL; gwp = gwp->next)
- {
- if (gwp->gw_key_present && take_a_crack(&s, gwp->key))
- {
- return STF_OK;
- }
- }
- }
-#ifdef USE_KEYRR
- else if (keys_from_dns != NULL)
- {
- /* KEY keys */
- const pubkey_list_t *kr;
-
- for (kr = keys_from_dns; kr != NULL; kr = kr->next)
- {
- if (kr->key->alg == PUBKEY_ALG_RSA && take_a_crack(&s, kr->key))
- {
- return STF_OK;
- }
- }
- }
-#endif /* USE_KEYRR */
- else
- {
- /* nothing yet: ask for asynch DNS lookup */
- return STF_SUSPEND;
- }
- }
-
- /* no acceptable key was found: diagnose */
- {
- if (s.tried_cnt == 0)
- {
- loglog(RC_LOG_SERIOUS, "no public key known for '%Y'", peer);
- }
- else if (s.tried_cnt == 1)
- {
- loglog(RC_LOG_SERIOUS, "signature check for '%Y' failed: "
- " wrong key?; tried %d", peer, s.tried_cnt);
- DBG(DBG_CONTROL,
- DBG_log("public key for '%Y' failed: "
- "decrypted SIG payload into a malformed ECB", peer)
- )
- }
- else
- {
- loglog(RC_LOG_SERIOUS, "signature check for '%Y' failed: "
- "tried %d keys but none worked.", peer, s.tried_cnt);
- DBG(DBG_CONTROL,
- DBG_log("all %d public keys for '%Y' failed: "
- "best decrypted SIG payload into a malformed ECB",
- s.tried_cnt, peer)
- )
- }
- return STF_FAIL + ISAKMP_INVALID_KEY_INFORMATION;
- }
-}
-
-static notification_t accept_nonce(struct msg_digest *md, chunk_t *dest,
- const char *name)
-{
- pb_stream *nonce_pbs = &md->chain[ISAKMP_NEXT_NONCE]->pbs;
- size_t len = pbs_left(nonce_pbs);
-
- if (len < MINIMUM_NONCE_SIZE || MAXIMUM_NONCE_SIZE < len)
- {
- loglog(RC_LOG_SERIOUS, "%s length not between %d and %d"
- , name , MINIMUM_NONCE_SIZE, MAXIMUM_NONCE_SIZE);
- return ISAKMP_PAYLOAD_MALFORMED; /* ??? */
- }
- free(dest->ptr);
- *dest = chunk_create(nonce_pbs->cur, len);
- *dest = chunk_clone(*dest);
- return ISAKMP_NOTHING_WRONG;
-}
-
-/* encrypt message, sans fixed part of header
- * IV is fetched from st->st_new_iv and stored into st->st_iv.
- * The theory is that there will be no "backing out", so we commit to IV.
- * We also close the pbs.
- */
-bool encrypt_message(pb_stream *pbs, struct state *st)
-{
- u_int8_t *enc_start = pbs->start + sizeof(struct isakmp_hdr);
- size_t enc_len = pbs_offset(pbs) - sizeof(struct isakmp_hdr);
- chunk_t data, iv;
- char *new_iv;
- size_t crypter_block_size, crypter_iv_size;
- encryption_algorithm_t enc_alg;
- crypter_t *crypter;
-
- DBG_cond_dump(DBG_CRYPT | DBG_RAW, "encrypting:\n", enc_start, enc_len);
- enc_alg = oakley_to_encryption_algorithm(st->st_oakley.encrypt);
- crypter = lib->crypto->create_crypter(lib->crypto, enc_alg, st->st_enc_key.len);
- crypter_block_size = crypter->get_block_size(crypter);
- crypter_iv_size = crypter->get_iv_size(crypter);
-
- /* Pad up to multiple of encryption blocksize.
- * See the description associated with the definition of
- * struct isakmp_hdr in packet.h.
- */
- {
- size_t padding = pad_up(enc_len, crypter_block_size);
-
- if (padding != 0)
- {
- if (!out_zero(padding, pbs, "encryption padding"))
- return FALSE;
- enc_len += padding;
- }
- }
-
- DBG(DBG_CRYPT, DBG_log("encrypting using %s", enum_show(&oakley_enc_names, st->st_oakley.encrypt)));
- data = chunk_create(enc_start, enc_len);
-
- /* form iv by truncation */
- st->st_new_iv_len = crypter_iv_size;
- iv = chunk_create(st->st_new_iv, st->st_new_iv_len);
-
- crypter->set_key(crypter, st->st_enc_key);
- crypter->encrypt(crypter, data, iv, NULL);
- crypter->destroy(crypter);
-
- new_iv = data.ptr + data.len - crypter_iv_size;
- memcpy(st->st_new_iv, new_iv, crypter_iv_size);
- update_iv(st);
- DBG_cond_dump(DBG_CRYPT, "next IV:", st->st_iv, st->st_iv_len);
- close_message(pbs);
- return TRUE;
-}
-
-/* Compute HASH(1), HASH(2) of Quick Mode.
- * HASH(1) is part of Quick I1 message.
- * HASH(2) is part of Quick R1 message.
- * Used by: quick_outI1, quick_inI1_outR1 (twice), quick_inR1_outI2
- * (see RFC 2409 "IKE" 5.5, pg. 18 or draft-ietf-ipsec-ike-01.txt 6.2 pg 25)
- */
-static size_t quick_mode_hash12(u_char *dest, u_char *start, u_char *roof,
- const struct state *st, const msgid_t *msgid,
- bool hash2)
-{
- chunk_t msgid_chunk = chunk_from_thing(*msgid);
- chunk_t msg_chunk = { start, roof - start };
- pseudo_random_function_t prf_alg;
- prf_t *prf;
- size_t prf_block_size;
-
- prf_alg = oakley_to_prf(st->st_oakley.hash);
- prf = lib->crypto->create_prf(lib->crypto, prf_alg);
- prf->set_key(prf, st->st_skeyid_a);
- prf->get_bytes(prf, msgid_chunk, NULL);
- if (hash2)
- {
- prf->get_bytes(prf, st->st_ni, NULL); /* include Ni_b in the hash */
- }
- prf->get_bytes(prf, msg_chunk, dest);
- prf_block_size = prf->get_block_size(prf);
- prf->destroy(prf);
-
- DBG(DBG_CRYPT,
- DBG_log("HASH(%d) computed:", hash2 + 1);
- DBG_dump("", dest, prf_block_size)
- )
- return prf_block_size;
-}
-
-/* Compute HASH(3) in Quick Mode (part of Quick I2 message).
- * Used by: quick_inR1_outI2, quick_inI2
- * See RFC2409 "The Internet Key Exchange (IKE)" 5.5.
- * NOTE: this hash (unlike HASH(1) and HASH(2)) ONLY covers the
- * Message ID and Nonces. This is a mistake.
- */
-static size_t quick_mode_hash3(u_char *dest, struct state *st)
-{
- chunk_t seed_chunk = chunk_from_chars(0x00);
- chunk_t msgid_chunk = chunk_from_thing(st->st_msgid);
- pseudo_random_function_t prf_alg;
- prf_t *prf;
- size_t prf_block_size;
-
- prf_alg = oakley_to_prf(st->st_oakley.hash);
- prf = lib->crypto->create_prf(lib->crypto, prf_alg);
- prf->set_key(prf, st->st_skeyid_a);
- prf->get_bytes(prf, seed_chunk, NULL );
- prf->get_bytes(prf, msgid_chunk, NULL);
- prf->get_bytes(prf, st->st_ni, NULL);
- prf->get_bytes(prf, st->st_nr, dest);
- prf_block_size = prf->get_block_size(prf);
- prf->destroy(prf);
-
- DBG_cond_dump(DBG_CRYPT, "HASH(3) computed:", dest, prf_block_size);
- return prf_block_size;
-}
-
-/* Compute Phase 2 IV.
- * Uses Phase 1 IV from st_iv; puts result in st_new_iv.
- */
-void init_phase2_iv(struct state *st, const msgid_t *msgid)
-{
- chunk_t iv_chunk = { st->st_ph1_iv, st->st_ph1_iv_len };
- chunk_t msgid_chunk = chunk_from_thing(*msgid);
- hash_algorithm_t hash_alg;
- hasher_t *hasher;
-
- hash_alg = oakley_to_hash_algorithm(st->st_oakley.hash);
- hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
-
- DBG_cond_dump(DBG_CRYPT, "last Phase 1 IV:",
- st->st_ph1_iv, st->st_ph1_iv_len);
-
- st->st_new_iv_len = hasher->get_hash_size(hasher);
- passert(st->st_new_iv_len <= sizeof(st->st_new_iv));
-
- hasher->get_hash(hasher, iv_chunk, NULL);
- hasher->get_hash(hasher, msgid_chunk, st->st_new_iv);
- hasher->destroy(hasher);
-
- DBG_cond_dump(DBG_CRYPT, "computed Phase 2 IV:",
- st->st_new_iv, st->st_new_iv_len);
-}
-
-/* Initiate quick mode.
- * --> HDR*, HASH(1), SA, Nr [, KE ] [, IDci, IDcr ]
- * (see RFC 2409 "IKE" 5.5)
- * Note: this is not called from demux.c
- */
-
-static bool emit_subnet_id(ip_subnet *net, u_int8_t np, u_int8_t protoid,
- u_int16_t port, pb_stream *outs)
-{
- struct isakmp_ipsec_id id;
- pb_stream id_pbs;
- ip_address ta;
- const unsigned char *tbp;
- size_t tal;
-
- id.isaiid_np = np;
- id.isaiid_idtype = subnetishost(net)
- ? aftoinfo(subnettypeof(net))->id_addr
- : aftoinfo(subnettypeof(net))->id_subnet;
- id.isaiid_protoid = protoid;
- id.isaiid_port = port;
-
- if (!out_struct(&id, &isakmp_ipsec_identification_desc, outs, &id_pbs))
- {
- return FALSE;
- }
- networkof(net, &ta);
- tal = addrbytesptr(&ta, &tbp);
- if (!out_raw(tbp, tal, &id_pbs, "client network"))
- {
- return FALSE;
- }
- if (!subnetishost(net))
- {
- maskof(net, &ta);
- tal = addrbytesptr(&ta, &tbp);
- if (!out_raw(tbp, tal, &id_pbs, "client mask"))
- {
- return FALSE;
- }
- }
- close_output_pbs(&id_pbs);
- return TRUE;
-}
-
-stf_status quick_outI1(int whack_sock, struct state *isakmp_sa,
- connection_t *c, lset_t policy, unsigned long try,
- so_serial_t replacing)
-{
- struct state *st = duplicate_state(isakmp_sa);
- pb_stream reply; /* not really a reply */
- pb_stream rbody;
- u_char /* set by START_HASH_PAYLOAD: */
- *r_hashval, /* where in reply to jam hash value */
- *r_hash_start; /* start of what is to be hashed */
- bool has_client = c->spd.this.has_client || c->spd.that.has_client ||
- c->spd.this.protocol || c->spd.that.protocol ||
- c->spd.this.port || c->spd.that.port;
- bool send_natoa = FALSE;
- u_int8_t np = ISAKMP_NEXT_NONE;
- connection_t *ph1_c = isakmp_sa->st_connection;
-
- if (c->spd.this.modecfg && !c->spd.this.has_client &&
- c->spd.this.host_srcip->is_anyaddr(c->spd.this.host_srcip))
- {
- host_t * ph1_srcip = ph1_c->spd.this.host_srcip;
-
- if (ph1_c->spd.this.modecfg && !ph1_srcip->is_anyaddr(ph1_srcip))
- {
- c->spd.this.host_srcip->destroy(c->spd.this.host_srcip);
- c->spd.this.host_srcip = ph1_srcip->clone(ph1_srcip);
- c->spd.this.client = ph1_c->spd.this.client;
- c->spd.this.has_client = TRUE;
- plog("inheriting virtual IP source address %H from ModeCfg", ph1_srcip);
- }
- }
-
- if (ph1_c->policy & (POLICY_XAUTH_RSASIG | POLICY_XAUTH_PSK) &&
- ph1_c->xauth_identity && !c->xauth_identity)
- {
- DBG(DBG_CONTROL,
- DBG_log("inheriting XAUTH identity %Y", ph1_c->xauth_identity)
- )
- c->xauth_identity = ph1_c->xauth_identity->clone(ph1_c->xauth_identity);
- }
-
- st->st_whack_sock = whack_sock;
- st->st_connection = c;
- set_cur_state(st); /* we must reset before exit */
- st->st_policy = policy;
- st->st_try = try;
-
- st->st_myuserprotoid = c->spd.this.protocol;
- st->st_peeruserprotoid = c->spd.that.protocol;
- st->st_myuserport = c->spd.this.port;
- st->st_peeruserport = c->spd.that.port;
-
- st->st_msgid = generate_msgid(isakmp_sa);
- st->st_state = STATE_QUICK_I1;
-
- insert_state(st); /* needs cookies, connection, and msgid */
-
- if (replacing == SOS_NOBODY)
- {
- plog("initiating Quick Mode %s {using isakmp#%lu}",
- prettypolicy(policy), isakmp_sa->st_serialno);
- }
- else
- {
- plog("initiating Quick Mode %s to replace #%lu {using isakmp#%lu}",
- prettypolicy(policy), replacing, isakmp_sa->st_serialno);
- }
- if (isakmp_sa->nat_traversal & NAT_T_DETECTED)
- {
- /* Duplicate nat_traversal status in new state */
- st->nat_traversal = isakmp_sa->nat_traversal;
-
- if (isakmp_sa->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_ME))
- {
- has_client = TRUE;
- }
- nat_traversal_change_port_lookup(NULL, st);
- }
- else
- {
- st->nat_traversal = 0;
- }
-
- /* are we going to send a NAT-OA payload? */
- if ((st->nat_traversal & NAT_T_WITH_NATOA)
- && !(st->st_policy & POLICY_TUNNEL)
- && (st->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_ME)))
- {
- send_natoa = TRUE;
- np = (st->nat_traversal & NAT_T_WITH_RFC_VALUES) ?
- ISAKMP_NEXT_NATOA_RFC : ISAKMP_NEXT_NATOA_DRAFTS;
- }
-
- /* set up reply */
- init_pbs(&reply, reply_buffer, sizeof(reply_buffer), "reply packet");
-
- /* HDR* out */
- {
- struct isakmp_hdr hdr;
-
- hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION;
- hdr.isa_np = ISAKMP_NEXT_HASH;
- hdr.isa_xchg = ISAKMP_XCHG_QUICK;
- hdr.isa_msgid = st->st_msgid;
- hdr.isa_flags = ISAKMP_FLAG_ENCRYPTION;
- memcpy(hdr.isa_icookie, st->st_icookie, COOKIE_SIZE);
- memcpy(hdr.isa_rcookie, st->st_rcookie, COOKIE_SIZE);
- if (!out_struct(&hdr, &isakmp_hdr_desc, &reply, &rbody))
- {
- reset_cur_state();
- return STF_INTERNAL_ERROR;
- }
- }
-
- /* HASH(1) -- create and note space to be filled later */
- START_HASH_PAYLOAD(rbody, ISAKMP_NEXT_SA);
-
- /* SA out */
-
- /*
- * See if pfs_group has been specified for this conn,
- * if not, fallback to old use-same-as-P1 behaviour
- */
-#ifndef NO_IKE_ALG
- if (st->st_connection)
- {
- st->st_pfs_group = ike_alg_pfsgroup(st->st_connection, policy);
- }
- if (!st->st_pfs_group)
-#endif
- /* If PFS specified, use the same group as during Phase 1:
- * since no negotiation is possible, we pick one that is
- * very likely supported.
- */
- st->st_pfs_group = policy & POLICY_PFS? isakmp_sa->st_oakley.group : NULL;
-
- /* Emit SA payload based on a subset of the policy bits.
- * POLICY_COMPRESS is considered iff we can do IPcomp.
- */
- {
- lset_t pm = POLICY_ENCRYPT | POLICY_AUTHENTICATE;
-
- if (can_do_IPcomp)
- {
- pm |= POLICY_COMPRESS;
- }
- if (!out_sa(&rbody,
- &ipsec_sadb[(st->st_policy & pm) >> POLICY_IPSEC_SHIFT],
- st, FALSE, ISAKMP_NEXT_NONCE))
- {
- reset_cur_state();
- return STF_INTERNAL_ERROR;
- }
- }
-
- /* Ni out */
- if (!build_and_ship_nonce(&st->st_ni, &rbody
- , policy & POLICY_PFS? ISAKMP_NEXT_KE : has_client? ISAKMP_NEXT_ID : np
- , "Ni"))
- {
- reset_cur_state();
- return STF_INTERNAL_ERROR;
- }
-
- /* [ KE ] out (for PFS) */
-
- if (st->st_pfs_group != NULL)
- {
- if (!build_and_ship_KE(st, &st->st_gi, st->st_pfs_group
- , &rbody, has_client? ISAKMP_NEXT_ID : np))
- {
- reset_cur_state();
- return STF_INTERNAL_ERROR;
- }
- }
-
- /* [ IDci, IDcr ] out */
- if (has_client)
- {
- /* IDci (we are initiator), then IDcr (peer is responder) */
- if (!emit_subnet_id(&c->spd.this.client
- , ISAKMP_NEXT_ID, st->st_myuserprotoid, st->st_myuserport, &rbody)
- || !emit_subnet_id(&c->spd.that.client
- , np, st->st_peeruserprotoid, st->st_peeruserport, &rbody))
- {
- reset_cur_state();
- return STF_INTERNAL_ERROR;
- }
- }
-
- /* Send NAT-OA if our address is NATed */
- if (send_natoa)
- {
- if (!nat_traversal_add_natoa(ISAKMP_NEXT_NONE, &rbody, st))
- {
- reset_cur_state();
- return STF_INTERNAL_ERROR;
- }
- }
-
- /* finish computing HASH(1), inserting it in output */
- (void) quick_mode_hash12(r_hashval, r_hash_start, rbody.cur
- , st, &st->st_msgid, FALSE);
-
- /* encrypt message, except for fixed part of header */
-
- init_phase2_iv(isakmp_sa, &st->st_msgid);
- st->st_new_iv_len = isakmp_sa->st_new_iv_len;
- memcpy(st->st_new_iv, isakmp_sa->st_new_iv, st->st_new_iv_len);
-
- if (!encrypt_message(&rbody, st))
- {
- reset_cur_state();
- return STF_INTERNAL_ERROR;
- }
-
- /* save packet, now that we know its size */
- st->st_tpacket = chunk_create(reply.start, pbs_offset(&reply));
- st->st_tpacket = chunk_clone(st->st_tpacket);
-
- /* send the packet */
-
- send_packet(st, "quick_outI1");
-
- delete_event(st);
- event_schedule(EVENT_RETRANSMIT, EVENT_RETRANSMIT_DELAY_0, st);
-
- if (replacing == SOS_NOBODY)
- {
- whack_log(RC_NEW_STATE + STATE_QUICK_I1
- , "%s: initiate"
- , enum_name(&state_names, st->st_state));
- }
- else
- {
- whack_log(RC_NEW_STATE + STATE_QUICK_I1
- , "%s: initiate to replace #%lu"
- , enum_name(&state_names, st->st_state)
- , replacing);
- }
- reset_cur_state();
- return STF_OK;
-}
-
-
-/*
- * Decode the CERT payload of Phase 1.
- */
-static void decode_cert(struct msg_digest *md)
-{
- struct payload_digest *p;
-
- for (p = md->chain[ISAKMP_NEXT_CERT]; p != NULL; p = p->next)
- {
- struct isakmp_cert *const cert = &p->payload.cert;
- chunk_t blob;
- time_t valid_until;
- blob.ptr = p->pbs.cur;
- blob.len = pbs_left(&p->pbs);
- if (cert->isacert_type == CERT_X509_SIGNATURE)
- {
- cert_t x509cert = cert_empty;
-
- x509cert.cert = lib->creds->create(lib->creds,
- CRED_CERTIFICATE, CERT_X509,
- BUILD_BLOB_ASN1_DER, blob,
- BUILD_END);
- if (x509cert.cert)
- {
- if (verify_x509cert(&x509cert, strict_crl_policy, &valid_until))
- {
- DBG(DBG_PARSING,
- DBG_log("Public key validated")
- )
- add_public_key_from_cert(&x509cert, valid_until, DAL_SIGNED);
- }
- else
- {
- plog("X.509 certificate rejected");
- }
- x509cert.cert->destroy(x509cert.cert);
- }
- else
- {
- plog("Syntax error in X.509 certificate");
- }
- }
- else if (cert->isacert_type == CERT_PKCS7_WRAPPED_X509)
- {
- linked_list_t *certs = linked_list_create();
-
- if (pkcs7_parse_signedData(blob, NULL, certs, NULL, NULL))
- {
- store_x509certs(certs, strict_crl_policy);
- }
- else
- {
- plog("Syntax error in PKCS#7 wrapped X.509 certificates");
- }
- certs->destroy_offset(certs, offsetof(certificate_t, destroy));
- }
- else
- {
- loglog(RC_LOG_SERIOUS, "ignoring %s certificate payload",
- enum_show(&cert_type_names, cert->isacert_type));
- DBG_cond_dump_chunk(DBG_PARSING, "CERT:\n", blob);
- }
- }
-}
-
-/*
- * Decode the CR payload of Phase 1.
- */
-static void decode_cr(struct msg_digest *md, connection_t *c)
-{
- struct payload_digest *p;
-
- for (p = md->chain[ISAKMP_NEXT_CR]; p != NULL; p = p->next)
- {
- struct isakmp_cr *const cr = &p->payload.cr;
- chunk_t ca_name;
-
- ca_name.len = pbs_left(&p->pbs);
- ca_name.ptr = (ca_name.len > 0)? p->pbs.cur : NULL;
-
- DBG_cond_dump_chunk(DBG_PARSING, "CR", ca_name);
-
- if (cr->isacr_type == CERT_X509_SIGNATURE)
- {
- if (ca_name.len > 0)
- {
- identification_t *ca;
-
- if (!is_asn1(ca_name))
- {
- continue;
- }
- if (c->requested_ca == NULL)
- {
- c->requested_ca = linked_list_create();
- }
- ca = identification_create_from_encoding(ID_DER_ASN1_DN, ca_name);
- c->requested_ca->insert_last(c->requested_ca, ca);
- DBG(DBG_PARSING | DBG_CONTROL,
- DBG_log("requested CA: \"%Y\"", ca)
- )
- }
- else
- {
- DBG(DBG_PARSING | DBG_CONTROL,
- DBG_log("requested CA: %%any")
- )
- }
- c->got_certrequest = TRUE;
- }
- else
- {
- loglog(RC_LOG_SERIOUS, "ignoring %s certificate request payload",
- enum_show(&cert_type_names, cr->isacr_type));
- }
- }
-}
-
-/* Decode the ID payload of Phase 1 (main_inI3_outR3 and main_inR3)
- * Note: we may change connections as a result.
- * We must be called before SIG or HASH are decoded since we
- * may change the peer's public key or ID.
- */
-static bool decode_peer_id(struct msg_digest *md, identification_t **peer)
-{
- struct state *const st = md->st;
- struct payload_digest *const id_pld = md->chain[ISAKMP_NEXT_ID];
- const pb_stream *const id_pbs = &id_pld->pbs;
- struct isakmp_id *const id = &id_pld->payload.id;
- chunk_t id_payload;
-
- /* I think that RFC2407 (IPSEC DOI) 4.6.2 is confused.
- * It talks about the protocol ID and Port fields of the ID
- * Payload, but they don't exist as such in Phase 1.
- * We use more appropriate names.
- * isaid_doi_specific_a is in place of Protocol ID.
- * isaid_doi_specific_b is in place of Port.
- * Besides, there is no good reason for allowing these to be
- * other than 0 in Phase 1.
- */
- if ((st->nat_traversal & NAT_T_WITH_PORT_FLOATING)
- && id->isaid_doi_specific_a == IPPROTO_UDP
- && (id->isaid_doi_specific_b == 0 || id->isaid_doi_specific_b == NAT_T_IKE_FLOAT_PORT))
- {
- DBG_log("protocol/port in Phase 1 ID Payload is %d/%d. "
- "accepted with port_floating NAT-T",
- id->isaid_doi_specific_a, id->isaid_doi_specific_b);
- }
- else if (!(id->isaid_doi_specific_a == 0 && id->isaid_doi_specific_b == 0)
- && !(id->isaid_doi_specific_a == IPPROTO_UDP && id->isaid_doi_specific_b == IKE_UDP_PORT))
- {
- loglog(RC_LOG_SERIOUS, "protocol/port in Phase 1 ID Payload must be 0/0 or %d/%d"
- " but are %d/%d"
- , IPPROTO_UDP, IKE_UDP_PORT
- , id->isaid_doi_specific_a, id->isaid_doi_specific_b);
- return FALSE;
- }
-
- id_payload = chunk_create(id_pbs->cur, pbs_left(id_pbs));
-
- switch (id->isaid_idtype)
- {
- case ID_IPV4_ADDR:
- if (id_payload.len != 4)
- {
- loglog(RC_LOG_SERIOUS, "improper %s Phase 1 ID payload",
- enum_show(&ident_names, id->isaid_idtype));
- return FALSE;
- }
- break;
- case ID_IPV6_ADDR:
- if (id_payload.len != 16)
- {
- loglog(RC_LOG_SERIOUS, "improper %s Phase 1 ID payload",
- enum_show(&ident_names, id->isaid_idtype));
- return FALSE;
- }
- break;
- case ID_USER_FQDN:
- case ID_FQDN:
- if (memchr(id_payload.ptr, '\0', id_payload.len) != NULL)
- {
- loglog(RC_LOG_SERIOUS, "%s Phase 1 ID payload contains "
- "a NUL character",
- enum_show(&ident_names, id->isaid_idtype));
- return FALSE;
- }
- break;
- case ID_KEY_ID:
- case ID_DER_ASN1_DN:
- break;
- default:
- /* XXX Could send notification back */
- loglog(RC_LOG_SERIOUS, "unacceptable identity type (%s) "
- "in Phase 1 ID payload",
- enum_show(&ident_names, id->isaid_idtype));
- return FALSE;
- }
- *peer = identification_create_from_encoding(id->isaid_idtype, id_payload);
-
- plog("Peer ID is %s: '%Y'", enum_show(&ident_names, id->isaid_idtype),
- *peer);
-
- /* check for certificates */
- decode_cert(md);
- return TRUE;
-}
-
-/* Now that we've decoded the ID payload, let's see if we
- * need to switch connections.
- * We must not switch horses if we initiated:
- * - if the initiation was explicit, we'd be ignoring user's intent
- * - if opportunistic, we'll lose our HOLD info
- */
-static bool switch_connection(struct msg_digest *md, identification_t *peer,
- bool initiator)
-{
- struct state *const st = md->st;
- connection_t *c = st->st_connection;
- identification_t *peer_ca;
-
- peer_ca = st->st_peer_pubkey ? st->st_peer_pubkey->issuer : NULL;
- if (peer_ca)
- {
- DBG(DBG_CONTROL,
- DBG_log("peer CA: \"%Y\"", peer_ca)
- )
- }
- else
- {
- DBG(DBG_CONTROL,
- DBG_log("peer CA: %%none")
- )
- }
-
- if (initiator)
- {
- int pathlen;
-
- if (!peer->equals(peer, c->spd.that.id))
- {
- loglog(RC_LOG_SERIOUS,
- "we require peer to have ID '%Y', but peer declares '%Y'",
- c->spd.that.id, peer);
- return FALSE;
- }
-
- if (c->spd.that.ca)
- {
- DBG(DBG_CONTROL,
- DBG_log("required CA: \"%s\"", c->spd.that.ca);
- )
- }
- else
- {
- DBG(DBG_CONTROL,
- DBG_log("required CA: %%none");
- )
- }
-
- if (!trusted_ca(peer_ca, c->spd.that.ca, &pathlen))
- {
- loglog(RC_LOG_SERIOUS
- , "we don't accept the peer's CA");
- return FALSE;
- }
- }
- else
- {
- connection_t *r;
-
- /* check for certificate requests */
- decode_cr(md, c);
-
- r = refine_host_connection(st, peer, peer_ca);
-
- /* delete the collected certificate requests */
- if (c->requested_ca)
- {
- c->requested_ca->destroy_offset(c->requested_ca,
- offsetof(identification_t, destroy));
- c->requested_ca = NULL;
- }
-
- if (r == NULL)
- {
- loglog(RC_LOG_SERIOUS, "no suitable connection for peer '%Y'", peer);
- return FALSE;
- }
-
- if (r->spd.this.ca)
- {
- DBG(DBG_CONTROL,
- DBG_log("offered CA: \"%Y\"", r->spd.this.ca)
- )
- }
- else
- {
- DBG(DBG_CONTROL,
- DBG_log("offered CA: %%none")
- )
- }
-
- if (r != c)
- {
- /* apparently, r is an improvement on c -- replace */
-
- DBG(DBG_CONTROL
- , DBG_log("switched from \"%s\" to \"%s\"", c->name, r->name));
- if (r->kind == CK_TEMPLATE)
- {
- /* instantiate it, filling in peer's ID */
- r = rw_instantiate(r, &c->spd.that.host_addr
- , c->spd.that.host_port, NULL, peer);
- }
-
- /* copy certificate request info */
- r->got_certrequest = c->got_certrequest;
-
- st->st_connection = r; /* kill reference to c */
- set_cur_connection(r);
- connection_discard(c);
- }
- else if (c->spd.that.has_id_wildcards)
- {
- c->spd.that.id->destroy(c->spd.that.id);
- c->spd.that.id = peer->clone(peer);
- c->spd.that.has_id_wildcards = FALSE;
- }
- }
- return TRUE;
-}
-
-/* Decode the variable part of an ID packet (during Quick Mode).
- * This is designed for packets that identify clients, not peers.
- * Rejects 0.0.0.0/32 or IPv6 equivalent because
- * (1) it is wrong and (2) we use this value for inband signalling.
- */
-static bool decode_net_id(struct isakmp_ipsec_id *id, pb_stream *id_pbs,
- ip_subnet *net, const char *which)
-{
- const struct af_info *afi = NULL;
-
- /* Note: the following may be a pointer into static memory
- * that may be recycled, but only if the type is not known.
- * That case is disposed of very early -- in the first switch.
- */
- const char *idtypename = enum_show(&ident_names, id->isaiid_idtype);
-
- switch (id->isaiid_idtype)
- {
- case ID_IPV4_ADDR:
- case ID_IPV4_ADDR_SUBNET:
- case ID_IPV4_ADDR_RANGE:
- afi = &af_inet4_info;
- break;
- case ID_IPV6_ADDR:
- case ID_IPV6_ADDR_SUBNET:
- case ID_IPV6_ADDR_RANGE:
- afi = &af_inet6_info;
- break;
- case ID_FQDN:
- return TRUE;
- default:
- /* XXX support more */
- loglog(RC_LOG_SERIOUS, "unsupported ID type %s"
- , idtypename);
- /* XXX Could send notification back */
- return FALSE;
- }
-
- switch (id->isaiid_idtype)
- {
- case ID_IPV4_ADDR:
- case ID_IPV6_ADDR:
- {
- ip_address temp_address;
- err_t ugh;
-
- ugh = initaddr(id_pbs->cur, pbs_left(id_pbs), afi->af, &temp_address);
-
- if (ugh != NULL)
- {
- loglog(RC_LOG_SERIOUS, "%s ID payload %s has wrong length in Quick I1 (%s)"
- , which, idtypename, ugh);
- /* XXX Could send notification back */
- return FALSE;
- }
- if (isanyaddr(&temp_address))
- {
- loglog(RC_LOG_SERIOUS, "%s ID payload %s is invalid (%s) in Quick I1"
- , which, idtypename, ip_str(&temp_address));
- /* XXX Could send notification back */
- return FALSE;
- }
- happy(addrtosubnet(&temp_address, net));
- DBG(DBG_PARSING | DBG_CONTROL
- , DBG_log("%s is %s", which, ip_str(&temp_address)));
- break;
- }
-
- case ID_IPV4_ADDR_SUBNET:
- case ID_IPV6_ADDR_SUBNET:
- {
- ip_address temp_address, temp_mask;
- err_t ugh;
-
- if (pbs_left(id_pbs) != 2 * afi->ia_sz)
- {
- loglog(RC_LOG_SERIOUS, "%s ID payload %s wrong length in Quick I1"
- , which, idtypename);
- /* XXX Could send notification back */
- return FALSE;
- }
- ugh = initaddr(id_pbs->cur
- , afi->ia_sz, afi->af, &temp_address);
- if (ugh == NULL)
- {
- ugh = initaddr(id_pbs->cur + afi->ia_sz
- , afi->ia_sz, afi->af, &temp_mask);
- }
- if (ugh == NULL)
- {
- ugh = initsubnet(&temp_address, masktocount(&temp_mask)
- , '0', net);
- }
- if (ugh == NULL && subnetisnone(net))
- {
- ugh = "contains only anyaddr";
- }
- if (ugh != NULL)
- {
- loglog(RC_LOG_SERIOUS, "%s ID payload %s bad subnet in Quick I1 (%s)"
- , which, idtypename, ugh);
- /* XXX Could send notification back */
- return FALSE;
- }
- DBG(DBG_PARSING | DBG_CONTROL,
- {
- char temp_buff[SUBNETTOT_BUF];
-
- subnettot(net, 0, temp_buff, sizeof(temp_buff));
- DBG_log("%s is subnet %s", which, temp_buff);
- });
- break;
- }
-
- case ID_IPV4_ADDR_RANGE:
- case ID_IPV6_ADDR_RANGE:
- {
- ip_address temp_address_from, temp_address_to;
- err_t ugh;
-
- if (pbs_left(id_pbs) != 2 * afi->ia_sz)
- {
- loglog(RC_LOG_SERIOUS, "%s ID payload %s wrong length in Quick I1"
- , which, idtypename);
- /* XXX Could send notification back */
- return FALSE;
- }
- ugh = initaddr(id_pbs->cur, afi->ia_sz, afi->af, &temp_address_from);
- if (ugh == NULL)
- {
- ugh = initaddr(id_pbs->cur + afi->ia_sz
- , afi->ia_sz, afi->af, &temp_address_to);
- }
- if (ugh != NULL)
- {
- loglog(RC_LOG_SERIOUS, "%s ID payload %s malformed (%s) in Quick I1"
- , which, idtypename, ugh);
- /* XXX Could send notification back */
- return FALSE;
- }
-
- ugh = rangetosubnet(&temp_address_from, &temp_address_to, net);
- if (ugh == NULL && subnetisnone(net))
- {
- ugh = "contains only anyaddr";
- }
- if (ugh != NULL)
- {
- char temp_buff1[ADDRTOT_BUF], temp_buff2[ADDRTOT_BUF];
-
- addrtot(&temp_address_from, 0, temp_buff1, sizeof(temp_buff1));
- addrtot(&temp_address_to, 0, temp_buff2, sizeof(temp_buff2));
- loglog(RC_LOG_SERIOUS, "%s ID payload in Quick I1, %s"
- " %s - %s unacceptable: %s"
- , which, idtypename, temp_buff1, temp_buff2, ugh);
- return FALSE;
- }
- DBG(DBG_PARSING | DBG_CONTROL,
- {
- char temp_buff[SUBNETTOT_BUF];
-
- subnettot(net, 0, temp_buff, sizeof(temp_buff));
- DBG_log("%s is subnet %s (received as range)"
- , which, temp_buff);
- });
- break;
- }
- }
-
- /* set the port selector */
- setportof(htons(id->isaiid_port), &net->addr);
-
- DBG(DBG_PARSING | DBG_CONTROL,
- DBG_log("%s protocol/port is %d/%d", which, id->isaiid_protoid, id->isaiid_port)
- )
-
- return TRUE;
-}
-
-/* like decode, but checks that what is received matches what was sent */
-static bool check_net_id(struct isakmp_ipsec_id *id, pb_stream *id_pbs,
- u_int8_t *protoid, u_int16_t *port, ip_subnet *net,
- const char *which)
-{
- ip_subnet net_temp;
-
- if (!decode_net_id(id, id_pbs, &net_temp, which))
- {
- return FALSE;
- }
- if (!samesubnet(net, &net_temp)
- || *protoid != id->isaiid_protoid || *port != id->isaiid_port)
- {
- loglog(RC_LOG_SERIOUS, "%s ID returned doesn't match my proposal", which);
- return FALSE;
- }
- return TRUE;
-}
-
-/*
- * look for the existence of a non-expiring preloaded public key
- */
-static bool has_preloaded_public_key(struct state *st)
-{
- connection_t *c = st->st_connection;
-
- /* do not consider rw connections since
- * the peer's identity must be known
- */
- if (c->kind == CK_PERMANENT)
- {
- pubkey_list_t *p;
-
- /* look for a matching RSA public key */
- for (p = pubkeys; p != NULL; p = p->next)
- {
- pubkey_t *key = p->key;
- key_type_t type = key->public_key->get_type(key->public_key);
-
- if (type == KEY_RSA &&
- c->spd.that.id->equals(c->spd.that.id, key->id) &&
- key->until_time == UNDEFINED_TIME)
- {
- /* found a preloaded public key */
- return TRUE;
- }
- }
- }
- return FALSE;
-}
-
-/* Compute keying material for an SA
- */
-static void compute_keymat_internal(struct state *st, u_int8_t protoid,
- ipsec_spi_t spi, size_t needed_len,
- u_char **keymat_out)
-{
- size_t i = 0, prf_block_size, needed_space;
- chunk_t protoid_chunk = chunk_from_thing(protoid);
- chunk_t spi_chunk = chunk_from_thing(spi);
- pseudo_random_function_t prf_alg = oakley_to_prf(st->st_oakley.hash);
- prf_t *prf = lib->crypto->create_prf(lib->crypto, prf_alg);
-
- prf->set_key(prf, st->st_skeyid_d);
- prf_block_size = prf->get_block_size(prf);
-
- /* Although only needed_len bytes are desired, we must round up to a
- * multiple of prf_block_size so that the buffer isn't overrun */
- needed_space = needed_len + pad_up(needed_len, prf_block_size);
- replace(*keymat_out, malloc(needed_space));
-
- for (;;)
- {
- char *keymat_i = (*keymat_out) + i;
- chunk_t keymat = { keymat_i, prf_block_size };
-
- if (st->st_shared.ptr != NULL)
- { /* PFS: include the g^xy */
- prf->get_bytes(prf, st->st_shared, NULL);
- }
- prf->get_bytes(prf, protoid_chunk, NULL);
- prf->get_bytes(prf, spi_chunk, NULL);
- prf->get_bytes(prf, st->st_ni, NULL);
- prf->get_bytes(prf, st->st_nr, keymat_i);
-
- i += prf_block_size;
- if (i >= needed_space)
- {
- break;
- }
-
- /* more keying material needed: prepare to go around again */
- prf->get_bytes(prf, keymat, NULL);
- }
- prf->destroy(prf);
-}
-
-/*
- * Produce the new key material of Quick Mode.
- * RFC 2409 "IKE" section 5.5
- * specifies how this is to be done.
- */
-static void compute_proto_keymat(struct state *st, u_int8_t protoid,
- struct ipsec_proto_info *pi, enum endpoint ep)
-{
- size_t needed_len = 0; /* bytes of keying material needed */
-
- /* Add up the requirements for keying material
- * (It probably doesn't matter if we produce too much!)
- */
- switch (protoid)
- {
- case PROTO_IPSEC_ESP:
- {
- needed_len = kernel_alg_esp_enc_keylen(pi->attrs.transid);
-
- if (needed_len && pi->attrs.key_len)
- {
- needed_len = pi->attrs.key_len / BITS_PER_BYTE;
- }
-
- switch (pi->attrs.transid)
- {
- case ESP_NULL:
- needed_len = 0;
- break;
- case ESP_AES_CCM_8:
- case ESP_AES_CCM_12:
- case ESP_AES_CCM_16:
- needed_len += 3;
- break;
- case ESP_AES_GCM_8:
- case ESP_AES_GCM_12:
- case ESP_AES_GCM_16:
- case ESP_AES_CTR:
- case ESP_AES_GMAC:
- needed_len += 4;
- break;
- default:
- if (needed_len == 0)
- {
- bad_case(pi->attrs.transid);
- }
- }
-
- if (kernel_alg_esp_auth_ok(pi->attrs.auth, NULL))
- {
- needed_len += kernel_alg_esp_auth_keylen(pi->attrs.auth);
- }
- else
- {
- switch (pi->attrs.auth)
- {
- case AUTH_ALGORITHM_NONE:
- break;
- case AUTH_ALGORITHM_HMAC_MD5:
- needed_len += HMAC_MD5_KEY_LEN;
- break;
- case AUTH_ALGORITHM_HMAC_SHA1:
- needed_len += HMAC_SHA1_KEY_LEN;
- break;
- case AUTH_ALGORITHM_DES_MAC:
- default:
- bad_case(pi->attrs.auth);
- }
- }
- break;
- }
- case PROTO_IPSEC_AH:
- {
- switch (pi->attrs.transid)
- {
- case AH_MD5:
- needed_len = HMAC_MD5_KEY_LEN;
- break;
- case AH_SHA:
- needed_len = HMAC_SHA1_KEY_LEN;
- break;
- default:
- bad_case(pi->attrs.transid);
- }
- break;
- }
- default:
- bad_case(protoid);
- }
-
- pi->keymat_len = needed_len;
-
- if (ep & EP_LOCAL)
- {
- compute_keymat_internal(st, protoid, pi->our_spi, needed_len,
- &pi->our_keymat);
- DBG(DBG_CRYPT,
- DBG_dump("KEYMAT computed:\n", pi->our_keymat,
- pi->keymat_len));
- }
- if (ep & EP_REMOTE)
- {
- compute_keymat_internal(st, protoid, pi->attrs.spi, needed_len,
- &pi->peer_keymat);
- DBG(DBG_CRYPT,
- DBG_dump("Peer KEYMAT computed:\n", pi->peer_keymat,
- pi->keymat_len));
- }
-}
-
-static void compute_keymats(struct state *st, enum endpoint ep)
-{
- if (st->st_ah.present)
- {
- compute_proto_keymat(st, PROTO_IPSEC_AH, &st->st_ah, ep);
- }
- if (st->st_esp.present)
- {
- compute_proto_keymat(st, PROTO_IPSEC_ESP, &st->st_esp, ep);
- }
-}
-
-static void wipe_proto_keymat(struct ipsec_proto_info *pi, enum endpoint ep)
-{
- if (ep & EP_LOCAL)
- {
- memwipe(pi->our_keymat, pi->keymat_len);
- }
- if (ep & EP_REMOTE)
- {
- memwipe(pi->peer_keymat, pi->keymat_len);
- }
-}
-
-static void wipe_keymats(struct state *st, enum endpoint ep)
-{
- if (st->st_ah.present)
- {
- wipe_proto_keymat(&st->st_ah, ep);
- }
- if (st->st_esp.present)
- {
- wipe_proto_keymat(&st->st_esp, ep);
- }
-}
-
-static bool uses_pubkey_auth(int auth)
-{
- switch (auth)
- {
- case OAKLEY_RSA_SIG:
- case OAKLEY_ECDSA_SIG:
- case OAKLEY_ECDSA_256:
- case OAKLEY_ECDSA_384:
- case OAKLEY_ECDSA_521:
- case XAUTHInitRSA:
- case XAUTHRespRSA:
- return TRUE;
- default:
- return FALSE;
- }
-}
-
-/* build an ID payload
- * Note: no memory is allocated for the body of the payload (tl->ptr).
- * We assume it will end up being a pointer into a sufficiently
- * stable datastructure. It only needs to last a short time.
- */
-static void build_id_payload(struct isakmp_ipsec_id *hd, chunk_t *tl, struct end *end)
-{
- identification_t *id = resolve_myid(end->id);
-
- zero(hd);
- hd->isaiid_idtype = id->get_type(id);
-
- switch (id->get_type(id))
- {
- case ID_ANY:
- hd->isaiid_idtype = aftoinfo(addrtypeof(&end->host_addr))->id_addr;
- tl->len = addrbytesptr(&end->host_addr,
- (const unsigned char **)&tl->ptr); /* sets tl->ptr too */
- break;
- case ID_IPV4_ADDR:
- case ID_IPV6_ADDR:
- case ID_FQDN:
- case ID_USER_FQDN:
- case ID_DER_ASN1_DN:
- case ID_KEY_ID:
- *tl = id->get_encoding(id);
- break;
- default:
- bad_case(id->get_type(id));
- }
-}
-
-/* State Transition Functions.
- *
- * The definition of state_microcode_table in demux.c is a good
- * overview of these routines.
- *
- * - Called from process_packet; result handled by complete_state_transition
- * - struct state_microcode member "processor" points to these
- * - these routine definitionss are in state order
- * - these routines must be restartable from any point of error return:
- * beware of memory allocated before any error.
- * - output HDR is usually emitted by process_packet (if state_microcode
- * member first_out_payload isn't ISAKMP_NEXT_NONE).
- *
- * The transition functions' functions include:
- * - process and judge payloads
- * - update st_iv (result of decryption is in st_new_iv)
- * - build reply packet
- */
-
-/* Handle a Main Mode Oakley first packet (responder side).
- * HDR;SA --> HDR;SA
- */
-stf_status main_inI1_outR1(struct msg_digest *md)
-{
- struct payload_digest *const sa_pd = md->chain[ISAKMP_NEXT_SA];
- struct state *st;
- connection_t *c;
- struct isakmp_proposal proposal;
- pb_stream proposal_pbs;
- pb_stream r_sa_pbs;
- u_int32_t ipsecdoisit;
- lset_t policy = LEMPTY;
- int vids_to_send = 0;
-
- /* We preparse the peer's proposal in order to determine
- * the requested authentication policy (RSA or PSK)
- */
- RETURN_STF_FAILURE(preparse_isakmp_sa_body(&sa_pd->payload.sa
- , &sa_pd->pbs, &ipsecdoisit, &proposal_pbs, &proposal));
-
- backup_pbs(&proposal_pbs);
- RETURN_STF_FAILURE(parse_isakmp_policy(&proposal_pbs
- , proposal.isap_notrans, &policy));
- restore_pbs(&proposal_pbs);
-
- /* We are only considering candidate connections that match
- * the requested authentication policy (RSA or PSK)
- */
- c = find_host_connection(&md->iface->addr, pluto_port
- , &md->sender, md->sender_port, policy);
-
- if (c == NULL && md->iface->ike_float)
- {
- c = find_host_connection(&md->iface->addr, NAT_T_IKE_FLOAT_PORT
- , &md->sender, md->sender_port, policy);
- }
-
- if (c == NULL)
- {
- /* See if a wildcarded connection can be found.
- * We cannot pick the right connection, so we're making a guess.
- * All Road Warrior connections are fair game:
- * we pick the first we come across (if any).
- * If we don't find any, we pick the first opportunistic
- * with the smallest subnet that includes the peer.
- * There is, of course, no necessary relationship between
- * an Initiator's address and that of its client,
- * but Food Groups kind of assumes one.
- */
- {
- connection_t *d;
-
- d = find_host_connection(&md->iface->addr
- , pluto_port, (ip_address*)NULL, md->sender_port, policy);
-
- for (; d != NULL; d = d->hp_next)
- {
- if (d->kind == CK_GROUP)
- {
- /* ignore */
- }
- else
- {
- if (d->kind == CK_TEMPLATE && !(d->policy & POLICY_OPPO))
- {
- /* must be Road Warrior: we have a winner */
- c = d;
- break;
- }
-
- /* Opportunistic or Shunt: pick tightest match */
- if (addrinsubnet(&md->sender, &d->spd.that.client)
- && (c == NULL || !subnetinsubnet(&c->spd.that.client, &d->spd.that.client)))
- c = d;
- }
- }
- }
-
- if (c == NULL)
- {
- loglog(RC_LOG_SERIOUS, "initial Main Mode message received on %s:%u"
- " but no connection has been authorized%s%s"
- , ip_str(&md->iface->addr), ntohs(portof(&md->iface->addr))
- , (policy != LEMPTY) ? " with policy=" : ""
- , (policy != LEMPTY) ? bitnamesof(sa_policy_bit_names, policy) : "");
- /* XXX notification is in order! */
- return STF_IGNORE;
- }
- else if (c->kind != CK_TEMPLATE)
- {
- loglog(RC_LOG_SERIOUS, "initial Main Mode message received on %s:%u"
- " but \"%s\" forbids connection"
- , ip_str(&md->iface->addr), pluto_port, c->name);
- /* XXX notification is in order! */
- return STF_IGNORE;
- }
- else
- {
- /* Create a temporary connection that is a copy of this one.
- * His ID isn't declared yet.
- */
- c = rw_instantiate(c, &md->sender, md->sender_port, NULL, NULL);
- }
- }
- else if (c->kind == CK_TEMPLATE)
- {
- /* Create an instance
- * This is a rare case: wildcard peer ID but static peer IP address
- */
- c = rw_instantiate(c, &md->sender, md->sender_port, NULL, c->spd.that.id);
- }
-
- /* Set up state */
- md->st = st = new_state();
- st->st_connection = c;
- set_cur_state(st); /* (caller will reset cur_state) */
- st->st_try = 0; /* not our job to try again from start */
- st->st_policy = c->policy & ~POLICY_IPSEC_MASK; /* only as accurate as connection */
-
- memcpy(st->st_icookie, md->hdr.isa_icookie, COOKIE_SIZE);
- get_cookie(FALSE, st->st_rcookie, COOKIE_SIZE, &md->sender);
-
- insert_state(st); /* needs cookies, connection, and msgid (0) */
-
- st->st_doi = ISAKMP_DOI_IPSEC;
- st->st_situation = SIT_IDENTITY_ONLY; /* We only support this */
-
- if ((c->kind == CK_INSTANCE) && (c->spd.that.host_port != pluto_port))
- {
- plog("responding to Main Mode from unknown peer %s:%u"
- , ip_str(&c->spd.that.host_addr), c->spd.that.host_port);
- }
- else if (c->kind == CK_INSTANCE)
- {
- plog("responding to Main Mode from unknown peer %s"
- , ip_str(&c->spd.that.host_addr));
- }
- else
- {
- plog("responding to Main Mode");
- }
-
- /* parse_isakmp_sa also spits out a winning SA into our reply,
- * so we have to build our md->reply and emit HDR before calling it.
- */
-
- /* determine how many Vendor ID payloads we will be sending */
- if (SEND_PLUTO_VID)
- {
- vids_to_send++;
- }
- if (SEND_CISCO_UNITY_VID)
- {
- vids_to_send++;
- }
- if (md->openpgp)
- {
- vids_to_send++;
- }
- if (SEND_XAUTH_VID)
- {
- vids_to_send++;
- }
- /* always send DPD Vendor ID */
- vids_to_send++;
- if (md->nat_traversal_vid && nat_traversal_enabled)
- {
- vids_to_send++;
- }
-
- /* HDR out.
- * We can't leave this to comm_handle() because we must
- * fill in the cookie.
- */
- {
- struct isakmp_hdr r_hdr = md->hdr;
-
- r_hdr.isa_flags &= ~ISAKMP_FLAG_COMMIT; /* we won't ever turn on this bit */
- memcpy(r_hdr.isa_rcookie, st->st_rcookie, COOKIE_SIZE);
- r_hdr.isa_np = ISAKMP_NEXT_SA;
- if (!out_struct(&r_hdr, &isakmp_hdr_desc, &md->reply, &md->rbody))
- return STF_INTERNAL_ERROR;
- }
-
- /* start of SA out */
- {
- struct isakmp_sa r_sa = sa_pd->payload.sa;
-
- r_sa.isasa_np = vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE;
-
- if (!out_struct(&r_sa, &isakmp_sa_desc, &md->rbody, &r_sa_pbs))
- return STF_INTERNAL_ERROR;
- }
-
- /* SA body in and out */
- RETURN_STF_FAILURE(parse_isakmp_sa_body(ipsecdoisit, &proposal_pbs
- ,&proposal, &r_sa_pbs, st, FALSE));
-
- /* if enabled send Pluto Vendor ID */
- if (SEND_PLUTO_VID)
- {
- if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
- , &md->rbody, VID_STRONGSWAN))
- {
- return STF_INTERNAL_ERROR;
- }
- }
-
- /* if enabled send Cisco Unity Vendor ID */
- if (SEND_CISCO_UNITY_VID)
- {
- if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
- , &md->rbody, VID_CISCO_UNITY))
- {
- return STF_INTERNAL_ERROR;
- }
- }
-
- /*
- * if the peer sent an OpenPGP Vendor ID we offer the same capability
- */
- if (md->openpgp)
- {
- if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
- , &md->rbody, VID_OPENPGP))
- {
- return STF_INTERNAL_ERROR;
- }
- }
-
- /* Announce our ability to do eXtended AUTHentication to the peer */
- if (SEND_XAUTH_VID)
- {
- if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
- , &md->rbody, VID_MISC_XAUTH))
- {
- return STF_INTERNAL_ERROR;
- }
- }
-
- /* Announce our ability to do Dead Peer Detection to the peer */
- if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
- , &md->rbody, VID_MISC_DPD))
- {
- return STF_INTERNAL_ERROR;
- }
-
- if (md->nat_traversal_vid && nat_traversal_enabled)
- {
- /* reply if NAT-Traversal draft is supported */
- st->nat_traversal = nat_traversal_vid_to_method(md->nat_traversal_vid);
-
- if (st->nat_traversal
- && !out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
- , &md->rbody, md->nat_traversal_vid))
- {
- return STF_INTERNAL_ERROR;
- }
- }
-
- close_message(&md->rbody);
-
- /* save initiator SA for HASH */
- free(st->st_p1isa.ptr);
- st->st_p1isa = chunk_create(sa_pd->pbs.start, pbs_room(&sa_pd->pbs));
- st->st_p1isa = chunk_clone(st->st_p1isa);
-
- return STF_OK;
-}
-
-/* STATE_MAIN_I1: HDR, SA --> auth dependent
- * PSK_AUTH, DS_AUTH: --> HDR, KE, Ni
- *
- * The following are not yet implemented:
- * PKE_AUTH: --> HDR, KE, [ HASH(1), ] <IDi1_b>PubKey_r, <Ni_b>PubKey_r
- * RPKE_AUTH: --> HDR, [ HASH(1), ] <Ni_b>Pubkey_r, <KE_b>Ke_i,
- * <IDi1_b>Ke_i [,<<Cert-I_b>Ke_i]
- *
- * We must verify that the proposal received matches one we sent.
- */
-stf_status main_inR1_outI2(struct msg_digest *md)
-{
- struct state *const st = md->st;
-
- u_int8_t np = ISAKMP_NEXT_NONE;
-
- /* verify echoed SA */
- {
- u_int32_t ipsecdoisit;
- pb_stream proposal_pbs;
- struct isakmp_proposal proposal;
- struct payload_digest *const sapd = md->chain[ISAKMP_NEXT_SA];
-
- RETURN_STF_FAILURE(preparse_isakmp_sa_body(&sapd->payload.sa
- ,&sapd->pbs, &ipsecdoisit, &proposal_pbs, &proposal));
- if (proposal.isap_notrans != 1)
- {
- loglog(RC_LOG_SERIOUS, "a single Transform is required in a selecting Oakley Proposal; found %u"
- , (unsigned)proposal.isap_notrans);
- RETURN_STF_FAILURE(ISAKMP_BAD_PROPOSAL_SYNTAX);
- }
- RETURN_STF_FAILURE(parse_isakmp_sa_body(ipsecdoisit
- , &proposal_pbs, &proposal, NULL, st, TRUE));
- }
-
- if (nat_traversal_enabled && md->nat_traversal_vid)
- {
- st->nat_traversal = nat_traversal_vid_to_method(md->nat_traversal_vid);
- plog("enabling possible NAT-traversal with method %s"
- , bitnamesof(natt_type_bitnames, st->nat_traversal));
- }
- if (st->nat_traversal & NAT_T_WITH_NATD)
- {
- np = (st->nat_traversal & NAT_T_WITH_RFC_VALUES) ?
- ISAKMP_NEXT_NATD_RFC : ISAKMP_NEXT_NATD_DRAFTS;
- }
-
- /**************** build output packet HDR;KE;Ni ****************/
-
- /* HDR out.
- * We can't leave this to comm_handle() because the isa_np
- * depends on the type of Auth (eventually).
- */
- echo_hdr(md, FALSE, ISAKMP_NEXT_KE);
-
- /* KE out */
- if (!build_and_ship_KE(st, &st->st_gi, st->st_oakley.group
- , &md->rbody, ISAKMP_NEXT_NONCE))
- {
- return STF_INTERNAL_ERROR;
- }
-
-#ifdef DEBUG
- /* Ni out */
- if (!build_and_ship_nonce(&st->st_ni, &md->rbody
- , (cur_debugging & IMPAIR_BUST_MI2)? ISAKMP_NEXT_VID : np, "Ni"))
- {
- return STF_INTERNAL_ERROR;
- }
- if (cur_debugging & IMPAIR_BUST_MI2)
- {
- /* generate a pointless large VID payload to push message over MTU */
- pb_stream vid_pbs;
-
- if (!out_generic(np, &isakmp_vendor_id_desc, &md->rbody, &vid_pbs))
- {
- return STF_INTERNAL_ERROR;
- }
- if (!out_zero(1500 /*MTU?*/, &vid_pbs, "Filler VID"))
- {
- return STF_INTERNAL_ERROR;
- }
- close_output_pbs(&vid_pbs);
- }
-#else
- /* Ni out */
- if (!build_and_ship_nonce(&st->st_ni, &md->rbody, np, "Ni"))
- {
- return STF_INTERNAL_ERROR;
- }
-#endif
-
- if (st->nat_traversal & NAT_T_WITH_NATD)
- {
- if (!nat_traversal_add_natd(ISAKMP_NEXT_NONE, &md->rbody, md))
- {
- return STF_INTERNAL_ERROR;
- }
- }
-
- /* finish message */
- close_message(&md->rbody);
-
- /* Reinsert the state, using the responder cookie we just received */
- unhash_state(st);
- memcpy(st->st_rcookie, md->hdr.isa_rcookie, COOKIE_SIZE);
- insert_state(st); /* needs cookies, connection, and msgid (0) */
-
- return STF_OK;
-}
-
-/* STATE_MAIN_R1:
- * PSK_AUTH, DS_AUTH: HDR, KE, Ni --> HDR, KE, Nr
- *
- * The following are not yet implemented:
- * PKE_AUTH: HDR, KE, [ HASH(1), ] <IDi1_b>PubKey_r, <Ni_b>PubKey_r
- * --> HDR, KE, <IDr1_b>PubKey_i, <Nr_b>PubKey_i
- * RPKE_AUTH:
- * HDR, [ HASH(1), ] <Ni_b>Pubkey_r, <KE_b>Ke_i, <IDi1_b>Ke_i [,<<Cert-I_b>Ke_i]
- * --> HDR, <Nr_b>PubKey_i, <KE_b>Ke_r, <IDr1_b>Ke_r
- */
-stf_status main_inI2_outR2(struct msg_digest *md)
-{
- struct state *const st = md->st;
- pb_stream *keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs;
-
- /* send CR if auth is RSA or ECDSA and no preloaded public key exists*/
- bool pubkey_auth = uses_pubkey_auth(st->st_oakley.auth);
- bool send_cr = !no_cr_send && pubkey_auth && !has_preloaded_public_key(st);
-
- u_int8_t np = ISAKMP_NEXT_NONE;
-
- /* KE in */
- RETURN_STF_FAILURE(accept_KE(&st->st_gi, "Gi", st->st_oakley.group, keyex_pbs));
-
- /* Ni in */
- RETURN_STF_FAILURE(accept_nonce(md, &st->st_ni, "Ni"));
-
- if (st->nat_traversal & NAT_T_WITH_NATD)
- {
- nat_traversal_natd_lookup(md);
-
- np = (st->nat_traversal & NAT_T_WITH_RFC_VALUES) ?
- ISAKMP_NEXT_NATD_RFC : ISAKMP_NEXT_NATD_DRAFTS;
- }
- if (st->nat_traversal)
- {
- nat_traversal_show_result(st->nat_traversal, md->sender_port);
- }
- if (st->nat_traversal & NAT_T_WITH_KA)
- {
- nat_traversal_new_ka_event();
- }
-
- /* decode certificate requests */
- st->st_connection->got_certrequest = FALSE;
- decode_cr(md, st->st_connection);
-
- /**************** build output packet HDR;KE;Nr ****************/
-
- /* HDR out done */
-
- /* KE out */
- if (!build_and_ship_KE(st, &st->st_gr, st->st_oakley.group
- , &md->rbody, ISAKMP_NEXT_NONCE))
- {
- return STF_INTERNAL_ERROR;
- }
-
-#ifdef DEBUG
- /* Nr out */
- if (!build_and_ship_nonce(&st->st_nr, &md->rbody,
- (cur_debugging & IMPAIR_BUST_MR2)? ISAKMP_NEXT_VID
- : (send_cr? ISAKMP_NEXT_CR : np), "Nr"))
- {
- return STF_INTERNAL_ERROR;
- }
- if (cur_debugging & IMPAIR_BUST_MR2)
- {
- /* generate a pointless large VID payload to push message over MTU */
- pb_stream vid_pbs;
-
- if (!out_generic((send_cr)? ISAKMP_NEXT_CR : np,
- &isakmp_vendor_id_desc, &md->rbody, &vid_pbs))
- {
- return STF_INTERNAL_ERROR;
- }
- if (!out_zero(1500 /*MTU?*/, &vid_pbs, "Filler VID"))
- {
- return STF_INTERNAL_ERROR;
- }
- close_output_pbs(&vid_pbs);
- }
-#else
- /* Nr out */
- if (!build_and_ship_nonce(&st->st_nr, &md->rbody,
- (send_cr)? ISAKMP_NEXT_CR : np, "Nr"))
- return STF_INTERNAL_ERROR;
-#endif
-
- /* CR out */
- if (send_cr)
- {
- if (st->st_connection->kind == CK_PERMANENT)
- {
- identification_t *ca = st->st_connection->spd.that.ca;
- chunk_t cr = (ca) ? ca->get_encoding(ca) : chunk_empty;
-
- if (!build_and_ship_CR(CERT_X509_SIGNATURE, cr, &md->rbody, np))
- {
- return STF_INTERNAL_ERROR;
- }
- }
- else
- {
- linked_list_t *list = collect_rw_ca_candidates(md);
- int count = list->get_count(list);
- bool error = FALSE;
-
- if (count)
- {
- enumerator_t *enumerator;
- identification_t *ca;
-
- enumerator = list->create_enumerator(list);
- while (enumerator->enumerate(enumerator, &ca))
- {
- if (!build_and_ship_CR(CERT_X509_SIGNATURE,
- ca->get_encoding(ca), &md->rbody,
- --count ? ISAKMP_NEXT_CR : np))
- {
- error = TRUE;
- break;
- }
- }
- enumerator->destroy(enumerator);
- }
- else
- {
- if (!build_and_ship_CR(CERT_X509_SIGNATURE, chunk_empty,
- &md->rbody, np))
- {
- error = TRUE;
- }
- }
- list->destroy_offset(list, offsetof(identification_t, destroy));
- if (error)
- {
- return STF_INTERNAL_ERROR;
- }
- }
- }
-
- if (st->nat_traversal & NAT_T_WITH_NATD)
- {
- if (!nat_traversal_add_natd(ISAKMP_NEXT_NONE, &md->rbody, md))
- {
- return STF_INTERNAL_ERROR;
- }
- }
-
- /* finish message */
- close_message(&md->rbody);
-
- /* next message will be encrypted, but not this one.
- * We could defer this calculation.
- */
- compute_dh_shared(st, st->st_gi);
- if (!generate_skeyids_iv(st))
- {
- return STF_FAIL + ISAKMP_AUTHENTICATION_FAILED;
- }
- update_iv(st);
-
- return STF_OK;
-}
-
-/* STATE_MAIN_I2:
- * SMF_PSK_AUTH: HDR, KE, Nr --> HDR*, IDi1, HASH_I
- * SMF_DS_AUTH: HDR, KE, Nr --> HDR*, IDi1, [ CERT, ] SIG_I
- *
- * The following are not yet implemented.
- * SMF_PKE_AUTH: HDR, KE, <IDr1_b>PubKey_i, <Nr_b>PubKey_i
- * --> HDR*, HASH_I
- * SMF_RPKE_AUTH: HDR, <Nr_b>PubKey_i, <KE_b>Ke_r, <IDr1_b>Ke_r
- * --> HDR*, HASH_I
- */
-stf_status main_inR2_outI3(struct msg_digest *md)
-{
- struct state *const st = md->st;
- pb_stream *const keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs;
- pb_stream id_pbs; /* ID Payload; also used for hash calculation */
-
- connection_t *c = st->st_connection;
- certpolicy_t cert_policy = c->spd.this.sendcert;
- cert_t *mycert = c->spd.this.cert;
- bool requested, send_cert, send_cr;
- bool pubkey_auth = uses_pubkey_auth(st->st_oakley.auth);
-
- int auth_payload = pubkey_auth ? ISAKMP_NEXT_SIG : ISAKMP_NEXT_HASH;
-
- /* KE in */
- RETURN_STF_FAILURE(accept_KE(&st->st_gr, "Gr", st->st_oakley.group, keyex_pbs));
-
- /* Nr in */
- RETURN_STF_FAILURE(accept_nonce(md, &st->st_nr, "Nr"));
-
- /* decode certificate requests */
- c->got_certrequest = FALSE;
- decode_cr(md, c);
-
- /* free collected certificate requests since as initiator
- * we don't heed them anyway
- */
- if (c->requested_ca)
- {
- c->requested_ca->destroy_offset(c->requested_ca,
- offsetof(identification_t, destroy));
- c->requested_ca = NULL;
- }
-
- /* send certificate if auth is RSA, we have one and we want
- * or are requested to send it
- */
- requested = cert_policy == CERT_SEND_IF_ASKED && c->got_certrequest;
- send_cert = pubkey_auth && mycert &&
- mycert->cert->get_type(mycert->cert) == CERT_X509 &&
- (cert_policy == CERT_ALWAYS_SEND || requested);
-
- /* send certificate request if we don't have a preloaded RSA public key */
- send_cr = !no_cr_send && send_cert && !has_preloaded_public_key(st);
-
- /* done parsing; initialize crypto */
- compute_dh_shared(st, st->st_gr);
- if (!generate_skeyids_iv(st))
- {
- return STF_FAIL + ISAKMP_AUTHENTICATION_FAILED;
- }
- if (st->nat_traversal & NAT_T_WITH_NATD)
- {
- nat_traversal_natd_lookup(md);
- }
- if (st->nat_traversal)
- {
- nat_traversal_show_result(st->nat_traversal, md->sender_port);
- }
- if (st->nat_traversal & NAT_T_WITH_KA)
- {
- nat_traversal_new_ka_event();
- }
-
- /*************** build output packet HDR*;IDii;HASH/SIG_I ***************/
- /* ??? NOTE: this is almost the same as main_inI3_outR3's code */
-
- /* HDR* out done */
-
- /* IDii out */
- {
- struct isakmp_ipsec_id id_hd;
- chunk_t id_b;
-
- build_id_payload(&id_hd, &id_b, &c->spd.this);
- id_hd.isaiid_np = (send_cert)? ISAKMP_NEXT_CERT : auth_payload;
- if (!out_struct(&id_hd, &isakmp_ipsec_identification_desc, &md->rbody, &id_pbs)
- || !out_chunk(id_b, &id_pbs, "my identity"))
- {
- return STF_INTERNAL_ERROR;
- }
- close_output_pbs(&id_pbs);
- }
-
- /* CERT out */
- if (pubkey_auth)
- {
- DBG(DBG_CONTROL,
- DBG_log("our certificate policy is %N", cert_policy_names, cert_policy)
- )
- if (mycert && mycert->cert->get_type(mycert->cert) == CERT_X509)
- {
- const char *request_text = "";
-
- if (cert_policy == CERT_SEND_IF_ASKED)
- {
- request_text = (send_cert)? "upon request":"without request";
- }
- plog("we have a cert %s sending it %s"
- , send_cert? "and are":"but are not", request_text);
- }
- else
- {
- plog("we don't have a cert");
- }
- }
- if (send_cert)
- {
- bool success = FALSE;
- chunk_t cert_encoding;
- pb_stream cert_pbs;
-
- struct isakmp_cert cert_hd;
- cert_hd.isacert_np = (send_cr)? ISAKMP_NEXT_CR : ISAKMP_NEXT_SIG;
- cert_hd.isacert_type = CERT_X509_SIGNATURE;
-
- if (!out_struct(&cert_hd, &isakmp_ipsec_certificate_desc, &md->rbody, &cert_pbs))
- {
- return STF_INTERNAL_ERROR;
- }
- if (mycert->cert->get_encoding(mycert->cert, CERT_ASN1_DER,
- &cert_encoding))
- {
- success = out_chunk(cert_encoding, &cert_pbs, "CERT");
- free(cert_encoding.ptr);
- }
- if (!success)
- {
- return STF_INTERNAL_ERROR;
- }
- close_output_pbs(&cert_pbs);
- }
-
- /* CR out */
- if (send_cr)
- {
- identification_t *ca = st->st_connection->spd.that.ca;
- chunk_t cr = (ca) ? ca->get_encoding(ca) : chunk_empty;
-
- if (!build_and_ship_CR(CERT_X509_SIGNATURE, cr, &md->rbody, ISAKMP_NEXT_SIG))
- {
- return STF_INTERNAL_ERROR;
- }
- }
-
- /* HASH_I or SIG_I out */
- {
- chunk_t hash = chunk_alloca(MAX_DIGEST_LEN);
-
- main_mode_hash(st, &hash, TRUE, &id_pbs);
-
- if (auth_payload == ISAKMP_NEXT_HASH)
- {
- /* HASH_I out */
- if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_hash_desc, &md->rbody,
- hash.ptr, hash.len, "HASH_I"))
- {
- return STF_INTERNAL_ERROR;
- }
- }
- else
- {
- /* SIG_I out */
- u_char sig_val[RSA_MAX_OCTETS];
- signature_scheme_t scheme;
- size_t sig_len;
-
- scheme = oakley_to_signature_scheme(st->st_oakley.auth);
-
- sig_len = sign_hash(scheme, c, sig_val, hash);
- if (sig_len == 0)
- {
- loglog(RC_LOG_SERIOUS, "unable to locate my private key for signature");
- return STF_FAIL + ISAKMP_AUTHENTICATION_FAILED;
- }
-
- if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_signature_desc
- , &md->rbody, sig_val, sig_len, "SIG_I"))
- {
- return STF_INTERNAL_ERROR;
- }
- }
- }
-
- /* encrypt message, except for fixed part of header */
-
- /* st_new_iv was computed by generate_skeyids_iv */
- if (!encrypt_message(&md->rbody, st))
- {
- return STF_INTERNAL_ERROR; /* ??? we may be partly committed */
- }
- return STF_OK;
-}
-
-/* Shared logic for asynchronous lookup of DNS KEY records.
- * Used for STATE_MAIN_R2 and STATE_MAIN_I3.
- */
-
-enum key_oppo_step {
- kos_null,
- kos_his_txt
-#ifdef USE_KEYRR
- , kos_his_key
-#endif
-};
-
-struct key_continuation {
- struct adns_continuation ac; /* common prefix */
- struct msg_digest *md;
- enum key_oppo_step step;
- bool failure_ok;
- err_t last_ugh;
-};
-
-typedef stf_status (key_tail_fn)(struct msg_digest *md
- , struct key_continuation *kc);
-
-static void report_key_dns_failure(identification_t *id, err_t ugh)
-{
- loglog(RC_LOG_SERIOUS, "no RSA public key known for '%Y'"
- "; DNS search for KEY failed (%s)", id, ugh);
-}
-
-
-/* Processs the Main Mode ID Payload and the Authenticator
- * (Hash or Signature Payload).
- * If a DNS query is still needed to get the other host's public key,
- * the query is initiated and STF_SUSPEND is returned.
- * Note: parameter kc is a continuation containing the results from
- * the previous DNS query, or NULL indicating no query has been issued.
- */
-static stf_status
-main_id_and_auth(struct msg_digest *md
- , bool initiator /* are we the Initiator? */
- , cont_fn_t cont_fn /* continuation function */
- , const struct key_continuation *kc /* current state, can be NULL */
-)
-{
- chunk_t hash = chunk_alloca(MAX_DIGEST_LEN);
- struct state *st = md->st;
- identification_t *peer;
- stf_status r = STF_OK;
-
- /* ID Payload in */
- if (!decode_peer_id(md, &peer))
- {
- return STF_FAIL + ISAKMP_INVALID_ID_INFORMATION;
- }
-
- /* Hash the ID Payload.
- * main_mode_hash requires idpl->cur to be at end of payload
- * so we temporarily set if so.
- */
- {
- pb_stream *idpl = &md->chain[ISAKMP_NEXT_ID]->pbs;
- u_int8_t *old_cur = idpl->cur;
-
- idpl->cur = idpl->roof;
- main_mode_hash(st, &hash, !initiator, idpl);
- idpl->cur = old_cur;
- }
-
- switch (st->st_oakley.auth)
- {
- case OAKLEY_PRESHARED_KEY:
- case XAUTHInitPreShared:
- case XAUTHRespPreShared:
- {
- pb_stream *const hash_pbs = &md->chain[ISAKMP_NEXT_HASH]->pbs;
-
- if (pbs_left(hash_pbs) != hash.len
- || memcmp(hash_pbs->cur, hash.ptr, hash.len) != 0)
- {
- DBG_cond_dump(DBG_CRYPT, "received HASH:"
- , hash_pbs->cur, pbs_left(hash_pbs));
- loglog(RC_LOG_SERIOUS, "received Hash Payload does not match computed value");
- /* XXX Could send notification back */
- r = STF_FAIL + ISAKMP_INVALID_HASH_INFORMATION;
- }
- }
- break;
-
- case OAKLEY_RSA_SIG:
- case XAUTHInitRSA:
- case XAUTHRespRSA:
- r = check_signature(KEY_RSA, peer, st, hash,
- &md->chain[ISAKMP_NEXT_SIG]->pbs,
-#ifdef USE_KEYRR
- kc == NULL ? NULL : kc->ac.keys_from_dns,
-#endif /* USE_KEYRR */
- kc == NULL ? NULL : kc->ac.gateways_from_dns
- );
-
- if (r == STF_SUSPEND)
- {
- err_t ugh = NULL;
-#ifdef ADNS
- /* initiate/resume asynchronous DNS lookup for key */
- struct key_continuation *nkc = malloc_thing(struct key_continuation);
- enum key_oppo_step step_done = kc == NULL? kos_null : kc->step;
-
- /* Record that state is used by a suspended md */
- passert(st->st_suspended_md == NULL);
- st->st_suspended_md = md;
-
- nkc->failure_ok = FALSE;
- nkc->md = md;
-
- switch (step_done)
- {
- case kos_null:
- /* first try: look for the TXT records */
- nkc->step = kos_his_txt;
-#ifdef USE_KEYRR
- nkc->failure_ok = TRUE;
-#endif
- ugh = start_adns_query(peer, peer, T_TXT, cont_fn, &nkc->ac);
- break;
-
-#ifdef USE_KEYRR
- case kos_his_txt:
- /* second try: look for the KEY records */
- nkc->step = kos_his_key;
- ugh = start_adns_query(peer, NULL, T_KEY, cont_fn, &nkc->ac);
- break;
-#endif /* USE_KEYRR */
-
- default:
- bad_case(step_done);
- }
-#else /* ADNS */
- ugh = "adns not supported";
-#endif /* ADNS */
- if (ugh != NULL)
- {
- report_key_dns_failure(peer, ugh);
- st->st_suspended_md = NULL;
- r = STF_FAIL + ISAKMP_INVALID_KEY_INFORMATION;
- }
- }
- break;
-
- case OAKLEY_ECDSA_256:
- case OAKLEY_ECDSA_384:
- case OAKLEY_ECDSA_521:
- r = check_signature(KEY_ECDSA, peer, st, hash,
- &md->chain[ISAKMP_NEXT_SIG]->pbs,
-#ifdef USE_KEYRR
- NULL,
-#endif /* USE_KEYRR */
- NULL);
- break;
-
- default:
- bad_case(st->st_oakley.auth);
- }
- if (r != STF_OK)
- {
- peer->destroy(peer);
- return r;
- }
- DBG(DBG_CRYPT, DBG_log("authentication succeeded"));
-
- /*
- * With the peer ID known, let's see if we need to switch connections.
- */
- if (!switch_connection(md, peer, initiator))
- {
- r = STF_FAIL + ISAKMP_INVALID_ID_INFORMATION;
- }
- peer->destroy(peer);
- return r;
-}
-
-/* This continuation is called as part of either
- * the main_inI3_outR3 state or main_inR3 state.
- *
- * The "tail" function is the corresponding tail
- * function main_inI3_outR3_tail | main_inR3_tail,
- * either directly when the state is started, or via
- * adns continuation.
- *
- * Basically, we go around in a circle:
- * main_in?3* -> key_continue
- * ^ \
- * / V
- * adns main_in?3*_tail
- * ^ |
- * \ V
- * main_id_and_auth
- *
- * until such time as main_id_and_auth is able
- * to find authentication, or we run out of things
- * to try.
- */
-static void key_continue(struct adns_continuation *cr, err_t ugh,
- key_tail_fn *tail)
-{
- struct key_continuation *kc = (void *)cr;
- struct state *st = kc->md->st;
-
- passert(cur_state == NULL);
-
- /* if st == NULL, our state has been deleted -- just clean up */
- if (st != NULL)
- {
- stf_status r;
-
- passert(st->st_suspended_md == kc->md);
- st->st_suspended_md = NULL; /* no longer connected or suspended */
- cur_state = st;
-
- if (!kc->failure_ok && ugh != NULL)
- {
- report_key_dns_failure(st->st_connection->spd.that.id, ugh);
- r = STF_FAIL + ISAKMP_INVALID_KEY_INFORMATION;
- }
- else
- {
-
-#ifdef USE_KEYRR
- passert(kc->step == kos_his_txt || kc->step == kos_his_key);
-#else
- passert(kc->step == kos_his_txt);
-#endif
- kc->last_ugh = ugh; /* record previous error in case we need it */
- r = (*tail)(kc->md, kc);
- }
- complete_state_transition(&kc->md, r);
- }
- if (kc->md != NULL)
- {
- release_md(kc->md);
- }
- cur_state = NULL;
-}
-
-/* STATE_MAIN_R2:
- * PSK_AUTH: HDR*, IDi1, HASH_I --> HDR*, IDr1, HASH_R
- * DS_AUTH: HDR*, IDi1, [ CERT, ] SIG_I --> HDR*, IDr1, [ CERT, ] SIG_R
- * PKE_AUTH, RPKE_AUTH: HDR*, HASH_I --> HDR*, HASH_R
- *
- * Broken into parts to allow asynchronous DNS lookup.
- *
- * - main_inI3_outR3 to start
- * - main_inI3_outR3_tail to finish or suspend for DNS lookup
- * - main_inI3_outR3_continue to start main_inI3_outR3_tail again
- */
-static key_tail_fn main_inI3_outR3_tail; /* forward */
-
-stf_status main_inI3_outR3(struct msg_digest *md)
-{
- return main_inI3_outR3_tail(md, NULL);
-}
-
-static void main_inI3_outR3_continue(struct adns_continuation *cr, err_t ugh)
-{
- key_continue(cr, ugh, main_inI3_outR3_tail);
-}
-
-static stf_status
-main_inI3_outR3_tail(struct msg_digest *md
-, struct key_continuation *kc)
-{
- struct state *const st = md->st;
- u_int8_t auth_payload;
- pb_stream r_id_pbs; /* ID Payload; also used for hash calculation */
- certpolicy_t cert_policy;
- cert_t *mycert;
- bool pubkey_auth, send_cert, requested;
-
- /* ID and HASH_I or SIG_I in
- * Note: this may switch the connection being used!
- */
- {
- stf_status r = main_id_and_auth(md, FALSE
- , main_inI3_outR3_continue
- , kc);
-
- if (r != STF_OK)
- {
- return r;
- }
- }
-
- /* send certificate if pubkey authentication is used, we have one
- * and we want or are requested to send it
- */
- cert_policy = st->st_connection->spd.this.sendcert;
- mycert = st->st_connection->spd.this.cert;
- requested = cert_policy == CERT_SEND_IF_ASKED
- && st->st_connection->got_certrequest;
- pubkey_auth = uses_pubkey_auth(st->st_oakley.auth);
- send_cert = pubkey_auth && mycert &&
- mycert->cert->get_type(mycert->cert) == CERT_X509 &&
- (cert_policy == CERT_ALWAYS_SEND || requested);
-
- /*************** build output packet HDR*;IDir;HASH/SIG_R ***************/
- /* proccess_packet() would automatically generate the HDR*
- * payload if smc->first_out_payload is not ISAKMP_NEXT_NONE.
- * We don't do this because we wish there to be no partially
- * built output packet if we need to suspend for asynch DNS.
- */
- /* ??? NOTE: this is almost the same as main_inR2_outI3's code */
-
- /* HDR* out
- * If auth were PKE_AUTH or RPKE_AUTH, ISAKMP_NEXT_HASH would
- * be first payload.
- */
- echo_hdr(md, TRUE, ISAKMP_NEXT_ID);
-
- auth_payload = pubkey_auth ? ISAKMP_NEXT_SIG : ISAKMP_NEXT_HASH;
-
- /* IDir out */
- {
- /* id_hd should be struct isakmp_id, but struct isakmp_ipsec_id
- * allows build_id_payload() to work for both phases.
- */
- struct isakmp_ipsec_id id_hd;
- chunk_t id_b;
-
- build_id_payload(&id_hd, &id_b, &st->st_connection->spd.this);
- id_hd.isaiid_np = (send_cert)? ISAKMP_NEXT_CERT : auth_payload;
- if (!out_struct(&id_hd, &isakmp_ipsec_identification_desc, &md->rbody, &r_id_pbs)
- || !out_chunk(id_b, &r_id_pbs, "my identity"))
- {
- return STF_INTERNAL_ERROR;
- }
- close_output_pbs(&r_id_pbs);
- }
-
- /* CERT out */
- if (pubkey_auth)
- {
- DBG(DBG_CONTROL,
- DBG_log("our certificate policy is %N", cert_policy_names, cert_policy)
- )
- if (mycert && mycert->cert->get_type(mycert->cert) == CERT_X509)
- {
- const char *request_text = "";
-
- if (cert_policy == CERT_SEND_IF_ASKED)
- {
- request_text = (send_cert)? "upon request":"without request";
- }
- plog("we have a cert %s sending it %s"
- , send_cert? "and are":"but are not", request_text);
- }
- else
- {
- plog("we don't have a cert");
- }
- }
- if (send_cert)
- {
- bool success = FALSE;
- chunk_t cert_encoding;
- pb_stream cert_pbs;
- struct isakmp_cert cert_hd;
-
- cert_hd.isacert_np = ISAKMP_NEXT_SIG;
- cert_hd.isacert_type = CERT_X509_SIGNATURE;
-
- if (!out_struct(&cert_hd, &isakmp_ipsec_certificate_desc, &md->rbody, &cert_pbs))
- {
- return STF_INTERNAL_ERROR;
- }
- if (mycert->cert->get_encoding(mycert->cert, CERT_ASN1_DER,
- &cert_encoding))
- {
- success = out_chunk(cert_encoding, &cert_pbs, "CERT");
- free(cert_encoding.ptr);
- }
- if (!success)
- {
- return STF_INTERNAL_ERROR;
- }
- close_output_pbs(&cert_pbs);
- }
-
- /* HASH_R or SIG_R out */
- {
- chunk_t hash = chunk_alloca(MAX_DIGEST_LEN);
-
- main_mode_hash(st, &hash, FALSE, &r_id_pbs);
-
- if (auth_payload == ISAKMP_NEXT_HASH)
- {
- /* HASH_R out */
- if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_hash_desc, &md->rbody,
- hash.ptr, hash.len, "HASH_R"))
- {
- return STF_INTERNAL_ERROR;
- }
- }
- else
- {
- /* SIG_R out */
- u_char sig_val[RSA_MAX_OCTETS];
- signature_scheme_t scheme;
- size_t sig_len;
-
- scheme = oakley_to_signature_scheme(st->st_oakley.auth);
-
- sig_len = sign_hash(scheme, st->st_connection, sig_val, hash);
- if (sig_len == 0)
- {
- loglog(RC_LOG_SERIOUS, "unable to locate my private key for signature");
- return STF_FAIL + ISAKMP_AUTHENTICATION_FAILED;
- }
-
- if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_signature_desc
- , &md->rbody, sig_val, sig_len, "SIG_R"))
- {
- return STF_INTERNAL_ERROR;
- }
- }
- }
-
- /* encrypt message, sans fixed part of header */
-
- if (!encrypt_message(&md->rbody, st))
- {
- return STF_INTERNAL_ERROR; /* ??? we may be partly committed */
- }
-
- /* Last block of Phase 1 (R3), kept for Phase 2 IV generation */
- DBG_cond_dump(DBG_CRYPT, "last encrypted block of Phase 1:"
- , st->st_new_iv, st->st_new_iv_len);
-
- ISAKMP_SA_established(st->st_connection, st->st_serialno);
-
- /* Save Phase 1 IV */
- st->st_ph1_iv_len = st->st_new_iv_len;
- set_ph1_iv(st, st->st_new_iv);
-
- return STF_OK;
-}
-
-/* STATE_MAIN_I3:
- * Handle HDR*;IDir;HASH/SIG_R from responder.
- *
- * Broken into parts to allow asynchronous DNS for KEY records.
- *
- * - main_inR3 to start
- * - main_inR3_tail to finish or suspend for DNS lookup
- * - main_inR3_continue to start main_inR3_tail again
- */
-
-static key_tail_fn main_inR3_tail; /* forward */
-
-stf_status main_inR3(struct msg_digest *md)
-{
- return main_inR3_tail(md, NULL);
-}
-
-static void main_inR3_continue(struct adns_continuation *cr, err_t ugh)
-{
- key_continue(cr, ugh, main_inR3_tail);
-}
-
-static stf_status main_inR3_tail(struct msg_digest *md,
- struct key_continuation *kc)
-{
- struct state *const st = md->st;
-
- /* ID and HASH_R or SIG_R in
- * Note: this may switch the connection being used!
- */
- {
- stf_status r = main_id_and_auth(md, TRUE, main_inR3_continue, kc);
-
- if (r != STF_OK)
- {
- return r;
- }
- }
-
- /**************** done input ****************/
-
- ISAKMP_SA_established(st->st_connection, st->st_serialno);
-
- /* Save Phase 1 IV */
- st->st_ph1_iv_len = st->st_new_iv_len;
- set_ph1_iv(st, st->st_new_iv);
-
-
- update_iv(st); /* finalize our Phase 1 IV */
-
- return STF_OK;
-}
-
-/* Handle first message of Phase 2 -- Quick Mode.
- * HDR*, HASH(1), SA, Ni [, KE ] [, IDci, IDcr ] -->
- * HDR*, HASH(2), SA, Nr [, KE ] [, IDci, IDcr ]
- * (see RFC 2409 "IKE" 5.5)
- * Installs inbound IPsec SAs.
- * Although this seems early, we know enough to do so, and
- * this way we know that it is soon enough to catch all
- * packets that other side could send using this IPsec SA.
- *
- * Broken into parts to allow asynchronous DNS for TXT records:
- *
- * - quick_inI1_outR1 starts the ball rolling.
- * It checks and parses enough to learn the Phase 2 IDs
- *
- * - quick_inI1_outR1_tail does the rest of the job
- * unless DNS must be consulted. In that case,
- * it starts a DNS query, salts away what is needed
- * to continue, and suspends. Calls
- * + quick_inI1_outR1_start_query
- * + quick_inI1_outR1_process_answer
- *
- * - quick_inI1_outR1_continue will restart quick_inI1_outR1_tail
- * when DNS comes back with an answer.
- *
- * A big chunk of quick_inI1_outR1_tail is executed twice.
- * This is necessary because the set of connections
- * might change while we are awaiting DNS.
- * When first called, gateways_from_dns == NULL. If DNS is
- * consulted asynchronously, gateways_from_dns != NULL the second time.
- * Remember that our state object might disappear too!
- *
- *
- * If the connection is opportunistic, we must verify delegation.
- *
- * 1. Check that we are authorized to be SG for
- * our client. We look for the TXT record that
- * delegates us. We also check that the public
- * key (if present) matches the private key we used.
- * Eventually, we should probably require DNSsec
- * authentication for our side.
- *
- * 2. If our client TXT record did not include a
- * public key, check the KEY record indicated
- * by the identity in the TXT record.
- *
- * 3. If the peer's client is the peer itself, we
- * consider it authenticated. Otherwise, we check
- * the TXT record for the client to see that
- * the identity of the SG matches the peer and
- * that some public key (if present in the TXT)
- * matches. We need not check the public key if
- * it isn't in the TXT record.
- *
- * Since p isn't yet instantiated, we need to look
- * in c for description of peer.
- *
- * We cannot afford to block waiting for a DNS query.
- * The code here is structured as two halves:
- * - process the result of just completed
- * DNS query (if any)
- * - if another query is needed, initiate the next
- * DNS query and suspend
- */
-
-enum verify_oppo_step {
- vos_fail,
- vos_start,
- vos_our_client,
- vos_our_txt,
-#ifdef USE_KEYRR
- vos_our_key,
-#endif /* USE_KEYRR */
- vos_his_client,
- vos_done
-};
-
-static const char *const verify_step_name[] = {
- "vos_fail",
- "vos_start",
- "vos_our_client",
- "vos_our_txt",
-#ifdef USE_KEYRR
- "vos_our_key",
-#endif /* USE_KEYRR */
- "vos_his_client",
- "vos_done"
-};
-
-/* hold anything we can handle of a Phase 2 ID */
-struct p2id {
- ip_subnet net;
- u_int8_t proto;
- u_int16_t port;
-};
-
-struct verify_oppo_bundle {
- enum verify_oppo_step step;
- bool failure_ok; /* if true, quick_inI1_outR1_continue will try
- * other things on DNS failure */
- struct msg_digest *md;
- struct p2id my, his;
- unsigned int new_iv_len; /* p1st's might change */
- u_char new_iv[MAX_DIGEST_LEN];
- /* int whackfd; */ /* not needed because we are Responder */
-};
-
-struct verify_oppo_continuation {
- struct adns_continuation ac; /* common prefix */
- struct verify_oppo_bundle b;
-};
-
-static stf_status quick_inI1_outR1_tail(struct verify_oppo_bundle *b
- , struct adns_continuation *ac);
-
-stf_status quick_inI1_outR1(struct msg_digest *md)
-{
- const struct state *const p1st = md->st;
- connection_t *c = p1st->st_connection;
- struct payload_digest *const id_pd = md->chain[ISAKMP_NEXT_ID];
- struct verify_oppo_bundle b;
-
- /* HASH(1) in */
- CHECK_QUICK_HASH(md
- , quick_mode_hash12(hash_val, hash_pbs->roof, md->message_pbs.roof
- , p1st, &md->hdr.isa_msgid, FALSE)
- , "HASH(1)", "Quick I1");
-
- /* [ IDci, IDcr ] in
- * We do this now (probably out of physical order) because
- * we wish to select the correct connection before we consult
- * it for policy.
- */
-
- if (id_pd != NULL)
- {
- /* ??? we are assuming IPSEC_DOI */
-
- /* IDci (initiator is peer) */
-
- if (!decode_net_id(&id_pd->payload.ipsec_id, &id_pd->pbs
- , &b.his.net, "peer client"))
- {
- return STF_FAIL + ISAKMP_INVALID_ID_INFORMATION;
- }
-
- /* Hack for MS 818043 NAT-T Update */
-
- if (id_pd->payload.ipsec_id.isaiid_idtype == ID_FQDN)
- {
- happy(addrtosubnet(&c->spd.that.host_addr, &b.his.net));
- }
-
- /* End Hack for MS 818043 NAT-T Update */
-
- b.his.proto = id_pd->payload.ipsec_id.isaiid_protoid;
- b.his.port = id_pd->payload.ipsec_id.isaiid_port;
- b.his.net.addr.u.v4.sin_port = htons(b.his.port);
-
- /* IDcr (we are responder) */
-
- if (!decode_net_id(&id_pd->next->payload.ipsec_id, &id_pd->next->pbs
- , &b.my.net, "our client"))
- {
- return STF_FAIL + ISAKMP_INVALID_ID_INFORMATION;
- }
- b.my.proto = id_pd->next->payload.ipsec_id.isaiid_protoid;
- b.my.port = id_pd->next->payload.ipsec_id.isaiid_port;
- b.my.net.addr.u.v4.sin_port = htons(b.my.port);
- }
- else
- {
- /* implicit IDci and IDcr: peer and self */
- if (!sameaddrtype(&c->spd.this.host_addr, &c->spd.that.host_addr))
- {
- return STF_FAIL;
- }
- happy(addrtosubnet(&c->spd.this.host_addr, &b.my.net));
- happy(addrtosubnet(&c->spd.that.host_addr, &b.his.net));
- b.his.proto = b.my.proto = 0;
- b.his.port = b.my.port = 0;
- }
- b.step = vos_start;
- b.md = md;
- b.new_iv_len = p1st->st_new_iv_len;
- memcpy(b.new_iv, p1st->st_new_iv, p1st->st_new_iv_len);
- return quick_inI1_outR1_tail(&b, NULL);
-}
-
-#ifdef ADNS
-
-static void
-report_verify_failure(struct verify_oppo_bundle *b, err_t ugh)
-{
- struct state *st = b->md->st;
- char fgwb[ADDRTOT_BUF]
- , cb[ADDRTOT_BUF];
- ip_address client;
- err_t which = NULL;
-
- switch (b->step)
- {
- case vos_our_client:
- case vos_our_txt:
-#ifdef USE_KEYRR
- case vos_our_key:
-#endif /* USE_KEYRR */
- which = "our";
- networkof(&b->my.net, &client);
- break;
-
- case vos_his_client:
- which = "his";
- networkof(&b->his.net, &client);
- break;
-
- case vos_start:
- case vos_done:
- case vos_fail:
- default:
- bad_case(b->step);
- }
-
- addrtot(&st->st_connection->spd.that.host_addr, 0, fgwb, sizeof(fgwb));
- addrtot(&client, 0, cb, sizeof(cb));
- loglog(RC_OPPOFAILURE
- , "gateway %s wants connection with %s as %s client, but DNS fails to confirm delegation: %s"
- , fgwb, cb, which, ugh);
-}
-
-static void quick_inI1_outR1_continue(struct adns_continuation *cr, err_t ugh)
-{
- stf_status r;
- struct verify_oppo_continuation *vc = (void *)cr;
- struct verify_oppo_bundle *b = &vc->b;
- struct state *st = b->md->st;
-
- passert(cur_state == NULL);
- /* if st == NULL, our state has been deleted -- just clean up */
- if (st != NULL)
- {
- passert(st->st_suspended_md == b->md);
- st->st_suspended_md = NULL; /* no longer connected or suspended */
- cur_state = st;
- if (!b->failure_ok && ugh != NULL)
- {
- report_verify_failure(b, ugh);
- r = STF_FAIL + ISAKMP_INVALID_ID_INFORMATION;
- }
- else
- {
- r = quick_inI1_outR1_tail(b, cr);
- }
- complete_state_transition(&b->md, r);
- }
- if (b->md != NULL)
- {
- release_md(b->md);
- }
- cur_state = NULL;
-}
-
-static stf_status quick_inI1_outR1_start_query(struct verify_oppo_bundle *b,
- enum verify_oppo_step next_step)
-{
- struct msg_digest *md = b->md;
- struct state *p1st = md->st;
- connection_t *c = p1st->st_connection;
- struct verify_oppo_continuation *vc = malloc_thing(struct verify_oppo_continuation);
- identification_t *id; /* subject of query */
- identification_t *our_id; /* needed for myid playing */
- identification_t *our_id_space; /* ephemeral: no need for unshare_id_content */
- ip_address client;
- err_t ugh = NULL;
-
- /* Record that state is used by a suspended md */
- b->step = next_step; /* not just vc->b.step */
- vc->b = *b;
- passert(p1st->st_suspended_md == NULL);
- p1st->st_suspended_md = b->md;
-
- DBG(DBG_CONTROL,
- {
- char ours[SUBNETTOT_BUF];
- char his[SUBNETTOT_BUF];
-
- subnettot(&c->spd.this.client, 0, ours, sizeof(ours));
- subnettot(&c->spd.that.client, 0, his, sizeof(his));
-
- DBG_log("responding with DNS query - from %s to %s new state: %s"
- , ours, his, verify_step_name[b->step]);
- });
-
- /* Resolve %myid in a cheesy way.
- * We have to do the resolution because start_adns_query
- * et al have insufficient information to do so.
- * If %myid is already known, we'll use that value
- * (XXX this may be a mistake: it could be stale).
- * If %myid is unknown, we should check to see if
- * there are credentials for the IP address or the FQDN.
- * Instead, we'll just assume the IP address since we are
- * acting as the responder and only the IP address would
- * have gotten it to us.
- * We don't even try to do this for the other side:
- * %myid makes no sense for the other side (but it is syntactically
- * legal).
- */
- our_id = resolve_myid(c->spd.this.id);
- if (our_id->get_type(our_id) == ID_ANY)
- {
- our_id_space = identification_create_from_sockaddr((sockaddr_t*)&c->spd.this.host_addr);
- our_id = our_id_space;
- }
-
- switch (next_step)
- {
- case vos_our_client:
- networkof(&b->my.net, &client);
- id = identification_create_from_sockaddr((sockaddr_t*)&client);
- vc->b.failure_ok = b->failure_ok = FALSE;
- ugh = start_adns_query(id
- , our_id
- , T_TXT
- , quick_inI1_outR1_continue
- , &vc->ac);
- break;
-
- case vos_our_txt:
- vc->b.failure_ok = b->failure_ok = TRUE;
- ugh = start_adns_query(our_id
- , our_id /* self as SG */
- , T_TXT
- , quick_inI1_outR1_continue
- , &vc->ac);
- break;
-
-#ifdef USE_KEYRR
- case vos_our_key:
- vc->b.failure_ok = b->failure_ok = FALSE;
- ugh = start_adns_query(our_id
- , NULL
- , T_KEY
- , quick_inI1_outR1_continue
- , &vc->ac);
- break;
-#endif
-
- case vos_his_client:
- networkof(&b->his.net, &client);
- id = identification_create_from_sockaddr((sockaddr_t*)&client);
- vc->b.failure_ok = b->failure_ok = FALSE;
- ugh = start_adns_query(id
- , c->spd.that.id
- , T_TXT
- , quick_inI1_outR1_continue
- , &vc->ac);
- break;
-
- default:
- bad_case(next_step);
- }
-
- if (ugh != NULL)
- {
- /* note: we'd like to use vc->b but vc has been freed
- * so we have to use b. This is why we plunked next_state
- * into b, not just vc->b.
- */
- report_verify_failure(b, ugh);
- p1st->st_suspended_md = NULL;
- return STF_FAIL + ISAKMP_INVALID_ID_INFORMATION;
- }
- else
- {
- return STF_SUSPEND;
- }
-}
-
-static enum verify_oppo_step quick_inI1_outR1_process_answer(
- struct verify_oppo_bundle *b,
- struct adns_continuation *ac,
- struct state *p1st)
-{
- connection_t *c = p1st->st_connection;
- enum verify_oppo_step next_step = vos_our_client;
- err_t ugh = NULL;
-
- DBG(DBG_CONTROL,
- {
- char ours[SUBNETTOT_BUF];
- char his[SUBNETTOT_BUF];
-
- subnettot(&c->spd.this.client, 0, ours, sizeof(ours));
- subnettot(&c->spd.that.client, 0, his, sizeof(his));
- DBG_log("responding on demand from %s to %s state: %s"
- , ours, his, verify_step_name[b->step]);
- });
-
- /* process just completed DNS query (if any) */
- switch (b->step)
- {
- case vos_start:
- /* no query to digest */
- next_step = vos_our_client;
- break;
-
- case vos_our_client:
- next_step = vos_his_client;
- {
- private_key_t *private = get_private_key(c);
- struct gw_info *gwp;
-
- if (private == NULL)
- {
- ugh = "we don't know our own key";
- break;
- }
- ugh = "our client does not delegate us as its Security Gateway";
- for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next)
- {
- ugh = "our client delegates us as its Security Gateway but with the wrong public key";
- /* If there is no key in the TXT record,
- * we count it as a win, but we will have
- * to separately fetch and check the KEY record.
- * If there is a key from the TXT record,
- * we count it as a win if we match the key.
- */
- if (!gwp->gw_key_present)
- {
- next_step = vos_our_txt;
- ugh = NULL; /* good! */
- break;
- }
- else if (private->belongs_to(private, gwp->key->public_key))
- {
- ugh = NULL; /* good! */
- break;
- }
- }
- }
- break;
-
- case vos_our_txt:
- next_step = vos_his_client;
- {
- private_key_t *private = get_private_key(c);
-
- if (private == NULL)
- {
- ugh = "we don't know our own key";
- break;
- }
- {
- struct gw_info *gwp;
-
- for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next)
- {
-#ifdef USE_KEYRR
- /* not an error yet, because we have to check KEY RR as well */
- ugh = NULL;
-#else
- ugh = "our client delegation depends on our " RRNAME " record, but it has the wrong public key";
-#endif
- if (gwp->gw_key_present
- && private->belongs_to(private, gwp->key->public_key))
- {
- ugh = NULL; /* good! */
- break;
- }
-#ifdef USE_KEYRR
- next_step = vos_our_key;
-#endif
- }
- }
- }
- break;
-
-#ifdef USE_KEYRR
- case vos_our_key:
- next_step = vos_his_client;
- {
- private_key_t *private = get_private_key(c);
-
- if (private == NULL)
- {
- ugh = "we don't know our own key";
- break;
- }
- {
- pubkey_list_t *kp;
-
- ugh = "our client delegation depends on our missing " RRNAME " record";
- for (kp = ac->keys_from_dns; kp != NULL; kp = kp->next)
- {
- ugh = "our client delegation depends on our " RRNAME " record, but it has the wrong public key";
- if (private->belongs_to(private, kp->key->public_key))
- {
- /* do this only once a day */
- if (!logged_txt_warning)
- {
- loglog(RC_LOG_SERIOUS, "found KEY RR but not TXT RR. See http://www.freeswan.org/err/txt-change.html.");
- logged_txt_warning = TRUE;
- }
- ugh = NULL; /* good! */
- break;
- }
- }
- }
- }
- break;
-#endif /* USE_KEYRR */
-
- case vos_his_client:
- next_step = vos_done;
- {
- public_key_t *pub_key;
- struct gw_info *gwp;
-
- /* check that the public key that authenticated
- * the ISAKMP SA (p1st) will do for this gateway.
- */
- pub_key = p1st->st_peer_pubkey->public_key;
-
- ugh = "peer's client does not delegate to peer";
- for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next)
- {
- ugh = "peer and its client disagree about public key";
- /* If there is a key from the TXT record,
- * we count it as a win if we match the key.
- * If there was no key, we claim a match since
- * it implies fetching a KEY from the same
- * place we must have gotten it.
- */
- if (!gwp->gw_key_present ||
- pub_key->equals(pub_key, gwp->key->public_key))
- {
- ugh = NULL; /* good! */
- break;
- }
- }
- }
- break;
-
- default:
- bad_case(b->step);
- }
-
- if (ugh != NULL)
- {
- report_verify_failure(b, ugh);
- next_step = vos_fail;
- }
- return next_step;
-}
-
-#endif /* ADNS */
-
-static stf_status quick_inI1_outR1_tail(struct verify_oppo_bundle *b,
- struct adns_continuation *ac)
-{
- struct msg_digest *md = b->md;
- struct state *const p1st = md->st;
- connection_t *c = p1st->st_connection;
- struct payload_digest *const id_pd = md->chain[ISAKMP_NEXT_ID];
- ip_subnet *our_net = &b->my.net
- , *his_net = &b->his.net;
-
- u_char /* set by START_HASH_PAYLOAD: */
- *r_hashval, /* where in reply to jam hash value */
- *r_hash_start; /* from where to start hashing */
-
- /* Now that we have identities of client subnets, we must look for
- * a suitable connection (our current one only matches for hosts).
- */
- {
- connection_t *p = find_client_connection(c
- , our_net, his_net, b->my.proto, b->my.port, b->his.proto, b->his.port);
-
- if (p == NULL)
- {
- /* This message occurs in very puzzling circumstances
- * so we must add as much information and beauty as we can.
- */
- struct end
- me = c->spd.this,
- he = c->spd.that;
- char buf[2*SUBNETTOT_BUF + 2*ADDRTOT_BUF + 2*BUF_LEN + 2*ADDRTOT_BUF + 12]; /* + 12 for separating */
- size_t l;
-
- me.client = *our_net;
- me.has_client = !subnetisaddr(our_net, &me.host_addr);
- me.protocol = b->my.proto;
- me.port = b->my.port;
-
- he.client = *his_net;
- he.has_client = !subnetisaddr(his_net, &he.host_addr);
- he.protocol = b->his.proto;
- he.port = b->his.port;
-
- l = format_end(buf, sizeof(buf), &me, NULL, TRUE, LEMPTY);
- l += snprintf(buf + l, sizeof(buf) - l, "...");
- (void)format_end(buf + l, sizeof(buf) - l, &he, NULL, FALSE, LEMPTY);
- plog("cannot respond to IPsec SA request"
- " because no connection is known for %s"
- , buf);
- return STF_FAIL + ISAKMP_INVALID_ID_INFORMATION;
- }
- else if (p != c)
- {
- /* We've got a better connection: it can support the
- * specified clients. But it may need instantiation.
- */
- if (p->kind == CK_TEMPLATE)
- {
- /* Yup, it needs instantiation. How much?
- * Is it a Road Warrior connection (simple)
- * or is it an Opportunistic connection (needing gw validation)?
- */
- if (p->policy & POLICY_OPPO)
- {
-#ifdef ADNS
- /* Opportunistic case: delegation must be verified.
- * Here be dragons.
- */
- enum verify_oppo_step next_step;
- ip_address our_client, his_client;
-
- passert(subnetishost(our_net) && subnetishost(his_net));
- networkof(our_net, &our_client);
- networkof(his_net, &his_client);
-
- next_step = quick_inI1_outR1_process_answer(b, ac, p1st);
- if (next_step == vos_fail)
- {
- return STF_FAIL + ISAKMP_INVALID_ID_INFORMATION;
- }
-
- /* short circuit: if peer's client is self,
- * accept that we've verified delegation in Phase 1
- */
- if (next_step == vos_his_client
- && sameaddr(&c->spd.that.host_addr, &his_client))
- {
- next_step = vos_done;
- }
-
- /* the second chunk: initiate the next DNS query (if any) */
- DBG(DBG_CONTROL,
- {
- char ours[SUBNETTOT_BUF];
- char his[SUBNETTOT_BUF];
-
- subnettot(&c->spd.this.client, 0, ours, sizeof(ours));
- subnettot(&c->spd.that.client, 0, his, sizeof(his));
-
- DBG_log("responding on demand from %s to %s new state: %s"
- , ours, his, verify_step_name[next_step]);
- });
-
- /* start next DNS query and suspend (if necessary) */
- if (next_step != vos_done)
- {
- return quick_inI1_outR1_start_query(b, next_step);
- }
-
- /* Instantiate inbound Opportunistic connection,
- * carrying over authenticated peer ID
- * and filling in a few more details.
- * We used to include gateways_from_dns, but that
- * seems pointless at this stage of negotiation.
- * We should record DNS sec use, if any -- belongs in
- * state during perhaps.
- */
- p = oppo_instantiate(p, &c->spd.that.host_addr, c->spd.that.id
- , NULL, &our_client, &his_client);
-#else /* ADNS */
- plog("opportunistic connections not supported because"
- " adns is not available");
- return STF_INTERNAL_ERROR;
-#endif /* ADNS */
- }
- else
- {
- /* Plain Road Warrior:
- * instantiate, carrying over authenticated peer ID
- */
- host_t *vip = c->spd.that.host_srcip;
-
- p = rw_instantiate(p, &c->spd.that.host_addr, md->sender_port
- , his_net, c->spd.that.id);
-
- /* inherit any virtual IP assigned by a Mode Config exchange */
- if (p->spd.that.modecfg && c->spd.that.modecfg &&
- subnetisaddr(his_net, (ip_address*)vip->get_sockaddr(vip)))
- {
- DBG(DBG_CONTROL,
- DBG_log("inheriting virtual IP source address %H from ModeCfg", vip)
- )
- p->spd.that.host_srcip->destroy(p->spd.that.host_srcip);
- p->spd.that.host_srcip = vip->clone(vip);
- p->spd.that.client = c->spd.that.client;
- p->spd.that.has_client = TRUE;
- }
-
- if (c->policy & (POLICY_XAUTH_RSASIG | POLICY_XAUTH_PSK) &&
- c->xauth_identity && !p->xauth_identity)
- {
- DBG(DBG_CONTROL,
- DBG_log("inheriting XAUTH identity %Y", c->xauth_identity)
- )
- p->xauth_identity = c->xauth_identity->clone(c->xauth_identity);
- }
- }
- }
-#ifdef DEBUG
- /* temporarily bump up cur_debugging to get "using..." message
- * printed if we'd want it with new connection.
- */
- {
- lset_t old_cur_debugging = cur_debugging;
-
- cur_debugging |= p->extra_debugging;
- DBG(DBG_CONTROL, DBG_log("using connection \"%s\"", p->name));
- cur_debugging = old_cur_debugging;
- }
-#endif
- c = p;
- }
- /* fill in the client's true ip address/subnet */
- if (p->spd.that.has_client_wildcard)
- {
- p->spd.that.client = *his_net;
- p->spd.that.has_client_wildcard = FALSE;
- }
- else if (is_virtual_connection(c))
- {
- c->spd.that.client = *his_net;
- c->spd.that.virt = NULL;
- if (subnetishost(his_net) && addrinsubnet(&c->spd.that.host_addr, his_net))
- {
- c->spd.that.has_client = FALSE;
- }
- }
-
- /* fill in the client's true port */
- if (p->spd.that.has_port_wildcard)
- {
- int port = htons(b->his.port);
-
- setportof(port, &p->spd.that.host_addr);
- setportof(port, &p->spd.that.client.addr);
-
- p->spd.that.port = b->his.port;
- p->spd.that.has_port_wildcard = FALSE;
- }
- }
-
- /* now that we are sure of our connection, create our new state */
- {
- enum endpoint ep = EP_LOCAL;
- struct state *const st = duplicate_state(p1st);
-
- /* first: fill in missing bits of our new state object
- * note: we don't copy over st_peer_pubkey, the public key
- * that authenticated the ISAKMP SA. We only need it in this
- * routine, so we can "reach back" to p1st to get it.
- */
-
- if (st->st_connection != c)
- {
- connection_t *t = st->st_connection;
-
- st->st_connection = c;
- set_cur_connection(c);
- connection_discard(t);
- }
-
- st->st_try = 0; /* not our job to try again from start */
-
- st->st_msgid = md->hdr.isa_msgid;
-
- st->st_new_iv_len = b->new_iv_len;
- memcpy(st->st_new_iv, b->new_iv, b->new_iv_len);
-
- set_cur_state(st); /* (caller will reset) */
- md->st = st; /* feed back new state */
-
- st->st_peeruserprotoid = b->his.proto;
- st->st_peeruserport = b->his.port;
- st->st_myuserprotoid = b->my.proto;
- st->st_myuserport = b->my.port;
-
- insert_state(st); /* needs cookies, connection, and msgid */
-
- /* copy the connection's
- * IPSEC policy into our state. The ISAKMP policy is water under
- * the bridge, I think. It will reflect the ISAKMP SA that we
- * are using.
- */
- st->st_policy = (p1st->st_policy & POLICY_ISAKMP_MASK)
- | (c->policy & ~POLICY_ISAKMP_MASK);
-
- if (p1st->nat_traversal & NAT_T_DETECTED)
- {
- st->nat_traversal = p1st->nat_traversal;
- nat_traversal_change_port_lookup(md, md->st);
- }
- else
- {
- st->nat_traversal = 0;
- }
- if ((st->nat_traversal & NAT_T_DETECTED)
- && (st->nat_traversal & NAT_T_WITH_NATOA))
- {
- nat_traversal_natoa_lookup(md);
- }
-
- /* Start the output packet.
- *
- * proccess_packet() would automatically generate the HDR*
- * payload if smc->first_out_payload is not ISAKMP_NEXT_NONE.
- * We don't do this because we wish there to be no partially
- * built output packet if we need to suspend for asynch DNS.
- *
- * We build the reply packet as we parse the message since
- * the parse_ipsec_sa_body emits the reply SA
- */
-
- /* HDR* out */
- echo_hdr(md, TRUE, ISAKMP_NEXT_HASH);
-
- /* HASH(2) out -- first pass */
- START_HASH_PAYLOAD(md->rbody, ISAKMP_NEXT_SA);
-
- /* process SA (in and out) */
- {
- struct payload_digest *const sapd = md->chain[ISAKMP_NEXT_SA];
- pb_stream r_sa_pbs;
- struct isakmp_sa sa = sapd->payload.sa;
-
- /* sa header is unchanged -- except for np */
- sa.isasa_np = ISAKMP_NEXT_NONCE;
- if (!out_struct(&sa, &isakmp_sa_desc, &md->rbody, &r_sa_pbs))
- {
- return STF_INTERNAL_ERROR;
- }
-
- /* parse and accept body */
- st->st_pfs_group = &unset_group;
- RETURN_STF_FAILURE(parse_ipsec_sa_body(&sapd->pbs
- , &sapd->payload.sa, &r_sa_pbs, FALSE, st));
- }
-
- passert(st->st_pfs_group != &unset_group);
-
- if ((st->st_policy & POLICY_PFS) && st->st_pfs_group == NULL)
- {
- loglog(RC_LOG_SERIOUS, "we require PFS but Quick I1 SA specifies no GROUP_DESCRIPTION");
- return STF_FAIL + ISAKMP_NO_PROPOSAL_CHOSEN;
- }
-
- /* Ni in */
- RETURN_STF_FAILURE(accept_nonce(md, &st->st_ni, "Ni"));
-
- /* [ KE ] in (for PFS) */
- RETURN_STF_FAILURE(accept_PFS_KE(md, &st->st_gi, "Gi", "Quick Mode I1"));
-
- plog("responding to Quick Mode");
-
- /**** finish reply packet: Nr [, KE ] [, IDci, IDcr ] ****/
-
- /* Nr out */
- if (!build_and_ship_nonce(&st->st_nr, &md->rbody
- , st->st_pfs_group != NULL? ISAKMP_NEXT_KE : id_pd != NULL? ISAKMP_NEXT_ID : ISAKMP_NEXT_NONE
- , "Nr"))
- {
- return STF_INTERNAL_ERROR;
- }
-
- /* [ KE ] out (for PFS) */
-
- if (st->st_pfs_group != NULL)
- {
- if (!build_and_ship_KE(st, &st->st_gr, st->st_pfs_group
- , &md->rbody, id_pd != NULL? ISAKMP_NEXT_ID : ISAKMP_NEXT_NONE))
- {
- return STF_INTERNAL_ERROR;
- }
-
- /* MPZ-Operations might be done after sending the packet... */
- compute_dh_shared(st, st->st_gi);
- }
-
- /* [ IDci, IDcr ] out */
- if (id_pd != NULL)
- {
- struct isakmp_ipsec_id *p = (void *)md->rbody.cur; /* UGH! */
-
- if (!out_raw(id_pd->pbs.start, pbs_room(&id_pd->pbs), &md->rbody, "IDci"))
- {
- return STF_INTERNAL_ERROR;
- }
- p->isaiid_np = ISAKMP_NEXT_ID;
-
- p = (void *)md->rbody.cur; /* UGH! */
-
- if (!out_raw(id_pd->next->pbs.start, pbs_room(&id_pd->next->pbs), &md->rbody, "IDcr"))
- {
- return STF_INTERNAL_ERROR;
- }
- p->isaiid_np = ISAKMP_NEXT_NONE;
- }
-
- if ((st->nat_traversal & NAT_T_WITH_NATOA)
- && (st->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_ME))
- && (st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TRANSPORT))
- {
- /** Send NAT-OA if our address is NATed and if we use Transport Mode */
- if (!nat_traversal_add_natoa(ISAKMP_NEXT_NONE, &md->rbody, md->st))
- {
- return STF_INTERNAL_ERROR;
- }
- }
- if ((st->nat_traversal & NAT_T_DETECTED)
- && (st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TRANSPORT)
- && (c->spd.that.has_client))
- {
- /** Remove client **/
- addrtosubnet(&c->spd.that.host_addr, &c->spd.that.client);
- c->spd.that.has_client = FALSE;
- }
-
- /* Compute reply HASH(2) and insert in output */
- (void)quick_mode_hash12(r_hashval, r_hash_start, md->rbody.cur
- , st, &st->st_msgid, TRUE);
-
- /* Derive new keying material */
- compute_keymats(st, ep);
-
- /* Tell the kernel to establish the new inbound SA
- * (unless the commit bit is set -- which we don't support).
- * We do this before any state updating so that
- * failure won't look like success.
- */
- if (!install_inbound_ipsec_sa(st))
- {
- wipe_keymats(st, ep);
- return STF_INTERNAL_ERROR; /* ??? we may be partly committed */
- }
- wipe_keymats(st, ep);
-
- /* encrypt message, except for fixed part of header */
-
- if (!encrypt_message(&md->rbody, st))
- {
- return STF_INTERNAL_ERROR; /* ??? we may be partly committed */
- }
-
- return STF_OK;
- }
-}
-
-/*
- * Initialize RFC 3706 Dead Peer Detection
- */
-static void dpd_init(struct state *st)
-{
- struct state *p1st = find_state(st->st_icookie, st->st_rcookie
- , &st->st_connection->spd.that.host_addr, 0);
-
- if (p1st == NULL)
- {
- loglog(RC_LOG_SERIOUS, "could not find phase 1 state for DPD");
- }
- else if (p1st->st_dpd)
- {
- plog("Dead Peer Detection (RFC 3706) enabled");
- /* randomize the first DPD event */
-
- event_schedule(EVENT_DPD
- , (0.5 + rand()/(RAND_MAX + 1.E0)) * st->st_connection->dpd_delay
- , st);
- }
-}
-
-/* Handle (the single) message from Responder in Quick Mode.
- * HDR*, HASH(2), SA, Nr [, KE ] [, IDci, IDcr ] -->
- * HDR*, HASH(3)
- * (see RFC 2409 "IKE" 5.5)
- * Installs inbound and outbound IPsec SAs, routing, etc.
- */
-stf_status quick_inR1_outI2(struct msg_digest *md)
-{
- enum endpoint ep = EP_LOCAL | EP_REMOTE;
- struct state *const st = md->st;
- const connection_t *c = st->st_connection;
-
- /* HASH(2) in */
- CHECK_QUICK_HASH(md
- , quick_mode_hash12(hash_val, hash_pbs->roof, md->message_pbs.roof
- , st, &st->st_msgid, TRUE)
- , "HASH(2)", "Quick R1");
-
- /* SA in */
- {
- struct payload_digest *const sa_pd = md->chain[ISAKMP_NEXT_SA];
-
- RETURN_STF_FAILURE(parse_ipsec_sa_body(&sa_pd->pbs
- , &sa_pd->payload.sa, NULL, TRUE, st));
- }
-
- /* Nr in */
- RETURN_STF_FAILURE(accept_nonce(md, &st->st_nr, "Nr"));
-
- /* [ KE ] in (for PFS) */
- RETURN_STF_FAILURE(accept_PFS_KE(md, &st->st_gr, "Gr", "Quick Mode R1"));
-
- if (st->st_pfs_group != NULL)
- {
- compute_dh_shared(st, st->st_gr);
- }
-
- /* [ IDci, IDcr ] in; these must match what we sent */
-
- {
- struct payload_digest *const id_pd = md->chain[ISAKMP_NEXT_ID];
-
- if (id_pd != NULL)
- {
- /* ??? we are assuming IPSEC_DOI */
-
- /* IDci (we are initiator) */
-
- if (!check_net_id(&id_pd->payload.ipsec_id, &id_pd->pbs
- , &st->st_myuserprotoid, &st->st_myuserport
- , &st->st_connection->spd.this.client
- , "our client"))
- {
- return STF_FAIL + ISAKMP_INVALID_ID_INFORMATION;
- }
-
- /* IDcr (responder is peer) */
-
- if (!check_net_id(&id_pd->next->payload.ipsec_id, &id_pd->next->pbs
- , &st->st_peeruserprotoid, &st->st_peeruserport
- , &st->st_connection->spd.that.client
- , "peer client"))
- {
- return STF_FAIL + ISAKMP_INVALID_ID_INFORMATION;
- }
- }
- else
- {
- /* no IDci, IDcr: we must check that the defaults match our proposal */
- if (!subnetisaddr(&c->spd.this.client, &c->spd.this.host_addr)
- || !subnetisaddr(&c->spd.that.client, &c->spd.that.host_addr))
- {
- loglog(RC_LOG_SERIOUS, "IDci, IDcr payloads missing in message"
- " but default does not match proposal");
- return STF_FAIL + ISAKMP_INVALID_ID_INFORMATION;
- }
- }
- }
-
- /* check the peer's group attributes */
- {
- identification_t *peer_ca = NULL;
- ietf_attributes_t *peer_attributes = NULL;
- bool match;
-
- get_peer_ca_and_groups(st->st_connection, &peer_ca, &peer_attributes);
- match = match_group_membership(peer_attributes,
- st->st_connection->name,
- st->st_connection->spd.that.groups);
- DESTROY_IF(peer_attributes);
-
- if (!match)
- {
- ietf_attributes_t *groups = st->st_connection->spd.that.groups;
-
- loglog(RC_LOG_SERIOUS,
- "peer with attributes '%s' is not a member of the groups '%s'",
- peer_attributes->get_string(peer_attributes),
- groups->get_string(groups));
- return STF_FAIL + ISAKMP_INVALID_ID_INFORMATION;
- }
- }
-
- if ((st->nat_traversal & NAT_T_DETECTED)
- && (st->nat_traversal & NAT_T_WITH_NATOA))
- {
- nat_traversal_natoa_lookup(md);
- }
-
- /* ??? We used to copy the accepted proposal into the state, but it was
- * never used. From sa_pd->pbs.start, length pbs_room(&sa_pd->pbs).
- */
-
- /**************** build reply packet HDR*, HASH(3) ****************/
-
- /* HDR* out done */
-
- /* HASH(3) out -- since this is the only content, no passes needed */
- {
- u_char /* set by START_HASH_PAYLOAD: */
- *r_hashval, /* where in reply to jam hash value */
- *r_hash_start; /* start of what is to be hashed */
-
- START_HASH_PAYLOAD(md->rbody, ISAKMP_NEXT_NONE);
- (void)quick_mode_hash3(r_hashval, st);
- }
-
- /* Derive new keying material */
- compute_keymats(st, ep);
-
- /* Tell the kernel to establish the inbound, outbound, and routing part
- * of the new SA (unless the commit bit is set -- which we don't support).
- * We do this before any state updating so that
- * failure won't look like success.
- */
- if (!install_ipsec_sa(st, TRUE))
- {
- wipe_keymats(st, ep);
- return STF_INTERNAL_ERROR;
- }
- wipe_keymats(st, ep);
-
- /* encrypt message, except for fixed part of header */
-
- if (!encrypt_message(&md->rbody, st))
- {
- return STF_INTERNAL_ERROR; /* ??? we may be partly committed */
- }
- DBG(DBG_CONTROLMORE,
- DBG_log("inR1_outI2: instance %s[%ld], setting newest_ipsec_sa to #%ld (was #%ld) (spd.eroute=#%ld)"
- , st->st_connection->name
- , st->st_connection->instance_serial
- , st->st_serialno
- , st->st_connection->newest_ipsec_sa
- , st->st_connection->spd.eroute_owner)
- )
- st->st_connection->newest_ipsec_sa = st->st_serialno;
-
- /* note (presumed) success */
- if (c->gw_info != NULL)
- {
- c->gw_info->key->last_worked_time = now();
- }
-
- /* If we want DPD on this connection then initialize it */
- if (st->st_connection->dpd_action != DPD_ACTION_NONE)
- {
- dpd_init(st);
- }
- return STF_OK;
-}
-
-/* Handle last message of Quick Mode.
- * HDR*, HASH(3) -> done
- * (see RFC 2409 "IKE" 5.5)
- * Installs outbound IPsec SAs, routing, etc.
- */
-stf_status quick_inI2(struct msg_digest *md)
-{
- enum endpoint ep = EP_REMOTE;
- struct state *const st = md->st;
-
- /* HASH(3) in */
- CHECK_QUICK_HASH(md, quick_mode_hash3(hash_val, st)
- , "HASH(3)", "Quick I2");
-
- /* Derive keying material */
- compute_keymats(st, ep);
-
- /* Tell the kernel to establish the outbound and routing part of the new SA
- * (the previous state established inbound)
- * (unless the commit bit is set -- which we don't support).
- * We do this before any state updating so that
- * failure won't look like success.
- */
- if (!install_ipsec_sa(st, FALSE))
- {
- wipe_keymats(st, ep);
- return STF_INTERNAL_ERROR;
- }
- wipe_keymats(st, ep);
-
- DBG(DBG_CONTROLMORE,
- DBG_log("inI2: instance %s[%ld], setting newest_ipsec_sa to #%ld (was #%ld) (spd.eroute=#%ld)"
- , st->st_connection->name
- , st->st_connection->instance_serial
- , st->st_serialno
- , st->st_connection->newest_ipsec_sa
- , st->st_connection->spd.eroute_owner)
- )
- st->st_connection->newest_ipsec_sa = st->st_serialno;
-
- update_iv(st); /* not actually used, but tidy */
-
- /* note (presumed) success */
- {
- struct gw_info *gw = st->st_connection->gw_info;
-
- if (gw != NULL)
- {
- gw->key->last_worked_time = now();
- }
- }
-
- /* If we want DPD on this connection then initialize it */
- if (st->st_connection->dpd_action != DPD_ACTION_NONE)
- {
- dpd_init(st);
- }
- return STF_OK;
-}
-
-static stf_status send_isakmp_notification(struct state *st, u_int16_t type,
- const void *data, size_t len)
-{
- msgid_t msgid;
- pb_stream reply;
- pb_stream rbody;
- u_char
- *r_hashval, /* where in reply to jam hash value */
- *r_hash_start; /* start of what is to be hashed */
-
- msgid = generate_msgid(st);
-
- init_pbs(&reply, reply_buffer, sizeof(reply_buffer), "ISAKMP notify");
-
- /* HDR* */
- {
- struct isakmp_hdr hdr;
-
- hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION;
- hdr.isa_np = ISAKMP_NEXT_HASH;
- hdr.isa_xchg = ISAKMP_XCHG_INFO;
- hdr.isa_msgid = msgid;
- hdr.isa_flags = ISAKMP_FLAG_ENCRYPTION;
- memcpy(hdr.isa_icookie, st->st_icookie, COOKIE_SIZE);
- memcpy(hdr.isa_rcookie, st->st_rcookie, COOKIE_SIZE);
- if (!out_struct(&hdr, &isakmp_hdr_desc, &reply, &rbody))
- {
- impossible();
- }
- }
- /* HASH -- create and note space to be filled later */
- START_HASH_PAYLOAD(rbody, ISAKMP_NEXT_N);
-
- /* NOTIFY */
- {
- pb_stream notify_pbs;
- struct isakmp_notification isan;
-
- isan.isan_np = ISAKMP_NEXT_NONE;
- isan.isan_doi = ISAKMP_DOI_IPSEC;
- isan.isan_protoid = PROTO_ISAKMP;
- isan.isan_spisize = COOKIE_SIZE * 2;
- isan.isan_type = type;
- if (!out_struct(&isan, &isakmp_notification_desc, &rbody, &notify_pbs))
- {
- return STF_INTERNAL_ERROR;
- }
- if (!out_raw(st->st_icookie, COOKIE_SIZE, &notify_pbs, "notify icookie"))
- {
- return STF_INTERNAL_ERROR;
- }
- if (!out_raw(st->st_rcookie, COOKIE_SIZE, &notify_pbs, "notify rcookie"))
- {
- return STF_INTERNAL_ERROR;
- }
- if (data != NULL && len > 0)
- {
- if (!out_raw(data, len, &notify_pbs, "notify data"))
- {
- return STF_INTERNAL_ERROR;
- }
- }
- close_output_pbs(&notify_pbs);
- }
-
- {
- /* finish computing HASH */
- chunk_t msgid_chunk = chunk_from_thing(msgid);
- chunk_t msg_chunk = { r_hash_start, rbody.cur-r_hash_start };
- pseudo_random_function_t prf_alg;
- prf_t *prf;
-
- prf_alg = oakley_to_prf(st->st_oakley.hash);
- prf = lib->crypto->create_prf(lib->crypto, prf_alg);
- prf->set_key(prf, st->st_skeyid_a);
- prf->get_bytes(prf, msgid_chunk, NULL);
- prf->get_bytes(prf, msg_chunk, r_hashval);
-
- DBG(DBG_CRYPT,
- DBG_log("HASH computed:");
- DBG_dump("", r_hashval, prf->get_block_size(prf));
- )
- prf->destroy(prf);
- }
-
- /* Encrypt message (preserve st_iv and st_new_iv) */
- {
- u_char old_iv[MAX_DIGEST_LEN];
- u_char new_iv[MAX_DIGEST_LEN];
-
- u_int old_iv_len = st->st_iv_len;
- u_int new_iv_len = st->st_new_iv_len;
-
- if (old_iv_len > MAX_DIGEST_LEN || new_iv_len > MAX_DIGEST_LEN)
- return STF_INTERNAL_ERROR;
-
- memcpy(old_iv, st->st_iv, old_iv_len);
- memcpy(new_iv, st->st_new_iv, new_iv_len);
-
- init_phase2_iv(st, &msgid);
- if (!encrypt_message(&rbody, st))
- {
- return STF_INTERNAL_ERROR;
- }
-
- /* restore preserved st_iv and st_new_iv */
- memcpy(st->st_iv, old_iv, old_iv_len);
- memcpy(st->st_new_iv, new_iv, new_iv_len);
- st->st_iv_len = old_iv_len;
- st->st_new_iv_len = new_iv_len;
- }
-
- /* Send packet (preserve st_tpacket) */
- {
- chunk_t saved_tpacket = st->st_tpacket;
-
- st->st_tpacket = chunk_create(reply.start, pbs_offset(&reply));
- send_packet(st, "ISAKMP notify");
- st->st_tpacket = saved_tpacket;
- }
-
- return STF_IGNORE;
-}
-
-/*
- * DPD Out Initiator
- */
-void dpd_outI(struct state *p2st)
-{
- struct state *st;
- u_int32_t seqno;
- time_t tm;
- time_t idle_time;
- time_t delay = p2st->st_connection->dpd_delay;
- time_t timeout = p2st->st_connection->dpd_timeout;
-
- /* find the newest related Phase 1 state */
- st = find_phase1_state(p2st->st_connection, ISAKMP_SA_ESTABLISHED_STATES);
-
- if (st == NULL)
- {
- loglog(RC_LOG_SERIOUS, "DPD: Could not find newest phase 1 state");
- return;
- }
-
- /* If no DPD, then get out of here */
- if (!st->st_dpd)
- {
- return;
- }
-
- /* schedule the next periodic DPD event */
- event_schedule(EVENT_DPD, delay, p2st);
-
- /* Current time */
- tm = now();
-
- /* Make sure we really need to invoke DPD */
- if (!was_eroute_idle(p2st, delay, &idle_time))
- {
- DBG(DBG_CONTROL,
- DBG_log("recent eroute activity %u seconds ago, "
- "no need to send DPD notification"
- , (int)idle_time)
- )
- st->st_last_dpd = tm;
- delete_dpd_event(st);
- return;
- }
-
- /* If an R_U_THERE has been sent or received recently, or if a
- * companion Phase 2 SA has shown eroute activity,
- * then we don't need to invoke DPD.
- */
- if (tm < st->st_last_dpd + delay)
- {
- DBG(DBG_CONTROL,
- DBG_log("recent DPD activity %u seconds ago, "
- "no need to send DPD notification"
- , (int)(tm - st->st_last_dpd))
- )
- return;
- }
-
- if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state))
- return;
-
- if (!st->st_dpd_seqno)
- {
- rng_t *rng;
-
- /* Get a non-zero random value that has room to grow */
- rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
- rng->get_bytes(rng, sizeof(st->st_dpd_seqno), (u_char *)&st->st_dpd_seqno);
- rng->destroy(rng);
- st->st_dpd_seqno &= 0x7fff;
- st->st_dpd_seqno++;
- }
- seqno = htonl(st->st_dpd_seqno);
-
- if (send_isakmp_notification(st, R_U_THERE, &seqno, sizeof(seqno)) != STF_IGNORE)
- {
- loglog(RC_LOG_SERIOUS, "DPD: Could not send R_U_THERE");
- return;
- }
- DBG(DBG_CONTROL,
- DBG_log("sent DPD notification R_U_THERE with seqno = %u", st->st_dpd_seqno)
- )
- st->st_dpd_expectseqno = st->st_dpd_seqno++;
- st->st_last_dpd = tm;
- /* Only schedule a new timeout if there isn't one currently,
- * or if it would be sooner than the current timeout. */
- if (st->st_dpd_event == NULL
- || st->st_dpd_event->ev_time > tm + timeout)
- {
- delete_dpd_event(st);
- event_schedule(EVENT_DPD_TIMEOUT, timeout, st);
- }
-}
-
-/*
- * DPD in Initiator, out Responder
- */
-stf_status
-dpd_inI_outR(struct state *st, struct isakmp_notification *const n, pb_stream *pbs)
-{
- time_t tm = now();
- u_int32_t seqno;
-
- if (st == NULL || !IS_ISAKMP_SA_ESTABLISHED(st->st_state))
- {
- loglog(RC_LOG_SERIOUS, "DPD: Received R_U_THERE for unestablished ISAKMP SA");
- return STF_IGNORE;
- }
- if (n->isan_spisize != COOKIE_SIZE * 2 || pbs_left(pbs) < COOKIE_SIZE * 2)
- {
- loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE has invalid SPI length (%d)", n->isan_spisize);
- return STF_FAIL + ISAKMP_PAYLOAD_MALFORMED;
- }
-
- if (memcmp(pbs->cur, st->st_icookie, COOKIE_SIZE) != 0)
- {
-#ifdef APPLY_CRISCO
- /* Ignore it, cisco sends odd icookies */
-#else
- loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE has invalid icookie (broken Cisco?)");
- return STF_FAIL + ISAKMP_INVALID_COOKIE;
-#endif
- }
- pbs->cur += COOKIE_SIZE;
-
- if (memcmp(pbs->cur, st->st_rcookie, COOKIE_SIZE) != 0)
- {
- loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE has invalid rcookie (broken Cisco?)");
- return STF_FAIL + ISAKMP_INVALID_COOKIE;
- }
- pbs->cur += COOKIE_SIZE;
-
- if (pbs_left(pbs) != sizeof(seqno))
- {
- loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE has invalid data length (%d)"
- , (int) pbs_left(pbs));
- return STF_FAIL + ISAKMP_PAYLOAD_MALFORMED;
- }
-
- seqno = ntohl(*(u_int32_t *)pbs->cur);
- DBG(DBG_CONTROL,
- DBG_log("received DPD notification R_U_THERE with seqno = %u", seqno)
- )
-
- if (st->st_dpd_peerseqno && seqno <= st->st_dpd_peerseqno) {
- loglog(RC_LOG_SERIOUS, "DPD: Received old or duplicate R_U_THERE");
- return STF_IGNORE;
- }
-
- st->st_dpd_peerseqno = seqno;
- delete_dpd_event(st);
-
- if (send_isakmp_notification(st, R_U_THERE_ACK, pbs->cur, pbs_left(pbs)) != STF_IGNORE)
- {
- loglog(RC_LOG_SERIOUS, "DPD Info: could not send R_U_THERE_ACK");
- return STF_IGNORE;
- }
- DBG(DBG_CONTROL,
- DBG_log("sent DPD notification R_U_THERE_ACK with seqno = %u", seqno)
- )
-
- st->st_last_dpd = tm;
- return STF_IGNORE;
-}
-
-/*
- * DPD out Responder
- */
-stf_status dpd_inR(struct state *st, struct isakmp_notification *const n,
- pb_stream *pbs)
-{
- u_int32_t seqno;
-
- if (st == NULL || !IS_ISAKMP_SA_ESTABLISHED(st->st_state))
- {
- loglog(RC_LOG_SERIOUS
- , "DPD: Received R_U_THERE_ACK for unestablished ISAKMP SA");
- return STF_FAIL;
- }
-
- if (n->isan_spisize != COOKIE_SIZE * 2 || pbs_left(pbs) < COOKIE_SIZE * 2)
- {
- loglog(RC_LOG_SERIOUS
- , "DPD: R_U_THERE_ACK has invalid SPI length (%d)"
- , n->isan_spisize);
- return STF_FAIL + ISAKMP_PAYLOAD_MALFORMED;
- }
-
- if (memcmp(pbs->cur, st->st_icookie, COOKIE_SIZE) != 0)
- {
-#ifdef APPLY_CRISCO
- /* Ignore it, cisco sends odd icookies */
-#else
- loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE_ACK has invalid icookie");
- return STF_FAIL + ISAKMP_INVALID_COOKIE;
-#endif
- }
- pbs->cur += COOKIE_SIZE;
-
- if (memcmp(pbs->cur, st->st_rcookie, COOKIE_SIZE) != 0)
- {
-#ifdef APPLY_CRISCO
- /* Ignore it, cisco sends odd icookies */
-#else
- loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE_ACK has invalid rcookie");
- return STF_FAIL + ISAKMP_INVALID_COOKIE;
-#endif
- }
- pbs->cur += COOKIE_SIZE;
-
- if (pbs_left(pbs) != sizeof(seqno))
- {
- loglog(RC_LOG_SERIOUS
- , " DPD: R_U_THERE_ACK has invalid data length (%d)"
- , (int) pbs_left(pbs));
- return STF_FAIL + ISAKMP_PAYLOAD_MALFORMED;
- }
-
- seqno = ntohl(*(u_int32_t *)pbs->cur);
- DBG(DBG_CONTROL,
- DBG_log("received DPD notification R_U_THERE_ACK with seqno = %u"
- , seqno)
- )
-
- if (!st->st_dpd_expectseqno && seqno != st->st_dpd_expectseqno)
- {
- loglog(RC_LOG_SERIOUS
- , "DPD: R_U_THERE_ACK has unexpected sequence number %u (expected %u)"
- , seqno, st->st_dpd_expectseqno);
- return STF_FAIL + ISAKMP_PAYLOAD_MALFORMED;
- }
-
- st->st_dpd_expectseqno = 0;
- delete_dpd_event(st);
- return STF_IGNORE;
-}
-
-/*
- * DPD Timeout Function
- *
- * This function is called when a timeout DPD_EVENT occurs. We set clear/trap
- * both the SA and the eroutes, depending on what the connection definition
- * tells us (either 'hold' or 'clear')
- */
-void
-dpd_timeout(struct state *st)
-{
- struct state *newest_phase1_st;
- connection_t *c = st->st_connection;
- int action = st->st_connection->dpd_action;
- char cname[BUF_LEN];
-
- passert(action == DPD_ACTION_HOLD
- || action == DPD_ACTION_CLEAR
- || DPD_ACTION_RESTART);
-
- /* is there a newer phase1_state? */
- newest_phase1_st = find_phase1_state(c, ISAKMP_SA_ESTABLISHED_STATES);
- if (newest_phase1_st != NULL && newest_phase1_st != st)
- {
- plog("DPD: Phase1 state #%ld has been superseded by #%ld"
- " - timeout ignored"
- , st->st_serialno, newest_phase1_st->st_serialno);
- return;
- }
-
- loglog(RC_LOG_SERIOUS, "DPD: No response from peer - declaring peer dead");
-
- /* delete the state, which is probably in phase 2 */
- set_cur_connection(c);
- plog("DPD: Terminating all SAs using this connection");
- delete_states_by_connection(c, TRUE);
- reset_cur_connection();
-
- switch (action)
- {
- case DPD_ACTION_HOLD:
- /* dpdaction=hold - Wipe the SA's but %trap the eroute so we don't
- * leak traffic. Also, being in %trap means new packets will
- * force an initiation of the conn again.
- */
- loglog(RC_LOG_SERIOUS, "DPD: Putting connection \"%s\" into %%trap", c->name);
- if (c->kind == CK_INSTANCE)
- {
- delete_connection(c, TRUE);
- }
- break;
- case DPD_ACTION_CLEAR:
- /* dpdaction=clear - Wipe the SA & eroute - everything */
- loglog(RC_LOG_SERIOUS, "DPD: Clearing connection \"%s\"", c->name);
- unroute_connection(c);
- if (c->kind == CK_INSTANCE)
- {
- delete_connection(c, TRUE);
- }
- break;
- case DPD_ACTION_RESTART:
- /* dpdaction=restart - Restart connection,
- * except if roadwarrior connection
- */
- loglog(RC_LOG_SERIOUS, "DPD: Restarting connection \"%s\"", c->name);
- unroute_connection(c);
-
- /* caching the connection name before deletion */
- strncpy(cname, c->name, BUF_LEN);
- cname[BUF_LEN-1] = '\0';
-
- if (c->kind == CK_INSTANCE)
- {
- delete_connection(c, TRUE);
- }
- initiate_connection(cname, NULL_FD);
- break;
- default:
- loglog(RC_LOG_SERIOUS, "DPD: unknown action");
- }
-}
-
diff --git a/src/pluto/ipsec_doi.h b/src/pluto/ipsec_doi.h
deleted file mode 100644
index c11edaa94..000000000
--- a/src/pluto/ipsec_doi.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/* IPsec DOI and Oakley resolution routines
- * Copyright (C) 1998-2002 D. Hugh Redelmeier.
- *
- * 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.
- */
-
-#ifndef _IPSEC_DOI_H
-#define _IPSEC_DOI_H
-
-#include "defs.h"
-
-extern void echo_hdr(struct msg_digest *md, bool enc, u_int8_t np);
-
-extern void ipsecdoi_initiate(int whack_sock, struct connection *c
- , lset_t policy, unsigned long try, so_serial_t replacing);
-
-extern void ipsecdoi_replace(struct state *st, unsigned long try);
-
-extern void init_phase2_iv(struct state *st, const msgid_t *msgid);
-
-extern stf_status quick_outI1(int whack_sock
- , struct state *isakmp_sa
- , struct connection *c
- , lset_t policy
- , unsigned long try
- , so_serial_t replacing);
-
-extern state_transition_fn
- main_inI1_outR1,
- main_inR1_outI2,
- main_inI2_outR2,
- main_inR2_outI3,
- main_inI3_outR3,
- main_inR3,
- quick_inI1_outR1,
- quick_inR1_outI2,
- quick_inI2;
-
-extern void send_delete(struct state *st);
-extern void accept_delete(struct state *st, struct msg_digest *md
- , struct payload_digest *p);
-extern void close_message(pb_stream *pbs);
-extern bool encrypt_message(pb_stream *pbs, struct state *st);
-
-
-extern void send_notification_from_state(struct state *st,
- enum state_kind state, u_int16_t type);
-extern void send_notification_from_md(struct msg_digest *md, u_int16_t type);
-
-extern const char *init_pluto_vendorid(void);
-
-extern void dpd_outI(struct state *st);
-extern stf_status dpd_inI_outR(struct state *st
- , struct isakmp_notification *const n, pb_stream *n_pbs);
-extern stf_status dpd_inR(struct state *st
- , struct isakmp_notification *const n, pb_stream *n_pbs);
-extern void dpd_timeout(struct state *st);
-
-/* START_HASH_PAYLOAD
- *
- * Emit a to-be-filled-in hash payload, noting the field start (r_hashval)
- * and the start of the part of the message to be hashed (r_hash_start).
- * This macro is magic.
- * - it can cause the caller to return
- * - it references variables local to the caller (r_hashval, r_hash_start, st)
- */
-#define START_HASH_PAYLOAD(rbody, np) { \
- pb_stream hash_pbs; \
- if (!out_generic(np, &isakmp_hash_desc, &(rbody), &hash_pbs)) \
- return STF_INTERNAL_ERROR; \
- r_hashval = hash_pbs.cur; /* remember where to plant value */ \
- if (!out_zero(st->st_oakley.hasher->hash_digest_size, &hash_pbs, "HASH")) \
- return STF_INTERNAL_ERROR; \
- close_output_pbs(&hash_pbs); \
- r_hash_start = (rbody).cur; /* hash from after HASH payload */ \
-}
-
-/* CHECK_QUICK_HASH
- *
- * This macro is magic -- it cannot be expressed as a function.
- * - it causes the caller to return!
- * - it declares local variables and expects the "do_hash" argument
- * expression to reference them (hash_val, hash_pbs)
- */
-#define CHECK_QUICK_HASH(md, do_hash, hash_name, msg_name) { \
- pb_stream *const hash_pbs = &md->chain[ISAKMP_NEXT_HASH]->pbs; \
- u_char hash_val[MAX_DIGEST_LEN]; \
- size_t hash_len = do_hash; \
- if (pbs_left(hash_pbs) != hash_len \
- || memcmp(hash_pbs->cur, hash_val, hash_len) != 0) \
- { \
- DBG_cond_dump(DBG_CRYPT, "received " hash_name ":", hash_pbs->cur, pbs_left(hash_pbs)); \
- loglog(RC_LOG_SERIOUS, "received " hash_name " does not match computed value in " msg_name); \
- /* XXX Could send notification back */ \
- return STF_FAIL + ISAKMP_INVALID_HASH_INFORMATION; \
- } \
- }
-
-#endif /* _IPSEC_DOI_H */
-
diff --git a/src/pluto/kameipsec.h b/src/pluto/kameipsec.h
deleted file mode 100644
index 5e9d8ce99..000000000
--- a/src/pluto/kameipsec.h
+++ /dev/null
@@ -1,47 +0,0 @@
-#ifndef __IPSEC_H
-#define __IPSEC_H 1
-
-/* The definitions, required to talk to KAME racoon IKE. */
-
-#define IPSEC_PORT_ANY 0
-#define IPSEC_ULPROTO_ANY 255
-#define IPSEC_PROTO_ANY 255
-
-enum {
- IPSEC_MODE_ANY = 0, /* We do not support this for SA */
- IPSEC_MODE_TRANSPORT = 1,
- IPSEC_MODE_TUNNEL = 2
-};
-
-enum {
- IPSEC_DIR_ANY = 0,
- IPSEC_DIR_INBOUND = 1,
- IPSEC_DIR_OUTBOUND = 2,
- IPSEC_DIR_FWD = 3, /* It is our own */
- IPSEC_DIR_MAX = 4,
- IPSEC_DIR_INVALID = 5
-};
-
-enum {
- IPSEC_POLICY_DISCARD = 0,
- IPSEC_POLICY_NONE = 1,
- IPSEC_POLICY_IPSEC = 2,
- IPSEC_POLICY_ENTRUST = 3,
- IPSEC_POLICY_BYPASS = 4
-};
-
-enum {
- IPSEC_LEVEL_DEFAULT = 0,
- IPSEC_LEVEL_USE = 1,
- IPSEC_LEVEL_REQUIRE = 2,
- IPSEC_LEVEL_UNIQUE = 3
-};
-
-#define IPSEC_MANUAL_REQID_MAX 0x3fff
-
-#define IPSEC_REPLAYWSIZE 32
-
-#define IP_IPSEC_POLICY 16
-#define IPV6_IPSEC_POLICY 34
-
-#endif /* __IPSEC_H */
diff --git a/src/pluto/kernel.c b/src/pluto/kernel.c
deleted file mode 100644
index e4729ef08..000000000
--- a/src/pluto/kernel.c
+++ /dev/null
@@ -1,2114 +0,0 @@
-/* routines that interface with the kernel's IPsec mechanism
- *
- * Copyright (C) 2010 Tobias Brunner
- * Copyright (C) 2009 Andreas Steffen
- * Hochschule fuer Technik Rapperswil
- *
- * Copyright (C) 1998-2002 D. Hugh Redelmeier
- * Copyright (C) 1997 Angelos D. Keromytis
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <stddef.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/queue.h>
-#include <sys/wait.h>
-
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <freeswan.h>
-
-#include <library.h>
-#include <hydra.h>
-#include <crypto/rngs/rng.h>
-#include <kernel/kernel_listener.h>
-
-#include <signal.h>
-#include <sys/time.h> /* for select(2) */
-#include <sys/types.h> /* for select(2) */
-#include <pfkeyv2.h>
-#include <pfkey.h>
-#include "kameipsec.h"
-
-#include "constants.h"
-#include "defs.h"
-#include "connections.h"
-#include "state.h"
-#include "timer.h"
-#include "kernel.h"
-#include "kernel_pfkey.h"
-#include "log.h"
-#include "ca.h"
-#include "server.h"
-#include "whack.h" /* for RC_LOG_SERIOUS */
-#include "keys.h"
-#include "crypto.h"
-#include "nat_traversal.h"
-#include "alg_info.h"
-#include "kernel_alg.h"
-#include "pluto.h"
-
-
-bool can_do_IPcomp = TRUE; /* can system actually perform IPCOMP? */
-
-/* test if the routes required for two different connections agree
- * It is assumed that the destination subnets agree; we are only
- * testing that the interfaces and nexthops match.
- */
-#define routes_agree(c, d) ((c)->interface == (d)->interface \
- && sameaddr(&(c)->spd.this.host_nexthop, &(d)->spd.this.host_nexthop))
-
-/* forward declaration */
-static bool shunt_eroute(connection_t *c, struct spd_route *sr,
- enum routing_t rt_kind, unsigned int op,
- const char *opname);
-
-static void set_text_said(char *text_said, const ip_address *dst,
- ipsec_spi_t spi, int proto);
-
-/**
- * Default IPsec SA config (e.g. to install trap policies).
- */
-static ipsec_sa_cfg_t null_ipsec_sa = {
- .mode = MODE_TRANSPORT,
- .esp = {
- .use = TRUE,
- },
-};
-
-/**
- * Helper function that converts an ip_subnet to a traffic_selector_t.
- */
-static traffic_selector_t *traffic_selector_from_subnet(const ip_subnet *client,
- const u_int8_t proto)
-{
- traffic_selector_t *ts;
- host_t *net;
- net = host_create_from_sockaddr((sockaddr_t*)&client->addr);
- ts = traffic_selector_create_from_subnet(net, client->maskbits, proto,
- net->get_port(net));
- return ts;
-}
-
-/**
- * Helper function that converts a traffic_selector_t to an ip_subnet.
- */
-static ip_subnet subnet_from_traffic_selector(traffic_selector_t *ts)
-{
- ip_subnet subnet;
- host_t *net;
- u_int8_t mask;
- ts->to_subnet(ts, &net, &mask);
- subnet.addr = *(ip_address*)net->get_sockaddr(net);
- subnet.maskbits = mask;
- net->destroy(net);
- return subnet;
-}
-
-
-void record_and_initiate_opportunistic(const ip_subnet *ours,
- const ip_subnet *his,
- int transport_proto, const char *why)
-{
- ip_address src, dst;
- passert(samesubnettype(ours, his));
-
- /* actually initiate opportunism */
- networkof(ours, &src);
- networkof(his, &dst);
- initiate_opportunistic(&src, &dst, transport_proto, TRUE, NULL_FD);
-}
-
-/* Generate Unique SPI numbers.
- *
- * The returned SPI is in network byte order.
- */
-ipsec_spi_t get_ipsec_spi(ipsec_spi_t avoid, int proto, struct spd_route *sr,
- bool tunnel)
-{
- host_t *host_src, *host_dst;
- u_int32_t spi;
-
- host_src = host_create_from_sockaddr((sockaddr_t*)&sr->that.host_addr);
- host_dst = host_create_from_sockaddr((sockaddr_t*)&sr->this.host_addr);
-
- if (hydra->kernel_interface->get_spi(hydra->kernel_interface, host_src,
- host_dst, proto, sr->reqid, &spi) != SUCCESS)
- {
- spi = 0;
- }
-
- host_src->destroy(host_src);
- host_dst->destroy(host_dst);
-
- return spi;
-}
-
-/* Generate Unique CPI numbers.
- * The result is returned as an SPI (4 bytes) in network order!
- * The real bits are in the nework-low-order 2 bytes.
- */
-ipsec_spi_t get_my_cpi(struct spd_route *sr, bool tunnel)
-{
- host_t *host_src, *host_dst;
- u_int16_t cpi;
-
- host_src = host_create_from_sockaddr((sockaddr_t*)&sr->that.host_addr);
- host_dst = host_create_from_sockaddr((sockaddr_t*)&sr->this.host_addr);
-
- if (hydra->kernel_interface->get_cpi(hydra->kernel_interface, host_src,
- host_dst, sr->reqid, &cpi) != SUCCESS)
-
- {
- cpi = 0;
- }
-
- host_src->destroy(host_src);
- host_dst->destroy(host_dst);
-
- return htonl((u_int32_t)ntohs(cpi));
-}
-
-/* Replace the shell metacharacters ', \, ", `, and $ in a character string
- * by escape sequences consisting of their octal values
- */
-static void escape_metachar(const char *src, char *dst, size_t dstlen)
-{
- while (*src != '\0' && dstlen > 4)
- {
- switch (*src)
- {
- case '\'':
- case '\\':
- case '"':
- case '`':
- case '$':
- sprintf(dst,"\\%s%o", (*src < 64)?"0":"", *src);
- dst += 4;
- dstlen -= 4;
- break;
- default:
- *dst++ = *src;
- dstlen--;
- }
- src++;
- }
- *dst = '\0';
-}
-
-/* invoke the updown script to do the routing and firewall commands required
- *
- * The user-specified updown script is run. Parameters are fed to it in
- * the form of environment variables. All such environment variables
- * have names starting with "PLUTO_".
- *
- * The operation to be performed is specified by PLUTO_VERB. This
- * verb has a suffix "-host" if the client on this end is just the
- * host; otherwise the suffix is "-client". If the address family
- * of the host is IPv6, an extra suffix of "-v6" is added.
- *
- * "prepare-host" and "prepare-client" are used to delete a route
- * that may exist (due to forces outside of Pluto). It is used to
- * prepare for pluto creating a route.
- *
- * "route-host" and "route-client" are used to install a route.
- * Since routing is based only on destination, the PLUTO_MY_CLIENT_*
- * values are probably of no use (using them may signify a bug).
- *
- * "unroute-host" and "unroute-client" are used to delete a route.
- * Since routing is based only on destination, the PLUTO_MY_CLIENT_*
- * values are probably of no use (using them may signify a bug).
- *
- * "up-host" and "up-client" are run when an eroute is added (not replaced).
- * They are useful for adjusting a firewall: usually for adding a rule
- * to let processed packets flow between clients. Note that only
- * one eroute may exist for a pair of client subnets but inbound
- * IPsec SAs may persist without an eroute.
- *
- * "down-host" and "down-client" are run when an eroute is deleted.
- * They are useful for adjusting a firewall.
- */
-
-#ifndef DEFAULT_UPDOWN
-# define DEFAULT_UPDOWN "ipsec _updown"
-#endif
-
-static bool do_command(connection_t *c, struct spd_route *sr, struct state *st,
- const char *verb)
-{
- char cmd[1536]; /* arbitrary limit on shell command length */
- const char *verb_suffix;
-
- /* figure out which verb suffix applies */
- {
- const char *hs, *cs;
-
- switch (addrtypeof(&sr->this.host_addr))
- {
- case AF_INET:
- hs = "-host";
- cs = "-client";
- break;
- case AF_INET6:
- hs = "-host-v6";
- cs = "-client-v6";
- break;
- default:
- loglog(RC_LOG_SERIOUS, "unknown address family");
- return FALSE;
- }
- verb_suffix = subnetisaddr(&sr->this.client, &sr->this.host_addr)
- ? hs : cs;
- }
-
- /* form the command string */
- {
- char
- nexthop_str[sizeof("PLUTO_NEXT_HOP='' ") +ADDRTOT_BUF] = "",
- srcip_str[sizeof("PLUTO_MY_SOURCEIP='' ")+ADDRTOT_BUF] = "",
- me_str[ADDRTOT_BUF],
- myid_str[BUF_LEN],
- myclient_str[SUBNETTOT_BUF],
- myclientnet_str[ADDRTOT_BUF],
- myclientmask_str[ADDRTOT_BUF],
- peer_str[ADDRTOT_BUF],
- peerid_str[BUF_LEN],
- peerclient_str[SUBNETTOT_BUF],
- peerclientnet_str[ADDRTOT_BUF],
- peerclientmask_str[ADDRTOT_BUF],
- peerca_str[BUF_LEN],
- mark_in[BUF_LEN] = "",
- mark_out[BUF_LEN] = "",
- udp_encap[BUF_LEN] = "",
- xauth_id_str[BUF_LEN] = "",
- secure_myid_str[BUF_LEN] = "",
- secure_peerid_str[BUF_LEN] = "",
- secure_peerca_str[BUF_LEN] = "",
- secure_xauth_id_str[BUF_LEN] = "";
- ip_address ta;
- pubkey_list_t *p;
-
- if (addrbytesptr(&sr->this.host_nexthop, NULL)
- && !isanyaddr(&sr->this.host_nexthop))
- {
- char *n;
-
- strcpy(nexthop_str, "PLUTO_NEXT_HOP='");
- n = nexthop_str + strlen(nexthop_str);
-
- addrtot(&sr->this.host_nexthop, 0
- ,n , sizeof(nexthop_str)-strlen(nexthop_str));
- strncat(nexthop_str, "' ", sizeof(nexthop_str));
- }
-
- if (!sr->this.host_srcip->is_anyaddr(sr->this.host_srcip))
- {
- char *n;
-
- strcpy(srcip_str, "PLUTO_MY_SOURCEIP='");
- n = srcip_str + strlen(srcip_str);
- snprintf(n, sizeof(srcip_str)-strlen(srcip_str), "%H",
- sr->this.host_srcip);
- strncat(srcip_str, "' ", sizeof(srcip_str));
- }
-
- if (sr->mark_in.value)
- {
- snprintf(mark_in, sizeof(mark_in), "PLUTO_MARK_IN='%u/0x%08x' ",
- sr->mark_in.value, sr->mark_in.mask);
- }
-
- if (sr->mark_out.value)
- {
- snprintf(mark_out, sizeof(mark_out), "PLUTO_MARK_OUT='%u/0x%08x' ",
- sr->mark_out.value, sr->mark_out.mask);
- }
-
- if (st && (st->nat_traversal & NAT_T_DETECTED))
- {
- snprintf(udp_encap, sizeof(udp_encap), "PLUTO_UDP_ENC='%u' ",
- sr->that.host_port);
- }
-
- addrtot(&sr->this.host_addr, 0, me_str, sizeof(me_str));
- snprintf(myid_str, sizeof(myid_str), "%Y", sr->this.id);
- escape_metachar(myid_str, secure_myid_str, sizeof(secure_myid_str));
- subnettot(&sr->this.client, 0, myclient_str, sizeof(myclientnet_str));
- networkof(&sr->this.client, &ta);
- addrtot(&ta, 0, myclientnet_str, sizeof(myclientnet_str));
- maskof(&sr->this.client, &ta);
- addrtot(&ta, 0, myclientmask_str, sizeof(myclientmask_str));
-
- if (c->xauth_identity &&
- c->xauth_identity->get_type(c->xauth_identity) != ID_ANY)
- {
- snprintf(xauth_id_str, sizeof(xauth_id_str), "%Y", c->xauth_identity);
- escape_metachar(xauth_id_str, secure_xauth_id_str,
- sizeof(secure_xauth_id_str));
- snprintf(xauth_id_str, sizeof(xauth_id_str), "PLUTO_XAUTH_ID='%s' ",
- secure_xauth_id_str);
- }
-
- addrtot(&sr->that.host_addr, 0, peer_str, sizeof(peer_str));
- snprintf(peerid_str, sizeof(peerid_str), "%Y", sr->that.id);
- escape_metachar(peerid_str, secure_peerid_str, sizeof(secure_peerid_str));
- subnettot(&sr->that.client, 0, peerclient_str, sizeof(peerclientnet_str));
- networkof(&sr->that.client, &ta);
- addrtot(&ta, 0, peerclientnet_str, sizeof(peerclientnet_str));
- maskof(&sr->that.client, &ta);
- addrtot(&ta, 0, peerclientmask_str, sizeof(peerclientmask_str));
-
- for (p = pubkeys; p != NULL; p = p->next)
- {
- pubkey_t *key = p->key;
- key_type_t type = key->public_key->get_type(key->public_key);
- int pathlen;
-
- if (type == KEY_RSA &&
- sr->that.id->equals(sr->that.id, key->id) &&
- trusted_ca(key->issuer, sr->that.ca, &pathlen))
- {
- if (key->issuer)
- {
- snprintf(peerca_str, BUF_LEN, "%Y", key->issuer);
- escape_metachar(peerca_str, secure_peerca_str, BUF_LEN);
- }
- else
- {
- secure_peerca_str[0] = '\0';
- }
- break;
- }
- }
-
- if (-1 == snprintf(cmd, sizeof(cmd)
- , "2>&1 " /* capture stderr along with stdout */
- "PLUTO_VERSION='1.1' " /* change VERSION when interface spec changes */
- "PLUTO_VERB='%s%s' "
- "PLUTO_CONNECTION='%s' "
- "%s" /* optional PLUTO_NEXT_HOP */
- "PLUTO_INTERFACE='%s' "
- "%s" /* optional PLUTO_HOST_ACCESS */
- "PLUTO_REQID='%u' "
- "PLUTO_ME='%s' "
- "PLUTO_MY_ID='%s' "
- "PLUTO_MY_CLIENT='%s' "
- "PLUTO_MY_CLIENT_NET='%s' "
- "PLUTO_MY_CLIENT_MASK='%s' "
- "PLUTO_MY_PORT='%u' "
- "PLUTO_MY_PROTOCOL='%u' "
- "PLUTO_PEER='%s' "
- "PLUTO_PEER_ID='%s' "
- "PLUTO_PEER_CLIENT='%s' "
- "PLUTO_PEER_CLIENT_NET='%s' "
- "PLUTO_PEER_CLIENT_MASK='%s' "
- "PLUTO_PEER_PORT='%u' "
- "PLUTO_PEER_PROTOCOL='%u' "
- "PLUTO_PEER_CA='%s' "
- "%s" /* optional PLUTO_MY_SRCIP */
- "%s" /* optional PLUTO_XAUTH_ID */
- "%s" /* optional PLUTO_MARK_IN */
- "%s" /* optional PLUTO_MARK_OUT */
- "%s" /* optional PLUTO_UDP_ENC */
- "%s" /* actual script */
- , verb, verb_suffix
- , c->name
- , nexthop_str
- , c->interface->vname
- , sr->this.hostaccess? "PLUTO_HOST_ACCESS='1' " : ""
- , sr->reqid
- , me_str
- , secure_myid_str
- , myclient_str
- , myclientnet_str
- , myclientmask_str
- , sr->this.port
- , sr->this.protocol
- , peer_str
- , secure_peerid_str
- , peerclient_str
- , peerclientnet_str
- , peerclientmask_str
- , sr->that.port
- , sr->that.protocol
- , secure_peerca_str
- , srcip_str
- , xauth_id_str
- , mark_in
- , mark_out
- , udp_encap
- , sr->this.updown == NULL? DEFAULT_UPDOWN : sr->this.updown))
- {
- loglog(RC_LOG_SERIOUS, "%s%s command too long!", verb, verb_suffix);
- return FALSE;
- }
- }
-
- DBG(DBG_CONTROL, DBG_log("executing %s%s: %s"
- , verb, verb_suffix, cmd));
-
- /* invoke the script, catching stderr and stdout
- * It may be of concern that some file descriptors will
- * be inherited. For the ones under our control, we
- * have done fcntl(fd, F_SETFD, FD_CLOEXEC) to prevent this.
- * Any used by library routines (perhaps the resolver or syslog)
- * will remain.
- */
- FILE *f = popen(cmd, "r");
-
- if (f == NULL)
- {
- loglog(RC_LOG_SERIOUS, "unable to popen %s%s command", verb, verb_suffix);
- return FALSE;
- }
-
- /* log any output */
- for (;;)
- {
- /* if response doesn't fit in this buffer, it will be folded */
- char resp[256];
-
- if (fgets(resp, sizeof(resp), f) == NULL)
- {
- if (ferror(f))
- {
- log_errno((e, "fgets failed on output of %s%s command"
- , verb, verb_suffix));
- return FALSE;
- }
- else
- {
- passert(feof(f));
- break;
- }
- }
- else
- {
- char *e = resp + strlen(resp);
-
- if (e > resp && e[-1] == '\n')
- e[-1] = '\0'; /* trim trailing '\n' */
- plog("%s%s output: %s", verb, verb_suffix, resp);
- }
- }
-
- /* report on and react to return code */
- {
- int r = pclose(f);
-
- if (r == -1)
- {
- log_errno((e, "pclose failed for %s%s command"
- , verb, verb_suffix));
- return FALSE;
- }
- else if (WIFEXITED(r))
- {
- if (WEXITSTATUS(r) != 0)
- {
- loglog(RC_LOG_SERIOUS, "%s%s command exited with status %d"
- , verb, verb_suffix, WEXITSTATUS(r));
- return FALSE;
- }
- }
- else if (WIFSIGNALED(r))
- {
- loglog(RC_LOG_SERIOUS, "%s%s command exited with signal %d"
- , verb, verb_suffix, WTERMSIG(r));
- return FALSE;
- }
- else
- {
- loglog(RC_LOG_SERIOUS, "%s%s command exited with unknown status %d"
- , verb, verb_suffix, r);
- return FALSE;
- }
- }
- return TRUE;
-}
-
-/* Check that we can route (and eroute). Diagnose if we cannot. */
-
-enum routability {
- route_impossible = 0,
- route_easy = 1,
- route_nearconflict = 2,
- route_farconflict = 3
-};
-
-static enum routability could_route(connection_t *c)
-{
- struct spd_route *esr, *rosr;
- connection_t *ero /* who, if anyone, owns our eroute? */
- , *ro = route_owner(c, &rosr, &ero, &esr); /* who owns our route? */
-
- /* it makes no sense to route a connection that is ISAKMP-only */
- if (!NEVER_NEGOTIATE(c->policy) && !HAS_IPSEC_POLICY(c->policy))
- {
- loglog(RC_ROUTE, "cannot route an ISAKMP-only connection");
- return route_impossible;
- }
-
- /* if this is a Road Warrior template, we cannot route.
- * Opportunistic template is OK.
- */
- if (c->kind == CK_TEMPLATE && !(c->policy & POLICY_OPPO))
- {
- loglog(RC_ROUTE, "cannot route Road Warrior template");
- return route_impossible;
- }
-
- /* if we don't know nexthop, we cannot route */
- if (isanyaddr(&c->spd.this.host_nexthop))
- {
- loglog(RC_ROUTE, "cannot route connection without knowing our nexthop");
- return route_impossible;
- }
-
- /* if routing would affect IKE messages, reject */
- if (c->spd.this.host_port != NAT_T_IKE_FLOAT_PORT
- && c->spd.this.host_port != IKE_UDP_PORT
- && addrinsubnet(&c->spd.that.host_addr, &c->spd.that.client))
- {
- loglog(RC_LOG_SERIOUS, "cannot install route: peer is within its client");
- return route_impossible;
- }
-
- /* If there is already a route for peer's client subnet
- * and it disagrees about interface or nexthop, we cannot steal it.
- * Note: if this connection is already routed (perhaps for another
- * state object), the route will agree.
- * This is as it should be -- it will arise during rekeying.
- */
- if (ro != NULL && !routes_agree(ro, c))
- {
- loglog(RC_LOG_SERIOUS, "cannot route -- route already in use for \"%s\""
- , ro->name);
- return route_impossible; /* another connection already
- using the eroute */
- }
-
- /* if there is an eroute for another connection, there is a problem */
- if (ero != NULL && ero != c)
- {
- connection_t *ero2, *ero_top;
- connection_t *inside, *outside;
-
- /*
- * note, wavesec (PERMANENT) goes *outside* and
- * OE goes *inside* (TEMPLATE)
- */
- inside = NULL;
- outside= NULL;
- if (ero->kind == CK_PERMANENT
- && c->kind == CK_TEMPLATE)
- {
- outside = ero;
- inside = c;
- }
- else if (c->kind == CK_PERMANENT
- && ero->kind == CK_TEMPLATE)
- {
- outside = c;
- inside = ero;
- }
-
- /* okay, check again, with correct order */
- if (outside && outside->kind == CK_PERMANENT
- && inside && inside->kind == CK_TEMPLATE)
- {
- char inst[CONN_INST_BUF];
-
- /* this is a co-terminal attempt of the "near" kind. */
- /* when chaining, we chain from inside to outside */
-
- /* XXX permit multiple deep connections? */
- passert(inside->policy_next == NULL);
-
- inside->policy_next = outside;
-
- /* since we are going to steal the eroute from the secondary
- * policy, we need to make sure that it no longer thinks that
- * it owns the eroute.
- */
- outside->spd.eroute_owner = SOS_NOBODY;
- outside->spd.routing = RT_UNROUTED_KEYED;
-
- /* set the priority of the new eroute owner to be higher
- * than that of the current eroute owner
- */
- inside->prio = outside->prio + 1;
-
- fmt_conn_instance(inside, inst);
-
- loglog(RC_LOG_SERIOUS
- , "conflict on eroute (%s), switching eroute to %s and linking %s"
- , inst, inside->name, outside->name);
-
- return route_nearconflict;
- }
-
- /* look along the chain of policies for one with the same name */
- ero_top = ero;
-
- for (ero2 = ero; ero2 != NULL; ero2 = ero->policy_next)
- {
- if (ero2->kind == CK_TEMPLATE
- && streq(ero2->name, c->name))
- break;
- }
-
- /* If we fell of the end of the list, then we found no TEMPLATE
- * so there must be a conflict that we can't resolve.
- * As the names are not equal, then we aren't replacing/rekeying.
- */
- if (ero2 == NULL)
- {
- char inst[CONN_INST_BUF];
-
- fmt_conn_instance(ero, inst);
-
- loglog(RC_LOG_SERIOUS
- , "cannot install eroute -- it is in use for \"%s\"%s #%lu"
- , ero->name, inst, esr->eroute_owner);
- return route_impossible;
- }
- }
- return route_easy;
-}
-
-bool trap_connection(connection_t *c)
-{
- switch (could_route(c))
- {
- case route_impossible:
- return FALSE;
-
- case route_nearconflict:
- case route_easy:
- /* RT_ROUTED_TUNNEL is treated specially: we don't override
- * because we don't want to lose track of the IPSEC_SAs etc.
- */
- if (c->spd.routing < RT_ROUTED_TUNNEL)
- {
- return route_and_eroute(c, &c->spd, NULL);
- }
- return TRUE;
-
- case route_farconflict:
- return FALSE;
- }
-
- return FALSE;
-}
-
-/**
- * Delete any eroute for a connection and unroute it if route isn't shared
- */
-void unroute_connection(connection_t *c)
-{
- struct spd_route *sr;
- enum routing_t cr;
-
- for (sr = &c->spd; sr; sr = sr->next)
- {
- cr = sr->routing;
-
- if (erouted(cr))
- {
- /* cannot handle a live one */
- passert(sr->routing != RT_ROUTED_TUNNEL);
- shunt_eroute(c, sr, RT_UNROUTED, ERO_DELETE, "delete");
- }
-
- sr->routing = RT_UNROUTED; /* do now so route_owner won't find us */
-
- /* only unroute if no other connection shares it */
- if (routed(cr) && route_owner(c, NULL, NULL, NULL) == NULL)
- {
- (void) do_command(c, sr, NULL, "unroute");
- }
- }
-}
-
-
-static void set_text_said(char *text_said, const ip_address *dst,
- ipsec_spi_t spi, int proto)
-{
- ip_said said;
-
- initsaid(dst, spi, proto, &said);
- satot(&said, 0, text_said, SATOT_BUF);
-}
-
-
-/**
- * Setup an IPsec route entry.
- * op is one of the ERO_* operators.
- */
-static bool raw_eroute(const ip_address *this_host,
- const ip_subnet *this_client,
- const ip_address *that_host,
- const ip_subnet *that_client,
- mark_t mark,
- ipsec_spi_t spi,
- unsigned int proto,
- unsigned int satype,
- unsigned int transport_proto,
- ipsec_sa_cfg_t *sa,
- unsigned int op,
- const char *opname USED_BY_DEBUG)
-{
- traffic_selector_t *ts_src, *ts_dst;
- host_t *host_src, *host_dst;
- policy_type_t type = POLICY_IPSEC;
- policy_dir_t dir = POLICY_OUT;
- policy_priority_t priority = POLICY_PRIORITY_DEFAULT;
- char text_said[SATOT_BUF];
- bool ok = TRUE,
- deleting = (op & ERO_MASK) == ERO_DELETE,
- replacing = op & (SADB_X_SAFLAGS_REPLACEFLOW << ERO_FLAG_SHIFT);
-
- set_text_said(text_said, that_host, spi, proto);
-
- DBG(DBG_CONTROL | DBG_KERNEL,
- {
- int sport = ntohs(portof(&this_client->addr));
- int dport = ntohs(portof(&that_client->addr));
- char mybuf[SUBNETTOT_BUF];
- char peerbuf[SUBNETTOT_BUF];
-
- subnettot(this_client, 0, mybuf, sizeof(mybuf));
- subnettot(that_client, 0, peerbuf, sizeof(peerbuf));
- DBG_log("%s eroute %s:%d -> %s:%d => %s:%d"
- , opname, mybuf, sport, peerbuf, dport
- , text_said, transport_proto);
- });
-
- if (satype == SADB_X_SATYPE_INT)
- {
- switch (ntohl(spi))
- {
- case SPI_PASS:
- type = POLICY_PASS;
- break;
- case SPI_DROP:
- case SPI_REJECT:
- type = POLICY_DROP;
- break;
- case SPI_TRAP:
- case SPI_TRAPSUBNET:
- case SPI_HOLD:
- if (op & (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT))
- {
- return TRUE;
- }
- priority = POLICY_PRIORITY_ROUTED;
- break;
- }
- }
-
- if (op & (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT))
- {
- dir = POLICY_IN;
- }
-
- host_src = host_create_from_sockaddr((sockaddr_t*)this_host);
- host_dst = host_create_from_sockaddr((sockaddr_t*)that_host);
- ts_src = traffic_selector_from_subnet(this_client, transport_proto);
- ts_dst = traffic_selector_from_subnet(that_client, transport_proto);
-
- if (deleting || replacing)
- {
- hydra->kernel_interface->del_policy(hydra->kernel_interface,
- ts_src, ts_dst, dir, sa->reqid, mark, priority);
- }
-
- if (!deleting)
- {
- ok = hydra->kernel_interface->add_policy(hydra->kernel_interface,
- host_src, host_dst, ts_src, ts_dst, dir, type, sa,
- mark, priority) == SUCCESS;
- }
-
- if (dir == POLICY_IN)
- { /* handle forward policy */
- dir = POLICY_FWD;
- if (deleting || replacing)
- {
- hydra->kernel_interface->del_policy(hydra->kernel_interface,
- ts_src, ts_dst, dir, sa->reqid, mark, priority);
- }
-
- if (!deleting && ok &&
- (sa->mode == MODE_TUNNEL || satype == SADB_X_SATYPE_INT))
- {
- ok = hydra->kernel_interface->add_policy(hydra->kernel_interface,
- host_src, host_dst, ts_src, ts_dst, dir, type, sa,
- mark, priority) == SUCCESS;
- }
- }
-
- host_src->destroy(host_src);
- host_dst->destroy(host_dst);
- ts_src->destroy(ts_src);
- ts_dst->destroy(ts_dst);
-
- return ok;
-}
-
-static bool eroute_connection(struct spd_route *sr, ipsec_spi_t spi,
- unsigned int proto, unsigned int satype,
- ipsec_sa_cfg_t *sa, unsigned int op,
- const char *opname)
-{
- const ip_address *peer = &sr->that.host_addr;
- char buf2[256];
- bool ok;
-
- snprintf(buf2, sizeof(buf2)
- , "eroute_connection %s", opname);
-
- if (proto == SA_INT)
- {
- peer = aftoinfo(addrtypeof(peer))->any;
- }
- ok = raw_eroute(peer, &sr->that.client,
- &sr->this.host_addr, &sr->this.client, sr->mark_in,
- spi, proto, satype, sr->this.protocol,
- sa, op | (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT), buf2);
- return raw_eroute(&sr->this.host_addr, &sr->this.client, peer,
- &sr->that.client, sr->mark_out, spi, proto, satype,
- sr->this.protocol, sa, op, buf2) && ok;
-}
-
-/* assign a bare hold to a connection */
-
-bool assign_hold(connection_t *c USED_BY_DEBUG, struct spd_route *sr,
- int transport_proto,
- const ip_address *src,
- const ip_address *dst)
-{
- /* either the automatically installed %hold eroute is broad enough
- * or we try to add a broader one and delete the automatic one.
- * Beware: this %hold might be already handled, but still squeak
- * through because of a race.
- */
- enum routing_t ro = sr->routing /* routing, old */
- , rn = ro; /* routing, new */
-
- passert(LHAS(LELEM(CK_PERMANENT) | LELEM(CK_INSTANCE), c->kind));
- /* figure out what routing should become */
- switch (ro)
- {
- case RT_UNROUTED:
- rn = RT_UNROUTED_HOLD;
- break;
- case RT_ROUTED_PROSPECTIVE:
- rn = RT_ROUTED_HOLD;
- break;
- default:
- /* no change: this %hold is old news and should just be deleted */
- break;
- }
-
- /* We need a broad %hold
- * First we ensure that there is a broad %hold.
- * There may already be one (race condition): no need to create one.
- * There may already be a %trap: replace it.
- * There may not be any broad eroute: add %hold.
- */
- if (rn != ro)
- {
- if (erouted(ro)
- ? !eroute_connection(sr, htonl(SPI_HOLD), SA_INT, SADB_X_SATYPE_INT,
- &null_ipsec_sa, ERO_REPLACE,
- "replace %trap with broad %hold")
- : !eroute_connection(sr, htonl(SPI_HOLD), SA_INT, SADB_X_SATYPE_INT,
- &null_ipsec_sa, ERO_ADD, "add broad %hold"))
- {
- return FALSE;
- }
- }
- sr->routing = rn;
- return TRUE;
-}
-
-/* install or remove eroute for SA Group */
-static bool sag_eroute(struct state *st, struct spd_route *sr,
- unsigned op, const char *opname)
-{
- u_int inner_proto, inner_satype;
- ipsec_spi_t inner_spi = 0;
- ipsec_sa_cfg_t sa = {
- .mode = MODE_TRANSPORT,
- };
- bool tunnel = FALSE;
-
- if (st->st_ah.present)
- {
- inner_spi = st->st_ah.attrs.spi;
- inner_proto = SA_AH;
- inner_satype = SADB_SATYPE_AH;
- sa.ah.use = TRUE;
- sa.ah.spi = inner_spi;
- tunnel |= st->st_ah.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL;
- }
-
- if (st->st_esp.present)
- {
- inner_spi = st->st_esp.attrs.spi;
- inner_proto = SA_ESP;
- inner_satype = SADB_SATYPE_ESP;
- sa.esp.use = TRUE;
- sa.esp.spi = inner_spi;
- tunnel |= st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL;
- }
-
- if (st->st_ipcomp.present)
- {
- inner_spi = st->st_ipcomp.attrs.spi;
- inner_proto = SA_COMP;
- inner_satype = SADB_X_SATYPE_COMP;
- sa.ipcomp.transform = st->st_ipcomp.attrs.transid;
- sa.ipcomp.cpi = htons(ntohl(inner_spi));
- tunnel |= st->st_ipcomp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL;
- }
-
- if (!sa.ah.use && !sa.esp.use && !sa.ipcomp.transform)
- {
- impossible(); /* no transform at all! */
- }
-
- if (tunnel)
- {
- inner_spi = st->st_tunnel_out_spi;
- inner_proto = SA_IPIP;
- inner_satype = SADB_X_SATYPE_IPIP;
- sa.mode = MODE_TUNNEL;
- }
-
- sa.reqid = sr->reqid;
-
- return eroute_connection(sr, inner_spi, inner_proto, inner_satype,
- &sa, op, opname);
-}
-
-/* compute a (host-order!) SPI to implement the policy in connection c */
-ipsec_spi_t
-shunt_policy_spi(connection_t *c, bool prospective)
-{
- /* note: these are in host order :-( */
- static const ipsec_spi_t shunt_spi[] =
- {
- SPI_TRAP, /* --initiateontraffic */
- SPI_PASS, /* --pass */
- SPI_DROP, /* --drop */
- SPI_REJECT, /* --reject */
- };
-
- static const ipsec_spi_t fail_spi[] =
- {
- 0, /* --none*/
- SPI_PASS, /* --failpass */
- SPI_DROP, /* --faildrop */
- SPI_REJECT, /* --failreject */
- };
-
- return prospective
- ? shunt_spi[(c->policy & POLICY_SHUNT_MASK) >> POLICY_SHUNT_SHIFT]
- : fail_spi[(c->policy & POLICY_FAIL_MASK) >> POLICY_FAIL_SHIFT];
-}
-
-/* Add/replace/delete a shunt eroute.
- * Such an eroute determines the fate of packets without the use
- * of any SAs. These are defaults, in effect.
- * If a negotiation has not been attempted, use %trap.
- * If negotiation has failed, the choice between %trap/%pass/%drop/%reject
- * is specified in the policy of connection c.
- */
-static bool shunt_eroute(connection_t *c, struct spd_route *sr,
- enum routing_t rt_kind,
- unsigned int op, const char *opname)
-{
- /* We are constructing a special SAID for the eroute.
- * The destination doesn't seem to matter, but the family does.
- * The protocol is SA_INT -- mark this as shunt.
- * The satype has no meaning, but is required for PF_KEY header!
- * The SPI signifies the kind of shunt.
- */
- ipsec_spi_t spi = shunt_policy_spi(c, rt_kind == RT_ROUTED_PROSPECTIVE);
-
- if (spi == 0)
- {
- /* we're supposed to end up with no eroute: rejig op and opname */
- switch (op)
- {
- case ERO_REPLACE:
- /* replace with nothing == delete */
- op = ERO_DELETE;
- opname = "delete";
- break;
- case ERO_ADD:
- /* add nothing == do nothing */
- return TRUE;
- case ERO_DELETE:
- /* delete remains delete */
- break;
- default:
- bad_case(op);
- }
- }
- if (sr->routing == RT_ROUTED_ECLIPSED && c->kind == CK_TEMPLATE)
- {
- /* We think that we have an eroute, but we don't.
- * Adjust the request and account for eclipses.
- */
- passert(eclipsable(sr));
- switch (op)
- {
- case ERO_REPLACE:
- /* really an add */
- op = ERO_ADD;
- opname = "replace eclipsed";
- eclipse_count--;
- break;
- case ERO_DELETE:
- /* delete unnecessary: we don't actually have an eroute */
- eclipse_count--;
- return TRUE;
- case ERO_ADD:
- default:
- bad_case(op);
- }
- }
- else if (eclipse_count > 0 && op == ERO_DELETE && eclipsable(sr))
- {
- /* maybe we are uneclipsing something */
- struct spd_route *esr;
- connection_t *ue = eclipsed(c, &esr);
-
- if (ue != NULL)
- {
- esr->routing = RT_ROUTED_PROSPECTIVE;
- return shunt_eroute(ue, esr
- , RT_ROUTED_PROSPECTIVE, ERO_REPLACE, "restoring eclipsed");
- }
- }
-
- return eroute_connection(sr, htonl(spi), SA_INT, SADB_X_SATYPE_INT,
- &null_ipsec_sa, op, opname);
-}
-
-static bool setup_half_ipsec_sa(struct state *st, bool inbound)
-{
- host_t *host_src, *host_dst;
- connection_t *c = st->st_connection;
- struct end *src, *dst;
- ipsec_mode_t mode = MODE_TRANSPORT;
- ipsec_sa_cfg_t sa = { .mode = 0 };
- lifetime_cfg_t lt_none = { .time = { .rekey = 0 } };
- mark_t mark;
- bool ok = TRUE;
- /* SPIs, saved for undoing, if necessary */
- struct kernel_sa said[EM_MAXRELSPIS], *said_next = said;
- if (inbound)
- {
- src = &c->spd.that;
- dst = &c->spd.this;
- mark = c->spd.mark_in;
- }
- else
- {
- src = &c->spd.this;
- dst = &c->spd.that;
- mark = c->spd.mark_out;
- }
-
- host_src = host_create_from_sockaddr((sockaddr_t*)&src->host_addr);
- host_dst = host_create_from_sockaddr((sockaddr_t*)&dst->host_addr);
-
- if (st->st_ah.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL
- || st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL
- || st->st_ipcomp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL)
- {
- mode = MODE_TUNNEL;
- }
-
- sa.mode = mode;
- sa.reqid = c->spd.reqid;
-
- memset(said, 0, sizeof(said));
-
- /* set up IPCOMP SA, if any */
-
- if (st->st_ipcomp.present)
- {
- ipsec_spi_t ipcomp_spi = inbound ? st->st_ipcomp.our_spi
- : st->st_ipcomp.attrs.spi;
-
- switch (st->st_ipcomp.attrs.transid)
- {
- case IPCOMP_DEFLATE:
- break;
-
- default:
- loglog(RC_LOG_SERIOUS, "IPCOMP transform %s not implemented",
- enum_name(&ipcomp_transformid_names,
- st->st_ipcomp.attrs.transid));
- goto fail;
- }
-
- sa.ipcomp.cpi = htons(ntohl(ipcomp_spi));
- sa.ipcomp.transform = st->st_ipcomp.attrs.transid;
-
- said_next->spi = ipcomp_spi;
- said_next->proto = IPPROTO_COMP;
-
- if (hydra->kernel_interface->add_sa(hydra->kernel_interface, host_src,
- host_dst, ipcomp_spi, said_next->proto, c->spd.reqid,
- mark, 0, &lt_none, ENCR_UNDEFINED, chunk_empty,
- AUTH_UNDEFINED, chunk_empty, mode,
- st->st_ipcomp.attrs.transid, 0 /* cpi */, FALSE, FALSE,
- inbound, NULL, NULL) != SUCCESS)
- {
- goto fail;
- }
- said_next++;
- mode = MODE_TRANSPORT;
- }
-
- /* set up ESP SA, if any */
-
- if (st->st_esp.present)
- {
- ipsec_spi_t esp_spi = inbound ? st->st_esp.our_spi
- : st->st_esp.attrs.spi;
- u_char *esp_dst_keymat = inbound ? st->st_esp.our_keymat
- : st->st_esp.peer_keymat;
- bool encap = st->nat_traversal & NAT_T_DETECTED;
- encryption_algorithm_t enc_alg;
- integrity_algorithm_t auth_alg;
- const struct esp_info *ei;
- chunk_t enc_key, auth_key;
- u_int16_t key_len;
-
- if ((ei = kernel_alg_esp_info(st->st_esp.attrs.transid,
- st->st_esp.attrs.auth)) == NULL)
- {
- loglog(RC_LOG_SERIOUS, "ESP transform %s / auth %s"
- " not implemented yet",
- enum_name(&esp_transform_names, st->st_esp.attrs.transid),
- enum_name(&auth_alg_names, st->st_esp.attrs.auth));
- goto fail;
- }
-
- key_len = st->st_esp.attrs.key_len / 8;
- if (key_len)
- {
- /* XXX: must change to check valid _range_ key_len */
- if (key_len > ei->enckeylen)
- {
- loglog(RC_LOG_SERIOUS, "ESP transform %s: key_len=%d > %d",
- enum_name(&esp_transform_names, st->st_esp.attrs.transid),
- (int)key_len, (int)ei->enckeylen);
- goto fail;
- }
- }
- else
- {
- key_len = ei->enckeylen;
- }
-
- switch (ei->transid)
- {
- case ESP_3DES:
- /* 168 bits in kernel, need 192 bits for keymat_len */
- if (key_len == 21)
- {
- key_len = 24;
- }
- break;
- case ESP_DES:
- /* 56 bits in kernel, need 64 bits for keymat_len */
- if (key_len == 7)
- {
- key_len = 8;
- }
- break;
- case ESP_AES_CCM_8:
- case ESP_AES_CCM_12:
- case ESP_AES_CCM_16:
- key_len += 3;
- break;
- case ESP_AES_GCM_8:
- case ESP_AES_GCM_12:
- case ESP_AES_GCM_16:
- case ESP_AES_CTR:
- case ESP_AES_GMAC:
- key_len += 4;
- break;
- default:
- break;
- }
-
- if (encap)
- {
- host_src->set_port(host_src, src->host_port);
- host_dst->set_port(host_dst, dst->host_port);
- // st->nat_oa is currently unused
- }
-
- /* divide up keying material */
- enc_alg = encryption_algorithm_from_esp(st->st_esp.attrs.transid);
- enc_key.ptr = esp_dst_keymat;
- enc_key.len = key_len;
- auth_alg = integrity_algorithm_from_esp(st->st_esp.attrs.auth);
- auth_alg = auth_alg ? : AUTH_UNDEFINED;
- auth_key.ptr = esp_dst_keymat + key_len;
- auth_key.len = ei->authkeylen;
-
- sa.esp.use = TRUE;
- sa.esp.spi = esp_spi;
-
- said_next->spi = esp_spi;
- said_next->proto = IPPROTO_ESP;
-
- if (hydra->kernel_interface->add_sa(hydra->kernel_interface, host_src,
- host_dst, esp_spi, said_next->proto, c->spd.reqid,
- mark, 0, &lt_none, enc_alg, enc_key,
- auth_alg, auth_key, mode, IPCOMP_NONE, 0 /* cpi */,
- encap, FALSE, inbound, NULL, NULL) != SUCCESS)
- {
- goto fail;
- }
- said_next++;
- mode = MODE_TRANSPORT;
- }
-
- /* set up AH SA, if any */
-
- if (st->st_ah.present)
- {
- ipsec_spi_t ah_spi = inbound ? st->st_ah.our_spi
- : st->st_ah.attrs.spi;
- u_char *ah_dst_keymat = inbound ? st->st_ah.our_keymat
- : st->st_ah.peer_keymat;
- integrity_algorithm_t auth_alg;
- chunk_t auth_key;
-
- auth_alg = integrity_algorithm_from_esp(st->st_ah.attrs.auth);
- auth_key.ptr = ah_dst_keymat;
- auth_key.len = st->st_ah.keymat_len;
-
- sa.ah.use = TRUE;
- sa.ah.spi = ah_spi;
-
- said_next->spi = ah_spi;
- said_next->proto = IPPROTO_AH;
-
- if (hydra->kernel_interface->add_sa(hydra->kernel_interface, host_src,
- host_dst, ah_spi, said_next->proto, c->spd.reqid,
- mark, 0, &lt_none, ENCR_UNDEFINED, chunk_empty,
- auth_alg, auth_key, mode, IPCOMP_NONE, 0 /* cpi */,
- FALSE, FALSE, inbound, NULL, NULL) != SUCCESS)
- {
- goto fail;
- }
- said_next++;
- mode = MODE_TRANSPORT;
- }
-
- goto cleanup;
-
-fail:
- /* undo the done SPIs */
- while (said_next-- != said)
- {
- hydra->kernel_interface->del_sa(hydra->kernel_interface, host_src,
- host_dst, said_next->spi,
- said_next->proto, 0 /* cpi */,
- mark);
- }
- ok = FALSE;
-
-cleanup:
- host_src->destroy(host_src);
- host_dst->destroy(host_dst);
- return ok;
-}
-
-static bool teardown_half_ipsec_sa(struct state *st, bool inbound)
-{
- connection_t *c = st->st_connection;
- const struct end *src, *dst;
- host_t *host_src, *host_dst;
- ipsec_spi_t spi;
- mark_t mark;
- bool result = TRUE;
-
- if (inbound)
- {
- src = &c->spd.that;
- dst = &c->spd.this;
- mark = c->spd.mark_in;
- }
- else
- {
- src = &c->spd.this;
- dst = &c->spd.that;
- mark = c->spd.mark_out;
- }
-
- host_src = host_create_from_sockaddr((sockaddr_t*)&src->host_addr);
- host_dst = host_create_from_sockaddr((sockaddr_t*)&dst->host_addr);
-
- if (st->st_ah.present)
- {
- spi = inbound ? st->st_ah.our_spi : st->st_ah.attrs.spi;
- result &= hydra->kernel_interface->del_sa(hydra->kernel_interface,
- host_src, host_dst, spi, IPPROTO_AH,
- 0 /* cpi */, mark) == SUCCESS;
- }
-
- if (st->st_esp.present)
- {
- spi = inbound ? st->st_esp.our_spi : st->st_esp.attrs.spi;
- result &= hydra->kernel_interface->del_sa(hydra->kernel_interface,
- host_src, host_dst, spi, IPPROTO_ESP,
- 0 /* cpi */, mark) == SUCCESS;
- }
-
- if (st->st_ipcomp.present)
- {
- spi = inbound ? st->st_ipcomp.our_spi : st->st_ipcomp.attrs.spi;
- result &= hydra->kernel_interface->del_sa(hydra->kernel_interface,
- host_src, host_dst, spi, IPPROTO_COMP,
- 0 /* cpi */, mark) == SUCCESS;
- }
-
- host_src->destroy(host_src);
- host_dst->destroy(host_dst);
-
- return result;
-}
-
-/*
- * get information about a given sa
- */
-bool get_sa_info(struct state *st, bool inbound, u_int *bytes, time_t *use_time)
-{
- connection_t *c = st->st_connection;
- traffic_selector_t *ts_src = NULL, *ts_dst = NULL;
- host_t *host_src = NULL, *host_dst = NULL;
- const struct end *src, *dst;
- ipsec_spi_t spi;
- mark_t mark;
- u_int64_t bytes_kernel = 0;
- bool result = FALSE;
-
- *use_time = UNDEFINED_TIME;
-
- if (!st->st_esp.present)
- {
- goto failed;
- }
-
- if (inbound)
- {
- src = &c->spd.that;
- dst = &c->spd.this;
- mark = c->spd.mark_in;
- spi = st->st_esp.our_spi;
- }
- else
- {
- src = &c->spd.this;
- dst = &c->spd.that;
- mark = c->spd.mark_out;
- spi = st->st_esp.attrs.spi;
- }
-
- host_src = host_create_from_sockaddr((sockaddr_t*)&src->host_addr);
- host_dst = host_create_from_sockaddr((sockaddr_t*)&dst->host_addr);
-
- switch(hydra->kernel_interface->query_sa(hydra->kernel_interface, host_src,
- host_dst, spi, IPPROTO_ESP,
- mark, &bytes_kernel))
- {
- case FAILED:
- goto failed;
- case SUCCESS:
- *bytes = bytes_kernel;
- break;
- case NOT_SUPPORTED:
- default:
- break;
- }
-
- if (st->st_serialno == c->spd.eroute_owner)
- {
- u_int32_t time_kernel;
-
- ts_src = traffic_selector_from_subnet(&src->client, src->protocol);
- ts_dst = traffic_selector_from_subnet(&dst->client, dst->protocol);
-
- if (hydra->kernel_interface->query_policy(hydra->kernel_interface,
- ts_src, ts_dst, inbound ? POLICY_IN : POLICY_OUT,
- mark, &time_kernel) != SUCCESS)
- {
- goto failed;
- }
- *use_time = time_kernel;
-
- if (inbound &&
- st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL)
- {
- if (hydra->kernel_interface->query_policy(hydra->kernel_interface,
- ts_src, ts_dst, POLICY_FWD, mark,
- &time_kernel) != SUCCESS)
- {
- goto failed;
- }
- *use_time = max(*use_time, time_kernel);
- }
- }
-
- result = TRUE;
-
-failed:
- DESTROY_IF(host_src);
- DESTROY_IF(host_dst);
- DESTROY_IF(ts_src);
- DESTROY_IF(ts_dst);
- return result;
-}
-
-/**
- * Handler for kernel events (called by thread-pool thread)
- */
-kernel_listener_t *kernel_handler;
-
-/**
- * Data for acquire events
- */
-typedef struct {
- /** Subnets */
- ip_subnet src, dst;
- /** Transport protocol */
- int proto;
-} acquire_data_t;
-
-/**
- * Callback for acquire events (called by main thread)
- */
-void handle_acquire(acquire_data_t *this)
-{
- record_and_initiate_opportunistic(&this->src, &this->dst, this->proto,
- "%acquire");
-}
-
-METHOD(kernel_listener_t, acquire, bool,
- kernel_listener_t *this, u_int32_t reqid,
- traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
-{
- if (src_ts && dst_ts)
- {
- acquire_data_t *data;
- DBG(DBG_CONTROL,
- DBG_log("creating acquire event for policy %R === %R "
- "with reqid {%u}", src_ts, dst_ts, reqid));
- INIT(data,
- .src = subnet_from_traffic_selector(src_ts),
- .dst = subnet_from_traffic_selector(dst_ts),
- .proto = src_ts->get_protocol(src_ts),
- );
- pluto->events->queue(pluto->events, (void*)handle_acquire, data, free);
- }
- else
- {
- DBG(DBG_CONTROL,
- DBG_log("ignoring acquire without traffic selectors for policy "
- "with reqid {%u}", reqid));
- }
- DESTROY_IF(src_ts);
- DESTROY_IF(dst_ts);
- return TRUE;
-}
-
-/**
- * Data for mapping events
- */
-typedef struct {
- /** reqid, spi of affected SA */
- u_int32_t reqid, spi;
- /** new endpont */
- ip_address new_end;
-} mapping_data_t;
-
-/**
- * Callback for mapping events (called by main thread)
- */
-void handle_mapping(mapping_data_t *this)
-{
- process_nat_t_new_mapping(this->reqid, this->spi, &this->new_end);
-}
-
-
-METHOD(kernel_listener_t, mapping, bool,
- kernel_listener_t *this, u_int32_t reqid, u_int32_t spi, host_t *remote)
-{
- mapping_data_t *data;
- DBG(DBG_CONTROL,
- DBG_log("creating mapping event for SA with SPI %.8x and reqid {%u}",
- spi, reqid));
- INIT(data,
- .reqid = reqid,
- .spi = spi,
- .new_end = *(ip_address*)remote->get_sockaddr(remote),
- );
- pluto->events->queue(pluto->events, (void*)handle_mapping, data, free);
- return TRUE;
-}
-
-void init_kernel(void)
-{
- /* register SA types that we can negotiate */
- can_do_IPcomp = FALSE; /* until we get a response from the kernel */
- pfkey_register();
-
- INIT(kernel_handler,
- .acquire = _acquire,
- .mapping = _mapping,
- );
- hydra->kernel_interface->add_listener(hydra->kernel_interface,
- kernel_handler);
-}
-
-void kernel_finalize()
-{
- hydra->kernel_interface->remove_listener(hydra->kernel_interface,
- kernel_handler);
- free(kernel_handler);
-}
-
-/* Note: install_inbound_ipsec_sa is only used by the Responder.
- * The Responder will subsequently use install_ipsec_sa for the outbound.
- * The Initiator uses install_ipsec_sa to install both at once.
- */
-bool install_inbound_ipsec_sa(struct state *st)
-{
- connection_t *const c = st->st_connection;
-
- /* If our peer has a fixed-address client, check if we already
- * have a route for that client that conflicts. We will take this
- * as proof that that route and the connections using it are
- * obsolete and should be eliminated. Interestingly, this is
- * the only case in which we can tell that a connection is obsolete.
- */
- passert(c->kind == CK_PERMANENT || c->kind == CK_INSTANCE);
- if (c->spd.that.has_client)
- {
- for (;;)
- {
- struct spd_route *esr;
- connection_t *o = route_owner(c, &esr, NULL, NULL);
-
- if (o == NULL)
- {
- break; /* nobody has a route */
- }
-
- /* note: we ignore the client addresses at this end */
- if (sameaddr(&o->spd.that.host_addr, &c->spd.that.host_addr) &&
- o->interface == c->interface)
- {
- break; /* existing route is compatible */
- }
-
- if (o->kind == CK_TEMPLATE && streq(o->name, c->name))
- {
- break; /* ??? is this good enough?? */
- }
-
- loglog(RC_LOG_SERIOUS, "route to peer's client conflicts with \"%s\" %s; releasing old connection to free the route"
- , o->name, ip_str(&o->spd.that.host_addr));
- release_connection(o, FALSE);
- }
- }
-
- DBG(DBG_CONTROL, DBG_log("install_inbound_ipsec_sa() checking if we can route"));
- /* check that we will be able to route and eroute */
- switch (could_route(c))
- {
- case route_easy:
- case route_nearconflict:
- break;
- default:
- return FALSE;
- }
-
- /* (attempt to) actually set up the SAs */
- return setup_half_ipsec_sa(st, TRUE);
-}
-
-/* Install a route and then a prospective shunt eroute or an SA group eroute.
- * Assumption: could_route gave a go-ahead.
- * Any SA Group must have already been created.
- * On failure, steps will be unwound.
- */
-bool route_and_eroute(connection_t *c, struct spd_route *sr, struct state *st)
-{
- struct spd_route *esr;
- struct spd_route *rosr;
- connection_t *ero /* who, if anyone, owns our eroute? */
- , *ro = route_owner(c, &rosr, &ero, &esr);
- bool eroute_installed = FALSE
- , firewall_notified = FALSE
- , route_installed = FALSE;
-
- connection_t *ero_top;
-
- DBG(DBG_CONTROLMORE,
- DBG_log("route_and_eroute with c: %s (next: %s) ero:%s esr:{%p} ro:%s rosr:{%p} and state: %lu"
- , c->name
- , (c->policy_next ? c->policy_next->name : "none")
- , ero ? ero->name : "null"
- , esr
- , ro ? ro->name : "null"
- , rosr
- , st ? st->st_serialno : 0));
-
- /* look along the chain of policies for one with the same name */
- ero_top = ero;
-
-#if 0
- /* XXX - mcr this made sense before, and likely will make sense
- * again, so I'l leaving this to remind me what is up */
- if (ero!= NULL && ero->routing == RT_UNROUTED_KEYED)
- ero = NULL;
-
- for (ero2 = ero; ero2 != NULL; ero2 = ero->policy_next)
- if ((ero2->kind == CK_TEMPLATE || ero2->kind==CK_SECONDARY)
- && streq(ero2->name, c->name))
- break;
-#endif
-
- /* install the eroute */
-
- if (ero != NULL)
- {
- /* We're replacing an eroute */
-
- /* if no state provided, then install a shunt for later */
- if (st == NULL)
- {
- eroute_installed = shunt_eroute(c, sr, RT_ROUTED_PROSPECTIVE
- , ERO_REPLACE, "replace");
- }
- else
- {
- eroute_installed = sag_eroute(st, sr, ERO_REPLACE, "replace");
- }
-#if 0
- /* XXX - MCR. I previously felt that this was a bogus check */
- if (ero != NULL && ero != c && esr != sr)
- {
- /* By elimination, we must be eclipsing ero. Check. */
- passert(ero->kind == CK_TEMPLATE && streq(ero->name, c->name));
- passert(LHAS(LELEM(RT_ROUTED_PROSPECTIVE) | LELEM(RT_ROUTED_ECLIPSED)
- , esr->routing));
- passert(samesubnet(&esr->this.client, &sr->this.client)
- && samesubnet(&esr->that.client, &sr->that.client));
- }
-#endif
- }
- else
- {
- /* we're adding an eroute */
-
- /* if no state provided, then install a shunt for later */
- if (st == NULL)
- {
- eroute_installed = shunt_eroute(c, sr, RT_ROUTED_PROSPECTIVE
- , ERO_ADD, "add");
- }
- else
- {
- eroute_installed = sag_eroute(st, sr, ERO_ADD, "add");
- }
- }
-
- /* notify the firewall of a new tunnel */
-
- if (eroute_installed)
- {
- /* do we have to notify the firewall? Yes, if we are installing
- * a tunnel eroute and the firewall wasn't notified
- * for a previous tunnel with the same clients. Any Previous
- * tunnel would have to be for our connection, so the actual
- * test is simple.
- */
- firewall_notified = st == NULL /* not a tunnel eroute */
- || sr->eroute_owner != SOS_NOBODY /* already notified */
- || do_command(c, sr, st, "up"); /* go ahead and notify */
- }
-
- /* install the route */
-
- DBG(DBG_CONTROL,
- DBG_log("route_and_eroute: firewall_notified: %s"
- , firewall_notified ? "true" : "false"));
- if (!firewall_notified)
- {
- /* we're in trouble -- don't do routing */
- }
- else if (ro == NULL)
- {
- /* a new route: no deletion required, but preparation is */
- (void) do_command(c, sr, st, "prepare"); /* just in case; ignore failure */
- route_installed = do_command(c, sr, st, "route");
- }
- else if (routed(sr->routing) || routes_agree(ro, c))
- {
- route_installed = TRUE; /* nothing to be done */
- }
- else
- {
- /* Some other connection must own the route
- * and the route must disagree. But since could_route
- * must have allowed our stealing it, we'll do so.
- *
- * A feature of LINUX allows us to install the new route
- * before deleting the old if the nexthops differ.
- * This reduces the "window of vulnerability" when packets
- * might flow in the clear.
- */
- if (sameaddr(&sr->this.host_nexthop, &esr->this.host_nexthop))
- {
- (void) do_command(ro, sr, st, "unroute");
- route_installed = do_command(c, sr, st, "route");
- }
- else
- {
- route_installed = do_command(c, sr, st, "route");
- (void) do_command(ro, sr, st, "unroute");
- }
-
- /* record unrouting */
- if (route_installed)
- {
- do {
- passert(!erouted(rosr->routing));
- rosr->routing = RT_UNROUTED;
-
- /* no need to keep old value */
- ro = route_owner(c, &rosr, NULL, NULL);
- } while (ro != NULL);
- }
- }
-
- /* all done -- clean up */
- if (route_installed)
- {
- /* Success! */
-
- if (ero != NULL && ero != c)
- {
- /* check if ero is an ancestor of c. */
- connection_t *ero2;
-
- for (ero2 = c; ero2 != NULL && ero2 != c; ero2 = ero2->policy_next)
- ;
-
- if (ero2 == NULL)
- {
- /* By elimination, we must be eclipsing ero. Checked above. */
- if (ero->spd.routing != RT_ROUTED_ECLIPSED)
- {
- ero->spd.routing = RT_ROUTED_ECLIPSED;
- eclipse_count++;
- }
- }
- }
-
- if (st == NULL)
- {
- passert(sr->eroute_owner == SOS_NOBODY);
- sr->routing = RT_ROUTED_PROSPECTIVE;
- }
- else
- {
- char cib[CONN_INST_BUF];
- sr->routing = RT_ROUTED_TUNNEL;
-
- DBG(DBG_CONTROL,
- DBG_log("route_and_eroute: instance \"%s\"%s, setting eroute_owner {spd=%p,sr=%p} to #%ld (was #%ld) (newest_ipsec_sa=#%ld)"
- , st->st_connection->name
- , (fmt_conn_instance(st->st_connection, cib), cib)
- , &st->st_connection->spd, sr
- , st->st_serialno
- , sr->eroute_owner
- , st->st_connection->newest_ipsec_sa));
- sr->eroute_owner = st->st_serialno;
- }
-
- return TRUE;
- }
- else
- {
- /* Failure! Unwind our work. */
- if (firewall_notified && sr->eroute_owner == SOS_NOBODY)
- (void) do_command(c, sr, st, "down");
-
- if (eroute_installed)
- {
- /* Restore original eroute, if we can.
- * Since there is nothing much to be done if the restoration
- * fails, ignore success or failure.
- */
- if (ero != NULL)
- {
- /* restore ero's former glory */
- if (esr->eroute_owner == SOS_NOBODY)
- {
- /* note: normal or eclipse case */
- (void) shunt_eroute(ero, esr
- , esr->routing, ERO_REPLACE, "restore");
- }
- else
- {
- /* Try to find state that owned eroute.
- * Don't do anything if it cannot be found.
- * This case isn't likely since we don't run
- * the updown script when replacing a SA group
- * with its successor (for the same conn).
- */
- struct state *ost = state_with_serialno(esr->eroute_owner);
-
- if (ost != NULL)
- (void) sag_eroute(ost, esr, ERO_REPLACE, "restore");
- }
- }
- else
- {
- /* there was no previous eroute: delete whatever we installed */
- if (st == NULL)
- {
- (void) shunt_eroute(c, sr, sr->routing, ERO_DELETE, "delete");
- }
- else
- {
- (void) sag_eroute(st, sr, ERO_DELETE, "delete");
- }
- }
- }
-
- return FALSE;
- }
-}
-
-bool install_ipsec_sa(struct state *st, bool inbound_also)
-{
- struct spd_route *sr;
-
- DBG(DBG_CONTROL, DBG_log("install_ipsec_sa() for #%ld: %s"
- , st->st_serialno
- , inbound_also?
- "inbound and outbound" : "outbound only"));
-
- switch (could_route(st->st_connection))
- {
- case route_easy:
- case route_nearconflict:
- break;
- default:
- return FALSE;
- }
-
- /* (attempt to) actually set up the SA group */
- if ((inbound_also && !setup_half_ipsec_sa(st, TRUE)) ||
- !setup_half_ipsec_sa(st, FALSE))
- {
- return FALSE;
- }
-
- for (sr = &st->st_connection->spd; sr != NULL; sr = sr->next)
- {
- DBG(DBG_CONTROL, DBG_log("sr for #%ld: %s"
- , st->st_serialno
- , enum_name(&routing_story, sr->routing)));
-
- /*
- * if the eroute owner is not us, then make it us.
- * See test co-terminal-02, pluto-rekey-01, pluto-unit-02/oppo-twice
- */
- pexpect(sr->eroute_owner == SOS_NOBODY
- || sr->routing >= RT_ROUTED_TUNNEL);
-
- if (sr->eroute_owner != st->st_serialno
- && sr->routing != RT_UNROUTED_KEYED)
- {
- if (!route_and_eroute(st->st_connection, sr, st))
- {
- delete_ipsec_sa(st, FALSE);
- /* XXX go and unroute any SRs that were successfully
- * routed already.
- */
- return FALSE;
- }
- }
- }
-
- return TRUE;
-}
-
-/* delete an IPSEC SA.
- * we may not succeed, but we bull ahead anyway because
- * we cannot do anything better by recognizing failure
- */
-void delete_ipsec_sa(struct state *st, bool inbound_only)
-{
- if (!inbound_only)
- {
- /* If the state is the eroute owner, we must adjust
- * the routing for the connection.
- */
- connection_t *c = st->st_connection;
- struct spd_route *sr;
-
- passert(st->st_connection);
-
- for (sr = &c->spd; sr; sr = sr->next)
- {
- if (sr->eroute_owner == st->st_serialno
- && sr->routing == RT_ROUTED_TUNNEL)
- {
- sr->eroute_owner = SOS_NOBODY;
-
- /* Routing should become RT_ROUTED_FAILURE,
- * but if POLICY_FAIL_NONE, then we just go
- * right back to RT_ROUTED_PROSPECTIVE as if no
- * failure happened.
- */
- sr->routing = (c->policy & POLICY_FAIL_MASK) == POLICY_FAIL_NONE
- ? RT_ROUTED_PROSPECTIVE : RT_ROUTED_FAILURE;
-
- (void) do_command(c, sr, st, "down");
- if ((c->policy & POLICY_DONT_REKEY) && c->kind == CK_INSTANCE)
- {
- /* in this special case, even if the connection
- * is still alive (due to an ISAKMP SA),
- * we get rid of routing.
- * Even though there is still an eroute, the c->routing
- * setting will convince unroute_connection to delete it.
- * unroute_connection would be upset if c->routing == RT_ROUTED_TUNNEL
- */
- unroute_connection(c);
- }
- else
- {
- (void) shunt_eroute(c, sr, sr->routing, ERO_REPLACE, "replace with shunt");
- }
- }
- }
- (void) teardown_half_ipsec_sa(st, FALSE);
- }
- (void) teardown_half_ipsec_sa(st, TRUE);
-}
-
-static bool update_nat_t_ipsec_esp_sa (struct state *st, bool inbound)
-{
- connection_t *c = st->st_connection;
- host_t *host_src, *host_dst, *new_src, *new_dst;
- ipsec_spi_t spi = inbound ? st->st_esp.our_spi : st->st_esp.attrs.spi;
- struct end *src = inbound ? &c->spd.that : &c->spd.this,
- *dst = inbound ? &c->spd.this : &c->spd.that;
- mark_t mark = inbound ? c->spd.mark_in : c->spd.mark_out;
- bool result;
-
- host_src = host_create_from_sockaddr((sockaddr_t*)&src->host_addr);
- host_dst = host_create_from_sockaddr((sockaddr_t*)&dst->host_addr);
-
- new_src = host_src->clone(host_src);
- new_dst = host_dst->clone(host_dst);
- new_src->set_port(new_src, src->host_port);
- new_dst->set_port(new_dst, dst->host_port);
-
- result = hydra->kernel_interface->update_sa(hydra->kernel_interface,
- spi, IPPROTO_ESP, 0 /* cpi */, host_src, host_dst,
- new_src, new_dst, TRUE /* encap */, TRUE /* new_encap */,
- mark) == SUCCESS;
-
- host_src->destroy(host_src);
- host_dst->destroy(host_dst);
- new_src->destroy(new_src);
- new_dst->destroy(new_dst);
-
- return result;
-}
-
-bool update_ipsec_sa (struct state *st)
-{
- if (IS_IPSEC_SA_ESTABLISHED(st->st_state))
- {
- if (st->st_esp.present && (
- (!update_nat_t_ipsec_esp_sa (st, TRUE)) ||
- (!update_nat_t_ipsec_esp_sa (st, FALSE))))
- {
- return FALSE;
- }
- }
- else if (IS_ONLY_INBOUND_IPSEC_SA_ESTABLISHED(st->st_state))
- {
- if (st->st_esp.present && !update_nat_t_ipsec_esp_sa (st, FALSE))
- {
- return FALSE;
- }
- }
- else
- {
- DBG_log("assert failed at %s:%d st_state=%d", __FILE__, __LINE__, st->st_state);
- return FALSE;
- }
- return TRUE;
-}
-
-/* Check if there was traffic on given SA during the last idle_max
- * seconds. If TRUE, the SA was idle and DPD exchange should be performed.
- * If FALSE, DPD is not necessary. We also return TRUE for errors, as they
- * could mean that the SA is broken and needs to be replace anyway.
- */
-bool was_eroute_idle(struct state *st, time_t idle_max, time_t *idle_time)
-{
- time_t use_time;
- u_int bytes;
- int ret = TRUE;
-
- passert(st != NULL);
-
- if (get_sa_info(st, TRUE, &bytes, &use_time) && use_time != UNDEFINED_TIME)
- {
- *idle_time = time_monotonic(NULL) - use_time;
- ret = *idle_time >= idle_max;
- }
-
- return ret;
-}
diff --git a/src/pluto/kernel.h b/src/pluto/kernel.h
deleted file mode 100644
index 1fa11c50e..000000000
--- a/src/pluto/kernel.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/* declarations of routines that interface with the kernel's IPsec mechanism
- * Copyright (C) 1998-2001 D. Hugh Redelmeier.
- *
- * 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 "connections.h"
-
-extern bool can_do_IPcomp; /* can system actually perform IPCOMP? */
-
-/* Declare eroute things early enough for uses.
- *
- * Flags are encoded above the low-order byte of verbs.
- * "real" eroutes are only outbound. Inbound eroutes don't exist,
- * but an addflow with an INBOUND flag allows IPIP tunnels to be
- * limited to appropriate source and destination addresses.
- */
-
-#define ERO_MASK 0xFF
-#define ERO_FLAG_SHIFT 8
-
-#define ERO_DELETE SADB_X_DELFLOW
-#define ERO_ADD SADB_X_ADDFLOW
-#define ERO_REPLACE (SADB_X_ADDFLOW | (SADB_X_SAFLAGS_REPLACEFLOW << ERO_FLAG_SHIFT))
-
-struct pfkey_proto_info {
- int proto;
- int encapsulation;
- unsigned reqid;
-};
-struct sadb_msg;
-
-struct kernel_sa {
- const ip_address *src;
- const ip_address *dst;
-
- const ip_subnet *src_client;
- const ip_subnet *dst_client;
-
- ipsec_spi_t spi;
- unsigned proto;
- unsigned satype;
- unsigned transport_proto;
- unsigned replay_window;
- unsigned reqid;
-
- unsigned authalg;
- unsigned authkeylen;
- char *authkey;
-
- unsigned encalg;
- unsigned enckeylen;
- char *enckey;
-
- unsigned compalg;
-
- int encapsulation;
-
- u_int16_t natt_sport, natt_dport;
- u_int8_t transid, natt_type;
- ip_address *natt_oa;
-
- const char *text_said;
-};
-
-/* A netlink header defines EM_MAXRELSPIS, the max number of SAs in a group.
- * Is there a PF_KEY equivalent?
- */
-#ifndef EM_MAXRELSPIS
-# define EM_MAXRELSPIS 4 /* AH ESP IPCOMP IPIP */
-#endif
-
-extern void record_and_initiate_opportunistic(const ip_subnet *
- , const ip_subnet *
- , int transport_proto
- , const char *why);
-
-extern void init_kernel(void);
-extern void kernel_finalize(void);
-
-extern bool trap_connection(struct connection *c);
-extern void unroute_connection(struct connection *c);
-
-extern bool assign_hold(struct connection *c
- , struct spd_route *sr
- , int transport_proto
- , const ip_address *src, const ip_address *dst);
-
-extern ipsec_spi_t shunt_policy_spi(struct connection *c, bool prospective);
-
-
-struct state; /* forward declaration of tag */
-extern ipsec_spi_t get_ipsec_spi(ipsec_spi_t avoid
- , int proto
- , struct spd_route *sr
- , bool tunnel_mode);
-extern ipsec_spi_t get_my_cpi(struct spd_route *sr, bool tunnel_mode);
-
-extern bool install_inbound_ipsec_sa(struct state *st);
-extern bool install_ipsec_sa(struct state *st, bool inbound_also);
-extern void delete_ipsec_sa(struct state *st, bool inbound_only);
-extern bool route_and_eroute(struct connection *c
- , struct spd_route *sr
- , struct state *st);
-extern bool was_eroute_idle(struct state *st, time_t idle_max
- , time_t *idle_time);
-extern bool get_sa_info(struct state *st, bool inbound, u_int *bytes
- , time_t *use_time);
-
-extern bool update_ipsec_sa(struct state *st);
diff --git a/src/pluto/kernel_alg.c b/src/pluto/kernel_alg.c
deleted file mode 100644
index b4b18fd80..000000000
--- a/src/pluto/kernel_alg.c
+++ /dev/null
@@ -1,663 +0,0 @@
-/* Kernel runtime algorithm handling interface
- * Copyright (C) JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
- * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-#include <sys/queue.h>
-
-#include <pfkeyv2.h>
-#include <pfkey.h>
-
-#include <freeswan.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "connections.h"
-#include "state.h"
-#include "packet.h"
-#include "spdb.h"
-#include "kernel.h"
-#include "kernel_alg.h"
-#include "alg_info.h"
-#include "log.h"
-#include "whack.h"
-#include "db_ops.h"
-
-/* ALG storage */
-static struct sadb_alg esp_aalg[SADB_AALG_MAX+1];
-static struct sadb_alg esp_ealg[SADB_EALG_MAX+1];
-static int esp_ealg_num = 0;
-static int esp_aalg_num = 0;
-
-#define ESP_EALG_PRESENT(algo) (((algo)<=SADB_EALG_MAX)&&(esp_ealg[(algo)].sadb_alg_id==(algo)))
-#define ESP_EALG_FOR_EACH_UPDOWN(algo) \
- for (algo=SADB_EALG_MAX; algo >0 ; algo--) \
- if (ESP_EALG_PRESENT(algo))
-#define ESP_AALG_PRESENT(algo) ((algo<=SADB_AALG_MAX)&&(esp_aalg[(algo)].sadb_alg_id==(algo)))
-#define ESP_AALG_FOR_EACH_UPDOWN(algo) \
- for (algo=SADB_AALG_MAX; algo >0 ; algo--) \
- if (ESP_AALG_PRESENT(algo))
-
-static struct sadb_alg* sadb_alg_ptr (int satype, int exttype, int alg_id,
- int rw)
-{
- struct sadb_alg *alg_p = NULL;
-
- switch (exttype)
- {
- case SADB_EXT_SUPPORTED_AUTH:
- if (alg_id > SADB_AALG_MAX)
- return NULL;
- break;
- case SADB_EXT_SUPPORTED_ENCRYPT:
- if (alg_id > SADB_EALG_MAX)
- return NULL;
- break;
- default:
- return NULL;
- }
-
- switch (satype)
- {
- case SADB_SATYPE_ESP:
- alg_p = (exttype == SADB_EXT_SUPPORTED_ENCRYPT)?
- &esp_ealg[alg_id] : &esp_aalg[alg_id];
- /* get for write: increment elem count */
- if (rw)
- {
- (exttype == SADB_EXT_SUPPORTED_ENCRYPT)?
- esp_ealg_num++ : esp_aalg_num++;
- }
- break;
- case SADB_SATYPE_AH:
- default:
- return NULL;
- }
-
- return alg_p;
-}
-
-const struct sadb_alg* kernel_alg_sadb_alg_get(int satype, int exttype,
- int alg_id)
-{
- return sadb_alg_ptr(satype, exttype, alg_id, 0);
-}
-
-/*
- * Forget previous registration
- */
-static void kernel_alg_init(void)
-{
- DBG(DBG_KERNEL,
- DBG_log("alg_init(): memset(%p, 0, %d) memset(%p, 0, %d)",
- &esp_aalg, (int)sizeof (esp_aalg),
- &esp_ealg, (int)sizeof (esp_ealg))
- )
- memset (&esp_aalg, 0, sizeof (esp_aalg));
- memset (&esp_ealg, 0, sizeof (esp_ealg));
- esp_ealg_num=esp_aalg_num = 0;
-}
-
-static int kernel_alg_add(int satype, int exttype,
- const struct sadb_alg *sadb_alg)
-{
- struct sadb_alg *alg_p = NULL;
- int alg_id = sadb_alg->sadb_alg_id;
-
- DBG(DBG_KERNEL,
- DBG_log("kernel_alg_add(): satype=%d, exttype=%d, alg_id=%d",
- satype, exttype, sadb_alg->sadb_alg_id)
- )
- if (!(alg_p = sadb_alg_ptr(satype, exttype, alg_id, 1)))
- return -1;
-
- /* This logic "mimics" KLIPS: first algo implementation will be used */
- if (alg_p->sadb_alg_id)
- {
- DBG(DBG_KERNEL,
- DBG_log("kernel_alg_add(): discarding already setup "
- "satype=%d, exttype=%d, alg_id=%d",
- satype, exttype, sadb_alg->sadb_alg_id)
- )
- return 0;
- }
- *alg_p = *sadb_alg;
- return 1;
-}
-
-bool kernel_alg_esp_enc_ok(u_int alg_id, u_int key_len,
- struct alg_info_esp *alg_info __attribute__((unused)))
-{
- struct sadb_alg *alg_p = NULL;
-
- /*
- * test #1: encrypt algo must be present
- */
- int ret = ESP_EALG_PRESENT(alg_id);
- if (!ret) goto out;
-
- alg_p = &esp_ealg[alg_id];
-
- /*
- * test #2: if key_len specified, it must be in range
- */
- if (key_len
- && (key_len < alg_p->sadb_alg_minbits || key_len > alg_p->sadb_alg_maxbits))
- {
- plog("kernel_alg_db_add() key_len not in range: alg_id=%d, "
- "key_len=%d, alg_minbits=%d, alg_maxbits=%d"
- , alg_id, key_len
- , alg_p->sadb_alg_minbits
- , alg_p->sadb_alg_maxbits);
- ret = FALSE;
- }
-
-out:
- if (ret)
- {
- DBG(DBG_KERNEL,
- DBG_log("kernel_alg_esp_enc_ok(%d,%d): "
- "alg_id=%d, "
- "alg_ivlen=%d, alg_minbits=%d, alg_maxbits=%d, "
- "res=%d, ret=%d"
- , alg_id, key_len
- , alg_p->sadb_alg_id
- , alg_p->sadb_alg_ivlen
- , alg_p->sadb_alg_minbits
- , alg_p->sadb_alg_maxbits
- , alg_p->sadb_alg_reserved
- , ret);
- )
- }
- else
- {
- DBG(DBG_KERNEL,
- DBG_log("kernel_alg_esp_enc_ok(%d,%d): NO", alg_id, key_len);
- )
- }
- return ret;
-}
-
-/*
- * ML: make F_STRICT logic consider enc,auth algorithms
- */
-bool kernel_alg_esp_ok_final(u_int ealg, u_int key_len, u_int aalg,
- struct alg_info_esp *alg_info)
-{
- int ealg_insecure;
-
- /*
- * key_len passed comes from esp_attrs read from peer
- * For many older algorithms (eg 3DES) this key_len is fixed
- * and get passed as 0.
- * ... then get default key_len
- */
- if (key_len == 0)
- key_len = kernel_alg_esp_enc_keylen(ealg) * BITS_PER_BYTE;
-
- /*
- * simple test to toss low key_len, will accept it only
- * if specified in "esp" string
- */
- ealg_insecure = (key_len < 128) ;
-
- if (ealg_insecure
- || (alg_info && alg_info->alg_info_flags & ALG_INFO_F_STRICT))
- {
- int i;
- struct esp_info *esp_info;
-
- if (alg_info)
- {
- ALG_INFO_ESP_FOREACH(alg_info, esp_info, i)
- {
- if (esp_info->esp_ealg_id == ealg
- && (esp_info->esp_ealg_keylen == 0 || key_len == 0
- || esp_info->esp_ealg_keylen == key_len)
- && esp_info->esp_aalg_id == aalg)
- {
- if (ealg_insecure)
- {
- loglog(RC_LOG_SERIOUS
- , "You should NOT use insecure ESP algorithms [%s (%d)]!"
- , enum_name(&esp_transform_names, ealg), key_len);
- }
- return TRUE;
- }
- }
- }
- plog("IPSec Transform [%s (%d), %s] refused due to %s",
- enum_name(&esp_transform_names, ealg), key_len,
- enum_name(&auth_alg_names, aalg),
- ealg_insecure ? "insecure key_len and enc. alg. not listed in \"esp\" string" : "strict flag");
- return FALSE;
- }
- return TRUE;
-}
-
-/**
- * Load kernel_alg arrays pluto's SADB_REGISTER user by pluto/kernel.c
- */
-void kernel_alg_register_pfkey(const struct sadb_msg *msg_buf, int buflen)
-{
- /* Trick: one 'type-mangle-able' pointer to ease offset/assign */
- union {
- const struct sadb_msg *msg;
- const struct sadb_supported *supported;
- const struct sadb_ext *ext;
- const struct sadb_alg *alg;
- const char *ch;
- } sadb;
-
- int satype;
- int msglen;
- int i = 0;
-
- /* Initialize alg arrays */
- kernel_alg_init();
- satype = msg_buf->sadb_msg_satype;
- sadb.msg = msg_buf;
- msglen = sadb.msg->sadb_msg_len*IPSEC_PFKEYv2_ALIGN;
- msglen -= sizeof(struct sadb_msg);
- buflen -= sizeof(struct sadb_msg);
- passert(buflen > 0);
-
- sadb.msg++;
-
- while (msglen)
- {
- int supp_exttype = sadb.supported->sadb_supported_exttype;
- int supp_len = sadb.supported->sadb_supported_len*IPSEC_PFKEYv2_ALIGN;
-
- DBG(DBG_KERNEL,
- DBG_log("kernel_alg_register_pfkey(): SADB_SATYPE_%s: "
- "sadb_msg_len=%d sadb_supported_len=%d"
- , satype==SADB_SATYPE_ESP? "ESP" : "AH"
- , msg_buf->sadb_msg_len, supp_len)
- )
- sadb.supported++;
- msglen -= supp_len;
- buflen -= supp_len;
- passert(buflen >= 0);
-
- for (supp_len -= sizeof(struct sadb_supported);
- supp_len;
- supp_len -= sizeof(struct sadb_alg), sadb.alg++,i++)
- {
- kernel_alg_add(satype, supp_exttype, sadb.alg);
-
- DBG(DBG_KERNEL,
- DBG_log("kernel_alg_register_pfkey(): SADB_SATYPE_%s: "
- "alg[%d], exttype=%d, satype=%d, alg_id=%d, "
- "alg_ivlen=%d, alg_minbits=%d, alg_maxbits=%d, "
- "res=%d"
- , satype == SADB_SATYPE_ESP? "ESP" : "AH"
- , i
- , supp_exttype
- , satype
- , sadb.alg->sadb_alg_id
- , sadb.alg->sadb_alg_ivlen
- , sadb.alg->sadb_alg_minbits
- , sadb.alg->sadb_alg_maxbits
- , sadb.alg->sadb_alg_reserved)
- )
- /* if AES_CBC is registered then also register AES_CCM and AES_GCM */
- if (satype == SADB_SATYPE_ESP &&
- supp_exttype == SADB_EXT_SUPPORTED_ENCRYPT &&
- sadb.alg->sadb_alg_id == SADB_X_EALG_AESCBC)
- {
- struct sadb_alg alg = *sadb.alg;
- int alg_id;
-
- for (alg_id = SADB_X_EALG_AES_CCM_ICV8;
- alg_id <= SADB_X_EALG_AES_GCM_ICV16; alg_id++)
- {
- if (alg_id != ESP_UNASSIGNED_17)
- {
- alg.sadb_alg_id = alg_id;
- kernel_alg_add(satype, supp_exttype, &alg);
- }
- }
-
- /* also register AES_GMAC */
- alg.sadb_alg_id = SADB_X_EALG_NULL_AES_GMAC;
- kernel_alg_add(satype, supp_exttype, &alg);
- }
- /* if SHA2_256 is registered then also register SHA2_256_96 */
- if (satype == SADB_SATYPE_ESP &&
- supp_exttype == SADB_EXT_SUPPORTED_AUTH &&
- sadb.alg->sadb_alg_id == SADB_X_AALG_SHA2_256HMAC)
- {
- struct sadb_alg alg = *sadb.alg;
-
- alg.sadb_alg_id = SADB_X_AALG_SHA2_256_96HMAC;
- kernel_alg_add(satype, supp_exttype, &alg);
- }
- }
- }
-}
-
-u_int kernel_alg_esp_enc_keylen(u_int alg_id)
-{
- u_int keylen = 0;
-
- if (!ESP_EALG_PRESENT(alg_id))
- {
- goto none;
- }
- keylen = esp_ealg[alg_id].sadb_alg_maxbits/BITS_PER_BYTE;
-
- switch (alg_id)
- {
- /*
- * this is veryUgly[TM]
- * Peer should have sent KEY_LENGTH attribute for ESP_AES
- * but if not do force it to 128 instead of using sadb_alg_maxbits
- * from kernel.
- */
- case ESP_AES:
- keylen = 128/BITS_PER_BYTE;
- break;
- }
-
-none:
- DBG(DBG_KERNEL,
- DBG_log("kernel_alg_esp_enc_keylen(): alg_id=%d, keylen=%d",
- alg_id, keylen)
- )
- return keylen;
-}
-
-struct sadb_alg* kernel_alg_esp_sadb_alg(u_int alg_id)
-{
- struct sadb_alg *sadb_alg = (ESP_EALG_PRESENT(alg_id))
- ? &esp_ealg[alg_id] : NULL;
-
- DBG(DBG_KERNEL,
- DBG_log("kernel_alg_esp_sadb_alg(): alg_id=%d, sadb_alg=%p"
- , alg_id, sadb_alg)
- )
- return sadb_alg;
-}
-
-/**
- * Print the name of a kernel algorithm
- */
-static void print_alg(char *buf, int *len, enum_names *alg_names, int alg_type)
-{
- char alg_name[BUF_LEN];
- int alg_name_len;
-
- alg_name_len = sprintf(alg_name, " %s", enum_name(alg_names, alg_type));
- if (*len + alg_name_len > CRYPTO_MAX_ALG_LINE)
- {
- whack_log(RC_COMMENT, "%s", buf);
- *len = sprintf(buf, " ");
- }
- sprintf(buf + *len, "%s", alg_name);
- *len += alg_name_len;
-}
-
-void kernel_alg_list(void)
-{
- char buf[BUF_LEN];
- int len;
- u_int sadb_id;
-
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, "List of registered ESP Algorithms:");
- whack_log(RC_COMMENT, " ");
-
- len = sprintf(buf, " encryption:");
- for (sadb_id = 1; sadb_id <= SADB_EALG_MAX; sadb_id++)
- {
- if (ESP_EALG_PRESENT(sadb_id))
- {
- print_alg(buf, &len, &esp_transform_names, sadb_id);
- }
- }
- whack_log(RC_COMMENT, "%s", buf);
-
- len = sprintf(buf, " integrity: ");
- for (sadb_id = 1; sadb_id <= SADB_AALG_MAX; sadb_id++)
- {
- if (ESP_AALG_PRESENT(sadb_id))
- {
- u_int aaid = alg_info_esp_sadb2aa(sadb_id);
-
- print_alg(buf, &len, &auth_alg_names, aaid);
- }
- }
- whack_log(RC_COMMENT, "%s", buf);
-}
-
-void kernel_alg_show_connection(connection_t *c, const char *instance)
-{
- struct state *st = state_with_serialno(c->newest_ipsec_sa);
-
- if (st && st->st_esp.present)
- {
- const char *aalg_name, *pfsgroup_name;
-
- aalg_name = (c->policy & POLICY_AUTHENTICATE) ?
- enum_show(&ah_transform_names, st->st_ah.attrs.transid):
- enum_show(&auth_alg_names, st->st_esp.attrs.auth);
-
- pfsgroup_name = (c->policy & POLICY_PFS) ?
- (c->alg_info_esp && c->alg_info_esp->esp_pfsgroup) ?
- enum_show(&oakley_group_names,
- c->alg_info_esp->esp_pfsgroup) :
- "<Phase1>" : "<N/A>";
-
- if (st->st_esp.attrs.key_len)
- {
- whack_log(RC_COMMENT, "\"%s\"%s: ESP%s proposal: %s_%u/%s/%s",
- c->name, instance,
- (st->st_ah.present) ? "/AH" : "",
- enum_show(&esp_transform_names, st->st_esp.attrs.transid),
- st->st_esp.attrs.key_len, aalg_name, pfsgroup_name);
- }
- else
- {
- whack_log(RC_COMMENT, "\"%s\"%s: ESP%s proposal: %s/%s/%s",
- c->name, instance,
- (st->st_ah.present) ? "/AH" : "",
- enum_show(&esp_transform_names, st->st_esp.attrs.transid),
- aalg_name, pfsgroup_name);
- }
- }
-}
-
-bool kernel_alg_esp_auth_ok(u_int auth,
- struct alg_info_esp *alg_info __attribute__((unused)))
-{
- return ESP_AALG_PRESENT(alg_info_esp_aa2sadb(auth));
-}
-
-u_int kernel_alg_esp_auth_keylen(u_int auth)
-{
- u_int sadb_aalg = alg_info_esp_aa2sadb(auth);
-
- u_int a_keylen = (sadb_aalg)
- ? esp_aalg[sadb_aalg].sadb_alg_maxbits/BITS_PER_BYTE
- : 0;
-
- DBG(DBG_CONTROL | DBG_CRYPT | DBG_PARSING,
- DBG_log("kernel_alg_esp_auth_keylen(auth=%d, sadb_aalg=%d): "
- "a_keylen=%d", auth, sadb_aalg, a_keylen)
- )
- return a_keylen;
-}
-
-struct esp_info* kernel_alg_esp_info(int transid, int auth)
-{
- int sadb_aalg, sadb_ealg;
- static struct esp_info ei_buf;
-
- sadb_ealg = transid;
- sadb_aalg = alg_info_esp_aa2sadb(auth);
-
- if (!ESP_EALG_PRESENT(sadb_ealg))
- goto none;
- if (!ESP_AALG_PRESENT(sadb_aalg))
- goto none;
-
- memset(&ei_buf, 0, sizeof (ei_buf));
- ei_buf.transid = transid;
- ei_buf.auth = auth;
-
- /* don't return "default" keylen because this value is used from
- * setup_half_ipsec_sa() to "validate" keylen
- * In effect, enckeylen will be used as "max" value
- */
- ei_buf.enckeylen = esp_ealg[sadb_ealg].sadb_alg_maxbits/BITS_PER_BYTE;
- ei_buf.authkeylen = esp_aalg[sadb_aalg].sadb_alg_maxbits/BITS_PER_BYTE;
- ei_buf.encryptalg = sadb_ealg;
- ei_buf.authalg = sadb_aalg;
-
- DBG(DBG_PARSING,
- DBG_log("kernel_alg_esp_info():"
- "transid=%d, auth=%d, ei=%p, "
- "enckeylen=%d, authkeylen=%d, encryptalg=%d, authalg=%d",
- transid, auth, &ei_buf,
- (int)ei_buf.enckeylen, (int)ei_buf.authkeylen,
- ei_buf.encryptalg, ei_buf.authalg)
- )
- return &ei_buf;
-
-none:
- DBG(DBG_PARSING,
- DBG_log("kernel_alg_esp_info():"
- "transid=%d, auth=%d, ei=NULL",
- transid, auth)
- )
- return NULL;
-}
-
-static void kernel_alg_policy_algorithms(struct esp_info *esp_info)
-{
- u_int ealg_id = esp_info->esp_ealg_id;
-
- switch(ealg_id)
- {
- case 0:
- case ESP_DES:
- case ESP_3DES:
- case ESP_NULL:
- case ESP_CAST:
- break;
- default:
- if (!esp_info->esp_ealg_keylen)
- {
- /* algos that need KEY_LENGTH
- *
- * Note: this is a very dirty hack ;-)
- * Idea: Add a key_length_needed attribute to
- * esp_ealg ??
- */
- esp_info->esp_ealg_keylen = esp_ealg[ealg_id].sadb_alg_maxbits;
- }
- }
-}
-
-static bool kernel_alg_db_add(struct db_context *db_ctx,
- struct esp_info *esp_info, lset_t policy)
-{
- u_int ealg_id, aalg_id;
-
- ealg_id = esp_info->esp_ealg_id;
-
- if (!ESP_EALG_PRESENT(ealg_id))
- {
- DBG_log("kernel_alg_db_add() kernel enc ealg_id=%d not present", ealg_id);
- return FALSE;
- }
-
- if (!(policy & POLICY_AUTHENTICATE) && /* skip ESP auth attrs for AH */
- esp_info->esp_aalg_id != AUTH_ALGORITHM_NONE)
- {
- aalg_id = alg_info_esp_aa2sadb(esp_info->esp_aalg_id);
-
- if (!ESP_AALG_PRESENT(aalg_id))
- {
- DBG_log("kernel_alg_db_add() kernel auth aalg_id=%d not present",
- aalg_id);
- return FALSE;
- }
- }
-
- /* do algo policy */
- kernel_alg_policy_algorithms(esp_info);
-
- /* open new transformation */
- db_trans_add(db_ctx, ealg_id);
-
- /* add ESP auth attr if not AH or AEAD */
- if (!(policy & POLICY_AUTHENTICATE) &&
- esp_info->esp_aalg_id != AUTH_ALGORITHM_NONE)
- {
- db_attr_add_values(db_ctx, AUTH_ALGORITHM, esp_info->esp_aalg_id);
- }
-
- /* add keylength if specified in esp= string */
- if (esp_info->esp_ealg_keylen)
- {
- db_attr_add_values(db_ctx, KEY_LENGTH, esp_info->esp_ealg_keylen);
- }
-
- return TRUE;
-}
-
-/*
- * Create proposal with runtime kernel algos, merging
- * with passed proposal if not NULL
- *
- * for now this function does free() previous returned
- * malloced pointer (this quirk allows easier spdb.c change)
- */
-struct db_context* kernel_alg_db_new(struct alg_info_esp *alg_info,
- lset_t policy)
-{
- const struct esp_info *esp_info;
- struct esp_info tmp_esp_info;
- struct db_context *ctx_new = NULL;
- u_int trans_cnt = esp_ealg_num * esp_aalg_num;
-
- if (!(policy & POLICY_ENCRYPT)) /* not possible, I think */
- {
- return NULL;
- }
-
- /* pass aprox. number of transforms and attributes */
- ctx_new = db_prop_new(PROTO_IPSEC_ESP, trans_cnt, trans_cnt * 2);
-
- if (alg_info)
- {
- int i;
-
- ALG_INFO_ESP_FOREACH(alg_info, esp_info, i)
- {
- tmp_esp_info = *esp_info;
- kernel_alg_db_add(ctx_new, &tmp_esp_info, policy);
- }
- }
- return ctx_new;
-}
-
diff --git a/src/pluto/kernel_alg.h b/src/pluto/kernel_alg.h
deleted file mode 100644
index 4c757db41..000000000
--- a/src/pluto/kernel_alg.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* Kernel runtime algorithm handling interface definitions
- * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
- *
- * 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.
- */
-
-#ifndef _KERNEL_ALG_H
-#define _KERNEL_ALG_H
-
-#include "alg_info.h"
-#include "spdb.h"
-
-/* status info */
-extern void kernel_alg_show_status(void);
-void kernel_alg_show_connection(struct connection *c, const char *instance);
-
-/* Registration messages from pluto */
-extern void kernel_alg_register_pfkey(const struct sadb_msg *msg, int buflen);
-
-/* ESP interface */
-extern struct sadb_alg *kernel_alg_esp_sadb_alg(u_int alg_id);
-extern u_int kernel_alg_esp_ivlen(u_int alg_id);
-extern bool kernel_alg_esp_enc_ok(u_int alg_id, u_int key_len, struct alg_info_esp *nfo);
-extern bool kernel_alg_esp_ok_final(u_int ealg, u_int key_len, u_int aalg, struct alg_info_esp *alg_info);
-extern u_int kernel_alg_esp_enc_keylen(u_int alg_id);
-extern bool kernel_alg_esp_auth_ok(u_int auth, struct alg_info_esp *nfo);
-extern u_int kernel_alg_esp_auth_keylen(u_int auth);
-extern void kernel_alg_list(void);
-
-/* get sadb_alg for passed args */
-extern const struct sadb_alg * kernel_alg_sadb_alg_get(int satype, int exttype, int alg_id);
-
-extern struct db_context * kernel_alg_db_new(struct alg_info_esp *ai, lset_t policy);
-struct esp_info * kernel_alg_esp_info(int esp_id, int auth_id);
-#endif /* _KERNEL_ALG_H */
diff --git a/src/pluto/kernel_pfkey.c b/src/pluto/kernel_pfkey.c
deleted file mode 100644
index 77fff2f9e..000000000
--- a/src/pluto/kernel_pfkey.c
+++ /dev/null
@@ -1,380 +0,0 @@
-/*
- * Copyright (C) 2010 Tobias Brunner
- * Hochschule fuer Technik Rapperswil
- * Copyright (C) 2003 Herbert Xu.
- * Copyright (C) 1998-2002 D. Hugh Redelmeier.
- * Copyright (C) 1997 Angelos D. Keromytis.
- *
- * 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 <errno.h>
-#include <unistd.h>
-
-#include <sys/select.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-
-#include <freeswan.h>
-#include <pfkeyv2.h>
-#include <pfkey.h>
-
-#include "constants.h"
-#include "kernel.h"
-#include "kernel_pfkey.h"
-#include "log.h"
-#include "whack.h" /* for RC_LOG_SERIOUS */
-#include "kernel_alg.h"
-
-
-static int pfkeyfd = NULL_FD;
-
-typedef u_int32_t pfkey_seq_t;
-static pfkey_seq_t pfkey_seq = 0; /* sequence number for our PF_KEY messages */
-
-static pid_t pid;
-
-#define NE(x) { x, #x } /* Name Entry -- shorthand for sparse_names */
-
-static sparse_names pfkey_type_names = {
- NE(SADB_RESERVED),
- NE(SADB_GETSPI),
- NE(SADB_UPDATE),
- NE(SADB_ADD),
- NE(SADB_DELETE),
- NE(SADB_GET),
- NE(SADB_ACQUIRE),
- NE(SADB_REGISTER),
- NE(SADB_EXPIRE),
- NE(SADB_FLUSH),
- NE(SADB_DUMP),
- NE(SADB_X_PROMISC),
- NE(SADB_X_PCHANGE),
- NE(SADB_X_GRPSA),
- NE(SADB_X_ADDFLOW),
- NE(SADB_X_DELFLOW),
- NE(SADB_X_DEBUG),
- NE(SADB_X_NAT_T_NEW_MAPPING),
- NE(SADB_MAX),
- { 0, sparse_end }
-};
-
-#undef NE
-
-typedef union {
- unsigned char bytes[PFKEYv2_MAX_MSGSIZE];
- struct sadb_msg msg;
- } pfkey_buf;
-
-static bool
-pfkey_input_ready(void)
-{
- int ndes;
- fd_set readfds;
- struct timeval tm = { .tv_sec = 0 }; /* don't wait, polling */
-
- FD_ZERO(&readfds); /* we only care about pfkeyfd */
- FD_SET(pfkeyfd, &readfds);
-
- do {
- ndes = select(pfkeyfd + 1, &readfds, NULL, NULL, &tm);
- } while (ndes == -1 && errno == EINTR);
-
- if (ndes < 0)
- {
- log_errno((e, "select() failed in pfkey_get()"));
- return FALSE;
- }
- else if (ndes == 0)
- {
- return FALSE; /* nothing to read */
- }
- passert(ndes == 1 && FD_ISSET(pfkeyfd, &readfds));
- return TRUE;
-}
-
-/* get a PF_KEY message from kernel.
- * Returns TRUE if message found, FALSE if no message pending,
- * and aborts or keeps trying when an error is encountered.
- * The only validation of the message is that the message length
- * received matches that in the message header, and that the message
- * is for this process.
- */
-static bool
-pfkey_get(pfkey_buf *buf)
-{
- for (;;)
- {
- /* len must be less than PFKEYv2_MAX_MSGSIZE,
- * so it should fit in an int. We use this fact when printing it.
- */
- ssize_t len;
-
- if (!pfkey_input_ready())
- {
- return FALSE;
- }
-
- len = read(pfkeyfd, buf->bytes, sizeof(buf->bytes));
-
- if (len < 0)
- {
- if (errno == EAGAIN)
- {
- return FALSE;
- }
- log_errno((e, "read() failed in pfkey_get()"));
- return FALSE;
- }
- else if ((size_t)len < sizeof(buf->msg))
- {
- plog("pfkey_get read truncated PF_KEY message: %d bytes; ignoring",
- (int)len);
- }
- else if ((size_t)len != buf->msg.sadb_msg_len * IPSEC_PFKEYv2_ALIGN)
- {
- plog("pfkey_get read PF_KEY message with length %d that doesn't"
- " equal sadb_msg_len %u * %u; ignoring message", (int)len,
- (unsigned)buf->msg.sadb_msg_len, (unsigned)IPSEC_PFKEYv2_ALIGN);
- }
- else if (buf->msg.sadb_msg_pid != (unsigned)pid)
- {
- /* not for us: ignore */
- DBG(DBG_KERNEL,
- DBG_log("pfkey_get: ignoring PF_KEY %s message %u for process"
- " %u", sparse_val_show(pfkey_type_names,
- buf->msg.sadb_msg_type),
- buf->msg.sadb_msg_seq, buf->msg.sadb_msg_pid));
- }
- else
- {
- DBG(DBG_KERNEL,
- DBG_log("pfkey_get: %s message %u",
- sparse_val_show(pfkey_type_names,
- buf->msg.sadb_msg_type),
- buf->msg.sadb_msg_seq));
- return TRUE;
- }
- }
-}
-
-/* get a response to a specific message */
-static bool
-pfkey_get_response(pfkey_buf *buf, pfkey_seq_t seq)
-{
- while (pfkey_get(buf))
- {
- if (buf->msg.sadb_msg_seq == seq)
- {
- return TRUE;
- }
- }
- return FALSE;
-}
-
-static bool
-pfkey_build(int error, const char *description, const char *text_said,
- struct sadb_ext *extensions[SADB_EXT_MAX + 1])
-{
- if (error != 0)
- {
- loglog(RC_LOG_SERIOUS, "building of %s %s failed, code %d", description,
- text_said, error);
- pfkey_extensions_free(extensions);
- return FALSE;
- }
- return TRUE;
-}
-
-/* pfkey_extensions_init + pfkey_build + pfkey_msg_hdr_build */
-static bool
-pfkey_msg_start(u_int8_t msg_type, u_int8_t satype, const char *description,
- const char *text_said,
- struct sadb_ext *extensions[SADB_EXT_MAX + 1])
-{
- pfkey_extensions_init(extensions);
- return pfkey_build(pfkey_msg_hdr_build(&extensions[0], msg_type, satype, 0,
- ++pfkey_seq, pid),
- description, text_said, extensions);
-}
-
-/* Finish (building, sending, accepting response for) PF_KEY message.
- * If response isn't NULL, the response from the kernel will be
- * placed there (and its errno field will not be examined).
- * Returns TRUE iff all appears well.
- */
-static bool
-finish_pfkey_msg(struct sadb_ext *extensions[SADB_EXT_MAX + 1],
- const char *description, const char *text_said,
- pfkey_buf *response)
-{
- struct sadb_msg *pfkey_msg;
- bool success = TRUE;
- int error;
-
- error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_IN);
-
- if (error != 0)
- {
- loglog(RC_LOG_SERIOUS, "pfkey_msg_build of %s %s failed, code %d",
- description, text_said, error);
- success = FALSE;
- }
- else
- {
- size_t len = pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN;
-
- DBG(DBG_KERNEL,
- DBG_log("finish_pfkey_msg: %s message %u for %s %s",
- sparse_val_show(pfkey_type_names, pfkey_msg->sadb_msg_type),
- pfkey_msg->sadb_msg_seq, description, text_said);
- DBG_dump(NULL, (void *) pfkey_msg, len));
-
- ssize_t r = write(pfkeyfd, pfkey_msg, len);
-
- if (r != (ssize_t)len)
- {
- if (r < 0)
- {
- log_errno((e, "pfkey write() of %s message %u for %s %s"
- " failed", sparse_val_show(pfkey_type_names,
- pfkey_msg->sadb_msg_type), pfkey_msg->sadb_msg_seq,
- description, text_said));
- }
- else
- {
- loglog(RC_LOG_SERIOUS, "ERROR: pfkey write() of %s message"
- " %u for %s %s truncated: %ld instead of %ld",
- sparse_val_show(pfkey_type_names,
- pfkey_msg->sadb_msg_type), pfkey_msg->sadb_msg_seq,
- description, text_said, (long)r, (long)len);
- }
- success = FALSE;
-
- /* if we were compiled with debugging, but we haven't already
- * dumped the command, do so.
- */
-#ifdef DEBUG
- if ((cur_debugging & DBG_KERNEL) == 0)
- DBG_dump(NULL, (void *) pfkey_msg, len);
-#endif
- }
- else
- {
- /* Check response from kernel.
- * It ought to be an echo, perhaps with additional info.
- * If the caller wants it, response will point to space.
- */
- pfkey_buf b;
- pfkey_buf *bp = response != NULL? response : &b;
-
- if (!pfkey_get_response(bp,
- ((struct sadb_msg *)extensions[0])->sadb_msg_seq))
- {
- loglog(RC_LOG_SERIOUS, "ERROR: no response to our PF_KEY %s"
- " message for %s %s", sparse_val_show(pfkey_type_names,
- pfkey_msg->sadb_msg_type), description, text_said);
- success = FALSE;
- }
- else if (pfkey_msg->sadb_msg_type != bp->msg.sadb_msg_type)
- {
- loglog(RC_LOG_SERIOUS, "ERROR: response to our PF_KEY %s"
- " message for %s %s was of wrong type (%s)",
- sparse_name(pfkey_type_names, pfkey_msg->sadb_msg_type),
- description, text_said, sparse_val_show(pfkey_type_names,
- bp->msg.sadb_msg_type));
- success = FALSE;
- }
- else if (response == NULL && bp->msg.sadb_msg_errno != 0)
- {
- /* Kernel is signalling a problem */
- loglog(RC_LOG_SERIOUS, "ERROR: PF_KEY %s response for %s %s"
- " included errno %u: %s",
- sparse_val_show(pfkey_type_names,
- pfkey_msg->sadb_msg_type), description, text_said,
- (unsigned) bp->msg.sadb_msg_errno,
- strerror(bp->msg.sadb_msg_errno));
- success = FALSE;
- }
- }
- }
- pfkey_extensions_free(extensions);
- pfkey_msg_free(&pfkey_msg);
- return success;
-}
-
-/* Process a SADB_REGISTER message from the kernel.
- * This will be a response to one of ours, but it may be asynchronous
- * (if kernel modules are loaded and unloaded).
- * Some sanity checking has already been performed.
- */
-static void
-pfkey_register_response(const struct sadb_msg *msg)
-{
- /* Find out what the kernel can support.
- */
- switch (msg->sadb_msg_satype)
- {
- case SADB_SATYPE_ESP:
-#ifndef NO_KERNEL_ALG
- kernel_alg_register_pfkey(msg, sizeof (pfkey_buf));
-#endif
- break;
- case SADB_X_SATYPE_IPCOMP:
- /* ??? There ought to be an extension to list the
- * supported algorithms, but RFC 2367 doesn't
- * list one for IPcomp.
- */
- can_do_IPcomp = TRUE;
- break;
- default:
- break;
- }
-}
-
-/** register SA types that can be negotiated */
-static void
-pfkey_register_proto(unsigned satype, const char *satypename)
-{
- struct sadb_ext *extensions[SADB_EXT_MAX + 1];
- pfkey_buf pfb;
-
- if (!(pfkey_msg_start(SADB_REGISTER, satype, satypename, NULL, extensions)
- && finish_pfkey_msg(extensions, satypename, "", &pfb)))
- {
- /* ??? should this be loglog */
- plog("no kernel support for %s", satypename);
- }
- else
- {
- pfkey_register_response(&pfb.msg);
- DBG(DBG_KERNEL,
- DBG_log("%s registered with kernel.", satypename));
- }
-}
-
-void
-pfkey_register(void)
-{
- pid = getpid();
-
- pfkeyfd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
- if (pfkeyfd == -1)
- {
- exit_log_errno((e, "socket() in init_pfkeyfd()"));
- }
-
- pfkey_register_proto(SADB_SATYPE_AH, "AH");
- pfkey_register_proto(SADB_SATYPE_ESP, "ESP");
- pfkey_register_proto(SADB_X_SATYPE_IPCOMP, "IPCOMP");
-
- close(pfkeyfd);
-}
diff --git a/src/pluto/kernel_pfkey.h b/src/pluto/kernel_pfkey.h
deleted file mode 100644
index b50ad6c37..000000000
--- a/src/pluto/kernel_pfkey.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2010 Tobias Brunner
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * Register our capabilities via PF_KEY, also learn the kernel's capabilities,
- * i.e. the supported algorithms.
- */
-void pfkey_register();
diff --git a/src/pluto/keys.c b/src/pluto/keys.c
deleted file mode 100644
index c5adbfd11..000000000
--- a/src/pluto/keys.c
+++ /dev/null
@@ -1,1474 +0,0 @@
-/* mechanisms for preshared keys (public, private, and preshared secrets)
- * Copyright (C) 1998-2001 D. Hugh Redelmeier.
- * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <errno.h>
-#include <time.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <resolv.h>
-#include <arpa/nameser.h> /* missing from <resolv.h> on old systems */
-#include <sys/queue.h>
-
-#ifdef HAVE_GLOB_H
-#include <glob.h>
-#ifndef GLOB_ABORTED
-# define GLOB_ABORTED GLOB_ABEND /* fix for old versions */
-#endif
-#endif
-
-#include <freeswan.h>
-
-#include <library.h>
-#include <asn1/asn1.h>
-#include <credentials/certificates/pgp_certificate.h>
-#include <credentials/sets/mem_cred.h>
-#include <credentials/sets/callback_cred.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "x509.h"
-#include "certs.h"
-#include "smartcard.h"
-#include "connections.h"
-#include "state.h"
-#include "lex.h"
-#include "keys.h"
-#include "adns.h" /* needs <resolv.h> */
-#include "dnskey.h" /* needs keys.h and adns.h */
-#include "log.h"
-#include "whack.h" /* for RC_LOG_SERIOUS */
-#include "timer.h"
-#include "fetch.h"
-
-const char *shared_secrets_file = SHARED_SECRETS_FILE;
-
-
-typedef enum secret_kind_t secret_kind_t;
-
-enum secret_kind_t {
- SECRET_PSK,
- SECRET_PUBKEY,
- SECRET_XAUTH,
- SECRET_PIN
-};
-
-typedef struct secret_t secret_t;
-
-struct secret_t {
- linked_list_t *ids;
- secret_kind_t kind;
- union {
- chunk_t preshared_secret;
- private_key_t *private_key;
- smartcard_t *smartcard;
- } u;
- secret_t *next;
-};
-
-/*
- * free a public key struct
- */
-static void free_public_key(pubkey_t *pk)
-{
- DESTROY_IF(pk->id);
- DESTROY_IF(pk->public_key);
- DESTROY_IF(pk->issuer);
- free(pk->serial.ptr);
- free(pk);
-}
-
-secret_t *secrets = NULL;
-
-/**
- * Find the secret associated with the combination of me and the peer.
- */
-const secret_t* match_secret(identification_t *my_id, identification_t *his_id,
- secret_kind_t kind)
-{
- enum { /* bits */
- match_default = 0x01,
- match_him = 0x02,
- match_me = 0x04
- };
-
- unsigned int best_match = 0;
- secret_t *s, *best = NULL;
-
- for (s = secrets; s != NULL; s = s->next)
- {
- unsigned int match = 0;
-
- if (s->kind != kind)
- {
- continue;
- }
-
- if (s->ids->get_count(s->ids) == 0)
- {
- /* a default (signified by lack of ids):
- * accept if no more specific match found
- */
- match = match_default;
- }
- else
- {
- /* check if both ends match ids */
- enumerator_t *enumerator;
- identification_t *id;
-
- enumerator = s->ids->create_enumerator(s->ids);
- while (enumerator->enumerate(enumerator, &id))
- {
- if (my_id->equals(my_id, id))
- {
- match |= match_me;
- }
- if (his_id->equals(his_id, id))
- {
- match |= match_him;
- }
- }
- enumerator->destroy(enumerator);
-
- /* If our end matched the only id in the list,
- * default to matching any peer.
- * A more specific match will trump this.
- */
- if (match == match_me && s->ids->get_count(s->ids) == 1)
- {
- match |= match_default;
- }
- }
-
- switch (match)
- {
- case match_me:
- /* if this is an asymmetric (eg. public key) system,
- * allow this-side-only match to count, even if
- * there are other ids in the list.
- */
- if (kind != SECRET_PUBKEY)
- {
- break;
- }
- /* FALLTHROUGH */
- case match_default: /* default all */
- case match_me | match_default: /* default peer */
- case match_me | match_him: /* explicit */
- if (match == best_match)
- {
- /* two good matches are equally good: do they agree? */
- bool same = FALSE;
-
- switch (kind)
- {
- case SECRET_PSK:
- case SECRET_XAUTH:
- same = chunk_equals(s->u.preshared_secret,
- best->u.preshared_secret);
- break;
- case SECRET_PUBKEY:
- same = s->u.private_key->equals(s->u.private_key,
- best->u.private_key);
- break;
- default:
- bad_case(kind);
- }
- if (!same)
- {
- loglog(RC_LOG_SERIOUS, "multiple ipsec.secrets entries with "
- "distinct secrets match endpoints: first secret used");
- best = s; /* list is backwards: take latest in list */
- }
- }
- else if (match > best_match)
- {
- /* this is the best match so far */
- best_match = match;
- best = s;
- }
- }
- }
- return best;
-}
-
-/**
- * Retrieves an XAUTH secret primarily based on the user ID and
- * secondarily based on the server ID
- */
-bool get_xauth_secret(identification_t *user, identification_t *server,
- chunk_t *secret)
-{
- const secret_t *s;
-
- s = match_secret(user, server, SECRET_XAUTH);
- if (s)
- {
- *secret = chunk_clone(s->u.preshared_secret);
- return TRUE;
- }
- else
- {
- *secret = chunk_empty;
- return FALSE;
- }
-}
-
-/**
- * We match the ID (if none, the IP address). Failure is indicated by a NULL.
- */
-static const secret_t* get_secret(const connection_t *c, secret_kind_t kind)
-{
- identification_t *my_id, *his_id;
- const secret_t *best;
-
- my_id = c->spd.this.id;
-
- if (his_id_was_instantiated(c))
- {
- /* roadwarrior: replace him with 0.0.0.0 */
- his_id = identification_create_from_string("%any");
- }
- else if (kind == SECRET_PSK && (c->policy & (POLICY_PSK | POLICY_XAUTH_PSK)) &&
- ((c->kind == CK_TEMPLATE &&
- c->spd.that.id->get_type(c->spd.that.id) == ID_ANY) ||
- (c->kind == CK_INSTANCE && id_is_ipaddr(c->spd.that.id))))
- {
- /* roadwarrior: replace him with 0.0.0.0 */
- his_id = identification_create_from_string("%any");
- }
- else
- {
- his_id = c->spd.that.id->clone(c->spd.that.id);
- }
-
- best = match_secret(my_id, his_id, kind);
-
- his_id->destroy(his_id);
- return best;
-}
-
-/* find the appropriate preshared key (see get_secret).
- * Failure is indicated by a NULL pointer.
- * Note: the result is not to be freed by the caller.
- */
-const chunk_t* get_preshared_secret(const connection_t *c)
-{
- const secret_t *s = get_secret(c, SECRET_PSK);
-
- DBG(DBG_PRIVATE,
- if (s == NULL)
- DBG_log("no Preshared Key Found");
- else
- DBG_dump_chunk("Preshared Key", s->u.preshared_secret);
- )
- return s == NULL? NULL : &s->u.preshared_secret;
-}
-
-/* check the existence of a private key matching a public key contained
- * in an X.509 or OpenPGP certificate
- */
-bool has_private_key(cert_t *cert)
-{
- secret_t *s;
- bool has_key = FALSE;
- public_key_t *pub_key = cert->cert->get_public_key(cert->cert);
-
- for (s = secrets; s != NULL; s = s->next)
- {
- if (s->kind == SECRET_PUBKEY &&
- s->u.private_key->belongs_to(s->u.private_key, pub_key))
- {
- has_key = TRUE;
- break;
- }
- }
- pub_key->destroy(pub_key);
- return has_key;
-}
-
-/*
- * get the matching private key belonging to a given X.509 certificate
- */
-private_key_t* get_x509_private_key(const cert_t *cert)
-{
- public_key_t *public_key = cert->cert->get_public_key(cert->cert);
- private_key_t *private_key = NULL;
- secret_t *s;
-
- for (s = secrets; s != NULL; s = s->next)
- {
-
- if (s->kind == SECRET_PUBKEY &&
- s->u.private_key->belongs_to(s->u.private_key, public_key))
- {
- private_key = s->u.private_key;
- break;
- }
- }
- public_key->destroy(public_key);
- return private_key;
-}
-
-/* find the appropriate private key (see get_secret).
- * Failure is indicated by a NULL pointer.
- */
-private_key_t* get_private_key(const connection_t *c)
-{
- const secret_t *s, *best = NULL;
-
- /* is a certificate assigned to this connection? */
- if (c->spd.this.cert)
- {
- certificate_t *certificate;
- public_key_t *pub_key;
-
- certificate = c->spd.this.cert->cert;
- pub_key = certificate->get_public_key(certificate);
-
- for (s = secrets; s != NULL; s = s->next)
- {
- if (s->kind == SECRET_PUBKEY &&
- s->u.private_key->belongs_to(s->u.private_key, pub_key))
- {
- best = s;
- break; /* found the private key - no sense in searching further */
- }
- }
- pub_key->destroy(pub_key);
- }
- else
- {
- best = get_secret(c, SECRET_PUBKEY);
- }
- return best ? best->u.private_key : NULL;
-}
-
-/* digest a secrets file
- *
- * The file is a sequence of records. A record is a maximal sequence of
- * tokens such that the first, and only the first, is in the first column
- * of a line.
- *
- * Tokens are generally separated by whitespace and are key words, ids,
- * strings, or data suitable for ttodata(3). As a nod to convention,
- * a trailing ":" on what would otherwise be a token is taken as a
- * separate token. If preceded by whitespace, a "#" is taken as starting
- * a comment: it and the rest of the line are ignored.
- *
- * One kind of record is an include directive. It starts with "include".
- * The filename is the only other token in the record.
- * If the filename does not start with /, it is taken to
- * be relative to the directory containing the current file.
- *
- * The other kind of record describes a key. It starts with a
- * sequence of ids and ends with key information. Each id
- * is an IP address, a Fully Qualified Domain Name (which will immediately
- * be resolved), or @FQDN which will be left as a name.
- *
- * The key part can be in several forms.
- *
- * The old form of the key is still supported: a simple
- * quoted strings (with no escapes) is taken as a preshred key.
- *
- * The new form starts the key part with a ":".
- *
- * For Preshared Key, use the "PSK" keyword, and follow it by a string
- * or a data token suitable for ttodata(3).
- *
- * For RSA Private Key, use the "RSA" keyword, followed by a
- * brace-enclosed list of key field keywords and data values.
- * The data values are large integers to be decoded by ttodata(3).
- * The fields are a subset of those used by BIND 8.2 and have the
- * same names.
- */
-
-/* parse PSK from file */
-static err_t process_psk_secret(chunk_t *psk)
-{
- err_t ugh = NULL;
-
- if (*tok == '"' || *tok == '\'')
- {
- chunk_t secret = { tok + 1, flp->cur - tok -2 };
-
- *psk = chunk_clone(secret);
- (void) shift();
- }
- else
- {
- char buf[BUF_LEN]; /* limit on size of binary representation of key */
- size_t sz;
-
- ugh = ttodatav(tok, flp->cur - tok, 0, buf, sizeof(buf), &sz
- , diag_space, sizeof(diag_space), TTODATAV_SPACECOUNTS);
- if (ugh != NULL)
- {
- /* ttodata didn't like PSK data */
- ugh = builddiag("PSK data malformed (%s): %s", ugh, tok);
- }
- else
- {
- chunk_t secret = { buf, sz };
- *psk = chunk_clone(secret);
- (void) shift();
- }
- }
- return ugh;
-}
-
-typedef enum rsa_private_key_part_t rsa_private_key_part_t;
-
-enum rsa_private_key_part_t {
- RSA_PART_MODULUS = 0,
- RSA_PART_PUBLIC_EXPONENT = 1,
- RSA_PART_PRIVATE_EXPONENT = 2,
- RSA_PART_PRIME1 = 3,
- RSA_PART_PRIME2 = 4,
- RSA_PART_EXPONENT1 = 5,
- RSA_PART_EXPONENT2 = 6,
- RSA_PART_COEFFICIENT = 7
-};
-
-const char *rsa_private_key_part_names[] = {
- "Modulus",
- "PublicExponent",
- "PrivateExponent",
- "Prime1",
- "Prime2",
- "Exponent1",
- "Exponent2",
- "Coefficient"
-};
-
-/**
- * Parse fields of an RSA private key in BIND 8.2's representation
- * consistiong of a braced list of keyword and value pairs in required order.
- */
-static err_t process_rsa_secret(private_key_t **key)
-{
- chunk_t rsa_chunk[countof(rsa_private_key_part_names)];
- u_char buf[RSA_MAX_ENCODING_BYTES]; /* limit on size of binary representation of key */
- rsa_private_key_part_t part, p;
- size_t sz;
- err_t ugh;
-
- for (part = RSA_PART_MODULUS; part <= RSA_PART_COEFFICIENT; part++)
- {
- const char *keyword = rsa_private_key_part_names[part];
-
- if (!shift())
- {
- ugh = "premature end of RSA key";
- goto end;
- }
- if (!tokeqword(keyword))
- {
- ugh = builddiag("%s keyword not found where expected in RSA key"
- , keyword);
- goto end;
- }
- if (!(shift() && (!tokeq(":") || shift()))) /* ignore optional ":" */
- {
- ugh = "premature end of RSA key";
- goto end;
- }
- ugh = ttodatav(tok, flp->cur - tok, 0, buf, sizeof(buf), &sz,
- diag_space, sizeof(diag_space), TTODATAV_SPACECOUNTS);
- if (ugh)
- {
- ugh = builddiag("RSA data malformed (%s): %s", ugh, tok);
- goto end;
- }
- rsa_chunk[part] = chunk_create(buf, sz);
- rsa_chunk[part] = chunk_clone(rsa_chunk[part]);
- }
-
- /* We require an (indented) '}' and the end of the record.
- * We break down the test so that the diagnostic will be more helpful.
- * Some people don't seem to wish to indent the brace!
- */
- if (!shift() || !tokeq("}"))
- {
- ugh = "malformed end of RSA private key -- indented '}' required";
- goto end;
- }
- if (shift())
- {
- ugh = "malformed end of RSA private key -- unexpected token after '}'";
- goto end;
- }
-
- *key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
- BUILD_RSA_MODULUS, rsa_chunk[RSA_PART_MODULUS],
- BUILD_RSA_PUB_EXP, rsa_chunk[RSA_PART_PUBLIC_EXPONENT],
- BUILD_RSA_PRIV_EXP, rsa_chunk[RSA_PART_PRIVATE_EXPONENT],
- BUILD_RSA_PRIME1, rsa_chunk[RSA_PART_PRIME1],
- BUILD_RSA_PRIME2, rsa_chunk[RSA_PART_PRIME2],
- BUILD_RSA_EXP1, rsa_chunk[RSA_PART_EXPONENT1],
- BUILD_RSA_EXP2, rsa_chunk[RSA_PART_EXPONENT2],
- BUILD_RSA_COEFF, rsa_chunk[RSA_PART_COEFFICIENT],
- BUILD_END);
-
- if (*key == NULL)
- {
- ugh = "parsing of RSA private key failed";
- }
-
-end:
- /* clean up and return */
- for (p = RSA_PART_MODULUS ; p < part; p++)
- {
- chunk_clear(&rsa_chunk[p]);
- }
- return ugh;
-}
-
-/* struct used to prompt for a secret passphrase
- * from a console with file descriptor fd
- */
-typedef struct {
- char secret[PROMPT_PASS_LEN+1];
- bool prompt;
- int fd;
- int try;
-} prompt_pass_t;
-
-/**
- * Passphrase callback to read from whack fd
- */
-static shared_key_t* whack_pass_cb(prompt_pass_t *pass, shared_key_type_t type,
- identification_t *me, identification_t *other,
- id_match_t *match_me, id_match_t *match_other)
-{
- int n;
-
- if (type != SHARED_ANY && type != SHARED_PRIVATE_KEY_PASS)
- {
- return NULL;
- }
-
- if (pass->try > MAX_PROMPT_PASS_TRIALS)
- {
- whack_log(RC_LOG_SERIOUS, "invalid passphrase, too many trials");
- return NULL;
- }
- if (pass->try == 1)
- {
- whack_log(RC_ENTERSECRET, "need passphrase for 'private key'");
- }
- else
- {
- whack_log(RC_ENTERSECRET, "invalid passphrase, please try again");
- }
- pass->try++;
-
- n = read(pass->fd, pass->secret, PROMPT_PASS_LEN);
- if (n == -1)
- {
- whack_log(RC_LOG_SERIOUS, "read(whackfd) failed");
- return NULL;
- }
- pass->secret[n-1] = '\0';
-
- if (strlen(pass->secret) == 0)
- {
- whack_log(RC_LOG_SERIOUS, "no passphrase entered, aborted");
- return NULL;
- }
- if (match_me)
- {
- *match_me = ID_MATCH_PERFECT;
- }
- if (match_other)
- {
- *match_other = ID_MATCH_NONE;
- }
- return shared_key_create(SHARED_PRIVATE_KEY_PASS,
- chunk_clone(chunk_create(pass->secret, strlen(pass->secret))));
-}
-
-/**
- * Loads a PKCS#1 or PGP private key file
- */
-static private_key_t* load_private_key(char* filename, prompt_pass_t *pass,
- key_type_t type)
-{
- private_key_t *key = NULL;
- char *path;
-
- path = concatenate_paths(PRIVATE_KEY_PATH, filename);
- if (pass && pass->prompt && pass->fd != NULL_FD)
- { /* use passphrase callback */
- callback_cred_t *cb;
-
- cb = callback_cred_create_shared((void*)whack_pass_cb, pass);
- lib->credmgr->add_local_set(lib->credmgr, &cb->set);
-
- key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
- BUILD_FROM_FILE, path, BUILD_END);
- lib->credmgr->remove_local_set(lib->credmgr, &cb->set);
- cb->destroy(cb);
- if (key)
- {
- whack_log(RC_SUCCESS, "valid passphrase");
- }
- }
- else if (pass)
- { /* use a given passphrase */
- mem_cred_t *mem;
- shared_key_t *shared;
-
- mem = mem_cred_create();
- lib->credmgr->add_local_set(lib->credmgr, &mem->set);
- shared = shared_key_create(SHARED_PRIVATE_KEY_PASS,
- chunk_clone(chunk_create(pass->secret, strlen(pass->secret))));
- mem->add_shared(mem, shared, NULL);
- key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
- BUILD_FROM_FILE, path, BUILD_END);
- lib->credmgr->remove_local_set(lib->credmgr, &mem->set);
- mem->destroy(mem);
- }
- else
- { /* no passphrase */
- key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
- BUILD_FROM_FILE, path, BUILD_END);
-
- }
- if (key)
- {
- plog(" loaded private key from '%s'", filename);
- }
- else
- {
- plog(" syntax error in private key file");
- }
- return key;
-}
-
-/**
- * process a key file protected with optional passphrase which can either be
- * read from ipsec.secrets or prompted for by using whack
- */
-static err_t process_keyfile(private_key_t **key, key_type_t type, int whackfd)
-{
- char filename[BUF_LEN];
- prompt_pass_t pass;
-
- memset(filename,'\0', BUF_LEN);
- memset(pass.secret,'\0', sizeof(pass.secret));
- pass.prompt = FALSE;
- pass.fd = whackfd;
- pass.try = 1;
-
- /* we expect the filename of a PKCS#1 private key file */
-
- if (*tok == '"' || *tok == '\'') /* quoted filename */
- memcpy(filename, tok+1, flp->cur - tok - 2);
- else
- memcpy(filename, tok, flp->cur - tok);
-
- if (shift())
- {
- /* we expect an appended passphrase or passphrase prompt*/
- if (tokeqword("%prompt"))
- {
- if (pass.fd == NULL_FD)
- {
- return "Private key file -- enter passphrase using 'ipsec secrets'";
- }
- pass.prompt = TRUE;
- }
- else
- {
- char *passphrase = tok;
- size_t len = flp->cur - passphrase;
-
- if (*tok == '"' || *tok == '\'') /* quoted passphrase */
- {
- passphrase++;
- len -= 2;
- }
- if (len > PROMPT_PASS_LEN)
- {
- return "Private key file -- passphrase exceeds 64 characters";
- }
- memcpy(pass.secret, passphrase, len);
- }
- if (shift())
- {
- return "Private key file -- unexpected token after passphrase";
- }
- }
- *key = load_private_key(filename, &pass, type);
-
- return *key ? NULL : "Private key file -- could not be loaded";
-}
-
-/**
- * Process pin read from ipsec.secrets or prompted for it using whack
- */
-static err_t process_pin(secret_t *s, int whackfd)
-{
- smartcard_t *sc;
- const char *pin_status = "no pin";
-
- s->kind = SECRET_PIN;
-
- /* looking for the smartcard keyword */
- if (!shift() || strncmp(tok, SCX_TOKEN, strlen(SCX_TOKEN)) != 0)
- return "PIN keyword must be followed by %smartcard<reader>:<id>";
-
- sc = scx_add(scx_parse_number_slot_id(tok + strlen(SCX_TOKEN)));
- s->u.smartcard = sc;
- scx_share(sc);
- if (sc->pin.ptr != NULL)
- {
- scx_release_context(sc);
- scx_free_pin(&sc->pin);
- }
- sc->valid = FALSE;
-
- if (!shift())
- return "PIN statement must be terminated either by <pin code>, %pinpad or %prompt";
-
- if (tokeqword("%prompt"))
- {
- shift();
- /* if whackfd exists, whack will be used to prompt for a pin */
- if (whackfd != NULL_FD)
- pin_status = scx_get_pin(sc, whackfd) ? "valid pin" : "invalid pin";
- else
- pin_status = "pin entry via prompt";
- }
- else if (tokeqword("%pinpad"))
- {
- chunk_t empty_pin = { "", 0 };
-
- shift();
-
- /* pin will be entered via pin pad during verification */
- sc->pin = chunk_clone(empty_pin);
- sc->pinpad = TRUE;
- sc->valid = TRUE;
- pin_status = "pin entry via pad";
- if (pkcs11_keep_state)
- {
- scx_verify_pin(sc);
- }
- }
- else
- {
- /* we read the pin directly from ipsec.secrets */
- err_t ugh = process_psk_secret(&sc->pin);
- if (ugh != NULL)
- return ugh;
- /* verify the pin */
- pin_status = scx_verify_pin(sc) ? "valid PIN" : "invalid PIN";
- }
-#ifdef SMARTCARD
- {
- char buf[BUF_LEN];
-
- if (sc->any_slot)
- snprintf(buf, BUF_LEN, "any slot");
- else
- snprintf(buf, BUF_LEN, "slot: %lu", sc->slot);
-
- plog(" %s for #%d (%s, id: %s)"
- , pin_status, sc->number, scx_print_slot(sc, ""), sc->id);
- }
-#else
- plog(" warning: SMARTCARD support is deactivated in pluto/Makefile!");
-#endif
- return NULL;
-}
-
-static void log_psk(char *label, secret_t *s)
-{
- int n = 0;
- char buf[BUF_LEN];
- enumerator_t *enumerator;
- identification_t *id;
-
- if (s->ids->get_count(s->ids) == 0)
- {
- n = snprintf(buf, BUF_LEN, "%%any");
- }
- else
- {
- enumerator = s->ids->create_enumerator(s->ids);
- while(enumerator->enumerate(enumerator, &id))
- {
- n += snprintf(buf + n, BUF_LEN - n, "%Y ", id);
- if (n >= BUF_LEN)
- {
- n = BUF_LEN - 1;
- break;
- }
- }
- enumerator->destroy(enumerator);
- }
- plog(" loaded %s secret for %.*s", label, n, buf);
-}
-
-static void process_secret(secret_t *s, int whackfd)
-{
- err_t ugh = NULL;
-
- s->kind = SECRET_PSK; /* default */
- if (tokeqword("psk"))
- {
- log_psk("PSK", s);
-
- /* preshared key: quoted string or ttodata format */
- ugh = !shift()? "unexpected end of record in PSK"
- : process_psk_secret(&s->u.preshared_secret);
- }
- else if (tokeqword("xauth"))
- {
- s->kind = SECRET_XAUTH;
- log_psk("XAUTH", s);
-
- /* xauth secret: quoted string or ttodata format */
- ugh = !shift()? "unexpected end of record in XAUTH"
- : process_psk_secret(&s->u.preshared_secret);
- }
- else if (tokeqword("rsa"))
- {
- /* RSA key: the fun begins.
- * A braced list of keyword and value pairs.
- */
- s->kind = SECRET_PUBKEY;
- if (!shift())
- {
- ugh = "bad RSA key syntax";
- }
- else if (tokeq("{"))
- {
- ugh = process_rsa_secret(&s->u.private_key);
- }
- else
- {
- ugh = process_keyfile(&s->u.private_key, KEY_RSA, whackfd);
- }
- }
- else if (tokeqword("ecdsa"))
- {
- s->kind = SECRET_PUBKEY;
- if (!shift())
- {
- ugh = "bad ECDSA key syntax";
- }
- else
- {
- ugh = process_keyfile(&s->u.private_key, KEY_ECDSA, whackfd);
- }
- }
- else if (tokeqword("pin"))
- {
- ugh = process_pin(s, whackfd);
- }
- else
- {
- ugh = builddiag("unrecognized key format: %s", tok);
- }
-
- if (ugh != NULL)
- {
- loglog(RC_LOG_SERIOUS, "\"%s\" line %d: %s"
- , flp->filename, flp->lino, ugh);
- s->ids->destroy_offset(s->ids, offsetof(identification_t, destroy));
- free(s);
- }
- else if (flushline("expected record boundary in key"))
- {
- /* gauntlet has been run: install new secret */
- lock_certs_and_keys("process_secret");
- s->next = secrets;
- secrets = s;
- unlock_certs_and_keys("process_secrets");
- }
-}
-
-static void process_secrets_file(const char *file_pat, int whackfd); /* forward declaration */
-
-static void process_secret_records(int whackfd)
-{
- /* read records from ipsec.secrets and load them into our table */
- for (;;)
- {
- (void)flushline(NULL); /* silently ditch leftovers, if any */
- if (flp->bdry == B_file)
- {
- break;
- }
- flp->bdry = B_none; /* eat the Record Boundary */
- (void)shift(); /* get real first token */
-
- if (tokeqword("include"))
- {
- /* an include directive */
- char fn[MAX_TOK_LEN]; /* space for filename (I hope) */
- char *p = fn;
- char *end_prefix = strrchr(flp->filename, '/');
-
- if (!shift())
- {
- loglog(RC_LOG_SERIOUS, "\"%s\" line %d: unexpected end of include directive"
- , flp->filename, flp->lino);
- continue; /* abandon this record */
- }
-
- /* if path is relative and including file's pathname has
- * a non-empty dirname, prefix this path with that dirname.
- */
- if (tok[0] != '/' && end_prefix != NULL)
- {
- size_t pl = end_prefix - flp->filename + 1;
-
- /* "clamp" length to prevent problems now;
- * will be rediscovered and reported later.
- */
- if (pl > sizeof(fn))
- {
- pl = sizeof(fn);
- }
- memcpy(fn, flp->filename, pl);
- p += pl;
- }
- if (flp->cur - tok >= &fn[sizeof(fn)] - p)
- {
- loglog(RC_LOG_SERIOUS, "\"%s\" line %d: include pathname too long"
- , flp->filename, flp->lino);
- continue; /* abandon this record */
- }
- strcpy(p, tok);
- (void) shift(); /* move to Record Boundary, we hope */
- if (flushline("ignoring malformed INCLUDE -- expected Record Boundary after filename"))
- {
- process_secrets_file(fn, whackfd);
- tok = NULL; /* correct, but probably redundant */
- }
- }
- else
- {
- /* expecting a list of indices and then the key info */
- secret_t *s = malloc_thing(secret_t);
-
- zero(s);
- s->ids = linked_list_create();
- s->kind = SECRET_PSK; /* default */
- s->u.preshared_secret = chunk_empty;
- s->next = NULL;
-
- for (;;)
- {
- if (tokeq(":"))
- {
- /* found key part */
- shift(); /* discard explicit separator */
- process_secret(s, whackfd);
- break;
- }
- else
- {
- identification_t *id;
-
- id = identification_create_from_string(tok);
- s->ids->insert_last(s->ids, id);
-
- if (!shift())
- {
- /* unexpected Record Boundary or EOF */
- loglog(RC_LOG_SERIOUS, "\"%s\" line %d: unexpected end"
- " of id list", flp->filename, flp->lino);
- s->ids->destroy_offset(s->ids,
- offsetof(identification_t, destroy));
- free(s);
- break;
- }
- }
- }
- }
- }
-}
-
-static int globugh(const char *epath, int eerrno)
-{
- log_errno_routine(eerrno, "problem with secrets file \"%s\"", epath);
- return 1; /* stop glob */
-}
-
-static void process_secrets_file(const char *file_pat, int whackfd)
-{
- struct file_lex_position pos;
- char **fnp;
-
- pos.depth = flp == NULL? 0 : flp->depth + 1;
-
- if (pos.depth > 10)
- {
- loglog(RC_LOG_SERIOUS, "preshared secrets file \"%s\" nested too deeply", file_pat);
- return;
- }
-
-#ifdef HAVE_GLOB_H
- /* do globbing */
- {
- glob_t globbuf;
- int r = glob(file_pat, GLOB_ERR, globugh, &globbuf);
-
- if (r != 0)
- {
- switch (r)
- {
- case GLOB_NOSPACE:
- loglog(RC_LOG_SERIOUS, "out of space processing secrets filename \"%s\"", file_pat);
- break;
- case GLOB_ABORTED:
- break; /* already logged */
- case GLOB_NOMATCH:
- loglog(RC_LOG_SERIOUS, "no secrets filename matched \"%s\"", file_pat);
- break;
- default:
- loglog(RC_LOG_SERIOUS, "unknown glob error %d", r);
- break;
- }
- globfree(&globbuf);
- return;
- }
-
- /* for each file... */
- for (fnp = globbuf.gl_pathv; *fnp != NULL; fnp++)
- {
- if (lexopen(&pos, *fnp, FALSE))
- {
- plog("loading secrets from \"%s\"", *fnp);
- flushline("file starts with indentation (continuation notation)");
- process_secret_records(whackfd);
- lexclose();
- }
- }
-
- globfree(&globbuf);
- }
-#else /* HAVE_GLOB_H */
- /* if glob(3) is not available, try to load pattern directly */
- if (lexopen(&pos, file_pat, FALSE))
- {
- plog("loading secrets from \"%s\"", file_pat);
- flushline("file starts with indentation (continuation notation)");
- process_secret_records(whackfd);
- lexclose();
- }
-#endif /* HAVE_GLOB_H */
-}
-
-void free_preshared_secrets(void)
-{
- lock_certs_and_keys("free_preshared_secrets");
-
- if (secrets != NULL)
- {
- secret_t *s, *ns;
-
- plog("forgetting secrets");
-
- for (s = secrets; s != NULL; s = ns)
- {
- ns = s->next;
- s->ids->destroy_offset(s->ids, offsetof(identification_t, destroy));
-
- switch (s->kind)
- {
- case SECRET_PSK:
- case SECRET_XAUTH:
- free(s->u.preshared_secret.ptr);
- break;
- case SECRET_PUBKEY:
- DESTROY_IF(s->u.private_key);
- break;
- case SECRET_PIN:
- scx_release(s->u.smartcard);
- break;
- default:
- bad_case(s->kind);
- }
- free(s);
- }
- secrets = NULL;
- }
-
- unlock_certs_and_keys("free_preshard_secrets");
-}
-
-void load_preshared_secrets(int whackfd)
-{
- free_preshared_secrets();
- (void) process_secrets_file(shared_secrets_file, whackfd);
-}
-
-/* public key machinery
- * Note: caller must set dns_auth_level.
- */
-
-pubkey_t* public_key_from_rsa(public_key_t *key)
-{
- pubkey_t *p = malloc_thing(pubkey_t);
-
- zero(p);
- p->id = identification_create_from_string("%any"); /* don't know, doesn't matter */
- p->issuer = NULL;
- p->serial = chunk_empty;
- p->public_key = key;
-
- /* note that we return a 1 reference count upon creation:
- * invariant: recount > 0.
- */
- p->refcnt = 1;
- return p;
-}
-
-/* Free a public key record.
- * As a convenience, this returns a pointer to next.
- */
-pubkey_list_t* free_public_keyentry(pubkey_list_t *p)
-{
- pubkey_list_t *nxt = p->next;
-
- if (p->key != NULL)
- {
- unreference_key(&p->key);
- }
- free(p);
- return nxt;
-}
-
-void free_public_keys(pubkey_list_t **keys)
-{
- while (*keys != NULL)
- {
- *keys = free_public_keyentry(*keys);
- }
-}
-
-/* root of chained public key list */
-
-pubkey_list_t *pubkeys = NULL; /* keys from ipsec.conf */
-
-void free_remembered_public_keys(void)
-{
- free_public_keys(&pubkeys);
-}
-
-/**
- * Transfer public keys from *keys list to front of pubkeys list
- */
-void transfer_to_public_keys(struct gw_info *gateways_from_dns
-#ifdef USE_KEYRR
-, pubkey_list_t **keys
-#endif /* USE_KEYRR */
-)
-{
- {
- struct gw_info *gwp;
-
- for (gwp = gateways_from_dns; gwp != NULL; gwp = gwp->next)
- {
- pubkey_list_t *pl = malloc_thing(pubkey_list_t);
-
- pl->key = gwp->key; /* note: this is a transfer */
- gwp->key = NULL; /* really, it is! */
- pl->next = pubkeys;
- pubkeys = pl;
- }
- }
-
-#ifdef USE_KEYRR
- {
- pubkey_list_t **pp = keys;
-
- while (*pp != NULL)
- {
- pp = &(*pp)->next;
- }
- *pp = pubkeys;
- pubkeys = *keys;
- *keys = NULL;
- }
-#endif /* USE_KEYRR */
-}
-
-
-static void install_public_key(pubkey_t *pk, pubkey_list_t **head)
-{
- pubkey_list_t *p = malloc_thing(pubkey_list_t);
-
- /* install new key at front */
- p->key = reference_key(pk);
- p->next = *head;
- *head = p;
-}
-
-void delete_public_keys(identification_t *id, key_type_t type,
- identification_t *issuer, chunk_t serial)
-{
- pubkey_list_t **pp, *p;
- pubkey_t *pk;
- key_type_t pk_type;
-
- for (pp = &pubkeys; (p = *pp) != NULL; )
- {
- pk = p->key;
- pk_type = pk->public_key->get_type(pk->public_key);
-
- if (id->equals(id, pk->id) && pk_type == type
- && (issuer == NULL || pk->issuer == NULL
- || issuer->equals(issuer, pk->issuer))
- && (serial.ptr == NULL || chunk_equals(serial, pk->serial)))
- {
- *pp = free_public_keyentry(p);
- }
- else
- {
- pp = &p->next;
- }
- }
-}
-
-pubkey_t* reference_key(pubkey_t *pk)
-{
- DBG(DBG_CONTROLMORE,
- DBG_log(" ref key: %p %p cnt %d '%Y'",
- pk, pk->public_key, pk->refcnt, pk->id)
- )
- pk->refcnt++;
- return pk;
-}
-
-void unreference_key(pubkey_t **pkp)
-{
- pubkey_t *pk = *pkp;
-
- if (pk == NULL)
- {
- return;
- }
-
- DBG(DBG_CONTROLMORE,
- DBG_log("unref key: %p %p cnt %d '%Y'",
- pk, pk->public_key, pk->refcnt, pk->id)
- )
-
- /* cancel out the pointer */
- *pkp = NULL;
-
- passert(pk->refcnt != 0);
- pk->refcnt--;
- if (pk->refcnt == 0)
- {
- free_public_key(pk);
- }
-}
-
-bool add_public_key(identification_t *id, enum dns_auth_level dns_auth_level,
- enum pubkey_alg alg, chunk_t rfc3110_key,
- pubkey_list_t **head)
-{
- public_key_t *key = NULL;
- pubkey_t *pk;
-
- /* first: algorithm-specific decoding of key chunk */
- switch (alg)
- {
- case PUBKEY_ALG_RSA:
- key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
- BUILD_BLOB_DNSKEY, rfc3110_key,
- BUILD_END);
- if (key == NULL)
- {
- return FALSE;
- }
- break;
- default:
- bad_case(alg);
- }
-
- pk = malloc_thing(pubkey_t);
- zero(pk);
- pk->public_key = key;
- pk->id = id->clone(id);
- pk->dns_auth_level = dns_auth_level;
- pk->until_time = UNDEFINED_TIME;
- pk->issuer = NULL;
- pk->serial = chunk_empty;
- install_public_key(pk, head);
- return TRUE;
-}
-
-/**
- * Extract id and public key a certificate and insert it into a pubkeyrec
- */
-void add_public_key_from_cert(cert_t *cert , time_t until,
- enum dns_auth_level dns_auth_level)
-{
- certificate_t *certificate = cert->cert;
- identification_t *subject = certificate->get_subject(certificate);
- identification_t *issuer = NULL;
- identification_t *id;
- chunk_t serialNumber = chunk_empty;
- pubkey_t *pk;
- key_type_t pk_type;
-
- /* ID type: ID_DER_ASN1_DN (X.509 subject field) */
- pk = malloc_thing(pubkey_t);
- zero(pk);
- pk->public_key = certificate->get_public_key(certificate);
- pk_type = pk->public_key->get_type(pk->public_key);
- pk->id = subject->clone(subject);
- pk->dns_auth_level = dns_auth_level;
- pk->until_time = until;
- if (certificate->get_type(certificate) == CERT_X509)
- {
- x509_t *x509 = (x509_t*)certificate;
-
- issuer = certificate->get_issuer(certificate);
- serialNumber = x509->get_serial(x509);
- pk->issuer = issuer->clone(issuer);
- pk->serial = chunk_clone(serialNumber);
- }
- delete_public_keys(pk->id, pk_type, pk->issuer, pk->serial);
- install_public_key(pk, &pubkeys);
-
- if (certificate->get_type(certificate) == CERT_X509)
- {
- x509_t *x509 = (x509_t*)certificate;
- enumerator_t *enumerator;
-
- /* insert all subjectAltNames from X.509 certificates */
- enumerator = x509->create_subjectAltName_enumerator(x509);
- while (enumerator->enumerate(enumerator, &id))
- {
- if (id->get_type(id) != ID_ANY)
- {
- pk = malloc_thing(pubkey_t);
- zero(pk);
- pk->id = id->clone(id);
- pk->public_key = certificate->get_public_key(certificate);
- pk->dns_auth_level = dns_auth_level;
- pk->until_time = until;
- pk->issuer = issuer->clone(issuer);
- pk->serial = chunk_clone(serialNumber);
- delete_public_keys(pk->id, pk_type, pk->issuer, pk->serial);
- install_public_key(pk, &pubkeys);
- }
- }
- enumerator->destroy(enumerator);
- }
- else
- {
- pgp_certificate_t *pgp_cert = (pgp_certificate_t*)certificate;
- chunk_t fingerprint = pgp_cert->get_fingerprint(pgp_cert);
-
- /* add v3 or v4 PGP fingerprint */
- pk = malloc_thing(pubkey_t);
- zero(pk);
- pk->id = identification_create_from_encoding(ID_KEY_ID, fingerprint);
- pk->public_key = certificate->get_public_key(certificate);
- pk->dns_auth_level = dns_auth_level;
- pk->until_time = until;
- delete_public_keys(pk->id, pk_type, pk->issuer, pk->serial);
- install_public_key(pk, &pubkeys);
- }
-}
-
-/* when a X.509 certificate gets revoked, all instances of
- * the corresponding public key must be removed
- */
-void remove_x509_public_key(const cert_t *cert)
-{
- public_key_t *revoked_key = cert->cert->get_public_key(cert->cert);
- pubkey_list_t *p, **pp;
-
- p = pubkeys;
- pp = &pubkeys;
-
- while(p != NULL)
- {
- if (revoked_key->equals(revoked_key, p->key->public_key))
- {
- /* remove p from list and free memory */
- *pp = free_public_keyentry(p);
- loglog(RC_LOG_SERIOUS, "invalid public key deleted");
- }
- else
- {
- pp = &p->next;
- }
- p =*pp;
- }
- revoked_key->destroy(revoked_key);
-}
-
-/*
- * list all public keys in the chained list
- */
-void list_public_keys(bool utc)
-{
- pubkey_list_t *p = pubkeys;
- chunk_t serial;
-
- if (p != NULL)
- {
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, "List of Public Keys:");
- }
-
- while (p != NULL)
- {
- pubkey_t *key = p->key;
- public_key_t *public = key->public_key;
- chunk_t keyid;
-
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, " identity: '%Y'", key->id);
- whack_log(RC_COMMENT, " pubkey: %N %4d bits, until %T %s",
- key_type_names, public->get_type(public),
- public->get_keysize(public),
- &key->until_time, utc,
- check_expiry(key->until_time, PUBKEY_WARNING_INTERVAL, TRUE));
- if (public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &keyid))
- {
- whack_log(RC_COMMENT," keyid: %#B", &keyid);
- }
- if (key->issuer)
- {
- whack_log(RC_COMMENT," issuer: \"%Y\"", key->issuer);
- }
- if (key->serial.len)
- {
- serial = chunk_skip_zero(key->serial);
- whack_log(RC_COMMENT," serial: %#B", &serial);
- }
- p = p->next;
- }
-}
diff --git a/src/pluto/keys.h b/src/pluto/keys.h
deleted file mode 100644
index 73cc21392..000000000
--- a/src/pluto/keys.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/* mechanisms for preshared keys (public, private, and preshared secrets)
- * Copyright (C) 1998-2002 D. Hugh Redelmeier.
- * Copyright (C) 2009 Andreas Steffen, Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#ifndef _KEYS_H
-#define _KEYS_H
-
-#include <utils/identification.h>
-#include <credentials/keys/private_key.h>
-#include <credentials/keys/public_key.h>
-
-#include "certs.h"
-#include "connections.h"
-
-#ifndef SHARED_SECRETS_FILE
-# define SHARED_SECRETS_FILE IPSEC_CONFDIR "/ipsec.secrets"
-#endif
-
-const char *shared_secrets_file;
-
-extern void load_preshared_secrets(int whackfd);
-extern void free_preshared_secrets(void);
-
-extern void xauth_defaults(void);
-
-extern bool get_xauth_secret(identification_t *user, identification_t *server,
- chunk_t *secret);
-extern const chunk_t *get_preshared_secret(const connection_t *c);
-extern private_key_t *get_private_key(const connection_t *c);
-extern private_key_t *get_x509_private_key(const cert_t *cert);
-
-/* public key machinery */
-
-typedef struct pubkey pubkey_t;
-
-struct pubkey {
- identification_t *id;
- unsigned refcnt; /* reference counted! */
- enum dns_auth_level dns_auth_level;
- char *dns_sig;
- time_t last_tried_time, last_worked_time, until_time;
- identification_t *issuer;
- chunk_t serial;
- public_key_t *public_key;
-};
-
-typedef struct pubkey_list pubkey_list_t;
-
-struct pubkey_list {
- pubkey_t *key;
- pubkey_list_t *next;
-};
-
-extern pubkey_list_t *pubkeys; /* keys from ipsec.conf or from certs */
-
-extern pubkey_t *public_key_from_rsa(public_key_t *key);
-extern pubkey_list_t *free_public_keyentry(pubkey_list_t *p);
-extern void free_public_keys(pubkey_list_t **keys);
-extern void free_remembered_public_keys(void);
-extern void delete_public_keys(identification_t *id, key_type_t type,
- identification_t *issuer, chunk_t serial);
-extern pubkey_t *reference_key(pubkey_t *pk);
-extern void unreference_key(pubkey_t **pkp);
-extern bool add_public_key(identification_t *id,
- enum dns_auth_level dns_auth_level,
- enum pubkey_alg alg,
- chunk_t rfc3110_key,
- pubkey_list_t **head);
-extern bool has_private_key(cert_t *cert);
-extern void add_public_key_from_cert(cert_t *cert, time_t until,
- enum dns_auth_level dns_auth_level);
-extern void remove_x509_public_key(const cert_t *cert);
-extern void list_public_keys(bool utc);
-
-struct gw_info; /* forward declaration of tag (defined in dnskey.h) */
-extern void transfer_to_public_keys(struct gw_info *gateways_from_dns
-#ifdef USE_KEYRR
- , pubkey_list_t **keys
-#endif /* USE_KEYRR */
- );
-
-#endif /* _KEYS_H */
diff --git a/src/pluto/lex.c b/src/pluto/lex.c
deleted file mode 100644
index d5ebdaba9..000000000
--- a/src/pluto/lex.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/* lexer (lexical analyzer) for control files
- * Copyright (C) 1998-2001 D. Hugh Redelmeier.
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <freeswan.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "log.h"
-#include "whack.h" /* for RC_LOG_SERIOUS */
-#include "lex.h"
-
-struct file_lex_position *flp = NULL;
-
-/* Open a file for lexical processing.
- * new_flp and name must point into storage with will live
- * at least until the file is closed.
- */
-bool
-lexopen(struct file_lex_position *new_flp, const char *name, bool optional)
-{
- FILE *f = fopen(name, "r");
-
- if (f == NULL)
- {
- if (!optional || errno != ENOENT)
- log_errno((e, "could not open \"%s\"", name));
- return FALSE;
- }
- else
- {
- new_flp->previous = flp;
- flp = new_flp;
- flp->filename = name;
- flp->fp = f;
- flp->lino = 0;
- flp->bdry = B_none;
-
- flp->cur = flp->buffer; /* nothing loaded yet */
- flp->under = *flp->cur = '\0';
-
- (void) shift(); /* prime tok */
- return TRUE;
- }
-}
-
-void
-lexclose(void)
-{
- fclose(flp->fp);
- flp = flp->previous;
-}
-
-/* Token decoding: shift() loads the next token into tok.
- * Iff a token starts at the left margin, it is considered
- * to be the first in a record. We create a special condition,
- * Record Boundary (analogous to EOF), just before such a token.
- * We are unwilling to shift through a record boundary:
- * it must be overridden first.
- * Returns FALSE iff Record Boundary or EOF (i.e. no token);
- * tok will then be NULL.
- */
-
-char *tok;
-#define tokeq(s) (streq(tok, (s)))
-#define tokeqword(s) (strcasecmp(tok, (s)) == 0)
-
-bool
-shift(void)
-{
- char *p = flp->cur;
- char *sor = NULL; /* start of record for any new lines */
-
- passert(flp->bdry == B_none);
-
- *p = flp->under;
- flp->under = '\0';
-
- for (;;)
- {
- switch (*p)
- {
- case '\0': /* end of line */
- case '#': /* comment to end of line: treat as end of line */
- /* get the next line */
- if (fgets(flp->buffer, sizeof(flp->buffer)-1, flp->fp) == NULL)
- {
- flp->bdry = B_file;
- tok = flp->cur = NULL;
- return FALSE;
- }
- else
- {
- /* strip trailing whitespace, including \n */
-
- for (p = flp->buffer+strlen(flp->buffer)-1
- ; p>flp->buffer && isspace(p[-1]); p--)
- ;
- *p = '\0';
-
- flp->lino++;
- sor = p = flp->buffer;
- }
- break; /* try again for a token */
-
- case ' ': /* whitespace */
- case '\t':
- p++;
- break; /* try again for a token */
-
- case '"': /* quoted token */
- case '\'':
- if (p != sor)
- {
- /* we have a quoted token: note and advance to its end */
- tok = p;
- p = strchr(p+1, *p);
- if (p == NULL)
- {
- loglog(RC_LOG_SERIOUS, "\"%s\" line %d: unterminated string"
- , flp->filename, flp->lino);
- p = tok + strlen(tok);
- }
- else
- {
- p++; /* include delimiter in token */
- }
-
- /* remember token delimiter and replace with '\0' */
- flp->under = *p;
- *p = '\0';
- flp->cur = p;
- return TRUE;
- }
- /* FALL THROUGH */
- default:
- if (p != sor)
- {
- /* we seem to have a token: note and advance to its end */
- tok = p;
-
- if (p[0] == '0' && p[1] == 't')
- {
- /* 0t... token goes to end of line */
- p += strlen(p);
- }
- else
- {
- /* "ordinary" token: up to whitespace or end of line */
- do {
- p++;
- } while (*p != '\0' && !isspace(*p))
- ;
-
- /* fudge to separate ':' from a preceding adjacent token */
- if (p-1 > tok && p[-1] == ':')
- p--;
- }
-
- /* remember token delimiter and replace with '\0' */
- flp->under = *p;
- *p = '\0';
- flp->cur = p;
- return TRUE;
- }
-
- /* we have a start-of-record: return it, deferring "real" token */
- flp->bdry = B_record;
- tok = NULL;
- flp->under = *p;
- flp->cur = p;
- return FALSE;
- }
- }
-}
-
-/* ensures we are at a Record (or File) boundary, optionally warning if not */
-
-bool
-flushline(const char *m)
-{
- if (flp->bdry != B_none)
- {
- return TRUE;
- }
- else
- {
- if (m != NULL)
- loglog(RC_LOG_SERIOUS, "\"%s\" line %d: %s", flp->filename, flp->lino, m);
- do {} while (shift());
- return FALSE;
- }
-}
diff --git a/src/pluto/lex.h b/src/pluto/lex.h
deleted file mode 100644
index aa0be7829..000000000
--- a/src/pluto/lex.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* lexer (lexical analyzer) for control files
- * Copyright (C) 1998-2001 D. Hugh Redelmeier.
- *
- * 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 MAX_TOK_LEN 2048 /* includes terminal '\0' */
-struct file_lex_position
-{
- int depth; /* how deeply we are nested */
- const char *filename;
- FILE *fp;
- enum { B_none, B_record, B_file } bdry; /* current boundary */
- int lino; /* line number in file */
- char buffer[MAX_TOK_LEN + 1]; /* note: one extra char for our use (jamming '"') */
- char *cur; /* cursor */
- char under; /* except in shift(): character originally at *cur */
- struct file_lex_position *previous;
-};
-
-extern struct file_lex_position *flp;
-
-extern bool lexopen(struct file_lex_position *new_flp, const char *name, bool optional);
-extern void lexclose(void);
-
-
-/* Token decoding: shift() loads the next token into tok.
- * Iff a token starts at the left margin, it is considered
- * to be the first in a record. We create a special condition,
- * Record Boundary (analogous to EOF), just before such a token.
- * We are unwilling to shift through a record boundary:
- * it must be overridden first.
- * Returns FALSE iff Record Boundary or EOF (i.e. no token);
- * tok will then be NULL.
- */
-
-extern char *tok;
-#define tokeq(s) (streq(tok, (s)))
-#define tokeqword(s) (strcasecmp(tok, (s)) == 0)
-
-extern bool shift(void);
-extern bool flushline(const char *m);
diff --git a/src/pluto/log.c b/src/pluto/log.c
deleted file mode 100644
index f6fa226d5..000000000
--- a/src/pluto/log.c
+++ /dev/null
@@ -1,946 +0,0 @@
-/* error logging functions
- * Copyright (C) 1997 Angelos D. Keromytis.
- * Copyright (C) 1998-2001 D. Hugh Redelmeier.
- * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <stdarg.h>
-#include <syslog.h>
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-#include <signal.h> /* used only if MSG_NOSIGNAL not defined */
-#include <sys/queue.h>
-#include <libgen.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#ifdef ANDROID
-#include <android/log.h>
-#endif
-
-#include <freeswan.h>
-#include <library.h>
-#include <debug.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "log.h"
-#include "server.h"
-#include "state.h"
-#include "connections.h"
-#include "myid.h"
-#include "kernel.h"
-#include "whack.h"
-#include "whack_attribute.h"
-#include "timer.h"
-
-/* close one per-peer log */
-static void perpeer_logclose(connection_t *c); /* forward */
-
-
-bool
- log_to_stderr = TRUE, /* should log go to stderr? */
- log_to_syslog = TRUE, /* should log go to syslog? */
- log_to_perpeer= FALSE; /* should log go to per-IP file? */
-
-bool
- logged_txt_warning = FALSE; /* should we complain about finding KEY? */
-
-/* should we complain when we find no local id */
-bool
- logged_myid_fqdn_txt_warning = FALSE,
- logged_myid_ip_txt_warning = FALSE,
- logged_myid_fqdn_key_warning = FALSE,
- logged_myid_ip_key_warning = FALSE;
-
-/* may include trailing / */
-const char *base_perpeer_logdir = PERPEERLOGDIR;
-static int perpeer_count = 0;
-
-/* from sys/queue.h */
-static TAILQ_HEAD(perpeer, connection) perpeer_list;
-
-
-/* Context for logging.
- *
- * Global variables: must be carefully adjusted at transaction boundaries!
- * If the context provides a whack file descriptor, messages
- * should be copied to it -- see whack_log()
- */
-int whack_log_fd = NULL_FD; /* only set during whack_handle() */
-struct state *cur_state = NULL; /* current state, for diagnostics */
-connection_t *cur_connection = NULL; /* current connection, for diagnostics */
-const ip_address *cur_from = NULL; /* source of current current message */
-u_int16_t cur_from_port; /* host order */
-
-/**
- * pluto dbg function for libstrongswan
- */
-static void pluto_dbg(debug_t group, level_t level, char *fmt, ...)
-{
- int priority = LOG_INFO;
- int debug_level;
- char buffer[8192];
- char *current = buffer, *next;
- va_list args;
-
- if (cur_debugging & DBG_PRIVATE)
- {
- debug_level = 4;
- }
- else if (cur_debugging & DBG_RAW)
- {
- debug_level = 3;
- }
- else if (cur_debugging & DBG_PARSING)
- {
- debug_level = 2;
- }
- else
- {
- debug_level = 1;
- }
-
- if (level <= debug_level)
- {
- va_start(args, fmt);
-
- if (log_to_stderr)
- {
- if (level > 1)
- {
- fprintf(stderr, "| ");
- }
- vfprintf(stderr, fmt, args);
- fprintf(stderr, "\n");
- }
- if (log_to_syslog
-#ifdef ANDROID
- || TRUE
-#endif
- )
- {
- /* write in memory buffer first */
- vsnprintf(buffer, sizeof(buffer), fmt, args);
-
- /* do a syslog with every line */
- while (current)
- {
- next = strchr(current, '\n');
- if (next)
- {
- *(next++) = '\0';
- }
- syslog(priority, "%s%s\n", (level > 1)? "| ":"", current);
-#ifdef ANDROID
- __android_log_print(level > 1 ? ANDROID_LOG_DEBUG
- : ANDROID_LOG_INFO, "pluto",
- "%s%s\n", level > 1 ? "| " : "", current);
-#endif
- current = next;
- }
- }
- va_end(args);
- }
-}
-
-void
-init_log(const char *program)
-{
- /* enable pluto debugging hook for libstrongswan */
- dbg = pluto_dbg;
-
- if (log_to_stderr)
- {
- setbuf(stderr, NULL);
- }
- if (log_to_syslog)
- {
- openlog(program, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_AUTHPRIV);
- }
- TAILQ_INIT(&perpeer_list);
-}
-
-void
-close_peerlog(void)
-{
- /* exit if the queue has not been initialized */
- if (perpeer_list.tqh_first == NULL)
- return;
-
- /* end of queue is given by pointer to "HEAD" */
- while (TAILQ_LAST(&perpeer_list, perpeer) != (void *)&perpeer_list)
- perpeer_logclose(TAILQ_LAST(&perpeer_list, perpeer));
-}
-
-void
-close_log(void)
-{
- if (log_to_syslog)
- closelog();
-
- close_peerlog();
-}
-
-/* Sanitize character string in situ: turns dangerous characters into \OOO.
- * With a bit of work, we could use simpler reps for \\, \r, etc.,
- * but this is only to protect against something that shouldn't be used.
- * Truncate resulting string to what fits in buffer.
- */
-static size_t
-sanitize(char *buf, size_t size)
-{
-# define UGLY_WIDTH 4 /* width for ugly character: \OOO */
- size_t len;
- size_t added = 0;
- char *p;
-
- passert(size >= UGLY_WIDTH); /* need room to swing cat */
-
- /* find right side of string to be sanitized and count
- * number of columns to be added. Stop on end of string
- * or lack of room for more result.
- */
- for (p = buf; *p != '\0' && &p[added] < &buf[size - UGLY_WIDTH]; )
- {
- unsigned char c = *p++;
-
- if (c == '\\' || !isprint(c))
- added += UGLY_WIDTH - 1;
- }
-
- /* at this point, p points after last original character to be
- * included. added is how many characters are added to sanitize.
- * so p[added] will point after last sanitized character.
- */
-
- p[added] = '\0';
- len = &p[added] - buf;
-
- /* scan backwards, copying characters to their new home
- * and inserting the expansions for ugly characters.
- * It is finished when no more shifting is required.
- * This is a predecrement loop.
- */
- while (added != 0)
- {
- char fmtd[UGLY_WIDTH + 1];
- unsigned char c;
-
- while ((c = *--p) != '\\' && isprint(c))
- p[added] = c;
- added -= UGLY_WIDTH - 1;
- snprintf(fmtd, sizeof(fmtd), "\\%03o", c);
- memcpy(p + added, fmtd, UGLY_WIDTH);
- }
- return len;
-# undef UGLY_WIDTH
-}
-
-/* format a string for the log, with suitable prefixes.
- * A format starting with ~ indicates that this is a reprocessing
- * of the message, so prefixing and quoting is suppressed.
- */
-static void
-fmt_log(char *buf, size_t buf_len, const char *fmt, va_list ap)
-{
- bool reproc = *fmt == '~';
- size_t ps;
- connection_t *c = cur_state != NULL ? cur_state->st_connection
- : cur_connection;
-
- buf[0] = '\0';
- if (reproc)
- fmt++; /* ~ at start of format suppresses this prefix */
- else if (c != NULL)
- {
- /* start with name of connection */
- char *const be = buf + buf_len;
- char *bp = buf;
-
- snprintf(bp, be - bp, "\"%s\"", c->name);
- bp += strlen(bp);
-
- /* if it fits, put in any connection instance information */
- if (be - bp > CONN_INST_BUF)
- {
- fmt_conn_instance(c, bp);
- bp += strlen(bp);
- }
-
- if (cur_state != NULL)
- {
- /* state number */
- snprintf(bp, be - bp, " #%lu", cur_state->st_serialno);
- bp += strlen(bp);
- }
- snprintf(bp, be - bp, ": ");
- }
- else if (cur_from != NULL)
- {
- /* peer's IP address */
- /* Note: must not use ip_str() because our caller might! */
- char ab[ADDRTOT_BUF];
-
- (void) addrtot(cur_from, 0, ab, sizeof(ab));
- snprintf(buf, buf_len, "packet from %s:%u: "
- , ab, (unsigned)cur_from_port);
- }
-
- ps = strlen(buf);
- vsnprintf(buf + ps, buf_len - ps, fmt, ap);
- if (!reproc)
- (void)sanitize(buf, buf_len);
-}
-
-static void
-perpeer_logclose(connection_t *c)
-{
- /* only free/close things if we had used them! */
- if (c->log_file != NULL)
- {
- passert(perpeer_count > 0);
-
- TAILQ_REMOVE(&perpeer_list, c, log_link);
- perpeer_count--;
- fclose(c->log_file);
- c->log_file=NULL;
- }
-}
-
-void
-perpeer_logfree(connection_t *c)
-{
- perpeer_logclose(c);
- if (c->log_file_name != NULL)
- {
- free(c->log_file_name);
- c->log_file_name = NULL;
- c->log_file_err = FALSE;
- }
-}
-
-/* open the per-peer log */
-static void
-open_peerlog(connection_t *c)
-{
- syslog(LOG_INFO, "opening log file for conn %s", c->name);
-
- if (c->log_file_name == NULL)
- {
- char peername[ADDRTOT_BUF], dname[ADDRTOT_BUF];
- int peernamelen, lf_len;
-
- addrtot(&c->spd.that.host_addr, 'Q', peername, sizeof(peername));
- peernamelen = strlen(peername);
-
- /* copy IP address, turning : and . into / */
- {
- char ch, *p, *q;
-
- p = peername;
- q = dname;
- do {
- ch = *p++;
- if (ch == '.' || ch == ':')
- ch = '/';
- *q++ = ch;
- } while (ch != '\0');
- }
-
- lf_len = peernamelen * 2
- + strlen(base_perpeer_logdir)
- + sizeof("//.log")
- + 1;
- c->log_file_name = malloc(lf_len);
-
- fprintf(stderr, "base dir |%s| dname |%s| peername |%s|"
- , base_perpeer_logdir, dname, peername);
- snprintf(c->log_file_name, lf_len, "%s/%s/%s.log"
- , base_perpeer_logdir, dname, peername);
-
- syslog(LOG_DEBUG, "conn %s logfile is %s", c->name, c->log_file_name);
- }
-
- /* now open the file, creating directories if necessary */
-
- { /* create the directory */
- char *dname;
- int bpl_len = strlen(base_perpeer_logdir);
- char *slashloc;
-
- dname = clone_str(c->log_file_name);
- dname = dirname(dname);
-
- if (access(dname, W_OK) != 0)
- {
- if (errno != ENOENT)
- {
- if (c->log_file_err)
- {
- syslog(LOG_CRIT, "can not write to %s: %s"
- , dname, strerror(errno));
- c->log_file_err = TRUE;
- free(dname);
- return;
- }
- }
-
- /* directory does not exist, walk path creating dirs */
- /* start at base_perpeer_logdir */
- slashloc = dname + bpl_len;
- slashloc++; /* since, by construction there is a slash
- right there */
-
- while (*slashloc != '\0')
- {
- char saveslash;
-
- /* look for next slash */
- while (*slashloc != '\0' && *slashloc != '/') slashloc++;
-
- saveslash = *slashloc;
-
- *slashloc = '\0';
-
- if (mkdir(dname, 0750) != 0 && errno != EEXIST)
- {
- syslog(LOG_CRIT, "can not create dir %s: %s"
- , dname, strerror(errno));
- c->log_file_err = TRUE;
- free(dname);
- return;
- }
- syslog(LOG_DEBUG, "created new directory %s", dname);
- *slashloc = saveslash;
- slashloc++;
- }
- }
- free(dname);
- }
-
- c->log_file = fopen(c->log_file_name, "a");
- if (c->log_file == NULL)
- {
- if (c->log_file_err)
- {
- syslog(LOG_CRIT, "logging system can not open %s: %s"
- , c->log_file_name, strerror(errno));
- c->log_file_err = TRUE;
- }
- return;
- }
-
- /* look for a connection to close! */
- while (perpeer_count >= MAX_PEERLOG_COUNT)
- {
- /* can not be NULL because perpeer_count > 0 */
- passert(TAILQ_LAST(&perpeer_list, perpeer) != (void *)&perpeer_list);
-
- perpeer_logclose(TAILQ_LAST(&perpeer_list, perpeer));
- }
-
- /* insert this into the list */
- TAILQ_INSERT_HEAD(&perpeer_list, c, log_link);
- passert(c->log_file != NULL);
- perpeer_count++;
-}
-
-/* log a line to cur_connection's log */
-static void
-peerlog(const char *prefix, const char *m)
-{
- if (cur_connection == NULL)
- {
- /* we can not log it in this case. Oh well. */
- return;
- }
-
- if (cur_connection->log_file == NULL)
- {
- open_peerlog(cur_connection);
- }
-
- /* despite our attempts above, we may not be able to open the file. */
- if (cur_connection->log_file != NULL)
- {
- char datebuf[32];
- time_t n;
- struct tm *t;
-
- time(&n);
- t = localtime(&n);
-
- strftime(datebuf, sizeof(datebuf), "%Y-%m-%d %T", t);
- fprintf(cur_connection->log_file, "%s %s%s\n", datebuf, prefix, m);
-
- /* now move it to the front of the list */
- TAILQ_REMOVE(&perpeer_list, cur_connection, log_link);
- TAILQ_INSERT_HEAD(&perpeer_list, cur_connection, log_link);
- }
-}
-
-void
-plog(const char *message, ...)
-{
- va_list args;
- char m[LOG_WIDTH]; /* longer messages will be truncated */
-
- va_start(args, message);
- fmt_log(m, sizeof(m), message, args);
- va_end(args);
-
- if (log_to_stderr)
- fprintf(stderr, "%s\n", m);
- if (log_to_syslog)
- syslog(LOG_WARNING, "%s", m);
- if (log_to_perpeer)
- peerlog("", m);
-#ifdef ANDROID
- __android_log_print(ANDROID_LOG_WARN, "pluto", "%s\n", m);
-#endif
-
- whack_log(RC_LOG, "~%s", m);
-}
-
-void
-loglog(int mess_no, const char *message, ...)
-{
- va_list args;
- char m[LOG_WIDTH]; /* longer messages will be truncated */
-
- va_start(args, message);
- fmt_log(m, sizeof(m), message, args);
- va_end(args);
-
- if (log_to_stderr)
- fprintf(stderr, "%s\n", m);
- if (log_to_syslog)
- syslog(LOG_WARNING, "%s", m);
- if (log_to_perpeer)
- peerlog("", m);
-#ifdef ANDROID
- __android_log_print(ANDROID_LOG_WARN, "pluto", "%s\n", m);
-#endif
-
- whack_log(mess_no, "~%s", m);
-}
-
-void
-log_errno_routine(int e, const char *message, ...)
-{
- va_list args;
- char m[LOG_WIDTH]; /* longer messages will be truncated */
-
- va_start(args, message);
- fmt_log(m, sizeof(m), message, args);
- va_end(args);
-
- if (log_to_stderr)
- fprintf(stderr, "ERROR: %s. Errno %d: %s\n", m, e, strerror(e));
- if (log_to_syslog)
- syslog(LOG_ERR, "ERROR: %s. Errno %d: %s", m, e, strerror(e));
- if (log_to_perpeer)
- peerlog(strerror(e), m);
-#ifdef ANDROID
- __android_log_print(ANDROID_LOG_ERROR, "pluto", "ERROR: %s. Errno %d: %s\n",
- m, e, strerror(e));
-#endif
-
- whack_log(RC_LOG_SERIOUS
- , "~ERROR: %s. Errno %d: %s", m, e, strerror(e));
-}
-
-void
-exit_log(const char *message, ...)
-{
- va_list args;
- char m[LOG_WIDTH]; /* longer messages will be truncated */
-
- va_start(args, message);
- fmt_log(m, sizeof(m), message, args);
- va_end(args);
-
- if (log_to_stderr)
- fprintf(stderr, "FATAL ERROR: %s\n", m);
- if (log_to_syslog)
- syslog(LOG_ERR, "FATAL ERROR: %s", m);
- if (log_to_perpeer)
- peerlog("FATAL ERROR: ", m);
-#ifdef ANDROID
- __android_log_print(ANDROID_LOG_ERROR, "pluto", "FATAL ERROR: %s\n", m);
-#endif
-
- whack_log(RC_LOG_SERIOUS, "~FATAL ERROR: %s", m);
-
- exit_pluto(1);
-}
-
-void
-exit_log_errno_routine(int e, const char *message, ...)
-{
- va_list args;
- char m[LOG_WIDTH]; /* longer messages will be truncated */
-
- va_start(args, message);
- fmt_log(m, sizeof(m), message, args);
- va_end(args);
-
- if (log_to_stderr)
- fprintf(stderr, "FATAL ERROR: %s. Errno %d: %s\n", m, e, strerror(e));
- if (log_to_syslog)
- syslog(LOG_ERR, "FATAL ERROR: %s. Errno %d: %s", m, e, strerror(e));
- if (log_to_perpeer)
- peerlog(strerror(e), m);
-#ifdef ANDROID
- __android_log_print(ANDROID_LOG_ERROR, "pluto", "FATAL ERROR: %s. "
- "Errno %d: %s\n", m, e, strerror(e));
-#endif
-
- whack_log(RC_LOG_SERIOUS
- , "~FATAL ERROR: %s. Errno %d: %s", m, e, strerror(e));
-
- exit_pluto(1);
-}
-
-/* emit message to whack.
- * form is "ddd statename text" where
- * - ddd is a decimal status code (RC_*) as described in whack.h
- * - text is a human-readable annotation
- */
-#ifdef DEBUG
-static volatile sig_atomic_t dying_breath = FALSE;
-#endif
-
-void
-whack_log(int mess_no, const char *message, ...)
-{
- int wfd = whack_log_fd != NULL_FD ? whack_log_fd
- : cur_state != NULL ? cur_state->st_whack_sock
- : NULL_FD;
-
- if (wfd != NULL_FD
-#ifdef DEBUG
- || dying_breath
-#endif
- )
- {
- va_list args;
- char m[LOG_WIDTH]; /* longer messages will be truncated */
- int prelen = snprintf(m, sizeof(m), "%03d ", mess_no);
-
- passert(prelen >= 0);
-
- va_start(args, message);
- fmt_log(m+prelen, sizeof(m)-prelen, message, args);
- va_end(args);
-
-#if DEBUG
- if (dying_breath)
- {
- /* status output copied to log */
- if (log_to_stderr)
- fprintf(stderr, "%s\n", m + prelen);
- if (log_to_syslog)
- syslog(LOG_WARNING, "%s", m + prelen);
- if (log_to_perpeer)
- peerlog("", m);
-#ifdef ANDROID
- __android_log_print(ANDROID_LOG_WARN, "pluto", "%s\n", m + prelen);
-#endif
- }
-#endif
-
- if (wfd != NULL_FD)
- {
- /* write to whack socket, but suppress possible SIGPIPE */
- size_t len = strlen(m);
-#ifdef MSG_NOSIGNAL /* depends on version of glibc??? */
- m[len] = '\n'; /* don't need NUL, do need NL */
- (void) send(wfd, m, len + 1, MSG_NOSIGNAL);
-#else /* !MSG_NOSIGNAL */
- int r;
- struct sigaction act
- , oldact;
-
- m[len] = '\n'; /* don't need NUL, do need NL */
- act.sa_handler = SIG_IGN;
- sigemptyset(&act.sa_mask);
- act.sa_flags = 0; /* no nothing */
- r = sigaction(SIGPIPE, &act, &oldact);
- passert(r == 0);
-
- (void) write(wfd, m, len + 1);
-
- r = sigaction(SIGPIPE, &oldact, NULL);
- passert(r == 0);
-#endif /* !MSG_NOSIGNAL */
- }
- }
-}
-
-/* Build up a diagnostic in a static buffer.
- * Although this would be a generally useful function, it is very
- * hard to come up with a discipline that prevents different uses
- * from interfering. It is intended that by limiting it to building
- * diagnostics, we will avoid this problem.
- * Juggling is performed to allow an argument to be a previous
- * result: the new string may safely depend on the old one. This
- * restriction is not checked in any way: violators will produce
- * confusing results (without crashing!).
- */
-char diag_space[sizeof(diag_space)];
-
-err_t
-builddiag(const char *fmt, ...)
-{
- static char diag_space[LOG_WIDTH]; /* longer messages will be truncated */
- char t[sizeof(diag_space)]; /* build result here first */
- va_list args;
-
- va_start(args, fmt);
- t[0] = '\0'; /* in case nothing terminates string */
- vsnprintf(t, sizeof(t), fmt, args);
- va_end(args);
- strcpy(diag_space, t);
- return diag_space;
-}
-
-/* Debugging message support */
-
-#ifdef DEBUG
-
-void
-switch_fail(int n, const char *file_str, unsigned long line_no)
-{
- char buf[30];
-
- snprintf(buf, sizeof(buf), "case %d unexpected", n);
- passert_fail(buf, file_str, line_no);
-}
-
-void
-passert_fail(const char *pred_str, const char *file_str, unsigned long line_no)
-{
- /* we will get a possibly unplanned prefix. Hope it works */
- loglog(RC_LOG_SERIOUS, "ASSERTION FAILED at %s:%lu: %s", file_str, line_no, pred_str);
- if (!dying_breath)
- {
- dying_breath = TRUE;
- show_status(TRUE, NULL);
- }
- abort(); /* exiting correctly doesn't always work */
-}
-
-void
-pexpect_log(const char *pred_str, const char *file_str, unsigned long line_no)
-{
- /* we will get a possibly unplanned prefix. Hope it works */
- loglog(RC_LOG_SERIOUS, "EXPECTATION FAILED at %s:%lu: %s", file_str, line_no, pred_str);
-}
-
-lset_t
- base_debugging = DBG_NONE, /* default to reporting nothing */
- cur_debugging = DBG_NONE;
-
-void
-extra_debugging(const connection_t *c)
-{
- if(c == NULL)
- {
- reset_debugging();
- return;
- }
-
- if (c!= NULL && c->extra_debugging != 0)
- {
- plog("enabling for connection: %s"
- , bitnamesof(debug_bit_names, c->extra_debugging & ~cur_debugging));
- cur_debugging |= c->extra_debugging;
- }
-}
-
-/* log a debugging message (prefixed by "| ") */
-
-void
-DBG_log(const char *message, ...)
-{
- va_list args;
- char m[LOG_WIDTH]; /* longer messages will be truncated */
-
- va_start(args, message);
- vsnprintf(m, sizeof(m), message, args);
- va_end(args);
-
- (void)sanitize(m, sizeof(m));
-
- if (log_to_stderr)
- fprintf(stderr, "| %s\n", m);
- if (log_to_syslog)
- syslog(LOG_DEBUG, "| %s", m);
- if (log_to_perpeer)
- peerlog("| ", m);
-#ifdef ANDROID
- __android_log_print(ANDROID_LOG_DEBUG, "pluto", "| %s\n", m);
-#endif
-}
-
-/* dump raw bytes in hex to stderr (for lack of any better destination) */
-
-void
-DBG_dump(const char *label, const void *p, size_t len)
-{
-# define DUMP_LABEL_WIDTH 20 /* arbitrary modest boundary */
-# define DUMP_WIDTH (4 * (1 + 4 * 3) + 1)
- char buf[DUMP_LABEL_WIDTH + DUMP_WIDTH];
- char *bp;
- const unsigned char *cp = p;
-
- bp = buf;
-
- if (label != NULL && label[0] != '\0')
- {
- /* Handle the label. Care must be taken to avoid buffer overrun. */
- size_t llen = strlen(label);
-
- if (llen + 1 > sizeof(buf))
- {
- DBG_log("%s", label);
- }
- else
- {
- strcpy(buf, label);
- if (buf[llen-1] == '\n')
- {
- buf[llen-1] = '\0'; /* get rid of newline */
- DBG_log("%s", buf);
- }
- else if (llen < DUMP_LABEL_WIDTH)
- {
- bp = buf + llen;
- }
- else
- {
- DBG_log("%s", buf);
- }
- }
- }
-
- do {
- int i, j;
-
- for (i = 0; len!=0 && i!=4; i++)
- {
- *bp++ = ' ';
- for (j = 0; len!=0 && j!=4; len--, j++)
- {
- static const char hexdig[] = "0123456789abcdef";
-
- *bp++ = ' ';
- *bp++ = hexdig[(*cp >> 4) & 0xF];
- *bp++ = hexdig[*cp & 0xF];
- cp++;
- }
- }
- *bp = '\0';
- DBG_log("%s", buf);
- bp = buf;
- } while (len != 0);
-# undef DUMP_LABEL_WIDTH
-# undef DUMP_WIDTH
-}
-
-#endif /* DEBUG */
-
-static void show_loaded_plugins()
-{
- whack_log(RC_COMMENT, "loaded plugins: %s",
- lib->plugins->loaded_plugins(lib->plugins));
-}
-
-void show_status(bool all, const char *name)
-{
- if (all)
- {
- whack_log(RC_COMMENT, "Status of IKEv1 pluto daemon (strongSwan "VERSION"):");
- show_ifaces_status();
- show_myid_status();
- show_loaded_plugins();
- show_debug_status();
- show_pools(name);
- whack_log(RC_COMMENT, BLANK_FORMAT); /* spacer */
- }
- show_connections_status(all, name);
- show_states_status(all, name);
-}
-
-/* ip_str: a simple to use variant of addrtot.
- * It stores its result in a static buffer.
- * This means that newer calls overwrite the storage of older calls.
- * Note: this is not used in any of the logging functions, so their
- * callers may use it.
- */
-const char *
-ip_str(const ip_address *src)
-{
- static char buf[ADDRTOT_BUF];
-
- addrtot(src, 0, buf, sizeof(buf));
- return buf;
-}
-
-/*
- * a routine that attempts to schedule itself daily.
- *
- */
-
-void
-daily_log_reset(void)
-{
- /* now perform actions */
- logged_txt_warning = FALSE;
-
- logged_myid_fqdn_txt_warning = FALSE;
- logged_myid_ip_txt_warning = FALSE;
- logged_myid_fqdn_key_warning = FALSE;
- logged_myid_ip_key_warning = FALSE;
-}
-
-void
-daily_log_event(void)
-{
- struct tm lt;
- time_t t, interval;
-
- /* attempt to schedule oneself to midnight, local time
- * do this by getting seconds in the day, and delaying
- * by 86400 - 3600*hours - 60*minutes - seconds.
- */
- time(&t);
- localtime_r(&t, &lt);
- interval = 3600 * (24 - lt.tm_hour) - 60 * lt.tm_min - lt.tm_sec;
-
- event_schedule(EVENT_LOG_DAILY, interval, NULL);
- daily_log_reset();
-}
-
-/*
- * Local Variables:
- * c-basic-offset:4
- * c-style: pluto
- * End:
- */
diff --git a/src/pluto/log.h b/src/pluto/log.h
deleted file mode 100644
index 52c01bbd4..000000000
--- a/src/pluto/log.h
+++ /dev/null
@@ -1,234 +0,0 @@
-/* logging definitions
- * Copyright (C) 1998-2001 D. Hugh Redelmeier.
- *
- * 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 <freeswan.h>
-
-#define LOG_WIDTH 1024 /* roof of number of chars in log line */
-
-#ifndef PERPEERLOGDIR
-#define PERPEERLOGDIR "/var/log/pluto/peer"
-#endif
-
-/* our versions of assert: log result */
-
-#ifdef DEBUG
-
-extern void passert_fail(const char *pred_str
- , const char *file_str, unsigned long line_no) NEVER_RETURNS;
-
-extern void pexpect_log(const char *pred_str
- , const char *file_str, unsigned long line_no);
-
-# define impossible() passert_fail("impossible", __FILE__, __LINE__)
-
-extern void switch_fail(int n
- , const char *file_str, unsigned long line_no) NEVER_RETURNS;
-
-# define bad_case(n) switch_fail((int) n, __FILE__, __LINE__)
-
-# define passert(pred) { \
- if (!(pred)) \
- passert_fail(#pred, __FILE__, __LINE__); \
- }
-
-# define pexpect(pred) { \
- if (!(pred)) \
- pexpect_log(#pred, __FILE__, __LINE__); \
- }
-
-/* assert that an err_t is NULL; evaluate exactly once */
-# define happy(x) { \
- err_t ugh = x; \
- if (ugh != NULL) \
- passert_fail(ugh, __FILE__, __LINE__); \
- }
-
-#else /*!DEBUG*/
-
-# define impossible() abort()
-# define bad_case(n) abort()
-# define passert(pred) { } /* do nothing */
-# define happy(x) { (void) x; } /* evaluate non-judgementally */
-
-#endif /*!DEBUG*/
-
-
-extern bool
- log_to_stderr, /* should log go to stderr? */
- log_to_syslog, /* should log go to syslog? */
- log_to_perpeer; /* should log go to per-IP file? */
-
-extern const char *base_perpeer_logdir;
-
-/* maximum number of files to keep open for per-peer log files */
-#define MAX_PEERLOG_COUNT 16
-
-/* Context for logging.
- *
- * Global variables: must be carefully adjusted at transaction boundaries!
- * All are to be left in RESET condition and will be checked.
- * There are several pairs of routines to set and reset them.
- * If the context provides a whack file descriptor, messages
- * should be copied to it -- see whack_log()
- */
-extern int whack_log_fd; /* only set during whack_handle() */
-extern struct state *cur_state; /* current state, for diagnostics */
-extern struct connection *cur_connection; /* current connection, for diagnostics */
-extern const ip_address *cur_from; /* source of current current message */
-extern u_int16_t cur_from_port; /* host order */
-
-#ifdef DEBUG
-
- extern lset_t cur_debugging; /* current debugging level */
-
- extern void extra_debugging(const struct connection *c);
-
-# define reset_debugging() { cur_debugging = base_debugging; }
-
-# define GLOBALS_ARE_RESET() (whack_log_fd == NULL_FD \
- && cur_state == NULL \
- && cur_connection == NULL \
- && cur_from == NULL \
- && cur_debugging == base_debugging)
-
-#else /*!DEBUG*/
-
-# define extra_debugging(c) { }
-
-# define reset_debugging() { }
-
-# define GLOBALS_ARE_RESET() (whack_log_fd == NULL_FD \
- && cur_state == NULL \
- && cur_connection == NULL \
- && cur_from == NULL)
-
-#endif /*!DEBUG*/
-
-#define reset_globals() { \
- whack_log_fd = NULL_FD; \
- cur_state = NULL; \
- cur_from = NULL; \
- reset_cur_connection(); \
- }
-
-
-#define set_cur_connection(c) { \
- cur_connection = (c); \
- extra_debugging(c); \
- }
-
-#define reset_cur_connection() { \
- cur_connection = NULL; \
- reset_debugging(); \
- }
-
-
-#define set_cur_state(s) { \
- cur_state = (s); \
- extra_debugging((s)->st_connection); \
- }
-
-#define reset_cur_state() { \
- cur_state = NULL; \
- reset_debugging(); \
- }
-
-extern void init_log(const char *program);
-extern void close_log(void);
-extern void plog(const char *message, ...) PRINTF_LIKE(1);
-extern void exit_log(const char *message, ...) PRINTF_LIKE(1) NEVER_RETURNS;
-
-/* close of all per-peer logging */
-extern void close_peerlog(void);
-
-/* free all per-peer log resources */
-extern void perpeer_logfree(struct connection *c);
-
-
-
-/* the following routines do a dance to capture errno before it is changed
- * A call must doubly parenthesize the argument list (no varargs macros).
- * The first argument must be "e", the local variable that captures errno.
- */
-#define log_errno(a) { int e = errno; log_errno_routine a; }
-extern void log_errno_routine(int e, const char *message, ...) PRINTF_LIKE(2);
-#define exit_log_errno(a) { int e = errno; exit_log_errno_routine a; }
-extern void exit_log_errno_routine(int e, const char *message, ...) PRINTF_LIKE(2) NEVER_RETURNS NEVER_RETURNS;
-
-extern void whack_log(int mess_no, const char *message, ...) PRINTF_LIKE(2);
-
-/* Log to both main log and whack log
- * Much like log, actually, except for specifying mess_no.
- */
-extern void loglog(int mess_no, const char *message, ...) PRINTF_LIKE(2);
-
-/* show status, usually on whack log */
-extern void show_status(bool all, const char *name);
-
-/* Build up a diagnostic in a static buffer.
- * Although this would be a generally useful function, it is very
- * hard to come up with a discipline that prevents different uses
- * from interfering. It is intended that by limiting it to building
- * diagnostics, we will avoid this problem.
- * Juggling is performed to allow an argument to be a previous
- * result: the new string may safely depend on the old one. This
- * restriction is not checked in any way: violators will produce
- * confusing results (without crashing!).
- */
-extern char diag_space[LOG_WIDTH]; /* output buffer, but can be occupied at call */
-extern err_t builddiag(const char *fmt, ...) PRINTF_LIKE(1);
-
-#ifdef DEBUG
-
-extern lset_t base_debugging; /* bits selecting what to report */
-
-#define DBGP(cond) (cur_debugging & (cond))
-#define DBG(cond, action) { if (DBGP(cond)) { action ; } }
-
-extern void DBG_log(const char *message, ...) PRINTF_LIKE(1);
-extern void DBG_dump(const char *label, const void *p, size_t len);
-#define DBG_dump_chunk(label, ch) DBG_dump(label, (ch).ptr, (ch).len)
-
-#else /*!DEBUG*/
-
-#define DBG(cond, action) { } /* do nothing */
-
-#endif /*!DEBUG*/
-
-#define DBG_cond_dump(cond, label, p, len) DBG(cond, DBG_dump(label, p, len))
-#define DBG_cond_dump_chunk(cond, label, ch) DBG(cond, DBG_dump_chunk(label, ch))
-
-
-/* ip_str: a simple to use variant of addrtot.
- * It stores its result in a static buffer.
- * This means that newer calls overwrite the storage of older calls.
- * Note: this is not used in any of the logging functions, so their
- * callers may use it.
- */
-extern const char *ip_str(const ip_address *src);
-
-/*
- * call this routine to reset daily items.
- */
-extern void daily_log_reset(void);
-extern void daily_log_event(void);
-
-/*
- * some events are to be logged only occasionally.
- */
-extern bool logged_txt_warning;
-extern bool logged_myid_ip_txt_warning;
-extern bool logged_myid_ip_key_warning;
-extern bool logged_myid_fqdn_txt_warning;
-extern bool logged_myid_fqdn_key_warning;
diff --git a/src/pluto/modecfg.c b/src/pluto/modecfg.c
deleted file mode 100644
index 8298ea601..000000000
--- a/src/pluto/modecfg.c
+++ /dev/null
@@ -1,1263 +0,0 @@
-/* Mode config related functions
- * Copyright (C) 2001-2002 Colubris Networks
- * Copyright (C) 2003 Sean Mathews - Nu Tech Software Solutions, inc.
- * Copyright (C) 2003-2004 Xelerance Corporation
- * Copyright (C) 2006-2010 Andreas Steffen - Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * This code originally written by Colubris Networks, Inc.
- * Extraction of patch and porting to 1.99 codebases by Xelerance Corporation
- * Porting to 2.x by Sean Mathews
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <freeswan.h>
-
-#include <library.h>
-#include <hydra.h>
-#include <utils/linked_list.h>
-#include <crypto/prfs/prf.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "state.h"
-#include "demux.h"
-#include "timer.h"
-#include "ipsec_doi.h"
-#include "log.h"
-#include "crypto.h"
-#include "modecfg.h"
-#include "whack.h"
-#include "pluto.h"
-
-#define MAX_XAUTH_TRIES 3
-
-#define DEFAULT_UNITY_BANNER "Welcome to strongSwan - the Linux VPN Solution!\n"
-
-/**
- * Creates a modecfg_attribute_t object
- */
-static modecfg_attribute_t *modecfg_attribute_create(configuration_attribute_type_t type,
- chunk_t value)
-{
- modecfg_attribute_t *this;
-
- this = malloc_thing(modecfg_attribute_t);
- this->type = ((u_int16_t)type) & 0x7FFF;
- this->is_tv = FALSE;
- this->value = chunk_clone(value);
- this->handler = NULL;
-
- return this;
-}
-
-/**
- * Creates a modecfg_attribute_t object coded in TV format
- */
-static modecfg_attribute_t *modecfg_attribute_create_tv(configuration_attribute_type_t type,
- size_t value)
-{
- modecfg_attribute_t *this;
-
- this = modecfg_attribute_create(type, chunk_empty);
- this->value.len = value;
- this->is_tv = TRUE;
-
- return this;
-}
-
-/**
- * Destroys a modecfg_attribute_t object
- */
-void modecfg_attribute_destroy(modecfg_attribute_t *this)
-{
- free(this->value.ptr);
- free(this);
-}
-
-/**
- * Get attributes to be sent to client
- */
-static void get_attributes(connection_t *c, linked_list_t *ca_list)
-{
- configuration_attribute_type_t type;
- identification_t *client_id;
- modecfg_attribute_t *ca;
- enumerator_t *enumerator;
- chunk_t value;
- host_t *vip = NULL, *requested_vip = NULL;
- bool want_unity_banner = FALSE;
- int family;
-
-#ifdef CISCO_QUIRKS
- /* always send banner in ModeCfg push mode */
- if (ca_list->get_count(ca_list) == 0)
- {
- want_unity_banner = TRUE;
- }
-#endif
-
- /* scan list of requested attributes in ModeCfg pull mode */
- while (ca_list->remove_last(ca_list, (void **)&ca) == SUCCESS)
- {
- switch (ca->type)
- {
- case INTERNAL_IP4_ADDRESS:
- case INTERNAL_IP6_ADDRESS:
- {
- int family;
-
- family = (ca->type == INTERNAL_IP4_ADDRESS) ? AF_INET : AF_INET6;
- DESTROY_IF(requested_vip);
- requested_vip = (ca->value.len) ?
- host_create_from_chunk(family, ca->value, 0) :
- host_create_any(family);
- plog("peer requested virtual IP %H", requested_vip);
- break;
- }
-#ifdef CISCO_QUIRKS
- case UNITY_BANNER:
- want_unity_banner = TRUE;
- break;
-#endif
- default:
- break;
- }
- modecfg_attribute_destroy(ca);
- }
-
- if (requested_vip == NULL)
- {
- requested_vip = host_create_any(AF_INET);
- }
-
- client_id = (c->xauth_identity) ? c->xauth_identity : c->spd.that.id;
-
- /* if no virtual IP has been assigned yet - acquire one */
- if (c->spd.that.host_srcip->is_anyaddr(c->spd.that.host_srcip))
- {
- if (c->spd.that.pool)
- {
- vip = hydra->attributes->acquire_address(hydra->attributes,
- c->spd.that.pool, client_id, requested_vip);
- if (vip)
- {
- c->spd.that.host_srcip->destroy(c->spd.that.host_srcip);
- c->spd.that.host_srcip = vip;
- }
- }
- else
- {
- plog("no virtual IP found");
- }
- }
-
- requested_vip->destroy(requested_vip);
-
- /* if we have a virtual IP address - send it */
- if (!c->spd.that.host_srcip->is_anyaddr(c->spd.that.host_srcip))
- {
- vip = c->spd.that.host_srcip;
- plog("assigning virtual IP %H to peer", vip);
- family = vip->get_family(vip);
- ca = modecfg_attribute_create((family == AF_INET) ?
- INTERNAL_IP4_ADDRESS :
- INTERNAL_IP6_ADDRESS,
- vip->get_address(vip));
- ca_list->insert_last(ca_list, ca);
-
- /* set the remote client subnet to virtual IP */
- c->spd.that.client.addr = *(ip_address*)vip->get_sockaddr(vip);
- c->spd.that.client.maskbits = (family == AF_INET) ? 32 : 128;
- c->spd.that.has_client = TRUE;
- }
-
- /* assign attributes from registered providers */
- enumerator = hydra->attributes->create_responder_enumerator(hydra->attributes,
- c->spd.that.pool, client_id, vip);
- while (enumerator->enumerate(enumerator, &type, &value))
- {
- ca = modecfg_attribute_create(type, value);
- ca_list->insert_last(ca_list, ca);
- if (type == UNITY_BANNER)
- {
- want_unity_banner = FALSE;
- }
- }
- enumerator->destroy(enumerator);
-
- if (want_unity_banner)
- {
- ca = modecfg_attribute_create(UNITY_BANNER,
- chunk_create(DEFAULT_UNITY_BANNER,
- strlen(DEFAULT_UNITY_BANNER)));
- ca_list->insert_last(ca_list, ca);
- }
-}
-
-/**
- * Set srcip and client subnet to internal IP address
- */
-static bool set_attributes(connection_t *c, linked_list_t *ca_list)
-{
- host_t *vip, *srcip;
- modecfg_attribute_t *ca, *ca_handler;
- enumerator_t *enumerator;
- bool vip_set = FALSE;
-
- enumerator = ca_list->create_enumerator(ca_list);
- while (enumerator->enumerate(enumerator, &ca))
- {
- int family = AF_INET6;
- attribute_handler_t *handler = NULL;
- enumerator_t *e;
-
- switch (ca->type)
- {
- case INTERNAL_IP4_ADDRESS:
- family = AF_INET;
- /* fall */
- case INTERNAL_IP6_ADDRESS:
- if (ca->value.len == 0)
- {
- vip = host_create_any(family);
- }
- else
- {
- /* skip prefix byte in IPv6 payload*/
- if (family == AF_INET6)
- {
- ca->value.len = 16;
- }
- vip = host_create_from_chunk(family, ca->value, 0);
- }
- if (vip)
- {
- srcip = c->spd.this.host_srcip;
-
- if (srcip->is_anyaddr(srcip) || srcip->equals(srcip, vip))
- {
- plog("setting virtual IP source address to %H", vip);
- }
- else
- {
- plog("replacing virtual IP source address %H by %H",
- srcip, vip);
- }
- srcip->destroy(srcip);
- c->spd.this.host_srcip = vip;
-
- /* setting client subnet to vip/32 */
- addrtosubnet((ip_address*)vip->get_sockaddr(vip),
- &c->spd.this.client);
- setportof(0, &c->spd.this.client.addr);
- c->spd.this.has_client = TRUE;
-
- vip_set = TRUE;
- }
- continue;
- case APPLICATION_VERSION:
-#ifdef CISCO_QUIRKS
- case UNITY_BANNER:
-#endif
- if (ca->value.len > 0)
- {
- DBG(DBG_PARSING | DBG_CONTROLMORE,
- DBG_log(" '%.*s'", ca->value.len, ca->value.ptr)
- )
- }
- break;
- default:
- break;
- }
-
- /* find the first handler which requested this attribute */
- e = c->requested->create_enumerator(c->requested);
- while (e->enumerate(e, &ca_handler))
- {
- if (ca_handler->type == ca->type)
- {
- handler = ca_handler->handler;
- break;
- }
- }
- e->destroy(e);
-
- /* and pass it to the handle function */
- handler = hydra->attributes->handle(hydra->attributes,
- c->spd.that.id, handler, ca->type, ca->value);
- if (handler)
- {
- ca_handler = modecfg_attribute_create(ca->type, ca->value);
- ca_handler->handler = handler;
-
- if (c->attributes == NULL)
- {
- c->attributes = linked_list_create();
- }
- c->attributes->insert_last(c->attributes, ca_handler);
- }
- }
- enumerator->destroy(enumerator);
- c->requested->destroy_function(c->requested, (void*)modecfg_attribute_destroy);
- c->requested = NULL;
- return vip_set;
-}
-
-/**
- * Register configuration attribute handlers
- */
-static void register_attribute_handlers(connection_t *c)
-{
- configuration_attribute_type_t type;
- modecfg_attribute_t *ca;
- chunk_t value;
- attribute_handler_t *handler;
- enumerator_t *enumerator;
-
- /* add configuration attributes requested by handlers */
- if (c->requested == NULL)
- {
- c->requested = linked_list_create();
- }
- enumerator = hydra->attributes->create_initiator_enumerator(
- hydra->attributes,c->spd.that.id, c->spd.this.host_srcip);
- while (enumerator->enumerate(enumerator, &handler, &type, &value))
- {
- ca = modecfg_attribute_create(type, value);
- ca->handler = handler;
- c->requested->insert_last(c->requested, ca);
- }
- enumerator->destroy(enumerator);
-}
-
-/**
- * Compute HASH of Mode Config.
- */
-static size_t modecfg_hash(u_char *dest, u_char *start, u_char *roof,
- const struct state *st)
-{
- chunk_t msgid_chunk = chunk_from_thing(st->st_msgid);
- chunk_t msg_chunk = { start, roof - start };
- size_t prf_block_size;
- pseudo_random_function_t prf_alg;
- prf_t *prf;
-
- prf_alg = oakley_to_prf(st->st_oakley.hash);
- prf = lib->crypto->create_prf(lib->crypto, prf_alg);
- prf->set_key(prf, st->st_skeyid_a);
- prf->get_bytes(prf, msgid_chunk, NULL);
- prf->get_bytes(prf, msg_chunk, dest);
- prf_block_size = prf->get_block_size(prf);
- prf->destroy(prf);
-
- DBG(DBG_CRYPT,
- DBG_log("ModeCfg HASH computed:");
- DBG_dump("", dest, prf_block_size)
- )
- return prf_block_size;
-}
-
-
-/**
- * Generate an IKE message containing ModeCfg information (eg: IP, DNS, WINS)
- */
-static stf_status modecfg_build_msg(struct state *st, pb_stream *rbody,
- u_int16_t msg_type, linked_list_t *ca_list,
- u_int16_t ap_id)
-{
- u_char *r_hash_start, *r_hashval;
- struct isakmp_mode_attr attrh;
- struct isakmp_attribute attr;
- pb_stream strattr,attrval;
- enumerator_t *enumerator;
- modecfg_attribute_t *ca;
-
- START_HASH_PAYLOAD(*rbody, ISAKMP_NEXT_ATTR);
-
- attrh.isama_np = ISAKMP_NEXT_NONE;
- attrh.isama_type = msg_type;
- attrh.isama_identifier = ap_id;
-
- if (!out_struct(&attrh, &isakmp_attr_desc, rbody, &strattr))
- {
- return STF_INTERNAL_ERROR;
- }
-
- enumerator = ca_list->create_enumerator(ca_list);
- while (enumerator->enumerate(enumerator, &ca))
- {
- DBG(DBG_CONTROLMORE,
- DBG_log("building %N attribute", configuration_attribute_type_names, ca->type)
- )
- if (ca->is_tv)
- {
- attr.isaat_af_type = ca->type | ISAKMP_ATTR_AF_TV;
- attr.isaat_lv = ca->value.len;
- out_struct(&attr, &isakmp_modecfg_attribute_desc, &strattr, &attrval);
- }
- else
- {
- char buf[BUF_LEN];
-
- attr.isaat_af_type = ca->type | ISAKMP_ATTR_AF_TLV;
- out_struct(&attr, &isakmp_modecfg_attribute_desc, &strattr, &attrval);
- snprintf(buf, BUF_LEN, "%N", configuration_attribute_type_names, ca->type);
- out_raw(ca->value.ptr, ca->value.len, &attrval, buf);
- }
- close_output_pbs(&attrval);
- }
- enumerator->destroy(enumerator);
- close_output_pbs(&strattr);
-
- modecfg_hash(r_hashval, r_hash_start, rbody->cur, st);
- close_message(rbody);
- encrypt_message(rbody, st);
- return STF_OK;
-}
-
-/**
- * Send ModeCfg message
- */
-static stf_status modecfg_send_msg(struct state *st, int isama_type,
- linked_list_t *ca_list)
-{
- pb_stream msg;
- pb_stream rbody;
- char buf[BUF_LEN];
-
- /* set up attr */
- init_pbs(&msg, buf, sizeof(buf), "ModeCfg msg buffer");
-
- /* this is the beginning of a new exchange */
- st->st_msgid = generate_msgid(st);
- init_phase2_iv(st, &st->st_msgid);
-
- /* HDR out */
- {
- struct isakmp_hdr hdr;
-
- zero(&hdr); /* default to 0 */
- hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION;
- hdr.isa_np = ISAKMP_NEXT_HASH;
- hdr.isa_xchg = ISAKMP_XCHG_MODE_CFG;
- hdr.isa_flags = ISAKMP_FLAG_ENCRYPTION;
- memcpy(hdr.isa_icookie, st->st_icookie, COOKIE_SIZE);
- memcpy(hdr.isa_rcookie, st->st_rcookie, COOKIE_SIZE);
- hdr.isa_msgid = st->st_msgid;
-
- if (!out_struct(&hdr, &isakmp_hdr_desc, &msg, &rbody))
- {
- return STF_INTERNAL_ERROR;
- }
- }
-
- /* ATTR out with isama_id of 0 */
- modecfg_build_msg(st, &rbody, isama_type, ca_list, 0);
-
- free(st->st_tpacket.ptr);
- st->st_tpacket = chunk_create(msg.start, pbs_offset(&msg));
- st->st_tpacket = chunk_clone(st->st_tpacket);
-
- /* Transmit */
- send_packet(st, "ModeCfg msg");
-
- if (st->st_event->ev_type != EVENT_RETRANSMIT)
- {
- delete_event(st);
- event_schedule(EVENT_RETRANSMIT, EVENT_RETRANSMIT_DELAY_0, st);
- }
- return STF_OK;
-}
-
-/**
- * Parse a ModeCfg attribute payload
- */
-static stf_status modecfg_parse_attributes(pb_stream *attrs, linked_list_t *ca_list)
-{
- struct isakmp_attribute attr;
- pb_stream strattr;
- u_int16_t attr_type;
- u_int16_t attr_len;
- chunk_t attr_chunk;
- modecfg_attribute_t *ca;
-
- while (pbs_left(attrs) >= sizeof(struct isakmp_attribute))
- {
- if (!in_struct(&attr, &isakmp_modecfg_attribute_desc, attrs, &strattr))
- {
- return STF_FAIL;
- }
- attr_type = attr.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK;
- attr_len = attr.isaat_lv;
- DBG(DBG_CONTROLMORE,
- DBG_log("processing %N attribute",
- configuration_attribute_type_names, attr_type)
- )
-
- switch (attr_type)
- {
- case INTERNAL_IP4_ADDRESS:
- case INTERNAL_IP4_NETMASK:
- case INTERNAL_IP4_DNS:
- case INTERNAL_IP4_NBNS:
- case INTERNAL_ADDRESS_EXPIRY:
- case INTERNAL_IP4_DHCP:
- if (attr_len != 4 && attr_len != 0)
- {
- goto error;
- }
- break;
- case INTERNAL_IP4_SUBNET:
- if (attr_len != 8 && attr_len != 0)
- {
- goto error;
- }
- break;
- case INTERNAL_IP6_NETMASK:
- case INTERNAL_IP6_DNS:
- case INTERNAL_IP6_NBNS:
- case INTERNAL_IP6_DHCP:
- if (attr_len != 16 && attr_len != 0)
- {
- goto error;
- }
- break;
- case INTERNAL_IP6_ADDRESS:
- if (attr_len != 17 && attr_len != 16 && attr_len != 0)
- {
- goto error;
- }
- break;
- case INTERNAL_IP6_SUBNET:
- if (attr_len != 17 && attr_len != 0)
- {
- goto error;
- }
- break;
- case SUPPORTED_ATTRIBUTES:
- if (attr_len % 2)
- {
- goto error;
- }
- break;
- case APPLICATION_VERSION:
- break;
- /* XAUTH attributes */
- case XAUTH_TYPE:
- case XAUTH_STATUS:
- case XAUTH_USER_NAME:
- case XAUTH_USER_PASSWORD:
- case XAUTH_PASSCODE:
- case XAUTH_MESSAGE:
- case XAUTH_CHALLENGE:
- case XAUTH_DOMAIN:
- case XAUTH_NEXT_PIN:
- case XAUTH_ANSWER:
- break;
- /* Microsoft attributes */
- case INTERNAL_IP4_SERVER:
- case INTERNAL_IP6_SERVER:
- break;
- /* Cisco Unity attributes */
- case UNITY_BANNER:
- case UNITY_SAVE_PASSWD:
- case UNITY_DEF_DOMAIN:
- case UNITY_SPLITDNS_NAME:
- case UNITY_SPLIT_INCLUDE:
- case UNITY_NATT_PORT:
- case UNITY_LOCAL_LAN:
- case UNITY_PFS:
- case UNITY_FW_TYPE:
- case UNITY_BACKUP_SERVERS:
- case UNITY_DDNS_HOSTNAME:
- break;
- default:
- plog("unknown attribute type (%u)", attr_type);
- continue;
- }
-
- /* add attribute */
- if (attr.isaat_af_type & ISAKMP_ATTR_AF_TV)
- {
- ca = modecfg_attribute_create_tv(attr_type, attr_len);
- }
- else
- {
- attr_chunk = chunk_create(strattr.cur, attr_len);
- ca = modecfg_attribute_create(attr_type, attr_chunk);
- }
- ca_list->insert_last(ca_list, ca);
- }
- return STF_OK;
-
-error:
- plog("%N attribute has invalid size of %u octets",
- configuration_attribute_type_names, attr_type, attr_len);
- return STF_FAIL;
-}
-
-/**
- * Parse a ModeCfg message
- */
-static stf_status modecfg_parse_msg(struct msg_digest *md, int isama_type,
- u_int16_t *isama_id, linked_list_t *ca_list)
-{
- modecfg_attribute_t *ca;
- struct state *const st = md->st;
- struct payload_digest *p;
- stf_status stat;
-
- st->st_msgid = md->hdr.isa_msgid;
-
- CHECK_QUICK_HASH(md, modecfg_hash(hash_val, hash_pbs->roof,
- md->message_pbs.roof, st), "MODECFG-HASH", "ISAKMP_CFG_MSG");
-
- /* process the ModeCfg payloads received */
- for (p = md->chain[ISAKMP_NEXT_ATTR]; p != NULL; p = p->next)
- {
- if (p->payload.attribute.isama_type == isama_type)
- {
- *isama_id = p->payload.attribute.isama_identifier;
-
- stat = modecfg_parse_attributes(&p->pbs, ca_list);
- if (stat == STF_OK)
- {
- /* return with a valid set of attributes */
- return STF_OK;
- }
- }
- else
- {
- plog("expected %s, got %s instead (ignored)"
- , enum_name(&attr_msg_type_names, isama_type)
- , enum_name(&attr_msg_type_names, p->payload.attribute.isama_type));
-
- stat = modecfg_parse_attributes(&p->pbs, ca_list);
- }
-
- /* abort if a parsing error occurred */
- if (stat != STF_OK)
- {
- ca_list->destroy_function(ca_list, (void*)modecfg_attribute_destroy);
- return stat;
- }
-
- /* discard the parsed attributes and look for another payload */
- while (ca_list->remove_last(ca_list, (void **)&ca) == SUCCESS) {}
- }
- return STF_IGNORE;
-}
-
-/**
- * Used in ModeCfg pull mode on the client (initiator)
- * called in demux.c
- * client -> CFG_REQUEST
- * STF_OK transitions to STATE_MODE_CFG_I1
- */
-stf_status modecfg_send_request(struct state *st)
-{
- connection_t *c = st->st_connection;
- stf_status stat;
- modecfg_attribute_t *ca;
- enumerator_t *enumerator;
- int family;
- chunk_t value;
- host_t *vip;
- linked_list_t *ca_list = linked_list_create();
-
- vip = c->spd.this.host_srcip;
- value = vip->is_anyaddr(vip) ? chunk_empty : vip->get_address(vip);
- family = vip->get_family(vip);
- ca = modecfg_attribute_create((family == AF_INET) ?
- INTERNAL_IP4_ADDRESS : INTERNAL_IP6_ADDRESS,
- value);
- ca_list->insert_last(ca_list, ca);
-
- register_attribute_handlers(c);
- enumerator = c->requested->create_enumerator(c->requested);
- while (enumerator->enumerate(enumerator, &ca))
- {
- ca = modecfg_attribute_create(ca->type, chunk_empty);
- ca_list->insert_last(ca_list, ca);
- }
- enumerator->destroy(enumerator);
-
- plog("sending ModeCfg request");
-
- st->st_state = STATE_MODE_CFG_I1;
- stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, ca_list);
- ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
- if (stat == STF_OK)
- {
- st->st_modecfg.started = TRUE;
- }
- return stat;
-}
-
-/**
- * Used in ModeCfg pull mode on the server (responder)
- * called in demux.c from STATE_MODE_CFG_R0
- * server <- CFG_REQUEST
- * server -> CFG_REPLY
- * STF_OK transitions to STATE_MODE_CFG_R0
- */
-stf_status modecfg_inR0(struct msg_digest *md)
-{
- struct state *const st = md->st;
- u_int16_t isama_id;
- stf_status stat, stat_build;
- linked_list_t *ca_list = linked_list_create();
-
- plog("parsing ModeCfg request");
-
- stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, ca_list);
- if (stat != STF_OK)
- {
- return stat;
- }
-
- /* build the CFG_REPLY */
- get_attributes(st->st_connection, ca_list);
-
- plog("sending ModeCfg reply");
-
- stat_build = modecfg_build_msg(st, &md->rbody, ISAKMP_CFG_REPLY,
- ca_list, isama_id);
- ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
-
- if (stat_build != STF_OK)
- {
- return stat_build;
- }
- st->st_msgid = 0;
- return STF_OK;
-}
-
-/**
- * Used in ModeCfg pull mode on the client (initiator)
- * called in demux.c from STATE_MODE_CFG_I1
- * client <- CFG_REPLY
- * STF_OK transitions to STATE_MODE_CFG_I2
- */
-stf_status modecfg_inI1(struct msg_digest *md)
-{
- struct state *const st = md->st;
- u_int16_t isama_id;
- stf_status stat;
- linked_list_t *ca_list = linked_list_create();
-
- plog("parsing ModeCfg reply");
-
- stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, ca_list);
- if (stat != STF_OK)
- {
- return stat;
- }
- st->st_modecfg.vars_set = set_attributes(st->st_connection, ca_list);
- st->st_msgid = 0;
- ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
- return STF_OK;
-}
-
-/**
- * Used in ModeCfg push mode on the server (responder)
- * called in demux.c
- * server -> CFG_SET
- * STF_OK transitions to STATE_MODE_CFG_R3
- */
-stf_status modecfg_send_set(struct state *st)
-{
- stf_status stat;
- linked_list_t *ca_list = linked_list_create();
-
-
- plog("sending ModeCfg set");
-
- get_attributes(st->st_connection, ca_list);
- st->st_state = STATE_MODE_CFG_R3;
- stat = modecfg_send_msg(st, ISAKMP_CFG_SET, ca_list);
- ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
- if (stat == STF_OK)
- {
- st->st_modecfg.started = TRUE;
- }
- return stat;
-}
-
-/**
- * Used in ModeCfg push mode on the client (initiator)
- * called in demux.c from STATE_MODE_CFG_I0
- * client <- CFG_SET
- * client -> CFG_ACK
- * STF_OK transitions to STATE_MODE_CFG_I3
- */
-stf_status modecfg_inI0(struct msg_digest *md)
-{
- struct state *const st = md->st;
- u_int16_t isama_id;
- stf_status stat, stat_build;
- modecfg_attribute_t *ca;
- linked_list_t *ca_list, *ca_ack_list;
-
- plog("parsing ModeCfg set");
-
- ca_list = linked_list_create();
- stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, ca_list);
- if (stat != STF_OK)
- {
- return stat;
- }
- register_attribute_handlers(st->st_connection);
- st->st_modecfg.vars_set = set_attributes(st->st_connection, ca_list);
-
- /* prepare ModeCfg ack which sends zero length attributes */
- ca_ack_list = linked_list_create();
- while (ca_list->remove_last(ca_list, (void **)&ca) == SUCCESS)
- {
- switch (ca->type)
- {
- case INTERNAL_IP4_ADDRESS:
- case INTERNAL_IP4_DNS:
- case INTERNAL_IP4_NBNS:
- case APPLICATION_VERSION:
- case INTERNAL_IP6_ADDRESS:
- case INTERNAL_IP6_DNS:
- case INTERNAL_IP6_NBNS:
-#ifdef CISCO_QUIRKS
- case UNITY_BANNER:
-#endif
- /* supported attributes */
- ca->value.len = 0;
- ca_ack_list->insert_last(ca_ack_list, ca);
- break;
- default:
- /* unsupportd attributes */
- modecfg_attribute_destroy(ca);
- }
- }
- ca_list->destroy(ca_list);
-
- plog("sending ModeCfg ack");
-
- stat_build = modecfg_build_msg(st, &md->rbody, ISAKMP_CFG_ACK,
- ca_ack_list, isama_id);
- ca_ack_list->destroy_function(ca_ack_list, (void *)modecfg_attribute_destroy);
- if (stat_build != STF_OK)
- {
- return stat_build;
- }
- st->st_msgid = 0;
- return STF_OK;
-}
-
-/**
- * Used in ModeCfg push mode on the server (responder)
- * called in demux.c from STATE_MODE_CFG_R3
- * server <- CFG_ACK
- * STF_OK transitions to STATE_MODE_CFG_R4
- */
-stf_status modecfg_inR3(struct msg_digest *md)
-{
- struct state *const st = md->st;
- u_int16_t isama_id;
- stf_status stat;
- linked_list_t *ca_list = linked_list_create();
-
- plog("parsing ModeCfg ack");
-
- stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, ca_list);
- ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
- if (stat != STF_OK)
- {
- return stat;
- }
- st->st_msgid = 0;
- return STF_OK;
-}
-
-/**
- * Used on the XAUTH server (responder)
- * called in demux.c
- * server -> CFG_REQUEST
- * STF_OK transitions to STATE_XAUTH_R1
- */
-stf_status xauth_send_request(struct state *st)
-{
- stf_status stat;
- modecfg_attribute_t *ca;
- linked_list_t *ca_list = linked_list_create();
-
- ca = modecfg_attribute_create(XAUTH_USER_NAME, chunk_empty);
- ca_list->insert_last(ca_list, ca);
- ca = modecfg_attribute_create(XAUTH_USER_PASSWORD, chunk_empty);
- ca_list->insert_last(ca_list, ca);
-
- plog("sending XAUTH request");
- st->st_state = STATE_XAUTH_R1;
- stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, ca_list);
- ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
- if (stat == STF_OK)
- {
- st->st_xauth.started = TRUE;
- }
- return stat;
-}
-
-/**
- * Used on the XAUTH client (initiator)
- * called in demux.c from STATE_XAUTH_I0
- * client <- CFG_REQUEST
- * client -> CFG_REPLY
- * STF_OK transitions to STATE_XAUTH_I1
- */
-stf_status xauth_inI0(struct msg_digest *md)
-{
- struct state *const st = md->st;
- connection_t *c = st->st_connection;
- u_int16_t isama_id;
- stf_status stat, stat_build;
- modecfg_attribute_t *ca;
- bool xauth_user_name_present = FALSE;
- bool xauth_user_password_present = FALSE;
- bool xauth_type_present = FALSE;
- chunk_t xauth_user_name, xauth_user_password;
- identification_t *user_id;
- linked_list_t *ca_list = linked_list_create();
-
- plog("parsing XAUTH request");
-
- stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, ca_list);
- if (stat != STF_OK)
- {
- return stat;
- }
-
- while (ca_list->remove_last(ca_list, (void **)&ca) == SUCCESS)
- {
- switch (ca->type)
- {
- case XAUTH_TYPE:
- if (ca->value.len != XAUTH_TYPE_GENERIC)
- {
- plog("xauth type %s is not supported",
- enum_name(&xauth_type_names, ca->value.len));
- stat = STF_FAIL;
- }
- else
- {
- xauth_type_present = TRUE;
- }
- break;
- case XAUTH_USER_NAME:
- xauth_user_name_present = TRUE;
- break;
- case XAUTH_USER_PASSWORD:
- xauth_user_password_present = TRUE;
- break;
- case XAUTH_MESSAGE:
- if (ca->value.len)
- {
- DBG(DBG_PARSING | DBG_CONTROLMORE,
- DBG_log(" '%.*s'", ca->value.len, ca->value.ptr)
- )
- }
- break;
- default:
- break;
- }
- modecfg_attribute_destroy(ca);
- }
-
- if (!xauth_user_name_present)
- {
- plog("user name attribute is missing in XAUTH request");
- stat = STF_FAIL;
- }
- if (!xauth_user_password_present)
- {
- plog("user password attribute is missing in XAUTH request");
- stat = STF_FAIL;
- }
-
- /* prepare XAUTH reply */
- if (stat == STF_OK)
- {
- /* get user credentials using a plugin function */
- if (!pluto->xauth->get_secret(pluto->xauth, c, &xauth_user_password))
- {
- plog("xauth user credentials not found");
- stat = STF_FAIL;
- }
- }
- if (stat == STF_OK)
- {
- /* insert xauth type if present */
- if (xauth_type_present)
- {
- ca = modecfg_attribute_create_tv(XAUTH_TYPE, XAUTH_TYPE_GENERIC);
- ca_list->insert_last(ca_list, ca);
- }
-
- /* insert xauth user name */
- user_id = (c->xauth_identity) ? c->xauth_identity : c->spd.this.id;
- xauth_user_name = user_id->get_encoding(user_id);
- DBG(DBG_CONTROL,
- DBG_log("my xauth user name is '%.*s'", xauth_user_name.len,
- xauth_user_name.ptr)
- )
- ca = modecfg_attribute_create(XAUTH_USER_NAME, xauth_user_name);
- ca_list->insert_last(ca_list, ca);
-
- /* insert xauth user password */
- DBG(DBG_PRIVATE,
- DBG_log("my xauth user password is '%.*s'", xauth_user_password.len,
- xauth_user_password.ptr)
- )
- ca = modecfg_attribute_create(XAUTH_USER_PASSWORD, xauth_user_password);
- ca_list->insert_last(ca_list, ca);
- chunk_clear(&xauth_user_password);
- }
- else
- {
- ca = modecfg_attribute_create_tv(XAUTH_STATUS, XAUTH_STATUS_FAIL);
- ca_list->insert_last(ca_list, ca);
- }
-
- plog("sending XAUTH reply");
- stat_build = modecfg_build_msg(st, &md->rbody, ISAKMP_CFG_REPLY,
- ca_list, isama_id);
- ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
- if (stat_build != STF_OK)
- {
- return stat_build;
- }
- if (stat == STF_OK)
- {
- st->st_xauth.started = TRUE;
- st->st_msgid = 0;
- return STF_OK;
- }
- else
- {
- /* send XAUTH reply msg and then delete ISAKMP SA */
- free(st->st_tpacket.ptr);
- st->st_tpacket = chunk_create(md->reply.start, pbs_offset(&md->reply));
- st->st_tpacket = chunk_clone(st->st_tpacket);
- send_packet(st, "XAUTH reply msg");
- delete_state(st);
- return STF_IGNORE;
- }
-}
-
-/**
- * Used on the XAUTH server (responder)
- * called in demux.c from STATE_XAUTH_R1
- server <- CFG_REPLY
- server -> CFG_SET
- STF_OK transitions to STATE_XAUTH_R2
- */
-stf_status xauth_inR1(struct msg_digest *md)
-{
- struct state *const st = md->st;
- connection_t *c = st->st_connection;
- u_int16_t isama_id;
- stf_status stat, stat_build;
- chunk_t xauth_user_name, xauth_user_password;
- int xauth_status = XAUTH_STATUS_OK;
- modecfg_attribute_t *ca;
- linked_list_t *ca_list = linked_list_create();
-
- plog("parsing XAUTH reply");
-
- stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, ca_list);
- if (stat != STF_OK)
- {
- return stat;
- }
-
- /* initialize xauth_secret */
- xauth_user_name = chunk_empty;
- xauth_user_password = chunk_empty;
-
- while (ca_list->remove_last(ca_list, (void **)&ca) == SUCCESS)
- {
- switch (ca->type)
- {
- case XAUTH_STATUS:
- xauth_status = ca->value.len;
- break;
- case XAUTH_USER_NAME:
- xauth_user_name = chunk_clone(ca->value);
- break;
- case XAUTH_USER_PASSWORD:
- xauth_user_password = chunk_clone(ca->value);
- break;
- default:
- break;
- }
- modecfg_attribute_destroy(ca);
- }
- /* did the client return an XAUTH FAIL status? */
- if (xauth_status == XAUTH_STATUS_FAIL)
- {
- plog("received FAIL status in XAUTH reply");
-
- /* client is not able to do XAUTH, delete ISAKMP SA */
- free(xauth_user_name.ptr);
- free(xauth_user_password.ptr);
- delete_state(st);
- ca_list->destroy(ca_list);
- return STF_IGNORE;
- }
-
- /* check XAUTH reply */
- if (xauth_user_name.ptr == NULL)
- {
- plog("user name attribute is missing in XAUTH reply");
- st->st_xauth.status = FALSE;
- }
- else if (xauth_user_password.ptr == NULL)
- {
- plog("user password attribute is missing in XAUTH reply");
- st->st_xauth.status = FALSE;
- }
- else
- {
- DBG(DBG_CONTROL,
- DBG_log("peer xauth user name is '%.*s'", xauth_user_name.len,
- xauth_user_name.ptr)
- )
- DESTROY_IF(c->xauth_identity);
- c->xauth_identity = identification_create_from_data(xauth_user_name);
-
- DBG(DBG_PRIVATE,
- DBG_log("peer xauth user password is '%.*s'", xauth_user_password.len,
- xauth_user_password.ptr)
- )
- /* verify the user credentials using a plugin function */
- st->st_xauth.status = pluto->xauth->verify_secret(pluto->xauth, c,
- xauth_user_password);
- plog("extended authentication %s", st->st_xauth.status? "was successful":"failed");
- }
- chunk_clear(&xauth_user_name);
- chunk_clear(&xauth_user_password);
-
- plog("sending XAUTH status");
- xauth_status = (st->st_xauth.status) ? XAUTH_STATUS_OK : XAUTH_STATUS_FAIL;
- ca = modecfg_attribute_create_tv(XAUTH_STATUS, xauth_status);
- ca_list->insert_last(ca_list, ca);
- stat_build = modecfg_send_msg(st, ISAKMP_CFG_SET, ca_list);
- ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
- if (stat_build != STF_OK)
- {
- return stat_build;
- }
- return STF_OK;
-}
-
-/**
- * Used on the XAUTH client (initiator)
- * called in demux.c from STATE_XAUTH_I1
- * client <- CFG_SET
- * client -> CFG_ACK
- * STF_OK transitions to STATE_XAUTH_I2
- */
-stf_status xauth_inI1(struct msg_digest *md)
-{
- struct state *const st = md->st;
- u_int16_t isama_id;
- stf_status stat, stat_build;
- modecfg_attribute_t *ca;
- linked_list_t *ca_list = linked_list_create();
-
- plog("parsing XAUTH status");
- stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, ca_list);
- if (stat != STF_OK)
- {
- /* notification payload - not exactly the right choice, but okay */
- md->note = ISAKMP_ATTRIBUTES_NOT_SUPPORTED;
- return stat;
- }
-
- st->st_xauth.status = FALSE;
- while (ca_list->remove_last(ca_list, (void **)&ca) == SUCCESS)
- {
- if (ca->type == XAUTH_STATUS)
- {
- st->st_xauth.status = (ca->value.len == XAUTH_STATUS_OK);
- }
- modecfg_attribute_destroy(ca);
- }
- plog("extended authentication %s", st->st_xauth.status? "was successful":"failed");
-
- plog("sending XAUTH ack");
- stat_build = modecfg_build_msg(st, &md->rbody, ISAKMP_CFG_ACK, ca_list, isama_id);
- ca_list->destroy(ca_list);
-
- if (stat_build != STF_OK)
- {
- return stat_build;
- }
- if (st->st_xauth.status)
- {
- st->st_msgid = 0;
- return STF_OK;
- }
- else
- {
- /* send XAUTH ack msg and then delete ISAKMP SA */
- free(st->st_tpacket.ptr);
- st->st_tpacket = chunk_create(md->reply.start, pbs_offset(&md->reply));
- st->st_tpacket = chunk_clone(st->st_tpacket);
- send_packet(st, "XAUTH ack msg");
- delete_state(st);
- return STF_IGNORE;
- }
-}
-
-/**
- * Used on the XAUTH server (responder)
- * called in demux.c from STATE_XAUTH_R2
- * server <- CFG_ACK
- * STF_OK transitions to STATE_XAUTH_R3
- */
-stf_status xauth_inR2(struct msg_digest *md)
-{
- struct state *const st = md->st;
- u_int16_t isama_id;
- stf_status stat;
- linked_list_t *ca_list = linked_list_create();
-
- plog("parsing XAUTH ack");
-
- stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, ca_list);
- if (stat != STF_OK)
- {
- return stat;
- }
- ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
- st->st_msgid = 0;
- if (st->st_xauth.status)
- {
- return STF_OK;
- }
- else
- {
- delete_state(st);
- return STF_IGNORE;
- }
-
-}
diff --git a/src/pluto/modecfg.h b/src/pluto/modecfg.h
deleted file mode 100644
index 7adf18682..000000000
--- a/src/pluto/modecfg.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/* Mode Config related functions
- * Copyright (C) 2001-2002 Colubris Networks
- * Copyright (C) 2003-2004 Xelerance Corporation
- *
- * 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.
- */
-
-#ifndef _MODECFG_H
-#define _MODECFG_H
-
-#include <chunk.h>
-#include <attributes/attribute_handler.h>
-
-#include "state.h"
-#include "demux.h"
-
-typedef struct modecfg_attribute_t modecfg_attribute_t;
-
-/**
- * Defines a modecfg_attribute_t object.
- */
-struct modecfg_attribute_t {
- /**
- * Type of the attribute.
- */
- u_int16_t type;
-
- /**
- * Attribute is coded as TV
- */
- bool is_tv;
-
- /**
- * Attribute value as chunk.
- */
- chunk_t value;
-
- /**
- * Attribute handler.
- */
- attribute_handler_t *handler;
-};
-
-/* Destroys a modecfg_attribute_t object */
-extern void modecfg_attribute_destroy(modecfg_attribute_t *this);
-
-/* ModeConfig pull mode start function */
-extern stf_status modecfg_send_request(struct state *st);
-
-/* ModeConfig pull mode state transition functions */
-extern stf_status modecfg_inR0(struct msg_digest *md);
-extern stf_status modecfg_inI1(struct msg_digest *md);
-
-/* ModeConfig push mode start function */
-extern stf_status modecfg_send_set(struct state *st);
-
-/* ModeConfig push mode state transition functions */
-extern stf_status modecfg_inI0(struct msg_digest *md);
-extern stf_status modecfg_inR3(struct msg_digest *md);
-
-/* XAUTH start function */
-extern stf_status xauth_send_request(struct state *st);
-
-/* XAUTH state transition funcgtions */
-extern stf_status xauth_inI0(struct msg_digest *md);
-extern stf_status xauth_inR1(struct msg_digest *md);
-extern stf_status xauth_inI1(struct msg_digest *md);
-extern stf_status xauth_inR2(struct msg_digest *md);
-
-#endif /* _MODECFG_H */
diff --git a/src/pluto/myid.c b/src/pluto/myid.c
deleted file mode 100644
index c90d14ef8..000000000
--- a/src/pluto/myid.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/* identity representation, as in IKE ID Payloads (RFC 2407 DOI 4.6.2.1)
- * Copyright (C) 1999-2001 D. Hugh Redelmeier
- *
- * 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 <errno.h>
-#include <unistd.h>
-
-#ifndef HOST_NAME_MAX /* POSIX 1003.1-2001 says <unistd.h> defines this */
-# define HOST_NAME_MAX 255 /* upper bound, according to SUSv2 */
-#endif
-
-#include <utils/identification.h>
-
-#include <freeswan.h>
-
-#include "myid.h"
-#include "constants.h"
-#include "defs.h"
-#include "log.h"
-#include "connections.h"
-#include "packet.h"
-#include "whack.h"
-
-enum myid_state myid_state = MYID_UNKNOWN;
-
-identification_t *myids[MYID_SPECIFIED+1]; /* %myid */
-
-/**
- * Fills in myid from environment variable IPSECmyid or defaultrouteaddr
- */
-void init_myid(void)
-{
- myid_state = MYID_UNKNOWN;
- {
- enum myid_state s;
-
- for (s = MYID_UNKNOWN; s <= MYID_SPECIFIED; s++)
- {
- myids[s] = identification_create_from_string("%any");
- }
- }
- set_myid(MYID_SPECIFIED, getenv("IPSECmyid"));
- set_myid(MYID_IP, getenv("defaultrouteaddr"));
- set_myFQDN();
-}
-
-/**
- * Free myid module
- */
-void free_myid(void)
-{
- enum myid_state s;
-
- for (s = MYID_UNKNOWN; s <= MYID_SPECIFIED; s++)
- {
- DESTROY_IF(myids[s]);
- }
-}
-
-void set_myid(enum myid_state s, char *idstr)
-{
- if (idstr)
- {
- myids[s]->destroy(myids[s]);
- myids[s] = identification_create_from_string(idstr);
- if (s == MYID_SPECIFIED)
- {
- myid_state = MYID_SPECIFIED;
- }
- }
-}
-
-void set_myFQDN(void)
-{
- char FQDN[HOST_NAME_MAX + 1];
- int r = gethostname(FQDN, sizeof(FQDN));
- size_t len;
-
- if (r != 0)
- {
- log_errno((e, "gethostname() failed in set_myFQDN"));
- }
- else
- {
- FQDN[sizeof(FQDN) - 1] = '\0'; /* insurance */
- len = strlen(FQDN);
-
- if (len > 0 && FQDN[len-1] == '.')
- {
- /* nuke trailing . */
- FQDN[len-1] = '\0';
- }
- if (!strcaseeq(FQDN, "localhost.localdomain"))
- {
- myids[MYID_HOSTNAME]->destroy(myids[MYID_HOSTNAME]);
- myids[MYID_HOSTNAME] = identification_create_from_string(FQDN);
- }
- }
-}
-
-void show_myid_status(void)
-{
- whack_log(RC_COMMENT, "%%myid = '%Y'", myids[myid_state]);
-}
-
-/*
- * Local Variables:
- * c-basic-offset:4
- * c-style: pluto
- * End:
- */
diff --git a/src/pluto/myid.h b/src/pluto/myid.h
deleted file mode 100644
index 012a34968..000000000
--- a/src/pluto/myid.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* identity representation, as in IKE ID Payloads (RFC 2407 DOI 4.6.2.1)
- * Copyright (C) 1999-2001 D. Hugh Redelmeier
- *
- * 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.
- */
-
-#ifndef _MYID_H
-#define _MYID_H
-
-#include <utils/identification.h>
-
-extern void init_myid(void);
-extern void free_myid(void);
-
-enum myid_state {
- MYID_UNKNOWN, /* not yet figured out */
- MYID_HOSTNAME, /* our current hostname */
- MYID_IP, /* our default IP address */
- MYID_SPECIFIED /* as specified by ipsec.conf */
-};
-
-extern enum myid_state myid_state;
-extern identification_t* myids[MYID_SPECIFIED+1]; /* %myid */
-extern void set_myid(enum myid_state s, char *);
-extern void show_myid_status(void);
-extern void set_myFQDN(void);
-
-#define resolve_myid(id) ((id)->get_type(id) == ID_MYID? myids[myid_state] : (id))
-
-#endif /* _MYID_H */
diff --git a/src/pluto/nat_traversal.c b/src/pluto/nat_traversal.c
deleted file mode 100644
index 28be76825..000000000
--- a/src/pluto/nat_traversal.c
+++ /dev/null
@@ -1,845 +0,0 @@
-/*
- * Copyright (C) 2010 Tobias Brunner
- * Copyright (C) 2009 Andreas Steffen
- * Hochschule fuer Technik Rapperswil
- * Copyright (C) 2002-2005 Mathieu Lafon
- * Arkoon Network Security
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <stdarg.h>
-#include <syslog.h>
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-#include <signal.h> /* used only if MSG_NOSIGNAL not defined */
-#include <sys/queue.h>
-
-#include <library.h>
-#include <crypto/hashers/hasher.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "log.h"
-#include "server.h"
-#include "state.h"
-#include "connections.h"
-#include "packet.h"
-#include "demux.h"
-#include "kernel.h"
-#include "whack.h"
-#include "timer.h"
-#include "cookie.h"
-#include "crypto.h"
-#include "vendor.h"
-#include "ike_alg.h"
-#include "nat_traversal.h"
-
-/* #define FORCE_NAT_TRAVERSAL */
-#define NAT_D_DEBUG
-#define NAT_T_SUPPORT_LAST_DRAFTS
-
-#ifndef SOL_UDP
-#define SOL_UDP 17
-#endif
-
-#ifndef UDP_ESPINUDP
-#define UDP_ESPINUDP 100
-#endif
-
-#define DEFAULT_KEEP_ALIVE_PERIOD 20
-
-#ifdef _IKE_ALG_H
-/* Alg patch: hash_digest_len -> hash_digest_size */
-#define hash_digest_len hash_digest_size
-#endif
-
-bool nat_traversal_enabled = FALSE;
-bool nat_traversal_support_non_ike = FALSE;
-bool nat_traversal_support_port_floating = FALSE;
-
-static unsigned int _kap = 0;
-static unsigned int _ka_evt = 0;
-static bool _force_ka = 0;
-
-static const char *natt_version = "0.6c";
-
-void init_nat_traversal (bool activate, unsigned int keep_alive_period,
- bool fka, bool spf)
-{
- nat_traversal_enabled = activate;
- nat_traversal_support_non_ike = activate;
-#ifdef NAT_T_SUPPORT_LAST_DRAFTS
- nat_traversal_support_port_floating = activate ? spf : FALSE;
-#endif
- _force_ka = fka;
- _kap = keep_alive_period ? keep_alive_period : DEFAULT_KEEP_ALIVE_PERIOD;
- plog(" including NAT-Traversal patch (Version %s)%s%s%s"
- , natt_version, activate ? "" : " [disabled]"
- , activate & fka ? " [Force KeepAlive]" : ""
- , activate & !spf ? " [Port Floating disabled]" : "");
-}
-
-static void disable_nat_traversal (int type)
-{
- if (type == ESPINUDP_WITH_NON_IKE)
- nat_traversal_support_non_ike = FALSE;
- else
- nat_traversal_support_port_floating = FALSE;
-
- if (!nat_traversal_support_non_ike &&
- !nat_traversal_support_port_floating)
- nat_traversal_enabled = FALSE;
-}
-
-static void _natd_hash(const struct hash_desc *oakley_hasher, char *hash,
- u_int8_t *icookie, u_int8_t *rcookie,
- const ip_address *ip, u_int16_t port)
-{
- if (is_zero_cookie(icookie))
- {
- DBG_log("_natd_hash: Warning, icookie is zero !!");
- }
- if (is_zero_cookie(rcookie))
- {
- DBG_log("_natd_hash: Warning, rcookie is zero !!");
- }
-
- /**
- * draft-ietf-ipsec-nat-t-ike-01.txt
- *
- * HASH = HASH(CKY-I | CKY-R | IP | Port)
- *
- * All values in network order
- */
- {
- chunk_t icookie_chunk = { icookie, COOKIE_SIZE };
- chunk_t rcookie_chunk = { rcookie, COOKIE_SIZE };
- chunk_t port_chunk = chunk_from_thing(port);
- chunk_t addr_chunk;
- hash_algorithm_t hash_alg;
- hasher_t *hasher;
- size_t hash_size;
-
- hash_alg = oakley_to_hash_algorithm(oakley_hasher->algo_id);
- hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
- hasher->get_hash(hasher, icookie_chunk, NULL);
- hasher->get_hash(hasher, rcookie_chunk, NULL);
- switch (addrtypeof(ip))
- {
- case AF_INET:
- addr_chunk = chunk_from_thing(ip->u.v4.sin_addr.s_addr);
- break;
- case AF_INET6:
- addr_chunk = chunk_from_thing(ip->u.v6.sin6_addr.s6_addr);
- break;
- default:
- addr_chunk = chunk_empty; /* should never occur */
- }
- hasher->get_hash(hasher, addr_chunk, NULL);
- hasher->get_hash(hasher, port_chunk, hash);
- hash_size = hasher->get_hash_size(hasher);
- hasher->destroy(hasher);
-#ifdef NAT_D_DEBUG
- DBG(DBG_NATT,
- DBG_dump_chunk("_natd_hash: icookie=", icookie_chunk);
- DBG_dump_chunk("_natd_hash: rcookie=", rcookie_chunk);
- DBG_dump_chunk("_natd_hash: ip=", addr_chunk);
- DBG_log("_natd_hash: port=%d", port);
- DBG_dump("_natd_hash: hash=", hash, hash_size);
- )
-#endif
- }
-}
-
-/* Add NAT-Traversal VIDs (supported ones)
- * used when we are Initiator
- */
-bool nat_traversal_add_vid(u_int8_t np, pb_stream *outs)
-{
- bool r = TRUE;
-
- if (nat_traversal_support_port_floating)
- {
- u_int8_t last_np = nat_traversal_support_non_ike ?
- ISAKMP_NEXT_VID : np;
-
- if (r)
- r = out_vendorid(ISAKMP_NEXT_VID, outs, VID_NATT_RFC);
- if (r)
- r = out_vendorid(ISAKMP_NEXT_VID, outs, VID_NATT_IETF_03);
- if (r)
- r = out_vendorid(ISAKMP_NEXT_VID, outs, VID_NATT_IETF_02);
- if (r)
- r = out_vendorid(last_np, outs, VID_NATT_IETF_02_N);
- }
- if (nat_traversal_support_non_ike)
- {
- if (r)
- r = out_vendorid(np, outs, VID_NATT_IETF_00);
- }
- return r;
-}
-
-u_int32_t nat_traversal_vid_to_method(unsigned short nat_t_vid)
-{
- switch (nat_t_vid)
- {
- case VID_NATT_IETF_00:
- return LELEM(NAT_TRAVERSAL_IETF_00_01);
- case VID_NATT_IETF_02:
- case VID_NATT_IETF_02_N:
- case VID_NATT_IETF_03:
- return LELEM(NAT_TRAVERSAL_IETF_02_03);
- case VID_NATT_RFC:
- return LELEM(NAT_TRAVERSAL_RFC);
- }
- return 0;
-}
-
-void nat_traversal_natd_lookup(struct msg_digest *md)
-{
- char hash[MAX_DIGEST_LEN];
- struct payload_digest *p;
- struct state *st = md->st;
- int i;
-
- if (!st || !md->iface || !st->st_oakley.hasher)
- {
- loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d"
- , __FILE__, __LINE__);
- return;
- }
-
- /** Count NAT-D **/
- for (p = md->chain[ISAKMP_NEXT_NATD_RFC], i=0; p != NULL; p = p->next, i++);
-
- /*
- * We need at least 2 NAT-D (1 for us, many for peer)
- */
- if (i < 2)
- {
- loglog(RC_LOG_SERIOUS,
- "NAT-Traversal: Only %d NAT-D - Aborting NAT-Traversal negotiation", i);
- st->nat_traversal = 0;
- return;
- }
-
- /*
- * First one with my IP & port
- */
- p = md->chain[ISAKMP_NEXT_NATD_RFC];
- _natd_hash(st->st_oakley.hasher, hash, st->st_icookie, st->st_rcookie,
- &(md->iface->addr), ntohs(st->st_connection->spd.this.host_port));
-
- if (!(pbs_left(&p->pbs) == st->st_oakley.hasher->hash_digest_len &&
- memeq(p->pbs.cur, hash, st->st_oakley.hasher->hash_digest_len)))
- {
-#ifdef NAT_D_DEBUG
- DBG(DBG_NATT,
- DBG_log("NAT_TRAVERSAL_NAT_BHND_ME");
- DBG_dump("expected NAT-D:", hash
- , st->st_oakley.hasher->hash_digest_len);
- DBG_dump("received NAT-D:", p->pbs.cur, pbs_left(&p->pbs));
- )
-#endif
- st->nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_ME);
- }
-
- /*
- * The others with sender IP & port
- */
- _natd_hash(st->st_oakley.hasher, hash, st->st_icookie, st->st_rcookie,
- &(md->sender), ntohs(md->sender_port));
- for (p = p->next, i=0 ; p != NULL; p = p->next)
- {
- if (pbs_left(&p->pbs) == st->st_oakley.hasher->hash_digest_len &&
- memeq(p->pbs.cur, hash, st->st_oakley.hasher->hash_digest_len))
- {
- i++;
- }
- }
- if (!i)
- {
-#ifdef NAT_D_DEBUG
- DBG(DBG_NATT,
- DBG_log("NAT_TRAVERSAL_NAT_BHND_PEER");
- DBG_dump("expected NAT-D:", hash
- , st->st_oakley.hasher->hash_digest_len);
- p = md->chain[ISAKMP_NEXT_NATD_RFC];
- for (p = p->next, i=0 ; p != NULL; p = p->next)
- {
- DBG_dump("received NAT-D:", p->pbs.cur, pbs_left(&p->pbs));
- }
- )
-#endif
- st->nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_PEER);
- }
-#ifdef FORCE_NAT_TRAVERSAL
- st->nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_PEER);
- st->nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_ME);
-#endif
-}
-
-bool nat_traversal_add_natd(u_int8_t np, pb_stream *outs,
- struct msg_digest *md)
-{
- char hash[MAX_DIGEST_LEN];
- struct state *st = md->st;
-
- if (!st || !st->st_oakley.hasher)
- {
- loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d"
- , __FILE__, __LINE__);
- return FALSE;
- }
-
- DBG(DBG_EMITTING,
- DBG_log("sending NATD payloads")
- )
-
- /*
- * First one with sender IP & port
- */
- _natd_hash(st->st_oakley.hasher, hash, st->st_icookie,
- is_zero_cookie(st->st_rcookie) ? md->hdr.isa_rcookie : st->st_rcookie,
- &(md->sender),
-#ifdef FORCE_NAT_TRAVERSAL
- 0
-#else
- ntohs(md->sender_port)
-#endif
- );
- if (!out_generic_raw((st->nat_traversal & NAT_T_WITH_RFC_VALUES
- ? ISAKMP_NEXT_NATD_RFC : ISAKMP_NEXT_NATD_DRAFTS), &isakmp_nat_d, outs,
- hash, st->st_oakley.hasher->hash_digest_len, "NAT-D"))
- {
- return FALSE;
- }
-
- /*
- * Second one with my IP & port
- */
- _natd_hash(st->st_oakley.hasher, hash, st->st_icookie,
- is_zero_cookie(st->st_rcookie) ? md->hdr.isa_rcookie : st->st_rcookie,
- &(md->iface->addr),
-#ifdef FORCE_NAT_TRAVERSAL
- 0
-#else
- ntohs(st->st_connection->spd.this.host_port)
-#endif
- );
- return (out_generic_raw(np, &isakmp_nat_d, outs,
- hash, st->st_oakley.hasher->hash_digest_len, "NAT-D"));
-}
-
-/*
- * nat_traversal_natoa_lookup()
- *
- * Look for NAT-OA in message
- */
-void nat_traversal_natoa_lookup(struct msg_digest *md)
-{
- struct payload_digest *p;
- struct state *st = md->st;
- int i;
- ip_address ip;
-
- if (!st || !md->iface)
- {
- loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d"
- , __FILE__, __LINE__);
- return;
- }
-
- /* Initialize NAT-OA */
- anyaddr(AF_INET, &st->nat_oa);
-
- /* Count NAT-OA **/
- for (p = md->chain[ISAKMP_NEXT_NATOA_RFC], i=0; p != NULL; p = p->next, i++);
-
- DBG(DBG_NATT,
- DBG_log("NAT-Traversal: received %d NAT-OA.", i)
- )
-
- if (i == 0)
- return;
-
- if (!(st->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_PEER)))
- {
- loglog(RC_LOG_SERIOUS, "NAT-Traversal: received %d NAT-OA. "
- "ignored because peer is not NATed", i);
- return;
- }
-
- if (i > 1)
- {
- loglog(RC_LOG_SERIOUS, "NAT-Traversal: received %d NAT-OA. "
- "using first, ignoring others", i);
- }
-
- /* Take first */
- p = md->chain[ISAKMP_NEXT_NATOA_RFC];
-
- DBG(DBG_PARSING,
- DBG_dump("NAT-OA:", p->pbs.start, pbs_room(&p->pbs));
- );
-
- switch (p->payload.nat_oa.isanoa_idtype)
- {
- case ID_IPV4_ADDR:
- if (pbs_left(&p->pbs) == sizeof(struct in_addr))
- {
- initaddr(p->pbs.cur, pbs_left(&p->pbs), AF_INET, &ip);
- }
- else
- {
- loglog(RC_LOG_SERIOUS, "NAT-Traversal: received IPv4 NAT-OA "
- "with invalid IP size (%d)", (int)pbs_left(&p->pbs));
- return;
- }
- break;
- case ID_IPV6_ADDR:
- if (pbs_left(&p->pbs) == sizeof(struct in6_addr))
- {
- initaddr(p->pbs.cur, pbs_left(&p->pbs), AF_INET6, &ip);
- }
- else
- {
- loglog(RC_LOG_SERIOUS, "NAT-Traversal: received IPv6 NAT-OA "
- "with invalid IP size (%d)", (int)pbs_left(&p->pbs));
- return;
- }
- break;
- default:
- loglog(RC_LOG_SERIOUS, "NAT-Traversal: "
- "invalid ID Type (%d) in NAT-OA - ignored",
- p->payload.nat_oa.isanoa_idtype);
- return;
- }
-
- DBG(DBG_NATT,
- {
- char ip_t[ADDRTOT_BUF];
- addrtot(&ip, 0, ip_t, sizeof(ip_t));
-
- DBG_log("received NAT-OA: %s", ip_t);
- }
- )
-
- if (isanyaddr(&ip))
- loglog(RC_LOG_SERIOUS, "NAT-Traversal: received %%any NAT-OA...");
- else
- st->nat_oa = ip;
-}
-
-bool nat_traversal_add_natoa(u_int8_t np, pb_stream *outs,
- struct state *st)
-{
- struct isakmp_nat_oa natoa;
- pb_stream pbs;
- unsigned char ip_val[sizeof(struct in6_addr)];
- size_t ip_len = 0;
- ip_address *ip;
-
- if ((!st) || (!st->st_connection))
- {
- loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d"
- , __FILE__, __LINE__);
- return FALSE;
- }
- ip = &(st->st_connection->spd.this.host_addr);
-
- memset(&natoa, 0, sizeof(natoa));
- natoa.isanoa_np = np;
-
- switch (addrtypeof(ip))
- {
- case AF_INET:
- ip_len = sizeof(ip->u.v4.sin_addr.s_addr);
- memcpy(ip_val, &ip->u.v4.sin_addr.s_addr, ip_len);
- natoa.isanoa_idtype = ID_IPV4_ADDR;
- break;
- case AF_INET6:
- ip_len = sizeof(ip->u.v6.sin6_addr.s6_addr);
- memcpy(ip_val, &ip->u.v6.sin6_addr.s6_addr, ip_len);
- natoa.isanoa_idtype = ID_IPV6_ADDR;
- break;
- default:
- loglog(RC_LOG_SERIOUS, "NAT-Traversal: "
- "invalid addrtypeof()=%d", addrtypeof(ip));
- return FALSE;
- }
-
- if (!out_struct(&natoa, &isakmp_nat_oa, outs, &pbs))
- return FALSE;
-
- if (!out_raw(ip_val, ip_len, &pbs, "NAT-OA"))
- return FALSE;
-
- DBG(DBG_NATT,
- DBG_dump("NAT-OA (S):", ip_val, ip_len)
- )
-
- close_output_pbs(&pbs);
- return TRUE;
-}
-
-void nat_traversal_show_result (u_int32_t nt, u_int16_t sport)
-{
- const char *mth = NULL, *rslt = NULL;
-
- switch (nt & NAT_TRAVERSAL_METHOD)
- {
- case LELEM(NAT_TRAVERSAL_IETF_00_01):
- mth = natt_type_bitnames[0];
- break;
- case LELEM(NAT_TRAVERSAL_IETF_02_03):
- mth = natt_type_bitnames[1];
- break;
- case LELEM(NAT_TRAVERSAL_RFC):
- mth = natt_type_bitnames[2];
- break;
- }
-
- switch (nt & NAT_T_DETECTED)
- {
- case 0:
- rslt = "no NAT detected";
- break;
- case LELEM(NAT_TRAVERSAL_NAT_BHND_ME):
- rslt = "i am NATed";
- break;
- case LELEM(NAT_TRAVERSAL_NAT_BHND_PEER):
- rslt = "peer is NATed";
- break;
- case LELEM(NAT_TRAVERSAL_NAT_BHND_ME) | LELEM(NAT_TRAVERSAL_NAT_BHND_PEER):
- rslt = "both are NATed";
- break;
- }
-
- loglog(RC_LOG_SERIOUS,
- "NAT-Traversal: Result using %s: %s",
- mth ? mth : "unknown method",
- rslt ? rslt : "unknown result"
- );
-
- if ((nt & LELEM(NAT_TRAVERSAL_NAT_BHND_PEER))
- && (sport == IKE_UDP_PORT)
- && ((nt & NAT_T_WITH_PORT_FLOATING)==0))
- {
- loglog(RC_LOG_SERIOUS,
- "Warning: peer is NATed but source port is still udp/%d. "
- "Ipsec-passthrough NAT device suspected -- NAT-T may not work.",
- IKE_UDP_PORT
- );
- }
-}
-
-int nat_traversal_espinudp_socket (int sk, u_int32_t type)
-{
- int r = setsockopt(sk, SOL_UDP, UDP_ESPINUDP, &type, sizeof(type));
-
- if (r < 0 && errno == ENOPROTOOPT)
- {
- loglog(RC_LOG_SERIOUS,
- "NAT-Traversal: ESPINUDP(%d) not supported by kernel -- "
- "NAT-T disabled", type);
- disable_nat_traversal(type);
- }
- return r;
-}
-
-void nat_traversal_new_ka_event (void)
-{
- if (_ka_evt)
- return; /* event already scheduled */
-
- event_schedule(EVENT_NAT_T_KEEPALIVE, _kap, NULL);
- _ka_evt = 1;
-}
-
-static void nat_traversal_send_ka (struct state *st)
-{
- static unsigned char ka_payload = 0xff;
- chunk_t sav;
-
- DBG(DBG_NATT,
- DBG_log("ka_event: send NAT-KA to %s:%d",
- ip_str(&st->st_connection->spd.that.host_addr),
- st->st_connection->spd.that.host_port);
- )
-
- /* save state chunk */
- sav = st->st_tpacket;
-
- /* send keep alive */
- st->st_tpacket = chunk_create(&ka_payload, 1);
- send_packet(st, "NAT-T Keep Alive");
-
- /* restore state chunk */
- st->st_tpacket = sav;
-}
-
-/**
- * Find ISAKMP States with NAT-T and send keep-alive
- */
-static void nat_traversal_ka_event_state (struct state *st, void *data)
-{
- unsigned int *_kap_st = (unsigned int *)data;
- const connection_t *c = st->st_connection;
-
- if (!c)
- return;
-
- if ((st->st_state == STATE_MAIN_R3 || st->st_state == STATE_MAIN_I4)
- && (st->nat_traversal & NAT_T_DETECTED)
- && ((st->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_ME)) || _force_ka))
- {
- /*
- * - ISAKMP established
- * - NAT-Traversal detected
- * - NAT-KeepAlive needed (we are NATed)
- */
- if (c->newest_isakmp_sa != st->st_serialno)
- {
- /*
- * if newest is also valid, ignore this one, we will only use
- * newest.
- */
- struct state *st_newest;
-
- st_newest = state_with_serialno(c->newest_isakmp_sa);
- if (st_newest
- && (st_newest->st_state == STATE_MAIN_R3 || st_newest->st_state == STATE_MAIN_I4)
- && (st_newest->nat_traversal & NAT_T_DETECTED)
- && ((st_newest->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_ME)) || _force_ka))
- {
- return;
- }
- }
- set_cur_state(st);
- nat_traversal_send_ka(st);
- reset_cur_state();
- (*_kap_st)++;
- }
-}
-
-void nat_traversal_ka_event (void)
-{
- unsigned int _kap_st = 0;
-
- _ka_evt = 0; /* ready to be reschedule */
-
- for_each_state((void *)nat_traversal_ka_event_state, &_kap_st);
-
- /* if there are still states who needs Keep-Alive, schedule new event */
- if (_kap_st)
- nat_traversal_new_ka_event();
-}
-
-struct _new_mapp_nfo {
- ip_address addr;
- u_int16_t sport, dport;
-};
-
-static void nat_traversal_find_new_mapp_state (struct state *st, void *data)
-{
- connection_t *c = st->st_connection;
- struct _new_mapp_nfo *nfo = (struct _new_mapp_nfo *)data;
-
- if (c != NULL
- && sameaddr(&c->spd.that.host_addr, &(nfo->addr))
- && c->spd.that.host_port == nfo->sport)
- {
-
- /* change host port */
- c->spd.that.host_port = nfo->dport;
-
- if (IS_IPSEC_SA_ESTABLISHED(st->st_state)
- || IS_ONLY_INBOUND_IPSEC_SA_ESTABLISHED(st->st_state))
- {
- if (!update_ipsec_sa(st))
- {
- /*
- * If ipsec update failed, restore old port or we'll
- * not be able to update anymore.
- */
- c->spd.that.host_port = nfo->sport;
- }
- }
- }
-}
-
-static int nat_traversal_new_mapping(const ip_address *src, u_int16_t sport,
- const ip_address *dst, u_int16_t dport)
-{
- char srca[ADDRTOT_BUF], dsta[ADDRTOT_BUF];
- struct _new_mapp_nfo nfo;
-
- addrtot(src, 0, srca, ADDRTOT_BUF);
- addrtot(dst, 0, dsta, ADDRTOT_BUF);
-
- if (!sameaddr(src, dst))
- {
- loglog(RC_LOG_SERIOUS, "nat_traversal_new_mapping: "
- "address change currently not supported [%s:%d,%s:%d]",
- srca, sport, dsta, dport);
- return -1;
- }
-
- if (sport == dport)
- {
- /* no change */
- return 0;
- }
-
- DBG_log("NAT-T: new mapping %s:%d/%d)", srca, sport, dport);
-
- nfo.addr = *src;
- nfo.sport = sport;
- nfo.dport = dport;
-
- for_each_state((void *)nat_traversal_find_new_mapp_state, &nfo);
-
- return 0;
-}
-
-void nat_traversal_change_port_lookup(struct msg_digest *md, struct state *st)
-{
- connection_t *c = st ? st->st_connection : NULL;
- struct iface *i = NULL;
-
- if ((st == NULL) || (c == NULL))
- return;
-
- if (md)
- {
- /*
- * If source port has changed, update (including other states and
- * established kernel SA)
- */
- if (c->spd.that.host_port != md->sender_port)
- {
- nat_traversal_new_mapping(&c->spd.that.host_addr, c->spd.that.host_port,
- &c->spd.that.host_addr, md->sender_port);
- }
-
- /*
- * If interface type has changed, update local port (500/4500)
- */
- if ((c->spd.this.host_port == NAT_T_IKE_FLOAT_PORT && !md->iface->ike_float)
- || (c->spd.this.host_port != NAT_T_IKE_FLOAT_PORT && md->iface->ike_float))
- {
- c->spd.this.host_port = (md->iface->ike_float)
- ? NAT_T_IKE_FLOAT_PORT : pluto_port;
-
- DBG(DBG_NATT,
- DBG_log("NAT-T: updating local port to %d", c->spd.this.host_port);
- );
- }
- }
-
- /*
- * If we're initiator and NAT-T (with port floating) is detected, we
- * need to change port (MAIN_I3 or QUICK_I1)
- */
- if ((st->st_state == STATE_MAIN_I3 || st->st_state == STATE_QUICK_I1)
- && (st->nat_traversal & NAT_T_WITH_PORT_FLOATING)
- && (st->nat_traversal & NAT_T_DETECTED)
- && (c->spd.this.host_port != NAT_T_IKE_FLOAT_PORT))
- {
- DBG(DBG_NATT,
- DBG_log("NAT-T: floating to port %d", NAT_T_IKE_FLOAT_PORT);
- )
- c->spd.this.host_port = NAT_T_IKE_FLOAT_PORT;
- c->spd.that.host_port = NAT_T_IKE_FLOAT_PORT;
- /*
- * Also update pending connections or they will be deleted if uniqueids
- * option is set.
- */
- update_pending(st, st);
- }
-
- /*
- * Find valid interface according to local port (500/4500)
- */
- if ((c->spd.this.host_port == NAT_T_IKE_FLOAT_PORT && !c->interface->ike_float)
- || (c->spd.this.host_port != NAT_T_IKE_FLOAT_PORT && c->interface->ike_float))
- {
- for (i = interfaces; i != NULL; i = i->next)
- {
- if (sameaddr(&c->interface->addr, &i->addr)
- && i->ike_float != c->interface->ike_float)
- {
- DBG(DBG_NATT,
- DBG_log("NAT-T: using interface %s:%d", i->rname,
- i->ike_float ? NAT_T_IKE_FLOAT_PORT : pluto_port);
- )
- c->interface = i;
- break;
- }
- }
- }
-}
-
-struct _new_kernel_mapp_nfo {
- u_int32_t reqid;
- u_int32_t spi;
- ip_address *addr;
-};
-
-static void nat_t_new_kernel_mapp (struct state *st, void *data)
-{
- connection_t *c = st->st_connection;
- struct _new_kernel_mapp_nfo *nfo = (struct _new_kernel_mapp_nfo *)data;
-
- if (c != NULL && st->st_esp.present
- && nfo->spi == st->st_esp.our_spi
- && nfo->reqid == c->spd.reqid)
- {
- u_int16_t port = ntohs(portof(nfo->addr));
-
- DBG(DBG_NATT, {
- char text_said[SATOT_BUF];
- char olda[ADDRTOT_BUF];
- char newa[ADDRTOT_BUF];
- ip_said said;
-
- initsaid(&c->spd.that.host_addr, nfo->spi, SA_ESP, &said);
- satot(&said, 0, text_said, SATOT_BUF);
- addrtot(&c->spd.that.host_addr, 0, olda, ADDRTOT_BUF);
- addrtot(nfo->addr, 0, newa, ADDRTOT_BUF);
-
- DBG_log("new kernel mapping %s %s:%d %s:%d",
- text_said, olda, c->spd.that.host_port, newa, port);
- })
-
- nat_traversal_new_mapping(&c->spd.that.host_addr, c->spd.that.host_port,
- nfo->addr, port);
- }
-}
-
-void process_nat_t_new_mapping(u_int32_t reqid, u_int32_t spi,
- ip_address *new_end)
-{
- struct _new_kernel_mapp_nfo nfo = {
- .reqid = reqid,
- .spi = spi,
- .addr = new_end,
- };
- for_each_state((void *)nat_t_new_kernel_mapp, &nfo);
-}
-
diff --git a/src/pluto/nat_traversal.h b/src/pluto/nat_traversal.h
deleted file mode 100644
index 80bdaf787..000000000
--- a/src/pluto/nat_traversal.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (C) 2010 Tobias Brunner
- * Hochschule fuer Technik Rapperswil
- * Copyright (C) 2002-2003 Mathieu Lafon
- * Arkoon Network Security
- *
- * 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.
- */
-
-#ifndef _NAT_TRAVERSAL_H
-#define _NAT_TRAVERSAL_H
-
-#include "packet.h"
-
-#define NAT_TRAVERSAL_IETF_00_01 1
-#define NAT_TRAVERSAL_IETF_02_03 2
-#define NAT_TRAVERSAL_RFC 3
-
-#define NAT_TRAVERSAL_NAT_BHND_ME 30
-#define NAT_TRAVERSAL_NAT_BHND_PEER 31
-
-#define NAT_TRAVERSAL_METHOD (0xffffffff - LELEM(30) - LELEM(31))
-
-/**
- * NAT-Traversal methods which need NAT-D
- */
-#define NAT_T_WITH_NATD \
- ( LELEM(NAT_TRAVERSAL_IETF_00_01) | LELEM(NAT_TRAVERSAL_IETF_02_03) | \
- LELEM(NAT_TRAVERSAL_RFC) )
-/**
- * NAT-Traversal methods which need NAT-OA
- */
-#define NAT_T_WITH_NATOA \
- ( LELEM(NAT_TRAVERSAL_IETF_00_01) | LELEM(NAT_TRAVERSAL_IETF_02_03) | \
- LELEM(NAT_TRAVERSAL_RFC) )
-/**
- * NAT-Traversal methods which use NAT-KeepAlive
- */
-#define NAT_T_WITH_KA \
- ( LELEM(NAT_TRAVERSAL_IETF_00_01) | LELEM(NAT_TRAVERSAL_IETF_02_03) | \
- LELEM(NAT_TRAVERSAL_RFC) )
-/**
- * NAT-Traversal methods which use floating port
- */
-#define NAT_T_WITH_PORT_FLOATING \
- ( LELEM(NAT_TRAVERSAL_IETF_02_03) | LELEM(NAT_TRAVERSAL_RFC) )
-
-/**
- * NAT-Traversal methods which use officials values (RFC)
- */
-#define NAT_T_WITH_RFC_VALUES \
- ( LELEM(NAT_TRAVERSAL_RFC) )
-
-/**
- * NAT-Traversal detected
- */
-#define NAT_T_DETECTED \
- ( LELEM(NAT_TRAVERSAL_NAT_BHND_ME) | LELEM(NAT_TRAVERSAL_NAT_BHND_PEER) )
-
-/**
- * NAT-T Port Floating
- */
-#define NAT_T_IKE_FLOAT_PORT 4500
-
-void init_nat_traversal (bool activate, unsigned int keep_alive_period,
- bool fka, bool spf);
-
-extern bool nat_traversal_enabled;
-extern bool nat_traversal_support_non_ike;
-extern bool nat_traversal_support_port_floating;
-
-/**
- * NAT-D
- */
-void nat_traversal_natd_lookup(struct msg_digest *md);
-#ifndef PB_STREAM_UNDEFINED
-bool nat_traversal_add_natd(u_int8_t np, pb_stream *outs,
- struct msg_digest *md);
-#endif
-
-/**
- * NAT-OA
- */
-void nat_traversal_natoa_lookup(struct msg_digest *md);
-#ifndef PB_STREAM_UNDEFINED
-bool nat_traversal_add_natoa(u_int8_t np, pb_stream *outs,
- struct state *st);
-#endif
-
-/**
- * NAT-keep_alive
- */
-void nat_traversal_new_ka_event (void);
-void nat_traversal_ka_event (void);
-
-void nat_traversal_show_result (u_int32_t nt, u_int16_t sport);
-
-int nat_traversal_espinudp_socket (int sk, u_int32_t type);
-
-/**
- * Vendor ID
- */
-#ifndef PB_STREAM_UNDEFINED
-bool nat_traversal_add_vid(u_int8_t np, pb_stream *outs);
-#endif
-u_int32_t nat_traversal_vid_to_method(unsigned short nat_t_vid);
-
-void nat_traversal_change_port_lookup(struct msg_digest *md, struct state *st);
-
-/**
- * New NAT mapping
- */
-void process_nat_t_new_mapping(u_int32_t reqid, u_int32_t spi,
- ip_address *new_end);
-
-/**
- * IKE port floating
- */
-bool
-nat_traversal_port_float(struct state *st, struct msg_digest *md, bool in);
-
-/**
- * Encapsulation mode macro (see demux.c)
- */
-#define NAT_T_ENCAPSULATION_MODE(st,nat_t_policy) ( \
- ((st)->nat_traversal & NAT_T_DETECTED) \
- ? ( ((nat_t_policy) & POLICY_TUNNEL) \
- ? ( ((st)->nat_traversal & NAT_T_WITH_RFC_VALUES) \
- ? (ENCAPSULATION_MODE_UDP_TUNNEL_RFC) \
- : (ENCAPSULATION_MODE_UDP_TUNNEL_DRAFTS) \
- ) \
- : ( ((st)->nat_traversal & NAT_T_WITH_RFC_VALUES) \
- ? (ENCAPSULATION_MODE_UDP_TRANSPORT_RFC) \
- : (ENCAPSULATION_MODE_UDP_TRANSPORT_DRAFTS) \
- ) \
- ) \
- : ( ((st)->st_policy & POLICY_TUNNEL) \
- ? (ENCAPSULATION_MODE_TUNNEL) \
- : (ENCAPSULATION_MODE_TRANSPORT) \
- ) \
- )
-
-#endif /* _NAT_TRAVERSAL_H */
-
diff --git a/src/pluto/ocsp.c b/src/pluto/ocsp.c
deleted file mode 100644
index c299e3d39..000000000
--- a/src/pluto/ocsp.c
+++ /dev/null
@@ -1,1558 +0,0 @@
-/* Support of the Online Certificate Status Protocol (OCSP)
- * Copyright (C) 2003 Christoph Gysin, Simon Zwahlen
- * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include <freeswan.h>
-
-#include <library.h>
-#include <asn1/asn1.h>
-#include <asn1/asn1_parser.h>
-#include <asn1/oid.h>
-#include <crypto/rngs/rng.h>
-#include <crypto/hashers/hasher.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "log.h"
-#include "x509.h"
-#include "crl.h"
-#include "ca.h"
-#include "certs.h"
-#include "smartcard.h"
-#include "whack.h"
-#include "keys.h"
-#include "fetch.h"
-#include "ocsp.h"
-
-#define NONCE_LENGTH 16
-
-static const char *const cert_status_names[] = {
- "good",
- "revoked",
- "unknown",
- "undefined"
-};
-
-
-static const char *const response_status_names[] = {
- "successful",
- "malformed request",
- "internal error",
- "try later",
- "status #4",
- "signature required",
- "unauthorized"
-};
-
-/* response container */
-typedef struct response response_t;
-
-struct response {
- chunk_t tbs;
- identification_t *responder_id_name;
- chunk_t responder_id_key;
- time_t produced_at;
- chunk_t responses;
- chunk_t nonce;
- int algorithm;
- chunk_t signature;
-};
-
-const response_t empty_response = {
- { NULL, 0 } , /* tbs */
- NULL , /* responder_id_name */
- { NULL, 0 } , /* responder_id_key */
- UNDEFINED_TIME, /* produced_at */
- { NULL, 0 } , /* single_response */
- { NULL, 0 } , /* nonce */
- OID_UNKNOWN , /* signature_algorithm */
- { NULL, 0 } /* signature */
-};
-
-/* single response container */
-typedef struct single_response single_response_t;
-
-struct single_response {
- single_response_t *next;
- int hash_algorithm;
- chunk_t issuer_name_hash;
- chunk_t issuer_key_hash;
- chunk_t serialNumber;
- cert_status_t status;
- time_t revocationTime;
- crl_reason_t revocationReason;
- time_t thisUpdate;
- time_t nextUpdate;
-};
-
-const single_response_t empty_single_response = {
- NULL , /* *next */
- OID_UNKNOWN , /* hash_algorithm */
- { NULL, 0 } , /* issuer_name_hash */
- { NULL, 0 } , /* issuer_key_hash */
- { NULL, 0 } , /* serial_number */
- CERT_UNDEFINED , /* status */
- UNDEFINED_TIME , /* revocationTime */
- CRL_REASON_UNSPECIFIED, /* revocationReason */
- UNDEFINED_TIME , /* this_update */
- UNDEFINED_TIME /* next_update */
-};
-
-
-/* list of single requests */
-typedef struct request_list request_list_t;
-struct request_list {
- chunk_t request;
- request_list_t *next;
-};
-
-/* some OCSP specific prefabricated ASN.1 constants */
-static const chunk_t ASN1_nonce_oid = chunk_from_chars(
- 0x06, 0x09, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02
-);
-static const chunk_t ASN1_response_oid = chunk_from_chars(
- 0x06, 0x09, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x04
-);
-static const chunk_t ASN1_response_content = chunk_from_chars(
- 0x04, 0x0D,
- 0x30, 0x0B,
- 0x06, 0x09, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01
-);
-
-/* default OCSP uri */
-static chunk_t ocsp_default_uri;
-
-/* ocsp cache: pointer to first element */
-static ocsp_location_t *ocsp_cache = NULL;
-
-/* static temporary storage for ocsp requestor information */
-static cert_t *ocsp_requestor_cert = NULL;
-
-static smartcard_t *ocsp_requestor_sc = NULL;
-
-static private_key_t *ocsp_requestor_key = NULL;
-
-/**
- * ASN.1 definition of ocspResponse
- */
-static const asn1Object_t ocspResponseObjects[] = {
- { 0, "OCSPResponse", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
- { 1, "responseStatus", ASN1_ENUMERATED, ASN1_BODY }, /* 1 */
- { 1, "responseBytesContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 2 */
- { 2, "responseBytes", ASN1_SEQUENCE, ASN1_NONE }, /* 3 */
- { 3, "responseType", ASN1_OID, ASN1_BODY }, /* 4 */
- { 3, "response", ASN1_OCTET_STRING, ASN1_BODY }, /* 5 */
- { 1, "end opt", ASN1_EOC, ASN1_END }, /* 6 */
- { 0, "exit", ASN1_EOC, ASN1_EXIT }
-};
-#define OCSP_RESPONSE_STATUS 1
-#define OCSP_RESPONSE_TYPE 4
-#define OCSP_RESPONSE 5
-
-/**
- * ASN.1 definition of basicResponse
- */
-static const asn1Object_t basicResponseObjects[] = {
- { 0, "BasicOCSPResponse", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
- { 1, "tbsResponseData", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
- { 2, "versionContext", ASN1_CONTEXT_C_0, ASN1_NONE |
- ASN1_DEF }, /* 2 */
- { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 3 */
- { 2, "responderIdContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 4 */
- { 3, "responderIdByName", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */
- { 2, "end choice", ASN1_EOC, ASN1_END }, /* 6 */
- { 2, "responderIdContext", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 7 */
- { 3, "responderIdByKey", ASN1_OCTET_STRING, ASN1_BODY }, /* 8 */
- { 2, "end choice", ASN1_EOC, ASN1_END }, /* 9 */
- { 2, "producedAt", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 10 */
- { 2, "responses", ASN1_SEQUENCE, ASN1_OBJ }, /* 11 */
- { 2, "responseExtensionsContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 12 */
- { 3, "responseExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 13 */
- { 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 14 */
- { 5, "extnID", ASN1_OID, ASN1_BODY }, /* 15 */
- { 5, "critical", ASN1_BOOLEAN, ASN1_BODY |
- ASN1_DEF }, /* 16 */
- { 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 17 */
- { 3, "end loop", ASN1_EOC, ASN1_END }, /* 18 */
- { 2, "end opt", ASN1_EOC, ASN1_END }, /* 19 */
- { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 20 */
- { 1, "signature", ASN1_BIT_STRING, ASN1_BODY }, /* 21 */
- { 1, "certsContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 22 */
- { 2, "certs", ASN1_SEQUENCE, ASN1_LOOP }, /* 23 */
- { 3, "certificate", ASN1_SEQUENCE, ASN1_RAW }, /* 24 */
- { 2, "end loop", ASN1_EOC, ASN1_END }, /* 25 */
- { 1, "end opt", ASN1_EOC, ASN1_END }, /* 26 */
- { 0, "exit", ASN1_EOC, ASN1_EXIT }
-};
-#define BASIC_RESPONSE_TBS_DATA 1
-#define BASIC_RESPONSE_VERSION 3
-#define BASIC_RESPONSE_ID_BY_NAME 5
-#define BASIC_RESPONSE_ID_BY_KEY 8
-#define BASIC_RESPONSE_PRODUCED_AT 10
-#define BASIC_RESPONSE_RESPONSES 11
-#define BASIC_RESPONSE_EXT_ID 15
-#define BASIC_RESPONSE_CRITICAL 16
-#define BASIC_RESPONSE_EXT_VALUE 17
-#define BASIC_RESPONSE_ALGORITHM 20
-#define BASIC_RESPONSE_SIGNATURE 21
-#define BASIC_RESPONSE_CERTIFICATE 24
-
-/**
- * ASN.1 definition of responses
- */
-static const asn1Object_t responsesObjects[] = {
- { 0, "responses", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
- { 1, "singleResponse", ASN1_EOC, ASN1_RAW }, /* 1 */
- { 0, "end loop", ASN1_EOC, ASN1_END }, /* 2 */
- { 0, "exit", ASN1_EOC, ASN1_EXIT }
-};
-#define RESPONSES_SINGLE_RESPONSE 1
-
-/**
- * ASN.1 definition of singleResponse
- */
-static const asn1Object_t singleResponseObjects[] = {
- { 0, "singleResponse", ASN1_SEQUENCE, ASN1_BODY }, /* 0 */
- { 1, "certID", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */
- { 2, "algorithm", ASN1_EOC, ASN1_RAW }, /* 2 */
- { 2, "issuerNameHash", ASN1_OCTET_STRING, ASN1_BODY }, /* 3 */
- { 2, "issuerKeyHash", ASN1_OCTET_STRING, ASN1_BODY }, /* 4 */
- { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 5 */
- { 1, "certStatusGood", ASN1_CONTEXT_S_0, ASN1_OPT }, /* 6 */
- { 1, "end opt", ASN1_EOC, ASN1_END }, /* 7 */
- { 1, "certStatusRevoked", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 8 */
- { 2, "revocationTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 9 */
- { 2, "revocationReason", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 10 */
- { 3, "crlReason", ASN1_ENUMERATED, ASN1_BODY }, /* 11 */
- { 2, "end opt", ASN1_EOC, ASN1_END }, /* 12 */
- { 1, "end opt", ASN1_EOC, ASN1_END }, /* 13 */
- { 1, "certStatusUnknown", ASN1_CONTEXT_S_2, ASN1_OPT }, /* 14 */
- { 1, "end opt", ASN1_EOC, ASN1_END }, /* 15 */
- { 1, "thisUpdate", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 16 */
- { 1, "nextUpdateContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 17 */
- { 2, "nextUpdate", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 18 */
- { 1, "end opt", ASN1_EOC, ASN1_END }, /* 19 */
- { 1, "singleExtensionsContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 20 */
- { 2, "singleExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 21 */
- { 3, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 22 */
- { 4, "extnID", ASN1_OID, ASN1_BODY }, /* 23 */
- { 4, "critical", ASN1_BOOLEAN, ASN1_BODY |
- ASN1_DEF }, /* 24 */
- { 4, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 25 */
- { 2, "end loop", ASN1_EOC, ASN1_END }, /* 26 */
- { 1, "end opt", ASN1_EOC, ASN1_END }, /* 27 */
- { 0, "exit", ASN1_EOC, ASN1_EXIT }
-};
-#define SINGLE_RESPONSE_ALGORITHM 2
-#define SINGLE_RESPONSE_ISSUER_NAME_HASH 3
-#define SINGLE_RESPONSE_ISSUER_KEY_HASH 4
-#define SINGLE_RESPONSE_SERIAL_NUMBER 5
-#define SINGLE_RESPONSE_CERT_STATUS_GOOD 6
-#define SINGLE_RESPONSE_CERT_STATUS_REVOKED 8
-#define SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME 9
-#define SINGLE_RESPONSE_CERT_STATUS_CRL_REASON 11
-#define SINGLE_RESPONSE_CERT_STATUS_UNKNOWN 14
-#define SINGLE_RESPONSE_THIS_UPDATE 16
-#define SINGLE_RESPONSE_NEXT_UPDATE 18
-#define SINGLE_RESPONSE_EXT_ID 23
-#define SINGLE_RESPONSE_CRITICAL 24
-#define SINGLE_RESPONSE_EXT_VALUE 25
-
-/*
- * Build an ocsp location from certificate information
- * without unsharing its contents
- */
-static bool build_ocsp_location(const cert_t *cert, ocsp_location_t *location)
-{
- certificate_t *certificate = cert->cert;
- identification_t *issuer = certificate->get_issuer(certificate);
- x509_t *x509 = (x509_t*)certificate;
- chunk_t issuer_dn = issuer->get_encoding(issuer);
- chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
- hasher_t *hasher;
- static u_char digest[HASH_SIZE_SHA1]; /* temporary storage */
-
- enumerator_t *enumerator = x509->create_ocsp_uri_enumerator(x509);
-
- location->uri = NULL;
- while (enumerator->enumerate(enumerator, &location->uri))
- {
- break;
- }
- enumerator->destroy(enumerator);
-
- if (location->uri == NULL)
- {
- ca_info_t *ca = get_ca_info(issuer, authKeyID);
- if (ca && ca->ocspuri)
- {
- location->uri = ca->ocspuri;
- }
- else
- { /* abort if no ocsp location uri is defined */
- return FALSE;
- }
- }
-
- /* compute authNameID from as SHA-1 hash of issuer DN */
- location->authNameID = chunk_create(digest, HASH_SIZE_SHA1);
- hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
- if (hasher == NULL)
- {
- return FALSE;
- }
- hasher->get_hash(hasher, issuer_dn, digest);
- hasher->destroy(hasher);
-
- location->next = NULL;
- location->issuer = issuer;
- location->authKeyID = authKeyID;
-
- if (authKeyID.ptr == NULL)
- {
- cert_t *authcert = get_authcert(issuer, authKeyID, X509_CA);
-
- if (authcert)
- {
- x509_t *x509 = (x509_t*)authcert->cert;
-
- location->authKeyID = x509->get_subjectKeyIdentifier(x509);
- }
- }
-
- location->nonce = chunk_empty;
- location->certinfo = NULL;
-
- return TRUE;
-}
-
-/**
- * Compare two ocsp locations for equality
- */
-static bool same_ocsp_location(const ocsp_location_t *a, const ocsp_location_t *b)
-{
- return ((a->authKeyID.ptr)
- ? same_keyid(a->authKeyID, b->authKeyID)
- : a->issuer->equals(a->issuer, b->issuer))
- && streq(a->uri, b->uri);
-}
-
-/**
- * Find an existing ocsp location in a chained list
- */
-ocsp_location_t* get_ocsp_location(const ocsp_location_t * loc, ocsp_location_t *chain)
-{
-
- while (chain)
- {
- if (same_ocsp_location(loc, chain))
- return chain;
- chain = chain->next;
- }
- return NULL;
-}
-
-/**
- * Retrieves the status of a cert from the ocsp cache
- * returns CERT_UNDEFINED if no status is found
- */
-static cert_status_t get_ocsp_status(const ocsp_location_t *loc,
- chunk_t serialNumber,
- time_t *nextUpdate, time_t *revocationTime,
- crl_reason_t *revocationReason)
-{
- ocsp_certinfo_t *certinfo, **certinfop;
- int cmp = -1;
-
- /* find location */
- ocsp_location_t *location = get_ocsp_location(loc, ocsp_cache);
-
- if (location == NULL)
- return CERT_UNDEFINED;
-
- /* traverse list of certinfos in increasing order */
- certinfop = &location->certinfo;
- certinfo = *certinfop;
-
- while (certinfo)
- {
- cmp = chunk_compare(serialNumber, certinfo->serialNumber);
- if (cmp <= 0)
- break;
- certinfop = &certinfo->next;
- certinfo = *certinfop;
- }
-
- if (cmp == 0)
- {
- *nextUpdate = certinfo->nextUpdate;
- *revocationTime = certinfo->revocationTime;
- *revocationReason = certinfo->revocationReason;
- return certinfo->status;
- }
-
- return CERT_UNDEFINED;
-}
-
-/**
- * Verify the ocsp status of a certificate
- */
-cert_status_t verify_by_ocsp(const cert_t *cert, time_t *until,
- time_t *revocationDate,
- crl_reason_t *revocationReason)
-{
- x509_t *x509 = (x509_t*)cert->cert;
- chunk_t serialNumber = x509->get_serial(x509);
- cert_status_t status;
- ocsp_location_t location;
- time_t nextUpdate = UNDEFINED_TIME;
-
- *revocationDate = UNDEFINED_TIME;
- *revocationReason = CRL_REASON_UNSPECIFIED;
-
- /* is an ocsp location defined? */
- if (!build_ocsp_location(cert, &location))
- {
- return CERT_UNDEFINED;
- }
-
- lock_ocsp_cache("verify_by_ocsp");
- status = get_ocsp_status(&location, serialNumber, &nextUpdate
- , revocationDate, revocationReason);
- unlock_ocsp_cache("verify_by_ocsp");
-
- if (status == CERT_UNDEFINED || nextUpdate < time(NULL))
- {
- plog("ocsp status is stale or not in cache");
- add_ocsp_fetch_request(&location, serialNumber);
-
- /* inititate fetching of ocsp status */
- wake_fetch_thread("verify_by_ocsp");
- }
- *until = nextUpdate;
- return status;
-}
-
-/**
- * Check if an ocsp status is about to expire
- */
-void check_ocsp(void)
-{
- ocsp_location_t *location;
-
- lock_ocsp_cache("check_ocsp");
- location = ocsp_cache;
-
- while (location)
- {
- char buf[BUF_LEN];
- bool first = TRUE;
- ocsp_certinfo_t *certinfo = location->certinfo;
-
- while (certinfo)
- {
- if (!certinfo->once)
- {
- time_t time_left = certinfo->nextUpdate - time(NULL);
-
- DBG(DBG_CONTROL,
- if (first)
- {
- DBG_log("issuer: \"%Y\"", location->issuer);
- if (location->authKeyID.ptr)
- {
- datatot(location->authKeyID.ptr, location->authKeyID.len
- , ':', buf, BUF_LEN);
- DBG_log("authkey: %s", buf);
- }
- first = FALSE;
- }
- datatot(certinfo->serialNumber.ptr, certinfo->serialNumber.len
- , ':', buf, BUF_LEN);
- DBG_log("serial: %s, %ld seconds left", buf, time_left)
- )
-
- if (time_left < 2*crl_check_interval)
- add_ocsp_fetch_request(location, certinfo->serialNumber);
- }
- certinfo = certinfo->next;
- }
- location = location->next;
- }
- unlock_ocsp_cache("check_ocsp");
-}
-
-/**
- * frees the allocated memory of a certinfo struct
- */
-static void free_certinfo(ocsp_certinfo_t *certinfo)
-{
- free(certinfo->serialNumber.ptr);
- free(certinfo);
-}
-
-/**
- * frees all certinfos in a chained list
- */
-static void free_certinfos(ocsp_certinfo_t *chain)
-{
- ocsp_certinfo_t *certinfo;
-
- while (chain)
- {
- certinfo = chain;
- chain = chain->next;
- free_certinfo(certinfo);
- }
-}
-
-/**
- * Frees the memory allocated to an ocsp location including all certinfos
- */
-static void free_ocsp_location(ocsp_location_t* location)
-{
- DESTROY_IF(location->issuer);
- free(location->authNameID.ptr);
- free(location->authKeyID.ptr);
- free(location->uri);
- free_certinfos(location->certinfo);
- free(location);
-}
-
-/*
- * Free a chained list of ocsp locations
- */
-void free_ocsp_locations(ocsp_location_t **chain)
-{
- while (*chain)
- {
- ocsp_location_t *location = *chain;
- *chain = location->next;
- free_ocsp_location(location);
- }
-}
-
-/**
- * Free the ocsp cache
- */
-void free_ocsp_cache(void)
-{
- lock_ocsp_cache("free_ocsp_cache");
- free_ocsp_locations(&ocsp_cache);
- unlock_ocsp_cache("free_ocsp_cache");
-}
-
-/**
- * Frees the ocsp cache and global variables
- */
-void free_ocsp(void)
-{
- free(ocsp_default_uri.ptr);
- free_ocsp_cache();
-}
-
-/**
- * List a chained list of ocsp_locations
- */
-void list_ocsp_locations(ocsp_location_t *location, bool requests,
- bool utc, bool strict)
-{
- bool first = TRUE;
-
- while (location)
- {
- ocsp_certinfo_t *certinfo = location->certinfo;
-
- if (certinfo)
- {
- if (first)
- {
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, "List of OCSP %s:", requests ?
- "Fetch Requests" : "Responses");
- first = FALSE;
- }
- whack_log(RC_COMMENT, " ");
- if (location->issuer)
- {
- whack_log(RC_COMMENT, " issuer: \"%Y\"", location->issuer);
- }
- whack_log(RC_COMMENT, " uri: '%s'", location->uri);
- if (location->authNameID.ptr)
- {
- whack_log(RC_COMMENT, " authname: %#B", &location->authNameID);
- }
- if (location->authKeyID.ptr)
- {
- whack_log(RC_COMMENT, " authkey: %#B", &location->authKeyID);
- }
- while (certinfo)
- {
- chunk_t serial = chunk_skip_zero(certinfo->serialNumber);
-
- if (requests)
- {
- whack_log(RC_COMMENT, " serial: %#B, %d trials",
- &serial, certinfo->trials);
- }
- else if (certinfo->once)
- {
- whack_log(RC_COMMENT, " serial: %#B, %s, once%s",
- &serial, cert_status_names[certinfo->status],
- (certinfo->nextUpdate < time(NULL))? " (expired)": "");
- }
- else
- {
- whack_log(RC_COMMENT, " serial: %#B, %s, until %T %s",
- &serial, cert_status_names[certinfo->status],
- &certinfo->nextUpdate, utc,
- check_expiry(certinfo->nextUpdate, OCSP_WARNING_INTERVAL, strict));
- }
- certinfo = certinfo->next;
- }
- }
- location = location->next;
- }
-}
-
-/**
- * List the ocsp cache
- */
-void list_ocsp_cache(bool utc, bool strict)
-{
- lock_ocsp_cache("list_ocsp_cache");
- list_ocsp_locations(ocsp_cache, FALSE, utc, strict);
- unlock_ocsp_cache("list_ocsp_cache");
-}
-
-static bool get_ocsp_requestor_cert(ocsp_location_t *location)
-{
- cert_t *cert = NULL;
-
- /* initialize temporary static storage */
- ocsp_requestor_cert = NULL;
- ocsp_requestor_sc = NULL;
- ocsp_requestor_key = NULL;
-
- for (;;)
- {
- certificate_t *certificate;
-
- /* looking for a certificate from the same issuer */
- cert = get_x509cert(location->issuer, location->authKeyID, cert);
- if (cert == NULL)
- {
- break;
- }
- certificate = cert->cert;
- DBG(DBG_CONTROL,
- DBG_log("candidate: '%Y'", certificate->get_subject(certificate));
- )
-
- if (cert->smartcard)
- {
- /* look for a matching private key on a smartcard */
- smartcard_t *sc = scx_get(cert);
-
- if (sc)
- {
- DBG(DBG_CONTROL,
- DBG_log("matching smartcard found")
- )
- if (sc->valid)
- {
- ocsp_requestor_cert = cert;
- ocsp_requestor_sc = sc;
- return TRUE;
- }
- plog("unable to sign ocsp request without PIN");
- }
- }
- else
- {
- /* look for a matching private key in the chained list */
- private_key_t *private = get_x509_private_key(cert);
-
- if (private)
- {
- DBG(DBG_CONTROL,
- DBG_log("matching private key found")
- )
- ocsp_requestor_cert = cert;
- ocsp_requestor_key = private;
- return TRUE;
- }
- }
- }
- return FALSE;
-}
-
-static chunk_t sc_build_sha1_signature(chunk_t tbs, smartcard_t *sc)
-{
- hasher_t *hasher;
- u_char *pos;
- chunk_t digest;
- chunk_t digest_info, sigdata;
- size_t siglen = 0;
-
- if (!scx_establish_context(sc) || !scx_login(sc))
- {
- scx_release_context(sc);
- return chunk_empty;
- }
-
- siglen = scx_get_keylength(sc);
-
- if (siglen == 0)
- {
- plog("failed to get keylength from smartcard");
- scx_release_context(sc);
- return chunk_empty;
- }
-
- DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log("signing hash with RSA key from smartcard (slot: %d, id: %s)"
- , (int)sc->slot, sc->id)
- )
-
- hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
- if (hasher == NULL)
- {
- return chunk_empty;
- }
- hasher->allocate_hash(hasher, tbs, &digest);
- hasher->destroy(hasher);
-
- /* according to PKCS#1 v2.1 digest must be packaged into
- * an ASN.1 structure for encryption
- */
- digest_info = asn1_wrap(ASN1_SEQUENCE, "mm"
- , asn1_algorithmIdentifier(OID_SHA1)
- , asn1_wrap(ASN1_OCTET_STRING, "m", digest));
-
- pos = asn1_build_object(&sigdata, ASN1_BIT_STRING, 1 + siglen);
- *pos++ = 0x00;
- scx_sign_hash(sc, digest_info.ptr, digest_info.len, pos, siglen);
- free(digest_info.ptr);
-
- if (!pkcs11_keep_state)
- {
- scx_release_context(sc);
- }
- return sigdata;
-}
-
-/**
- * build signature into ocsp request gets built only if a request cert
- * with a corresponding private key is found
- */
-static chunk_t build_signature(chunk_t tbsRequest)
-{
- chunk_t sigdata, cert, certs = chunk_empty;
-
- if (ocsp_requestor_sc)
- {
- /* RSA signature is done on smartcard */
- sigdata = sc_build_sha1_signature(tbsRequest, ocsp_requestor_sc);
- }
- else
- {
- /* RSA signature is done in software */
- sigdata = x509_build_signature(tbsRequest, OID_SHA1, ocsp_requestor_key,
- TRUE);
- }
- if (sigdata.ptr == NULL)
- {
- return chunk_empty;
- }
-
- /* include our certificate */
- if (ocsp_requestor_cert->cert->get_encoding(ocsp_requestor_cert->cert,
- CERT_ASN1_DER, &cert))
- {
- certs = asn1_wrap(ASN1_CONTEXT_C_0, "m",
- asn1_wrap(ASN1_SEQUENCE, "m", cert));
- }
- /* build signature comprising algorithm, signature and cert */
- return asn1_wrap(ASN1_CONTEXT_C_0, "m"
- , asn1_wrap(ASN1_SEQUENCE, "mmm"
- , asn1_algorithmIdentifier(OID_SHA1_WITH_RSA)
- , sigdata
- , certs
- )
- );
-}
-
-/**
- * Build request (into requestList)
- * no singleRequestExtensions used
- */
-static chunk_t build_request(ocsp_location_t *location, ocsp_certinfo_t *certinfo)
-{
- chunk_t reqCert = asn1_wrap(ASN1_SEQUENCE, "mmmm"
- , asn1_algorithmIdentifier(OID_SHA1)
- , asn1_simple_object(ASN1_OCTET_STRING, location->authNameID)
- , asn1_simple_object(ASN1_OCTET_STRING, location->authKeyID)
- , asn1_simple_object(ASN1_INTEGER, certinfo->serialNumber));
-
- return asn1_wrap(ASN1_SEQUENCE, "m", reqCert);
-}
-
-/**
- * build requestList (into TBSRequest)
- */
-static chunk_t build_request_list(ocsp_location_t *location)
-{
- chunk_t requestList;
- request_list_t *reqs = NULL;
- ocsp_certinfo_t *certinfo = location->certinfo;
- u_char *pos;
-
- size_t datalen = 0;
-
- /* build content */
- while (certinfo)
- {
- /* build request for every certificate in list
- * and store them in a chained list
- */
- request_list_t *req = malloc_thing(request_list_t);
-
- req->request = build_request(location, certinfo);
- req->next = reqs;
- reqs = req;
-
- datalen += req->request.len;
- certinfo = certinfo->next;
- }
-
- pos = asn1_build_object(&requestList, ASN1_SEQUENCE, datalen);
-
- /* copy all in chained list, free list afterwards */
- while (reqs)
- {
- request_list_t *req = reqs;
-
- mv_chunk(&pos, req->request);
- reqs = reqs->next;
- free(req);
- }
-
- return requestList;
-}
-
-/**
- * Build requestorName (into TBSRequest)
- */
-static chunk_t build_requestor_name(void)
-{
- certificate_t *certificate = ocsp_requestor_cert->cert;
- identification_t *subject = certificate->get_subject(certificate);
-
- return asn1_wrap(ASN1_CONTEXT_C_1, "m"
- , asn1_simple_object(ASN1_CONTEXT_C_4
- , subject->get_encoding(subject)));
-}
-
-/**
- * build nonce extension (into requestExtensions)
- */
-static chunk_t build_nonce_extension(ocsp_location_t *location)
-{
- rng_t *rng;
-
- /* generate a random nonce */
- location->nonce.ptr = malloc(NONCE_LENGTH),
- location->nonce.len = NONCE_LENGTH;
- rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
- rng->get_bytes(rng, location->nonce.len, location->nonce.ptr);
- rng->destroy(rng);
-
- return asn1_wrap(ASN1_SEQUENCE, "cm"
- , ASN1_nonce_oid
- , asn1_simple_object(ASN1_OCTET_STRING, location->nonce));
-}
-
-/**
- * Build requestExtensions (into TBSRequest)
- */
-static chunk_t build_request_ext(ocsp_location_t *location)
-{
- return asn1_wrap(ASN1_CONTEXT_C_2, "m"
- , asn1_wrap(ASN1_SEQUENCE, "mm"
- , build_nonce_extension(location)
- , asn1_wrap(ASN1_SEQUENCE, "cc"
- , ASN1_response_oid
- , ASN1_response_content
- )
- )
- );
-}
-
-/**
- * Build TBSRequest (into OCSPRequest)
- */
-static chunk_t build_tbs_request(ocsp_location_t *location, bool has_requestor_cert)
-{
- /* version is skipped since the default is ok */
- return asn1_wrap(ASN1_SEQUENCE, "mmm"
- , (has_requestor_cert)
- ? build_requestor_name()
- : chunk_empty
- , build_request_list(location)
- , build_request_ext(location));
-}
-
-/**
- * Assembles an ocsp request to given location
- * and sets nonce field in location to the sent nonce
- */
-chunk_t build_ocsp_request(ocsp_location_t *location)
-{
- bool has_requestor_cert;
- chunk_t tbsRequest, signature;
-
- DBG(DBG_CONTROL,
- DBG_log("assembling ocsp request");
- DBG_log("issuer: \"%Y\"", location->issuer);
- if (location->authKeyID.ptr)
- {
- DBG_log("authkey: %#B", &location->authKeyID);
- }
- )
- lock_certs_and_keys("build_ocsp_request");
-
- /* looks for requestor cert and matching private key */
- has_requestor_cert = get_ocsp_requestor_cert(location);
-
- /* build content */
- tbsRequest = build_tbs_request(location, has_requestor_cert);
-
- /* sign tbsReuqest */
- signature = (has_requestor_cert)? build_signature(tbsRequest)
- : chunk_empty;
-
- unlock_certs_and_keys("build_ocsp_request");
-
- return asn1_wrap(ASN1_SEQUENCE, "mm"
- , tbsRequest
- , signature);
-}
-
-/**
- * Check if the OCSP response has a valid signature
- */
-static bool valid_ocsp_response(response_t *res)
-{
- int pathlen, pathlen_constraint;
- cert_t *authcert;
-
- lock_authcert_list("valid_ocsp_response");
-
- authcert = get_authcert(res->responder_id_name, res->responder_id_key,
- X509_OCSP_SIGNER | X509_CA);
- if (authcert == NULL)
- {
- plog("no matching ocsp signer cert found");
- unlock_authcert_list("valid_ocsp_response");
- return FALSE;
- }
- DBG(DBG_CONTROL,
- DBG_log("ocsp signer cert found")
- )
-
- if (!x509_check_signature(res->tbs, res->signature, res->algorithm,
- authcert->cert))
- {
- plog("signature of ocsp response is invalid");
- unlock_authcert_list("valid_ocsp_response");
- return FALSE;
- }
- DBG(DBG_CONTROL,
- DBG_log("signature of ocsp response is valid")
- )
-
-
- for (pathlen = -1; pathlen <= X509_MAX_PATH_LEN; pathlen++)
- {
- cert_t *cert = authcert;
- certificate_t *certificate = cert->cert;
- x509_t *x509 = (x509_t*)certificate;
- identification_t *subject = certificate->get_subject(certificate);
- identification_t *issuer = certificate->get_issuer(certificate);
- chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
- time_t not_before, not_after;
-
- DBG(DBG_CONTROL,
- DBG_log("subject: '%Y'", subject);
- DBG_log("issuer: '%Y'", issuer);
- if (authKeyID.ptr)
- {
- DBG_log("authkey: %#B", &authKeyID);
- }
- )
-
- if (!certificate->get_validity(certificate, NULL, &not_before, &not_after))
- {
- plog("certificate is invalid (valid from %T to %T)",
- &not_before, FALSE, &not_after, FALSE);
-
- unlock_authcert_list("valid_ocsp_response");
- return FALSE;
- }
- DBG(DBG_CONTROL,
- DBG_log("certificate is valid")
- )
-
- authcert = get_authcert(issuer, authKeyID, X509_CA);
- if (authcert == NULL)
- {
- plog("issuer cacert not found");
- unlock_authcert_list("valid_ocsp_response");
- return FALSE;
- }
- DBG(DBG_CONTROL,
- DBG_log("issuer cacert found")
- )
-
- if (!certificate->issued_by(certificate, authcert->cert))
- {
- plog("certificate signature is invalid");
- unlock_authcert_list("valid_ocsp_response");
- return FALSE;
- }
- DBG(DBG_CONTROL,
- DBG_log("certificate signature is valid")
- )
-
- /* check path length constraint */
- pathlen_constraint = x509->get_constraint(x509, X509_PATH_LEN);
- if (pathlen_constraint != X509_NO_CONSTRAINT &&
- pathlen > pathlen_constraint)
- {
- plog("path length of %d violates constraint of %d",
- pathlen, pathlen_constraint);
- return FALSE;
- }
-
- /* check if cert is self-signed */
- if (x509->get_flags(x509) & X509_SELF_SIGNED)
- {
- DBG(DBG_CONTROL,
- DBG_log("reached self-signed root ca with a path length of %d",
- pathlen)
- )
- unlock_authcert_list("valid_ocsp_response");
- return TRUE;
- }
- }
- plog("maximum path length of %d exceeded", X509_MAX_PATH_LEN);
- unlock_authcert_list("valid_ocsp_response");
- return FALSE;
-}
-
-/**
- * Parse a basic OCSP response
- */
-static bool parse_basic_ocsp_response(chunk_t blob, int level0, response_t *res)
-{
- asn1_parser_t *parser;
- chunk_t object;
- u_int version;
- int objectID;
- int extn_oid = OID_UNKNOWN;
- bool success = FALSE;
- bool critical;
-
- parser = asn1_parser_create(basicResponseObjects, blob);
- parser->set_top_level(parser, level0);
-
- while (parser->iterate(parser, &objectID, &object))
- {
- switch (objectID)
- {
- case BASIC_RESPONSE_TBS_DATA:
- res->tbs = object;
- break;
- case BASIC_RESPONSE_VERSION:
- version = (object.len)? (1 + (u_int)*object.ptr) : 1;
- if (version != OCSP_BASIC_RESPONSE_VERSION)
- {
- plog("wrong ocsp basic response version (version= %i)", version);
- goto end;
- }
- break;
- case BASIC_RESPONSE_ID_BY_NAME:
- res->responder_id_name = identification_create_from_encoding(
- ID_DER_ASN1_DN, object);
- DBG(DBG_PARSING,
- DBG_log(" '%Y'", res->responder_id_name)
- )
- break;
- case BASIC_RESPONSE_ID_BY_KEY:
- res->responder_id_key = object;
- break;
- case BASIC_RESPONSE_PRODUCED_AT:
- res->produced_at = asn1_to_time(&object, ASN1_GENERALIZEDTIME);
- break;
- case BASIC_RESPONSE_RESPONSES:
- res->responses = object;
- break;
- case BASIC_RESPONSE_EXT_ID:
- extn_oid = asn1_known_oid(object);
- break;
- case BASIC_RESPONSE_CRITICAL:
- critical = object.len && *object.ptr;
- DBG(DBG_PARSING,
- DBG_log(" %s",(critical)?"TRUE":"FALSE");
- )
- break;
- case BASIC_RESPONSE_EXT_VALUE:
- if (extn_oid == OID_NONCE)
- res->nonce = object;
- break;
- case BASIC_RESPONSE_ALGORITHM:
- res->algorithm = asn1_parse_algorithmIdentifier(object,
- parser->get_level(parser)+1, NULL);
- break;
- case BASIC_RESPONSE_SIGNATURE:
- res->signature = object;
- break;
- case BASIC_RESPONSE_CERTIFICATE:
- {
- cert_t *cert = malloc_thing(cert_t);
- x509_t *x509;
-
- *cert = cert_empty;
- cert->cert = lib->creds->create(lib->creds,
- CRED_CERTIFICATE, CERT_X509,
- BUILD_BLOB_ASN1_DER, object,
- BUILD_END);
- if (cert->cert == NULL)
- {
- DBG(DBG_CONTROL | DBG_PARSING,
- DBG_log("parsing of embedded ocsp certificate failed")
- )
- cert_free(cert);
- break;
- }
- x509 = (x509_t*)cert->cert;
-
- if ((x509->get_flags(x509) & X509_OCSP_SIGNER) &&
- trust_authcert_candidate(cert, NULL))
- {
- add_authcert(cert, X509_OCSP_SIGNER);
- }
- else
- {
- DBG(DBG_CONTROL | DBG_PARSING,
- DBG_log("embedded ocsp certificate rejected")
- )
- cert_free(cert);
- }
- }
- break;
- }
- }
- success = parser->success(parser);
-
-end:
- parser->destroy(parser);
- return success;
-
-}
-
-
-/**
- * Parse an ocsp response and return the result as a response_t struct
- */
-static response_status parse_ocsp_response(chunk_t blob, response_t * res)
-{
- asn1_parser_t *parser;
- chunk_t object;
- int objectID;
- int ocspResponseType = OID_UNKNOWN;
- bool success = FALSE;
- response_status rStatus = STATUS_INTERNALERROR;
-
- parser = asn1_parser_create(ocspResponseObjects, blob);
-
- while (parser->iterate(parser, &objectID, &object))
- {
- switch (objectID) {
- case OCSP_RESPONSE_STATUS:
- rStatus = (response_status) *object.ptr;
-
- switch (rStatus)
- {
- case STATUS_SUCCESSFUL:
- break;
- case STATUS_MALFORMEDREQUEST:
- case STATUS_INTERNALERROR:
- case STATUS_TRYLATER:
- case STATUS_SIGREQUIRED:
- case STATUS_UNAUTHORIZED:
- plog("ocsp response: server said '%s'"
- , response_status_names[rStatus]);
- goto end;
- default:
- goto end;
- }
- break;
- case OCSP_RESPONSE_TYPE:
- ocspResponseType = asn1_known_oid(object);
- break;
- case OCSP_RESPONSE:
- {
- switch (ocspResponseType) {
- case OID_BASIC:
- success = parse_basic_ocsp_response(object,
- parser->get_level(parser)+1, res);
- break;
- default:
- DBG(DBG_CONTROL,
- DBG_log("ocsp response is not of type BASIC");
- DBG_dump_chunk("ocsp response OID: ", object);
- )
- goto end;
- }
- }
- break;
- }
- }
- success &= parser->success(parser);
-
-end:
- parser->destroy(parser);
- return rStatus;
-}
-
-/**
- * Parse a basic OCSP response
- */
-static bool parse_ocsp_single_response(chunk_t blob, int level0,
- single_response_t *sres)
-{
- asn1_parser_t *parser;
- chunk_t object;
- u_int extn_oid;
- int objectID;
- bool critical;
- bool success = FALSE;
-
- parser = asn1_parser_create(singleResponseObjects, blob);
- parser->set_top_level(parser, level0);
-
- while (parser->iterate(parser, &objectID, &object))
- {
- switch (objectID)
- {
- case SINGLE_RESPONSE_ALGORITHM:
- sres->hash_algorithm = asn1_parse_algorithmIdentifier(object,
- parser->get_level(parser)+1, NULL);
- break;
- case SINGLE_RESPONSE_ISSUER_NAME_HASH:
- sres->issuer_name_hash = object;
- break;
- case SINGLE_RESPONSE_ISSUER_KEY_HASH:
- sres->issuer_key_hash = object;
- break;
- case SINGLE_RESPONSE_SERIAL_NUMBER:
- sres->serialNumber = object;
- break;
- case SINGLE_RESPONSE_CERT_STATUS_GOOD:
- sres->status = CERT_GOOD;
- break;
- case SINGLE_RESPONSE_CERT_STATUS_REVOKED:
- sres->status = CERT_REVOKED;
- break;
- case SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME:
- sres->revocationTime = asn1_to_time(&object, ASN1_GENERALIZEDTIME);
- break;
- case SINGLE_RESPONSE_CERT_STATUS_CRL_REASON:
- sres->revocationReason = (object.len == 1)
- ? *object.ptr : CRL_REASON_UNSPECIFIED;
- break;
- case SINGLE_RESPONSE_CERT_STATUS_UNKNOWN:
- sres->status = CERT_UNKNOWN;
- break;
- case SINGLE_RESPONSE_THIS_UPDATE:
- sres->thisUpdate = asn1_to_time(&object, ASN1_GENERALIZEDTIME);
- break;
- case SINGLE_RESPONSE_NEXT_UPDATE:
- sres->nextUpdate = asn1_to_time(&object, ASN1_GENERALIZEDTIME);
- break;
- case SINGLE_RESPONSE_EXT_ID:
- extn_oid = asn1_known_oid(object);
- break;
- case SINGLE_RESPONSE_CRITICAL:
- critical = object.len && *object.ptr;
- DBG(DBG_PARSING,
- DBG_log(" %s",(critical)?"TRUE":"FALSE");
- )
- case SINGLE_RESPONSE_EXT_VALUE:
- break;
- }
- }
- success = parser->success(parser);
- parser->destroy(parser);
- return success;
-}
-
-/**
- * Add an ocsp location to a chained list
- */
-ocsp_location_t* add_ocsp_location(const ocsp_location_t *loc,
- ocsp_location_t **chain)
-{
- ocsp_location_t *location = malloc_thing(ocsp_location_t);
-
- /* unshare location fields */
- location->issuer = loc->issuer->clone(loc->issuer);
- location->authNameID = chunk_clone(loc->authNameID);
- location->authKeyID = chunk_clone(loc->authKeyID);
- location->uri = strdup(loc->uri);
- location->certinfo = NULL;
-
- /* insert new ocsp location in front of chain */
- location->next = *chain;
- *chain = location;
-
- DBG(DBG_CONTROL,
- DBG_log("new ocsp location added")
- )
-
- return location;
-}
-
-/**
- * add a certinfo struct to a chained list
- */
-void add_certinfo(ocsp_location_t *loc, ocsp_certinfo_t *info,
- ocsp_location_t **chain, bool request)
-{
- ocsp_location_t *location;
- ocsp_certinfo_t *certinfo, **certinfop;
- char buf[BUF_LEN];
- time_t now;
- int cmp = -1;
-
- location = get_ocsp_location(loc, *chain);
- if (location == NULL)
- {
- location = add_ocsp_location(loc, chain);
- }
-
- /* traverse list of certinfos in increasing order */
- certinfop = &location->certinfo;
- certinfo = *certinfop;
-
- while (certinfo)
- {
- cmp = chunk_compare(info->serialNumber, certinfo->serialNumber);
- if (cmp <= 0)
- break;
- certinfop = &certinfo->next;
- certinfo = *certinfop;
- }
-
- if (cmp != 0)
- {
- /* add a new certinfo entry */
- ocsp_certinfo_t *cnew = malloc_thing(ocsp_certinfo_t);
-
- cnew->serialNumber = chunk_clone(info->serialNumber);
- cnew->next = certinfo;
- cnew->trials = 0;
- *certinfop = cnew;
- certinfo = cnew;
- }
-
- DBG(DBG_CONTROL,
- datatot(info->serialNumber.ptr, info->serialNumber.len, ':'
- , buf, BUF_LEN);
- DBG_log("ocsp %s for serial %s %s"
- , request?"fetch request":"certinfo"
- , buf
- , (cmp == 0)? (request?"already exists":"updated"):"added")
- )
-
- time(&now);
-
- if (request)
- {
- certinfo->status = CERT_UNDEFINED;
-
- if (cmp != 0)
- {
- certinfo->thisUpdate = now;
- }
- certinfo->nextUpdate = UNDEFINED_TIME;
- }
- else
- {
- certinfo->status = info->status;
- certinfo->revocationTime = info->revocationTime;
- certinfo->revocationReason = info->revocationReason;
-
- certinfo->thisUpdate = (info->thisUpdate != UNDEFINED_TIME)?
- info->thisUpdate : now;
-
- certinfo->once = (info->nextUpdate == UNDEFINED_TIME);
-
- certinfo->nextUpdate = (certinfo->once)?
- (now + OCSP_DEFAULT_VALID_TIME) : info->nextUpdate;
- }
-}
-
-/**
- * Process received ocsp single response and add it to ocsp cache
- */
-static void process_single_response(ocsp_location_t *location,
- single_response_t *sres)
-{
- ocsp_certinfo_t *certinfo, **certinfop;
- int cmp = -1;
-
- if (sres->hash_algorithm != OID_SHA1)
- {
- plog("only SHA-1 hash supported in OCSP single response");
- return;
- }
- if (!(chunk_equals(sres->issuer_name_hash, location->authNameID)
- && chunk_equals(sres->issuer_key_hash, location->authKeyID)))
- {
- plog("ocsp single response has wrong issuer");
- return;
- }
-
- /* traverse list of certinfos in increasing order */
- certinfop = &location->certinfo;
- certinfo = *certinfop;
-
- while (certinfo)
- {
- cmp = chunk_compare(sres->serialNumber, certinfo->serialNumber);
- if (cmp <= 0)
- break;
- certinfop = &certinfo->next;
- certinfo = *certinfop;
- }
-
- if (cmp != 0)
- {
- plog("received unrequested cert status from ocsp server");
- return;
- }
-
- /* unlink cert from ocsp fetch request list */
- *certinfop = certinfo->next;
-
- /* update certinfo using the single response information */
- certinfo->thisUpdate = sres->thisUpdate;
- certinfo->nextUpdate = sres->nextUpdate;
- certinfo->status = sres->status;
- certinfo->revocationTime = sres->revocationTime;
- certinfo->revocationReason = sres->revocationReason;
-
- /* add or update certinfo in ocsp cache */
- lock_ocsp_cache("process_single_response");
- add_certinfo(location, certinfo, &ocsp_cache, FALSE);
- unlock_ocsp_cache("process_single_response");
-
- /* free certinfo unlinked from ocsp fetch request list */
- free_certinfo(certinfo);
-}
-
-/**
- * Destroy a response_t object
- */
-static void free_response(response_t *res)
-{
- DESTROY_IF(res->responder_id_name);
-}
-
-/**
- * Parse and verify ocsp response and update the ocsp cache
- */
-void parse_ocsp(ocsp_location_t *location, chunk_t blob)
-{
- response_t res = empty_response;
-
- /* parse the ocsp response without looking at the single responses yet */
- response_status status = parse_ocsp_response(blob, &res);
-
- if (status != STATUS_SUCCESSFUL)
- {
- plog("error in ocsp response");
- goto free;
- }
- /* check if there was a nonce in the request */
- if (location->nonce.ptr && res.nonce.ptr == NULL)
- {
- plog("ocsp response contains no nonce, replay attack possible");
- }
- /* check if the nonce is identical */
- if (res.nonce.ptr && !chunk_equals(res.nonce, location->nonce))
- {
- plog("invalid nonce in ocsp response");
- goto free;
- }
- /* check if the response is signed by a trusted key */
- if (!valid_ocsp_response(&res))
- {
- plog("invalid ocsp response");
- goto free;
- }
- DBG(DBG_CONTROL,
- DBG_log("valid ocsp response")
- )
-
- /* now parse the single responses one at a time */
- {
- asn1_parser_t *parser;
- chunk_t object;
- int objectID;
-
- parser = asn1_parser_create(responsesObjects, res.responses);
-
- while (parser->iterate(parser, &objectID, &object))
- {
- if (objectID == RESPONSES_SINGLE_RESPONSE)
- {
- single_response_t sres = empty_single_response;
-
- if (!parse_ocsp_single_response(object,
- parser->get_level(parser)+1, &sres))
- {
- goto end;
- }
- process_single_response(location, &sres);
- }
- }
-end:
- parser->destroy(parser);
- }
-
-free:
- free_response(&res);
-}
diff --git a/src/pluto/ocsp.h b/src/pluto/ocsp.h
deleted file mode 100644
index 977cca3c8..000000000
--- a/src/pluto/ocsp.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* Support of the Online Certificate Status Protocol (OCSP) Support
- * Copyright (C) 2003 Christoph Gysin, Simon Zwahlen
- * Zuercher Hochschule Winterthur
- *
- * 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 "constants.h"
-
-#include <credentials/certificates/crl.h>
-
-/* constants */
-
-#define OCSP_BASIC_RESPONSE_VERSION 1
-#define OCSP_DEFAULT_VALID_TIME 120 /* validity of one-time response in seconds */
-#define OCSP_WARNING_INTERVAL 2 /* days */
-
-/* OCSP response status */
-
-typedef enum {
- STATUS_SUCCESSFUL = 0,
- STATUS_MALFORMEDREQUEST = 1,
- STATUS_INTERNALERROR = 2,
- STATUS_TRYLATER = 3,
- STATUS_SIGREQUIRED = 5,
- STATUS_UNAUTHORIZED= 6
-} response_status;
-
-/* OCSP access structures */
-
-typedef struct ocsp_certinfo ocsp_certinfo_t;
-
-struct ocsp_certinfo {
- ocsp_certinfo_t *next;
- int trials;
- chunk_t serialNumber;
- cert_status_t status;
- bool once;
- crl_reason_t revocationReason;
- time_t revocationTime;
- time_t thisUpdate;
- time_t nextUpdate;
-};
-
-typedef struct ocsp_location ocsp_location_t;
-
-struct ocsp_location {
- ocsp_location_t *next;
- identification_t *issuer;
- chunk_t authNameID;
- chunk_t authKeyID;
- chunk_t nonce;
- char *uri;
- ocsp_certinfo_t *certinfo;
-};
-
-extern ocsp_location_t* get_ocsp_location(const ocsp_location_t *loc
- , ocsp_location_t *chain);
-extern ocsp_location_t* add_ocsp_location(const ocsp_location_t *loc
- , ocsp_location_t **chain);
-extern void add_certinfo(ocsp_location_t *loc, ocsp_certinfo_t *info
- , ocsp_location_t **chain, bool request);
-extern void check_ocsp(void);
-extern cert_status_t verify_by_ocsp(const cert_t *cert, time_t *until
- , time_t *revocationTime, crl_reason_t *revocationReason);
-extern bool ocsp_set_request_cert(char* path);
-extern void ocsp_set_default_uri(char* uri);
-extern void ocsp_cache_add_cert(const cert_t* cert);
-extern chunk_t build_ocsp_request(ocsp_location_t* location);
-extern void parse_ocsp(ocsp_location_t* location, chunk_t blob);
-extern void list_ocsp_locations(ocsp_location_t *location, bool requests
- , bool utc, bool strict);
-extern void list_ocsp_cache(bool utc, bool strict);
-extern void free_ocsp_locations(ocsp_location_t **chain);
-extern void free_ocsp_cache(void);
-extern void free_ocsp(void);
-extern void ocsp_purge_cache(void);
diff --git a/src/pluto/packet.c b/src/pluto/packet.c
deleted file mode 100644
index 35fc4afcc..000000000
--- a/src/pluto/packet.c
+++ /dev/null
@@ -1,1242 +0,0 @@
-/* parsing packets: formats and tools
- * Copyright (C) 1997 Angelos D. Keromytis.
- * Copyright (C) 1998-2001 D. Hugh Redelmeier.
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <netinet/in.h>
-#include <string.h>
-
-#include <freeswan.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "log.h"
-#include "packet.h"
-#include "whack.h" /* for RC_LOG_SERIOUS */
-
-/* ISAKMP Header: for all messages
- * layout from RFC 2408 "ISAKMP" section 3.1
- * 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
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Initiator !
- * ! Cookie !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Responder !
- * ! Cookie !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! MjVer ! MnVer ! Exchange Type ! Flags !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Message ID !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-
-static field_desc isa_fields[] = {
- { ft_raw, COOKIE_SIZE, "initiator cookie", NULL },
- { ft_raw, COOKIE_SIZE, "responder cookie", NULL },
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_enum, 8/BITS_PER_BYTE, "ISAKMP version", &version_names },
- { ft_enum, 8/BITS_PER_BYTE, "exchange type", &exchange_names },
- { ft_set, 8/BITS_PER_BYTE, "flags", flag_bit_names },
- { ft_raw, 32/BITS_PER_BYTE, "message ID", NULL },
- { ft_len, 32/BITS_PER_BYTE, "length", NULL },
- { ft_end, 0, NULL, NULL }
-};
-
-struct_desc isakmp_hdr_desc = { "ISAKMP Message", isa_fields, sizeof(struct isakmp_hdr) };
-
-/* Generic portion of all ISAKMP payloads.
- * layout from RFC 2408 "ISAKMP" section 3.2
- * This describes the first 32-bit chunk of all payloads.
- * The previous next payload depends on the actual payload type.
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-
-static field_desc isag_fields[] = {
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_len, 16/BITS_PER_BYTE, "length", NULL },
- { ft_end, 0, NULL, NULL }
-};
-
-struct_desc isakmp_generic_desc = { "ISAKMP Generic Payload", isag_fields, sizeof(struct isakmp_generic) };
-
-
-/* ISAKMP Data Attribute (generic representation within payloads)
- * layout from RFC 2408 "ISAKMP" section 3.3
- * This is not a payload type.
- * In TLV format, this is followed by a value field.
- * 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
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * !A! Attribute Type ! AF=0 Attribute Length !
- * !F! ! AF=1 Attribute Value !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * . AF=0 Attribute Value .
- * . AF=1 Not Transmitted .
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-
-/* Oakley Attributes */
-static field_desc isaat_fields_oakley[] = {
- { ft_af_enum, 16/BITS_PER_BYTE, "af+type", &oakley_attr_names },
- { ft_lv, 16/BITS_PER_BYTE, "length/value", NULL },
- { ft_end, 0, NULL, NULL }
-};
-
-struct_desc isakmp_oakley_attribute_desc = {
- "ISAKMP Oakley attribute",
- isaat_fields_oakley, sizeof(struct isakmp_attribute) };
-
-/* IPsec DOI Attributes */
-static field_desc isaat_fields_ipsec[] = {
- { ft_af_enum, 16/BITS_PER_BYTE, "af+type", &ipsec_attr_names },
- { ft_lv, 16/BITS_PER_BYTE, "length/value", NULL },
- { ft_end, 0, NULL, NULL }
-};
-
-struct_desc isakmp_ipsec_attribute_desc = {
- "ISAKMP IPsec DOI attribute",
- isaat_fields_ipsec, sizeof(struct isakmp_attribute) };
-
-/* Mode Config Attributes */
-static field_desc isaat_fields_modecfg[] = {
- { ft_af_loose_enum, 16/BITS_PER_BYTE, "ModeCfg attr type", &modecfg_attr_names },
- { ft_lv, 16/BITS_PER_BYTE, "length/value", NULL },
- { ft_end, 0, NULL, NULL }
-};
-
-struct_desc isakmp_modecfg_attribute_desc = {
- "ISAKMP ModeCfg attribute",
- isaat_fields_modecfg, sizeof(struct isakmp_attribute) };
-
-/* ISAKMP Security Association Payload
- * layout from RFC 2408 "ISAKMP" section 3.4
- * A variable length Situation follows.
- * Previous next payload: ISAKMP_NEXT_SA
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Domain of Interpretation (DOI) !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! !
- * ~ Situation ~
- * ! !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-static field_desc isasa_fields[] = {
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_len, 16/BITS_PER_BYTE, "length", NULL },
- { ft_enum, 32/BITS_PER_BYTE, "DOI", &doi_names },
- { ft_end, 0, NULL, NULL }
-};
-
-struct_desc isakmp_sa_desc = { "ISAKMP Security Association Payload", isasa_fields, sizeof(struct isakmp_sa) };
-
-static field_desc ipsec_sit_field[] = {
- { ft_set, 32/BITS_PER_BYTE, "IPsec DOI SIT", &sit_bit_names },
- { ft_end, 0, NULL, NULL }
-};
-
-struct_desc ipsec_sit_desc = { "IPsec DOI SIT", ipsec_sit_field, sizeof(u_int32_t) };
-
-/* ISAKMP Proposal Payload
- * layout from RFC 2408 "ISAKMP" section 3.5
- * A variable length SPI follows.
- * Previous next payload: ISAKMP_NEXT_P
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Proposal # ! Protocol-Id ! SPI Size !# of Transforms!
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! SPI (variable) !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-static field_desc isap_fields[] = {
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_len, 16/BITS_PER_BYTE, "length", NULL },
- { ft_nat, 8/BITS_PER_BYTE, "proposal number", NULL },
- { ft_enum, 8/BITS_PER_BYTE, "protocol ID", &protocol_names },
- { ft_nat, 8/BITS_PER_BYTE, "SPI size", NULL },
- { ft_nat, 8/BITS_PER_BYTE, "number of transforms", NULL },
- { ft_end, 0, NULL, NULL }
-};
-
-struct_desc isakmp_proposal_desc = { "ISAKMP Proposal Payload", isap_fields, sizeof(struct isakmp_proposal) };
-
-/* ISAKMP Transform Payload
- * layout from RFC 2408 "ISAKMP" section 3.6
- * Variable length SA Attributes follow.
- * Previous next payload: ISAKMP_NEXT_T
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Transform # ! Transform-Id ! RESERVED2 !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! !
- * ~ SA Attributes ~
- * ! !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-
-/* PROTO_ISAKMP */
-static field_desc isat_fields_isakmp[] = {
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_len, 16/BITS_PER_BYTE, "length", NULL },
- { ft_nat, 8/BITS_PER_BYTE, "transform number", NULL },
- { ft_enum, 8/BITS_PER_BYTE, "transform ID", &isakmp_transformid_names },
- { ft_mbz, 16/BITS_PER_BYTE, NULL, NULL },
- { ft_end, 0, NULL, NULL }
-};
-
-struct_desc isakmp_isakmp_transform_desc = {
- "ISAKMP Transform Payload (ISAKMP)",
- isat_fields_isakmp, sizeof(struct isakmp_transform) };
-
-/* PROTO_IPSEC_AH */
-static field_desc isat_fields_ah[] = {
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_len, 16/BITS_PER_BYTE, "length", NULL },
- { ft_nat, 8/BITS_PER_BYTE, "transform number", NULL },
- { ft_enum, 8/BITS_PER_BYTE, "transform ID", &ah_transform_names },
- { ft_mbz, 16/BITS_PER_BYTE, NULL, NULL },
- { ft_end, 0, NULL, NULL }
-};
-
-struct_desc isakmp_ah_transform_desc = {
- "ISAKMP Transform Payload (AH)",
- isat_fields_ah, sizeof(struct isakmp_transform) };
-
-/* PROTO_IPSEC_ESP */
-static field_desc isat_fields_esp[] = {
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_len, 16/BITS_PER_BYTE, "length", NULL },
- { ft_nat, 8/BITS_PER_BYTE, "transform number", NULL },
- { ft_enum, 8/BITS_PER_BYTE, "transform ID", &esp_transform_names },
- { ft_mbz, 16/BITS_PER_BYTE, NULL, NULL },
- { ft_end, 0, NULL, NULL }
-};
-
-struct_desc isakmp_esp_transform_desc = {
- "ISAKMP Transform Payload (ESP)",
- isat_fields_esp, sizeof(struct isakmp_transform) };
-
-/* PROTO_IPCOMP */
-static field_desc isat_fields_ipcomp[] = {
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_len, 16/BITS_PER_BYTE, "length", NULL },
- { ft_nat, 8/BITS_PER_BYTE, "transform number", NULL },
- { ft_enum, 8/BITS_PER_BYTE, "transform ID", &ipcomp_transformid_names },
- { ft_mbz, 16/BITS_PER_BYTE, NULL, NULL },
- { ft_end, 0, NULL, NULL }
-};
-
-struct_desc isakmp_ipcomp_transform_desc = {
- "ISAKMP Transform Payload (COMP)",
- isat_fields_ipcomp, sizeof(struct isakmp_transform) };
-
-
-/* ISAKMP Key Exchange Payload: no fixed fields beyond the generic ones.
- * layout from RFC 2408 "ISAKMP" section 3.7
- * Variable Key Exchange Data follow the generic fields.
- * Previous next payload: ISAKMP_NEXT_KE
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! !
- * ~ Key Exchange Data ~
- * ! !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-struct_desc isakmp_keyex_desc = { "ISAKMP Key Exchange Payload", isag_fields, sizeof(struct isakmp_generic) };
-
-/* ISAKMP Identification Payload
- * layout from RFC 2408 "ISAKMP" section 3.8
- * See "struct identity" declared later.
- * Variable length Identification Data follow.
- * Previous next payload: ISAKMP_NEXT_ID
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! ID Type ! DOI Specific ID Data !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! !
- * ~ Identification Data ~
- * ! !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-static field_desc isaid_fields[] = {
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_len, 16/BITS_PER_BYTE, "length", NULL },
- { ft_enum, 8/BITS_PER_BYTE, "ID type", &ident_names }, /* ??? depends on DOI? */
- { ft_nat, 8/BITS_PER_BYTE, "DOI specific A", NULL }, /* ??? depends on DOI? */
- { ft_nat, 16/BITS_PER_BYTE, "DOI specific B", NULL }, /* ??? depends on DOI? */
- { ft_end, 0, NULL, NULL }
-};
-
-struct_desc isakmp_identification_desc = { "ISAKMP Identification Payload", isaid_fields, sizeof(struct isakmp_id) };
-
-/* IPSEC Identification Payload Content
- * layout from RFC 2407 "IPsec DOI" section 4.6.2
- * See struct isakmp_id declared earlier.
- * Note: Hashing skips the ISAKMP generic payload header
- * Variable length Identification Data follow.
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! ID Type ! Protocol ID ! Port !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ~ Identification Data ~
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-static field_desc isaiid_fields[] = {
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_len, 16/BITS_PER_BYTE, "length", NULL },
- { ft_enum, 8/BITS_PER_BYTE, "ID type", &ident_names },
- { ft_nat, 8/BITS_PER_BYTE, "Protocol ID", NULL }, /* ??? UDP/TCP or 0? */
- { ft_nat, 16/BITS_PER_BYTE, "port", NULL },
- { ft_end, 0, NULL, NULL }
-};
-
-struct_desc isakmp_ipsec_identification_desc = { "ISAKMP Identification Payload (IPsec DOI)", isaiid_fields, sizeof(struct isakmp_ipsec_id) };
-
-/* ISAKMP Certificate Payload: oddball fixed field beyond the generic ones.
- * layout from RFC 2408 "ISAKMP" section 3.9
- * Variable length Certificate Data follow the generic fields.
- * Previous next payload: ISAKMP_NEXT_CERT.
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Cert Encoding ! !
- * +-+-+-+-+-+-+-+-+ !
- * ~ Certificate Data ~
- * ! !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-static field_desc isacert_fields[] = {
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_len, 16/BITS_PER_BYTE, "length", NULL },
- { ft_enum, 8/BITS_PER_BYTE, "cert encoding", &cert_type_names },
- { ft_end, 0, NULL, NULL }
-};
-
-/* Note: the size field of isakmp_ipsec_certificate_desc cannot be
- * sizeof(struct isakmp_cert) because that will rounded up for padding.
- */
- struct_desc isakmp_ipsec_certificate_desc = { "ISAKMP Certificate Payload", isacert_fields, ISAKMP_CERT_SIZE };
-
-/* ISAKMP Certificate Request Payload: oddball field beyond the generic ones.
- * layout from RFC 2408 "ISAKMP" section 3.10
- * Variable length Certificate Types and Certificate Authorities follow.
- * Previous next payload: ISAKMP_NEXT_CR.
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Cert. Type ! !
- * +-+-+-+-+-+-+-+-+ !
- * ~ Certificate Authority ~
- * ! !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-static field_desc isacr_fields[] = {
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_len, 16/BITS_PER_BYTE, "length", NULL },
- { ft_enum, 8/BITS_PER_BYTE, "cert type", &cert_type_names },
- { ft_end, 0, NULL, NULL }
-};
-
-/* Note: the size field of isakmp_ipsec_cert_req_desc cannot be
- * sizeof(struct isakmp_cr) because that will rounded up for padding.
- */
-struct_desc isakmp_ipsec_cert_req_desc = { "ISAKMP Certificate RequestPayload", isacr_fields, ISAKMP_CR_SIZE };
-
-/* ISAKMP Hash Payload: no fixed fields beyond the generic ones.
- * layout from RFC 2408 "ISAKMP" section 3.11
- * Variable length Hash Data follow.
- * Previous next payload: ISAKMP_NEXT_HASH.
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! !
- * ~ Hash Data ~
- * ! !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-struct_desc isakmp_hash_desc = { "ISAKMP Hash Payload", isag_fields, sizeof(struct isakmp_generic) };
-
-/* ISAKMP Signature Payload: no fixed fields beyond the generic ones.
- * layout from RFC 2408 "ISAKMP" section 3.12
- * Variable length Signature Data follow.
- * Previous next payload: ISAKMP_NEXT_SIG.
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! !
- * ~ Signature Data ~
- * ! !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-struct_desc isakmp_signature_desc = { "ISAKMP Signature Payload", isag_fields, sizeof(struct isakmp_generic) };
-
-/* ISAKMP Nonce Payload: no fixed fields beyond the generic ones.
- * layout from RFC 2408 "ISAKMP" section 3.13
- * Variable length Nonce Data follow.
- * Previous next payload: ISAKMP_NEXT_NONCE.
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! !
- * ~ Nonce Data ~
- * ! !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-struct_desc isakmp_nonce_desc = { "ISAKMP Nonce Payload", isag_fields, sizeof(struct isakmp_generic) };
-
-/* ISAKMP Notification Payload
- * layout from RFC 2408 "ISAKMP" section 3.14
- * This is followed by a variable length SPI
- * and then possibly by variable length Notification Data.
- * Previous next payload: ISAKMP_NEXT_N
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Domain of Interpretation (DOI) !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Protocol-ID ! SPI Size ! Notify Message Type !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! !
- * ~ Security Parameter Index (SPI) ~
- * ! !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! !
- * ~ Notification Data ~
- * ! !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-static field_desc isan_fields[] = {
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_len, 16/BITS_PER_BYTE, "length", NULL },
- { ft_enum, 32/BITS_PER_BYTE, "DOI", &doi_names },
- { ft_nat, 8/BITS_PER_BYTE, "protocol ID", NULL }, /* ??? really enum: ISAKMP, IPSEC, ESP, ... */
- { ft_nat, 8/BITS_PER_BYTE, "SPI size", NULL },
- { ft_enum, 16/BITS_PER_BYTE, "Notify Message Type", &notification_names },
- { ft_end, 0, NULL, NULL }
-};
-
-struct_desc isakmp_notification_desc = { "ISAKMP Notification Payload", isan_fields, sizeof(struct isakmp_notification) };
-
-/* ISAKMP Delete Payload
- * layout from RFC 2408 "ISAKMP" section 3.15
- * This is followed by a variable length SPI.
- * Previous next payload: ISAKMP_NEXT_D
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Domain of Interpretation (DOI) !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Protocol-Id ! SPI Size ! # of SPIs !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! !
- * ~ Security Parameter Index(es) (SPI) ~
- * ! !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-static field_desc isad_fields[] = {
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_len, 16/BITS_PER_BYTE, "length", NULL },
- { ft_enum, 32/BITS_PER_BYTE, "DOI", &doi_names },
- { ft_nat, 8/BITS_PER_BYTE, "protocol ID", NULL }, /* ??? really enum: ISAKMP, IPSEC */
- { ft_nat, 8/BITS_PER_BYTE, "SPI size", NULL },
- { ft_nat, 16/BITS_PER_BYTE, "number of SPIs", NULL },
- { ft_end, 0, NULL, NULL }
-};
-
-struct_desc isakmp_delete_desc = { "ISAKMP Delete Payload", isad_fields, sizeof(struct isakmp_delete) };
-
-/* ISAKMP Vendor ID Payload
- * layout from RFC 2408 "ISAKMP" section 3.15
- * This is followed by a variable length VID.
- * Previous next payload: ISAKMP_NEXT_VID
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! !
- * ~ Vendor ID (VID) ~
- * ! !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-struct_desc isakmp_vendor_id_desc = { "ISAKMP Vendor ID Payload", isag_fields, sizeof(struct isakmp_generic) };
-
-/* MODECFG */
-/*
- * From draft-dukes-ike-mode-cfg
-3.2. Attribute Payload
- 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- ! Next Payload ! RESERVED ! Payload Length !
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- ! Type ! RESERVED ! Identifier !
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- ! !
- ~ Attributes ~
- ! !
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-*/
-static field_desc isaattr_fields[] = {
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_len, 16/BITS_PER_BYTE, "length", NULL },
- { ft_enum, 8/BITS_PER_BYTE, "Attr Msg Type", &attr_msg_type_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_nat, 16/BITS_PER_BYTE, "Identifier", NULL },
- { ft_end, 0, NULL, NULL }
-};
-
-struct_desc isakmp_attr_desc = { "ISAKMP Mode Attribute", isaattr_fields, sizeof(struct isakmp_mode_attr) };
-
-/* ISAKMP NAT-Traversal NAT-D
- * layout from draft-ietf-ipsec-nat-t-ike-01.txt section 3.2
- *
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! HASH of the address and port !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-struct_desc isakmp_nat_d = { "ISAKMP NAT-D Payload", isag_fields, sizeof(struct isakmp_generic) };
-
-/* ISAKMP NAT-Traversal NAT-OA
- * layout from draft-ietf-ipsec-nat-t-ike-01.txt section 4.2
- *
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! ID Type ! RESERVED ! RESERVED !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! IPv4 (4 octets) or IPv6 address (16 octets) !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-static field_desc isanat_oa_fields[] = {
- { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
- { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
- { ft_len, 16/BITS_PER_BYTE, "length", NULL },
- { ft_enum, 8/BITS_PER_BYTE, "ID type", &ident_names },
- { ft_mbz, 24/BITS_PER_BYTE, NULL, NULL },
- { ft_end, 0, NULL, NULL }
-};
-
-struct_desc isakmp_nat_oa = { "ISAKMP NAT-OA Payload", isanat_oa_fields, sizeof(struct isakmp_nat_oa) };
-
-/* descriptor for each payload type
- *
- * There is a slight problem in that some payloads differ, depending
- * on the mode. Since this is table only used for top-level payloads,
- * Proposal and Transform payloads need not be handled.
- * That leaves only Identification payloads as a problem.
- * We make all these entries NULL
- */
-struct_desc *const payload_descs[ISAKMP_NEXT_ROOF] = {
- NULL, /* 0 ISAKMP_NEXT_NONE (No other payload following) */
- &isakmp_sa_desc, /* 1 ISAKMP_NEXT_SA (Security Association) */
- NULL, /* 2 ISAKMP_NEXT_P (Proposal) */
- NULL, /* 3 ISAKMP_NEXT_T (Transform) */
- &isakmp_keyex_desc, /* 4 ISAKMP_NEXT_KE (Key Exchange) */
- NULL, /* 5 ISAKMP_NEXT_ID (Identification) */
- &isakmp_ipsec_certificate_desc, /* 6 ISAKMP_NEXT_CERT (Certificate) */
- &isakmp_ipsec_cert_req_desc, /* 7 ISAKMP_NEXT_CR (Certificate Request) */
- &isakmp_hash_desc, /* 8 ISAKMP_NEXT_HASH (Hash) */
- &isakmp_signature_desc, /* 9 ISAKMP_NEXT_SIG (Signature) */
- &isakmp_nonce_desc, /* 10 ISAKMP_NEXT_NONCE (Nonce) */
- &isakmp_notification_desc, /* 11 ISAKMP_NEXT_N (Notification) */
- &isakmp_delete_desc, /* 12 ISAKMP_NEXT_D (Delete) */
- &isakmp_vendor_id_desc, /* 13 ISAKMP_NEXT_VID (Vendor ID) */
- &isakmp_attr_desc, /* 14 ISAKMP_NEXT_ATTR (Mode Config) */
- NULL, /* 15 */
- NULL, /* 16 */
- NULL, /* 17 */
- NULL, /* 18 */
- NULL, /* 19 */
- &isakmp_nat_d, /* 20=130 ISAKMP_NEXT_NATD (NAT-D) */
- &isakmp_nat_oa, /* 20=131 ISAKMP_NEXT_NATOA (NAT-OA) */
-};
-
-void
-init_pbs(pb_stream *pbs, u_int8_t *start, size_t len, const char *name)
-{
- pbs->container = NULL;
- pbs->desc = NULL;
- pbs->name = name;
- pbs->start = pbs->cur = start;
- pbs->roof = start + len;
- pbs->lenfld = NULL;
- pbs->lenfld_desc = NULL;
-}
-
-#ifdef DEBUG
-
-/* print a host struct
- *
- * This code assumes that the network and host structure
- * members have the same alignment and size! This requires
- * that all padding be explicit.
- */
-void
-DBG_print_struct(const char *label, const void *struct_ptr
-, struct_desc *sd, bool len_meaningful)
-{
- bool immediate = FALSE;
- const u_int8_t *inp = struct_ptr;
- field_desc *fp;
-
- DBG_log("%s%s:", label, sd->name);
-
- for (fp = sd->fields; fp->field_type != ft_end; fp++)
- {
- int i = fp->size;
- u_int32_t n = 0;
-
- switch (fp->field_type)
- {
- case ft_mbz: /* must be zero */
- inp += i;
- break;
- case ft_nat: /* natural number (may be 0) */
- case ft_len: /* length of this struct and any following crud */
- case ft_lv: /* length/value field of attribute */
- case ft_enum: /* value from an enumeration */
- case ft_loose_enum: /* value from an enumeration with only some names known */
- case ft_af_enum: /* Attribute Format + value from an enumeration */
- case ft_af_loose_enum: /* Attribute Format + value from an enumeration */
- case ft_set: /* bits representing set */
- switch (i)
- {
- case 8/BITS_PER_BYTE:
- n = *(const u_int8_t *)inp;
- break;
- case 16/BITS_PER_BYTE:
- n = *(const u_int16_t *)inp;
- break;
- case 32/BITS_PER_BYTE:
- n = *(const u_int32_t *)inp;
- break;
- default:
- bad_case(i);
- }
- switch (fp->field_type)
- {
- case ft_len: /* length of this struct and any following crud */
- case ft_lv: /* length/value field of attribute */
- if (!immediate && !len_meaningful)
- break;
- /* FALL THROUGH */
- case ft_nat: /* natural number (may be 0) */
- DBG_log(" %s: %lu", fp->name, (unsigned long)n);
- break;
- case ft_af_enum: /* Attribute Format + value from an enumeration */
- case ft_af_loose_enum: /* Attribute Format + value from an enumeration */
- if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV)
- immediate = TRUE;
- /* FALL THROUGH */
- case ft_enum: /* value from an enumeration */
- case ft_loose_enum: /* value from an enumeration with only some names known */
- DBG_log(" %s: %s", fp->name, enum_show(fp->desc, n));
- break;
- case ft_set: /* bits representing set */
- DBG_log(" %s: %s", fp->name, bitnamesof(fp->desc, n));
- break;
- default:
- bad_case(fp->field_type);
- }
- inp += i;
- break;
-
- case ft_raw: /* bytes to be left in network-order */
- {
- char m[50]; /* arbitrary limit on name width in log */
-
- snprintf(m, sizeof(m), " %s:", fp->name);
- DBG_dump(m, inp, i);
- inp += i;
- }
- break;
- default:
- bad_case(fp->field_type);
- }
- }
-}
-
-static void
-DBG_prefix_print_struct(const pb_stream *pbs
-, const char *label, const void *struct_ptr
-, struct_desc *sd, bool len_meaningful)
-{
- /* print out a title, with a prefix of asterisks to show
- * the nesting level.
- */
- char space[40]; /* arbitrary limit on label+flock-of-* */
- size_t len = strlen(label);
-
- if (sizeof(space) <= len)
- {
- DBG_print_struct(label, struct_ptr, sd, len_meaningful);
- }
- else
- {
- const pb_stream *p = pbs;
- char *pre = &space[sizeof(space) - (len + 1)];
-
- strcpy(pre, label);
-
- /* put at least one * out */
- for (;;)
- {
- if (pre <= space)
- break;
- *--pre = '*';
- if (p == NULL)
- break;
- p = p->container;
- }
- DBG_print_struct(pre, struct_ptr, sd, len_meaningful);
- }
-}
-
-#endif
-
-/* "parse" a network struct into a host struct.
- *
- * This code assumes that the network and host structure
- * members have the same alignment and size! This requires
- * that all padding be explicit.
- *
- * If obj_pbs is supplied, a new pb_stream is created for the
- * variable part of the structure (this depends on their
- * being one length field in the structure). The cursor of this
- * new PBS is set to after the parsed part of the struct.
- *
- * This routine returns TRUE iff it succeeds.
- */
-
-bool
-in_struct(void *struct_ptr, struct_desc *sd
-, pb_stream *ins, pb_stream *obj_pbs)
-{
- err_t ugh = NULL;
- u_int8_t *cur = ins->cur;
-
- if (ins->roof - cur < (ptrdiff_t)sd->size)
- {
- ugh = builddiag("not enough room in input packet for %s", sd->name);
- }
- else
- {
- u_int8_t *roof = cur + sd->size; /* may be changed by a length field */
- u_int8_t *outp = struct_ptr;
- bool immediate = FALSE;
- field_desc *fp;
-
- for (fp = sd->fields; ugh == NULL; fp++)
- {
- size_t i = fp->size;
-
- passert(ins->roof - cur >= (ptrdiff_t)i);
- passert(cur - ins->cur <= (ptrdiff_t)(sd->size - i));
- passert(outp - (cur - ins->cur) == struct_ptr);
-
-#if 0
- DBG(DBG_PARSING, DBG_log("%d %s"
- , (int) (cur - ins->cur), fp->name == NULL? "" : fp->name));
-#endif
- switch (fp->field_type)
- {
- case ft_mbz: /* must be zero */
- for (; i != 0; i--)
- {
- if (*cur++ != 0)
- {
- ugh = builddiag("byte %d of %s must be zero, but is not"
- , (int) (cur - ins->cur), sd->name);
- break;
- }
- *outp++ = '\0'; /* probably redundant */
- }
- break;
-
- case ft_nat: /* natural number (may be 0) */
- case ft_len: /* length of this struct and any following crud */
- case ft_lv: /* length/value field of attribute */
- case ft_enum: /* value from an enumeration */
- case ft_loose_enum: /* value from an enumeration with only some names known */
- case ft_af_enum: /* Attribute Format + value from an enumeration */
- case ft_af_loose_enum: /* Attribute Format + value from an enumeration */
- case ft_set: /* bits representing set */
- {
- u_int32_t n = 0;
-
- for (; i != 0; i--)
- n = (n << BITS_PER_BYTE) | *cur++;
-
- switch (fp->field_type)
- {
- case ft_len: /* length of this struct and any following crud */
- case ft_lv: /* length/value field of attribute */
- {
- u_int32_t len = fp->field_type == ft_len? n
- : immediate? sd->size : n + sd->size;
-
- if (len < sd->size)
- {
- ugh = builddiag("%s of %s is smaller than minimum"
- , fp->name, sd->name);
- }
- else if (pbs_left(ins) < len)
- {
- ugh = builddiag("%s of %s is larger than can fit"
- , fp->name, sd->name);
- }
- else
- {
- roof = ins->cur + len;
- }
- break;
- }
- case ft_af_loose_enum: /* Attribute Format + value from an enumeration */
- if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV)
- immediate = TRUE;
- break;
- case ft_af_enum: /* Attribute Format + value from an enumeration */
- if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV)
- immediate = TRUE;
- /* FALL THROUGH */
- case ft_enum: /* value from an enumeration */
- if (enum_name(fp->desc, n) == NULL)
- {
- ugh = builddiag("%s of %s has an unknown value: %lu"
- , fp->name, sd->name, (unsigned long)n);
- }
- /* FALL THROUGH */
- case ft_loose_enum: /* value from an enumeration with only some names known */
- break;
- case ft_set: /* bits representing set */
- if (!testset(fp->desc, n))
- {
- ugh = builddiag("bitset %s of %s has unknown member(s): %s"
- , fp->name, sd->name, bitnamesof(fp->desc, n));
- }
- break;
- default:
- break;
- }
- i = fp->size;
- switch (i)
- {
- case 8/BITS_PER_BYTE:
- *(u_int8_t *)outp = n;
- break;
- case 16/BITS_PER_BYTE:
- *(u_int16_t *)outp = n;
- break;
- case 32/BITS_PER_BYTE:
- *(u_int32_t *)outp = n;
- break;
- default:
- bad_case(i);
- }
- outp += i;
- break;
- }
-
- case ft_raw: /* bytes to be left in network-order */
- for (; i != 0; i--)
- {
- *outp++ = *cur++;
- }
- break;
-
- case ft_end: /* end of field list */
- passert(cur == ins->cur + sd->size);
- if (obj_pbs != NULL)
- {
- init_pbs(obj_pbs, ins->cur, roof - ins->cur, sd->name);
- obj_pbs->container = ins;
- obj_pbs->desc = sd;
- obj_pbs->cur = cur;
- }
- ins->cur = roof;
- DBG(DBG_PARSING
- , DBG_prefix_print_struct(ins, "parse ", struct_ptr, sd, TRUE));
- return TRUE;
-
- default:
- bad_case(fp->field_type);
- }
- }
- }
-
- /* some failure got us here: report it */
- loglog(RC_LOG_SERIOUS, ugh);
- return FALSE;
-}
-
-bool
-in_raw(void *bytes, size_t len, pb_stream *ins, const char *name)
-{
- if (pbs_left(ins) < len)
- {
- loglog(RC_LOG_SERIOUS, "not enough bytes left to get %s from %s", name, ins->name);
- return FALSE;
- }
- else
- {
- if (bytes == NULL)
- {
- DBG(DBG_PARSING
- , DBG_log("skipping %u raw bytes of %s (%s)"
- , (unsigned) len, ins->name, name);
- DBG_dump(name, ins->cur, len));
- }
- else
- {
- memcpy(bytes, ins->cur, len);
- DBG(DBG_PARSING
- , DBG_log("parsing %u raw bytes of %s into %s"
- , (unsigned) len, ins->name, name);
- DBG_dump(name, bytes, len));
- }
- ins->cur += len;
- return TRUE;
- }
-}
-
-/* "emit" a host struct into a network packet.
- *
- * This code assumes that the network and host structure
- * members have the same alignment and size! This requires
- * that all padding be explicit.
- *
- * If obj_pbs is non-NULL, its pbs describes a new output stream set up
- * to contain the object. The cursor will be left at the variable part.
- * This new stream must subsequently be finalized by close_output_pbs().
- *
- * The value of any field of type ft_len is computed, not taken
- * from the input struct. The length is actually filled in when
- * the object's output stream is finalized. If obj_pbs is NULL,
- * finalization is done by out_struct before it returns.
- *
- * This routine returns TRUE iff it succeeds.
- */
-
-bool
-out_struct(const void *struct_ptr, struct_desc *sd
-, pb_stream *outs, pb_stream *obj_pbs)
-{
- err_t ugh = NULL;
- const u_int8_t *inp = struct_ptr;
- u_int8_t *cur = outs->cur;
-
- DBG(DBG_EMITTING
- , DBG_prefix_print_struct(outs, "emit ", struct_ptr, sd, obj_pbs==NULL));
-
- if (outs->roof - cur < (ptrdiff_t)sd->size)
- {
- ugh = builddiag("not enough room left in output packet to place %s"
- , sd->name);
- }
- else
- {
- bool immediate = FALSE;
- pb_stream obj;
- field_desc *fp;
-
- obj.lenfld = NULL; /* until a length field is discovered */
- obj.lenfld_desc = NULL;
-
- for (fp = sd->fields; ugh == NULL; fp++)
- {
- size_t i = fp->size;
-
- passert(outs->roof - cur >= (ptrdiff_t)i);
- passert(cur - outs->cur <= (ptrdiff_t)(sd->size - i));
- passert(inp - (cur - outs->cur) == struct_ptr);
-
-#if 0
- DBG(DBG_EMITTING, DBG_log("%d %s"
- , (int) (cur - outs->cur), fp->name == NULL? "" : fp->name);
-#endif
- switch (fp->field_type)
- {
- case ft_mbz: /* must be zero */
- inp += i;
- for (; i != 0; i--)
- *cur++ = '\0';
- break;
- case ft_nat: /* natural number (may be 0) */
- case ft_len: /* length of this struct and any following crud */
- case ft_lv: /* length/value field of attribute */
- case ft_enum: /* value from an enumeration */
- case ft_loose_enum: /* value from an enumeration with only some names known */
- case ft_af_enum: /* Attribute Format + value from an enumeration */
- case ft_af_loose_enum: /* Attribute Format + value from an enumeration */
- case ft_set: /* bits representing set */
- {
- u_int32_t n = 0;
-
- switch (i)
- {
- case 8/BITS_PER_BYTE:
- n = *(const u_int8_t *)inp;
- break;
- case 16/BITS_PER_BYTE:
- n = *(const u_int16_t *)inp;
- break;
- case 32/BITS_PER_BYTE:
- n = *(const u_int32_t *)inp;
- break;
- default:
- bad_case(i);
- }
-
- switch (fp->field_type)
- {
- case ft_len: /* length of this struct and any following crud */
- case ft_lv: /* length/value field of attribute */
- if (immediate)
- break; /* not a length */
- /* We can't check the length because it will likely
- * be filled in after variable part is supplied.
- * We do record where this is so that it can be
- * filled in by a subsequent close_output_pbs().
- */
- passert(obj.lenfld == NULL); /* only one ft_len allowed */
- obj.lenfld = cur;
- obj.lenfld_desc = fp;
- break;
- case ft_af_loose_enum: /* Attribute Format + value from an enumeration */
- if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV)
- immediate = TRUE;
- break;
- case ft_af_enum: /* Attribute Format + value from an enumeration */
- if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV)
- immediate = TRUE;
- /* FALL THROUGH */
- case ft_enum: /* value from an enumeration */
- if (enum_name(fp->desc, n) == NULL)
- {
- ugh = builddiag("%s of %s has an unknown value: %lu"
- , fp->name, sd->name, (unsigned long)n);
- }
- /* FALL THROUGH */
- case ft_loose_enum: /* value from an enumeration with only some names known */
- break;
- case ft_set: /* bits representing set */
- if (!testset(fp->desc, n))
- {
- ugh = builddiag("bitset %s of %s has unknown member(s): %s"
- , fp->name, sd->name, bitnamesof(fp->desc, n));
- }
- break;
- default:
- break;
- }
-
- while (i-- != 0)
- {
- cur[i] = (u_int8_t)n;
- n >>= BITS_PER_BYTE;
- }
- inp += fp->size;
- cur += fp->size;
- break;
- }
- case ft_raw: /* bytes to be left in network-order */
- for (; i != 0; i--)
- *cur++ = *inp++;
- break;
- case ft_end: /* end of field list */
- passert(cur == outs->cur + sd->size);
-
- obj.container = outs;
- obj.desc = sd;
- obj.name = sd->name;
- obj.start = outs->cur;
- obj.cur = cur;
- obj.roof = outs->roof; /* limit of possible */
- /* obj.lenfld and obj.lenfld_desc already set */
-
- if (obj_pbs == NULL)
- {
- close_output_pbs(&obj); /* fill in length field, if any */
- }
- else
- {
- /* We set outs->cur to outs->roof so that
- * any attempt to output something into outs
- * before obj is closed will trigger an error.
- */
- outs->cur = outs->roof;
-
- *obj_pbs = obj;
- }
- return TRUE;
-
- default:
- bad_case(fp->field_type);
- }
- }
- }
-
- /* some failure got us here: report it */
- loglog(RC_LOG_SERIOUS, ugh); /* ??? serious, but errno not relevant */
- return FALSE;
-}
-
-bool
-out_generic(u_int8_t np, struct_desc *sd
-, pb_stream *outs, pb_stream *obj_pbs)
-{
- struct isakmp_generic gen;
-
- passert(sd->fields == isakmp_generic_desc.fields);
- gen.isag_np = np;
- return out_struct(&gen, sd, outs, obj_pbs);
-}
-
-bool
-out_generic_raw(u_int8_t np, struct_desc *sd
-, pb_stream *outs, const void *bytes, size_t len, const char *name)
-{
- pb_stream pbs;
-
- if (!out_generic(np, sd, outs, &pbs)
- || !out_raw(bytes, len, &pbs, name))
- return FALSE;
- close_output_pbs(&pbs);
- return TRUE;
-}
-
-bool
-out_raw(const void *bytes, size_t len, pb_stream *outs, const char *name)
-{
- if (pbs_left(outs) < len)
- {
- loglog(RC_LOG_SERIOUS, "not enough room left to place %lu bytes of %s in %s"
- , (unsigned long) len, name, outs->name);
- return FALSE;
- }
- else
- {
- DBG(DBG_EMITTING
- , DBG_log("emitting %u raw bytes of %s into %s"
- , (unsigned) len, name, outs->name);
- DBG_dump(name, bytes, len));
- memcpy(outs->cur, bytes, len);
- outs->cur += len;
- return TRUE;
- }
-}
-
-bool
-out_zero(size_t len, pb_stream *outs, const char *name)
-{
- if (pbs_left(outs) < len)
- {
- loglog(RC_LOG_SERIOUS, "not enough room left to place %s in %s", name, outs->name);
- return FALSE;
- }
- else
- {
- DBG(DBG_EMITTING, DBG_log("emitting %u zero bytes of %s into %s"
- , (unsigned) len, name, outs->name));
- memset(outs->cur, 0x00, len);
- outs->cur += len;
- return TRUE;
- }
-}
-
-/* Record current length.
- * Note: currently, this may be repeated any number of times;
- * the last one wins.
- */
-void
-close_output_pbs(pb_stream *pbs)
-{
- if (pbs->lenfld != NULL)
- {
- u_int32_t len = pbs_offset(pbs);
- int i = pbs->lenfld_desc->size;
-
- if (pbs->lenfld_desc->field_type == ft_lv)
- len -= sizeof(struct isakmp_attribute);
- DBG(DBG_EMITTING, DBG_log("emitting length of %s: %lu"
- , pbs->name, (unsigned long) len));
- while (i-- != 0)
- {
- pbs->lenfld[i] = (u_int8_t)len;
- len >>= BITS_PER_BYTE;
- }
- }
- if (pbs->container != NULL)
- pbs->container->cur = pbs->cur; /* pass space utilization up */
-}
diff --git a/src/pluto/packet.h b/src/pluto/packet.h
deleted file mode 100644
index 1510b81a0..000000000
--- a/src/pluto/packet.h
+++ /dev/null
@@ -1,653 +0,0 @@
-/* parsing packets: formats and tools
- * Copyright (C) 1997 Angelos D. Keromytis.
- * Copyright (C) 1998-2001 D. Hugh Redelmeier.
- *
- * 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.
- */
-
-#ifndef _PACKET_H
-#define _PACKET_H
-
-/* a struct_desc describes a structure for the struct I/O routines.
- * This requires arrays of field_desc values to describe struct fields.
- */
-
-typedef const struct struct_desc {
- const char *name;
- const struct field_desc *fields;
- size_t size;
-} struct_desc;
-
-/* Note: if an ft_af_enum field has the ISAKMP_ATTR_AF_TV bit set,
- * the subsequent ft_lv field will be interpreted as an immediate value.
- * This matches how attributes are encoded.
- * See RFC 2408 "ISAKMP" 3.3
- */
-
-enum field_type {
- ft_mbz, /* must be zero */
- ft_nat, /* natural number (may be 0) */
- ft_len, /* length of this struct and any following crud */
- ft_lv, /* length/value field of attribute */
- ft_enum, /* value from an enumeration */
- ft_loose_enum, /* value from an enumeration with only some names known */
- ft_af_loose_enum, /* Attribute Format + enumeration, some names known */
- ft_af_enum, /* Attribute Format + value from an enumeration */
- ft_set, /* bits representing set */
- ft_raw, /* bytes to be left in network-order */
- ft_end, /* end of field list */
-};
-
-typedef const struct field_desc {
- enum field_type field_type;
- int size; /* size, in bytes, of field */
- const char *name;
- const void *desc; /* enum_names for enum or char *[] for bits */
-} field_desc;
-
-/* The formatting of input and output of packets is done
- * through packet_byte_stream objects.
- * These describe a stream of bytes in memory.
- * Several routines are provided to manipulate these objects
- * Actual packet transfer is done elsewhere.
- */
-typedef struct packet_byte_stream {
- struct packet_byte_stream *container; /* PBS of which we are part */
- struct_desc *desc;
- const char *name; /* what does this PBS represent? */
- u_int8_t
- *start,
- *cur, /* current position in stream */
- *roof; /* byte after last in PBS (actually just a limit on output) */
- /* For an output PBS, the length field will be filled in later so
- * we need to record its particulars. Note: it may not be aligned.
- */
- u_int8_t *lenfld;
- field_desc *lenfld_desc;
-} pb_stream;
-
-/* For an input PBS, pbs_offset is amount of stream processed.
- * For an output PBS, pbs_offset is current size of stream.
- * For an input PBS, pbs_room is size of stream.
- * For an output PBS, pbs_room is maximum size allowed.
- */
-#define pbs_offset(pbs) ((size_t)((pbs)->cur - (pbs)->start))
-#define pbs_room(pbs) ((size_t)((pbs)->roof - (pbs)->start))
-#define pbs_left(pbs) ((size_t)((pbs)->roof - (pbs)->cur))
-
-extern void init_pbs(pb_stream *pbs, u_int8_t *start, size_t len, const char *name);
-
-extern bool in_struct(void *struct_ptr, struct_desc *sd,
- pb_stream *ins, pb_stream *obj_pbs);
-extern bool in_raw(void *bytes, size_t len, pb_stream *ins, const char *name);
-
-extern bool out_struct(const void *struct_ptr, struct_desc *sd,
- pb_stream *outs, pb_stream *obj_pbs);
-extern bool out_generic(u_int8_t np, struct_desc *sd,
- pb_stream *outs, pb_stream *obj_pbs);
-extern bool out_generic_raw(u_int8_t np, struct_desc *sd,
- pb_stream *outs, const void *bytes, size_t len, const char *name);
-#define out_generic_chunk(np, sd, outs, ch, name) \
- out_generic_raw(np, sd, outs, (ch).ptr, (ch).len, name)
-extern bool out_zero(size_t len, pb_stream *outs, const char *name);
-extern bool out_raw(const void *bytes, size_t len, pb_stream *outs, const char *name);
-#define out_chunk(ch, outs, name) out_raw((ch).ptr, (ch).len, (outs), (name))
-extern void close_output_pbs(pb_stream *pbs);
-
-#ifdef DEBUG
-extern void DBG_print_struct(const char *label, const void *struct_ptr,
- struct_desc *sd, bool len_meaningful);
-#endif
-
-/* ISAKMP Header: for all messages
- * layout from RFC 2408 "ISAKMP" section 3.1
- * 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
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Initiator !
- * ! Cookie !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Responder !
- * ! Cookie !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! MjVer ! MnVer ! Exchange Type ! Flags !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Message ID !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * Although the drafts are a little unclear, there are a few
- * places that specify that messages should be padded with 0x00
- * octets (bytes) to make the length a multiple of something.
- *
- * RFC 2408 "ISAKMP" 3.6 specifies that all messages will be
- * padded to be a multiple of 4 octets in length.
- * ??? This looks vestigial, and we ignore this requirement.
- *
- * RFC 2409 "IKE" Appedix B specifies:
- * Each message should be padded up to the nearest block size
- * using bytes containing 0x00.
- * ??? This does not appear to be limited to encrypted messages,
- * but it surely must be: the block size is meant to be the encryption
- * block size, and that is meaningless for a non-encrypted message.
- *
- * RFC 2409 "IKE" 5.3 specifies:
- * Encrypted payloads are padded up to the nearest block size.
- * All padding bytes, except for the last one, contain 0x00. The
- * last byte of the padding contains the number of the padding
- * bytes used, excluding the last one. Note that this means there
- * will always be padding.
- * ??? This is nuts since payloads are not padded, messages are.
- * It also contradicts Appendix B. So we ignore it.
- *
- * Summary: we pad encrypted output messages with 0x00 to bring them
- * up to a multiple of the encryption block size. On input, we require
- * that any encrypted portion of a message be a multiple of the encryption
- * block size. After any decryption, we ignore padding (any bytes after
- * the first payload that specifies a next payload of none; we don't
- * require them to be zero).
- */
-
-struct isakmp_hdr
-{
- u_int8_t isa_icookie[COOKIE_SIZE];
- u_int8_t isa_rcookie[COOKIE_SIZE];
- u_int8_t isa_np; /* Next payload */
- u_int8_t isa_version; /* high-order 4 bits: Major; low order 4: Minor */
-#define ISA_MAJ_SHIFT 4
-#define ISA_MIN_MASK (~((~0u) << ISA_MAJ_SHIFT))
- u_int8_t isa_xchg; /* Exchange type */
- u_int8_t isa_flags;
- u_int32_t isa_msgid; /* Message ID (RAW) */
- u_int32_t isa_length; /* Length of message */
-};
-
-extern struct_desc isakmp_hdr_desc;
-
-/* Generic portion of all ISAKMP payloads.
- * layout from RFC 2408 "ISAKMP" section 3.2
- * This describes the first 32-bit chunk of all payloads.
- * The previous next payload depends on the actual payload type.
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-struct isakmp_generic
-{
- u_int8_t isag_np;
- u_int8_t isag_reserved;
- u_int16_t isag_length;
-};
-
-extern struct_desc isakmp_generic_desc;
-
-/* ISAKMP Data Attribute (generic representation within payloads)
- * layout from RFC 2408 "ISAKMP" section 3.3
- * This is not a payload type.
- * In TLV format, this is followed by a value field.
- * 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
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * !A! Attribute Type ! AF=0 Attribute Length !
- * !F! ! AF=1 Attribute Value !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * . AF=0 Attribute Value .
- * . AF=1 Not Transmitted .
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-struct isakmp_attribute
-{
- /* The high order bit of isaat_af_type is the Attribute Format
- * If it is off, the format is TLV: lv is the length of the following
- * attribute value.
- * If it is on, the format is TV: lv is the value of the attribute.
- * ISAKMP_ATTR_AF_MASK is the mask in host form.
- *
- * The low order 15 bits of isaat_af_type is the Attribute Type.
- * ISAKMP_ATTR_RTYPE_MASK is the mask in host form.
- */
- u_int16_t isaat_af_type; /* high order bit: AF; lower 15: rtype */
- u_int16_t isaat_lv; /* Length or value */
-};
-
-#define ISAKMP_ATTR_AF_MASK 0x8000
-#define ISAKMP_ATTR_AF_TV ISAKMP_ATTR_AF_MASK /* value in lv */
-#define ISAKMP_ATTR_AF_TLV 0 /* length in lv; value follows */
-
-#define ISAKMP_ATTR_RTYPE_MASK 0x7FFF
-
-extern struct_desc
- isakmp_oakley_attribute_desc,
- isakmp_ipsec_attribute_desc;
-
-/* ISAKMP Security Association Payload
- * layout from RFC 2408 "ISAKMP" section 3.4
- * A variable length Situation follows.
- * Previous next payload: ISAKMP_NEXT_SA
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Domain of Interpretation (DOI) !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! !
- * ~ Situation ~
- * ! !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-struct isakmp_sa
-{
- u_int8_t isasa_np; /* Next payload */
- u_int8_t isasa_reserved;
- u_int16_t isasa_length; /* Payload length */
- u_int32_t isasa_doi; /* DOI */
-};
-
-extern struct_desc isakmp_sa_desc;
-
-extern struct_desc ipsec_sit_desc;
-
-/* ISAKMP Proposal Payload
- * layout from RFC 2408 "ISAKMP" section 3.5
- * A variable length SPI follows.
- * Previous next payload: ISAKMP_NEXT_P
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Proposal # ! Protocol-Id ! SPI Size !# of Transforms!
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! SPI (variable) !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-struct isakmp_proposal
-{
- u_int8_t isap_np;
- u_int8_t isap_reserved;
- u_int16_t isap_length;
- u_int8_t isap_proposal;
- u_int8_t isap_protoid;
- u_int8_t isap_spisize;
- u_int8_t isap_notrans; /* Number of transforms */
-};
-
-extern struct_desc isakmp_proposal_desc;
-
-/* ISAKMP Transform Payload
- * layout from RFC 2408 "ISAKMP" section 3.6
- * Variable length SA Attributes follow.
- * Previous next payload: ISAKMP_NEXT_T
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Transform # ! Transform-Id ! RESERVED2 !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! !
- * ~ SA Attributes ~
- * ! !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-struct isakmp_transform
-{
- u_int8_t isat_np;
- u_int8_t isat_reserved;
- u_int16_t isat_length;
- u_int8_t isat_transnum; /* Number of the transform */
- u_int8_t isat_transid;
- u_int16_t isat_reserved2;
-};
-
-extern struct_desc
- isakmp_isakmp_transform_desc,
- isakmp_ah_transform_desc,
- isakmp_esp_transform_desc,
- isakmp_ipcomp_transform_desc;
-
-/* ISAKMP Key Exchange Payload: no fixed fields beyond the generic ones.
- * layout from RFC 2408 "ISAKMP" section 3.7
- * Variable Key Exchange Data follow the generic fields.
- * Previous next payload: ISAKMP_NEXT_KE
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! !
- * ~ Key Exchange Data ~
- * ! !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-extern struct_desc isakmp_keyex_desc;
-
-/* ISAKMP Identification Payload
- * layout from RFC 2408 "ISAKMP" section 3.8
- * See "struct identity" declared later.
- * Variable length Identification Data follow.
- * Previous next payload: ISAKMP_NEXT_ID
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! ID Type ! DOI Specific ID Data !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! !
- * ~ Identification Data ~
- * ! !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-struct isakmp_id
-{
- u_int8_t isaid_np;
- u_int8_t isaid_reserved;
- u_int16_t isaid_length;
- u_int8_t isaid_idtype;
- u_int8_t isaid_doi_specific_a;
- u_int16_t isaid_doi_specific_b;
-};
-
-extern struct_desc isakmp_identification_desc;
-
-/* IPSEC Identification Payload Content
- * layout from RFC 2407 "IPsec DOI" section 4.6.2
- * See struct isakmp_id declared earlier.
- * Note: Hashing skips the ISAKMP generic payload header
- * Variable length Identification Data follow.
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! ID Type ! Protocol ID ! Port !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ~ Identification Data ~
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-struct isakmp_ipsec_id
-{
- u_int8_t isaiid_np;
- u_int8_t isaiid_reserved;
- u_int16_t isaiid_length;
- u_int8_t isaiid_idtype;
- u_int8_t isaiid_protoid;
- u_int16_t isaiid_port;
-};
-
-extern struct_desc isakmp_ipsec_identification_desc;
-
-/* ISAKMP Certificate Payload: no fixed fields beyond the generic ones.
- * layout from RFC 2408 "ISAKMP" section 3.9
- * Variable length Certificate Data follow the generic fields.
- * Previous next payload: ISAKMP_NEXT_CERT.
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Cert Encoding ! !
- * +-+-+-+-+-+-+-+-+ !
- * ~ Certificate Data ~
- * ! !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-struct isakmp_cert
-{
- u_int8_t isacert_np;
- u_int8_t isacert_reserved;
- u_int16_t isacert_length;
- u_int8_t isacert_type;
-};
-
-/* NOTE: this packet type has a fixed portion that is not a
- * multiple of 4 octets. This means that sizeof(struct isakmp_cert)
- * yields the wrong value for the length.
- */
-#define ISAKMP_CERT_SIZE 5
-
-extern struct_desc isakmp_ipsec_certificate_desc;
-
-/* ISAKMP Certificate Request Payload: no fixed fields beyond the generic ones.
- * layout from RFC 2408 "ISAKMP" section 3.10
- * Variable length Certificate Types and Certificate Authorities follow.
- * Previous next payload: ISAKMP_NEXT_CR.
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Cert. Type ! !
- * +-+-+-+-+-+-+-+-+ !
- * ~ Certificate Authority ~
- * ! !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-struct isakmp_cr
-{
- u_int8_t isacr_np;
- u_int8_t isacr_reserved;
- u_int16_t isacr_length;
- u_int8_t isacr_type;
-};
-
-/* NOTE: this packet type has a fixed portion that is not a
- * multiple of 4 octets. This means that sizeof(struct isakmp_cr)
- * yields the wrong value for the length.
- */
-#define ISAKMP_CR_SIZE 5
-
-extern struct_desc isakmp_ipsec_cert_req_desc;
-
-/* ISAKMP Hash Payload: no fixed fields beyond the generic ones.
- * layout from RFC 2408 "ISAKMP" section 3.11
- * Variable length Hash Data follow.
- * Previous next payload: ISAKMP_NEXT_HASH.
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! !
- * ~ Hash Data ~
- * ! !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-extern struct_desc isakmp_hash_desc;
-
-/* ISAKMP Signature Payload: no fixed fields beyond the generic ones.
- * layout from RFC 2408 "ISAKMP" section 3.12
- * Variable length Signature Data follow.
- * Previous next payload: ISAKMP_NEXT_SIG.
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! !
- * ~ Signature Data ~
- * ! !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-extern struct_desc isakmp_signature_desc;
-
-/* ISAKMP Nonce Payload: no fixed fields beyond the generic ones.
- * layout from RFC 2408 "ISAKMP" section 3.13
- * Variable length Nonce Data follow.
- * Previous next payload: ISAKMP_NEXT_NONCE.
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! !
- * ~ Nonce Data ~
- * ! !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-extern struct_desc isakmp_nonce_desc;
-
-/* ISAKMP Notification Payload
- * layout from RFC 2408 "ISAKMP" section 3.14
- * This is followed by a variable length SPI
- * and then possibly by variable length Notification Data.
- * Previous next payload: ISAKMP_NEXT_N
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Domain of Interpretation (DOI) !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Protocol-ID ! SPI Size ! Notify Message Type !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! !
- * ~ Security Parameter Index (SPI) ~
- * ! !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! !
- * ~ Notification Data ~
- * ! !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-struct isakmp_notification
-{
- u_int8_t isan_np;
- u_int8_t isan_reserved;
- u_int16_t isan_length;
- u_int32_t isan_doi;
- u_int8_t isan_protoid;
- u_int8_t isan_spisize;
- u_int16_t isan_type;
-};
-
-extern struct_desc isakmp_notification_desc;
-
-/* ISAKMP Delete Payload
- * layout from RFC 2408 "ISAKMP" section 3.15
- * This is followed by a variable length SPI.
- * Previous next payload: ISAKMP_NEXT_D
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Domain of Interpretation (DOI) !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Protocol-Id ! SPI Size ! # of SPIs !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! !
- * ~ Security Parameter Index(es) (SPI) ~
- * ! !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-struct isakmp_delete
-{
- u_int8_t isad_np;
- u_int8_t isad_reserved;
- u_int16_t isad_length;
- u_int32_t isad_doi;
- u_int8_t isad_protoid;
- u_int8_t isad_spisize;
- u_int16_t isad_nospi;
-};
-
-extern struct_desc isakmp_delete_desc;
-
-/* From draft-dukes-ike-mode-cfg
-3.2. Attribute Payload
- 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- ! Next Payload ! RESERVED ! Payload Length !
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- ! Type ! RESERVED ! Identifier !
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- ! !
- ! !
- ~ Attributes ~
- ! !
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-*/
-struct isakmp_mode_attr
-{
- u_int8_t isama_np;
- u_int8_t isama_reserved;
- u_int16_t isama_length;
- u_int8_t isama_type;
- u_int8_t isama_reserved2;
- u_int16_t isama_identifier;
-};
-
-extern struct_desc isakmp_attr_desc;
-extern struct_desc isakmp_modecfg_attribute_desc;
-
-/* ISAKMP Vendor ID Payload
- * layout from RFC 2408 "ISAKMP" section 3.15
- * This is followed by a variable length VID.
- * Previous next payload: ISAKMP_NEXT_VID
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! Next Payload ! RESERVED ! Payload Length !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ! !
- * ~ Vendor ID (VID) ~
- * ! !
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-extern struct_desc isakmp_vendor_id_desc;
-
-struct isakmp_nat_oa
-{
- u_int8_t isanoa_np;
- u_int8_t isanoa_reserved_1;
- u_int16_t isanoa_length;
- u_int8_t isanoa_idtype;
- u_int8_t isanoa_reserved_2;
- u_int16_t isanoa_reserved_3;
-};
-
-extern struct_desc isakmp_nat_d;
-extern struct_desc isakmp_nat_oa;
-
-/* union of all payloads */
-
-union payload {
- struct isakmp_generic generic;
- struct isakmp_sa sa;
- struct isakmp_proposal proposal;
- struct isakmp_transform transform;
- struct isakmp_id id; /* Main Mode */
- struct isakmp_cert cert;
- struct isakmp_cr cr;
- struct isakmp_ipsec_id ipsec_id; /* Quick Mode */
- struct isakmp_notification notification;
- struct isakmp_delete delete;
- struct isakmp_nat_oa nat_oa;
- struct isakmp_mode_attr attribute;
-};
-
-/* descriptor for each payload type
- *
- * There is a slight problem in that some payloads differ, depending
- * on the mode. Since this is table only used for top-level payloads,
- * Proposal and Transform payloads need not be handled.
- * That leaves only Identification payloads as a problem.
- * We make all these entries NULL
- */
-extern struct_desc *const payload_descs[ISAKMP_NEXT_ROOF];
-
-#endif /* _PACKET_H */
diff --git a/src/pluto/pkcs7.c b/src/pluto/pkcs7.c
deleted file mode 100644
index 10b2a4d5a..000000000
--- a/src/pluto/pkcs7.c
+++ /dev/null
@@ -1,755 +0,0 @@
-/* Support of PKCS#7 data structures
- * Copyright (C) 2005 Jan Hutter, Martin Willi
- * Copyright (C) 2002-2009 Andreas Steffen
- *
- * HSR Hochschule fuer Technik Rapperswil, Switzerland
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include <library.h>
-#include <debug.h>
-#include <asn1/asn1.h>
-#include <asn1/asn1_parser.h>
-#include <asn1/oid.h>
-#include <crypto/rngs/rng.h>
-#include <crypto/crypters/crypter.h>
-#include <credentials/certificates/x509.h>
-
-#include "pkcs7.h"
-
-const contentInfo_t empty_contentInfo = {
- OID_UNKNOWN , /* type */
- { NULL, 0 } /* content */
-};
-
-/**
- * ASN.1 definition of the PKCS#7 ContentInfo type
- */
-static const asn1Object_t contentInfoObjects[] = {
- { 0, "contentInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
- { 1, "contentType", ASN1_OID, ASN1_BODY }, /* 1 */
- { 1, "content", ASN1_CONTEXT_C_0, ASN1_OPT|ASN1_BODY }, /* 2 */
- { 1, "end opt", ASN1_EOC, ASN1_END }, /* 3 */
- { 0, "exit", ASN1_EOC, ASN1_EXIT }
-};
-#define PKCS7_INFO_TYPE 1
-#define PKCS7_INFO_CONTENT 2
-
-/**
- * ASN.1 definition of the PKCS#7 signedData type
- */
-static const asn1Object_t signedDataObjects[] = {
- { 0, "signedData", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
- { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
- { 1, "digestAlgorithms", ASN1_SET, ASN1_LOOP }, /* 2 */
- { 2, "algorithm", ASN1_EOC, ASN1_RAW }, /* 3 */
- { 1, "end loop", ASN1_EOC, ASN1_END }, /* 4 */
- { 1, "contentInfo", ASN1_EOC, ASN1_RAW }, /* 5 */
- { 1, "certificates", ASN1_CONTEXT_C_0, ASN1_OPT|ASN1_LOOP }, /* 6 */
- { 2, "certificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 7 */
- { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 8 */
- { 1, "crls", ASN1_CONTEXT_C_1, ASN1_OPT|ASN1_LOOP }, /* 9 */
- { 2, "crl", ASN1_SEQUENCE, ASN1_OBJ }, /* 10 */
- { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 11 */
- { 1, "signerInfos", ASN1_SET, ASN1_LOOP }, /* 12 */
- { 2, "signerInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 13 */
- { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 14 */
- { 3, "issuerAndSerialNumber", ASN1_SEQUENCE, ASN1_BODY }, /* 15 */
- { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 16 */
- { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 17 */
- { 3, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 18 */
- { 3, "authenticatedAttributes", ASN1_CONTEXT_C_0, ASN1_OPT|ASN1_OBJ }, /* 19 */
- { 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */
- { 3, "digestEncryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 21 */
- { 3, "encryptedDigest", ASN1_OCTET_STRING, ASN1_BODY }, /* 22 */
- { 3, "unauthenticatedAttributes", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 23 */
- { 3, "end opt", ASN1_EOC, ASN1_END }, /* 24 */
- { 1, "end loop", ASN1_EOC, ASN1_END }, /* 25 */
- { 0, "exit", ASN1_EOC, ASN1_EXIT }
-};
-#define PKCS7_SIGNED_VERSION 1
-#define PKCS7_DIGEST_ALG 3
-#define PKCS7_SIGNED_CONTENT_INFO 5
-#define PKCS7_SIGNED_CERT 7
-#define PKCS7_SIGNER_INFO 13
-#define PKCS7_SIGNER_INFO_VERSION 14
-#define PKCS7_SIGNED_ISSUER 16
-#define PKCS7_SIGNED_SERIAL_NUMBER 17
-#define PKCS7_DIGEST_ALGORITHM 18
-#define PKCS7_AUTH_ATTRIBUTES 19
-#define PKCS7_DIGEST_ENC_ALGORITHM 21
-#define PKCS7_ENCRYPTED_DIGEST 22
-
-/**
- * ASN.1 definition of the PKCS#7 envelopedData type
- */
-static const asn1Object_t envelopedDataObjects[] = {
- { 0, "envelopedData", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
- { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
- { 1, "recipientInfos", ASN1_SET, ASN1_LOOP }, /* 2 */
- { 2, "recipientInfo", ASN1_SEQUENCE, ASN1_BODY }, /* 3 */
- { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 4 */
- { 3, "issuerAndSerialNumber", ASN1_SEQUENCE, ASN1_BODY }, /* 5 */
- { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 6 */
- { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 7 */
- { 3, "encryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 8 */
- { 3, "encryptedKey", ASN1_OCTET_STRING, ASN1_BODY }, /* 9 */
- { 1, "end loop", ASN1_EOC, ASN1_END }, /* 10 */
- { 1, "encryptedContentInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 11 */
- { 2, "contentType", ASN1_OID, ASN1_BODY }, /* 12 */
- { 2, "contentEncryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 13 */
- { 2, "encryptedContent", ASN1_CONTEXT_S_0, ASN1_BODY }, /* 14 */
- { 0, "exit", ASN1_EOC, ASN1_EXIT }
-};
-#define PKCS7_ENVELOPED_VERSION 1
-#define PKCS7_RECIPIENT_INFO_VERSION 4
-#define PKCS7_ISSUER 6
-#define PKCS7_SERIAL_NUMBER 7
-#define PKCS7_ENCRYPTION_ALG 8
-#define PKCS7_ENCRYPTED_KEY 9
-#define PKCS7_CONTENT_TYPE 12
-#define PKCS7_CONTENT_ENC_ALGORITHM 13
-#define PKCS7_ENCRYPTED_CONTENT 14
-#define PKCS7_ENVELOPED_ROOF 15
-
-/**
- * Parse PKCS#7 ContentInfo object
- */
-bool pkcs7_parse_contentInfo(chunk_t blob, u_int level0, contentInfo_t *cInfo)
-{
- asn1_parser_t *parser;
- chunk_t object;
- int objectID;
- bool success = FALSE;
-
- parser = asn1_parser_create(contentInfoObjects, blob);
- parser->set_top_level(parser, level0);
-
- while (parser->iterate(parser, &objectID, &object))
- {
- if (objectID == PKCS7_INFO_TYPE)
- {
- cInfo->type = asn1_known_oid(object);
- if (cInfo->type < OID_PKCS7_DATA
- || cInfo->type > OID_PKCS7_ENCRYPTED_DATA)
- {
- DBG1(DBG_LIB, "unknown pkcs7 content type");
- goto end;
- }
- }
- else if (objectID == PKCS7_INFO_CONTENT)
- {
- cInfo->content = object;
- }
- }
- success = parser->success(parser);
-
-end:
- parser->destroy(parser);
- return success;
-}
-
-/**
- * Parse a PKCS#7 signedData object
- */
-bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data,
- linked_list_t *certs,
- chunk_t *attributes, certificate_t *cacert)
-{
- asn1_parser_t *parser;
- chunk_t object;
- int digest_alg = OID_UNKNOWN;
- int enc_alg = OID_UNKNOWN;
- int signerInfos = 0;
- int version;
- int objectID;
- bool success = FALSE;
-
- contentInfo_t cInfo = empty_contentInfo;
- chunk_t encrypted_digest = chunk_empty;
-
- if (!pkcs7_parse_contentInfo(blob, 0, &cInfo))
- {
- return FALSE;
- }
- if (cInfo.type != OID_PKCS7_SIGNED_DATA)
- {
- DBG1(DBG_LIB, "pkcs7 content type is not signedData");
- return FALSE;
- }
-
- parser = asn1_parser_create(signedDataObjects, cInfo.content);
- parser->set_top_level(parser, 2);
-
- while (parser->iterate(parser, &objectID, &object))
- {
- u_int level = parser->get_level(parser);
-
- switch (objectID)
- {
- case PKCS7_SIGNED_VERSION:
- version = object.len ? (int)*object.ptr : 0;
- DBG2(DBG_LIB, " v%d", version);
- break;
- case PKCS7_DIGEST_ALG:
- digest_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
- break;
- case PKCS7_SIGNED_CONTENT_INFO:
- if (data != NULL)
- {
- pkcs7_parse_contentInfo(object, level, data);
- }
- break;
- case PKCS7_SIGNED_CERT:
- {
- certificate_t *cert;
-
- DBG2(DBG_LIB, " parsing pkcs7-wrapped certificate");
- cert = lib->creds->create(lib->creds,
- CRED_CERTIFICATE, CERT_X509,
- BUILD_BLOB_ASN1_DER, object,
- BUILD_END);
- if (cert)
- {
- certs->insert_last(certs, cert);
- }
- }
- break;
- case PKCS7_SIGNER_INFO:
- signerInfos++;
- DBG2(DBG_LIB, " signer #%d", signerInfos);
- break;
- case PKCS7_SIGNER_INFO_VERSION:
- version = object.len ? (int)*object.ptr : 0;
- DBG2(DBG_LIB, " v%d", version);
- break;
- case PKCS7_SIGNED_ISSUER:
- {
- identification_t *issuer = identification_create_from_encoding(
- ID_DER_ASN1_DN, object);
- DBG2(DBG_LIB, " \"%Y\"", issuer);
- issuer->destroy(issuer);
- break;
- }
- case PKCS7_AUTH_ATTRIBUTES:
- if (attributes != NULL)
- {
- *attributes = object;
- *attributes->ptr = ASN1_SET;
- }
- break;
- case PKCS7_DIGEST_ALGORITHM:
- digest_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
- break;
- case PKCS7_DIGEST_ENC_ALGORITHM:
- enc_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
- break;
- case PKCS7_ENCRYPTED_DIGEST:
- encrypted_digest = object;
- }
- }
- success = parser->success(parser);
- parser->destroy(parser);
- if (!success)
- {
- return FALSE;
- }
-
- /* check the signature only if a cacert is available */
- if (cacert != NULL)
- {
- public_key_t *key;
- signature_scheme_t scheme;
-
- scheme = signature_scheme_from_oid(digest_alg);
- if (scheme == SIGN_UNKNOWN)
- {
- DBG1(DBG_LIB, "unsupported signature scheme");
- return FALSE;
- }
- if (signerInfos == 0)
- {
- DBG1(DBG_LIB, "no signerInfo object found");
- return FALSE;
- }
- else if (signerInfos > 1)
- {
- DBG1(DBG_LIB, "more than one signerInfo object found");
- return FALSE;
- }
- if (attributes->ptr == NULL)
- {
- DBG1(DBG_LIB, "no authenticatedAttributes object found");
- return FALSE;
- }
- if (enc_alg != OID_RSA_ENCRYPTION)
- {
- DBG1(DBG_LIB, "only RSA digest encryption supported");
- return FALSE;
- }
-
- /* verify the signature */
- key = cacert->get_public_key(cacert);
- if (key == NULL)
- {
- DBG1(DBG_LIB, "no public key found in CA certificate");
- return FALSE;
- }
- if (key->verify(key, scheme, *attributes, encrypted_digest))
- {
- DBG2(DBG_LIB, "signature is valid");
- }
- else
- {
- DBG1(DBG_LIB, "invalid signature");
- success = FALSE;
- }
- key->destroy(key);
- }
- return success;
-}
-
-/**
- * Parse a PKCS#7 envelopedData object
- */
-bool pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data,
- chunk_t serialNumber,
- private_key_t *key)
-{
- asn1_parser_t *parser;
- chunk_t object;
- chunk_t iv = chunk_empty;
- chunk_t symmetric_key = chunk_empty;
- chunk_t encrypted_content = chunk_empty;
-
- crypter_t *crypter = NULL;
-
- int enc_alg = OID_UNKNOWN;
- int content_enc_alg = OID_UNKNOWN;
- int version;
- int objectID;
- bool success = FALSE;
-
- contentInfo_t cInfo = empty_contentInfo;
- *data = chunk_empty;
-
- if (!pkcs7_parse_contentInfo(blob, 0, &cInfo))
- {
- goto failed;
- }
- if (cInfo.type != OID_PKCS7_ENVELOPED_DATA)
- {
- DBG1(DBG_LIB, "pkcs7 content type is not envelopedData");
- goto failed;
- }
-
- parser = asn1_parser_create(envelopedDataObjects, cInfo.content);
- parser->set_top_level(parser, 2);
-
- while (parser->iterate(parser, &objectID, &object))
- {
- u_int level = parser->get_level(parser);
-
- switch (objectID)
- {
- case PKCS7_ENVELOPED_VERSION:
- version = object.len ? (int)*object.ptr : 0;
- DBG2(DBG_LIB, " v%d", version);
- if (version != 0)
- {
- DBG1(DBG_LIB, "envelopedData version is not 0");
- goto end;
- }
- break;
- case PKCS7_RECIPIENT_INFO_VERSION:
- version = object.len ? (int)*object.ptr : 0;
- DBG2(DBG_LIB, " v%d", version);
- if (version != 0)
- {
- DBG1(DBG_LIB, "recipient info version is not 0");
- goto end;
- }
- break;
- case PKCS7_ISSUER:
- {
- identification_t *issuer = identification_create_from_encoding(
- ID_DER_ASN1_DN, object);
- DBG2(DBG_LIB, " \"%Y\"", issuer);
- issuer->destroy(issuer);
- break;
- }
- case PKCS7_SERIAL_NUMBER:
- if (!chunk_equals(serialNumber, object))
- {
- DBG1(DBG_LIB, "serial numbers do not match");
- goto end;
- }
- break;
- case PKCS7_ENCRYPTION_ALG:
- enc_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
- if (enc_alg != OID_RSA_ENCRYPTION)
- {
- DBG1(DBG_LIB, "only rsa encryption supported");
- goto end;
- }
- break;
- case PKCS7_ENCRYPTED_KEY:
- if (!key->decrypt(key, ENCRYPT_RSA_PKCS1, object, &symmetric_key))
- {
- DBG1(DBG_LIB, "symmetric key could not be decrypted with rsa");
- goto end;
- }
- DBG4(DBG_LIB, "symmetric key %B", &symmetric_key);
- break;
- case PKCS7_CONTENT_TYPE:
- if (asn1_known_oid(object) != OID_PKCS7_DATA)
- {
- DBG1(DBG_LIB, "encrypted content not of type pkcs7 data");
- goto end;
- }
- break;
- case PKCS7_CONTENT_ENC_ALGORITHM:
- content_enc_alg = asn1_parse_algorithmIdentifier(object, level, &iv);
-
- if (content_enc_alg == OID_UNKNOWN)
- {
- DBG1(DBG_LIB, "unknown content encryption algorithm");
- goto end;
- }
- if (!asn1_parse_simple_object(&iv, ASN1_OCTET_STRING, level+1, "IV"))
- {
- DBG1(DBG_LIB, "IV could not be parsed");
- goto end;
- }
- break;
- case PKCS7_ENCRYPTED_CONTENT:
- encrypted_content = object;
- break;
- }
- }
- success = parser->success(parser);
-
-end:
- parser->destroy(parser);
- if (!success)
- {
- goto failed;
- }
- success = FALSE;
-
- /* decrypt the content */
- {
- encryption_algorithm_t alg;
- size_t key_size;
- crypter_t *crypter;
-
- alg = encryption_algorithm_from_oid(content_enc_alg, &key_size);
- if (alg == ENCR_UNDEFINED)
- {
- DBG1(DBG_LIB, "unsupported content encryption algorithm");
- goto failed;
- }
- crypter = lib->crypto->create_crypter(lib->crypto, alg, key_size);
- if (crypter == NULL)
- {
- DBG1(DBG_LIB, "crypter %N not available", encryption_algorithm_names, alg);
- goto failed;
- }
- if (symmetric_key.len != crypter->get_key_size(crypter))
- {
- DBG1(DBG_LIB, "symmetric key length %d is wrong", symmetric_key.len);
- goto failed;
- }
- if (iv.len != crypter->get_iv_size(crypter))
- {
- DBG1(DBG_LIB, "IV length %d is wrong", iv.len);
- goto failed;
- }
- crypter->set_key(crypter, symmetric_key);
- crypter->decrypt(crypter, encrypted_content, iv, data);
- DBG4(DBG_LIB, "decrypted content with padding: %B", data);
- }
-
- /* remove the padding */
- {
- u_char *pos = data->ptr + data->len - 1;
- u_char pattern = *pos;
- size_t padding = pattern;
-
- if (padding > data->len)
- {
- DBG1(DBG_LIB, "padding greater than data length");
- goto failed;
- }
- data->len -= padding;
-
- while (padding-- > 0)
- {
- if (*pos-- != pattern)
- {
- DBG1(DBG_LIB, "wrong padding pattern");
- goto failed;
- }
- }
- }
- success = TRUE;
-
-failed:
- DESTROY_IF(crypter);
- chunk_clear(&symmetric_key);
- if (!success)
- {
- free(data->ptr);
- }
- return success;
-}
-
-/**
- * @brief Builds a contentType attribute
- *
- * @return ASN.1 encoded contentType attribute
- */
-chunk_t pkcs7_contentType_attribute(void)
-{
- return asn1_wrap(ASN1_SEQUENCE, "mm",
- asn1_build_known_oid(OID_PKCS9_CONTENT_TYPE),
- asn1_wrap(ASN1_SET, "m",
- asn1_build_known_oid(OID_PKCS7_DATA)));
-}
-
-/**
- * @brief Builds a messageDigest attribute
- *
- *
- * @param[in] blob content to create digest of
- * @param[in] digest_alg digest algorithm to be used
- * @return ASN.1 encoded messageDigest attribute
- *
- */
-chunk_t pkcs7_messageDigest_attribute(chunk_t content, int digest_alg)
-{
- chunk_t digest;
- hash_algorithm_t hash_alg;
- hasher_t *hasher;
-
- hash_alg = hasher_algorithm_from_oid(digest_alg);
- hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
- hasher->allocate_hash(hasher, content, &digest);
- hasher->destroy(hasher);
-
- return asn1_wrap(ASN1_SEQUENCE, "mm",
- asn1_build_known_oid(OID_PKCS9_MESSAGE_DIGEST),
- asn1_wrap(ASN1_SET, "m",
- asn1_wrap(ASN1_OCTET_STRING, "m", digest)));
-}
-
-/**
- * build a DER-encoded contentInfo object
- */
-static chunk_t pkcs7_build_contentInfo(contentInfo_t *cInfo)
-{
- return (cInfo->content.ptr) ?
- asn1_wrap(ASN1_SEQUENCE, "mm",
- asn1_build_known_oid(cInfo->type),
- asn1_simple_object(ASN1_CONTEXT_C_0, cInfo->content)) :
- asn1_build_known_oid(cInfo->type);
-}
-
-/**
- * build issuerAndSerialNumber object
- */
-chunk_t pkcs7_build_issuerAndSerialNumber(certificate_t *cert)
-{
- identification_t *issuer = cert->get_issuer(cert);
- x509_t *x509 = (x509_t*)cert;
-
- return asn1_wrap(ASN1_SEQUENCE, "cm",
- issuer->get_encoding(issuer),
- asn1_integer("c", x509->get_serial(x509)));
-}
-
-/**
- * create a signed pkcs7 contentInfo object
- */
-chunk_t pkcs7_build_signedData(chunk_t data, chunk_t attributes,
- certificate_t *cert, int digest_alg,
- private_key_t *key)
-{
- contentInfo_t pkcs7Data, signedData;
- chunk_t authenticatedAttributes = chunk_empty;
- chunk_t encryptedDigest = chunk_empty;
- chunk_t signerInfo, cInfo, signature, encoding = chunk_empty;;
- signature_scheme_t scheme = signature_scheme_from_oid(digest_alg);
-
- if (attributes.ptr)
- {
- if (key->sign(key, scheme, attributes, &signature))
- {
- encryptedDigest = asn1_wrap(ASN1_OCTET_STRING, "m", signature);
- authenticatedAttributes = chunk_clone(attributes);
- *authenticatedAttributes.ptr = ASN1_CONTEXT_C_0;
- }
- }
- else if (data.ptr)
- {
- if (key->sign(key, scheme, data, &signature))
- {
- encryptedDigest = asn1_wrap(ASN1_OCTET_STRING, "m", signature);
- }
- }
- signerInfo = asn1_wrap(ASN1_SEQUENCE, "cmmmmm"
- , ASN1_INTEGER_1
- , pkcs7_build_issuerAndSerialNumber(cert)
- , asn1_algorithmIdentifier(digest_alg)
- , authenticatedAttributes
- , asn1_algorithmIdentifier(OID_RSA_ENCRYPTION)
- , encryptedDigest);
-
- pkcs7Data.type = OID_PKCS7_DATA;
- pkcs7Data.content = (data.ptr == NULL)? chunk_empty
- : asn1_simple_object(ASN1_OCTET_STRING, data);
-
- cert->get_encoding(cert, CERT_ASN1_DER, &encoding);
- signedData.type = OID_PKCS7_SIGNED_DATA;
- signedData.content = asn1_wrap(ASN1_SEQUENCE, "cmmmm"
- , ASN1_INTEGER_1
- , asn1_wrap(ASN1_SET, "m", asn1_algorithmIdentifier(digest_alg))
- , pkcs7_build_contentInfo(&pkcs7Data)
- , asn1_wrap(ASN1_CONTEXT_C_0, "m", encoding)
- , asn1_wrap(ASN1_SET, "m", signerInfo));
-
- cInfo = pkcs7_build_contentInfo(&signedData);
- DBG3(DBG_LIB, "signedData %B", &cInfo);
-
- free(pkcs7Data.content.ptr);
- free(signedData.content.ptr);
- return cInfo;
-}
-
-/**
- * create a symmetrically encrypted pkcs7 contentInfo object
- */
-chunk_t pkcs7_build_envelopedData(chunk_t data, certificate_t *cert, int enc_alg)
-{
- encryption_algorithm_t alg;
- size_t alg_key_size;
- chunk_t symmetricKey, protectedKey, iv, in, out;
- crypter_t *crypter;
-
- alg = encryption_algorithm_from_oid(enc_alg, &alg_key_size);
- crypter = lib->crypto->create_crypter(lib->crypto, alg,
- alg_key_size/BITS_PER_BYTE);
- if (crypter == NULL)
- {
- DBG1(DBG_LIB, "crypter for %N not available", encryption_algorithm_names, alg);
- return chunk_empty;
- }
-
- /* generate a true random symmetric encryption key and a pseudo-random iv */
- {
- rng_t *rng;
-
- rng = lib->crypto->create_rng(lib->crypto, RNG_TRUE);
- rng->allocate_bytes(rng, crypter->get_key_size(crypter), &symmetricKey);
- DBG4(DBG_LIB, "symmetric encryption key %B", &symmetricKey);
- rng->destroy(rng);
-
- rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
- rng->allocate_bytes(rng, crypter->get_iv_size(crypter), &iv);
- DBG4(DBG_LIB, "initialization vector: %B", &iv);
- rng->destroy(rng);
- }
-
- /* pad the data to a multiple of the block size */
- {
- size_t block_size = crypter->get_block_size(crypter);
- size_t padding = block_size - data.len % block_size;
-
- in.len = data.len + padding;
- in.ptr = malloc(in.len);
-
- DBG2(DBG_LIB, "padding %u bytes of data to multiple block size of %u bytes",
- data.len, in.len);
-
- /* copy data */
- memcpy(in.ptr, data.ptr, data.len);
- /* append padding */
- memset(in.ptr + data.len, padding, padding);
- }
- DBG3(DBG_LIB, "padded unencrypted data %B", &in);
-
- /* symmetric encryption of data object */
- crypter->set_key(crypter, symmetricKey);
- crypter->encrypt(crypter, in, iv, &out);
- crypter->destroy(crypter);
- chunk_clear(&in);
- DBG3(DBG_LIB, "encrypted data %B", &out);
-
- /* protect symmetric key by public key encryption */
- {
- public_key_t *key = cert->get_public_key(cert);
-
- if (key == NULL)
- {
- DBG1(DBG_LIB, "public key not found in encryption certificate");
- chunk_clear(&symmetricKey);
- chunk_free(&iv);
- chunk_free(&out);
- return chunk_empty;
- }
- key->encrypt(key, ENCRYPT_RSA_PKCS1, symmetricKey, &protectedKey);
- key->destroy(key);
- }
-
- /* build pkcs7 enveloped data object */
- {
-
- chunk_t contentEncryptionAlgorithm = asn1_wrap(ASN1_SEQUENCE, "mm"
- , asn1_build_known_oid(enc_alg)
- , asn1_simple_object(ASN1_OCTET_STRING, iv));
-
- chunk_t encryptedContentInfo = asn1_wrap(ASN1_SEQUENCE, "mmm"
- , asn1_build_known_oid(OID_PKCS7_DATA)
- , contentEncryptionAlgorithm
- , asn1_wrap(ASN1_CONTEXT_S_0, "m", out));
-
- chunk_t encryptedKey = asn1_wrap(ASN1_OCTET_STRING, "m"
- , protectedKey);
-
- chunk_t recipientInfo = asn1_wrap(ASN1_SEQUENCE, "cmmm"
- , ASN1_INTEGER_0
- , pkcs7_build_issuerAndSerialNumber(cert)
- , asn1_algorithmIdentifier(OID_RSA_ENCRYPTION)
- , encryptedKey);
-
- chunk_t cInfo;
- contentInfo_t envelopedData;
-
- envelopedData.type = OID_PKCS7_ENVELOPED_DATA;
- envelopedData.content = asn1_wrap(ASN1_SEQUENCE, "cmm"
- , ASN1_INTEGER_0
- , asn1_wrap(ASN1_SET, "m", recipientInfo)
- , encryptedContentInfo);
-
- cInfo = pkcs7_build_contentInfo(&envelopedData);
- DBG3(DBG_LIB, "envelopedData %B", &cInfo);
-
- chunk_free(&envelopedData.content);
- chunk_free(&iv);
- chunk_clear(&symmetricKey);
- return cInfo;
- }
-}
diff --git a/src/pluto/pkcs7.h b/src/pluto/pkcs7.h
deleted file mode 100644
index 1743ea9c4..000000000
--- a/src/pluto/pkcs7.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* Support of PKCS#7 data structures
- * Copyright (C) 2005 Jan Hutter, Martin Willi
- * Copyright (C) 2002-2009 Andreas Steffen
- *
- * Hochschule fuer Technik Rapperswil, Switzerland
- *
- * 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.
- */
-
-#ifndef _PKCS7_H
-#define _PKCS7_H
-
-#include <utils/linked_list.h>
-#include <crypto/crypters/crypter.h>
-#include <credentials/keys/private_key.h>
-#include <credentials/certificates/certificate.h>
-
-/* Access structure for a PKCS#7 ContentInfo object */
-
-typedef struct contentInfo contentInfo_t;
-
-struct contentInfo {
- int type;
- chunk_t content;
-};
-
-extern const contentInfo_t empty_contentInfo;
-
-extern bool pkcs7_parse_contentInfo(chunk_t blob, u_int level0,
- contentInfo_t *cInfo);
-extern bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data,
- linked_list_t *cert, chunk_t *attributes,
- certificate_t *cacert);
-extern bool pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data,
- chunk_t serialNumber, private_key_t *key);
-extern chunk_t pkcs7_contentType_attribute(void);
-extern chunk_t pkcs7_messageDigest_attribute(chunk_t content, int digest_alg);
-extern chunk_t pkcs7_build_issuerAndSerialNumber(certificate_t *cert);
-extern chunk_t pkcs7_build_signedData(chunk_t data, chunk_t attributes,
- certificate_t *cert, int digest_alg,
- private_key_t *key);
-extern chunk_t pkcs7_build_envelopedData(chunk_t data, certificate_t *cert,
- int enc_alg);
-
-#endif /* _PKCS7_H */
diff --git a/src/pluto/plugin_list.c b/src/pluto/plugin_list.c
deleted file mode 100644
index 499218904..000000000
--- a/src/pluto/plugin_list.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2011 Martin Willi, revosec AG
- * Copyright (C) 2011 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 <whack.h>
-#include <log.h>
-
-#include <library.h>
-#include <utils/linked_list.h>
-
-/**
- * List loaded plugin information
- */
-void plugin_list(void)
-{
- plugin_feature_t *features, *fp;
- enumerator_t *enumerator;
- linked_list_t *list;
- plugin_t *plugin;
- int count, i;
- bool loaded;
- char *str;
-
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, "List of loaded Plugins:");
- whack_log(RC_COMMENT, " ");
-
- enumerator = lib->plugins->create_plugin_enumerator(lib->plugins);
- while (enumerator->enumerate(enumerator, &plugin, &list))
- {
- whack_log(RC_COMMENT, "%s:", plugin->get_name(plugin));
- if (plugin->get_features)
- {
- count = plugin->get_features(plugin, &features);
- for (i = 0; i < count; i++)
- {
- str = plugin_feature_get_string(&features[i]);
- switch (features[i].kind)
- {
- case FEATURE_PROVIDE:
- fp = &features[i];
- loaded = list->find_first(list, NULL,
- (void**)&fp) == SUCCESS;
- whack_log(RC_COMMENT, " %s%s",
- str, loaded ? "" : " (not loaded)");
- break;
- case FEATURE_DEPENDS:
- whack_log(RC_COMMENT, " %s", str);
- break;
- case FEATURE_SDEPEND:
- whack_log(RC_COMMENT, " %s(soft)", str);
- break;
- default:
- break;
- }
- free(str);
- }
- }
- }
- enumerator->destroy(enumerator);
-}
diff --git a/src/pluto/plugin_list.h b/src/pluto/plugin_list.h
deleted file mode 100644
index 62e4a167d..000000000
--- a/src/pluto/plugin_list.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* Generates a list of all loaded plugins and their dependencies
- * Copyright (C) 2011 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.
- */
-
-#ifndef _PLUGIN_LIST_H
-#define _PLUGIN_LIST_H
-
-extern void plugin_list(void);
-
-#endif /* _PLUGIN_LIST_H */
diff --git a/src/pluto/plugins/xauth/Makefile.am b/src/pluto/plugins/xauth/Makefile.am
deleted file mode 100644
index 354325b35..000000000
--- a/src/pluto/plugins/xauth/Makefile.am
+++ /dev/null
@@ -1,15 +0,0 @@
-
-INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
- -I$(top_srcdir)/src/libfreeswan -I$(top_srcdir)/src/whack \
- -I$(top_srcdir)/src/pluto
-
-AM_CFLAGS = -rdynamic
-
-plugin_LTLIBRARIES = libstrongswan-xauth.la
-
-libstrongswan_xauth_la_SOURCES = \
- xauth_plugin.h xauth_plugin.c \
- xauth_default_provider.c xauth_default_provider.h \
- xauth_default_verifier.c xauth_default_verifier.h
-
-libstrongswan_xauth_la_LDFLAGS = -module -avoid-version
diff --git a/src/pluto/plugins/xauth/xauth_default_provider.c b/src/pluto/plugins/xauth/xauth_default_provider.c
deleted file mode 100644
index 77c5facc4..000000000
--- a/src/pluto/plugins/xauth/xauth_default_provider.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2010 Andreas Steffen
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <keys.h>
-
-#include "xauth_default_provider.h"
-
-typedef struct private_xauth_default_provider_t private_xauth_default_provider_t;
-
-/**
- * private data of xauth_default_provider
- */
-struct private_xauth_default_provider_t {
-
- /**
- * public functions
- */
- xauth_provider_t public;
-};
-
-METHOD(xauth_provider_t, get_secret, bool,
- private_xauth_default_provider_t *this, connection_t *c, chunk_t *secret)
-{
- identification_t *user, *server;
-
- server = c->spd.that.id;
- user = (c->xauth_identity) ? c->xauth_identity : c->spd.this.id;
-
- return get_xauth_secret(user, server, secret);
-}
-
-METHOD(xauth_provider_t, destroy, void,
- private_xauth_default_provider_t *this)
-{
- free(this);
-}
-
-/*
- * Described in header.
- */
-xauth_provider_t *xauth_default_provider_create()
-{
- private_xauth_default_provider_t *this;
-
- INIT(this,
- .public = {
- .get_secret = _get_secret,
- .destroy = _destroy,
- }
- );
-
- return &this->public;
-}
-
diff --git a/src/pluto/plugins/xauth/xauth_default_verifier.c b/src/pluto/plugins/xauth/xauth_default_verifier.c
deleted file mode 100644
index ca2e36aa0..000000000
--- a/src/pluto/plugins/xauth/xauth_default_verifier.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2010 Andreas Steffen
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <keys.h>
-
-#include "xauth_default_verifier.h"
-
-typedef struct private_xauth_default_verifier_t private_xauth_default_verifier_t;
-
-/**
- * private data of xauth_default_verifier
- */
-struct private_xauth_default_verifier_t {
-
- /**
- * public functions
- */
- xauth_verifier_t public;
-};
-
-METHOD(xauth_verifier_t, verify_secret, bool,
- private_xauth_default_verifier_t *this, connection_t *c, chunk_t secret)
-{
- identification_t *user, *server;
- chunk_t xauth_secret;
- bool success = FALSE;
-
- server = c->spd.this.id;
- user = (c->xauth_identity) ? c->xauth_identity : c->spd.that.id;
-
- if (get_xauth_secret(user, server, &xauth_secret))
- {
- success = chunk_equals(secret, xauth_secret);
-
- if (!success && secret.len && secret.ptr[secret.len - 1] == 0)
- { /* fix for null-terminated passwords (e.g. from Android 4) */
- secret.len--;
- success = chunk_equals(secret, xauth_secret);
- }
-
- chunk_clear(&xauth_secret);
- }
- return success;
-}
-
-METHOD(xauth_verifier_t, destroy, void,
- private_xauth_default_verifier_t *this)
-{
- free(this);
-}
-
-
-/*
- * Described in header.
- */
-xauth_verifier_t *xauth_default_verifier_create()
-{
- private_xauth_default_verifier_t *this;
-
- INIT(this,
- .public = {
- .verify_secret = _verify_secret,
- .destroy = _destroy,
- }
- );
-
- return &this->public;
-}
-
diff --git a/src/pluto/pluto.8 b/src/pluto/pluto.8
deleted file mode 100644
index ed6f78050..000000000
--- a/src/pluto/pluto.8
+++ /dev/null
@@ -1,1594 +0,0 @@
-.TH IPSEC_PLUTO 8 "28 March 1999"
-.SH NAME
-pluto \- IPsec IKE keying daemon and control interface
-.PP
-whack \- control interface for IKE keying daemon
-.SH SYNOPSIS
-.na
-.nh
-.HP
-.ft B
-ipsec pluto
-[\-\-help]
-[\-\-version]
-[\-\-optionsfrom\ \c
-\fIfilename\fP]
-[\-\-nofork]
-[\-\-stderrlog]
-[\-\-uniqueids]
-[\fB\-\-interface\fP \fIinterfacename\fP]
-[\-\-ikeport\ \c
-\fIportnumber\fP]
-[\-\-ctlbase\ \c
-\fIpath\fP]
-[\-\-secretsfile\ \c
-\fIsecrets\(hyfile\fP]
-[\-\-adns \fIpathname\fP]
-[\-\-lwdnsq \fIpathname\fP]
-[\-\-perpeerlog]
-[\-\-perpeerlogbase\ \c
-\fIdirname\fP]
-[\-\-debug\(hynone]
-[\-\-debug\(hyall]
-[\-\-debug\(hyraw]
-[\-\-debug\(hycrypt]
-[\-\-debug\(hyparsing]
-[\-\-debug\(hyemitting]
-[\-\-debug\(hycontrol]
-[\-\-debug\(hylifecycle]
-[\-\-debug\(hykernel]
-[\-\-debug\(hydns]
-[\-\-debug\(hyoppo]
-[\-\-debug\(hyprivate]
-.HP
-.ft B
-ipsec whack
-[\-\-help]
-[\-\-version]
-.HP
-.ft B
-ipsec whack
-\-\-name\ \c
-\fIconnection-name\fP
-.br
-[\-\-id\ \c
-\fIid\fP] \c
-[\-\-host\ \c
-\fIip\(hyaddress\fP]
-[\-\-ikeport\ \c
-\fIport\(hynumber\fP]
-[\-\-nexthop\ \c
-\fIip\(hyaddress\fP]
-[\-\-client\ \c
-\fIsubnet\fP]
-[\-\-dnskeyondemand]
-[\-\-updown\ \c
-\fIupdown\fP]
-.br
-\-\-to
-.br
-[\-\-id\ \c
-\fIid\fP]
-[\-\-host\ \c
-\fIip\(hyaddress\fP]
-[\-\-ikeport\ \c
-\fIport\(hynumber\fP]
-[\-\-nexthop\ \c
-\fIip\(hyaddress\fP]
-[\-\-client\ \c
-\fIsubnet\fP]
-[\-\-dnskeyondemand]
-[\-\-updown\ \c
-\fIupdown\fP]
-.br
-[\-\-psk]
-[\-\-rsasig]
-[\-\-encrypt]
-[\-\-authenticate]
-[\-\-compress]
-[\-\-tunnel]
-[\-\-pfs]
-[\-\-disablearrivalcheck]
-[\-\-ipv4]
-[\-\-ipv6]
-[\-\-tunnelipv4]
-[\-\-tunnelipv6]
-[\-\-ikelifetime\ \c
-\fIseconds\fP]
-[\-\-ipseclifetime\ \c
-\fIseconds\fP]
-[\-\-rekeymargin\ \c
-\fIseconds\fP]
-[\-\-rekeyfuzz\ \c
-\fIpercentage\fP]
-[\-\-keyingtries\ \c
-\fIcount\fP]
-[\-\-dontrekey]
-[\-\-delete]
-[\-\-ctlbase\ \c
-\fIpath\fP]
-[\-\-optionsfrom\ \c
-\fIfilename\fP]
-[\-\-label\ \c
-\fIstring\fP]
-.HP
-.ft B
-ipsec whack
-\-\-keyid\ \c
-\fIid\fP
-[\-\-addkey]
-[\-\-pubkeyrsa\ \c
-\fIkey\fP]
-[\-\-ctlbase\ \c
-\fIpath\fP]
-[\-\-optionsfrom\ \c
-\fIfilename\fP]
-[\-\-label\ \c
-\fIstring\fP]
-.HP
-.ft B
-ipsec whack
-\-\-myid\ \c
-\fIid\fP
-.HP
-.ft B
-ipsec whack
-\-\-listen|\-\-unlisten
-[\-\-ctlbase\ \c
-\fIpath\fP]
-[\-\-optionsfrom\ \c
-\fIfilename\fP]
-[\-\-label\ \c
-\fIstring\fP]
-.HP
-.ft B
-ipsec whack
-\-\-route|\-\-unroute
-\-\-name\ \c
-\fIconnection-name\fP
-[\-\-ctlbase\ \c
-\fIpath\fP]
-[\-\-optionsfrom\ \c
-\fIfilename\fP]
-[\-\-label\ \c
-\fIstring\fP]
-.HP
-.ft B
-ipsec whack
-\-\-initiate|\-\-terminate
-\-\-name\ \c
-\fIconnection-name\fP
-[\-\-asynchronous]
-[\-\-ctlbase\ \c
-\fIpath\fP]
-[\-\-optionsfrom\ \c
-\fIfilename\fP]
-[\-\-label\ \c
-\fIstring\fP]
-.HP
-.ft B
-ipsec whack
-[\-\-tunnelipv4]
-[\-\-tunnelipv6]
-\-\-oppohere \fIip\(hyaddress\fP
-\-\-oppothere \fIip\(hyaddress\fP
-.HP
-.ft B
-ipsec whack
-\-\-delete
-\-\-name\ \c
-\fIconnection-name\fP
-[\-\-ctlbase\ \c
-\fIpath\fP]
-[\-\-optionsfrom\ \c
-\fIfilename\fP]
-[\-\-label\ \c
-\fIstring\fP]
-.HP
-.ft B
-ipsec whack
-\-\-deletestate\ \c
-\fIstate-number\fP
-[\-\-ctlbase\ \c
-\fIpath\fP]
-[\-\-optionsfrom\ \c
-\fIfilename\fP]
-[\-\-label\ \c
-\fIstring\fP]
-.HP
-.ft B
-ipsec whack
-[\-\-name\ \c
-\fIconnection-name\fP]
-[\-\-debug\(hynone]
-[\-\-debug\(hyall]
-[\-\-debug\(hyraw]
-[\-\-debug\(hycrypt]
-[\-\-debug\(hyparsing]
-[\-\-debug\(hyemitting]
-[\-\-debug\(hycontrol]
-[\-\-debug\(hylifecycle]
-[\-\-debug\(hykernel]
-[\-\-debug\(hydns]
-[\-\-debug\(hyoppo]
-[\-\-debug\(hyprivate]
-[\-\-ctlbase\ \c
-\fIpath\fP]
-[\-\-optionsfrom\ \c
-\fIfilename\fP]
-[\-\-label\ \c
-\fIstring\fP]
-.HP
-.ft B
-ipsec whack
-\-\-status
-[\-\-ctlbase\ \c
-\fIpath\fP]
-[\-\-optionsfrom\ \c
-\fIfilename\fP]
-[\-\-label\ \c
-\fIstring\fP]
-.HP
-.ft B
-ipsec whack
-\-\-shutdown
-[\-\-ctlbase\ \c
-\fIpath\fP]
-[\-\-optionsfrom\ \c
-\fIfilename\fP]
-[\-\-label\ \c
-\fIstring\fP]
-.ft R
-.hy
-.ad
-.SH DESCRIPTION
-.BR pluto
-is an IKE (``IPsec Key Exchange'') daemon.
-.BR whack
-is an auxiliary program to allow requests to be made to a running
-.BR pluto .
-.LP
-.BR pluto
-is used to automatically build shared ``security associations'' on a
-system that has IPsec, the secure IP protocol.
-In other words,
-.BR pluto
-can eliminate much of the work of manual keying.
-The actual
-secure transmission of packets is the responsibility of the Linux kernel.
-\fIipsec_auto\fP(8) provides a more convenient interface to
-\fBpluto\fP and \fBwhack\fP.
-.SS IKE's Job
-.LP
-A \fISecurity Association\fP (\fISA\fP) is an agreement between two network nodes on
-how to process certain traffic between them. This processing involves
-encapsulation, authentication, encryption, or compression.
-.LP
-IKE can be deployed on a network node to negotiate Security
-Associations for that node. These IKE implementations can only
-negotiate with other IKE implementations, so IKE must be on each node
-that is to be an endpoint of an IKE-negotiated Security Association.
-No other nodes need to be running IKE.
-.LP
-An IKE instance (i.e. an IKE implementation on a particular network
-node) communicates with another IKE instance using UDP IP packets, so
-there must be a route between the nodes in each direction.
-.LP
-The negotiation of Security Associations requires a number of choices
-that involve tradeoffs between security, convenience, trust, and
-efficiency. These are policy issues and are normally specified to the
-IKE instance by the system administrator.
-.LP
-IKE deals with two kinds of Security Associations. The first part of
-a negotiation between IKE instances is to build an ISAKMP SA. An
-ISAKMP SA is used to protect communication between the two IKEs.
-IPsec SAs can then be built by the IKEs \- these are used to carry
-protected IP traffic between the systems.
-.LP
-The negotiation of the ISAKMP SA is known as Phase 1. In theory,
-Phase 1 can be accomplished by a couple of different exchange types,
-but we only implement one called Main Mode (we don't implement
-Aggressive Mode).
-.LP
-Any negotiation under the protection of an ISAKMP SA, including the
-negotiation of IPsec SAs, is part of Phase 2. The exchange type
-that we use to negotiate an IPsec SA is called Quick Mode.
-.LP
-IKE instances must be able to authenticate each other as part of their
-negotiation of an ISAKMP SA. This can be done by several mechanisms
-described in the draft standards.
-.LP
-IKE negotiation can be initiated by any instance with any other. If
-both can find an agreeable set of characteristics for a Security
-Association, and both recognize each others authenticity, they can set
-up a Security Association. The standards do not specify what causes
-an IKE instance to initiate a negotiation.
-.LP
-In summary, an IKE instance is prepared to automate the management of
-Security Associations in an IPsec environment, but a number of issues
-are considered policy and are left in the system administrator's hands.
-.SS Pluto
-.LP
-\fBpluto\fP is an implementation of IKE. It runs as a daemon on a network
-node. Currently, this network node must be a Linux 2.6 system running the
-native \fBNETKEY\fP IPsec stack.
-.LP
-\fBpluto\fP only implements a subset of IKE. This is enough for it to
-interoperate with other instances of \fBpluto\fP, and many other IKE
-implementations. We are working on implementing more of IKE.
-.LP
-The policy for acceptable characteristics for Security Associations is
-mostly hardwired into the code of \fBpluto\fP (spdb.c). Eventually
-this will be moved into a security policy database with reasonable
-expressive power and more convenience.
-.LP
-\fBpluto\fP uses shared secrets or RSA signatures to authenticate
-peers with whom it is negotiating.
-.LP
-\fBpluto\fP initiates negotiation of a Security Association when it is
-manually prodded: the program \fBwhack\fP is run to trigger this.
-It will also initiate a negotiation when the Linux kernel traps an outbound
-packet for Opportunistic Encryption.
-.LP
-\fBpluto\fP implements ISAKMP SAs itself. After it has negotiated the
-characteristics of an IPsec SA, it directs the Linux kernel to implement it.
-It also invokes a script to adjust any firewall and issue \fIroute\fP(8)
-commands.
-.LP
-When \fBpluto\fP shuts down, it closes all Security Associations.
-.SS Before Running Pluto
-.LP
-\fBpluto\fP runs as a daemon with userid root. Before running it, a few
-things must be set up.
-.LP
-\fBpluto\fP requires a Linux 2.6 kernel with the modules for the native IPsec
-stack enabled.
-.LP
-\fBpluto\fP supports multiple public networks (that is, networks
-that are considered insecure and thus need to have their traffic
-encrypted or authenticated). It discovers the
-public interfaces to use by looking at all interfaces that are
-configured (the \fB\-\-interface\fP option can be used to limit
-the interfaces considered).
-It does this only when \fBwhack\fP tells it to \-\-listen,
-so the interfaces must be configured by then.
-\fIifconfig\fP(8) with the \fB\-a\fP flag will show
-the name and status of each network interface.
-.LP
-\fBpluto\fP requires a database of preshared secrets and RSA private keys.
-This is described in the
-.IR ipsec.secrets (5).
-\fBpluto\fP is told of RSA public keys via \fBwhack\fP commands.
-If the connection is Opportunistic, and no RSA public key is known,
-\fBpluto\fP will attempt to fetch RSA keys using the Domain Name System.
-.SS ipsec.secrets file
-.LP
-A \fBpluto\fP daemon and another IKE daemon (for example, another instance
-of \fBpluto\fP) must convince each other that they are who they are supposed
-to be before any negotiation can succeed. This authentication is
-accomplished by using either secrets that have been shared beforehand
-(manually) or by using RSA signatures. There are other techniques,
-but they have not been implemented in \fBpluto\fP.
-.LP
-The file \fI/etc/ipsec.secrets\fP is used to keep preshared secret keys
-and RSA private keys for
-authentication with other IKE daemons. For debugging, there is an
-argument to the \fBpluto\fP command to use a different file.
-This file is described in
-.IR ipsec.secrets (5).
-.SS Running Pluto
-.LP
-To fire up the daemon, just type \fBpluto\fP (be sure to be running as
-the superuser).
-The default IKE port number is 500, the UDP port assigned by IANA for IKE Daemons.
-\fBpluto\fP must be run by the superuser to be able to use the UDP 500 port.
-.LP
-\fBpluto\fP attempts to create a lockfile with the name
-\fI/var/run/pluto.pid\fP. If the lockfile cannot be created,
-\fBpluto\fP exits \- this prevents multiple \fBpluto\fPs from
-competing Any ``leftover'' lockfile must be removed before
-\fBpluto\fP will run. \fBpluto\fP writes its pid into this file so
-that scripts can find it. This lock will not function properly if it
-is on an NFS volume (but sharing locks on multiple machines doesn't
-make sense anyway).
-.LP
-\fBpluto\fP then forks and the parent exits. This is the conventional
-``daemon fork''. It can make debugging awkward, so there is an option
-to suppress this fork.
-.LP
-All logging, including diagnostics, is sent to
-.IR syslog (3)
-with facility=authpriv;
-it decides where to put these messages (possibly in /var/log/secure).
-Since this too can make debugging awkward, there is an option to
-steer logging to stderr.
-.LP
-If the \fB\-\-perpeerlog\fP option is given, then pluto will open
-a log file per connection. By default, this is in /var/log/pluto/peer,
-in a subdirectory formed by turning all dot (.) [IPv4} or colon (:)
-[IPv6] into slashes (/).
-.LP
-The base directory can be changed with the \fB\-\-perpeerlogbase\fP.
-.LP
-Once \fBpluto\fP is started, it waits for requests from \fBwhack\fP.
-.SS Pluto's Internal State
-.LP
-To understand how to use \fBpluto\fP, it is helpful to understand a little
-about its internal state. Furthermore, the terminology is needed to decipher
-some of the diagnostic messages.
-.LP
-The \fI(potential) connection\fP database describes attributes of a
-connection. These include the IP addresses of the hosts and client
-subnets and the security characteristics desired. \fBpluto\fP
-requires this information (simply called a connection) before it can
-respond to a request to build an SA. Each connection is given a name
-when it is created, and all references are made using this name.
-.LP
-During the IKE exchange to build an SA, the information about the
-negotiation is represented in a \fIstate object\fP. Each state object
-reflects how far the negotiation has reached. Once the negotiation is
-complete and the SA established, the state object remains to represent
-the SA. When the SA is terminated, the state object is discarded.
-Each State object is given a serial number and this is used to refer
-to the state objects in logged messages.
-.LP
-Each state object corresponds to a connection and can be thought of
-as an instantiation of that connection.
-At any particular time, there may be any number of state objects
-corresponding to a particular connection.
-Often there is one representing an ISAKMP SA and another representing
-an IPsec SA.
-.LP
-Each connection may be routed, and must be while it has an IPsec SA.
-The connection specifies the characteristics of the route: the
-interface on this machine, the ``gateway'' (the nexthop),
-and the peer's client subnet. Two
-connections may not be simultaneously routed if they are for the same
-peer's client subnet but use different interfaces or gateways
-(\fBpluto\fP's logic does not reflect any advanced routing capabilities).
-.LP
-Each eroute is associated with the state object for an IPsec SA
-because it has the particular characteristics of the SA.
-Two eroutes conflict if they specify the identical local
-and remote clients (unlike for routes, the local clients are
-taken into account).
-.LP
-When \fBpluto\fP needs to install a route for a connection,
-it must make sure that no conflicting route is in use. If another
-connection has a conflicting route, that route will be taken down, as long
-as there is no IPsec SA instantiating that connection.
-If there is such an IPsec SA, the attempt to install a route will fail.
-.LP
-There is an exception. If \fBpluto\fP, as Responder, needs to install
-a route to a fixed client subnet for a connection, and there is
-already a conflicting route, then the SAs using the route are deleted
-to make room for the new SAs. The rationale is that the new
-connection is probably more current. The need for this usually is a
-product of Road Warrior connections (these are explained later; they
-cannot be used to initiate).
-.LP
-When \fBpluto\fP needs to install an eroute for an IPsec SA (for a
-state object), first the state object's connection must be routed (if
-this cannot be done, the eroute and SA will not be installed).
-If a conflicting eroute is already in place for another connection,
-the eroute and SA will not be installed (but note that the routing
-exception mentioned above may have already deleted potentially conflicting SAs).
-If another IPsec
-SA for the same connection already has an eroute, all its outgoing traffic
-is taken over by the new eroute. The incoming traffic will still be
-processed. This characteristic is exploited during rekeying.
-.LP
-Some of these routing characteristics are specific to \fBKLIPS\fP, the FreeS/WAN
-implementation of IPsec and are not relevant when running pluto on the native
-Linux 2.6 IPsec stack.
-.SS Using Whack
-.LP
-\fBwhack\fP is used to command a running \fBpluto\fP.
-\fBwhack\fP uses a UNIX domain socket to speak to \fBpluto\fP
-(by default, \fI/var/pluto.ctl\fP).
-.LP
-\fBwhack\fP has an intricate argument syntax.
-This syntax allows many different functions to be specified.
-The help form shows the usage or version information.
-The connection form gives \fBpluto\fP a description of a potential connection.
-The public key form informs \fBpluto\fP of the RSA public key for a potential peer.
-The delete form deletes a connection description and all SAs corresponding
-to it.
-The listen form tells \fBpluto\fP to start or stop listening on the public interfaces
-for IKE requests from peers.
-The route form tells \fBpluto\fP to set up routing for a connection;
-the unroute form undoes this.
-The initiate form tells \fBpluto\fP to negotiate an SA corresponding to a connection.
-The terminate form tells \fBpluto\fP to remove all SAs corresponding to a connection,
-including those being negotiated.
-The status form displays the \fBpluto\fP's internal state.
-The debug form tells \fBpluto\fP to change the selection of debugging output
-``on the fly''. The shutdown form tells
-\fBpluto\fP to shut down, deleting all SAs.
-.LP
-Most options are specific to one of the forms, and will be described
-with that form. There are three options that apply to all forms.
-.TP
-\fB\-\-ctlbase\fP\ \fIpath\fP
-\fIpath\fP.ctl is used as the UNIX domain socket for talking
-to \fBpluto\fP.
-This option facilitates debugging.
-.TP
-\fB\-\-optionsfrom\fP\ \fIfilename\fP
-adds the contents of the file to the argument list.
-.TP
-\fB\-\-label\fP\ \fIstring\fP
-adds the string to all error messages generated by \fBwhack\fP.
-.LP
-The help form of \fBwhack\fP is self-explanatory.
-.TP
-\fB\-\-help\fP
-display the usage message.
-.TP
-\fB\-\-version\fP
-display the version of \fBwhack\fP.
-.LP
-The connection form describes a potential connection to \fBpluto\fP.
-\fBpluto\fP needs to know what connections can and should be negotiated.
-When \fBpluto\fP is the initiator, it needs to know what to propose.
-When \fBpluto\fP is the responder, it needs to know enough to decide whether
-is is willing to set up the proposed connection.
-.LP
-The description of a potential connection can specify a large number
-of details. Each connection has a unique name. This name will appear
-in a updown shell command, so it should not contain punctuation
-that would make the command ill-formed.
-.TP
-\fB\-\-name\fP\ \fIconnection-name\fP
-.LP
-The topology of
-a connection is symmetric, so to save space here is half a picture:
-
-\ \ \ client_subnet<\-\->host:ikeport<\-\->nexthop<\-\-\-
-
-A similar trick is used in the flags. The same flag names are used for
-both ends. Those before the \fB\-\-to\fP flag describe the left side
-and those afterwards describe the right side. When \fBpluto\fP attempts
-to use the connection, it decides whether it is the left side or the right
-side of the connection, based on the IP numbers of its interfaces.
-.TP
-\fB\-\-id\fP\ \fIid\fP
-the identity of the end. Currently, this can be an IP address (specified
-as dotted quad or as a Fully Qualified Domain Name, which will be resolved
-immediately) or as a Fully Qualified Domain Name itself (prefixed by ``@''
-to signify that it should not be resolved), or as user@FQDN, or as the
-magic value \fB%myid\fP.
-\fBPluto\fP only authenticates the identity, and does not use it for
-addressing, so, for example, an IP address need not be the one to which
-packets are to be sent. If the option is absent, the
-identity defaults to the IP address specified by \fB\-\-host\fP.
-\fB%myid\fP allows the identity to be separately specified (by the \fBpluto\fP or \fBwhack\fP option \fB\-\-myid\fP
-or by the \fBipsec.conf\fP(5) \fBconfig setup\fP parameter \fPmyid\fP).
-Otherwise, \fBpluto\fP tries to guess what \fB%myid\fP should stand for:
-the IP address of \fB%defaultroute\fP, if it is supported by a suitable TXT record in the reverse domain for that IP address,
-or the system's hostname, if it is supported by a suitable TXT record in its forward domain.
-.\" The identity is transmitted in the IKE protocol, and is what is authenticated.
-.TP
-\fB\-\-host\fP\ \fIip\(hyaddress\fP
-.TP
-\fB\-\-host\fP\ \fB%any\fP
-.TP
-\fB\-\-host\fP\ \fB%opportunistic\fP
-the IP address of the end (generally the public interface).
-If \fBpluto\fP is to act as a responder
-for IKE negotiations initiated from unknown IP addresses (the
-``Road Warrior'' case), the
-IP address should be specified as \fB%any\fP (currently,
-the obsolete notation \fB0.0.0.0\fP is also accepted for this).
-If \fBpluto\fP is to opportunistically initiate the connection,
-use \fB%opportunistic\fP
-.TP
-\fB\-\-ikeport\fP\ \fIport\(hynumber\fP
-the UDP port that IKE listens to on that host. The default is 500.
-(\fBpluto\fP on this machine uses the port specified by its own command
-line argument, so this only affects where \fBpluto\fP sends messages.)
-.TP
-\fB\-\-nexthop\fP\ \fIip\(hyaddress\fP
-where to route packets for the peer's client (presumably for the peer too,
-but it will not be used for this).
-When \fBpluto\fP installs an IPsec SA, it issues a route command.
-It uses the nexthop as the gateway.
-The default is the peer's IP address (this can be explicitly written as
-\fB%direct\fP; the obsolete notation \fB0.0.0.0\fP is accepted).
-This option is necessary if \fBpluto\fP's host's interface used for sending
-packets to the peer is neither point-to-point nor directly connected to the
-peer.
-.TP
-\fB\-\-client\fP\ \fIsubnet\fP
-the subnet for which the IPsec traffic will be destined. If not specified,
-the host will be the client.
-The subnet can be specified in any of the forms supported by \fIipsec_atosubnet\fP(3).
-The general form is \fIaddress\fP/\fImask\fP. The \fIaddress\fP can be either
-a domain name or four decimal numbers (specifying octets) separated by dots.
-The most convenient form of the \fImask\fP is a decimal integer, specifying
-the number of leading one bits in the mask. So, for example, 10.0.0.0/8
-would specify the class A network ``Net 10''.
-.TP
-\fB\-\-dnskeyondemand]\fP
-specifies that when an RSA public key is needed to authenticate this
-host, and it isn't already known, fetch it from DNS.
-.TP
-\fB\-\-updown\fP\ \fIupdown\fP
-specifies an external shell command to be run whenever \fBpluto\fP
-brings up or down a connection.
-The script is used to build a shell command, so it may contain positional
-parameters, but ought not to have punctuation that would cause the
-resulting command to be ill-formed.
-The default is \fIipsec _updown\fP.
-.TP
-\fB\-\-to\fP
-separates the specification of the left and right ends of the connection.
-.LP
-The potential connection description also specifies characteristics of
-rekeying and security.
-.TP
-\fB\-\-psk\fP
-Propose and allow preshared secret authentication for IKE peers. This authentication
-requires that each side use the same secret. May be combined with \fB\-\-rsasig\fP;
-at least one must be specified.
-.TP
-\fB\-\-rsasig\fP
-Propose and allow RSA signatures for authentication of IKE peers. This authentication
-requires that each side have have a private key of its own and know the
-public key of its peer. May be combined with \fB\-\-psk\fP;
-at least one must be specified.
-.TP
-\fB\-\-encrypt\fP
-All proposed or accepted IPsec SAs will include non-null ESP.
-The actual choices of transforms are wired into \fBpluto\fP.
-.TP
-\fB\-\-authenticate\fP
-All proposed IPsec SAs will include AH.
-All accepted IPsec SAs will include AH or ESP with authentication.
-The actual choices of transforms are wired into \fBpluto\fP.
-Note that this has nothing to do with IKE authentication.
-.TP
-\fB\-\-compress\fP
-All proposed IPsec SAs will include IPCOMP (compression).
-This will be ignored if the kernel is not configured with IPCOMP support.
-.TP
-\fB\-\-tunnel\fP
-the IPsec SA should use tunneling. Implicit if the SA is for clients.
-Must only be used with \fB\-\-authenticate\fP or \fB\-\-encrypt\fP.
-.TP
-\fB\-\-ipv4\fP
-The host addresses will be interpreted as IPv4 addresses. This is the
-default. Note that for a connection, all host addresses must be of
-the same Address Family (IPv4 and IPv6 use different Address Families).
-.TP
-\fB\-\-ipv6\fP
-The host addresses (including nexthop) will be interpreted as IPv6 addresses.
-Note that for a connection, all host addresses must be of
-the same Address Family (IPv4 and IPv6 use different Address Families).
-.TP
-\fB\-\-tunnelipv4\fP
-The client addresses will be interpreted as IPv4 addresses. The default is
-to match what the host will be. This does not imply \fB\-\-tunnel\fP so the
-flag can be safely used when no tunnel is actually specified.
-Note that for a connection, all tunnel addresses must be of the same
-Address Family.
-.TP
-\fB\-\-tunnelipv6\fP
-The client addresses will be interpreted as IPv6 addresses. The default is
-to match what the host will be. This does not imply \fB\-\-tunnel\fP so the
-flag can be safely used when no tunnel is actually specified.
-Note that for a connection, all tunnel addresses must be of the same
-Address Family.
-.TP
-\fB\-\-pfs\fP
-There should be Perfect Forward Secrecy \- new keying material will
-be generated for each IPsec SA rather than being derived from the ISAKMP
-SA keying material.
-Since the group to be used cannot be negotiated (a dubious feature of the
-standard), \fBpluto\fP will propose the same group that was used during Phase 1.
-We don't implement a stronger form of PFS which would require that the
-ISAKMP SA be deleted after the IPSEC SA is negotiated.
-.TP
-\fB\-\-disablearrivalcheck\fP
-If the connection is a tunnel, allow packets arriving through the tunnel
-to have any source and destination addresses.
-.LP
-If none of the \fB\-\-encrypt\fP, \fB\-\-authenticate\fP, \fB\-\-compress\fP,
-or \fB\-\-pfs\fP flags is given, the initiating the connection will
-only build an ISAKMP SA. For such a connection, client subnets have
-no meaning and must not be specified.
-.LP
-More work is needed to allow for flexible policies. Currently
-policy is hardwired in the source file spdb.c. The ISAKMP SAs may use
-Oakley groups MODP1024 and MODP1536; 3DES encryption; SHA1-96
-and MD5-96 authentication. The IPsec SAs may use 3DES and
-MD5-96 or SHA1-96 for ESP, or just MD5-96 or SHA1-96 for AH.
-IPCOMP Compression is always Deflate.
-.TP
-\fB\-\-ikelifetime\fP\ \fIseconds\fP
-how long \fBpluto\fP will propose that an ISAKMP SA be allowed to live.
-The default is 10800 (three hours) and the maximum is 86400 (one day).
-This option will not affect what is accepted.
-\fBpluto\fP will reject proposals that exceed the maximum.
-.TP
-\fB\-\-ipseclifetime\fP\ \fIseconds\fP
-how long \fBpluto\fP will propose that an IPsec SA be allowed to live.
-The default is 3600 (one hour) and the maximum is 86400 (one day).
-This option will not affect what is accepted.
-\fBpluto\fP will reject proposals that exceed the maximum.
-.TP
-\fB\-\-rekeymargin\fP\ \fIseconds\fP
-how long before an SA's expiration should \fBpluto\fP try to negotiate
-a replacement SA. This will only happen if \fBpluto\fP was the initiator.
-The default is 540 (nine minutes).
-.TP
-\fB\-\-rekeyfuzz\fP\ \fIpercentage\fP
-maximum size of random component to add to rekeymargin, expressed as
-a percentage of rekeymargin. \fBpluto\fP will select a delay uniformly
-distributed within this range. By default, the percentage will be 100.
-If greater determinism is desired, specify 0. It may be appropriate
-for the percentage to be much larger than 100.
-.TP
-\fB\-\-keyingtries\fP\ \fIcount\fP
-how many times \fBpluto\fP should try to negotiate an SA,
-either for the first time or for rekeying.
-A value of 0 is interpreted as a very large number: never give up.
-The default is three.
-.TP
-\fB\-\-dontrekey\fP
-A misnomer.
-Only rekey a connection if we were the Initiator and there was recent
-traffic on the existing connection.
-This applies to Phase 1 and Phase 2.
-This is currently the only automatic way for a connection to terminate.
-It may be useful with Road Warrior or Opportunistic connections.
-.br
-Since SA lifetime negotiation is take-it-or-leave it, a Responder
-normally uses the shorter of the negotiated or the configured lifetime.
-This only works because if the lifetime is shorter than negotiated,
-the Responder will rekey in time so that everything works.
-This interacts badly with \fB\-\-dontrekey\fP. In this case,
-the Responder will end up rekeying to rectify a shortfall in an IPsec SA
-lifetime; for an ISAKMP SA, the Responder will accept the negotiated
-lifetime.
-.TP
-\fB\-\-delete\fP
-when used in the connection form, it causes any previous connection
-with this name to be deleted before this one is added. Unlike a
-normal delete, no diagnostic is produced if there was no previous
-connection to delete. Any routing in place for the connection is undone.
-.LP
-The delete form deletes a named connection description and any
-SAs established or negotiations initiated using this connection.
-Any routing in place for the connection is undone.
-.TP
-\fB\-\-delete\fP
-.TP
-\fB\-\-name\fP\ \fIconnection-name\fP
-.LP
-The deletestate form deletes the state object with the specified serial number.
-This is useful for selectively deleting instances of connections.
-.TP
-\fB\-\-deletestate\fP\ \fIstate-number\fP
-.LP
-The route form of the \fBwhack\fP command tells \fBpluto\fP to set up
-routing for a connection.
-Although like a traditional route, it uses an ipsec device as a
-virtual interface.
-Once routing is set up, no packets will be
-sent ``in the clear'' to the peer's client specified in the connection.
-A TRAP shunt eroute will be installed; if outbound traffic is caught,
-Pluto will initiate the connection.
-An explicit \fBwhack\fP route is not always needed: if it hasn't been
-done when an IPsec SA is being installed, one will be automatically attempted.
-.LP
-When a routing is attempted for a connection, there must not already
-be a routing for a different connection with the same subnet but different
-interface or destination, or if
-there is, it must not be being used by an IPsec SA. Otherwise the
-attempt will fail.
-.TP
-\fB\-\-route\fP
-.TP
-\fB\-\-name\fP\ \fIconnection-name\fP
-.LP
-The unroute form of the \fBwhack\fP command tells \fBpluto\fP to undo
-a routing. \fBpluto\fP will refuse if an IPsec SA is using the connection.
-If another connection is sharing the same routing, it will be left in place.
-Without a routing, packets will be sent without encryption or authentication.
-.TP
-\fB\-\-unroute\fP
-.TP
-\fB\-\-name\fP\ \fIconnection-name\fP
-.LP
-The initiate form tells \fBpluto\fP to initiate a negotiation with another
-\fBpluto\fP (or other IKE daemon) according to the named connection.
-Initiation requires a route that \fB\-\-route\fP would provide;
-if none is in place at the time an IPsec SA is being installed,
-\fBpluto\fP attempts to set one up.
-.TP
-\fB\-\-initiate\fP
-.TP
-\fB\-\-name\fP\ \fIconnection-name\fP
-.TP
-\fB\-\-asynchronous
-.LP
-The initiate form of the \fBwhack\fP command will relay back from
-\fBpluto\fP status information via the UNIX domain socket (unless
-\-\-asynchronous is specified). The status information is meant to
-look a bit like that from \fBFTP\fP. Currently \fBwhack\fP simply
-copies this to stderr. When the request is finished (eg. the SAs are
-established or \fBpluto\fP gives up), \fBpluto\fP closes the channel,
-causing \fBwhack\fP to terminate.
-.LP
-The opportunistic initiate form is mainly used for debugging.
-.TP
-\fB\-\-tunnelipv4\fP
-.TP
-\fB\-\-tunnelipv6\fP
-.TP
-\fB\-\-oppohere\fP\ \fIip-address\fP
-.TP
-\fB\-\-oppothere\fP\ \fIip-address\fP
-.LP
-This will cause \fBpluto\fP to attempt to opportunistically initiate a
-connection from here to the there, even if a previous attempt
-had been made.
-The whack log will show the progress of this attempt.
-.LP
-The terminate form tells \fBpluto\fP to delete any SAs that use the specified
-connection and to stop any negotiations in process.
-It does not prevent new negotiations from starting (the delete form
-has this effect).
-.TP
-\fB\-\-terminate\fP
-.TP
-\fB\-\-name\fP\ \fIconnection-name\fP
-.LP
-The public key for informs \fBpluto\fP of the RSA public key for a potential peer.
-Private keys must be kept secret, so they are kept in
-.IR ipsec.secrets (5).
-.TP
-\fB\-\-keyid\ \fP\fIid\fP
-specififies the identity of the peer for which a public key should be used.
-Its form is identical to the identity in the connection.
-If no public key is specified, \fBpluto\fP attempts to find KEY records
-from DNS for the id (if a FQDN) or through reverse lookup (if an IP address).
-Note that there several interesting ways in which this is not secure.
-.TP
-\fB\-\-addkey\fP
-specifies that the new key is added to the collection; otherwise the
-new key replaces any old ones.
-.TP
-\fB\-\-pubkeyrsa\ \fP\fIkey\fP
-specifies the value of the RSA public key. It is a sequence of bytes
-as described in RFC 2537 ``RSA/MD5 KEYs and SIGs in the Domain Name System (DNS)''.
-It is denoted in a way suitable for \fIipsec_ttodata\fP(3).
-For example, a base 64 numeral starts with 0s.
-.LP
-The listen form tells \fBpluto\fP to start listening for IKE requests
-on its public interfaces. To avoid race conditions, it is normal to
-load the appropriate connections into \fBpluto\fP before allowing it
-to listen. If \fBpluto\fP isn't listening, it is pointless to
-initiate negotiations, so it will refuse requests to do so. Whenever
-the listen form is used, \fBpluto\fP looks for public interfaces and
-will notice when new ones have been added and when old ones have been
-removed. This is also the trigger for \fBpluto\fP to read the
-\fIipsec.secrets\fP file. So listen may useful more than once.
-.TP
-\fB\-\-listen\fP
-start listening for IKE traffic on public interfaces.
-.TP
-\fB\-\-unlisten\fP
-stop listening for IKE traffic on public interfaces.
-.LP
-The status form will display information about the internal state of
-\fBpluto\fP: information about each potential connection, about
-each state object, and about each shunt that \fBpluto\fP is managing
-without an associated connection.
-.TP
-\fB\-\-status\fP
-.LP
-The shutdown form is the proper way to shut down \fBpluto\fP.
-It will tear down the SAs on this machine that \fBpluto\fP has negotiated.
-It does not inform its peers, so the SAs on their machines remain.
-.TP
-\fB\-\-shutdown\fP
-.SS Examples
-.LP
-It would be normal to start \fBpluto\fP in one of the system initialization
-scripts. It needs to be run by the superuser. Generally, no arguments are needed.
-To run in manually, the superuser can simply type
-
-\ \ \ ipsec pluto
-
-The command will immediately return, but a \fBpluto\fP process will be left
-running, waiting for requests from \fBwhack\fP or a peer.
-.LP
-Using \fBwhack\fP, several potential connections would be described:
-.HP
-.na
-\ \ \ ipsec whack \-\-name\ silly
-\-\-host\ 127.0.0.1 \-\-to \-\-host\ 127.0.0.2
-\-\-ikelifetime\ 900 \-\-ipseclifetime\ 800 \-\-keyingtries\ 3
-.ad
-.LP
-Since this silly connection description specifies neither encryption,
-authentication, nor tunneling, it could only be used to establish
-an ISAKMP SA.
-.HP
-.na
-\ \ \ ipsec whack \-\-name\ secret \-\-host\ 10.0.0.1 \-\-client\ 10.0.1.0/24
-\-\-to \-\-host\ 10.0.0.2 \-\-client\ 10.0.2.0/24
-\-\-encrypt
-.ad
-.LP
-This is something that must be done on both sides. If the other
-side is \fBpluto\fP, the same \fBwhack\fP command could be used on it
-(the command syntax is designed to not distinguish which end is ours).
-.LP
-Now that the connections are specified, \fBpluto\fP is ready to handle
-requests and replies via the public interfaces. We must tell it to discover
-those interfaces and start accepting messages from peers:
-
-\ \ \ ipsec whack \-\-listen
-.LP
-If we don't immediately wish to bring up a secure connection between
-the two clients, we might wish to prevent insecure traffic.
-The routing form asks \fBpluto\fP to cause the packets sent from
-our client to the peer's client to be routed through the ipsec0
-device; if there is no SA, they will be discarded:
-
-\ \ \ ipsec whack \-\-route secret
-.LP
-Finally, we are ready to get \fBpluto\fP to initiate negotiation
-for an IPsec SA (and implicitly, an ISAKMP SA):
-
-\ \ \ ipsec whack \-\-initiate\ \-\-name\ secret
-
-A small log of interesting events will appear on standard output
-(other logging is sent to syslog).
-.LP
-\fBwhack\fP can also be used to terminate \fBpluto\fP cleanly, tearing down
-all SAs that it has negotiated.
-
-\ \ \ ipsec whack \-\-shutdown
-
-Notification of any IPSEC SA deletion, but not ISAKMP SA deletion
-is sent to the peer. Unfortunately, such Notification is not reliable.
-Furthermore, \fBpluto\fP itself ignores Notifications.
-.SS The updown command
-.LP
-Whenever \fBpluto\fP brings a connection up or down, it invokes
-the updown command. This command is specified using the \fB\-\-updown\fP
-option. This allows for customized control over routing and firewall manipulation.
-.LP
-The updown is invoked for five different operations. Each of
-these operations can be for our client subnet or for our host itself.
-.TP
-\fBprepare-host\fP or \fBprepare-client\fP
-is run before bringing up a new connection if no other connection
-with the same clients is up. Generally, this is useful for deleting a
-route that might have been set up before \fBpluto\fP was run or
-perhaps by some agent not known to \fBpluto\fP.
-.TP
-\fBroute-host\fP or \fBroute-client\fP
-is run when bringing up a connection for a new peer client subnet
-(even if \fBprepare-host\fP or \fBprepare-client\fP was run). The
-command should install a suitable route. Routing decisions are based
-only on the destination (peer's client) subnet address, unlike eroutes
-which discriminate based on source too.
-.TP
-\fBunroute-host\fP or \fBunroute-client\fP
-is run when bringing down the last connection for a particular peer
-client subnet. It should undo what the \fBroute-host\fP or \fBroute-client\fP
-did.
-.TP
-\fBup-host\fP or \fBup-client\fP
-is run when bringing up a tunnel eroute with a pair of client subnets
-that does not already have a tunnel eroute.
-This command should install firewall rules as appropriate.
-It is generally a good idea to allow IKE messages (UDP port 500)
-travel between the hosts.
-.TP
-\fBdown-host\fP or \fBdown-client\fP
-is run when bringing down the eroute for a pair of client subnets.
-This command should delete firewall rules as appropriate. Note that
-there may remain some inbound IPsec SAs with these client subnets.
-.LP
-The script is passed a large number of environment variables to specify
-what needs to be done.
-.TP
-\fBPLUTO_VERSION\fP
-indicates what version of this interface is being used. This document
-describes version 1.1. This is upwardly compatible with version 1.0.
-.TP
-\fBPLUTO_VERB\fP
-specifies the name of the operation to be performed
-(\fBprepare-host\fP,r \fBprepare-client\fP,
-\fBup-host\fP, \fBup-client\fP,
-\fBdown-host\fP, or \fBdown-client\fP). If the address family for
-security gateway to security gateway communications is IPv6, then
-a suffix of \-v6 is added to the verb.
-.TP
-\fBPLUTO_CONNECTION\fP
-is the name of the connection for which we are routing.
-.TP
-\fBPLUTO_NEXT_HOP\fP
-is the next hop to which packets bound for the peer must be sent.
-.TP
-\fBPLUTO_INTERFACE\fP
-is the name of the ipsec interface to be used.
-.TP
-\fBPLUTO_ME\fP
-is the IP address of our host.
-.TP
-\fBPLUTO_MY_CLIENT\fP
-is the IP address / count of our client subnet.
-If the client is just the host, this will be the host's own IP address / max
-(where max is 32 for IPv4 and 128 for IPv6).
-.TP
-\fBPLUTO_MY_CLIENT_NET\fP
-is the IP address of our client net.
-If the client is just the host, this will be the host's own IP address.
-.TP
-\fBPLUTO_MY_CLIENT_MASK\fP
-is the mask for our client net.
-If the client is just the host, this will be 255.255.255.255.
-.TP
-\fBPLUTO_PEER\fP
-is the IP address of our peer.
-.TP
-\fBPLUTO_PEER_CLIENT\fP
-is the IP address / count of the peer's client subnet.
-If the client is just the peer, this will be the peer's own IP address / max
-(where max is 32 for IPv4 and 128 for IPv6).
-.TP
-\fBPLUTO_PEER_CLIENT_NET\fP
-is the IP address of the peer's client net.
-If the client is just the peer, this will be the peer's own IP address.
-.TP
-\fBPLUTO_PEER_CLIENT_MASK\fP
-is the mask for the peer's client net.
-If the client is just the peer, this will be 255.255.255.255.
-.LP
-All output sent by the script to stderr or stdout is logged. The
-script should return an exit status of 0 if and only if it succeeds.
-.LP
-\fBPluto\fP waits for the script to finish and will not do any other
-processing while it is waiting.
-The script may assume that \fBpluto\fP will not change anything
-while the script runs.
-The script should avoid doing anything that takes much time and it
-should not issue any command that requires processing by \fBpluto\fP.
-Either of these activities could be performed by a background
-subprocess of the script.
-.SS Rekeying
-.LP
-When an SA that was initiated by \fBpluto\fP has only a bit of
-lifetime left,
-\fBpluto\fP will initiate the creation of a new SA. This applies to
-ISAKMP and IPsec SAs.
-The rekeying will be initiated when the SA's remaining lifetime is
-less than the rekeymargin plus a random percentage, between 0 and
-rekeyfuzz, of the rekeymargin.
-.LP
-Similarly, when an SA that was initiated by the peer has only a bit of
-lifetime left, \fBpluto\fP will try to initiate the creation of a
-replacement.
-To give preference to the initiator, this rekeying will only be initiated
-when the SA's remaining lifetime is half of rekeymargin.
-If rekeying is done by the responder, the roles will be reversed: the
-responder for the old SA will be the initiator for the replacement.
-The former initiator might also initiate rekeying, so there may
-be redundant SAs created.
-To avoid these complications, make sure that rekeymargin is generous.
-.LP
-One risk of having the former responder initiate is that perhaps
-none of its proposals is acceptable to the former initiator
-(they have not been used in a successful negotiation).
-To reduce the chances of this happening, and to prevent loss of security,
-the policy settings are taken from the old SA (this is the case even if
-the former initiator is initiating).
-These may be stricter than those of the connection.
-.LP
-\fBpluto\fP will not rekey an SA if that SA is not the most recent of its
-type (IPsec or ISAKMP) for its potential connection.
-This avoids creating redundant SAs.
-.LP
-The random component in the rekeying time (rekeyfuzz) is intended to
-make certain pathological patterns of rekeying unstable. If both
-sides decide to rekey at the same time, twice as many SAs as necessary
-are created. This could become a stable pattern without the
-randomness.
-.LP
-Another more important case occurs when a security gateway has SAs
-with many other security gateways. Each of these connections might
-need to be rekeyed at the same time. This would cause a high peek
-requirement for resources (network bandwidth, CPU time, entropy for
-random numbers). The rekeyfuzz can be used to stagger the rekeying
-times.
-.LP
-Once a new set of SAs has been negotiated, \fBpluto\fP will never send
-traffic on a superseded one. Traffic will be accepted on an old SA
-until it expires.
-.SS Selecting a Connection When Responding: Road Warrior Support
-.LP
-When \fBpluto\fP receives an initial Main Mode message, it needs to
-decide which connection this message is for. It picks based solely on
-the source and destination IP addresses of the message. There might
-be several connections with suitable IP addresses, in which case one
-of them is arbitrarily chosen. (The ISAKMP SA proposal contained in
-the message could be taken into account, but it is not.)
-.LP
-The ISAKMP SA is negotiated before the parties pass further
-identifying information, so all ISAKMP SA characteristics specified in
-the connection description should be the same for every connection
-with the same two host IP addresses. At the moment, the only
-characteristic that might differ is authentication method.
-.LP
-Up to this point,
-all configuring has presumed that the IP addresses
-are known to all parties ahead of time. This will not work
-when either end is mobile (or assigned a dynamic IP address for other
-reasons). We call this situation ``Road Warrior''. It is fairly tricky
-and has some important limitations, most of which are features of
-the IKE protocol.
-.LP
-Only the initiator may be mobile:
-the initiator may have an IP number unknown to the responder. When
-the responder doesn't recognize the IP address on the first Main Mode
-packet, it looks for a connection with itself as one end and \fB%any\fP
-as the other.
-If it cannot find one, it refuses to negotiate. If it
-does find one, it creates a temporary connection that is a duplicate
-except with the \fB%any\fP replaced by the source IP address from the
-packet; if there was no identity specified for the peer, the new IP
-address will be used.
-.LP
-When \fBpluto\fP is using one of these temporary connections and
-needs to find the preshared secret or RSA private key in \fIipsec.secrets\fP,
-and and the connection specified no identity for the peer, \fB%any\fP
-is used as its identity. After all, the real IP address was apparently
-unknown to the configuration, so it is unreasonable to require that
-it be used in this table.
-.LP
-Part way into the Phase 1 (Main Mode) negotiation using one of these
-temporary connection descriptions, \fBpluto\fP will be receive an
-Identity Payload. At this point, \fBpluto\fP checks for a more
-appropriate connection, one with an identity for the peer that matches
-the payload but which would use the same keys so-far used for
-authentication. If it finds one, it will switch to using this better
-connection (or a temporary derived from this, if it has \fB%any\fP
-for the peer's IP address). It may even turn out that no connection
-matches the newly discovered identity, including the current connection;
-if so, \fBpluto\fP terminates negotiation.
-.LP
-Unfortunately, if preshared secret authentication is being used, the
-Identity Payload is encrypted using this secret, so the secret must be
-selected by the responder without knowing this payload. This
-limits there to being at most one preshared secret for all Road Warrior
-systems connecting to a host. RSA Signature authentications does not
-require that the responder know how to select the initiator's public key
-until after the initiator's Identity Payload is decoded (using the
-responder's private key, so that must be preselected).
-.LP
-When \fBpluto\fP is responding to a Quick Mode negotiation via one of these
-temporary connection descriptions, it may well find that the subnets
-specified by the initiator don't match those in the temporary
-connection description. If so, it will look for a connection with
-matching subnets, its own host address, a peer address of \fB%any\fP
-and matching identities.
-If it finds one, a new temporary connection is derived from this one
-and used for the Quick Mode negotiation of IPsec SAs. If it does not
-find one, \fBpluto\fP terminates negotiation.
-.LP
-Be sure to specify an appropriate nexthop for the responder
-to send a message to the initiator: \fBpluto\fP has no way of guessing
-it (if forwarding isn't required, use an explicit \fB%direct\fP as the nexthop
-and the IP address of the initiator will be filled in; the obsolete
-notation \fB0.0.0.0\fP is still accepted).
-.LP
-\fBpluto\fP has no special provision for the initiator side. The current
-(possibly dynamic) IP address and nexthop must be used in defining
-connections. These must be
-properly configured each time the initiator's IP address changes.
-\fBpluto\fP has no mechanism to do this automatically.
-.LP
-Although we call this Road Warrior Support, it could also be used to
-support encrypted connections with anonymous initiators. The
-responder's organization could announce the preshared secret that would be used
-with unrecognized initiators and let anyone connect. Of course the initiator's
-identity would not be authenticated.
-.LP
-If any Road Warrior connections are supported, \fBpluto\fP cannot
-reject an exchange initiated by an unknown host until it has
-determined that the secret is not shared or the signature is invalid.
-This must await the
-third Main Mode message from the initiator. If no Road Warrior
-connection is supported, the first message from an unknown source
-would be rejected. This has implications for ease of debugging
-configurations and for denial of service attacks.
-.LP
-Although a Road Warrior connection must be initiated by the mobile
-side, the other side can and will rekey using the temporary connection
-it has created. If the Road Warrior wishes to be able to disconnect,
-it is probably wise to set \fB\-\-keyingtries\fP to 1 in the
-connection on the non-mobile side to prevent it trying to rekey the
-connection. Unfortunately, there is no mechanism to unroute the
-connection automatically.
-.SS Debugging
-.LP
-\fBpluto\fP accepts several optional arguments, useful mostly for debugging.
-Except for \fB\-\-interface\fP, each should appear at most once.
-.TP
-\fB\-\-interface\fP \fIinterfacename\fP
-specifies that the named real public network interface should be considered.
-The interface name specified should not be \fBipsec\fP\fIN\fP.
-If the option doesn't appear, all interfaces are considered.
-To specify several interfaces, use the option once for each.
-One use of this option is to specify which interface should be used
-when two or more share the same IP address.
-.TP
-\fB\-\-ikeport\fP \fIport-number\fP
-changes the UDP port that \fBpluto\fP will use
-(default, specified by IANA: 500)
-.TP
-\fB\-\-ctlbase\fP \fIpath\fP
-basename for control files.
-\fIpath\fP.ctl is the socket through which \fBwhack\fP communicates with
-\fBpluto\fP.
-\fIpath\fP.pid is the lockfile to prevent multiple \fBpluto\fP instances.
-The default is \fI/var/run/pluto\fP).
-.TP
-\fB\-\-secretsfile\fP \fIfile\fP
-specifies the file for authentication secrets
-(default: \fI/etc/ipsec.secrets\fP).
-This name is subject to ``globbing'' as in \fIsh\fP(1),
-so every file with a matching name is processed.
-Quoting is generally needed to prevent the shell from doing the globbing.
-.TP
-\fB\-\-adns\fP \fIpathname\fP
-.TP
-\fB\-\-lwdnsq\fP \fIpathname\fP
-specifies where to find \fBpluto\fP's helper program for asynchronous DNS lookup.
-\fBpluto\fP can be built to use one of two helper programs: \fB_pluto_adns\fP
-or \fBlwdnsq\fP. You must use the program for which it was built.
-By default, \fBpluto\fP will look for the program in
-\fB$IPSEC_DIR\fP (if that environment variable is defined) or, failing that,
-in the same directory as \fBpluto\fP.
-.TP
-\fB\-\-nofork\fP
-disable ``daemon fork'' (default is to fork). In addition, after the
-lock file and control socket are created, print the line ``Pluto
-initialized'' to standard out.
-.TP
-\fB\-\-uniqueids\fP
-if this option has been selected, whenever a new ISAKMP SA is
-established, any connection with the same Peer ID but a different
-Peer IP address is unoriented (causing all its SAs to be deleted).
-This helps clean up dangling SAs when a connection is lost and
-then regained at another IP address.
-.TP
-\fB\-\-stderrlog\fP
-log goes to standard out {default is to use \fIsyslogd\fP(8))
-.LP
-\fBpluto\fP is willing to produce a prodigious amount of debugging
-information. To do so, it must be compiled with \-DDEBUG. There are
-several classes of debugging output, and \fBpluto\fP may be directed to
-produce a selection of them. All lines of
-debugging output are prefixed with ``|\ '' to distinguish them from error
-messages.
-.LP
-When \fBpluto\fP is invoked, it may be given arguments to specify
-which classes to output. The current options are:
-.TP
-\fB\-\-debug-raw\fP
-show the raw bytes of messages
-.TP
-\fB\-\-debug-crypt\fP
-show the encryption and decryption of messages
-.TP
-\fB\-\-debug-parsing\fP
-show the structure of input messages
-.TP
-\fB\-\-debug-emitting\fP
-show the structure of output messages
-.TP
-\fB\-\-debug-control\fP
-show \fBpluto\fP's decision making
-.TP
-\fB\-\-debug-lifecycle\fP
-[this option is temporary] log more detail of lifecycle of SAs
-.TP
-\fB\-\-debug-kernel\fP
-show \fBpluto\fP's interaction with the kernel
-.TP
-\fB\-\-debug-dns\fP
-show \fBpluto\fP's interaction with \fBDNS\fP for KEY and TXT records
-.TP
-\fB\-\-debug-oppo\fP
-show why \fBpluto\fP didn't find a suitable DNS TXT record to authorize opportunistic initiation
-.TP
-\fB\-\-debug-all\fP
-all of the above
-.TP
-\fB\-\-debug-private\fP
-allow debugging output with private keys.
-.TP
-\fB\-\-debug-none\fP
-none of the above
-.LP
-The debug form of the
-\fBwhack\fP command will change the selection in a running
-\fBpluto\fP.
-If a connection name is specified, the flags are added whenever
-\fBpluto\fP has identified that it is dealing with that connection.
-Unfortunately, this is often part way into the operation being observed.
-.LP
-For example, to start a \fBpluto\fP with a display of the structure of input
-and output:
-.IP
-pluto \-\-debug-emitting \-\-debug-parsing
-.LP
-To later change this \fBpluto\fP to only display raw bytes:
-.IP
-whack \-\-debug-raw
-.LP
-For testing, SSH's IKE test page is quite useful:
-.IP
-\fIhttp://isakmp-test.ssh.fi/\fP
-.LP
-Hint: ISAKMP SAs are often kept alive by IKEs even after the IPsec SA
-is established. This allows future IPsec SA's to be negotiated
-directly. If one of the IKEs is restarted, the other may try to use
-the ISAKMP SA but the new IKE won't know about it. This can lead to
-much confusion. \fBpluto\fP is not yet smart enough to get out of such a
-mess.
-.SS Pluto's Behaviour When Things Go Wrong
-.LP
-When \fBpluto\fP doesn't understand or accept a message, it just
-ignores the message. It is not yet capable of communicating the
-problem to the other IKE daemon (in the future it might use
-Notifications to accomplish this in many cases). It does log a diagnostic.
-.LP
-When \fBpluto\fP gets no response from a message, it resends the same
-message (a message will be sent at most three times). This is
-appropriate: UDP is unreliable.
-.LP
-When pluto gets a message that it has already seen, there are many
-cases when it notices and discards it. This too is appropriate for UDP.
-.LP
-Combine these three rules, and you can explain many apparently
-mysterious behaviours. In a \fBpluto\fP log, retrying isn't usually the
-interesting event. The critical thing is either earlier (\fBpluto\fP
-got a message which it didn't like and so ignored, so it was still
-awaiting an acceptable message and got impatient) or on the other
-system (\fBpluto\fP didn't send a reply because it wasn't happy with
-the previous message).
-.SS Notes
-.LP
-Each IPsec SA is assigned an SPI, a 32-bit number used to refer to the SA.
-The IKE protocol lets the destination of the SA choose the SPI.
-The range 0 to 0xFF is reserved for IANA.
-\fBPluto\fP also avoids choosing an SPI in the range 0x100 to 0xFFF,
-leaving these SPIs free for manual keying.
-Remember that the peer, if not \fBpluto\fP, may well chose
-SPIs in this range.
-.SS Policies
-.LP
-This catalogue of policies may be of use when trying to configure
-\fBPluto\fP and another IKE implementation to interoperate.
-.LP
-In Phase 1, only Main Mode is supported. We are not sure that
-Aggressive Mode is secure. For one thing, it does not support
-identity protection. It may allow more severe Denial Of Service
-attacks.
-.LP
-No Informational Exchanges are supported. These are optional and
-since their delivery is not assured, they must not matter.
-It is the case that some IKE implementations won't interoperate
-without Informational Exchanges, but we feel they are broken.
-.LP
-No Informational Payloads are supported. These are optional, but
-useful. It is of concern that these payloads are not authenticated in
-Phase 1, nor in those Phase 2 messages authenticated with HASH(3).
-.IP \(bu \w'\(bu\ 'u
-Diffie Hellman Groups MODP 1024 and MODP 1536 (2 and 5)
-are supported.
-Group MODP768 (1) is not supported because it is too weak.
-.IP \(bu
-Host authetication can be done by RSA Signatures or Pre-Shared
-Secrets.
-.IP \(bu
-3DES CBC (Cypher Block Chaining mode) is the only encryption
-supported, both for ISAKMP SAs and IPSEC SAs.
-.IP \(bu
-MD5 and SHA1 hashing are supported for packet authentication in both
-kinds of SAs.
-.IP \(bu
-The ESP, AH, or AH plus ESP are supported. If, and only if, AH and
-ESP are combined, the ESP need not have its own authentication
-component. The selection is controlled by the \-\-encrypt and
-\-\-authenticate flags.
-.IP \(bu
-Each of these may be combined with IPCOMP Deflate compression,
-but only if the potential connection specifies compression and only
-if the kernel is configured with IPCOMP support.
-.IP \(bu
-The IPSEC SAs may be tunnel or transport mode, where appropriate.
-The \-\-tunnel flag controls this when \fBpluto\fP is initiating.
-.IP \(bu
-When responding to an ISAKMP SA proposal, the maximum acceptable
-lifetime is eight hours. The default is one hour. There is no
-minimum. The \-\-ikelifetime flag controls this when \fBpluto\fP
-is initiating.
-.IP \(bu
-When responding to an IPSEC SA proposal, the maximum acceptable
-lifetime is one day. The default is eight hours. There is no
-minimum. The \-\-ipseclifetime flag controls this when \fBpluto\fP
-is initiating.
-.IP \(bu
-PFS is acceptable, and will be proposed if the \-\-pfs flag was
-specified. The DH group proposed will be the same as negotiated for
-Phase 1.
-.SH SIGNALS
-.LP
-\fBPluto\fP responds to \fBSIGHUP\fP by issuing a suggestion that ``\fBwhack\fP
-\-\-listen'' might have been intended.
-.LP
-\fBPluto\fP exits when it receives \fBSIGTERM\fP.
-.SH EXIT STATUS
-.LP
-\fBpluto\fP normally forks a daemon process, so the exit status is
-normally a very preliminary result.
-.TP
-0
-means that all is OK so far.
-.TP
-1
-means that something was wrong.
-.TP
-10
-means that the lock file already exists.
-.LP
-If \fBwhack\fP detects a problem, it will return an exit status of 1.
-If it received progress messages from \fBpluto\fP, it returns as status
-the value of the numeric prefix from the last such message
-that was not a message sent to syslog or a comment
-(but the prefix for success is treated as 0).
-Otherwise, the exit status is 0.
-.SH FILES
-\fI/var/run/pluto.pid\fP
-.br
-\fI/var/run/pluto.ctl\fP
-.br
-\fI/etc/ipsec.secrets\fP
-.br
-\fI$IPSEC_LIBDIR/_pluto_adns\fP
-.br
-\fI$IPSEC_EXECDIR/lwdnsq\fP
-.br
-\fI/dev/urandom\fP
-.SH ENVIRONMENT
-\fIIPSEC_LIBDIR\fP
-.br
-\fIIPSEC_EXECDIR\fP
-.br
-\fIIPSECmyid\fP
-.SH SEE ALSO
-.LP
-The rest of the FreeS/WAN distribution, in particular \fIipsec\fP(8).
-.LP
-\fIipsec_auto\fP(8) is designed to make using \fBpluto\fP more pleasant.
-Use it!
-.LP
-.IR ipsec.secrets (5)
-describes the format of the secrets file.
-.LP
-\fIipsec_atoaddr\fP(3), part of the FreeS/WAN distribution, describes the
-forms that IP addresses may take.
-\fIipsec_atosubnet\fP(3), part of the FreeS/WAN distribution, describes the
-forms that subnet specifications.
-.LP
-For more information on IPsec, the mailing list, and the relevant
-documents, see:
-.IP
-.nh
-\fIhttp://www.ietf.cnri.reston.va.us/html.charters/ipsec-charter.html\fP
-.hy
-.LP
-At the time of writing, the most relevant IETF RFCs are:
-.IP
-RFC2409 The Internet Key Exchange (IKE)
-.IP
-RFC2408 Internet Security Association and Key Management Protocol (ISAKMP)
-.IP
-RFC2407 The Internet IP Security Domain of Interpretation for ISAKMP
-.LP
-The FreeS/WAN web site <htp://www.freeswan.org>
-and the mailing lists described there.
-.SH HISTORY
-This code is released under the GPL terms.
-See the accompanying file COPYING-2.0 for more details.
-The GPL does NOT apply to those pieces of code written by others
-which are included in this distribution, except as noted by the
-individual authors.
-.LP
-This software was originally written
-for the FreeS/WAN project
-<http://www.freeswan.org>
-by Angelos D. Keromytis
-(angelos@dsl.cis.upenn.edu), in May/June 1997, in Athens, Greece.
-Thanks go to John Ioannidis for his help.
-.LP
-It is currently (2000)
-being developed and maintained by D. Hugh Redelmeier
-(hugh@mimosa.com), in Canada. The regulations of Greece and Canada
-allow us to make the code freely redistributable.
-.LP
-Kai Martius (admin@imib.med.tu-dresden.de) contributed the initial
-version of the code supporting PFS.
-.LP
-Richard Guy Briggs <rgb@conscoop.ottawa.on.ca> and Peter Onion
-<ponion@srd.bt.co.uk> added the PFKEY2 support.
-.LP
-We gratefully acknowledge that we use parts of Eric Young's \fIlibdes\fP
-package; see \fI../libdes/COPYRIGHT\fP.
-.SH BUGS
-.BR pluto
-is a work-in-progress. It currently has many limitations.
-For example, it ignores notification messages that it receives, and
-it generates only Delete Notifications and those only for IPSEC SAs.
-.LP
-\fBpluto\fP does not support the Commit Flag.
-The Commit Flag is a bad feature of the IKE protocol.
-It isn't protected -- neither encrypted nor authenticated.
-A man in the middle could turn it on, leading to DoS.
-We just ignore it, with a warning.
-This should let us interoperate with
-implementations that insist on it, with minor damage.
-.LP
-\fBpluto\fP does not check that the SA returned by the Responder
-is actually one that was proposed. It only checks that the SA is
-acceptable. The difference is not large, but can show up in attributes
-such as SA lifetime.
-.LP
-There is no good way for a connection to be automatically terminated.
-This is a problem for Road Warrior and Opportunistic connections.
-The \fB\-\-dontrekey\fP option does prevent the SAs from
-being rekeyed on expiry.
-Additionally, if a Road Warrior connection has a client subnet with a fixed IP
-address, a negotiation with that subnet will cause any other
-connection instantiations with that same subnet to be unoriented
-(deleted, in effect).
-See also the \-\-uniqueids option for an extension of this.
-.LP
-When \fBpluto\fP sends a message to a peer that has disappeared,
-\fBpluto\fP receives incomplete information from the kernel, so it
-logs the unsatisfactory message ``some IKE message we sent has been
-rejected with ECONNREFUSED (kernel supplied no details)''. John
-Denker suggests that this command is useful for tracking down the
-source of these problems:
-.br
- tcpdump \-i eth0 icmp[0] != 8 and icmp[0] != 0
-.br
-Substitute your public interface for eth0 if it is different.
-.LP
-The word ``authenticate'' is used for two different features. We must
-authenticate each IKE peer to the other. This is an important task of
-Phase 1. Each packet must be authenticated, both in IKE and in IPsec,
-and the method for IPsec is negotiated as an AH SA or part of an ESP SA.
-Unfortunately, the protocol has no mechanism for authenticating the Phase 2
-identities.
-.LP
-Bugs should be reported to the <users@lists.freeswan.org> mailing list.
-Caution: we cannot accept
-actual code from US residents, or even US citizens living outside the
-US, because that would bring FreeS/WAN under US export law. Some
-other countries cause similar problems. In general, we would prefer
-that you send detailed problem reports rather than code: we want
-FreeS/WAN to be unquestionably freely exportable, which means being
-very careful about where the code comes from, and for a small bug fix,
-that is often more time-consuming than just reinventing the fix
-ourselves.
diff --git a/src/pluto/pluto.c b/src/pluto/pluto.c
deleted file mode 100644
index 66fdb30b9..000000000
--- a/src/pluto/pluto.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2010 Andreas Steffen
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include "pluto.h"
-
-#include <debug.h>
-
-typedef struct private_pluto_t private_pluto_t;
-
-/**
- * Private additions to pluto_t.
- */
-struct private_pluto_t {
-
- /**
- * Public members of pluto_t.
- */
- pluto_t public;
-};
-
-/**
- * Single instance of pluto_t.
- */
-pluto_t *pluto;
-
-/**
- * Described in header.
- */
-void pluto_deinit()
-{
- private_pluto_t *this = (private_pluto_t*)pluto;
- this->public.events->destroy(this->public.events);
- this->public.xauth->destroy(this->public.xauth);
- free(this);
- pluto = NULL;
-}
-
-/**
- * Described in header.
- */
-bool pluto_init(char *file)
-{
- private_pluto_t *this;
-
- INIT(this,
- .public = {
- .events = event_queue_create(),
- .xauth = xauth_manager_create(),
- },
- );
- pluto = &this->public;
-
- if (lib->integrity &&
- !lib->integrity->check_file(lib->integrity, "pluto", file))
- {
- DBG1(DBG_LIB, "integrity check of pluto failed");
- return FALSE;
- }
- return TRUE;
-}
-
diff --git a/src/pluto/pluto.h b/src/pluto/pluto.h
deleted file mode 100644
index 2440093ca..000000000
--- a/src/pluto/pluto.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2010 Andreas Steffen
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup pluto pluto
- *
- * @defgroup xauth xauth
- * @ingroup pluto
- *
- * @defgroup pplugins plugins
- * @ingroup pluto
- *
- * @addtogroup pluto
- * @{
- */
-
-#ifndef PLUTO_H_
-#define PLUTO_H_
-
-typedef struct pluto_t pluto_t;
-
-#include <event_queue.h>
-#include <xauth/xauth_manager.h>
-
-#include <library.h>
-
-/**
- * Pluto daemon support object.
- */
-struct pluto_t {
-
- /**
- * event queue (callbacks, executed by the pluto main thread)
- */
- event_queue_t *events;
-
- /**
- * manager for payload attributes
- */
- xauth_manager_t *xauth;
-
-};
-
-/**
- * The single instance of pluto_t.
- *
- * Set between calls to pluto_init() and pluto_deinit() calls.
- */
-extern pluto_t *pluto;
-
-/**
- * Initialize pluto.
- *
- * @return FALSE if integrity check failed
- */
-bool pluto_init(char *file);
-
-/**
- * Deinitialize pluto.
- */
-void pluto_deinit(void);
-
-#endif /** PLUTO_H_ @}*/
-
diff --git a/src/pluto/plutomain.c b/src/pluto/plutomain.c
deleted file mode 100644
index dbc857ce2..000000000
--- a/src/pluto/plutomain.c
+++ /dev/null
@@ -1,852 +0,0 @@
-/* Pluto main program
- * Copyright (C) 1997 Angelos D. Keromytis.
- * Copyright (C) 1998-2001 D. Hugh Redelmeier.
- * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <ctype.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <fcntl.h>
-#include <getopt.h>
-#include <resolv.h>
-#include <arpa/nameser.h> /* missing from <resolv.h> on old systems */
-#include <sys/queue.h>
-#include <sys/prctl.h>
-#include <signal.h>
-#include <pwd.h>
-#include <grp.h>
-
-#ifdef CAPABILITIES
-#ifdef HAVE_SYS_CAPABILITY_H
-#include <sys/capability.h>
-#endif /* HAVE_SYS_CAPABILITY_H */
-#endif /* CAPABILITIES */
-
-#include <freeswan.h>
-
-#include <hydra.h>
-#include <library.h>
-#include <debug.h>
-#include <utils/enumerator.h>
-#include <utils/optionsfrom.h>
-
-#include <pfkeyv2.h>
-#include <pfkey.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "myid.h"
-#include "ca.h"
-#include "certs.h"
-#include "ac.h"
-#include "connections.h"
-#include "foodgroups.h"
-#include "packet.h"
-#include "demux.h" /* needs packet.h */
-#include "server.h"
-#include "kernel.h"
-#include "log.h"
-#include "keys.h"
-#include "adns.h" /* needs <resolv.h> */
-#include "dnskey.h" /* needs keys.h and adns.h */
-#include "state.h"
-#include "ipsec_doi.h" /* needs demux.h and state.h */
-#include "ocsp.h"
-#include "crl.h"
-#include "fetch.h"
-#include "crypto.h"
-#include "nat_traversal.h"
-#include "virtual.h"
-#include "timer.h"
-#include "vendor.h"
-#include "builder.h"
-#include "whack_attribute.h"
-#include "pluto.h"
-
-#ifdef ANDROID
-#include <private/android_filesystem_config.h> /* for AID_VPN */
-#endif
-
-/**
- * Number of threads in the thread pool, if not specified in config.
- */
-#define DEFAULT_THREADS 4
-
-/**
- * PID file, in which pluto stores its process id
- */
-static char pluto_lock[sizeof(ctl_addr.sun_path)] = DEFAULT_CTLBASE LOCK_SUFFIX;
-
-/**
- * TRUE if the lock has been checked. This helps to avoid any unintended
- * deletion of the lock or control socket.
- */
-static bool pluto_lock_checked = FALSE;
-
-/**
- * Global reference to PID file (required to truncate, if undeletable)
- */
-static FILE *pidfile = NULL;
-
-
-static void usage(const char *mess)
-{
- if (mess != NULL && *mess != '\0')
- fprintf(stderr, "%s\n", mess);
- fprintf(stderr
- , "Usage: pluto"
- " [--help]"
- " [--version]"
- " [--optionsfrom <filename>]"
- " \\\n\t"
- "[--nofork]"
- " [--stderrlog]"
- " [--nocrsend]"
- " \\\n\t"
- "[--strictcrlpolicy]"
- " [--crlcheckinterval <interval>]"
- " [--cachecrls]"
- " [--uniqueids]"
- " \\\n\t"
- "[--interface <ifname>]"
- " [--ikeport <port-number>]"
- " \\\n\t"
- "[--ctlbase <path>]"
- " \\\n\t"
- "[--perpeerlogbase <path>] [--perpeerlog]"
- " \\\n\t"
- "[--secretsfile <secrets-file>]"
- " [--policygroupsdir <policygroups-dir>]"
- " \\\n\t"
- "[--adns <pathname>]"
- "[--pkcs11module <path>]"
- "[--pkcs11keepstate]"
- "[--pkcs11initargs <string>]"
-#ifdef DEBUG
- " \\\n\t"
- "[--debug-none]"
- " [--debug-all]"
- " \\\n\t"
- "[--debug-raw]"
- " [--debug-crypt]"
- " [--debug-parsing]"
- " [--debug-emitting]"
- " \\\n\t"
- "[--debug-control]"
- " [--debug-lifecycle]"
- " [--debug-kernel]"
- " [--debug-dns]"
- " \\\n\t"
- "[--debug-oppo]"
- " [--debug-controlmore]"
- " [--debug-private]"
- " [--debug-natt]"
-#endif
- " \\\n\t"
- "[--nat_traversal] [--keep_alive <delay_sec>]"
- " \\\n\t"
- "[--force_keepalive] [--disable_port_floating]"
- " \\\n\t"
- "[--virtual_private <network_list>]"
- "\n"
- "strongSwan "VERSION"\n");
- exit_pluto(mess == NULL? 0 : 1);
-}
-
-static bool check_lock()
-{
- struct stat stb;
- FILE *fpid;
-
- if (stat(pluto_lock, &stb) == 0)
- {
- fpid = fopen(pluto_lock, "r");
- if (fpid)
- {
- char buf[64];
- pid_t pid = 0;
-
- memset(buf, 0, sizeof(buf));
- if (fread(buf, 1, sizeof(buf), fpid))
- {
- buf[sizeof(buf) - 1] = '\0';
- pid = atoi(buf);
- }
- fclose(fpid);
- if (pid && kill(pid, 0) == 0)
- { /* such a process is running */
- return TRUE;
- }
- }
- fprintf(stderr, "pluto: removing lock file \"%s\", process not "
- "running\n", pluto_lock);
- unlink(pluto_lock);
- }
- pluto_lock_checked = TRUE;
- return FALSE;
-}
-
-static void fill_lock(void)
-{
- pidfile = fopen(pluto_lock, "w");
- if (pidfile)
- {
- fprintf(pidfile, "%u\n", (u_int)getpid());
- fflush(pidfile);
- }
- /* keep pidfile open so we can truncate it, if we cannot delete it */
-}
-
-static void delete_lock(void)
-{
- /* because unlinking the PID file may fail, we truncate it to ensure the
- * daemon can be properly restarted. one probable cause for this is the
- * combination of not running as root and the effective user lacking
- * permissions on the parent dir(s) of the PID file */
- if (pluto_lock_checked)
- {
- if (pidfile)
- {
- ignore_result(ftruncate(fileno(pidfile), 0));
- fclose(pidfile);
- }
- unlink(pluto_lock);
- /* delete this here to avoid that exit_pluto calls delete the socket */
- delete_ctl_socket();
- }
-}
-
-
-/* by default pluto sends certificate requests to its peers */
-bool no_cr_send = FALSE;
-
-/* by default the CRL policy is lenient */
-bool strict_crl_policy = FALSE;
-
-/* by default CRLs are cached locally as files */
-bool cache_crls = FALSE;
-
-/* by default pluto does not check crls dynamically */
-long crl_check_interval = 0;
-
-/* path to the PKCS#11 module */
-char *pkcs11_module_path = NULL;
-
-/* by default pluto logs out after every smartcard use */
-bool pkcs11_keep_state = FALSE;
-
-/* by default pluto does not allow pkcs11 proxy access via whack */
-bool pkcs11_proxy = FALSE;
-
-/* argument string to pass to PKCS#11 module.
- * Not used for compliant modules, just for NSS softoken
- */
-static const char *pkcs11_init_args = NULL;
-
-/* options read by optionsfrom */
-options_t *options;
-
-int main(int argc, char **argv)
-{
- bool fork_desired = TRUE;
- bool log_to_stderr_desired = FALSE;
- bool nat_traversal = FALSE;
- bool nat_t_spf = TRUE; /* support port floating */
- unsigned int keep_alive = 0;
- bool force_keepalive = FALSE;
- char *virtual_private = NULL;
-#ifdef CAPABILITIES
- int keep[] = {
- CAP_NET_ADMIN,
- CAP_NET_BIND_SERVICE,
-#ifdef ANDROID
- CAP_NET_RAW,
-#endif
- };
-#endif /* CAPABILITIES */
-
- /* initialize library and optionsfrom */
- if (!library_init(NULL))
- {
- library_deinit();
- exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
- }
- if (!libhydra_init("pluto"))
- {
- libhydra_deinit();
- library_deinit();
- exit(SS_RC_INITIALIZATION_FAILED);
- }
- if (!pluto_init(argv[0]))
- {
- pluto_deinit();
- libhydra_deinit();
- library_deinit();
- exit(SS_RC_DAEMON_INTEGRITY);
- }
- options = options_create();
-
- /* handle arguments */
- for (;;)
- {
-# define DBG_OFFSET 256
- static const struct option long_opts[] = {
- /* name, has_arg, flag, val */
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, 'v' },
- { "optionsfrom", required_argument, NULL, '+' },
- { "nofork", no_argument, NULL, 'd' },
- { "stderrlog", no_argument, NULL, 'e' },
- { "nocrsend", no_argument, NULL, 'c' },
- { "strictcrlpolicy", no_argument, NULL, 'r' },
- { "crlcheckinterval", required_argument, NULL, 'x'},
- { "cachecrls", no_argument, NULL, 'C' },
- { "uniqueids", no_argument, NULL, 'u' },
- { "interface", required_argument, NULL, 'i' },
- { "ikeport", required_argument, NULL, 'p' },
- { "ctlbase", required_argument, NULL, 'b' },
- { "secretsfile", required_argument, NULL, 's' },
- { "foodgroupsdir", required_argument, NULL, 'f' },
- { "perpeerlogbase", required_argument, NULL, 'P' },
- { "perpeerlog", no_argument, NULL, 'l' },
- { "policygroupsdir", required_argument, NULL, 'f' },
- { "adns", required_argument, NULL, 'a' },
- { "pkcs11module", required_argument, NULL, 'm' },
- { "pkcs11keepstate", no_argument, NULL, 'k' },
- { "pkcs11initargs", required_argument, NULL, 'z' },
- { "pkcs11proxy", no_argument, NULL, 'y' },
- { "nat_traversal", no_argument, NULL, '1' },
- { "keep_alive", required_argument, NULL, '2' },
- { "force_keepalive", no_argument, NULL, '3' },
- { "disable_port_floating", no_argument, NULL, '4' },
- { "debug-natt", no_argument, NULL, '5' },
- { "virtual_private", required_argument, NULL, '6' },
-#ifdef DEBUG
- { "debug-none", no_argument, NULL, 'N' },
- { "debug-all", no_argument, NULL, 'A' },
- { "debug-raw", no_argument, NULL, DBG_RAW + DBG_OFFSET },
- { "debug-crypt", no_argument, NULL, DBG_CRYPT + DBG_OFFSET },
- { "debug-parsing", no_argument, NULL, DBG_PARSING + DBG_OFFSET },
- { "debug-emitting", no_argument, NULL, DBG_EMITTING + DBG_OFFSET },
- { "debug-control", no_argument, NULL, DBG_CONTROL + DBG_OFFSET },
- { "debug-lifecycle", no_argument, NULL, DBG_LIFECYCLE + DBG_OFFSET },
- { "debug-klips", no_argument, NULL, DBG_KERNEL + DBG_OFFSET },
- { "debug-kernel", no_argument, NULL, DBG_KERNEL + DBG_OFFSET },
- { "debug-dns", no_argument, NULL, DBG_DNS + DBG_OFFSET },
- { "debug-oppo", no_argument, NULL, DBG_OPPO + DBG_OFFSET },
- { "debug-controlmore", no_argument, NULL, DBG_CONTROLMORE + DBG_OFFSET },
- { "debug-private", no_argument, NULL, DBG_PRIVATE + DBG_OFFSET },
-
- { "impair-delay-adns-key-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_KEY_ANSWER + DBG_OFFSET },
- { "impair-delay-adns-txt-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_TXT_ANSWER + DBG_OFFSET },
- { "impair-bust-mi2", no_argument, NULL, IMPAIR_BUST_MI2 + DBG_OFFSET },
- { "impair-bust-mr2", no_argument, NULL, IMPAIR_BUST_MR2 + DBG_OFFSET },
-#endif
- { 0,0,0,0 }
- };
- /* Note: we don't like the way short options get parsed
- * by getopt_long, so we simply pass an empty string as
- * the list. It could be "hvdenp:l:s:" "NARXPECK".
- */
- int c = getopt_long(argc, argv, "", long_opts, NULL);
-
- /* Note: "breaking" from case terminates loop */
- switch (c)
- {
- case EOF: /* end of flags */
- break;
-
- case 0: /* long option already handled */
- continue;
-
- case ':': /* diagnostic already printed by getopt_long */
- case '?': /* diagnostic already printed by getopt_long */
- usage("");
- break; /* not actually reached */
-
- case 'h': /* --help */
- usage(NULL);
- break; /* not actually reached */
-
- case 'v': /* --version */
- {
- const char **sp = ipsec_copyright_notice();
-
- printf("strongSwan "VERSION"%s\n", compile_time_interop_options);
- for (; *sp != NULL; sp++)
- puts(*sp);
- }
- exit_pluto(0);
- break; /* not actually reached */
-
- case '+': /* --optionsfrom <filename> */
- if (!options->from(options, optarg, &argc, &argv, optind))
- {
- exit_pluto(1);
- }
- continue;
-
- case 'd': /* --nofork*/
- fork_desired = FALSE;
- continue;
-
- case 'e': /* --stderrlog */
- log_to_stderr_desired = TRUE;
- continue;
-
- case 'c': /* --nocrsend */
- no_cr_send = TRUE;
- continue;
-
- case 'r': /* --strictcrlpolicy */
- strict_crl_policy = TRUE;
- continue;
-
- case 'x': /* --crlcheckinterval <time>*/
- if (optarg == NULL || !isdigit(optarg[0]))
- usage("missing interval time");
-
- {
- char *endptr;
- long interval = strtol(optarg, &endptr, 0);
-
- if (*endptr != '\0' || endptr == optarg
- || interval <= 0)
- usage("<interval-time> must be a positive number");
- crl_check_interval = interval;
- }
- continue;
-
- case 'C': /* --cachecrls */
- cache_crls = TRUE;
- continue;
-
- case 'u': /* --uniqueids */
- uniqueIDs = TRUE;
- continue;
-
- case 'i': /* --interface <ifname> */
- if (!use_interface(optarg))
- usage("too many --interface specifications");
- continue;
-
- case 'p': /* --port <portnumber> */
- if (optarg == NULL || !isdigit(optarg[0]))
- usage("missing port number");
-
- {
- char *endptr;
- long port = strtol(optarg, &endptr, 0);
-
- if (*endptr != '\0' || endptr == optarg
- || port <= 0 || port > 0x10000)
- usage("<port-number> must be a number between 1 and 65535");
- pluto_port = port;
- }
- continue;
-
- case 'b': /* --ctlbase <path> */
- if (snprintf(ctl_addr.sun_path, sizeof(ctl_addr.sun_path)
- , "%s%s", optarg, CTL_SUFFIX) == -1)
- usage("<path>" CTL_SUFFIX " too long for sun_path");
- if (snprintf(info_addr.sun_path, sizeof(info_addr.sun_path)
- , "%s%s", optarg, INFO_SUFFIX) == -1)
- usage("<path>" INFO_SUFFIX " too long for sun_path");
- if (snprintf(pluto_lock, sizeof(pluto_lock)
- , "%s%s", optarg, LOCK_SUFFIX) == -1)
- usage("<path>" LOCK_SUFFIX " must fit");
- continue;
-
- case 's': /* --secretsfile <secrets-file> */
- shared_secrets_file = optarg;
- continue;
-
- case 'f': /* --policygroupsdir <policygroups-dir> */
- policygroups_dir = optarg;
- continue;
-#ifdef ADNS
- case 'a': /* --adns <pathname> */
- pluto_adns_option = optarg;
- continue;
-#endif
- case 'm': /* --pkcs11module <pathname> */
- pkcs11_module_path = optarg;
- continue;
-
- case 'k': /* --pkcs11keepstate */
- pkcs11_keep_state = TRUE;
- continue;
-
- case 'y': /* --pkcs11proxy */
- pkcs11_proxy = TRUE;
- continue;
-
- case 'z': /* --pkcs11initargs */
- pkcs11_init_args = optarg;
- continue;
-
-#ifdef DEBUG
- case 'N': /* --debug-none */
- base_debugging = DBG_NONE;
- continue;
-
- case 'A': /* --debug-all */
- base_debugging = DBG_ALL;
- continue;
-#endif
-
- case 'P': /* --perpeerlogbase */
- base_perpeer_logdir = optarg;
- continue;
-
- case 'l':
- log_to_perpeer = TRUE;
- continue;
-
- case '1': /* --nat_traversal */
- nat_traversal = TRUE;
- continue;
- case '2': /* --keep_alive */
- keep_alive = atoi(optarg);
- continue;
- case '3': /* --force_keepalive */
- force_keepalive = TRUE;
- continue;
- case '4': /* --disable_port_floating */
- nat_t_spf = FALSE;
- continue;
- case '5': /* --debug-nat_t */
- base_debugging |= DBG_NATT;
- continue;
- case '6': /* --virtual_private */
- virtual_private = optarg;
- continue;
-
- default:
-#ifdef DEBUG
- if (c >= DBG_OFFSET)
- {
- base_debugging |= c - DBG_OFFSET;
- continue;
- }
-# undef DBG_OFFSET
-#endif
- bad_case(c);
- }
- break;
- }
- if (optind != argc)
- usage("unexpected argument");
- reset_debugging();
-
- if (check_lock())
- {
- fprintf(stderr, "pluto: lock file \"%s\" already exists\n", pluto_lock);
- exit_pluto(10);
- }
-
- /* select between logging methods */
-
- if (log_to_stderr_desired)
- {
- log_to_syslog = FALSE;
- }
- else
- {
- log_to_stderr = FALSE;
- }
-
- /* set the logging function of pfkey debugging */
-#ifdef DEBUG
- pfkey_debug_func = DBG_log;
-#else
- pfkey_debug_func = NULL;
-#endif
-
- /* create control socket.
- * We must create it before the parent process returns so that
- * there will be no race condition in using it. The easiest
- * place to do this is before the daemon fork.
- */
- {
- err_t ugh = init_ctl_socket();
-
- if (ugh != NULL)
- {
- fprintf(stderr, "pluto: %s", ugh);
- exit_pluto(1);
- }
- }
-
- /* If not suppressed, do daemon fork */
-
- if (fork_desired)
- {
- {
- pid_t pid = fork();
-
- if (pid < 0)
- {
- int e = errno;
-
- fprintf(stderr, "pluto: fork failed (%d %s)\n",
- errno, strerror(e));
- exit_pluto(1);
- }
-
- if (pid != 0)
- {
- /* parent: die
- * must not use exit_pluto: lock would be removed!
- */
- exit(0);
- }
- /* child: fill PID into lock file */
- fill_lock();
- }
-
- if (setsid() < 0)
- {
- int e = errno;
-
- fprintf(stderr, "setsid() failed in main(). Errno %d: %s\n",
- errno, strerror(e));
- exit_pluto(1);
- }
- }
- else
- {
- /* no daemon fork: we have to fill in lock file */
- fill_lock();
- fprintf(stdout, "Pluto initialized\n");
- fflush(stdout);
- }
-
- /* Redirect stdin, stdout and stderr to /dev/null
- */
- {
- int fd;
- if ((fd = open("/dev/null", O_RDWR)) == -1)
- abort();
- if (dup2(fd, 0) != 0)
- abort();
- if (dup2(fd, 1) != 1)
- abort();
- if (!log_to_stderr && dup2(fd, 2) != 2)
- abort();
- close(fd);
- }
-
- /* for uncritical pseudo random numbers */
- srand(time(NULL) + getpid());
-
- init_constants();
- init_log("pluto");
-
- /* Note: some scripts may look for this exact message -- don't change
- * ipsec barf was one, but it no longer does.
- */
- plog("Starting IKEv1 pluto daemon (strongSwan "VERSION")%s",
- compile_time_interop_options);
-
- if (lib->integrity)
- {
- plog("integrity tests enabled:");
- plog("lib 'libstrongswan': passed file and segment integrity tests");
- plog("lib 'libhydra': passed file and segment integrity tests");
- plog("daemon 'pluto': passed file integrity test");
- }
-
- /* load plugins, further infrastructure may need it */
- if (!lib->plugins->load(lib->plugins, NULL,
- lib->settings->get_str(lib->settings, "pluto.load", PLUGINS)))
- {
- exit(SS_RC_INITIALIZATION_FAILED);
- }
- DBG1(DBG_DMN, "loaded plugins: %s",
- lib->plugins->loaded_plugins(lib->plugins));
-
- init_builder();
- if (!init_secret() || !init_crypto())
- {
- plog("initialization failed - aborting pluto");
- exit_pluto(SS_RC_INITIALIZATION_FAILED);
- }
- init_nat_traversal(nat_traversal, keep_alive, force_keepalive, nat_t_spf);
- init_virtual_ip(virtual_private);
- scx_init(pkcs11_module_path, pkcs11_init_args);
- init_states();
- init_demux();
- init_kernel();
-#ifdef ADNS
- init_adns();
-#endif
- init_myid();
- fetch_initialize();
- ac_initialize();
- whack_attribute_initialize();
-
- /* drop unneeded capabilities and change UID/GID */
- prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
-
-#ifdef IPSEC_GROUP
- {
- struct group group, *grp;
- char buf[1024];
-
- if (getgrnam_r(IPSEC_GROUP, &group, buf, sizeof(buf), &grp) != 0 ||
- grp == NULL || setgid(grp->gr_gid) != 0)
- {
- plog("unable to change daemon group");
- abort();
- }
- }
-#endif
-#ifdef IPSEC_USER
- {
- struct passwd passwd, *pwp;
- char buf[1024];
-
- if (getpwnam_r(IPSEC_USER, &passwd, buf, sizeof(buf), &pwp) != 0 ||
- pwp == NULL || setuid(pwp->pw_uid) != 0)
- {
- plog("unable to change daemon user");
- abort();
- }
- }
-#endif
-#ifdef ANDROID
- if (setuid(AID_VPN) != 0)
- {
- plog("unable to change daemon user");
- abort();
- }
-#endif
-
-#ifdef CAPABILITIES_LIBCAP
- {
- cap_t caps;
- caps = cap_init();
- cap_set_flag(caps, CAP_EFFECTIVE, countof(keep), keep, CAP_SET);
- cap_set_flag(caps, CAP_INHERITABLE, countof(keep), keep, CAP_SET);
- cap_set_flag(caps, CAP_PERMITTED, countof(keep), keep, CAP_SET);
- if (cap_set_proc(caps) != 0)
- {
- plog("unable to drop daemon capabilities");
- abort();
- }
- cap_free(caps);
- }
-#endif /* CAPABILITIES_LIBCAP */
-#ifdef CAPABILITIES_NATIVE
- {
- struct __user_cap_data_struct caps = { .effective = 0 };
- struct __user_cap_header_struct header = {
- .version = _LINUX_CAPABILITY_VERSION,
- };
- int i;
- for (i = 0; i < countof(keep); i++)
- {
- caps.effective |= 1 << keep[i];
- caps.permitted |= 1 << keep[i];
- caps.inheritable |= 1 << keep[i];
- }
- if (capset(&header, &caps) != 0)
- {
- plog("unable to drop daemon capabilities");
- abort();
- }
- }
-#endif /* CAPABILITIES_NATIVE */
-
- /* loading X.509 CA certificates */
- load_authcerts("ca", CA_CERT_PATH, X509_CA);
- /* loading X.509 AA certificates */
- load_authcerts("aa", AA_CERT_PATH, X509_AA);
- /* loading X.509 OCSP certificates */
- load_authcerts("ocsp", OCSP_CERT_PATH, X509_OCSP_SIGNER);
- /* loading X.509 CRLs */
- load_crls();
- /* loading attribute certificates (experimental) */
- ac_load_certs();
-
- lib->processor->set_threads(lib->processor,
- lib->settings->get_int(lib->settings, "pluto.threads",
- DEFAULT_THREADS));
-
- daily_log_event();
- call_server();
- return -1; /* Shouldn't ever reach this */
-}
-
-/* leave pluto, with status.
- * Once child is launched, parent must not exit this way because
- * the lock would be released.
- *
- * 0 OK
- * 1 general discomfort
- * 10 lock file exists
- */
-void exit_pluto(int status)
-{
- lib->processor->set_threads(lib->processor, 0);
- reset_globals(); /* needed because we may be called in odd state */
- free_preshared_secrets();
- free_remembered_public_keys();
- delete_every_connection();
- whack_attribute_finalize(); /* free in-memory pools */
- kernel_finalize();
- fetch_finalize(); /* stop fetching thread */
- free_crl_fetch(); /* free chain of crl fetch requests */
- free_ocsp_fetch(); /* free chain of ocsp fetch requests */
- free_authcerts(); /* free chain of X.509 authority certificates */
- free_crls(); /* free chain of X.509 CRLs */
- free_ca_infos(); /* free chain of X.509 CA information records */
- free_ocsp(); /* free ocsp cache */
- free_ifaces();
- ac_finalize(); /* free X.509 attribute certificates */
- scx_finalize(); /* finalize and unload PKCS #11 module */
-#ifdef ADNS
- stop_adns();
-#endif
- free_md_pool();
- free_crypto();
- free_myid(); /* free myids */
- free_events(); /* free remaining events */
- free_vendorid(); /* free all vendor id records */
- free_builder();
- delete_lock();
- options->destroy(options);
- pluto_deinit();
- lib->credmgr->flush_cache(lib->credmgr, CERT_ANY);
- lib->plugins->unload(lib->plugins);
- libhydra_deinit();
- library_deinit();
- close_log();
- exit(status);
-}
-
-/*
- * Local Variables:
- * c-basic-offset:4
- * c-style: pluto
- * End:
- */
diff --git a/src/pluto/rcv_whack.c b/src/pluto/rcv_whack.c
deleted file mode 100644
index 0a7b33ab5..000000000
--- a/src/pluto/rcv_whack.c
+++ /dev/null
@@ -1,728 +0,0 @@
-/* whack communicating routines
- * Copyright (C) 1997 Angelos D. Keromytis.
- * Copyright (C) 1998-2001 D. Hugh Redelmeier.
- *
- * 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 <stdio.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <resolv.h>
-#include <arpa/nameser.h> /* missing from <resolv.h> on old systems */
-#include <sys/queue.h>
-#include <fcntl.h>
-
-#include <freeswan.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "ca.h"
-#include "certs.h"
-#include "ac.h"
-#include "smartcard.h"
-#include "connections.h"
-#include "foodgroups.h"
-#include "whack.h" /* needs connections.h */
-#include "packet.h"
-#include "demux.h" /* needs packet.h */
-#include "state.h"
-#include "ipsec_doi.h" /* needs demux.h and state.h */
-#include "kernel.h"
-#include "rcv_whack.h"
-#include "log.h"
-#include "keys.h"
-#include "adns.h" /* needs <resolv.h> */
-#include "dnskey.h" /* needs keys.h and adns.h */
-#include "server.h"
-#include "fetch.h"
-#include "ocsp.h"
-#include "crl.h"
-#include "myid.h"
-#include "kernel_alg.h"
-#include "ike_alg.h"
-#include "plugin_list.h"
-#include "whack_attribute.h"
-
-/* helper variables and function to decode strings from whack message */
-
-static char *next_str
- , *str_roof;
-
-static bool unpack_str(char **p)
-{
- char *end = memchr(next_str, '\0', str_roof - next_str);
-
- if (end == NULL)
- {
- return FALSE; /* fishy: no end found */
- }
- else
- {
- *p = next_str == end? NULL : next_str;
- next_str = end + 1;
- return TRUE;
- }
-}
-
-/* bits loading keys from asynchronous DNS */
-
-enum key_add_attempt {
- ka_TXT,
-#ifdef USE_KEYRR
- ka_KEY,
-#endif
- ka_roof /* largest value + 1 */
-};
-
-struct key_add_common {
- int refCount;
- char *diag[ka_roof];
- int whack_fd;
- bool success;
-};
-
-struct key_add_continuation {
- struct adns_continuation ac; /* common prefix */
- struct key_add_common *common; /* common data */
- enum key_add_attempt lookingfor;
-};
-
-static void key_add_ugh(identification_t *keyid, err_t ugh)
-{
- loglog(RC_NOKEY, "failure to fetch key for %'Y' from DNS: %s", keyid, ugh);
-}
-
-/* last one out: turn out the lights */
-static void key_add_merge(struct key_add_common *oc, identification_t *keyid)
-{
- if (oc->refCount == 0)
- {
- enum key_add_attempt kaa;
-
- /* if no success, print all diagnostics */
- if (!oc->success)
- {
- for (kaa = ka_TXT; kaa != ka_roof; kaa++)
- {
- key_add_ugh(keyid, oc->diag[kaa]);
- }
- }
- for (kaa = ka_TXT; kaa != ka_roof; kaa++)
- {
- free(oc->diag[kaa]);
- }
- close(oc->whack_fd);
- free(oc);
- }
-}
-
-#ifdef ADNS
-
-static void key_add_continue(struct adns_continuation *ac, err_t ugh)
-{
- struct key_add_continuation *kc = (void *) ac;
- struct key_add_common *oc = kc->common;
-
- passert(whack_log_fd == NULL_FD);
- whack_log_fd = oc->whack_fd;
-
- if (ugh != NULL)
- {
- oc->diag[kc->lookingfor] = clone_str(ugh);
- }
- else
- {
- oc->success = TRUE;
- transfer_to_public_keys(kc->ac.gateways_from_dns
-#ifdef USE_KEYRR
- , &kc->ac.keys_from_dns
-#endif /* USE_KEYRR */
- );
- }
-
- oc->refCount--;
- key_add_merge(oc, ac->id);
- whack_log_fd = NULL_FD;
-}
-
-#endif /* ADNS */
-
-static void key_add_request(const whack_message_t *msg)
-{
- identification_t *key_id;
-
- key_id = identification_create_from_string(msg->keyid);
-
- if (!msg->whack_addkey)
- {
- delete_public_keys(key_id, msg->pubkey_alg, NULL, chunk_empty);
- }
- if (msg->keyval.len == 0)
- {
- struct key_add_common *oc = malloc_thing(struct key_add_common);
- enum key_add_attempt kaa;
- err_t ugh;
-
- /* initialize state shared by queries */
- oc->refCount = 0;
- oc->whack_fd = dup_any(whack_log_fd);
- oc->success = FALSE;
-
- for (kaa = ka_TXT; kaa != ka_roof; kaa++)
- {
- struct key_add_continuation *kc;
-
- oc->diag[kaa] = NULL;
- oc->refCount++;
- kc = malloc_thing(struct key_add_continuation);
- kc->common = oc;
- kc->lookingfor = kaa;
- ugh = NULL;
-
- switch (kaa)
- {
-#ifdef ADNS
- case ka_TXT:
- ugh = start_adns_query(key_id
- , key_id /* same */
- , T_TXT
- , key_add_continue
- , &kc->ac);
- break;
-#endif /* ADNS */
-#ifdef USE_KEYRR
- case ka_KEY:
- ugh = start_adns_query(key_id
- , NULL
- , T_KEY
- , key_add_continue
- , &kc->ac);
- break;
-#endif /* USE_KEYRR */
- default:
- bad_case(kaa); /* suppress gcc warning */
- }
- if (ugh)
- {
- oc->diag[kaa] = clone_str(ugh);
- oc->refCount--;
- }
- }
-
- /* Done launching queries. Handle total failure case. */
- key_add_merge(oc, key_id);
- }
- else
- {
- if (!add_public_key(key_id, DAL_LOCAL, msg->pubkey_alg, msg->keyval,
- &pubkeys))
- {
- loglog(RC_LOG_SERIOUS, "failed to add public key");
- }
- }
- key_id->destroy(key_id);
-}
-
-/* Handle a kernel request. Supposedly, there's a message in
- * the kernelsock socket.
- */
-void whack_handle(int whackctlfd)
-{
- whack_message_t msg;
- struct sockaddr_un whackaddr;
- int whackaddrlen = sizeof(whackaddr);
- int whackfd = accept(whackctlfd, (struct sockaddr *)&whackaddr, &whackaddrlen);
- /* Note: actual value in n should fit in int. To print, cast to int. */
- ssize_t n;
-
- if (whackfd < 0)
- {
- log_errno((e, "accept() failed in whack_handle()"));
- return;
- }
- if (fcntl(whackfd, F_SETFD, FD_CLOEXEC) < 0)
- {
- log_errno((e, "failed to set CLOEXEC in whack_handle()"));
- close(whackfd);
- return;
- }
-
- n = read(whackfd, &msg, sizeof(msg));
-
- if (n == -1)
- {
- log_errno((e, "read() failed in whack_handle()"));
- close(whackfd);
- return;
- }
-
- whack_log_fd = whackfd;
-
- /* sanity check message */
- {
- err_t ugh = NULL;
-
- next_str = msg.string;
- str_roof = (char *)&msg + n;
-
- if ((size_t)n < offsetof(whack_message_t, whack_shutdown) + sizeof(msg.whack_shutdown))
- {
- ugh = builddiag("ignoring runt message from whack: got %d bytes", (int)n);
- }
- else if (msg.magic != WHACK_MAGIC)
- {
- if (msg.magic == WHACK_BASIC_MAGIC)
- {
- /* Only shutdown command. Simpler inter-version compatibility. */
- if (msg.whack_shutdown)
- {
- plog("shutting down");
- exit_pluto(0); /* delete lock and leave, with 0 status */
- }
- ugh = ""; /* bail early, but without complaint */
- }
- else
- {
- ugh = builddiag("ignoring message from whack with bad magic %d; should be %d; probably wrong version"
- , msg.magic, WHACK_MAGIC);
- }
- }
- else if (next_str > str_roof)
- {
- ugh = builddiag("ignoring truncated message from whack: got %d bytes; expected %u"
- , (int) n, (unsigned) sizeof(msg));
- }
- else if (!unpack_str(&msg.name) /* string 1 */
- || !unpack_str(&msg.left.id) /* string 2 */
- || !unpack_str(&msg.left.cert) /* string 3 */
- || !unpack_str(&msg.left.ca) /* string 4 */
- || !unpack_str(&msg.left.groups) /* string 5 */
- || !unpack_str(&msg.left.updown) /* string 6 */
- || !unpack_str(&msg.left.sourceip) /* string 7 */
- || !unpack_str(&msg.left.virt) /* string 8 */
- || !unpack_str(&msg.right.id) /* string 9 */
- || !unpack_str(&msg.right.cert) /* string 10 */
- || !unpack_str(&msg.right.ca) /* string 11 */
- || !unpack_str(&msg.right.groups) /* string 12 */
- || !unpack_str(&msg.right.updown) /* string 13 */
- || !unpack_str(&msg.right.sourceip) /* string 14 */
- || !unpack_str(&msg.right.virt) /* string 15 */
- || !unpack_str(&msg.keyid) /* string 16 */
- || !unpack_str(&msg.myid) /* string 17 */
- || !unpack_str(&msg.cacert) /* string 18 */
- || !unpack_str(&msg.ldaphost) /* string 19 */
- || !unpack_str(&msg.ldapbase) /* string 20 */
- || !unpack_str(&msg.crluri) /* string 21 */
- || !unpack_str(&msg.crluri2) /* string 22 */
- || !unpack_str(&msg.ocspuri) /* string 23 */
- || !unpack_str(&msg.ike) /* string 24 */
- || !unpack_str(&msg.esp) /* string 25 */
- || !unpack_str(&msg.sc_data) /* string 26 */
- || !unpack_str(&msg.whack_lease_ip) /* string 27 */
- || !unpack_str(&msg.whack_lease_id) /* string 28 */
- || !unpack_str(&msg.xauth_identity) /* string 29 */
- || str_roof - next_str != (ptrdiff_t)msg.keyval.len) /* check chunk */
- {
- ugh = "message from whack contains bad string";
- }
- else
- {
- msg.keyval.ptr = next_str; /* grab chunk */
- }
-
- if (ugh != NULL)
- {
- if (*ugh != '\0')
- loglog(RC_BADWHACKMESSAGE, "%s", ugh);
- whack_log_fd = NULL_FD;
- close(whackfd);
- return;
- }
- }
-
- if (msg.whack_options)
- {
-#ifdef DEBUG
- if (msg.name == NULL)
- {
- /* we do a two-step so that if either old or new would
- * cause the message to print, it will be printed.
- */
- cur_debugging |= msg.debugging;
- DBG(DBG_CONTROL
- , DBG_log("base debugging = %s"
- , bitnamesof(debug_bit_names, msg.debugging)));
- cur_debugging = base_debugging = msg.debugging;
- }
- else if (!msg.whack_connection)
- {
- connection_t *c = con_by_name(msg.name, TRUE);
-
- if (c != NULL)
- {
- c->extra_debugging = msg.debugging;
- DBG(DBG_CONTROL
- , DBG_log("\"%s\" extra_debugging = %s"
- , c->name
- , bitnamesof(debug_bit_names, c->extra_debugging)));
- }
- }
-#endif
- }
-
- if (msg.whack_myid)
- {
- set_myid(MYID_SPECIFIED, msg.myid);
- }
-
- /* Deleting combined with adding a connection works as replace.
- * To make this more useful, in only this combination,
- * delete will silently ignore the lack of the connection.
- */
- if (msg.whack_delete)
- {
- if (msg.whack_ca)
- {
- find_ca_info_by_name(msg.name, TRUE);
- }
- else
- {
- delete_connections_by_name(msg.name, !msg.whack_connection);
- }
- }
-
- if (msg.whack_deletestate)
- {
- struct state *st = state_with_serialno(msg.whack_deletestateno);
-
- if (st == NULL)
- {
- loglog(RC_UNKNOWN_NAME, "no state #%lu to delete"
- , msg.whack_deletestateno);
- }
- else
- {
- delete_state(st);
- }
- }
-
- if (msg.whack_crash)
- {
- delete_states_by_peer(&msg.whack_crash_peer);
- }
-
- if (msg.whack_connection)
- {
- add_connection(&msg);
- }
-
- if (msg.whack_ca && msg.cacert != NULL)
- {
- add_ca_info(&msg);
- }
-
- /* process "listen" before any operation that could require it */
- if (msg.whack_listen)
- {
- close_peerlog(); /* close any open per-peer logs */
- plog("listening for IKE messages");
- listening = TRUE;
- daily_log_reset();
-#ifdef ADNS
- reset_adns_restart_count();
-#endif
- set_myFQDN();
- find_ifaces();
- load_preshared_secrets(NULL_FD);
- load_groups();
- }
- if (msg.whack_unlisten)
- {
- plog("no longer listening for IKE messages");
- listening = FALSE;
- }
-
- if (msg.whack_reread & REREAD_SECRETS)
- {
- load_preshared_secrets(whackfd);
- }
-
- if (msg.whack_reread & REREAD_CACERTS)
- {
- load_authcerts("ca", CA_CERT_PATH, X509_CA);
- }
-
- if (msg.whack_reread & REREAD_AACERTS)
- {
- load_authcerts("aa", AA_CERT_PATH, X509_AA);
- }
-
- if (msg.whack_reread & REREAD_OCSPCERTS)
- {
- load_authcerts("ocsp", OCSP_CERT_PATH, X509_OCSP_SIGNER);
- }
-
- if (msg.whack_reread & REREAD_ACERTS)
- {
- ac_load_certs();
- }
-
- if (msg.whack_reread & REREAD_CRLS)
- {
- load_crls();
- }
-
- if (msg.whack_purgeocsp)
- {
- free_ocsp_fetch();
- free_ocsp_cache();
- }
-
- if (msg.whack_leases)
- {
- list_leases(msg.name, msg.whack_lease_ip, msg.whack_lease_id);
- }
-
- if (msg.whack_list & LIST_PUBKEYS)
- {
- list_public_keys(msg.whack_utc);
- }
-
- if (msg.whack_list & LIST_CERTS)
- {
- cert_list(msg.whack_utc);
- }
-
- if (msg.whack_list & LIST_CACERTS)
- {
- list_authcerts("CA", X509_CA, msg.whack_utc);
- }
-
- if (msg.whack_list & LIST_AACERTS)
- {
- list_authcerts("AA", X509_AA, msg.whack_utc);
- }
-
- if (msg.whack_list & LIST_OCSPCERTS)
- {
- list_authcerts("OCSP", X509_OCSP_SIGNER, msg.whack_utc);
- }
-
- if (msg.whack_list & LIST_ACERTS)
- {
- ac_list_certs(msg.whack_utc);
- }
-
- if (msg.whack_list & LIST_CAINFOS)
- {
- list_ca_infos(msg.whack_utc);
- }
-
- if (msg.whack_list & LIST_CRLS)
- {
- list_crls(msg.whack_utc, strict_crl_policy);
- list_crl_fetch_requests(msg.whack_utc);
- }
-
- if (msg.whack_list & LIST_OCSP)
- {
- list_ocsp_cache(msg.whack_utc, strict_crl_policy);
- list_ocsp_fetch_requests(msg.whack_utc);
- }
-
- if (msg.whack_list & LIST_CARDS)
- {
- scx_list(msg.whack_utc);
- }
-
- if (msg.whack_list & LIST_ALGS)
- {
- ike_alg_list();
- kernel_alg_list();
- }
-
- if (msg.whack_list & LIST_PLUGINS)
- {
- plugin_list();
- }
-
- if (msg.whack_key)
- {
- /* add a public key */
- key_add_request(&msg);
- }
-
- if (msg.whack_route)
- {
- if (!listening)
- {
- whack_log(RC_DEAF, "need --listen before --route");
- }
- if (msg.name == NULL)
- {
- whack_log(RC_UNKNOWN_NAME
- , "whack --route requires a connection name");
- }
- else
- {
- connection_t *c = con_by_name(msg.name, TRUE);
-
- if (c != NULL && c->ikev1)
- {
- set_cur_connection(c);
- if (!oriented(*c))
- {
- whack_log(RC_ORIENT
- , "we have no ipsecN interface for either end of this connection");
- }
- else if (c->policy & POLICY_GROUP)
- {
- route_group(c);
- }
- else if (!trap_connection(c))
- {
- whack_log(RC_ROUTE, "could not route");
- }
- reset_cur_connection();
- }
- }
- }
-
- if (msg.whack_unroute)
- {
- if (msg.name == NULL)
- {
- whack_log(RC_UNKNOWN_NAME
- , "whack --unroute requires a connection name");
- }
- else
- {
- connection_t *c = con_by_name(msg.name, TRUE);
-
- if (c != NULL && c->ikev1)
- {
- struct spd_route *sr;
- int fail = 0;
-
- set_cur_connection(c);
-
- for (sr = &c->spd; sr != NULL; sr = sr->next)
- {
- if (sr->routing >= RT_ROUTED_TUNNEL)
- {
- fail++;
- }
- }
- if (fail > 0)
- {
- whack_log(RC_RTBUSY, "cannot unroute: route busy");
- }
- else if (c->policy & POLICY_GROUP)
- {
- unroute_group(c);
- }
- else
- {
- unroute_connection(c);
- }
- reset_cur_connection();
- }
- }
- }
-
- if (msg.whack_initiate)
- {
- if (!listening)
- {
- whack_log(RC_DEAF, "need --listen before --initiate");
- }
- else if (msg.name == NULL)
- {
- whack_log(RC_UNKNOWN_NAME
- , "whack --initiate requires a connection name");
- }
- else
- {
- initiate_connection(msg.name
- , msg.whack_async? NULL_FD : dup_any(whackfd));
- }
- }
-
- if (msg.whack_oppo_initiate)
- {
- if (!listening)
- {
- whack_log(RC_DEAF, "need --listen before opportunistic initiation");
- }
- else
- {
- initiate_opportunistic(&msg.oppo_my_client, &msg.oppo_peer_client, 0
- , FALSE
- , msg.whack_async? NULL_FD : dup_any(whackfd));
- }
- }
-
- if (msg.whack_terminate)
- {
- if (msg.name == NULL)
- {
- whack_log(RC_UNKNOWN_NAME
- , "whack --terminate requires a connection name");
- }
- else
- {
- terminate_connection(msg.name);
- }
- }
-
- if (msg.whack_status)
- {
- show_status(msg.whack_statusall, msg.name);
- }
-
- if (msg.whack_shutdown)
- {
- plog("shutting down");
- exit_pluto(0); /* delete lock and leave, with 0 status */
- }
-
- if (msg.whack_sc_op != SC_OP_NONE)
- {
- if (pkcs11_proxy)
- {
- scx_op_via_whack(msg.sc_data, msg.inbase, msg.outbase
- , msg.whack_sc_op, msg.keyid, whackfd);
- }
- else
- {
- plog("pkcs11 access to smartcard not allowed (set pkcs11proxy=yes)");
- }
- }
-
- whack_log_fd = NULL_FD;
- close(whackfd);
-}
-
-/*
- * Local Variables:
- * c-basic-offset:4
- * c-style: pluto
- * End:
- */
diff --git a/src/pluto/rcv_whack.h b/src/pluto/rcv_whack.h
deleted file mode 100644
index 66edaaf80..000000000
--- a/src/pluto/rcv_whack.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* whack communicating routines
- * Copyright (C) 1998, 1999 D. Hugh Redelmeier.
- *
- * 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.
- */
-
-extern void whack_handle(int kernelfd);
diff --git a/src/pluto/rsaref/pkcs11.h b/src/pluto/rsaref/pkcs11.h
deleted file mode 100644
index 3283bdc89..000000000
--- a/src/pluto/rsaref/pkcs11.h
+++ /dev/null
@@ -1,299 +0,0 @@
-/* pkcs11.h include file for PKCS #11. */
-/* $Revision: 1.2 $ */
-
-/* License to copy and use this software is granted provided that it is
- * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
- * (Cryptoki)" in all material mentioning or referencing this software.
-
- * License is also granted to make and use derivative works provided that
- * such works are identified as "derived from the RSA Security Inc. PKCS #11
- * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
- * referencing the derived work.
-
- * RSA Security Inc. makes no representations concerning either the
- * merchantability of this software or the suitability of this software for
- * any particular purpose. It is provided "as is" without express or implied
- * warranty of any kind.
- */
-
-#ifndef _PKCS11_H_
-#define _PKCS11_H_ 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Before including this file (pkcs11.h) (or pkcs11t.h by
- * itself), 6 platform-specific macros must be defined. These
- * macros are described below, and typical definitions for them
- * are also given. Be advised that these definitions can depend
- * on both the platform and the compiler used (and possibly also
- * on whether a Cryptoki library is linked statically or
- * dynamically).
- *
- * In addition to defining these 6 macros, the packing convention
- * for Cryptoki structures should be set. The Cryptoki
- * convention on packing is that structures should be 1-byte
- * aligned.
- *
- * If you're using Microsoft Developer Studio 5.0 to produce
- * Win32 stuff, this might be done by using the following
- * preprocessor directive before including pkcs11.h or pkcs11t.h:
- *
- * #pragma pack(push, cryptoki, 1)
- *
- * and using the following preprocessor directive after including
- * pkcs11.h or pkcs11t.h:
- *
- * #pragma pack(pop, cryptoki)
- *
- * If you're using an earlier version of Microsoft Developer
- * Studio to produce Win16 stuff, this might be done by using
- * the following preprocessor directive before including
- * pkcs11.h or pkcs11t.h:
- *
- * #pragma pack(1)
- *
- * In a UNIX environment, you're on your own for this. You might
- * not need to do (or be able to do!) anything.
- *
- *
- * Now for the macros:
- *
- *
- * 1. CK_PTR: The indirection string for making a pointer to an
- * object. It can be used like this:
- *
- * typedef CK_BYTE CK_PTR CK_BYTE_PTR;
- *
- * If you're using Microsoft Developer Studio 5.0 to produce
- * Win32 stuff, it might be defined by:
- *
- * #define CK_PTR *
- *
- * If you're using an earlier version of Microsoft Developer
- * Studio to produce Win16 stuff, it might be defined by:
- *
- * #define CK_PTR far *
- *
- * In a typical UNIX environment, it might be defined by:
- *
- * #define CK_PTR *
- *
- *
- * 2. CK_DEFINE_FUNCTION(returnType, name): A macro which makes
- * an exportable Cryptoki library function definition out of a
- * return type and a function name. It should be used in the
- * following fashion to define the exposed Cryptoki functions in
- * a Cryptoki library:
- *
- * CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(
- * CK_VOID_PTR pReserved
- * )
- * {
- * ...
- * }
- *
- * If you're using Microsoft Developer Studio 5.0 to define a
- * function in a Win32 Cryptoki .dll, it might be defined by:
- *
- * #define CK_DEFINE_FUNCTION(returnType, name) \
- * returnType __declspec(dllexport) name
- *
- * If you're using an earlier version of Microsoft Developer
- * Studio to define a function in a Win16 Cryptoki .dll, it
- * might be defined by:
- *
- * #define CK_DEFINE_FUNCTION(returnType, name) \
- * returnType __export _far _pascal name
- *
- * In a UNIX environment, it might be defined by:
- *
- * #define CK_DEFINE_FUNCTION(returnType, name) \
- * returnType name
- *
- *
- * 3. CK_DECLARE_FUNCTION(returnType, name): A macro which makes
- * an importable Cryptoki library function declaration out of a
- * return type and a function name. It should be used in the
- * following fashion:
- *
- * extern CK_DECLARE_FUNCTION(CK_RV, C_Initialize)(
- * CK_VOID_PTR pReserved
- * );
- *
- * If you're using Microsoft Developer Studio 5.0 to declare a
- * function in a Win32 Cryptoki .dll, it might be defined by:
- *
- * #define CK_DECLARE_FUNCTION(returnType, name) \
- * returnType __declspec(dllimport) name
- *
- * If you're using an earlier version of Microsoft Developer
- * Studio to declare a function in a Win16 Cryptoki .dll, it
- * might be defined by:
- *
- * #define CK_DECLARE_FUNCTION(returnType, name) \
- * returnType __export _far _pascal name
- *
- * In a UNIX environment, it might be defined by:
- *
- * #define CK_DECLARE_FUNCTION(returnType, name) \
- * returnType name
- *
- *
- * 4. CK_DECLARE_FUNCTION_POINTER(returnType, name): A macro
- * which makes a Cryptoki API function pointer declaration or
- * function pointer type declaration out of a return type and a
- * function name. It should be used in the following fashion:
- *
- * // Define funcPtr to be a pointer to a Cryptoki API function
- * // taking arguments args and returning CK_RV.
- * CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtr)(args);
- *
- * or
- *
- * // Define funcPtrType to be the type of a pointer to a
- * // Cryptoki API function taking arguments args and returning
- * // CK_RV, and then define funcPtr to be a variable of type
- * // funcPtrType.
- * typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtrType)(args);
- * funcPtrType funcPtr;
- *
- * If you're using Microsoft Developer Studio 5.0 to access
- * functions in a Win32 Cryptoki .dll, in might be defined by:
- *
- * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
- * returnType __declspec(dllimport) (* name)
- *
- * If you're using an earlier version of Microsoft Developer
- * Studio to access functions in a Win16 Cryptoki .dll, it might
- * be defined by:
- *
- * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
- * returnType __export _far _pascal (* name)
- *
- * In a UNIX environment, it might be defined by:
- *
- * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
- * returnType (* name)
- *
- *
- * 5. CK_CALLBACK_FUNCTION(returnType, name): A macro which makes
- * a function pointer type for an application callback out of
- * a return type for the callback and a name for the callback.
- * It should be used in the following fashion:
- *
- * CK_CALLBACK_FUNCTION(CK_RV, myCallback)(args);
- *
- * to declare a function pointer, myCallback, to a callback
- * which takes arguments args and returns a CK_RV. It can also
- * be used like this:
- *
- * typedef CK_CALLBACK_FUNCTION(CK_RV, myCallbackType)(args);
- * myCallbackType myCallback;
- *
- * If you're using Microsoft Developer Studio 5.0 to do Win32
- * Cryptoki development, it might be defined by:
- *
- * #define CK_CALLBACK_FUNCTION(returnType, name) \
- * returnType (* name)
- *
- * If you're using an earlier version of Microsoft Developer
- * Studio to do Win16 development, it might be defined by:
- *
- * #define CK_CALLBACK_FUNCTION(returnType, name) \
- * returnType _far _pascal (* name)
- *
- * In a UNIX environment, it might be defined by:
- *
- * #define CK_CALLBACK_FUNCTION(returnType, name) \
- * returnType (* name)
- *
- *
- * 6. NULL_PTR: This macro is the value of a NULL pointer.
- *
- * In any ANSI/ISO C environment (and in many others as well),
- * this should best be defined by
- *
- * #ifndef NULL_PTR
- * #define NULL_PTR 0
- * #endif
- */
-
-
-/* All the various Cryptoki types and #define'd values are in the
- * file pkcs11t.h. */
-#include "pkcs11t.h"
-
-#define __PASTE(x,y) x##y
-
-
-/* ==============================================================
- * Define the "extern" form of all the entry points.
- * ==============================================================
- */
-
-#define CK_NEED_ARG_LIST 1
-#define CK_PKCS11_FUNCTION_INFO(name) \
- extern CK_DECLARE_FUNCTION(CK_RV, name)
-
-/* pkcs11f.h has all the information about the Cryptoki
- * function prototypes. */
-#include "pkcs11f.h"
-
-#undef CK_NEED_ARG_LIST
-#undef CK_PKCS11_FUNCTION_INFO
-
-
-/* ==============================================================
- * Define the typedef form of all the entry points. That is, for
- * each Cryptoki function C_XXX, define a type CK_C_XXX which is
- * a pointer to that kind of function.
- * ==============================================================
- */
-
-#define CK_NEED_ARG_LIST 1
-#define CK_PKCS11_FUNCTION_INFO(name) \
- typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, __PASTE(CK_,name))
-
-/* pkcs11f.h has all the information about the Cryptoki
- * function prototypes. */
-#include "pkcs11f.h"
-
-#undef CK_NEED_ARG_LIST
-#undef CK_PKCS11_FUNCTION_INFO
-
-
-/* ==============================================================
- * Define structed vector of entry points. A CK_FUNCTION_LIST
- * contains a CK_VERSION indicating a library's Cryptoki version
- * and then a whole slew of function pointers to the routines in
- * the library. This type was declared, but not defined, in
- * pkcs11t.h.
- * ==============================================================
- */
-
-#define CK_PKCS11_FUNCTION_INFO(name) \
- __PASTE(CK_,name) name;
-
-struct CK_FUNCTION_LIST {
-
- CK_VERSION version; /* Cryptoki version */
-
-/* Pile all the function pointers into the CK_FUNCTION_LIST. */
-/* pkcs11f.h has all the information about the Cryptoki
- * function prototypes. */
-#include "pkcs11f.h"
-
-};
-
-#undef CK_PKCS11_FUNCTION_INFO
-
-
-#undef __PASTE
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/src/pluto/rsaref/pkcs11f.h b/src/pluto/rsaref/pkcs11f.h
deleted file mode 100644
index 54b884aed..000000000
--- a/src/pluto/rsaref/pkcs11f.h
+++ /dev/null
@@ -1,912 +0,0 @@
-/* pkcs11f.h include file for PKCS #11. */
-/* $Revision: 1.2 $ */
-
-/* License to copy and use this software is granted provided that it is
- * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
- * (Cryptoki)" in all material mentioning or referencing this software.
-
- * License is also granted to make and use derivative works provided that
- * such works are identified as "derived from the RSA Security Inc. PKCS #11
- * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
- * referencing the derived work.
-
- * RSA Security Inc. makes no representations concerning either the
- * merchantability of this software or the suitability of this software for
- * any particular purpose. It is provided "as is" without express or implied
- * warranty of any kind.
- */
-
-/* This header file contains pretty much everything about all the */
-/* Cryptoki function prototypes. Because this information is */
-/* used for more than just declaring function prototypes, the */
-/* order of the functions appearing herein is important, and */
-/* should not be altered. */
-
-/* General-purpose */
-
-/* C_Initialize initializes the Cryptoki library. */
-CK_PKCS11_FUNCTION_INFO(C_Initialize)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_VOID_PTR pInitArgs /* if this is not NULL_PTR, it gets
- * cast to CK_C_INITIALIZE_ARGS_PTR
- * and dereferenced */
-);
-#endif
-
-
-/* C_Finalize indicates that an application is done with the
- * Cryptoki library. */
-CK_PKCS11_FUNCTION_INFO(C_Finalize)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_VOID_PTR pReserved /* reserved. Should be NULL_PTR */
-);
-#endif
-
-
-/* C_GetInfo returns general information about Cryptoki. */
-CK_PKCS11_FUNCTION_INFO(C_GetInfo)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_INFO_PTR pInfo /* location that receives information */
-);
-#endif
-
-
-/* C_GetFunctionList returns the function list. */
-CK_PKCS11_FUNCTION_INFO(C_GetFunctionList)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_FUNCTION_LIST_PTR_PTR ppFunctionList /* receives pointer to
- * function list */
-);
-#endif
-
-
-
-/* Slot and token management */
-
-/* C_GetSlotList obtains a list of slots in the system. */
-CK_PKCS11_FUNCTION_INFO(C_GetSlotList)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_BBOOL tokenPresent, /* only slots with tokens? */
- CK_SLOT_ID_PTR pSlotList, /* receives array of slot IDs */
- CK_ULONG_PTR pulCount /* receives number of slots */
-);
-#endif
-
-
-/* C_GetSlotInfo obtains information about a particular slot in
- * the system. */
-CK_PKCS11_FUNCTION_INFO(C_GetSlotInfo)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SLOT_ID slotID, /* the ID of the slot */
- CK_SLOT_INFO_PTR pInfo /* receives the slot information */
-);
-#endif
-
-
-/* C_GetTokenInfo obtains information about a particular token
- * in the system. */
-CK_PKCS11_FUNCTION_INFO(C_GetTokenInfo)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SLOT_ID slotID, /* ID of the token's slot */
- CK_TOKEN_INFO_PTR pInfo /* receives the token information */
-);
-#endif
-
-
-/* C_GetMechanismList obtains a list of mechanism types
- * supported by a token. */
-CK_PKCS11_FUNCTION_INFO(C_GetMechanismList)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SLOT_ID slotID, /* ID of token's slot */
- CK_MECHANISM_TYPE_PTR pMechanismList, /* gets mech. array */
- CK_ULONG_PTR pulCount /* gets # of mechs. */
-);
-#endif
-
-
-/* C_GetMechanismInfo obtains information about a particular
- * mechanism possibly supported by a token. */
-CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SLOT_ID slotID, /* ID of the token's slot */
- CK_MECHANISM_TYPE type, /* type of mechanism */
- CK_MECHANISM_INFO_PTR pInfo /* receives mechanism info */
-);
-#endif
-
-
-/* C_InitToken initializes a token. */
-CK_PKCS11_FUNCTION_INFO(C_InitToken)
-#ifdef CK_NEED_ARG_LIST
-/* pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10 */
-(
- CK_SLOT_ID slotID, /* ID of the token's slot */
- CK_UTF8CHAR_PTR pPin, /* the SO's initial PIN */
- CK_ULONG ulPinLen, /* length in bytes of the PIN */
- CK_UTF8CHAR_PTR pLabel /* 32-byte token label (blank padded) */
-);
-#endif
-
-
-/* C_InitPIN initializes the normal user's PIN. */
-CK_PKCS11_FUNCTION_INFO(C_InitPIN)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_UTF8CHAR_PTR pPin, /* the normal user's PIN */
- CK_ULONG ulPinLen /* length in bytes of the PIN */
-);
-#endif
-
-
-/* C_SetPIN modifies the PIN of the user who is logged in. */
-CK_PKCS11_FUNCTION_INFO(C_SetPIN)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_UTF8CHAR_PTR pOldPin, /* the old PIN */
- CK_ULONG ulOldLen, /* length of the old PIN */
- CK_UTF8CHAR_PTR pNewPin, /* the new PIN */
- CK_ULONG ulNewLen /* length of the new PIN */
-);
-#endif
-
-
-
-/* Session management */
-
-/* C_OpenSession opens a session between an application and a
- * token. */
-CK_PKCS11_FUNCTION_INFO(C_OpenSession)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SLOT_ID slotID, /* the slot's ID */
- CK_FLAGS flags, /* from CK_SESSION_INFO */
- CK_VOID_PTR pApplication, /* passed to callback */
- CK_NOTIFY Notify, /* callback function */
- CK_SESSION_HANDLE_PTR phSession /* gets session handle */
-);
-#endif
-
-
-/* C_CloseSession closes a session between an application and a
- * token. */
-CK_PKCS11_FUNCTION_INFO(C_CloseSession)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession /* the session's handle */
-);
-#endif
-
-
-/* C_CloseAllSessions closes all sessions with a token. */
-CK_PKCS11_FUNCTION_INFO(C_CloseAllSessions)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SLOT_ID slotID /* the token's slot */
-);
-#endif
-
-
-/* C_GetSessionInfo obtains information about the session. */
-CK_PKCS11_FUNCTION_INFO(C_GetSessionInfo)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_SESSION_INFO_PTR pInfo /* receives session info */
-);
-#endif
-
-
-/* C_GetOperationState obtains the state of the cryptographic operation
- * in a session. */
-CK_PKCS11_FUNCTION_INFO(C_GetOperationState)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* session's handle */
- CK_BYTE_PTR pOperationState, /* gets state */
- CK_ULONG_PTR pulOperationStateLen /* gets state length */
-);
-#endif
-
-
-/* C_SetOperationState restores the state of the cryptographic
- * operation in a session. */
-CK_PKCS11_FUNCTION_INFO(C_SetOperationState)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* session's handle */
- CK_BYTE_PTR pOperationState, /* holds state */
- CK_ULONG ulOperationStateLen, /* holds state length */
- CK_OBJECT_HANDLE hEncryptionKey, /* en/decryption key */
- CK_OBJECT_HANDLE hAuthenticationKey /* sign/verify key */
-);
-#endif
-
-
-/* C_Login logs a user into a token. */
-CK_PKCS11_FUNCTION_INFO(C_Login)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_USER_TYPE userType, /* the user type */
- CK_UTF8CHAR_PTR pPin, /* the user's PIN */
- CK_ULONG ulPinLen /* the length of the PIN */
-);
-#endif
-
-
-/* C_Logout logs a user out from a token. */
-CK_PKCS11_FUNCTION_INFO(C_Logout)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession /* the session's handle */
-);
-#endif
-
-
-
-/* Object management */
-
-/* C_CreateObject creates a new object. */
-CK_PKCS11_FUNCTION_INFO(C_CreateObject)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_ATTRIBUTE_PTR pTemplate, /* the object's template */
- CK_ULONG ulCount, /* attributes in template */
- CK_OBJECT_HANDLE_PTR phObject /* gets new object's handle. */
-);
-#endif
-
-
-/* C_CopyObject copies an object, creating a new object for the
- * copy. */
-CK_PKCS11_FUNCTION_INFO(C_CopyObject)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_OBJECT_HANDLE hObject, /* the object's handle */
- CK_ATTRIBUTE_PTR pTemplate, /* template for new object */
- CK_ULONG ulCount, /* attributes in template */
- CK_OBJECT_HANDLE_PTR phNewObject /* receives handle of copy */
-);
-#endif
-
-
-/* C_DestroyObject destroys an object. */
-CK_PKCS11_FUNCTION_INFO(C_DestroyObject)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_OBJECT_HANDLE hObject /* the object's handle */
-);
-#endif
-
-
-/* C_GetObjectSize gets the size of an object in bytes. */
-CK_PKCS11_FUNCTION_INFO(C_GetObjectSize)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_OBJECT_HANDLE hObject, /* the object's handle */
- CK_ULONG_PTR pulSize /* receives size of object */
-);
-#endif
-
-
-/* C_GetAttributeValue obtains the value of one or more object
- * attributes. */
-CK_PKCS11_FUNCTION_INFO(C_GetAttributeValue)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_OBJECT_HANDLE hObject, /* the object's handle */
- CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs; gets vals */
- CK_ULONG ulCount /* attributes in template */
-);
-#endif
-
-
-/* C_SetAttributeValue modifies the value of one or more object
- * attributes */
-CK_PKCS11_FUNCTION_INFO(C_SetAttributeValue)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_OBJECT_HANDLE hObject, /* the object's handle */
- CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs and values */
- CK_ULONG ulCount /* attributes in template */
-);
-#endif
-
-
-/* C_FindObjectsInit initializes a search for token and session
- * objects that match a template. */
-CK_PKCS11_FUNCTION_INFO(C_FindObjectsInit)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_ATTRIBUTE_PTR pTemplate, /* attribute values to match */
- CK_ULONG ulCount /* attrs in search template */
-);
-#endif
-
-
-/* C_FindObjects continues a search for token and session
- * objects that match a template, obtaining additional object
- * handles. */
-CK_PKCS11_FUNCTION_INFO(C_FindObjects)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* session's handle */
- CK_OBJECT_HANDLE_PTR phObject, /* gets obj. handles */
- CK_ULONG ulMaxObjectCount, /* max handles to get */
- CK_ULONG_PTR pulObjectCount /* actual # returned */
-);
-#endif
-
-
-/* C_FindObjectsFinal finishes a search for token and session
- * objects. */
-CK_PKCS11_FUNCTION_INFO(C_FindObjectsFinal)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession /* the session's handle */
-);
-#endif
-
-
-
-/* Encryption and decryption */
-
-/* C_EncryptInit initializes an encryption operation. */
-CK_PKCS11_FUNCTION_INFO(C_EncryptInit)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_MECHANISM_PTR pMechanism, /* the encryption mechanism */
- CK_OBJECT_HANDLE hKey /* handle of encryption key */
-);
-#endif
-
-
-/* C_Encrypt encrypts single-part data. */
-CK_PKCS11_FUNCTION_INFO(C_Encrypt)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* session's handle */
- CK_BYTE_PTR pData, /* the plaintext data */
- CK_ULONG ulDataLen, /* bytes of plaintext */
- CK_BYTE_PTR pEncryptedData, /* gets ciphertext */
- CK_ULONG_PTR pulEncryptedDataLen /* gets c-text size */
-);
-#endif
-
-
-/* C_EncryptUpdate continues a multiple-part encryption
- * operation. */
-CK_PKCS11_FUNCTION_INFO(C_EncryptUpdate)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* session's handle */
- CK_BYTE_PTR pPart, /* the plaintext data */
- CK_ULONG ulPartLen, /* plaintext data len */
- CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
- CK_ULONG_PTR pulEncryptedPartLen /* gets c-text size */
-);
-#endif
-
-
-/* C_EncryptFinal finishes a multiple-part encryption
- * operation. */
-CK_PKCS11_FUNCTION_INFO(C_EncryptFinal)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* session handle */
- CK_BYTE_PTR pLastEncryptedPart, /* last c-text */
- CK_ULONG_PTR pulLastEncryptedPartLen /* gets last size */
-);
-#endif
-
-
-/* C_DecryptInit initializes a decryption operation. */
-CK_PKCS11_FUNCTION_INFO(C_DecryptInit)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_MECHANISM_PTR pMechanism, /* the decryption mechanism */
- CK_OBJECT_HANDLE hKey /* handle of decryption key */
-);
-#endif
-
-
-/* C_Decrypt decrypts encrypted data in a single part. */
-CK_PKCS11_FUNCTION_INFO(C_Decrypt)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* session's handle */
- CK_BYTE_PTR pEncryptedData, /* ciphertext */
- CK_ULONG ulEncryptedDataLen, /* ciphertext length */
- CK_BYTE_PTR pData, /* gets plaintext */
- CK_ULONG_PTR pulDataLen /* gets p-text size */
-);
-#endif
-
-
-/* C_DecryptUpdate continues a multiple-part decryption
- * operation. */
-CK_PKCS11_FUNCTION_INFO(C_DecryptUpdate)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* session's handle */
- CK_BYTE_PTR pEncryptedPart, /* encrypted data */
- CK_ULONG ulEncryptedPartLen, /* input length */
- CK_BYTE_PTR pPart, /* gets plaintext */
- CK_ULONG_PTR pulPartLen /* p-text size */
-);
-#endif
-
-
-/* C_DecryptFinal finishes a multiple-part decryption
- * operation. */
-CK_PKCS11_FUNCTION_INFO(C_DecryptFinal)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_BYTE_PTR pLastPart, /* gets plaintext */
- CK_ULONG_PTR pulLastPartLen /* p-text size */
-);
-#endif
-
-
-
-/* Message digesting */
-
-/* C_DigestInit initializes a message-digesting operation. */
-CK_PKCS11_FUNCTION_INFO(C_DigestInit)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_MECHANISM_PTR pMechanism /* the digesting mechanism */
-);
-#endif
-
-
-/* C_Digest digests data in a single part. */
-CK_PKCS11_FUNCTION_INFO(C_Digest)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_BYTE_PTR pData, /* data to be digested */
- CK_ULONG ulDataLen, /* bytes of data to digest */
- CK_BYTE_PTR pDigest, /* gets the message digest */
- CK_ULONG_PTR pulDigestLen /* gets digest length */
-);
-#endif
-
-
-/* C_DigestUpdate continues a multiple-part message-digesting
- * operation. */
-CK_PKCS11_FUNCTION_INFO(C_DigestUpdate)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_BYTE_PTR pPart, /* data to be digested */
- CK_ULONG ulPartLen /* bytes of data to be digested */
-);
-#endif
-
-
-/* C_DigestKey continues a multi-part message-digesting
- * operation, by digesting the value of a secret key as part of
- * the data already digested. */
-CK_PKCS11_FUNCTION_INFO(C_DigestKey)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_OBJECT_HANDLE hKey /* secret key to digest */
-);
-#endif
-
-
-/* C_DigestFinal finishes a multiple-part message-digesting
- * operation. */
-CK_PKCS11_FUNCTION_INFO(C_DigestFinal)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_BYTE_PTR pDigest, /* gets the message digest */
- CK_ULONG_PTR pulDigestLen /* gets byte count of digest */
-);
-#endif
-
-
-
-/* Signing and MACing */
-
-/* C_SignInit initializes a signature (private key encryption)
- * operation, where the signature is (will be) an appendix to
- * the data, and plaintext cannot be recovered from the
- *signature. */
-CK_PKCS11_FUNCTION_INFO(C_SignInit)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
- CK_OBJECT_HANDLE hKey /* handle of signature key */
-);
-#endif
-
-
-/* C_Sign signs (encrypts with private key) data in a single
- * part, where the signature is (will be) an appendix to the
- * data, and plaintext cannot be recovered from the signature. */
-CK_PKCS11_FUNCTION_INFO(C_Sign)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_BYTE_PTR pData, /* the data to sign */
- CK_ULONG ulDataLen, /* count of bytes to sign */
- CK_BYTE_PTR pSignature, /* gets the signature */
- CK_ULONG_PTR pulSignatureLen /* gets signature length */
-);
-#endif
-
-
-/* C_SignUpdate continues a multiple-part signature operation,
- * where the signature is (will be) an appendix to the data,
- * and plaintext cannot be recovered from the signature. */
-CK_PKCS11_FUNCTION_INFO(C_SignUpdate)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_BYTE_PTR pPart, /* the data to sign */
- CK_ULONG ulPartLen /* count of bytes to sign */
-);
-#endif
-
-
-/* C_SignFinal finishes a multiple-part signature operation,
- * returning the signature. */
-CK_PKCS11_FUNCTION_INFO(C_SignFinal)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_BYTE_PTR pSignature, /* gets the signature */
- CK_ULONG_PTR pulSignatureLen /* gets signature length */
-);
-#endif
-
-
-/* C_SignRecoverInit initializes a signature operation, where
- * the data can be recovered from the signature. */
-CK_PKCS11_FUNCTION_INFO(C_SignRecoverInit)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
- CK_OBJECT_HANDLE hKey /* handle of the signature key */
-);
-#endif
-
-
-/* C_SignRecover signs data in a single operation, where the
- * data can be recovered from the signature. */
-CK_PKCS11_FUNCTION_INFO(C_SignRecover)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_BYTE_PTR pData, /* the data to sign */
- CK_ULONG ulDataLen, /* count of bytes to sign */
- CK_BYTE_PTR pSignature, /* gets the signature */
- CK_ULONG_PTR pulSignatureLen /* gets signature length */
-);
-#endif
-
-
-
-/* Verifying signatures and MACs */
-
-/* C_VerifyInit initializes a verification operation, where the
- * signature is an appendix to the data, and plaintext cannot
- * cannot be recovered from the signature (e.g. DSA). */
-CK_PKCS11_FUNCTION_INFO(C_VerifyInit)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
- CK_OBJECT_HANDLE hKey /* verification key */
-);
-#endif
-
-
-/* C_Verify verifies a signature in a single-part operation,
- * where the signature is an appendix to the data, and plaintext
- * cannot be recovered from the signature. */
-CK_PKCS11_FUNCTION_INFO(C_Verify)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_BYTE_PTR pData, /* signed data */
- CK_ULONG ulDataLen, /* length of signed data */
- CK_BYTE_PTR pSignature, /* signature */
- CK_ULONG ulSignatureLen /* signature length*/
-);
-#endif
-
-
-/* C_VerifyUpdate continues a multiple-part verification
- * operation, where the signature is an appendix to the data,
- * and plaintext cannot be recovered from the signature. */
-CK_PKCS11_FUNCTION_INFO(C_VerifyUpdate)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_BYTE_PTR pPart, /* signed data */
- CK_ULONG ulPartLen /* length of signed data */
-);
-#endif
-
-
-/* C_VerifyFinal finishes a multiple-part verification
- * operation, checking the signature. */
-CK_PKCS11_FUNCTION_INFO(C_VerifyFinal)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_BYTE_PTR pSignature, /* signature to verify */
- CK_ULONG ulSignatureLen /* signature length */
-);
-#endif
-
-
-/* C_VerifyRecoverInit initializes a signature verification
- * operation, where the data is recovered from the signature. */
-CK_PKCS11_FUNCTION_INFO(C_VerifyRecoverInit)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
- CK_OBJECT_HANDLE hKey /* verification key */
-);
-#endif
-
-
-/* C_VerifyRecover verifies a signature in a single-part
- * operation, where the data is recovered from the signature. */
-CK_PKCS11_FUNCTION_INFO(C_VerifyRecover)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_BYTE_PTR pSignature, /* signature to verify */
- CK_ULONG ulSignatureLen, /* signature length */
- CK_BYTE_PTR pData, /* gets signed data */
- CK_ULONG_PTR pulDataLen /* gets signed data len */
-);
-#endif
-
-
-
-/* Dual-function cryptographic operations */
-
-/* C_DigestEncryptUpdate continues a multiple-part digesting
- * and encryption operation. */
-CK_PKCS11_FUNCTION_INFO(C_DigestEncryptUpdate)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* session's handle */
- CK_BYTE_PTR pPart, /* the plaintext data */
- CK_ULONG ulPartLen, /* plaintext length */
- CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
- CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
-);
-#endif
-
-
-/* C_DecryptDigestUpdate continues a multiple-part decryption and
- * digesting operation. */
-CK_PKCS11_FUNCTION_INFO(C_DecryptDigestUpdate)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* session's handle */
- CK_BYTE_PTR pEncryptedPart, /* ciphertext */
- CK_ULONG ulEncryptedPartLen, /* ciphertext length */
- CK_BYTE_PTR pPart, /* gets plaintext */
- CK_ULONG_PTR pulPartLen /* gets plaintext len */
-);
-#endif
-
-
-/* C_SignEncryptUpdate continues a multiple-part signing and
- * encryption operation. */
-CK_PKCS11_FUNCTION_INFO(C_SignEncryptUpdate)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* session's handle */
- CK_BYTE_PTR pPart, /* the plaintext data */
- CK_ULONG ulPartLen, /* plaintext length */
- CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
- CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
-);
-#endif
-
-
-/* C_DecryptVerifyUpdate continues a multiple-part decryption and
- * verify operation. */
-CK_PKCS11_FUNCTION_INFO(C_DecryptVerifyUpdate)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* session's handle */
- CK_BYTE_PTR pEncryptedPart, /* ciphertext */
- CK_ULONG ulEncryptedPartLen, /* ciphertext length */
- CK_BYTE_PTR pPart, /* gets plaintext */
- CK_ULONG_PTR pulPartLen /* gets p-text length */
-);
-#endif
-
-
-
-/* Key management */
-
-/* C_GenerateKey generates a secret key, creating a new key
- * object. */
-CK_PKCS11_FUNCTION_INFO(C_GenerateKey)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_MECHANISM_PTR pMechanism, /* key generation mech. */
- CK_ATTRIBUTE_PTR pTemplate, /* template for new key */
- CK_ULONG ulCount, /* # of attrs in template */
- CK_OBJECT_HANDLE_PTR phKey /* gets handle of new key */
-);
-#endif
-
-
-/* C_GenerateKeyPair generates a public-key/private-key pair,
- * creating new key objects. */
-CK_PKCS11_FUNCTION_INFO(C_GenerateKeyPair)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* session
- * handle */
- CK_MECHANISM_PTR pMechanism, /* key-gen
- * mech. */
- CK_ATTRIBUTE_PTR pPublicKeyTemplate, /* template
- * for pub.
- * key */
- CK_ULONG ulPublicKeyAttributeCount, /* # pub.
- * attrs. */
- CK_ATTRIBUTE_PTR pPrivateKeyTemplate, /* template
- * for priv.
- * key */
- CK_ULONG ulPrivateKeyAttributeCount, /* # priv.
- * attrs. */
- CK_OBJECT_HANDLE_PTR phPublicKey, /* gets pub.
- * key
- * handle */
- CK_OBJECT_HANDLE_PTR phPrivateKey /* gets
- * priv. key
- * handle */
-);
-#endif
-
-
-/* C_WrapKey wraps (i.e., encrypts) a key. */
-CK_PKCS11_FUNCTION_INFO(C_WrapKey)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_MECHANISM_PTR pMechanism, /* the wrapping mechanism */
- CK_OBJECT_HANDLE hWrappingKey, /* wrapping key */
- CK_OBJECT_HANDLE hKey, /* key to be wrapped */
- CK_BYTE_PTR pWrappedKey, /* gets wrapped key */
- CK_ULONG_PTR pulWrappedKeyLen /* gets wrapped key size */
-);
-#endif
-
-
-/* C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new
- * key object. */
-CK_PKCS11_FUNCTION_INFO(C_UnwrapKey)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* session's handle */
- CK_MECHANISM_PTR pMechanism, /* unwrapping mech. */
- CK_OBJECT_HANDLE hUnwrappingKey, /* unwrapping key */
- CK_BYTE_PTR pWrappedKey, /* the wrapped key */
- CK_ULONG ulWrappedKeyLen, /* wrapped key len */
- CK_ATTRIBUTE_PTR pTemplate, /* new key template */
- CK_ULONG ulAttributeCount, /* template length */
- CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
-);
-#endif
-
-
-/* C_DeriveKey derives a key from a base key, creating a new key
- * object. */
-CK_PKCS11_FUNCTION_INFO(C_DeriveKey)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* session's handle */
- CK_MECHANISM_PTR pMechanism, /* key deriv. mech. */
- CK_OBJECT_HANDLE hBaseKey, /* base key */
- CK_ATTRIBUTE_PTR pTemplate, /* new key template */
- CK_ULONG ulAttributeCount, /* template length */
- CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
-);
-#endif
-
-
-
-/* Random number generation */
-
-/* C_SeedRandom mixes additional seed material into the token's
- * random number generator. */
-CK_PKCS11_FUNCTION_INFO(C_SeedRandom)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_BYTE_PTR pSeed, /* the seed material */
- CK_ULONG ulSeedLen /* length of seed material */
-);
-#endif
-
-
-/* C_GenerateRandom generates random data. */
-CK_PKCS11_FUNCTION_INFO(C_GenerateRandom)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_BYTE_PTR RandomData, /* receives the random data */
- CK_ULONG ulRandomLen /* # of bytes to generate */
-);
-#endif
-
-
-
-/* Parallel function management */
-
-/* C_GetFunctionStatus is a legacy function; it obtains an
- * updated status of a function running in parallel with an
- * application. */
-CK_PKCS11_FUNCTION_INFO(C_GetFunctionStatus)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession /* the session's handle */
-);
-#endif
-
-
-/* C_CancelFunction is a legacy function; it cancels a function
- * running in parallel. */
-CK_PKCS11_FUNCTION_INFO(C_CancelFunction)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_SESSION_HANDLE hSession /* the session's handle */
-);
-#endif
-
-
-
-/* Functions added in for Cryptoki Version 2.01 or later */
-
-/* C_WaitForSlotEvent waits for a slot event (token insertion,
- * removal, etc.) to occur. */
-CK_PKCS11_FUNCTION_INFO(C_WaitForSlotEvent)
-#ifdef CK_NEED_ARG_LIST
-(
- CK_FLAGS flags, /* blocking/nonblocking flag */
- CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */
- CK_VOID_PTR pRserved /* reserved. Should be NULL_PTR */
-);
-#endif
diff --git a/src/pluto/rsaref/pkcs11t.h b/src/pluto/rsaref/pkcs11t.h
deleted file mode 100644
index 3da20b215..000000000
--- a/src/pluto/rsaref/pkcs11t.h
+++ /dev/null
@@ -1,1685 +0,0 @@
-/* pkcs11t.h include file for PKCS #11. */
-/* $Revision: 1.2 $ */
-
-/* License to copy and use this software is granted provided that it is
- * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
- * (Cryptoki)" in all material mentioning or referencing this software.
-
- * License is also granted to make and use derivative works provided that
- * such works are identified as "derived from the RSA Security Inc. PKCS #11
- * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
- * referencing the derived work.
-
- * RSA Security Inc. makes no representations concerning either the
- * merchantability of this software or the suitability of this software for
- * any particular purpose. It is provided "as is" without express or implied
- * warranty of any kind.
- */
-
-/* See top of pkcs11.h for information about the macros that
- * must be defined and the structure-packing conventions that
- * must be set before including this file. */
-
-#ifndef _PKCS11T_H_
-#define _PKCS11T_H_ 1
-
-#define CK_TRUE 1
-#define CK_FALSE 0
-
-#ifndef CK_DISABLE_TRUE_FALSE
-#ifndef FALSE
-#define FALSE CK_FALSE
-#endif
-
-#ifndef TRUE
-#define TRUE CK_TRUE
-#endif
-#endif
-
-/* an unsigned 8-bit value */
-typedef unsigned char CK_BYTE;
-
-/* an unsigned 8-bit character */
-typedef CK_BYTE CK_CHAR;
-
-/* an 8-bit UTF-8 character */
-typedef CK_BYTE CK_UTF8CHAR;
-
-/* a BYTE-sized Boolean flag */
-typedef CK_BYTE CK_BBOOL;
-
-/* an unsigned value, at least 32 bits long */
-typedef unsigned long int CK_ULONG;
-
-/* a signed value, the same size as a CK_ULONG */
-/* CK_LONG is new for v2.0 */
-typedef long int CK_LONG;
-
-/* at least 32 bits; each bit is a Boolean flag */
-typedef CK_ULONG CK_FLAGS;
-
-
-/* some special values for certain CK_ULONG variables */
-#define CK_UNAVAILABLE_INFORMATION (~0UL)
-#define CK_EFFECTIVELY_INFINITE 0
-
-
-typedef CK_BYTE CK_PTR CK_BYTE_PTR;
-typedef CK_CHAR CK_PTR CK_CHAR_PTR;
-typedef CK_UTF8CHAR CK_PTR CK_UTF8CHAR_PTR;
-typedef CK_ULONG CK_PTR CK_ULONG_PTR;
-typedef void CK_PTR CK_VOID_PTR;
-
-/* Pointer to a CK_VOID_PTR-- i.e., pointer to pointer to void */
-typedef CK_VOID_PTR CK_PTR CK_VOID_PTR_PTR;
-
-
-/* The following value is always invalid if used as a session */
-/* handle or object handle */
-#define CK_INVALID_HANDLE 0
-
-
-typedef struct CK_VERSION {
- CK_BYTE major; /* integer portion of version number */
- CK_BYTE minor; /* 1/100ths portion of version number */
-} CK_VERSION;
-
-typedef CK_VERSION CK_PTR CK_VERSION_PTR;
-
-
-typedef struct CK_INFO {
- /* manufacturerID and libraryDecription have been changed from
- * CK_CHAR to CK_UTF8CHAR for v2.10 */
- CK_VERSION cryptokiVersion; /* Cryptoki interface ver */
- CK_UTF8CHAR manufacturerID[32]; /* blank padded */
- CK_FLAGS flags; /* must be zero */
-
- /* libraryDescription and libraryVersion are new for v2.0 */
- CK_UTF8CHAR libraryDescription[32]; /* blank padded */
- CK_VERSION libraryVersion; /* version of library */
-} CK_INFO;
-
-typedef CK_INFO CK_PTR CK_INFO_PTR;
-
-
-/* CK_NOTIFICATION enumerates the types of notifications that
- * Cryptoki provides to an application */
-/* CK_NOTIFICATION has been changed from an enum to a CK_ULONG
- * for v2.0 */
-typedef CK_ULONG CK_NOTIFICATION;
-#define CKN_SURRENDER 0
-
-
-typedef CK_ULONG CK_SLOT_ID;
-
-typedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR;
-
-
-/* CK_SLOT_INFO provides information about a slot */
-typedef struct CK_SLOT_INFO {
- /* slotDescription and manufacturerID have been changed from
- * CK_CHAR to CK_UTF8CHAR for v2.10 */
- CK_UTF8CHAR slotDescription[64]; /* blank padded */
- CK_UTF8CHAR manufacturerID[32]; /* blank padded */
- CK_FLAGS flags;
-
- /* hardwareVersion and firmwareVersion are new for v2.0 */
- CK_VERSION hardwareVersion; /* version of hardware */
- CK_VERSION firmwareVersion; /* version of firmware */
-} CK_SLOT_INFO;
-
-/* flags: bit flags that provide capabilities of the slot
- * Bit Flag Mask Meaning
- */
-#define CKF_TOKEN_PRESENT 0x00000001 /* a token is there */
-#define CKF_REMOVABLE_DEVICE 0x00000002 /* removable devices*/
-#define CKF_HW_SLOT 0x00000004 /* hardware slot */
-
-typedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR;
-
-
-/* CK_TOKEN_INFO provides information about a token */
-typedef struct CK_TOKEN_INFO {
- /* label, manufacturerID, and model have been changed from
- * CK_CHAR to CK_UTF8CHAR for v2.10 */
- CK_UTF8CHAR label[32]; /* blank padded */
- CK_UTF8CHAR manufacturerID[32]; /* blank padded */
- CK_UTF8CHAR model[16]; /* blank padded */
- CK_CHAR serialNumber[16]; /* blank padded */
- CK_FLAGS flags; /* see below */
-
- /* ulMaxSessionCount, ulSessionCount, ulMaxRwSessionCount,
- * ulRwSessionCount, ulMaxPinLen, and ulMinPinLen have all been
- * changed from CK_USHORT to CK_ULONG for v2.0 */
- CK_ULONG ulMaxSessionCount; /* max open sessions */
- CK_ULONG ulSessionCount; /* sess. now open */
- CK_ULONG ulMaxRwSessionCount; /* max R/W sessions */
- CK_ULONG ulRwSessionCount; /* R/W sess. now open */
- CK_ULONG ulMaxPinLen; /* in bytes */
- CK_ULONG ulMinPinLen; /* in bytes */
- CK_ULONG ulTotalPublicMemory; /* in bytes */
- CK_ULONG ulFreePublicMemory; /* in bytes */
- CK_ULONG ulTotalPrivateMemory; /* in bytes */
- CK_ULONG ulFreePrivateMemory; /* in bytes */
-
- /* hardwareVersion, firmwareVersion, and time are new for
- * v2.0 */
- CK_VERSION hardwareVersion; /* version of hardware */
- CK_VERSION firmwareVersion; /* version of firmware */
- CK_CHAR utcTime[16]; /* time */
-} CK_TOKEN_INFO;
-
-/* The flags parameter is defined as follows:
- * Bit Flag Mask Meaning
- */
-#define CKF_RNG 0x00000001 /* has random #
- * generator */
-#define CKF_WRITE_PROTECTED 0x00000002 /* token is
- * write-
- * protected */
-#define CKF_LOGIN_REQUIRED 0x00000004 /* user must
- * login */
-#define CKF_USER_PIN_INITIALIZED 0x00000008 /* normal user's
- * PIN is set */
-
-/* CKF_RESTORE_KEY_NOT_NEEDED is new for v2.0. If it is set,
- * that means that *every* time the state of cryptographic
- * operations of a session is successfully saved, all keys
- * needed to continue those operations are stored in the state */
-#define CKF_RESTORE_KEY_NOT_NEEDED 0x00000020
-
-/* CKF_CLOCK_ON_TOKEN is new for v2.0. If it is set, that means
- * that the token has some sort of clock. The time on that
- * clock is returned in the token info structure */
-#define CKF_CLOCK_ON_TOKEN 0x00000040
-
-/* CKF_PROTECTED_AUTHENTICATION_PATH is new for v2.0. If it is
- * set, that means that there is some way for the user to login
- * without sending a PIN through the Cryptoki library itself */
-#define CKF_PROTECTED_AUTHENTICATION_PATH 0x00000100
-
-/* CKF_DUAL_CRYPTO_OPERATIONS is new for v2.0. If it is true,
- * that means that a single session with the token can perform
- * dual simultaneous cryptographic operations (digest and
- * encrypt; decrypt and digest; sign and encrypt; and decrypt
- * and sign) */
-#define CKF_DUAL_CRYPTO_OPERATIONS 0x00000200
-
-/* CKF_TOKEN_INITIALIZED if new for v2.10. If it is true, the
- * token has been initialized using C_InitializeToken or an
- * equivalent mechanism outside the scope of PKCS #11.
- * Calling C_InitializeToken when this flag is set will cause
- * the token to be reinitialized. */
-#define CKF_TOKEN_INITIALIZED 0x00000400
-
-/* CKF_SECONDARY_AUTHENTICATION if new for v2.10. If it is
- * true, the token supports secondary authentication for
- * private key objects. This flag is deprecated in v2.11 and
- onwards. */
-#define CKF_SECONDARY_AUTHENTICATION 0x00000800
-
-/* CKF_USER_PIN_COUNT_LOW if new for v2.10. If it is true, an
- * incorrect user login PIN has been entered at least once
- * since the last successful authentication. */
-#define CKF_USER_PIN_COUNT_LOW 0x00010000
-
-/* CKF_USER_PIN_FINAL_TRY if new for v2.10. If it is true,
- * supplying an incorrect user PIN will it to become locked. */
-#define CKF_USER_PIN_FINAL_TRY 0x00020000
-
-/* CKF_USER_PIN_LOCKED if new for v2.10. If it is true, the
- * user PIN has been locked. User login to the token is not
- * possible. */
-#define CKF_USER_PIN_LOCKED 0x00040000
-
-/* CKF_USER_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
- * the user PIN value is the default value set by token
- * initialization or manufacturing, or the PIN has been
- * expired by the card. */
-#define CKF_USER_PIN_TO_BE_CHANGED 0x00080000
-
-/* CKF_SO_PIN_COUNT_LOW if new for v2.10. If it is true, an
- * incorrect SO login PIN has been entered at least once since
- * the last successful authentication. */
-#define CKF_SO_PIN_COUNT_LOW 0x00100000
-
-/* CKF_SO_PIN_FINAL_TRY if new for v2.10. If it is true,
- * supplying an incorrect SO PIN will it to become locked. */
-#define CKF_SO_PIN_FINAL_TRY 0x00200000
-
-/* CKF_SO_PIN_LOCKED if new for v2.10. If it is true, the SO
- * PIN has been locked. SO login to the token is not possible.
- */
-#define CKF_SO_PIN_LOCKED 0x00400000
-
-/* CKF_SO_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
- * the SO PIN value is the default value set by token
- * initialization or manufacturing, or the PIN has been
- * expired by the card. */
-#define CKF_SO_PIN_TO_BE_CHANGED 0x00800000
-
-typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR;
-
-
-/* CK_SESSION_HANDLE is a Cryptoki-assigned value that
- * identifies a session */
-typedef CK_ULONG CK_SESSION_HANDLE;
-
-typedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR;
-
-
-/* CK_USER_TYPE enumerates the types of Cryptoki users */
-/* CK_USER_TYPE has been changed from an enum to a CK_ULONG for
- * v2.0 */
-typedef CK_ULONG CK_USER_TYPE;
-/* Security Officer */
-#define CKU_SO 0
-/* Normal user */
-#define CKU_USER 1
-/* Context specific (added in v2.20) */
-#define CKU_CONTEXT_SPECIFIC 2
-
-/* CK_STATE enumerates the session states */
-/* CK_STATE has been changed from an enum to a CK_ULONG for
- * v2.0 */
-typedef CK_ULONG CK_STATE;
-#define CKS_RO_PUBLIC_SESSION 0
-#define CKS_RO_USER_FUNCTIONS 1
-#define CKS_RW_PUBLIC_SESSION 2
-#define CKS_RW_USER_FUNCTIONS 3
-#define CKS_RW_SO_FUNCTIONS 4
-
-
-/* CK_SESSION_INFO provides information about a session */
-typedef struct CK_SESSION_INFO {
- CK_SLOT_ID slotID;
- CK_STATE state;
- CK_FLAGS flags; /* see below */
-
- /* ulDeviceError was changed from CK_USHORT to CK_ULONG for
- * v2.0 */
- CK_ULONG ulDeviceError; /* device-dependent error code */
-} CK_SESSION_INFO;
-
-/* The flags are defined in the following table:
- * Bit Flag Mask Meaning
- */
-#define CKF_RW_SESSION 0x00000002 /* session is r/w */
-#define CKF_SERIAL_SESSION 0x00000004 /* no parallel */
-
-typedef CK_SESSION_INFO CK_PTR CK_SESSION_INFO_PTR;
-
-
-/* CK_OBJECT_HANDLE is a token-specific identifier for an
- * object */
-typedef CK_ULONG CK_OBJECT_HANDLE;
-
-typedef CK_OBJECT_HANDLE CK_PTR CK_OBJECT_HANDLE_PTR;
-
-
-/* CK_OBJECT_CLASS is a value that identifies the classes (or
- * types) of objects that Cryptoki recognizes. It is defined
- * as follows: */
-/* CK_OBJECT_CLASS was changed from CK_USHORT to CK_ULONG for
- * v2.0 */
-typedef CK_ULONG CK_OBJECT_CLASS;
-
-/* The following classes of objects are defined: */
-/* CKO_HW_FEATURE is new for v2.10 */
-/* CKO_DOMAIN_PARAMETERS is new for v2.11 */
-/* CKO_MECHANISM is new for v2.20 */
-#define CKO_DATA 0x00000000
-#define CKO_CERTIFICATE 0x00000001
-#define CKO_PUBLIC_KEY 0x00000002
-#define CKO_PRIVATE_KEY 0x00000003
-#define CKO_SECRET_KEY 0x00000004
-#define CKO_HW_FEATURE 0x00000005
-#define CKO_DOMAIN_PARAMETERS 0x00000006
-#define CKO_MECHANISM 0x00000007
-#define CKO_VENDOR_DEFINED 0x80000000
-
-typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR;
-
-/* CK_HW_FEATURE_TYPE is new for v2.10. CK_HW_FEATURE_TYPE is a
- * value that identifies the hardware feature type of an object
- * with CK_OBJECT_CLASS equal to CKO_HW_FEATURE. */
-typedef CK_ULONG CK_HW_FEATURE_TYPE;
-
-/* The following hardware feature types are defined */
-/* CKH_USER_INTERFACE is new for v2.20 */
-#define CKH_MONOTONIC_COUNTER 0x00000001
-#define CKH_CLOCK 0x00000002
-#define CKH_USER_INTERFACE 0x00000003
-#define CKH_VENDOR_DEFINED 0x80000000
-
-/* CK_KEY_TYPE is a value that identifies a key type */
-/* CK_KEY_TYPE was changed from CK_USHORT to CK_ULONG for v2.0 */
-typedef CK_ULONG CK_KEY_TYPE;
-
-/* the following key types are defined: */
-#define CKK_RSA 0x00000000
-#define CKK_DSA 0x00000001
-#define CKK_DH 0x00000002
-
-/* CKK_ECDSA and CKK_KEA are new for v2.0 */
-/* CKK_ECDSA is deprecated in v2.11, CKK_EC is preferred. */
-#define CKK_ECDSA 0x00000003
-#define CKK_EC 0x00000003
-#define CKK_X9_42_DH 0x00000004
-#define CKK_KEA 0x00000005
-
-#define CKK_GENERIC_SECRET 0x00000010
-#define CKK_RC2 0x00000011
-#define CKK_RC4 0x00000012
-#define CKK_DES 0x00000013
-#define CKK_DES2 0x00000014
-#define CKK_DES3 0x00000015
-
-/* all these key types are new for v2.0 */
-#define CKK_CAST 0x00000016
-#define CKK_CAST3 0x00000017
-/* CKK_CAST5 is deprecated in v2.11, CKK_CAST128 is preferred. */
-#define CKK_CAST5 0x00000018
-#define CKK_CAST128 0x00000018
-#define CKK_RC5 0x00000019
-#define CKK_IDEA 0x0000001A
-#define CKK_SKIPJACK 0x0000001B
-#define CKK_BATON 0x0000001C
-#define CKK_JUNIPER 0x0000001D
-#define CKK_CDMF 0x0000001E
-#define CKK_AES 0x0000001F
-
-/* BlowFish and TwoFish are new for v2.20 */
-#define CKK_BLOWFISH 0x00000020
-#define CKK_TWOFISH 0x00000021
-
-#define CKK_VENDOR_DEFINED 0x80000000
-
-
-/* CK_CERTIFICATE_TYPE is a value that identifies a certificate
- * type */
-/* CK_CERTIFICATE_TYPE was changed from CK_USHORT to CK_ULONG
- * for v2.0 */
-typedef CK_ULONG CK_CERTIFICATE_TYPE;
-
-/* The following certificate types are defined: */
-/* CKC_X_509_ATTR_CERT is new for v2.10 */
-/* CKC_WTLS is new for v2.20 */
-#define CKC_X_509 0x00000000
-#define CKC_X_509_ATTR_CERT 0x00000001
-#define CKC_WTLS 0x00000002
-#define CKC_VENDOR_DEFINED 0x80000000
-
-
-/* CK_ATTRIBUTE_TYPE is a value that identifies an attribute
- * type */
-/* CK_ATTRIBUTE_TYPE was changed from CK_USHORT to CK_ULONG for
- * v2.0 */
-typedef CK_ULONG CK_ATTRIBUTE_TYPE;
-
-/* The CKF_ARRAY_ATTRIBUTE flag identifies an attribute which
- consists of an array of values. */
-#define CKF_ARRAY_ATTRIBUTE 0x40000000
-
-/* The following attribute types are defined: */
-#define CKA_CLASS 0x00000000
-#define CKA_TOKEN 0x00000001
-#define CKA_PRIVATE 0x00000002
-#define CKA_LABEL 0x00000003
-#define CKA_APPLICATION 0x00000010
-#define CKA_VALUE 0x00000011
-
-/* CKA_OBJECT_ID is new for v2.10 */
-#define CKA_OBJECT_ID 0x00000012
-
-#define CKA_CERTIFICATE_TYPE 0x00000080
-#define CKA_ISSUER 0x00000081
-#define CKA_SERIAL_NUMBER 0x00000082
-
-/* CKA_AC_ISSUER, CKA_OWNER, and CKA_ATTR_TYPES are new
- * for v2.10 */
-#define CKA_AC_ISSUER 0x00000083
-#define CKA_OWNER 0x00000084
-#define CKA_ATTR_TYPES 0x00000085
-
-/* CKA_TRUSTED is new for v2.11 */
-#define CKA_TRUSTED 0x00000086
-
-/* CKA_CERTIFICATE_CATEGORY ...
- * CKA_CHECK_VALUE are new for v2.20 */
-#define CKA_CERTIFICATE_CATEGORY 0x00000087
-#define CKA_JAVA_MIDP_SECURITY_DOMAIN 0x00000088
-#define CKA_URL 0x00000089
-#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY 0x0000008A
-#define CKA_HASH_OF_ISSUER_PUBLIC_KEY 0x0000008B
-#define CKA_CHECK_VALUE 0x00000090
-
-#define CKA_KEY_TYPE 0x00000100
-#define CKA_SUBJECT 0x00000101
-#define CKA_ID 0x00000102
-#define CKA_SENSITIVE 0x00000103
-#define CKA_ENCRYPT 0x00000104
-#define CKA_DECRYPT 0x00000105
-#define CKA_WRAP 0x00000106
-#define CKA_UNWRAP 0x00000107
-#define CKA_SIGN 0x00000108
-#define CKA_SIGN_RECOVER 0x00000109
-#define CKA_VERIFY 0x0000010A
-#define CKA_VERIFY_RECOVER 0x0000010B
-#define CKA_DERIVE 0x0000010C
-#define CKA_START_DATE 0x00000110
-#define CKA_END_DATE 0x00000111
-#define CKA_MODULUS 0x00000120
-#define CKA_MODULUS_BITS 0x00000121
-#define CKA_PUBLIC_EXPONENT 0x00000122
-#define CKA_PRIVATE_EXPONENT 0x00000123
-#define CKA_PRIME_1 0x00000124
-#define CKA_PRIME_2 0x00000125
-#define CKA_EXPONENT_1 0x00000126
-#define CKA_EXPONENT_2 0x00000127
-#define CKA_COEFFICIENT 0x00000128
-#define CKA_PRIME 0x00000130
-#define CKA_SUBPRIME 0x00000131
-#define CKA_BASE 0x00000132
-
-/* CKA_PRIME_BITS and CKA_SUB_PRIME_BITS are new for v2.11 */
-#define CKA_PRIME_BITS 0x00000133
-#define CKA_SUBPRIME_BITS 0x00000134
-#define CKA_SUB_PRIME_BITS CKA_SUBPRIME_BITS
-/* (To retain backwards-compatibility) */
-
-#define CKA_VALUE_BITS 0x00000160
-#define CKA_VALUE_LEN 0x00000161
-
-/* CKA_EXTRACTABLE, CKA_LOCAL, CKA_NEVER_EXTRACTABLE,
- * CKA_ALWAYS_SENSITIVE, CKA_MODIFIABLE, CKA_ECDSA_PARAMS,
- * and CKA_EC_POINT are new for v2.0 */
-#define CKA_EXTRACTABLE 0x00000162
-#define CKA_LOCAL 0x00000163
-#define CKA_NEVER_EXTRACTABLE 0x00000164
-#define CKA_ALWAYS_SENSITIVE 0x00000165
-
-/* CKA_KEY_GEN_MECHANISM is new for v2.11 */
-#define CKA_KEY_GEN_MECHANISM 0x00000166
-
-#define CKA_MODIFIABLE 0x00000170
-
-/* CKA_ECDSA_PARAMS is deprecated in v2.11,
- * CKA_EC_PARAMS is preferred. */
-#define CKA_ECDSA_PARAMS 0x00000180
-#define CKA_EC_PARAMS 0x00000180
-
-#define CKA_EC_POINT 0x00000181
-
-/* CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS,
- * are new for v2.10. Deprecated in v2.11 and onwards. */
-#define CKA_SECONDARY_AUTH 0x00000200
-#define CKA_AUTH_PIN_FLAGS 0x00000201
-
-/* CKA_ALWAYS_AUTHENTICATE ...
- * CKA_UNWRAP_TEMPLATE are new for v2.20 */
-#define CKA_ALWAYS_AUTHENTICATE 0x00000202
-
-#define CKA_WRAP_WITH_TRUSTED 0x00000210
-#define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000211)
-#define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000212)
-
-/* CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, and CKA_HAS_RESET
- * are new for v2.10 */
-#define CKA_HW_FEATURE_TYPE 0x00000300
-#define CKA_RESET_ON_INIT 0x00000301
-#define CKA_HAS_RESET 0x00000302
-
-/* The following attributes are new for v2.20 */
-#define CKA_PIXEL_X 0x00000400
-#define CKA_PIXEL_Y 0x00000401
-#define CKA_RESOLUTION 0x00000402
-#define CKA_CHAR_ROWS 0x00000403
-#define CKA_CHAR_COLUMNS 0x00000404
-#define CKA_COLOR 0x00000405
-#define CKA_BITS_PER_PIXEL 0x00000406
-#define CKA_CHAR_SETS 0x00000480
-#define CKA_ENCODING_METHODS 0x00000481
-#define CKA_MIME_TYPES 0x00000482
-#define CKA_MECHANISM_TYPE 0x00000500
-#define CKA_REQUIRED_CMS_ATTRIBUTES 0x00000501
-#define CKA_DEFAULT_CMS_ATTRIBUTES 0x00000502
-#define CKA_SUPPORTED_CMS_ATTRIBUTES 0x00000503
-#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE|0x00000600)
-
-#define CKA_VENDOR_DEFINED 0x80000000
-
-
-/* CK_ATTRIBUTE is a structure that includes the type, length
- * and value of an attribute */
-typedef struct CK_ATTRIBUTE {
- CK_ATTRIBUTE_TYPE type;
- CK_VOID_PTR pValue;
-
- /* ulValueLen went from CK_USHORT to CK_ULONG for v2.0 */
- CK_ULONG ulValueLen; /* in bytes */
-} CK_ATTRIBUTE;
-
-typedef CK_ATTRIBUTE CK_PTR CK_ATTRIBUTE_PTR;
-
-
-/* CK_DATE is a structure that defines a date */
-typedef struct CK_DATE{
- CK_CHAR year[4]; /* the year ("1900" - "9999") */
- CK_CHAR month[2]; /* the month ("01" - "12") */
- CK_CHAR day[2]; /* the day ("01" - "31") */
-} CK_DATE;
-
-
-/* CK_MECHANISM_TYPE is a value that identifies a mechanism
- * type */
-/* CK_MECHANISM_TYPE was changed from CK_USHORT to CK_ULONG for
- * v2.0 */
-typedef CK_ULONG CK_MECHANISM_TYPE;
-
-/* the following mechanism types are defined: */
-#define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000000
-#define CKM_RSA_PKCS 0x00000001
-#define CKM_RSA_9796 0x00000002
-#define CKM_RSA_X_509 0x00000003
-
-/* CKM_MD2_RSA_PKCS, CKM_MD5_RSA_PKCS, and CKM_SHA1_RSA_PKCS
- * are new for v2.0. They are mechanisms which hash and sign */
-#define CKM_MD2_RSA_PKCS 0x00000004
-#define CKM_MD5_RSA_PKCS 0x00000005
-#define CKM_SHA1_RSA_PKCS 0x00000006
-
-/* CKM_RIPEMD128_RSA_PKCS, CKM_RIPEMD160_RSA_PKCS, and
- * CKM_RSA_PKCS_OAEP are new for v2.10 */
-#define CKM_RIPEMD128_RSA_PKCS 0x00000007
-#define CKM_RIPEMD160_RSA_PKCS 0x00000008
-#define CKM_RSA_PKCS_OAEP 0x00000009
-
-/* CKM_RSA_X9_31_KEY_PAIR_GEN, CKM_RSA_X9_31, CKM_SHA1_RSA_X9_31,
- * CKM_RSA_PKCS_PSS, and CKM_SHA1_RSA_PKCS_PSS are new for v2.11 */
-#define CKM_RSA_X9_31_KEY_PAIR_GEN 0x0000000A
-#define CKM_RSA_X9_31 0x0000000B
-#define CKM_SHA1_RSA_X9_31 0x0000000C
-#define CKM_RSA_PKCS_PSS 0x0000000D
-#define CKM_SHA1_RSA_PKCS_PSS 0x0000000E
-
-#define CKM_DSA_KEY_PAIR_GEN 0x00000010
-#define CKM_DSA 0x00000011
-#define CKM_DSA_SHA1 0x00000012
-#define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020
-#define CKM_DH_PKCS_DERIVE 0x00000021
-
-/* CKM_X9_42_DH_KEY_PAIR_GEN, CKM_X9_42_DH_DERIVE,
- * CKM_X9_42_DH_HYBRID_DERIVE, and CKM_X9_42_MQV_DERIVE are new for
- * v2.11 */
-#define CKM_X9_42_DH_KEY_PAIR_GEN 0x00000030
-#define CKM_X9_42_DH_DERIVE 0x00000031
-#define CKM_X9_42_DH_HYBRID_DERIVE 0x00000032
-#define CKM_X9_42_MQV_DERIVE 0x00000033
-
-/* CKM_SHA256/384/512 are new for v2.20 */
-#define CKM_SHA256_RSA_PKCS 0x00000040
-#define CKM_SHA384_RSA_PKCS 0x00000041
-#define CKM_SHA512_RSA_PKCS 0x00000042
-#define CKM_SHA256_RSA_PKCS_PSS 0x00000043
-#define CKM_SHA384_RSA_PKCS_PSS 0x00000044
-#define CKM_SHA512_RSA_PKCS_PSS 0x00000045
-
-#define CKM_RC2_KEY_GEN 0x00000100
-#define CKM_RC2_ECB 0x00000101
-#define CKM_RC2_CBC 0x00000102
-#define CKM_RC2_MAC 0x00000103
-
-/* CKM_RC2_MAC_GENERAL and CKM_RC2_CBC_PAD are new for v2.0 */
-#define CKM_RC2_MAC_GENERAL 0x00000104
-#define CKM_RC2_CBC_PAD 0x00000105
-
-#define CKM_RC4_KEY_GEN 0x00000110
-#define CKM_RC4 0x00000111
-#define CKM_DES_KEY_GEN 0x00000120
-#define CKM_DES_ECB 0x00000121
-#define CKM_DES_CBC 0x00000122
-#define CKM_DES_MAC 0x00000123
-
-/* CKM_DES_MAC_GENERAL and CKM_DES_CBC_PAD are new for v2.0 */
-#define CKM_DES_MAC_GENERAL 0x00000124
-#define CKM_DES_CBC_PAD 0x00000125
-
-#define CKM_DES2_KEY_GEN 0x00000130
-#define CKM_DES3_KEY_GEN 0x00000131
-#define CKM_DES3_ECB 0x00000132
-#define CKM_DES3_CBC 0x00000133
-#define CKM_DES3_MAC 0x00000134
-
-/* CKM_DES3_MAC_GENERAL, CKM_DES3_CBC_PAD, CKM_CDMF_KEY_GEN,
- * CKM_CDMF_ECB, CKM_CDMF_CBC, CKM_CDMF_MAC,
- * CKM_CDMF_MAC_GENERAL, and CKM_CDMF_CBC_PAD are new for v2.0 */
-#define CKM_DES3_MAC_GENERAL 0x00000135
-#define CKM_DES3_CBC_PAD 0x00000136
-#define CKM_CDMF_KEY_GEN 0x00000140
-#define CKM_CDMF_ECB 0x00000141
-#define CKM_CDMF_CBC 0x00000142
-#define CKM_CDMF_MAC 0x00000143
-#define CKM_CDMF_MAC_GENERAL 0x00000144
-#define CKM_CDMF_CBC_PAD 0x00000145
-
-/* the following four DES mechanisms are new for v2.20 */
-#define CKM_DES_OFB64 0x00000150
-#define CKM_DES_OFB8 0x00000151
-#define CKM_DES_CFB64 0x00000152
-#define CKM_DES_CFB8 0x00000153
-
-#define CKM_MD2 0x00000200
-
-/* CKM_MD2_HMAC and CKM_MD2_HMAC_GENERAL are new for v2.0 */
-#define CKM_MD2_HMAC 0x00000201
-#define CKM_MD2_HMAC_GENERAL 0x00000202
-
-#define CKM_MD5 0x00000210
-
-/* CKM_MD5_HMAC and CKM_MD5_HMAC_GENERAL are new for v2.0 */
-#define CKM_MD5_HMAC 0x00000211
-#define CKM_MD5_HMAC_GENERAL 0x00000212
-
-#define CKM_SHA_1 0x00000220
-
-/* CKM_SHA_1_HMAC and CKM_SHA_1_HMAC_GENERAL are new for v2.0 */
-#define CKM_SHA_1_HMAC 0x00000221
-#define CKM_SHA_1_HMAC_GENERAL 0x00000222
-
-/* CKM_RIPEMD128, CKM_RIPEMD128_HMAC,
- * CKM_RIPEMD128_HMAC_GENERAL, CKM_RIPEMD160, CKM_RIPEMD160_HMAC,
- * and CKM_RIPEMD160_HMAC_GENERAL are new for v2.10 */
-#define CKM_RIPEMD128 0x00000230
-#define CKM_RIPEMD128_HMAC 0x00000231
-#define CKM_RIPEMD128_HMAC_GENERAL 0x00000232
-#define CKM_RIPEMD160 0x00000240
-#define CKM_RIPEMD160_HMAC 0x00000241
-#define CKM_RIPEMD160_HMAC_GENERAL 0x00000242
-
-/* CKM_SHA256/384/512 are new for v2.20 */
-#define CKM_SHA256 0x00000250
-#define CKM_SHA256_HMAC 0x00000251
-#define CKM_SHA256_HMAC_GENERAL 0x00000252
-#define CKM_SHA384 0x00000260
-#define CKM_SHA384_HMAC 0x00000261
-#define CKM_SHA384_HMAC_GENERAL 0x00000262
-#define CKM_SHA512 0x00000270
-#define CKM_SHA512_HMAC 0x00000271
-#define CKM_SHA512_HMAC_GENERAL 0x00000272
-
-/* All of the following mechanisms are new for v2.0 */
-/* Note that CAST128 and CAST5 are the same algorithm */
-#define CKM_CAST_KEY_GEN 0x00000300
-#define CKM_CAST_ECB 0x00000301
-#define CKM_CAST_CBC 0x00000302
-#define CKM_CAST_MAC 0x00000303
-#define CKM_CAST_MAC_GENERAL 0x00000304
-#define CKM_CAST_CBC_PAD 0x00000305
-#define CKM_CAST3_KEY_GEN 0x00000310
-#define CKM_CAST3_ECB 0x00000311
-#define CKM_CAST3_CBC 0x00000312
-#define CKM_CAST3_MAC 0x00000313
-#define CKM_CAST3_MAC_GENERAL 0x00000314
-#define CKM_CAST3_CBC_PAD 0x00000315
-#define CKM_CAST5_KEY_GEN 0x00000320
-#define CKM_CAST128_KEY_GEN 0x00000320
-#define CKM_CAST5_ECB 0x00000321
-#define CKM_CAST128_ECB 0x00000321
-#define CKM_CAST5_CBC 0x00000322
-#define CKM_CAST128_CBC 0x00000322
-#define CKM_CAST5_MAC 0x00000323
-#define CKM_CAST128_MAC 0x00000323
-#define CKM_CAST5_MAC_GENERAL 0x00000324
-#define CKM_CAST128_MAC_GENERAL 0x00000324
-#define CKM_CAST5_CBC_PAD 0x00000325
-#define CKM_CAST128_CBC_PAD 0x00000325
-#define CKM_RC5_KEY_GEN 0x00000330
-#define CKM_RC5_ECB 0x00000331
-#define CKM_RC5_CBC 0x00000332
-#define CKM_RC5_MAC 0x00000333
-#define CKM_RC5_MAC_GENERAL 0x00000334
-#define CKM_RC5_CBC_PAD 0x00000335
-#define CKM_IDEA_KEY_GEN 0x00000340
-#define CKM_IDEA_ECB 0x00000341
-#define CKM_IDEA_CBC 0x00000342
-#define CKM_IDEA_MAC 0x00000343
-#define CKM_IDEA_MAC_GENERAL 0x00000344
-#define CKM_IDEA_CBC_PAD 0x00000345
-#define CKM_GENERIC_SECRET_KEY_GEN 0x00000350
-#define CKM_CONCATENATE_BASE_AND_KEY 0x00000360
-#define CKM_CONCATENATE_BASE_AND_DATA 0x00000362
-#define CKM_CONCATENATE_DATA_AND_BASE 0x00000363
-#define CKM_XOR_BASE_AND_DATA 0x00000364
-#define CKM_EXTRACT_KEY_FROM_KEY 0x00000365
-#define CKM_SSL3_PRE_MASTER_KEY_GEN 0x00000370
-#define CKM_SSL3_MASTER_KEY_DERIVE 0x00000371
-#define CKM_SSL3_KEY_AND_MAC_DERIVE 0x00000372
-
-/* CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_PRE_MASTER_KEY_GEN,
- * CKM_TLS_MASTER_KEY_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE, and
- * CKM_TLS_MASTER_KEY_DERIVE_DH are new for v2.11 */
-#define CKM_SSL3_MASTER_KEY_DERIVE_DH 0x00000373
-#define CKM_TLS_PRE_MASTER_KEY_GEN 0x00000374
-#define CKM_TLS_MASTER_KEY_DERIVE 0x00000375
-#define CKM_TLS_KEY_AND_MAC_DERIVE 0x00000376
-#define CKM_TLS_MASTER_KEY_DERIVE_DH 0x00000377
-
-/* CKM_TLS_PRF is new for v2.20 */
-#define CKM_TLS_PRF 0x00000378
-
-#define CKM_SSL3_MD5_MAC 0x00000380
-#define CKM_SSL3_SHA1_MAC 0x00000381
-#define CKM_MD5_KEY_DERIVATION 0x00000390
-#define CKM_MD2_KEY_DERIVATION 0x00000391
-#define CKM_SHA1_KEY_DERIVATION 0x00000392
-
-/* CKM_SHA256/384/512 are new for v2.20 */
-#define CKM_SHA256_KEY_DERIVATION 0x00000393
-#define CKM_SHA384_KEY_DERIVATION 0x00000394
-#define CKM_SHA512_KEY_DERIVATION 0x00000395
-
-#define CKM_PBE_MD2_DES_CBC 0x000003A0
-#define CKM_PBE_MD5_DES_CBC 0x000003A1
-#define CKM_PBE_MD5_CAST_CBC 0x000003A2
-#define CKM_PBE_MD5_CAST3_CBC 0x000003A3
-#define CKM_PBE_MD5_CAST5_CBC 0x000003A4
-#define CKM_PBE_MD5_CAST128_CBC 0x000003A4
-#define CKM_PBE_SHA1_CAST5_CBC 0x000003A5
-#define CKM_PBE_SHA1_CAST128_CBC 0x000003A5
-#define CKM_PBE_SHA1_RC4_128 0x000003A6
-#define CKM_PBE_SHA1_RC4_40 0x000003A7
-#define CKM_PBE_SHA1_DES3_EDE_CBC 0x000003A8
-#define CKM_PBE_SHA1_DES2_EDE_CBC 0x000003A9
-#define CKM_PBE_SHA1_RC2_128_CBC 0x000003AA
-#define CKM_PBE_SHA1_RC2_40_CBC 0x000003AB
-
-/* CKM_PKCS5_PBKD2 is new for v2.10 */
-#define CKM_PKCS5_PBKD2 0x000003B0
-
-#define CKM_PBA_SHA1_WITH_SHA1_HMAC 0x000003C0
-
-/* WTLS mechanisms are new for v2.20 */
-#define CKM_WTLS_PRE_MASTER_KEY_GEN 0x000003D0
-#define CKM_WTLS_MASTER_KEY_DERIVE 0x000003D1
-#define CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC 0x000003D2
-#define CKM_WTLS_PRF 0x000003D3
-#define CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE 0x000003D4
-#define CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE 0x000003D5
-
-#define CKM_KEY_WRAP_LYNKS 0x00000400
-#define CKM_KEY_WRAP_SET_OAEP 0x00000401
-
-/* CKM_CMS_SIG is new for v2.20 */
-#define CKM_CMS_SIG 0x00000500
-
-/* Fortezza mechanisms */
-#define CKM_SKIPJACK_KEY_GEN 0x00001000
-#define CKM_SKIPJACK_ECB64 0x00001001
-#define CKM_SKIPJACK_CBC64 0x00001002
-#define CKM_SKIPJACK_OFB64 0x00001003
-#define CKM_SKIPJACK_CFB64 0x00001004
-#define CKM_SKIPJACK_CFB32 0x00001005
-#define CKM_SKIPJACK_CFB16 0x00001006
-#define CKM_SKIPJACK_CFB8 0x00001007
-#define CKM_SKIPJACK_WRAP 0x00001008
-#define CKM_SKIPJACK_PRIVATE_WRAP 0x00001009
-#define CKM_SKIPJACK_RELAYX 0x0000100a
-#define CKM_KEA_KEY_PAIR_GEN 0x00001010
-#define CKM_KEA_KEY_DERIVE 0x00001011
-#define CKM_FORTEZZA_TIMESTAMP 0x00001020
-#define CKM_BATON_KEY_GEN 0x00001030
-#define CKM_BATON_ECB128 0x00001031
-#define CKM_BATON_ECB96 0x00001032
-#define CKM_BATON_CBC128 0x00001033
-#define CKM_BATON_COUNTER 0x00001034
-#define CKM_BATON_SHUFFLE 0x00001035
-#define CKM_BATON_WRAP 0x00001036
-
-/* CKM_ECDSA_KEY_PAIR_GEN is deprecated in v2.11,
- * CKM_EC_KEY_PAIR_GEN is preferred */
-#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040
-#define CKM_EC_KEY_PAIR_GEN 0x00001040
-
-#define CKM_ECDSA 0x00001041
-#define CKM_ECDSA_SHA1 0x00001042
-
-/* CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE, and CKM_ECMQV_DERIVE
- * are new for v2.11 */
-#define CKM_ECDH1_DERIVE 0x00001050
-#define CKM_ECDH1_COFACTOR_DERIVE 0x00001051
-#define CKM_ECMQV_DERIVE 0x00001052
-
-#define CKM_JUNIPER_KEY_GEN 0x00001060
-#define CKM_JUNIPER_ECB128 0x00001061
-#define CKM_JUNIPER_CBC128 0x00001062
-#define CKM_JUNIPER_COUNTER 0x00001063
-#define CKM_JUNIPER_SHUFFLE 0x00001064
-#define CKM_JUNIPER_WRAP 0x00001065
-#define CKM_FASTHASH 0x00001070
-
-/* CKM_AES_KEY_GEN, CKM_AES_ECB, CKM_AES_CBC, CKM_AES_MAC,
- * CKM_AES_MAC_GENERAL, CKM_AES_CBC_PAD, CKM_DSA_PARAMETER_GEN,
- * CKM_DH_PKCS_PARAMETER_GEN, and CKM_X9_42_DH_PARAMETER_GEN are
- * new for v2.11 */
-#define CKM_AES_KEY_GEN 0x00001080
-#define CKM_AES_ECB 0x00001081
-#define CKM_AES_CBC 0x00001082
-#define CKM_AES_MAC 0x00001083
-#define CKM_AES_MAC_GENERAL 0x00001084
-#define CKM_AES_CBC_PAD 0x00001085
-
-/* BlowFish and TwoFish are new for v2.20 */
-#define CKM_BLOWFISH_KEY_GEN 0x00001090
-#define CKM_BLOWFISH_CBC 0x00001091
-#define CKM_TWOFISH_KEY_GEN 0x00001092
-#define CKM_TWOFISH_CBC 0x00001093
-
-
-/* CKM_xxx_ENCRYPT_DATA mechanisms are new for v2.20 */
-#define CKM_DES_ECB_ENCRYPT_DATA 0x00001100
-#define CKM_DES_CBC_ENCRYPT_DATA 0x00001101
-#define CKM_DES3_ECB_ENCRYPT_DATA 0x00001102
-#define CKM_DES3_CBC_ENCRYPT_DATA 0x00001103
-#define CKM_AES_ECB_ENCRYPT_DATA 0x00001104
-#define CKM_AES_CBC_ENCRYPT_DATA 0x00001105
-
-#define CKM_DSA_PARAMETER_GEN 0x00002000
-#define CKM_DH_PKCS_PARAMETER_GEN 0x00002001
-#define CKM_X9_42_DH_PARAMETER_GEN 0x00002002
-
-#define CKM_VENDOR_DEFINED 0x80000000
-
-typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR;
-
-
-/* CK_MECHANISM is a structure that specifies a particular
- * mechanism */
-typedef struct CK_MECHANISM {
- CK_MECHANISM_TYPE mechanism;
- CK_VOID_PTR pParameter;
-
- /* ulParameterLen was changed from CK_USHORT to CK_ULONG for
- * v2.0 */
- CK_ULONG ulParameterLen; /* in bytes */
-} CK_MECHANISM;
-
-typedef CK_MECHANISM CK_PTR CK_MECHANISM_PTR;
-
-
-/* CK_MECHANISM_INFO provides information about a particular
- * mechanism */
-typedef struct CK_MECHANISM_INFO {
- CK_ULONG ulMinKeySize;
- CK_ULONG ulMaxKeySize;
- CK_FLAGS flags;
-} CK_MECHANISM_INFO;
-
-/* The flags are defined as follows:
- * Bit Flag Mask Meaning */
-#define CKF_HW 0x00000001 /* performed by HW */
-
-/* The flags CKF_ENCRYPT, CKF_DECRYPT, CKF_DIGEST, CKF_SIGN,
- * CKG_SIGN_RECOVER, CKF_VERIFY, CKF_VERIFY_RECOVER,
- * CKF_GENERATE, CKF_GENERATE_KEY_PAIR, CKF_WRAP, CKF_UNWRAP,
- * and CKF_DERIVE are new for v2.0. They specify whether or not
- * a mechanism can be used for a particular task */
-#define CKF_ENCRYPT 0x00000100
-#define CKF_DECRYPT 0x00000200
-#define CKF_DIGEST 0x00000400
-#define CKF_SIGN 0x00000800
-#define CKF_SIGN_RECOVER 0x00001000
-#define CKF_VERIFY 0x00002000
-#define CKF_VERIFY_RECOVER 0x00004000
-#define CKF_GENERATE 0x00008000
-#define CKF_GENERATE_KEY_PAIR 0x00010000
-#define CKF_WRAP 0x00020000
-#define CKF_UNWRAP 0x00040000
-#define CKF_DERIVE 0x00080000
-
-/* CKF_EC_F_P, CKF_EC_F_2M, CKF_EC_ECPARAMETERS, CKF_EC_NAMEDCURVE,
- * CKF_EC_UNCOMPRESS, and CKF_EC_COMPRESS are new for v2.11. They
- * describe a token's EC capabilities not available in mechanism
- * information. */
-#define CKF_EC_F_P 0x00100000
-#define CKF_EC_F_2M 0x00200000
-#define CKF_EC_ECPARAMETERS 0x00400000
-#define CKF_EC_NAMEDCURVE 0x00800000
-#define CKF_EC_UNCOMPRESS 0x01000000
-#define CKF_EC_COMPRESS 0x02000000
-
-#define CKF_EXTENSION 0x80000000 /* FALSE for this version */
-
-typedef CK_MECHANISM_INFO CK_PTR CK_MECHANISM_INFO_PTR;
-
-
-/* CK_RV is a value that identifies the return value of a
- * Cryptoki function */
-/* CK_RV was changed from CK_USHORT to CK_ULONG for v2.0 */
-typedef CK_ULONG CK_RV;
-
-#define CKR_OK 0x00000000
-#define CKR_CANCEL 0x00000001
-#define CKR_HOST_MEMORY 0x00000002
-#define CKR_SLOT_ID_INVALID 0x00000003
-
-/* CKR_FLAGS_INVALID was removed for v2.0 */
-
-/* CKR_GENERAL_ERROR and CKR_FUNCTION_FAILED are new for v2.0 */
-#define CKR_GENERAL_ERROR 0x00000005
-#define CKR_FUNCTION_FAILED 0x00000006
-
-/* CKR_ARGUMENTS_BAD, CKR_NO_EVENT, CKR_NEED_TO_CREATE_THREADS,
- * and CKR_CANT_LOCK are new for v2.01 */
-#define CKR_ARGUMENTS_BAD 0x00000007
-#define CKR_NO_EVENT 0x00000008
-#define CKR_NEED_TO_CREATE_THREADS 0x00000009
-#define CKR_CANT_LOCK 0x0000000A
-
-#define CKR_ATTRIBUTE_READ_ONLY 0x00000010
-#define CKR_ATTRIBUTE_SENSITIVE 0x00000011
-#define CKR_ATTRIBUTE_TYPE_INVALID 0x00000012
-#define CKR_ATTRIBUTE_VALUE_INVALID 0x00000013
-#define CKR_DATA_INVALID 0x00000020
-#define CKR_DATA_LEN_RANGE 0x00000021
-#define CKR_DEVICE_ERROR 0x00000030
-#define CKR_DEVICE_MEMORY 0x00000031
-#define CKR_DEVICE_REMOVED 0x00000032
-#define CKR_ENCRYPTED_DATA_INVALID 0x00000040
-#define CKR_ENCRYPTED_DATA_LEN_RANGE 0x00000041
-#define CKR_FUNCTION_CANCELED 0x00000050
-#define CKR_FUNCTION_NOT_PARALLEL 0x00000051
-
-/* CKR_FUNCTION_NOT_SUPPORTED is new for v2.0 */
-#define CKR_FUNCTION_NOT_SUPPORTED 0x00000054
-
-#define CKR_KEY_HANDLE_INVALID 0x00000060
-
-/* CKR_KEY_SENSITIVE was removed for v2.0 */
-
-#define CKR_KEY_SIZE_RANGE 0x00000062
-#define CKR_KEY_TYPE_INCONSISTENT 0x00000063
-
-/* CKR_KEY_NOT_NEEDED, CKR_KEY_CHANGED, CKR_KEY_NEEDED,
- * CKR_KEY_INDIGESTIBLE, CKR_KEY_FUNCTION_NOT_PERMITTED,
- * CKR_KEY_NOT_WRAPPABLE, and CKR_KEY_UNEXTRACTABLE are new for
- * v2.0 */
-#define CKR_KEY_NOT_NEEDED 0x00000064
-#define CKR_KEY_CHANGED 0x00000065
-#define CKR_KEY_NEEDED 0x00000066
-#define CKR_KEY_INDIGESTIBLE 0x00000067
-#define CKR_KEY_FUNCTION_NOT_PERMITTED 0x00000068
-#define CKR_KEY_NOT_WRAPPABLE 0x00000069
-#define CKR_KEY_UNEXTRACTABLE 0x0000006A
-
-#define CKR_MECHANISM_INVALID 0x00000070
-#define CKR_MECHANISM_PARAM_INVALID 0x00000071
-
-/* CKR_OBJECT_CLASS_INCONSISTENT and CKR_OBJECT_CLASS_INVALID
- * were removed for v2.0 */
-#define CKR_OBJECT_HANDLE_INVALID 0x00000082
-#define CKR_OPERATION_ACTIVE 0x00000090
-#define CKR_OPERATION_NOT_INITIALIZED 0x00000091
-#define CKR_PIN_INCORRECT 0x000000A0
-#define CKR_PIN_INVALID 0x000000A1
-#define CKR_PIN_LEN_RANGE 0x000000A2
-
-/* CKR_PIN_EXPIRED and CKR_PIN_LOCKED are new for v2.0 */
-#define CKR_PIN_EXPIRED 0x000000A3
-#define CKR_PIN_LOCKED 0x000000A4
-
-#define CKR_SESSION_CLOSED 0x000000B0
-#define CKR_SESSION_COUNT 0x000000B1
-#define CKR_SESSION_HANDLE_INVALID 0x000000B3
-#define CKR_SESSION_PARALLEL_NOT_SUPPORTED 0x000000B4
-#define CKR_SESSION_READ_ONLY 0x000000B5
-#define CKR_SESSION_EXISTS 0x000000B6
-
-/* CKR_SESSION_READ_ONLY_EXISTS and
- * CKR_SESSION_READ_WRITE_SO_EXISTS are new for v2.0 */
-#define CKR_SESSION_READ_ONLY_EXISTS 0x000000B7
-#define CKR_SESSION_READ_WRITE_SO_EXISTS 0x000000B8
-
-#define CKR_SIGNATURE_INVALID 0x000000C0
-#define CKR_SIGNATURE_LEN_RANGE 0x000000C1
-#define CKR_TEMPLATE_INCOMPLETE 0x000000D0
-#define CKR_TEMPLATE_INCONSISTENT 0x000000D1
-#define CKR_TOKEN_NOT_PRESENT 0x000000E0
-#define CKR_TOKEN_NOT_RECOGNIZED 0x000000E1
-#define CKR_TOKEN_WRITE_PROTECTED 0x000000E2
-#define CKR_UNWRAPPING_KEY_HANDLE_INVALID 0x000000F0
-#define CKR_UNWRAPPING_KEY_SIZE_RANGE 0x000000F1
-#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT 0x000000F2
-#define CKR_USER_ALREADY_LOGGED_IN 0x00000100
-#define CKR_USER_NOT_LOGGED_IN 0x00000101
-#define CKR_USER_PIN_NOT_INITIALIZED 0x00000102
-#define CKR_USER_TYPE_INVALID 0x00000103
-
-/* CKR_USER_ANOTHER_ALREADY_LOGGED_IN and CKR_USER_TOO_MANY_TYPES
- * are new to v2.01 */
-#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN 0x00000104
-#define CKR_USER_TOO_MANY_TYPES 0x00000105
-
-#define CKR_WRAPPED_KEY_INVALID 0x00000110
-#define CKR_WRAPPED_KEY_LEN_RANGE 0x00000112
-#define CKR_WRAPPING_KEY_HANDLE_INVALID 0x00000113
-#define CKR_WRAPPING_KEY_SIZE_RANGE 0x00000114
-#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x00000115
-#define CKR_RANDOM_SEED_NOT_SUPPORTED 0x00000120
-
-/* These are new to v2.0 */
-#define CKR_RANDOM_NO_RNG 0x00000121
-
-/* These are new to v2.11 */
-#define CKR_DOMAIN_PARAMS_INVALID 0x00000130
-
-/* These are new to v2.0 */
-#define CKR_BUFFER_TOO_SMALL 0x00000150
-#define CKR_SAVED_STATE_INVALID 0x00000160
-#define CKR_INFORMATION_SENSITIVE 0x00000170
-#define CKR_STATE_UNSAVEABLE 0x00000180
-
-/* These are new to v2.01 */
-#define CKR_CRYPTOKI_NOT_INITIALIZED 0x00000190
-#define CKR_CRYPTOKI_ALREADY_INITIALIZED 0x00000191
-#define CKR_MUTEX_BAD 0x000001A0
-#define CKR_MUTEX_NOT_LOCKED 0x000001A1
-
-/* This is new to v2.20 */
-#define CKR_FUNCTION_REJECTED 0x00000200
-
-#define CKR_VENDOR_DEFINED 0x80000000
-
-
-/* CK_NOTIFY is an application callback that processes events */
-typedef CK_CALLBACK_FUNCTION(CK_RV, CK_NOTIFY)(
- CK_SESSION_HANDLE hSession, /* the session's handle */
- CK_NOTIFICATION event,
- CK_VOID_PTR pApplication /* passed to C_OpenSession */
-);
-
-
-/* CK_FUNCTION_LIST is a structure holding a Cryptoki spec
- * version and pointers of appropriate types to all the
- * Cryptoki functions */
-/* CK_FUNCTION_LIST is new for v2.0 */
-typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST;
-
-typedef CK_FUNCTION_LIST CK_PTR CK_FUNCTION_LIST_PTR;
-
-typedef CK_FUNCTION_LIST_PTR CK_PTR CK_FUNCTION_LIST_PTR_PTR;
-
-
-/* CK_CREATEMUTEX is an application callback for creating a
- * mutex object */
-typedef CK_CALLBACK_FUNCTION(CK_RV, CK_CREATEMUTEX)(
- CK_VOID_PTR_PTR ppMutex /* location to receive ptr to mutex */
-);
-
-
-/* CK_DESTROYMUTEX is an application callback for destroying a
- * mutex object */
-typedef CK_CALLBACK_FUNCTION(CK_RV, CK_DESTROYMUTEX)(
- CK_VOID_PTR pMutex /* pointer to mutex */
-);
-
-
-/* CK_LOCKMUTEX is an application callback for locking a mutex */
-typedef CK_CALLBACK_FUNCTION(CK_RV, CK_LOCKMUTEX)(
- CK_VOID_PTR pMutex /* pointer to mutex */
-);
-
-
-/* CK_UNLOCKMUTEX is an application callback for unlocking a
- * mutex */
-typedef CK_CALLBACK_FUNCTION(CK_RV, CK_UNLOCKMUTEX)(
- CK_VOID_PTR pMutex /* pointer to mutex */
-);
-
-
-/* CK_C_INITIALIZE_ARGS provides the optional arguments to
- * C_Initialize */
-typedef struct CK_C_INITIALIZE_ARGS {
- CK_CREATEMUTEX CreateMutex;
- CK_DESTROYMUTEX DestroyMutex;
- CK_LOCKMUTEX LockMutex;
- CK_UNLOCKMUTEX UnlockMutex;
- CK_FLAGS flags;
- CK_VOID_PTR pReserved;
-} CK_C_INITIALIZE_ARGS;
-
-/* flags: bit flags that provide capabilities of the slot
- * Bit Flag Mask Meaning
- */
-#define CKF_LIBRARY_CANT_CREATE_OS_THREADS 0x00000001
-#define CKF_OS_LOCKING_OK 0x00000002
-
-typedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR;
-
-
-/* additional flags for parameters to functions */
-
-/* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */
-#define CKF_DONT_BLOCK 1
-
-/* CK_RSA_PKCS_OAEP_MGF_TYPE is new for v2.10.
- * CK_RSA_PKCS_OAEP_MGF_TYPE is used to indicate the Message
- * Generation Function (MGF) applied to a message block when
- * formatting a message block for the PKCS #1 OAEP encryption
- * scheme. */
-typedef CK_ULONG CK_RSA_PKCS_MGF_TYPE;
-
-typedef CK_RSA_PKCS_MGF_TYPE CK_PTR CK_RSA_PKCS_MGF_TYPE_PTR;
-
-/* The following MGFs are defined */
-/* CKG_MGF1_SHA256, CKG_MGF1_SHA384, and CKG_MGF1_SHA512
- * are new for v2.20 */
-#define CKG_MGF1_SHA1 0x00000001
-#define CKG_MGF1_SHA256 0x00000002
-#define CKG_MGF1_SHA384 0x00000003
-#define CKG_MGF1_SHA512 0x00000004
-
-/* CK_RSA_PKCS_OAEP_SOURCE_TYPE is new for v2.10.
- * CK_RSA_PKCS_OAEP_SOURCE_TYPE is used to indicate the source
- * of the encoding parameter when formatting a message block
- * for the PKCS #1 OAEP encryption scheme. */
-typedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE;
-
-typedef CK_RSA_PKCS_OAEP_SOURCE_TYPE CK_PTR CK_RSA_PKCS_OAEP_SOURCE_TYPE_PTR;
-
-/* The following encoding parameter sources are defined */
-#define CKZ_DATA_SPECIFIED 0x00000001
-
-/* CK_RSA_PKCS_OAEP_PARAMS is new for v2.10.
- * CK_RSA_PKCS_OAEP_PARAMS provides the parameters to the
- * CKM_RSA_PKCS_OAEP mechanism. */
-typedef struct CK_RSA_PKCS_OAEP_PARAMS {
- CK_MECHANISM_TYPE hashAlg;
- CK_RSA_PKCS_MGF_TYPE mgf;
- CK_RSA_PKCS_OAEP_SOURCE_TYPE source;
- CK_VOID_PTR pSourceData;
- CK_ULONG ulSourceDataLen;
-} CK_RSA_PKCS_OAEP_PARAMS;
-
-typedef CK_RSA_PKCS_OAEP_PARAMS CK_PTR CK_RSA_PKCS_OAEP_PARAMS_PTR;
-
-/* CK_RSA_PKCS_PSS_PARAMS is new for v2.11.
- * CK_RSA_PKCS_PSS_PARAMS provides the parameters to the
- * CKM_RSA_PKCS_PSS mechanism(s). */
-typedef struct CK_RSA_PKCS_PSS_PARAMS {
- CK_MECHANISM_TYPE hashAlg;
- CK_RSA_PKCS_MGF_TYPE mgf;
- CK_ULONG sLen;
-} CK_RSA_PKCS_PSS_PARAMS;
-
-typedef CK_RSA_PKCS_PSS_PARAMS CK_PTR CK_RSA_PKCS_PSS_PARAMS_PTR;
-
-/* CK_EC_KDF_TYPE is new for v2.11. */
-typedef CK_ULONG CK_EC_KDF_TYPE;
-
-/* The following EC Key Derivation Functions are defined */
-#define CKD_NULL 0x00000001
-#define CKD_SHA1_KDF 0x00000002
-
-/* CK_ECDH1_DERIVE_PARAMS is new for v2.11.
- * CK_ECDH1_DERIVE_PARAMS provides the parameters to the
- * CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE mechanisms,
- * where each party contributes one key pair.
- */
-typedef struct CK_ECDH1_DERIVE_PARAMS {
- CK_EC_KDF_TYPE kdf;
- CK_ULONG ulSharedDataLen;
- CK_BYTE_PTR pSharedData;
- CK_ULONG ulPublicDataLen;
- CK_BYTE_PTR pPublicData;
-} CK_ECDH1_DERIVE_PARAMS;
-
-typedef CK_ECDH1_DERIVE_PARAMS CK_PTR CK_ECDH1_DERIVE_PARAMS_PTR;
-
-
-/* CK_ECDH2_DERIVE_PARAMS is new for v2.11.
- * CK_ECDH2_DERIVE_PARAMS provides the parameters to the
- * CKM_ECMQV_DERIVE mechanism, where each party contributes two key pairs. */
-typedef struct CK_ECDH2_DERIVE_PARAMS {
- CK_EC_KDF_TYPE kdf;
- CK_ULONG ulSharedDataLen;
- CK_BYTE_PTR pSharedData;
- CK_ULONG ulPublicDataLen;
- CK_BYTE_PTR pPublicData;
- CK_ULONG ulPrivateDataLen;
- CK_OBJECT_HANDLE hPrivateData;
- CK_ULONG ulPublicDataLen2;
- CK_BYTE_PTR pPublicData2;
-} CK_ECDH2_DERIVE_PARAMS;
-
-typedef CK_ECDH2_DERIVE_PARAMS CK_PTR CK_ECDH2_DERIVE_PARAMS_PTR;
-
-typedef struct CK_ECMQV_DERIVE_PARAMS {
- CK_EC_KDF_TYPE kdf;
- CK_ULONG ulSharedDataLen;
- CK_BYTE_PTR pSharedData;
- CK_ULONG ulPublicDataLen;
- CK_BYTE_PTR pPublicData;
- CK_ULONG ulPrivateDataLen;
- CK_OBJECT_HANDLE hPrivateData;
- CK_ULONG ulPublicDataLen2;
- CK_BYTE_PTR pPublicData2;
- CK_OBJECT_HANDLE publicKey;
-} CK_ECMQV_DERIVE_PARAMS;
-
-typedef CK_ECMQV_DERIVE_PARAMS CK_PTR CK_ECMQV_DERIVE_PARAMS_PTR;
-
-/* Typedefs and defines for the CKM_X9_42_DH_KEY_PAIR_GEN and the
- * CKM_X9_42_DH_PARAMETER_GEN mechanisms (new for PKCS #11 v2.11) */
-typedef CK_ULONG CK_X9_42_DH_KDF_TYPE;
-typedef CK_X9_42_DH_KDF_TYPE CK_PTR CK_X9_42_DH_KDF_TYPE_PTR;
-
-/* The following X9.42 DH key derivation functions are defined
- (besides CKD_NULL already defined : */
-#define CKD_SHA1_KDF_ASN1 0x00000003
-#define CKD_SHA1_KDF_CONCATENATE 0x00000004
-
-/* CK_X9_42_DH1_DERIVE_PARAMS is new for v2.11.
- * CK_X9_42_DH1_DERIVE_PARAMS provides the parameters to the
- * CKM_X9_42_DH_DERIVE key derivation mechanism, where each party
- * contributes one key pair */
-typedef struct CK_X9_42_DH1_DERIVE_PARAMS {
- CK_X9_42_DH_KDF_TYPE kdf;
- CK_ULONG ulOtherInfoLen;
- CK_BYTE_PTR pOtherInfo;
- CK_ULONG ulPublicDataLen;
- CK_BYTE_PTR pPublicData;
-} CK_X9_42_DH1_DERIVE_PARAMS;
-
-typedef struct CK_X9_42_DH1_DERIVE_PARAMS CK_PTR CK_X9_42_DH1_DERIVE_PARAMS_PTR;
-
-/* CK_X9_42_DH2_DERIVE_PARAMS is new for v2.11.
- * CK_X9_42_DH2_DERIVE_PARAMS provides the parameters to the
- * CKM_X9_42_DH_HYBRID_DERIVE and CKM_X9_42_MQV_DERIVE key derivation
- * mechanisms, where each party contributes two key pairs */
-typedef struct CK_X9_42_DH2_DERIVE_PARAMS {
- CK_X9_42_DH_KDF_TYPE kdf;
- CK_ULONG ulOtherInfoLen;
- CK_BYTE_PTR pOtherInfo;
- CK_ULONG ulPublicDataLen;
- CK_BYTE_PTR pPublicData;
- CK_ULONG ulPrivateDataLen;
- CK_OBJECT_HANDLE hPrivateData;
- CK_ULONG ulPublicDataLen2;
- CK_BYTE_PTR pPublicData2;
-} CK_X9_42_DH2_DERIVE_PARAMS;
-
-typedef CK_X9_42_DH2_DERIVE_PARAMS CK_PTR CK_X9_42_DH2_DERIVE_PARAMS_PTR;
-
-typedef struct CK_X9_42_MQV_DERIVE_PARAMS {
- CK_X9_42_DH_KDF_TYPE kdf;
- CK_ULONG ulOtherInfoLen;
- CK_BYTE_PTR pOtherInfo;
- CK_ULONG ulPublicDataLen;
- CK_BYTE_PTR pPublicData;
- CK_ULONG ulPrivateDataLen;
- CK_OBJECT_HANDLE hPrivateData;
- CK_ULONG ulPublicDataLen2;
- CK_BYTE_PTR pPublicData2;
- CK_OBJECT_HANDLE publicKey;
-} CK_X9_42_MQV_DERIVE_PARAMS;
-
-typedef CK_X9_42_MQV_DERIVE_PARAMS CK_PTR CK_X9_42_MQV_DERIVE_PARAMS_PTR;
-
-/* CK_KEA_DERIVE_PARAMS provides the parameters to the
- * CKM_KEA_DERIVE mechanism */
-/* CK_KEA_DERIVE_PARAMS is new for v2.0 */
-typedef struct CK_KEA_DERIVE_PARAMS {
- CK_BBOOL isSender;
- CK_ULONG ulRandomLen;
- CK_BYTE_PTR pRandomA;
- CK_BYTE_PTR pRandomB;
- CK_ULONG ulPublicDataLen;
- CK_BYTE_PTR pPublicData;
-} CK_KEA_DERIVE_PARAMS;
-
-typedef CK_KEA_DERIVE_PARAMS CK_PTR CK_KEA_DERIVE_PARAMS_PTR;
-
-
-/* CK_RC2_PARAMS provides the parameters to the CKM_RC2_ECB and
- * CKM_RC2_MAC mechanisms. An instance of CK_RC2_PARAMS just
- * holds the effective keysize */
-typedef CK_ULONG CK_RC2_PARAMS;
-
-typedef CK_RC2_PARAMS CK_PTR CK_RC2_PARAMS_PTR;
-
-
-/* CK_RC2_CBC_PARAMS provides the parameters to the CKM_RC2_CBC
- * mechanism */
-typedef struct CK_RC2_CBC_PARAMS {
- /* ulEffectiveBits was changed from CK_USHORT to CK_ULONG for
- * v2.0 */
- CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */
-
- CK_BYTE iv[8]; /* IV for CBC mode */
-} CK_RC2_CBC_PARAMS;
-
-typedef CK_RC2_CBC_PARAMS CK_PTR CK_RC2_CBC_PARAMS_PTR;
-
-
-/* CK_RC2_MAC_GENERAL_PARAMS provides the parameters for the
- * CKM_RC2_MAC_GENERAL mechanism */
-/* CK_RC2_MAC_GENERAL_PARAMS is new for v2.0 */
-typedef struct CK_RC2_MAC_GENERAL_PARAMS {
- CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */
- CK_ULONG ulMacLength; /* Length of MAC in bytes */
-} CK_RC2_MAC_GENERAL_PARAMS;
-
-typedef CK_RC2_MAC_GENERAL_PARAMS CK_PTR \
- CK_RC2_MAC_GENERAL_PARAMS_PTR;
-
-
-/* CK_RC5_PARAMS provides the parameters to the CKM_RC5_ECB and
- * CKM_RC5_MAC mechanisms */
-/* CK_RC5_PARAMS is new for v2.0 */
-typedef struct CK_RC5_PARAMS {
- CK_ULONG ulWordsize; /* wordsize in bits */
- CK_ULONG ulRounds; /* number of rounds */
-} CK_RC5_PARAMS;
-
-typedef CK_RC5_PARAMS CK_PTR CK_RC5_PARAMS_PTR;
-
-
-/* CK_RC5_CBC_PARAMS provides the parameters to the CKM_RC5_CBC
- * mechanism */
-/* CK_RC5_CBC_PARAMS is new for v2.0 */
-typedef struct CK_RC5_CBC_PARAMS {
- CK_ULONG ulWordsize; /* wordsize in bits */
- CK_ULONG ulRounds; /* number of rounds */
- CK_BYTE_PTR pIv; /* pointer to IV */
- CK_ULONG ulIvLen; /* length of IV in bytes */
-} CK_RC5_CBC_PARAMS;
-
-typedef CK_RC5_CBC_PARAMS CK_PTR CK_RC5_CBC_PARAMS_PTR;
-
-
-/* CK_RC5_MAC_GENERAL_PARAMS provides the parameters for the
- * CKM_RC5_MAC_GENERAL mechanism */
-/* CK_RC5_MAC_GENERAL_PARAMS is new for v2.0 */
-typedef struct CK_RC5_MAC_GENERAL_PARAMS {
- CK_ULONG ulWordsize; /* wordsize in bits */
- CK_ULONG ulRounds; /* number of rounds */
- CK_ULONG ulMacLength; /* Length of MAC in bytes */
-} CK_RC5_MAC_GENERAL_PARAMS;
-
-typedef CK_RC5_MAC_GENERAL_PARAMS CK_PTR \
- CK_RC5_MAC_GENERAL_PARAMS_PTR;
-
-
-/* CK_MAC_GENERAL_PARAMS provides the parameters to most block
- * ciphers' MAC_GENERAL mechanisms. Its value is the length of
- * the MAC */
-/* CK_MAC_GENERAL_PARAMS is new for v2.0 */
-typedef CK_ULONG CK_MAC_GENERAL_PARAMS;
-
-typedef CK_MAC_GENERAL_PARAMS CK_PTR CK_MAC_GENERAL_PARAMS_PTR;
-
-/* CK_DES/AES_ECB/CBC_ENCRYPT_DATA_PARAMS are new for v2.20 */
-typedef struct CK_DES_CBC_ENCRYPT_DATA_PARAMS {
- CK_BYTE iv[8];
- CK_BYTE_PTR pData;
- CK_ULONG length;
-} CK_DES_CBC_ENCRYPT_DATA_PARAMS;
-
-typedef CK_DES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR;
-
-typedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS {
- CK_BYTE iv[16];
- CK_BYTE_PTR pData;
- CK_ULONG length;
-} CK_AES_CBC_ENCRYPT_DATA_PARAMS;
-
-typedef CK_AES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR;
-
-/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS provides the parameters to the
- * CKM_SKIPJACK_PRIVATE_WRAP mechanism */
-/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS is new for v2.0 */
-typedef struct CK_SKIPJACK_PRIVATE_WRAP_PARAMS {
- CK_ULONG ulPasswordLen;
- CK_BYTE_PTR pPassword;
- CK_ULONG ulPublicDataLen;
- CK_BYTE_PTR pPublicData;
- CK_ULONG ulPAndGLen;
- CK_ULONG ulQLen;
- CK_ULONG ulRandomLen;
- CK_BYTE_PTR pRandomA;
- CK_BYTE_PTR pPrimeP;
- CK_BYTE_PTR pBaseG;
- CK_BYTE_PTR pSubprimeQ;
-} CK_SKIPJACK_PRIVATE_WRAP_PARAMS;
-
-typedef CK_SKIPJACK_PRIVATE_WRAP_PARAMS CK_PTR \
- CK_SKIPJACK_PRIVATE_WRAP_PTR;
-
-
-/* CK_SKIPJACK_RELAYX_PARAMS provides the parameters to the
- * CKM_SKIPJACK_RELAYX mechanism */
-/* CK_SKIPJACK_RELAYX_PARAMS is new for v2.0 */
-typedef struct CK_SKIPJACK_RELAYX_PARAMS {
- CK_ULONG ulOldWrappedXLen;
- CK_BYTE_PTR pOldWrappedX;
- CK_ULONG ulOldPasswordLen;
- CK_BYTE_PTR pOldPassword;
- CK_ULONG ulOldPublicDataLen;
- CK_BYTE_PTR pOldPublicData;
- CK_ULONG ulOldRandomLen;
- CK_BYTE_PTR pOldRandomA;
- CK_ULONG ulNewPasswordLen;
- CK_BYTE_PTR pNewPassword;
- CK_ULONG ulNewPublicDataLen;
- CK_BYTE_PTR pNewPublicData;
- CK_ULONG ulNewRandomLen;
- CK_BYTE_PTR pNewRandomA;
-} CK_SKIPJACK_RELAYX_PARAMS;
-
-typedef CK_SKIPJACK_RELAYX_PARAMS CK_PTR \
- CK_SKIPJACK_RELAYX_PARAMS_PTR;
-
-
-typedef struct CK_PBE_PARAMS {
- CK_BYTE_PTR pInitVector;
- CK_UTF8CHAR_PTR pPassword;
- CK_ULONG ulPasswordLen;
- CK_BYTE_PTR pSalt;
- CK_ULONG ulSaltLen;
- CK_ULONG ulIteration;
-} CK_PBE_PARAMS;
-
-typedef CK_PBE_PARAMS CK_PTR CK_PBE_PARAMS_PTR;
-
-
-/* CK_KEY_WRAP_SET_OAEP_PARAMS provides the parameters to the
- * CKM_KEY_WRAP_SET_OAEP mechanism */
-/* CK_KEY_WRAP_SET_OAEP_PARAMS is new for v2.0 */
-typedef struct CK_KEY_WRAP_SET_OAEP_PARAMS {
- CK_BYTE bBC; /* block contents byte */
- CK_BYTE_PTR pX; /* extra data */
- CK_ULONG ulXLen; /* length of extra data in bytes */
-} CK_KEY_WRAP_SET_OAEP_PARAMS;
-
-typedef CK_KEY_WRAP_SET_OAEP_PARAMS CK_PTR \
- CK_KEY_WRAP_SET_OAEP_PARAMS_PTR;
-
-
-typedef struct CK_SSL3_RANDOM_DATA {
- CK_BYTE_PTR pClientRandom;
- CK_ULONG ulClientRandomLen;
- CK_BYTE_PTR pServerRandom;
- CK_ULONG ulServerRandomLen;
-} CK_SSL3_RANDOM_DATA;
-
-
-typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS {
- CK_SSL3_RANDOM_DATA RandomInfo;
- CK_VERSION_PTR pVersion;
-} CK_SSL3_MASTER_KEY_DERIVE_PARAMS;
-
-typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS CK_PTR \
- CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR;
-
-
-typedef struct CK_SSL3_KEY_MAT_OUT {
- CK_OBJECT_HANDLE hClientMacSecret;
- CK_OBJECT_HANDLE hServerMacSecret;
- CK_OBJECT_HANDLE hClientKey;
- CK_OBJECT_HANDLE hServerKey;
- CK_BYTE_PTR pIVClient;
- CK_BYTE_PTR pIVServer;
-} CK_SSL3_KEY_MAT_OUT;
-
-typedef CK_SSL3_KEY_MAT_OUT CK_PTR CK_SSL3_KEY_MAT_OUT_PTR;
-
-
-typedef struct CK_SSL3_KEY_MAT_PARAMS {
- CK_ULONG ulMacSizeInBits;
- CK_ULONG ulKeySizeInBits;
- CK_ULONG ulIVSizeInBits;
- CK_BBOOL bIsExport;
- CK_SSL3_RANDOM_DATA RandomInfo;
- CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
-} CK_SSL3_KEY_MAT_PARAMS;
-
-typedef CK_SSL3_KEY_MAT_PARAMS CK_PTR CK_SSL3_KEY_MAT_PARAMS_PTR;
-
-/* CK_TLS_PRF_PARAMS is new for version 2.20 */
-typedef struct CK_TLS_PRF_PARAMS {
- CK_BYTE_PTR pSeed;
- CK_ULONG ulSeedLen;
- CK_BYTE_PTR pLabel;
- CK_ULONG ulLabelLen;
- CK_BYTE_PTR pOutput;
- CK_ULONG_PTR pulOutputLen;
-} CK_TLS_PRF_PARAMS;
-
-typedef CK_TLS_PRF_PARAMS CK_PTR CK_TLS_PRF_PARAMS_PTR;
-
-/* WTLS is new for version 2.20 */
-typedef struct CK_WTLS_RANDOM_DATA {
- CK_BYTE_PTR pClientRandom;
- CK_ULONG ulClientRandomLen;
- CK_BYTE_PTR pServerRandom;
- CK_ULONG ulServerRandomLen;
-} CK_WTLS_RANDOM_DATA;
-
-typedef CK_WTLS_RANDOM_DATA CK_PTR CK_WTLS_RANDOM_DATA_PTR;
-
-typedef struct CK_WTLS_MASTER_KEY_DERIVE_PARAMS {
- CK_MECHANISM_TYPE DigestMechanism;
- CK_WTLS_RANDOM_DATA RandomInfo;
- CK_BYTE_PTR pVersion;
-} CK_WTLS_MASTER_KEY_DERIVE_PARAMS;
-
-typedef CK_WTLS_MASTER_KEY_DERIVE_PARAMS CK_PTR \
- CK_WTLS_MASTER_KEY_DERIVE_PARAMS_PTR;
-
-typedef struct CK_WTLS_PRF_PARAMS {
- CK_MECHANISM_TYPE DigestMechanism;
- CK_BYTE_PTR pSeed;
- CK_ULONG ulSeedLen;
- CK_BYTE_PTR pLabel;
- CK_ULONG ulLabelLen;
- CK_BYTE_PTR pOutput;
- CK_ULONG_PTR pulOutputLen;
-} CK_WTLS_PRF_PARAMS;
-
-typedef CK_WTLS_PRF_PARAMS CK_PTR CK_WTLS_PRF_PARAMS_PTR;
-
-typedef struct CK_WTLS_KEY_MAT_OUT {
- CK_OBJECT_HANDLE hMacSecret;
- CK_OBJECT_HANDLE hKey;
- CK_BYTE_PTR pIV;
-} CK_WTLS_KEY_MAT_OUT;
-
-typedef CK_WTLS_KEY_MAT_OUT CK_PTR CK_WTLS_KEY_MAT_OUT_PTR;
-
-typedef struct CK_WTLS_KEY_MAT_PARAMS {
- CK_MECHANISM_TYPE DigestMechanism;
- CK_ULONG ulMacSizeInBits;
- CK_ULONG ulKeySizeInBits;
- CK_ULONG ulIVSizeInBits;
- CK_ULONG ulSequenceNumber;
- CK_BBOOL bIsExport;
- CK_WTLS_RANDOM_DATA RandomInfo;
- CK_WTLS_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
-} CK_WTLS_KEY_MAT_PARAMS;
-
-typedef CK_WTLS_KEY_MAT_PARAMS CK_PTR CK_WTLS_KEY_MAT_PARAMS_PTR;
-
-/* CMS is new for version 2.20 */
-typedef struct CK_CMS_SIG_PARAMS {
- CK_OBJECT_HANDLE certificateHandle;
- CK_MECHANISM_PTR pSigningMechanism;
- CK_MECHANISM_PTR pDigestMechanism;
- CK_UTF8CHAR_PTR pContentType;
- CK_BYTE_PTR pRequestedAttributes;
- CK_ULONG ulRequestedAttributesLen;
- CK_BYTE_PTR pRequiredAttributes;
- CK_ULONG ulRequiredAttributesLen;
-} CK_CMS_SIG_PARAMS;
-
-typedef CK_CMS_SIG_PARAMS CK_PTR CK_CMS_SIG_PARAMS_PTR;
-
-typedef struct CK_KEY_DERIVATION_STRING_DATA {
- CK_BYTE_PTR pData;
- CK_ULONG ulLen;
-} CK_KEY_DERIVATION_STRING_DATA;
-
-typedef CK_KEY_DERIVATION_STRING_DATA CK_PTR \
- CK_KEY_DERIVATION_STRING_DATA_PTR;
-
-
-/* The CK_EXTRACT_PARAMS is used for the
- * CKM_EXTRACT_KEY_FROM_KEY mechanism. It specifies which bit
- * of the base key should be used as the first bit of the
- * derived key */
-/* CK_EXTRACT_PARAMS is new for v2.0 */
-typedef CK_ULONG CK_EXTRACT_PARAMS;
-
-typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR;
-
-/* CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is new for v2.10.
- * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is used to
- * indicate the Pseudo-Random Function (PRF) used to generate
- * key bits using PKCS #5 PBKDF2. */
-typedef CK_ULONG CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE;
-
-typedef CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE CK_PTR CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE_PTR;
-
-/* The following PRFs are defined in PKCS #5 v2.0. */
-#define CKP_PKCS5_PBKD2_HMAC_SHA1 0x00000001
-
-
-/* CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is new for v2.10.
- * CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is used to indicate the
- * source of the salt value when deriving a key using PKCS #5
- * PBKDF2. */
-typedef CK_ULONG CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE;
-
-typedef CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE CK_PTR CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE_PTR;
-
-/* The following salt value sources are defined in PKCS #5 v2.0. */
-#define CKZ_SALT_SPECIFIED 0x00000001
-
-/* CK_PKCS5_PBKD2_PARAMS is new for v2.10.
- * CK_PKCS5_PBKD2_PARAMS is a structure that provides the
- * parameters to the CKM_PKCS5_PBKD2 mechanism. */
-typedef struct CK_PKCS5_PBKD2_PARAMS {
- CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource;
- CK_VOID_PTR pSaltSourceData;
- CK_ULONG ulSaltSourceDataLen;
- CK_ULONG iterations;
- CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf;
- CK_VOID_PTR pPrfData;
- CK_ULONG ulPrfDataLen;
- CK_UTF8CHAR_PTR pPassword;
- CK_ULONG_PTR ulPasswordLen;
-} CK_PKCS5_PBKD2_PARAMS;
-
-typedef CK_PKCS5_PBKD2_PARAMS CK_PTR CK_PKCS5_PBKD2_PARAMS_PTR;
-
-#endif
diff --git a/src/pluto/rsaref/unix.h b/src/pluto/rsaref/unix.h
deleted file mode 100644
index 2e7eb6663..000000000
--- a/src/pluto/rsaref/unix.h
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-#ifndef UNIX_H
-#define UNIX_H
-
-#define CK_PTR *
-
-#define CK_DEFINE_FUNCTION(returnType, name) \
- returnType name
-
-#define CK_DECLARE_FUNCTION(returnType, name) \
- returnType name
-
-#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
- returnType (* name)
-
-#define CK_CALLBACK_FUNCTION(returnType, name) \
- returnType (* name)
-
-#ifndef NULL_PTR
-#define NULL_PTR 0
-#endif
-
-#endif
diff --git a/src/pluto/server.c b/src/pluto/server.c
deleted file mode 100644
index 167b1d4c7..000000000
--- a/src/pluto/server.c
+++ /dev/null
@@ -1,910 +0,0 @@
-/* get-next-event loop
- * Copyright (C) 1997 Angelos D. Keromytis.
- * Copyright (C) 1998-2002 D. Hugh Redelmeier.
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include <errno.h>
-#include <signal.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#ifdef SOLARIS
-# include <sys/sockio.h> /* for Solaris 2.6: defines SIOCGIFCONF */
-#endif
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/time.h>
-#include <netdb.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <net/if.h>
-#include <sys/ioctl.h>
-#include <resolv.h>
-#include <arpa/nameser.h> /* missing from <resolv.h> on old systems */
-#include <sys/queue.h>
-
-#include <freeswan.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "state.h"
-#include "connections.h"
-#include "kernel.h"
-#include "log.h"
-#include "server.h"
-#include "timer.h"
-#include "packet.h"
-#include "demux.h" /* needs packet.h */
-#include "rcv_whack.h"
-#include "keys.h"
-#include "adns.h" /* needs <resolv.h> */
-#include "dnskey.h" /* needs keys.h and adns.h */
-#include "whack.h" /* for RC_LOG_SERIOUS */
-#include "pluto.h"
-
-#include <pfkeyv2.h>
-#include <pfkey.h>
-#include "kameipsec.h"
-#include "nat_traversal.h"
-
-/*
- * Server main loop and socket initialization routines.
- */
-
-static const int on = TRUE; /* by-reference parameter; constant, we hope */
-
-/* control (whack) socket */
-int ctl_fd = NULL_FD; /* file descriptor of control (whack) socket */
-struct sockaddr_un ctl_addr = { AF_UNIX, DEFAULT_CTLBASE CTL_SUFFIX };
-
-/* info (showpolicy) socket */
-int policy_fd = NULL_FD;
-struct sockaddr_un info_addr= { AF_UNIX, DEFAULT_CTLBASE INFO_SUFFIX };
-
-/* Initialize the control socket.
- * Note: this is called very early, so little infrastructure is available.
- * It is important that the socket is created before the original
- * Pluto process returns.
- */
-err_t
-init_ctl_socket(void)
-{
- err_t failed = NULL;
-
- delete_ctl_socket(); /* preventative medicine */
- ctl_fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (ctl_fd == -1)
- failed = "create";
- else if (fcntl(ctl_fd, F_SETFD, FD_CLOEXEC) == -1)
- failed = "fcntl FD+CLOEXEC";
- else if (setsockopt(ctl_fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof(on)) < 0)
- failed = "setsockopt";
- else
- {
- /* to keep control socket secure, use umask */
- mode_t ou = umask(~S_IRWXU);
-
- if (bind(ctl_fd, (struct sockaddr *)&ctl_addr
- , offsetof(struct sockaddr_un, sun_path) + strlen(ctl_addr.sun_path)) < 0)
- failed = "bind";
- umask(ou);
- }
-
- /* 5 is a haphazardly chosen limit for the backlog.
- * Rumour has it that this is the max on BSD systems.
- */
- if (failed == NULL && listen(ctl_fd, 5) < 0)
- failed = "listen() on";
-
- return failed == NULL? NULL : builddiag("could not %s control socket: %d %s"
- , failed, errno, strerror(errno));
-}
-
-void
-delete_ctl_socket(void)
-{
- /* Is noting failure useful? Not when used as preventative medicine. */
- unlink(ctl_addr.sun_path);
-}
-
-bool listening = FALSE; /* should we pay attention to IKE messages? */
-
-struct iface *interfaces = NULL; /* public interfaces */
-
-/* Initialize the interface sockets. */
-
-static void
-mark_ifaces_dead(void)
-{
- struct iface *p;
-
- for (p = interfaces; p != NULL; p = p->next)
- p->change = IFN_DELETE;
-}
-
-static void
-free_dead_ifaces(void)
-{
- struct iface *p;
- bool some_dead = FALSE
- , some_new = FALSE;
-
- for (p = interfaces; p != NULL; p = p->next)
- {
- if (p->change == IFN_DELETE)
- {
- plog("shutting down interface %s/%s %s"
- , p->vname, p->rname, ip_str(&p->addr));
- some_dead = TRUE;
- }
- else if (p->change == IFN_ADD)
- {
- some_new = TRUE;
- }
- }
-
- if (some_dead)
- {
- struct iface **pp;
-
- release_dead_interfaces();
- for (pp = &interfaces; (p = *pp) != NULL; )
- {
- if (p->change == IFN_DELETE)
- {
- *pp = p->next; /* advance *pp */
- free(p->vname);
- free(p->rname);
- close(p->fd);
- free(p);
- }
- else
- {
- pp = &p->next; /* advance pp */
- }
- }
- }
-
- /* this must be done after the release_dead_interfaces
- * in case some to the newly unoriented connections can
- * become oriented here.
- */
- if (some_dead || some_new)
- check_orientations();
-}
-
-void
-free_ifaces(void)
-{
- mark_ifaces_dead();
- free_dead_ifaces();
-}
-
-struct raw_iface {
- ip_address addr;
- char name[IFNAMSIZ + 20]; /* what would be a safe size? */
- struct raw_iface *next;
-};
-
-/* Called to handle --interface <ifname>
- * Semantics: if specified, only these (real) interfaces are considered.
- */
-static const char *pluto_ifn[10];
-static int pluto_ifn_roof = 0;
-
-bool
-use_interface(const char *rifn)
-{
- if (pluto_ifn_roof >= (int)countof(pluto_ifn))
- {
- return FALSE;
- }
- else
- {
- pluto_ifn[pluto_ifn_roof++] = rifn;
- return TRUE;
- }
-}
-
-static struct raw_iface *
-find_raw_ifaces4(void)
-{
- int j; /* index into buf */
- struct ifconf ifconf;
- struct ifreq buf[300]; /* for list of interfaces -- arbitrary limit */
- struct raw_iface *rifaces = NULL;
- int master_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); /* Get a UDP socket */
-
- /* get list of interfaces with assigned IPv4 addresses from system */
-
- if (master_sock == -1)
- exit_log_errno((e, "socket() failed in find_raw_ifaces4()"));
-
- if (setsockopt(master_sock, SOL_SOCKET, SO_REUSEADDR
- , (const void *)&on, sizeof(on)) < 0)
- exit_log_errno((e, "setsockopt() in find_raw_ifaces4()"));
-
- /* bind the socket */
- {
- ip_address any;
-
- happy(anyaddr(AF_INET, &any));
- setportof(htons(pluto_port), &any);
- if (bind(master_sock, sockaddrof(&any), sockaddrlenof(&any)) < 0)
- exit_log_errno((e, "bind() failed in find_raw_ifaces4()"));
- }
-
- /* Get local interfaces. See netdevice(7). */
- ifconf.ifc_len = sizeof(buf);
- ifconf.ifc_buf = (void *) buf;
- zero(buf);
-
- if (ioctl(master_sock, SIOCGIFCONF, &ifconf) == -1)
- exit_log_errno((e, "ioctl(SIOCGIFCONF) in find_raw_ifaces4()"));
-
- /* Add an entry to rifaces for each interesting interface. */
- for (j = 0; (j+1) * sizeof(*buf) <= (size_t)ifconf.ifc_len; j++)
- {
- struct raw_iface ri;
- const struct sockaddr_in *rs = (struct sockaddr_in *) &buf[j].ifr_addr;
- struct ifreq auxinfo;
-
- /* ignore all but AF_INET interfaces */
- if (rs->sin_family != AF_INET)
- continue; /* not interesting */
-
- /* build a NUL-terminated copy of the rname field */
- memcpy(ri.name, buf[j].ifr_name, IFNAMSIZ);
- ri.name[IFNAMSIZ] = '\0';
-
- /* ignore if our interface names were specified, and this isn't one */
- if (pluto_ifn_roof != 0)
- {
- int i;
-
- for (i = 0; i != pluto_ifn_roof; i++)
- if (streq(ri.name, pluto_ifn[i]))
- break;
- if (i == pluto_ifn_roof)
- continue; /* not found -- skip */
- }
-
- /* Find out stuff about this interface. See netdevice(7). */
- zero(&auxinfo); /* paranoia */
- memcpy(auxinfo.ifr_name, buf[j].ifr_name, IFNAMSIZ);
- if (ioctl(master_sock, SIOCGIFFLAGS, &auxinfo) == -1)
- exit_log_errno((e
- , "ioctl(SIOCGIFFLAGS) for %s in find_raw_ifaces4()"
- , ri.name));
- if (!(auxinfo.ifr_flags & IFF_UP))
- continue; /* ignore an interface that isn't UP */
-
- /* ignore unconfigured interfaces */
- if (rs->sin_addr.s_addr == 0)
- continue;
-
- happy(initaddr((const void *)&rs->sin_addr, sizeof(struct in_addr)
- , AF_INET, &ri.addr));
-
- DBG(DBG_CONTROL, DBG_log("found %s with address %s"
- , ri.name, ip_str(&ri.addr)));
- ri.next = rifaces;
- rifaces = clone_thing(ri);
- }
-
- close(master_sock);
-
- return rifaces;
-}
-
-static struct raw_iface *
-find_raw_ifaces6(void)
-{
-
- /* Get list of interfaces with IPv6 addresses from system from /proc/net/if_inet6).
- *
- * Documentation of format?
- * RTFS: linux-2.2.16/net/ipv6/addrconf.c:iface_proc_info()
- * linux-2.4.9-13/net/ipv6/addrconf.c:iface_proc_info()
- *
- * Sample from Gerhard's laptop:
- * 00000000000000000000000000000001 01 80 10 80 lo
- * 30490009000000000000000000010002 02 40 00 80 ipsec0
- * 30490009000000000000000000010002 07 40 00 80 eth0
- * fe80000000000000025004fffefd5484 02 0a 20 80 ipsec0
- * fe80000000000000025004fffefd5484 07 0a 20 80 eth0
- *
- * Each line contains:
- * - IPv6 address: 16 bytes, in hex, no punctuation
- * - ifindex: 1 byte, in hex
- * - prefix_len: 1 byte, in hex
- * - scope (e.g. global, link local): 1 byte, in hex
- * - flags: 1 byte, in hex
- * - device name: string, followed by '\n'
- */
- struct raw_iface *rifaces = NULL;
- static const char proc_name[] = "/proc/net/if_inet6";
- FILE *proc_sock = fopen(proc_name, "r");
-
- if (proc_sock == NULL)
- {
- DBG(DBG_CONTROL, DBG_log("could not open %s", proc_name));
- }
- else
- {
- for (;;)
- {
- struct raw_iface ri;
- unsigned short xb[8]; /* IPv6 address as 8 16-bit chunks */
- char sb[8*5]; /* IPv6 address as string-with-colons */
- unsigned int if_idx; /* proc field, not used */
- unsigned int plen; /* proc field, not used */
- unsigned int scope; /* proc field, used to exclude link-local */
- unsigned int dad_status; /* proc field, not used */
- /* ??? I hate and distrust scanf -- DHR */
- int r = fscanf(proc_sock
- , "%4hx%4hx%4hx%4hx%4hx%4hx%4hx%4hx"
- " %02x %02x %02x %02x %20s\n"
- , xb+0, xb+1, xb+2, xb+3, xb+4, xb+5, xb+6, xb+7
- , &if_idx, &plen, &scope, &dad_status, ri.name);
-
- /* ??? we should diagnose any problems */
- if (r != 13)
- break;
-
- /* ignore addresses with link local scope.
- * From linux-2.4.9-13/include/net/ipv6.h:
- * IPV6_ADDR_LINKLOCAL 0x0020U
- * IPV6_ADDR_SCOPE_MASK 0x00f0U
- */
- if ((scope & 0x00f0U) == 0x0020U)
- continue;
-
- snprintf(sb, sizeof(sb)
- , "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"
- , xb[0], xb[1], xb[2], xb[3], xb[4], xb[5], xb[6], xb[7]);
-
- happy(ttoaddr(sb, 0, AF_INET6, &ri.addr));
-
- if (!isunspecaddr(&ri.addr))
- {
- DBG(DBG_CONTROL
- , DBG_log("found %s with address %s"
- , ri.name, sb));
- ri.next = rifaces;
- rifaces = clone_thing(ri);
- }
- }
- fclose(proc_sock);
- }
-
- return rifaces;
-}
-
-static int
-create_socket(struct raw_iface *ifp, const char *v_name, int port)
-{
- int fd = socket(addrtypeof(&ifp->addr), SOCK_DGRAM, IPPROTO_UDP);
- int fcntl_flags;
-
- if (fd < 0)
- {
- log_errno((e, "socket() in process_raw_ifaces()"));
- return -1;
- }
-
- /* Set socket Nonblocking */
- if ((fcntl_flags=fcntl(fd, F_GETFL)) >= 0) {
- if (!(fcntl_flags & O_NONBLOCK)) {
- fcntl_flags |= O_NONBLOCK;
- fcntl(fd, F_SETFL, fcntl_flags);
- }
- }
-
- if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
- {
- log_errno((e, "fcntl(,, FD_CLOEXEC) in process_raw_ifaces()"));
- close(fd);
- return -1;
- }
-
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR
- , (const void *)&on, sizeof(on)) < 0)
- {
- log_errno((e, "setsockopt SO_REUSEADDR in process_raw_ifaces()"));
- close(fd);
- return -1;
- }
-
- /* To improve error reporting. See ip(7). */
-#if defined(IP_RECVERR) && defined(MSG_ERRQUEUE)
- if (setsockopt(fd, SOL_IP, IP_RECVERR
- , (const void *)&on, sizeof(on)) < 0)
- {
- log_errno((e, "setsockopt IP_RECVERR in process_raw_ifaces()"));
- close(fd);
- return -1;
- }
-#endif
-
- /* With IPv6, there is no fragmentation after
- * it leaves our interface. PMTU discovery
- * is mandatory but doesn't work well with IKE (why?).
- * So we must set the IPV6_USE_MIN_MTU option.
- * See draft-ietf-ipngwg-rfc2292bis-01.txt 11.1
- */
-#ifdef IPV6_USE_MIN_MTU /* YUCK: not always defined */
- if (addrtypeof(&ifp->addr) == AF_INET6
- && setsockopt(fd, SOL_SOCKET, IPV6_USE_MIN_MTU
- , (const void *)&on, sizeof(on)) < 0)
- {
- log_errno((e, "setsockopt IPV6_USE_MIN_MTU in process_raw_ifaces()"));
- close(fd);
- return -1;
- }
-#endif
-
- {
- struct sadb_x_policy policy;
- int level, opt;
-
- policy.sadb_x_policy_len = sizeof(policy) / IPSEC_PFKEYv2_ALIGN;
- policy.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
- policy.sadb_x_policy_type = IPSEC_POLICY_BYPASS;
- policy.sadb_x_policy_dir = IPSEC_DIR_INBOUND;
- policy.sadb_x_policy_reserved = 0;
- policy.sadb_x_policy_id = 0;
- policy.sadb_x_policy_reserved2 = 0;
-
- if (addrtypeof(&ifp->addr) == AF_INET6)
- {
- level = IPPROTO_IPV6;
- opt = IPV6_IPSEC_POLICY;
- }
- else
- {
- level = IPPROTO_IP;
- opt = IP_IPSEC_POLICY;
- }
-
- if (setsockopt(fd, level, opt
- , &policy, sizeof(policy)) < 0)
- {
- log_errno((e, "setsockopt IPSEC_POLICY in process_raw_ifaces()"));
- close(fd);
- return -1;
- }
-
- policy.sadb_x_policy_dir = IPSEC_DIR_OUTBOUND;
-
- if (setsockopt(fd, level, opt
- , &policy, sizeof(policy)) < 0)
- {
- log_errno((e, "setsockopt IPSEC_POLICY in process_raw_ifaces()"));
- close(fd);
- return -1;
- }
- }
-
- setportof(htons(port), &ifp->addr);
- if (bind(fd, sockaddrof(&ifp->addr), sockaddrlenof(&ifp->addr)) < 0)
- {
- log_errno((e, "bind() for %s/%s %s:%u in process_raw_ifaces()"
- , ifp->name, v_name
- , ip_str(&ifp->addr), (unsigned) port));
- close(fd);
- return -1;
- }
- setportof(htons(pluto_port), &ifp->addr);
- return fd;
-}
-
-static void
-process_raw_ifaces(struct raw_iface *rifaces)
-{
- struct raw_iface *ifp;
-
- /* For each real interface...
- */
- for (ifp = rifaces; ifp != NULL; ifp = ifp->next)
- {
- struct raw_iface *v = NULL;
- bool after = FALSE; /* has vfp passed ifp on the list? */
- bool bad = FALSE;
- struct raw_iface *vfp;
-
- for (vfp = rifaces; vfp != NULL; vfp = vfp->next)
- {
- if (vfp == ifp)
- {
- after = TRUE;
- }
- else if (sameaddr(&ifp->addr, &vfp->addr))
- {
- /* ugh: a second interface with the same IP address
- * "after" allows us to avoid double reporting.
- */
- if (after)
- {
- bad = TRUE;
- break;
- }
- continue;
- }
- }
-
- if (bad)
- continue;
-
- v = ifp;
-
- /* We've got all we need; see if this is a new thing:
- * search old interfaces list.
- */
- {
- struct iface **p = &interfaces;
-
- for (;;)
- {
- struct iface *q = *p;
-
- /* search is over if at end of list */
- if (q == NULL)
- {
- /* matches nothing -- create a new entry */
- int fd = create_socket(ifp, v->name, pluto_port);
-
- if (fd < 0)
- break;
-
- if (nat_traversal_support_non_ike
- && addrtypeof(&ifp->addr) == AF_INET)
- {
- nat_traversal_espinudp_socket(fd, ESPINUDP_WITH_NON_IKE);
- }
-
- q = malloc_thing(struct iface);
- zero(q);
- q->rname = clone_str(ifp->name);
- q->vname = clone_str(v->name);
- q->addr = ifp->addr;
- q->fd = fd;
- q->next = interfaces;
- q->change = IFN_ADD;
- interfaces = q;
- plog("adding interface %s/%s %s:%d"
- , q->vname, q->rname, ip_str(&q->addr), pluto_port);
-
- if (nat_traversal_support_port_floating
- && addrtypeof(&ifp->addr) == AF_INET)
- {
- fd = create_socket(ifp, v->name, NAT_T_IKE_FLOAT_PORT);
- if (fd < 0)
- break;
- nat_traversal_espinudp_socket(fd,
- ESPINUDP_WITH_NON_ESP);
- q = malloc_thing(struct iface);
- zero(q);
- q->rname = clone_str(ifp->name);
- q->vname = clone_str(v->name);
- q->addr = ifp->addr;
- setportof(htons(NAT_T_IKE_FLOAT_PORT), &q->addr);
- q->fd = fd;
- q->next = interfaces;
- q->change = IFN_ADD;
- q->ike_float = TRUE;
- interfaces = q;
- plog("adding interface %s/%s %s:%d",
- q->vname, q->rname, ip_str(&q->addr), NAT_T_IKE_FLOAT_PORT);
- }
- break;
- }
-
- /* search over if matching old entry found */
- if (streq(q->rname, ifp->name)
- && streq(q->vname, v->name)
- && sameaddr(&q->addr, &ifp->addr))
- {
- /* matches -- rejuvinate old entry */
- q->change = IFN_KEEP;
-
- /* look for other interfaces to keep (due to NAT-T) */
- for (q = q->next ; q ; q = q->next)
- {
- if (streq(q->rname, ifp->name)
- && streq(q->vname, v->name)
- && sameaddr(&q->addr, &ifp->addr))
- {
- q->change = IFN_KEEP;
- }
- }
- break;
- }
-
- /* try again */
- p = &q->next;
- } /* for (;;) */
- }
- }
-
- /* delete the raw interfaces list */
- while (rifaces != NULL)
- {
- struct raw_iface *t = rifaces;
-
- rifaces = t->next;
- free(t);
- }
-}
-
-void
-find_ifaces(void)
-{
- mark_ifaces_dead();
- process_raw_ifaces(find_raw_ifaces4());
- process_raw_ifaces(find_raw_ifaces6());
-
- free_dead_ifaces(); /* ditch remaining old entries */
-
- if (interfaces == NULL)
- loglog(RC_LOG_SERIOUS, "no public interfaces found");
-}
-
-void
-show_ifaces_status(void)
-{
- struct iface *p;
-
- for (p = interfaces; p != NULL; p = p->next)
- whack_log(RC_COMMENT, "interface %s/%s %s:%d"
- , p->vname, p->rname, ip_str(&p->addr), ntohs(portof(&p->addr)));
-}
-
-void
-show_debug_status(void)
-{
-#ifdef DEBUG
- whack_log(RC_COMMENT, "debug options: %s"
- , bitnamesof(debug_bit_names, cur_debugging));
-#endif
-}
-
-static volatile sig_atomic_t sighupflag = FALSE;
-
-static void
-huphandler(int sig UNUSED)
-{
- sighupflag = TRUE;
-}
-
-static volatile sig_atomic_t sigtermflag = FALSE;
-
-static void
-termhandler(int sig UNUSED)
-{
- sigtermflag = TRUE;
-}
-
-/* call_server listens for incoming ISAKMP packets and Whack messages,
- * and handles timer events.
- */
-void
-call_server(void)
-{
- struct iface *ifp;
-
- /* catch SIGHUP and SIGTERM */
- {
- int r;
- struct sigaction act;
-
- act.sa_handler = &huphandler;
- sigemptyset(&act.sa_mask);
- act.sa_flags = 0; /* no SA_ONESHOT, no SA_RESTART, no nothing */
- r = sigaction(SIGHUP, &act, NULL);
- passert(r == 0);
-
- act.sa_handler = &termhandler;
- r = sigaction(SIGTERM, &act, NULL);
- r = sigaction(SIGINT, &act, NULL);
- passert(r == 0);
- }
-
- for (;;)
- {
- fd_set readfds;
- fd_set writefds;
- int ndes, events_fd;
-
- /* wait for next interesting thing */
-
- for (;;)
- {
- long next_time = next_event(); /* time to any pending timer event */
- int maxfd = ctl_fd;
-
- if (sigtermflag)
- exit_pluto(0);
-
- if (sighupflag)
- {
- /* Ignorant folks think poking any daemon with SIGHUP
- * is polite. We catch it and tell them otherwise.
- * There is one use: unsticking a hung recvfrom.
- * This sticking happens sometimes -- kernel bug?
- */
- sighupflag = FALSE;
- plog("Pluto ignores SIGHUP -- perhaps you want \"whack --listen\"");
- }
-
- FD_ZERO(&readfds);
- FD_ZERO(&writefds);
- FD_SET(ctl_fd, &readfds);
-
-#ifdef ADNS
- /* the only write file-descriptor of interest */
- if (adns_qfd != NULL_FD && unsent_ADNS_queries)
- {
- if (maxfd < adns_qfd)
- maxfd = adns_qfd;
- FD_SET(adns_qfd, &writefds);
- }
-
- if (adns_afd != NULL_FD)
- {
- if (maxfd < adns_afd)
- maxfd = adns_afd;
- FD_SET(adns_afd, &readfds);
- }
-#endif /* ADNS */
-
- events_fd = pluto->events->get_event_fd(pluto->events);
- if (maxfd < events_fd)
- maxfd = events_fd;
- FD_SET(events_fd, &readfds);
-
- if (listening)
- {
- for (ifp = interfaces; ifp != NULL; ifp = ifp->next)
- {
- if (maxfd < ifp->fd)
- maxfd = ifp->fd;
- passert(!FD_ISSET(ifp->fd, &readfds));
- FD_SET(ifp->fd, &readfds);
- }
- }
-
- if (next_time == -1)
- {
- /* select without timer */
-
- ndes = select(maxfd + 1, &readfds, &writefds, NULL, NULL);
- }
- else if (next_time == 0)
- {
- /* timer without select: there is a timer event pending,
- * and it should fire now so don't bother to do the select.
- */
- ndes = 0; /* signify timer expiration */
- }
- else
- {
- /* select with timer */
-
- struct timeval tm;
-
- tm.tv_sec = next_time;
- tm.tv_usec = 0;
- ndes = select(maxfd + 1, &readfds, &writefds, NULL, &tm);
- }
-
- if (ndes != -1)
- break; /* success */
-
- if (errno != EINTR)
- exit_log_errno((e, "select() failed in call_server()"));
-
- /* retry if terminated by signal */
- }
-
- /* figure out what is interesting */
-
- if (ndes == 0)
- {
- /* timer event */
-
- DBG(DBG_CONTROL,
- DBG_log(BLANK_FORMAT);
- DBG_log("*time to handle event"));
-
- handle_timer_event();
- passert(GLOBALS_ARE_RESET());
- }
- else
- {
- /* at least one file descriptor is ready */
-
-#ifdef ADNS
- if (adns_qfd != NULL_FD && FD_ISSET(adns_qfd, &writefds))
- {
- passert(ndes > 0);
- send_unsent_ADNS_queries();
- passert(GLOBALS_ARE_RESET());
- ndes--;
- }
-
- if (adns_afd != NULL_FD && FD_ISSET(adns_afd, &readfds))
- {
- passert(ndes > 0);
- DBG(DBG_CONTROL,
- DBG_log(BLANK_FORMAT);
- DBG_log("*received adns message"));
- handle_adns_answer();
- passert(GLOBALS_ARE_RESET());
- ndes--;
- }
-#endif /* ADNS*/
-
- if (FD_ISSET(events_fd, &readfds))
- {
- passert(ndes > 0);
- DBG(DBG_CONTROL,
- DBG_log(BLANK_FORMAT);
- DBG_log("*handling asynchronous events"));
- pluto->events->handle(pluto->events);
- passert(GLOBALS_ARE_RESET());
- ndes--;
- }
-
- for (ifp = interfaces; ifp != NULL; ifp = ifp->next)
- {
- if (FD_ISSET(ifp->fd, &readfds))
- {
- /* comm_handle will print DBG_CONTROL intro,
- * with more info than we have here.
- */
-
- passert(ndes > 0);
- comm_handle(ifp);
- passert(GLOBALS_ARE_RESET());
- ndes--;
- }
- }
-
- if (FD_ISSET(ctl_fd, &readfds))
- {
- passert(ndes > 0);
- DBG(DBG_CONTROL,
- DBG_log(BLANK_FORMAT);
- DBG_log("*received whack message"));
- whack_handle(ctl_fd);
- passert(GLOBALS_ARE_RESET());
- ndes--;
- }
-
- passert(ndes == 0);
- }
- }
-}
-
-/*
- * Local Variables:
- * c-basic-offset: 4
- * End Variables:
- */
diff --git a/src/pluto/server.h b/src/pluto/server.h
deleted file mode 100644
index b8123f6dc..000000000
--- a/src/pluto/server.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* get-next-event loop
- * Copyright (C) 1998-2001 D. Hugh Redelmeier.
- *
- * 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.
- */
-
-extern int ctl_fd; /* file descriptor of control (whack) socket */
-extern struct sockaddr_un ctl_addr; /* address of control (whack) socket */
-
-extern int info_fd; /* file descriptor of control (info) socket */
-extern struct sockaddr_un info_addr; /* address of control (info) socket */
-
-extern err_t init_ctl_socket(void);
-extern void delete_ctl_socket(void);
-
-extern bool listening; /* should we pay attention to IKE messages? */
-
-
-/* interface: a terminal point for IKE traffic, IPsec transport mode
- * and IPsec tunnels.
- * Essentially:
- * - an IP device (eg. eth1), and
- * - its partner, an ipsec device (eg. ipsec0), and
- * - their shared IP address (eg. 10.7.3.2)
- * Note: the port for IKE is always implicitly UDP/pluto_port.
- */
-struct iface {
- char *vname; /* virtual (ipsec) device name */
- char *rname; /* real device name */
- ip_address addr; /* interface IP address */
- int fd; /* file descriptor of socket for IKE UDP messages */
- struct iface *next;
- bool ike_float;
- enum { IFN_ADD, IFN_KEEP, IFN_DELETE } change;
-};
-
-extern struct iface *interfaces; /* public interfaces */
-
-extern bool use_interface(const char *rifn);
-extern void find_ifaces(void);
-extern void show_ifaces_status(void);
-extern void free_ifaces(void);
-extern void show_debug_status(void);
-extern void call_server(void);
-
-/* in rcv_info.c */
-extern err_t init_info_socket(void);
-extern void delete_info_socket(void);
diff --git a/src/pluto/smartcard.c b/src/pluto/smartcard.c
deleted file mode 100644
index 85e246ac4..000000000
--- a/src/pluto/smartcard.c
+++ /dev/null
@@ -1,1940 +0,0 @@
-/* Support of smartcards and cryptotokens
- * Copyright (C) 2003 Christoph Gysin, Simon Zwahlen
- * Copyright (C) 2004 David Buechi, Michael Meier
- * Zuercher Hochschule Winterthur, Switzerland
- *
- * Copyright (C) 2005 Michael Joosten
- *
- * Copyright (C) 2005 Andreas Steffen
- * Hochschule fuer Technik Rapperswil, Switzerland
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <time.h>
-#include <dlfcn.h>
-
-#include <freeswan.h>
-
-#include <asn1/asn1.h>
-#include <credentials/keys/public_key.h>
-#include <credentials/certificates/x509.h>
-
-#include "constants.h"
-
-#ifdef SMARTCARD
-#include "rsaref/unix.h"
-#include "rsaref/pkcs11.h"
-#endif
-
-#include "defs.h"
-#include "log.h"
-#include "x509.h"
-#include "ca.h"
-#include "certs.h"
-#include "keys.h"
-#include "smartcard.h"
-#include "whack.h"
-#include "fetch.h"
-
-#define DEFAULT_BASE 16
-
-/* chained list of smartcard records */
-static smartcard_t *smartcards = NULL;
-
-/* number of generated sc objects */
-static int sc_number = 0;
-
-const smartcard_t empty_sc = {
- NULL , /* next */
- 0 , /* last_load */
- NULL , /* last_cert */
- 0 , /* count */
- 0 , /* number */
- 999999 , /* slot */
- NULL , /* id */
- NULL , /* label */
- { NULL, 0 } , /* pin */
- FALSE , /* pinpad */
- FALSE , /* valid */
- FALSE , /* session_opened */
- FALSE , /* logged_in */
- TRUE , /* any_slot */
- 0L , /* session */
-};
-
-#ifdef SMARTCARD /* compile with smartcard support */
-
-#define SCX_MAGIC 0xd00bed00
-
-struct scx_pkcs11_module {
- u_int _magic;
- void *handle;
-};
-
-typedef struct scx_pkcs11_module scx_pkcs11_module_t;
-
-/* PKCS #11 cryptoki context */
-static bool scx_initialized = FALSE;
-static scx_pkcs11_module_t *pkcs11_module = NULL_PTR;
-static CK_FUNCTION_LIST_PTR pkcs11_functions = NULL_PTR;
-
-/* crytoki v2.11 - return values of PKCS #11 functions*/
-
-static const char *const pkcs11_return_name[] = {
- "CKR_OK",
- "CKR_CANCEL",
- "CKR_HOST_MEMORY",
- "CKR_SLOT_ID_INVALID",
- "CKR_FLAGS_INVALID",
- "CKR_GENERAL_ERROR",
- "CKR_FUNCTION_FAILED",
- "CKR_ARGUMENTS_BAD",
- "CKR_NO_EVENT",
- "CKR_NEED_TO_CREATE_THREADS",
- "CKR_CANT_LOCK"
- };
-
-static const char *const pkcs11_return_name_10[] = {
- "CKR_ATTRIBUTE_READ_ONLY",
- "CKR_ATTRIBUTE_SENSITIVE",
- "CKR_ATTRIBUTE_TYPE_INVALID",
- "CKR_ATTRIBUTE_VALUE_INVALID"
- };
-
-static const char *const pkcs11_return_name_20[] = {
- "CKR_DATA_INVALID",
- "CKR_DATA_LEN_RANGE"
- };
-
-static const char *const pkcs11_return_name_30[] = {
- "CKR_DEVICE_ERROR",
- "CKR_DEVICE_MEMORY",
- "CKR_DEVICE_REMOVED"
- };
-
-static const char *const pkcs11_return_name_40[] = {
- "CKR_ENCRYPTED_DATA_INVALID",
- "CKR_ENCRYPTED_DATA_LEN_RANGE"
- };
-
-static const char *const pkcs11_return_name_50[] = {
- "CKR_FUNCTION_CANCELED",
- "CKR_FUNCTION_NOT_PARALLEL",
- "CKR_0x52_UNDEFINED",
- "CKR_0x53_UNDEFINED",
- "CKR_FUNCTION_NOT_SUPPORTED"
- };
-
-static const char *const pkcs11_return_name_60[] = {
- "CKR_KEY_HANDLE_INVALID",
- "CKR_KEY_SENSITIVE",
- "CKR_KEY_SIZE_RANGE",
- "CKR_KEY_TYPE_INCONSISTENT",
- "CKR_KEY_NOT_NEEDED",
- "CKR_KEY_CHANGED",
- "CKR_KEY_NEEDED",
- "CKR_KEY_INDIGESTIBLE",
- "CKR_KEY_FUNCTION_NOT_PERMITTED",
- "CKR_KEY_NOT_WRAPPABLE",
- "CKR_KEY_UNEXTRACTABLE"
- };
-
-static const char *const pkcs11_return_name_70[] = {
- "CKR_MECHANISM_INVALID",
- "CKR_MECHANISM_PARAM_INVALID"
- };
-
-static const char *const pkcs11_return_name_80[] = {
- "CKR_OBJECT_HANDLE_INVALID"
- };
-
-static const char *const pkcs11_return_name_90[] = {
- "CKR_OPERATION_ACTIVE",
- "CKR_OPERATION_NOT_INITIALIZED"
- };
-
-static const char *const pkcs11_return_name_A0[] = {
- "CKR_PIN_INCORRECT",
- "CKR_PIN_INVALID",
- "CKR_PIN_LEN_RANGE",
- "CKR_PIN_EXPIRED",
- "CKR_PIN_LOCKED"
- };
-
-static const char *const pkcs11_return_name_B0[] = {
- "CKR_SESSION_CLOSED",
- "CKR_SESSION_COUNT",
- "CKR_0xB2_UNDEFINED",
- "CKR_SESSION_HANDLE_INVALID",
- "CKR_SESSION_PARALLEL_NOT_SUPPORTED",
- "CKR_SESSION_READ_ONLY",
- "CKR_SESSION_EXISTS",
- "CKR_SESSION_READ_ONLY_EXISTS",
- "CKR_SESSION_READ_WRITE_SO_EXISTS"
- };
-
-static const char *const pkcs11_return_name_C0[] = {
- "CKR_SIGNATURE_INVALID",
- "CKR_SIGNATURE_LEN_RANGE"
- };
-
-static const char *const pkcs11_return_name_D0[] = {
- "CKR_TEMPLATE_INCOMPLETE",
- "CKR_TEMPLATE_INCONSISTENT"
- };
-
-static const char *const pkcs11_return_name_E0[] = {
- "CKR_TOKEN_NOT_PRESENT",
- "CKR_TOKEN_NOT_RECOGNIZED",
- "CKR_TOKEN_WRITE_PROTECTED"
- };
-
-static const char *const pkcs11_return_name_F0[] = {
- "CKR_UNWRAPPING_KEY_HANDLE_INVALID",
- "CKR_UNWRAPPING_KEY_SIZE_RANGE",
- "CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT"
- };
-
-static const char *const pkcs11_return_name_100[] = {
- "CKR_USER_ALREADY_LOGGED_IN",
- "CKR_USER_NOT_LOGGED_IN",
- "CKR_USER_PIN_NOT_INITIALIZED",
- "CKR_USER_TYPE_INVALID",
- "CKR_USER_ANOTHER_ALREADY_LOGGED_IN",
- "CKR_USER_TOO_MANY_TYPES"
- };
-
-static const char *const pkcs11_return_name_110[] = {
- "CKR_WRAPPED_KEY_INVALID",
- "CKR_0x111_UNDEFINED",
- "CKR_WRAPPED_KEY_LEN_RANGE",
- "CKR_WRAPPING_KEY_HANDLE_INVALID",
- "CKR_WRAPPING_KEY_SIZE_RANGE",
- "CKR_WRAPPING_KEY_TYPE_INCONSISTENT"
- };
-
-static const char *const pkcs11_return_name_120[] = {
- "CKR_RANDOM_SEED_NOT_SUPPORTED",
- "CKR_RANDOM_NO_RNG"
- };
-
-static const char *const pkcs11_return_name_130[] = {
- "CKR_DOMAIN_PARAMS_INVALID"
- };
-
-static const char *const pkcs11_return_name_150[] = {
- "CKR_BUFFER_TOO_SMALL"
- };
-
-static const char *const pkcs11_return_name_160[] = {
- "CKR_SAVED_STATE_INVALID"
- };
-
-static const char *const pkcs11_return_name_170[] = {
- "CKR_INFORMATION_SENSITIVE"
- };
-
-static const char *const pkcs11_return_name_180[] = {
- "CKR_STATE_UNSAVEABLE"
- };
-
-static const char *const pkcs11_return_name_190[] = {
- "CKR_CRYPTOKI_NOT_INITIALIZED",
- "CKR_CRYPTOKI_ALREADY_INITIALIZED"
- };
-
-static const char *const pkcs11_return_name_1A0[] = {
- "CKR_MUTEX_BAD",
- "CKR_MUTEX_NOT_LOCKED"
- };
-
-static const char *const pkcs11_return_name_200[] = {
- "CKR_FUNCTION_REJECTED"
- };
-
-static const char *const pkcs11_return_name_vendor[] = {
- "CKR_VENDOR_DEFINED"
- };
-
-static enum_names pkcs11_return_names_vendor =
- { CKR_VENDOR_DEFINED, CKR_VENDOR_DEFINED
- , pkcs11_return_name_vendor, NULL };
-
-static enum_names pkcs11_return_names_200 =
- { CKR_FUNCTION_REJECTED, CKR_FUNCTION_REJECTED
- , pkcs11_return_name_200, &pkcs11_return_names_vendor };
-
-static enum_names pkcs11_return_names_1A0 =
- { CKR_MUTEX_BAD, CKR_MUTEX_NOT_LOCKED
- , pkcs11_return_name_1A0, &pkcs11_return_names_200 };
-
-static enum_names pkcs11_return_names_190 =
- { CKR_CRYPTOKI_NOT_INITIALIZED, CKR_CRYPTOKI_ALREADY_INITIALIZED
- , pkcs11_return_name_190, &pkcs11_return_names_1A0 };
-
-static enum_names pkcs11_return_names_180 =
- { CKR_STATE_UNSAVEABLE, CKR_STATE_UNSAVEABLE
- , pkcs11_return_name_180, &pkcs11_return_names_190 };
-
-static enum_names pkcs11_return_names_170 =
- { CKR_INFORMATION_SENSITIVE, CKR_INFORMATION_SENSITIVE
- , pkcs11_return_name_170, &pkcs11_return_names_180 };
-
-static enum_names pkcs11_return_names_160 =
- { CKR_SAVED_STATE_INVALID, CKR_SAVED_STATE_INVALID
- , pkcs11_return_name_160, &pkcs11_return_names_170 };
-
-static enum_names pkcs11_return_names_150 =
- { CKR_BUFFER_TOO_SMALL, CKR_BUFFER_TOO_SMALL
- , pkcs11_return_name_150, &pkcs11_return_names_160 };
-
-static enum_names pkcs11_return_names_130 =
- { CKR_DOMAIN_PARAMS_INVALID, CKR_DOMAIN_PARAMS_INVALID
- , pkcs11_return_name_130, &pkcs11_return_names_150 };
-
-static enum_names pkcs11_return_names_120 =
- { CKR_RANDOM_SEED_NOT_SUPPORTED, CKR_RANDOM_NO_RNG
- , pkcs11_return_name_120, &pkcs11_return_names_130 };
-
-static enum_names pkcs11_return_names_110 =
- { CKR_WRAPPED_KEY_INVALID, CKR_WRAPPING_KEY_TYPE_INCONSISTENT
- , pkcs11_return_name_110, &pkcs11_return_names_120 };
-
-static enum_names pkcs11_return_names_100 =
- { CKR_USER_ALREADY_LOGGED_IN, CKR_USER_TOO_MANY_TYPES
- , pkcs11_return_name_100, &pkcs11_return_names_110 };
-
-static enum_names pkcs11_return_names_F0 =
- { CKR_UNWRAPPING_KEY_HANDLE_INVALID, CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT
- , pkcs11_return_name_F0, &pkcs11_return_names_100 };
-
-static enum_names pkcs11_return_names_E0 =
- { CKR_TOKEN_NOT_PRESENT, CKR_TOKEN_WRITE_PROTECTED
- , pkcs11_return_name_E0, &pkcs11_return_names_F0 };
-
-static enum_names pkcs11_return_names_D0 =
- { CKR_TEMPLATE_INCOMPLETE, CKR_TEMPLATE_INCONSISTENT
- , pkcs11_return_name_D0,&pkcs11_return_names_E0 };
-
-static enum_names pkcs11_return_names_C0 =
- { CKR_SIGNATURE_INVALID, CKR_SIGNATURE_LEN_RANGE
- , pkcs11_return_name_C0, &pkcs11_return_names_D0 };
-
-static enum_names pkcs11_return_names_B0 =
- { CKR_SESSION_CLOSED, CKR_SESSION_READ_WRITE_SO_EXISTS
- , pkcs11_return_name_B0, &pkcs11_return_names_C0 };
-
-static enum_names pkcs11_return_names_A0 =
- { CKR_PIN_INCORRECT, CKR_PIN_LOCKED
- , pkcs11_return_name_A0, &pkcs11_return_names_B0 };
-
-static enum_names pkcs11_return_names_90 =
- { CKR_OPERATION_ACTIVE, CKR_OPERATION_NOT_INITIALIZED
- , pkcs11_return_name_90, &pkcs11_return_names_A0 };
-
-static enum_names pkcs11_return_names_80 =
- { CKR_OBJECT_HANDLE_INVALID, CKR_OBJECT_HANDLE_INVALID
- , pkcs11_return_name_80, &pkcs11_return_names_90 };
-
-static enum_names pkcs11_return_names_70 =
- { CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID
- , pkcs11_return_name_70, &pkcs11_return_names_80 };
-
-static enum_names pkcs11_return_names_60 =
- { CKR_KEY_HANDLE_INVALID, CKR_KEY_UNEXTRACTABLE
- , pkcs11_return_name_60, &pkcs11_return_names_70 };
-
-static enum_names pkcs11_return_names_50 =
- { CKR_FUNCTION_CANCELED, CKR_FUNCTION_NOT_SUPPORTED
- , pkcs11_return_name_50, &pkcs11_return_names_60 };
-
-static enum_names pkcs11_return_names_40 =
- { CKR_ENCRYPTED_DATA_INVALID, CKR_ENCRYPTED_DATA_LEN_RANGE
- , pkcs11_return_name_40, &pkcs11_return_names_50 };
-
-static enum_names pkcs11_return_names_30 =
- { CKR_DEVICE_ERROR, CKR_DEVICE_REMOVED
- , pkcs11_return_name_30, &pkcs11_return_names_40 };
-
-static enum_names pkcs11_return_names_20 =
- { CKR_DATA_INVALID, CKR_DATA_LEN_RANGE
- , pkcs11_return_name_20, &pkcs11_return_names_30 };
-
-static enum_names pkcs11_return_names_10 =
- { CKR_ATTRIBUTE_READ_ONLY, CKR_ATTRIBUTE_VALUE_INVALID
- , pkcs11_return_name_10, &pkcs11_return_names_20};
-
-static enum_names pkcs11_return_names =
- { CKR_OK, CKR_CANT_LOCK
- , pkcs11_return_name, &pkcs11_return_names_10};
-
-/*
- * Unload a PKCS#11 module.
- * The calling application is responsible for cleaning up
- * and calling C_Finalize()
- */
-static CK_RV scx_unload_pkcs11_module(scx_pkcs11_module_t *mod)
-{
- if (!mod || mod->_magic != SCX_MAGIC)
- return CKR_ARGUMENTS_BAD;
-
- if (dlclose(mod->handle) < 0)
- return CKR_FUNCTION_FAILED;
-
- memset(mod, 0, sizeof(*mod));
- free(mod);
- return CKR_OK;
-}
-
-static scx_pkcs11_module_t* scx_load_pkcs11_module(const char *name,
- CK_FUNCTION_LIST_PTR_PTR funcs)
-{
- CK_RV (*c_get_function_list)(CK_FUNCTION_LIST_PTR_PTR);
- scx_pkcs11_module_t *mod;
- void *handle;
- int rv;
-
- if (name == NULL || *name == '\0')
- return NULL;
-
- /* Try to load PKCS#11 library module*/
- handle = dlopen(name, RTLD_NOW);
- if (handle == NULL)
- return NULL;
-
- mod = malloc_thing(scx_pkcs11_module_t);
- mod->_magic = SCX_MAGIC;
- mod->handle = handle;
-
- /* Get the list of function pointers */
- c_get_function_list = (CK_RV (*)(CK_FUNCTION_LIST_PTR_PTR))
- dlsym(mod->handle, "C_GetFunctionList");
- if (!c_get_function_list)
- goto failed;
-
- rv = c_get_function_list(funcs);
- if (rv == CKR_OK)
- return mod;
-
-failed: scx_unload_pkcs11_module(mod);
- return NULL;
-}
-
-/*
- * retrieve a certificate object
- */
-static cert_t* scx_find_cert_object(CK_SESSION_HANDLE session,
- CK_OBJECT_HANDLE object, smartcard_t *sc)
-{
- size_t hex_len, label_len;
- u_char *hex_id = NULL;
- cert_t *cert;
- chunk_t blob;
-
- CK_ATTRIBUTE attr[] = {
- { CKA_ID, NULL_PTR, 0L },
- { CKA_LABEL, NULL_PTR, 0L },
- { CKA_VALUE, NULL_PTR, 0L }
- };
-
- /* get the length of the attributes first */
- CK_RV rv = pkcs11_functions->C_GetAttributeValue(session, object, attr, 3);
- if (rv != CKR_OK)
- {
- plog("couldn't read the attribute sizes: %s"
- , enum_show(&pkcs11_return_names, rv));
- return NULL;
- }
-
- free(sc->label);
-
- hex_id = malloc(attr[0].ulValueLen);
- hex_len = attr[0].ulValueLen;
- sc->label = malloc(attr[1].ulValueLen + 1);
- label_len = attr[1].ulValueLen;
- blob.ptr = malloc(attr[2].ulValueLen);
- blob.len = attr[2].ulValueLen;
-
- attr[0].pValue = hex_id;
- attr[1].pValue = sc->label;
- attr[2].pValue = blob.ptr;
-
- /* now get the attributes */
- rv = pkcs11_functions->C_GetAttributeValue(session, object, attr, 3);
- if (rv != CKR_OK)
- {
- plog("couldn't read the attributes: %s"
- , enum_show(&pkcs11_return_names, rv));
- free(hex_id);
- free(sc->label);
- free(blob.ptr);
- return NULL;
- }
-
- free(sc->id);
-
- /* convert id from hex to ASCII */
- sc->id = malloc(2*hex_len + 1);
- datatot(hex_id, hex_len, 16, sc->id, 2*hex_len + 1);
- free(hex_id);
-
- /* safeguard in case the label is not null terminated */
- sc->label[label_len] = '\0';
-
- /* parse the retrieved cert */
-
- /* initialize the return argument */
- cert = malloc_thing(cert_t);
- *cert = cert_empty;
- cert->smartcard = TRUE;
- cert->cert = lib->creds->create(lib->creds,
- CRED_CERTIFICATE, CERT_X509,
- BUILD_BLOB_ASN1_DER, blob,
- BUILD_END);
- if (cert->cert)
- {
- return cert;
- }
-
- plog("failed to load cert from smartcard, error in X.509 certificate");
- cert_free(cert);
- return NULL;
-}
-
-
-/*
- * search a given slot for PKCS#11 certificate objects
- */
-static void scx_find_cert_objects(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
-{
- CK_RV rv;
- CK_OBJECT_CLASS class = CKO_CERTIFICATE;
- CK_ATTRIBUTE attr[] = {{ CKA_CLASS, &class, sizeof(class) }};
-
- rv = pkcs11_functions->C_FindObjectsInit(session, attr, 1);
- if (rv != CKR_OK)
- {
- plog("error in C_FindObjectsInit: %s"
- , enum_show(&pkcs11_return_names, rv));
- return;
- }
-
- for (;;)
- {
- CK_OBJECT_HANDLE object;
- CK_ULONG obj_count = 0;
- time_t valid_until;
- smartcard_t *sc;
- cert_t *cert;
- certificate_t *certificate;
- x509_t *x509;
-
- rv = pkcs11_functions->C_FindObjects(session, &object, 1, &obj_count);
- if (rv != CKR_OK)
- {
- plog("error in C_FindObjects: %s"
- , enum_show(&pkcs11_return_names, rv));
- break;
- }
-
- /* no objects left */
- if (obj_count == 0)
- break;
-
- /* create and initialize a new smartcard object */
- sc = malloc_thing(smartcard_t);
- *sc = empty_sc;
- sc->any_slot = FALSE;
- sc->slot = slot;
- cert = scx_find_cert_object(session, object, sc);
- if (!cert)
- {
- scx_free(sc);
- continue;
- }
- DBG(DBG_CONTROL,
- DBG_log("found cert in %s with id: %s, label: '%s'"
- , scx_print_slot(sc, ""), sc->id, sc->label)
- )
-
- /* check validity of certificate */
- certificate = cert->cert;
- if (!certificate->get_validity(certificate, NULL, NULL, &valid_until))
- {
- cert_free(cert);
- scx_free(sc);
- continue;
- }
- DBG(DBG_CONTROL,
- DBG_log(" certificate is valid")
- )
-
- sc = scx_add(sc);
-
- /* put end entity and ca certificates into different chains */
- x509 = (x509_t*)certificate;
- if (x509->get_flags(x509) & X509_CA)
- {
- sc->last_cert = add_authcert(cert, X509_CA);
- }
- else
- {
- add_public_key_from_cert(cert, valid_until, DAL_LOCAL);
- sc->last_cert = cert_add(cert);
- }
-
- cert_share(sc->last_cert);
- time(&sc->last_load);
- }
-
- rv = pkcs11_functions->C_FindObjectsFinal(session);
- if (rv != CKR_OK)
- {
- plog("error in C_FindObjectsFinal: %s"
- , enum_show(&pkcs11_return_names, rv));
- }
-}
-
-/*
- * search all slots for PKCS#11 certificate objects
- */
-static void scx_find_all_cert_objects(void)
-{
- CK_RV rv;
- CK_SLOT_ID_PTR slots = NULL_PTR;
- CK_ULONG slot_count = 0;
- CK_ULONG i;
-
- if (!scx_initialized)
- {
- plog("pkcs11 module not initialized");
- return;
- }
-
- /* read size, always returns CKR_OK ! */
- rv = pkcs11_functions->C_GetSlotList(FALSE, NULL_PTR, &slot_count);
-
- /* allocate memory for the slots */
- slots = (CK_SLOT_ID *)malloc(slot_count * sizeof(CK_SLOT_ID));
-
- rv = pkcs11_functions->C_GetSlotList(FALSE, slots, &slot_count);
- if (rv != CKR_OK)
- {
- plog("error in C_GetSlotList: %s", enum_show(&pkcs11_return_names, rv));
- free(slots);
- return;
- }
-
- /* look in every slot for certificate objects */
- for (i = 0; i < slot_count; i++)
- {
- CK_SLOT_ID slot = slots[i];
- CK_SLOT_INFO info;
- CK_SESSION_HANDLE session;
-
- rv = pkcs11_functions->C_GetSlotInfo(slot, &info);
-
- if (rv != CKR_OK)
- {
- plog("error in C_GetSlotInfo: %s"
- , enum_show(&pkcs11_return_names, rv));
- continue;
- }
-
- if (!(info.flags & CKF_TOKEN_PRESENT))
- {
- plog("no token present in slot %lu", slot);
- continue;
- }
-
- rv = pkcs11_functions->C_OpenSession(slot
- , CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &session);
- if (rv != CKR_OK)
- {
- plog("failed to open a session on slot %lu: %s"
- , slot, enum_show(&pkcs11_return_names, rv));
- continue;
- }
- DBG(DBG_CONTROLMORE,
- DBG_log("pkcs11 session #%ld for searching slot %lu", session, slot)
- )
- scx_find_cert_objects(slot, session);
-
- rv = pkcs11_functions->C_CloseSession(session);
- if (rv != CKR_OK)
- {
- plog("error in C_CloseSession: %s"
- , enum_show(&pkcs11_return_names, rv));
- }
- }
- free(slots);
-}
-#endif
-
-/*
- * load and initialize PKCS#11 cryptoki module
- *
- * init_args should be unused when we have a PKCS#11 compliant module,
- * but NSS softoken breaks that API.
- */
-void scx_init(const char* module, const char *init_args)
-{
-#ifdef SMARTCARD
- CK_C_INITIALIZE_ARGS args = { .pReserved = (char *)init_args, };
- CK_RV rv;
-
- if (scx_initialized)
- {
- plog("weird - pkcs11 module seems already to be initialized");
- return;
- }
-
- if (module == NULL)
-#ifdef PKCS11_DEFAULT_LIB
- module = PKCS11_DEFAULT_LIB;
-#else
- {
- plog("no pkcs11 module defined");
- return;
- }
-#endif
-
- DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log("pkcs11 module '%s' loading...", module)
- )
- pkcs11_module = scx_load_pkcs11_module(module, &pkcs11_functions);
- if (pkcs11_module == NULL)
- {
- plog("failed to load pkcs11 module '%s'", module);
- return;
- }
-
- DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log("pkcs11 module initializing...")
- )
- rv = pkcs11_functions->C_Initialize(init_args ? &args : NULL);
- if (rv != CKR_OK)
- {
- plog("failed to initialize pkcs11 module: %s"
- , enum_show(&pkcs11_return_names, rv));
- return;
- }
-
- scx_initialized = TRUE;
- DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log("pkcs11 module loaded and initialized")
- )
-
- scx_find_all_cert_objects();
-#endif
-}
-
-/*
- * finalize and unload PKCS#11 cryptoki module
- */
-void scx_finalize(void)
-{
-#ifdef SMARTCARD
- while (smartcards != NULL)
- {
- scx_release(smartcards);
- }
-
- if (pkcs11_functions != NULL_PTR)
- {
- pkcs11_functions->C_Finalize(NULL_PTR);
- pkcs11_functions = NULL_PTR;
- }
-
- if (pkcs11_module != NULL)
- {
- scx_unload_pkcs11_module(pkcs11_module);
- pkcs11_module = NULL;
- }
-
- scx_initialized = FALSE;
- DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log("pkcs11 module finalized and unloaded")
- )
-#endif
-}
-
-/*
- * does a filename contain the token %smartcard?
- */
-bool scx_on_smartcard(const char *filename)
-{
- return strneq(filename, SCX_TOKEN, strlen(SCX_TOKEN));
-}
-
-#ifdef SMARTCARD
-/*
- * find a specific object on the smartcard
- */
-static bool scx_pkcs11_find_object(CK_SESSION_HANDLE session,
- CK_OBJECT_HANDLE_PTR object,
- CK_OBJECT_CLASS class, const char* id)
-{
- size_t len;
- char buf[BUF_LEN];
- CK_RV rv;
- CK_ULONG obj_count = 0;
- CK_ULONG attr_count = 1;
-
- CK_ATTRIBUTE attr[] = {
- { CKA_CLASS, &class, sizeof(class) },
- { CKA_ID, &buf, 0L }
- };
-
- if (id != NULL)
- {
- ttodata(id, strlen(id), 16, buf, BUF_LEN, &len);
- attr[1].ulValueLen = len;
- attr_count = 2;
- }
-
- /* get info for certificate with id */
- rv = pkcs11_functions->C_FindObjectsInit(session, attr, attr_count);
- if (rv != CKR_OK)
- {
- plog("error in C_FindObjectsInit: %s"
- , enum_show(&pkcs11_return_names, rv));
- return FALSE;
- }
-
- rv = pkcs11_functions->C_FindObjects(session, object, 1, &obj_count);
- if (rv != CKR_OK)
- {
- plog("error in C_FindObjects: %s"
- , enum_show(&pkcs11_return_names, rv));
- return FALSE;
- }
-
- rv = pkcs11_functions->C_FindObjectsFinal(session);
- if (rv != CKR_OK)
- {
- plog("error in C_FindObjectsFinal: %s"
- , enum_show(&pkcs11_return_names, rv));
- return FALSE;
- }
-
- return (obj_count != 0);
-}
-
-/*
- * check if a given certificate object id is found in a slot
- */
-static bool scx_find_cert_id_in_slot(smartcard_t *sc, CK_SLOT_ID slot)
-{
- CK_SESSION_HANDLE session;
- CK_OBJECT_HANDLE object;
- CK_SLOT_INFO info;
-
- CK_RV rv = pkcs11_functions->C_GetSlotInfo(slot, &info);
-
- if (rv != CKR_OK)
- {
- plog("error in C_GetSlotInfo: %s"
- , enum_show(&pkcs11_return_names, rv));
- return FALSE;
- }
-
- if (!(info.flags & CKF_TOKEN_PRESENT))
- {
- plog("no token present in slot %lu", slot);
- return FALSE;
- }
-
- rv = pkcs11_functions->C_OpenSession(slot
- , CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &session);
- if (rv != CKR_OK)
- {
- plog("failed to open a session on slot %lu: %s"
- , slot, enum_show(&pkcs11_return_names, rv));
- return FALSE;
- }
- DBG(DBG_CONTROLMORE,
- DBG_log("pkcs11 session #%ld for searching slot %lu", session, slot)
- )
-
- /* check if there is a certificate on the card in the specified slot */
- if (scx_pkcs11_find_object(session, &object, CKO_CERTIFICATE, sc->id))
- {
- sc->slot = slot;
- sc->any_slot = FALSE;
- sc->session = session;
- sc->session_opened = TRUE;
- return TRUE;
- }
-
- rv = pkcs11_functions->C_CloseSession(session);
- if (rv != CKR_OK)
- {
- plog("error in C_CloseSession: %s"
- , enum_show(&pkcs11_return_names, rv));
- }
- return FALSE;
-}
-#endif
-
-/*
- * Connect to the smart card in the reader and select the correct slot
- */
-bool scx_establish_context(smartcard_t *sc)
-{
-#ifdef SMARTCARD
- bool id_found = FALSE;
-
- if (!scx_initialized)
- {
- plog("pkcs11 module not initialized");
- return FALSE;
- }
-
- if (sc->session_opened)
- {
- DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log("pkcs11 session #%ld already open", sc->session)
- )
- return TRUE;
- }
-
- if (!sc->any_slot)
- id_found = scx_find_cert_id_in_slot(sc, sc->slot);
-
- if (!id_found)
- {
- CK_RV rv;
- CK_SLOT_ID slot;
- CK_SLOT_ID_PTR slots = NULL_PTR;
- CK_ULONG slot_count = 0;
- CK_ULONG i;
-
- /* read size, always returns CKR_OK ! */
- rv = pkcs11_functions->C_GetSlotList(FALSE, NULL_PTR, &slot_count);
-
- /* allocate memory for the slots */
- slots = (CK_SLOT_ID *)malloc(slot_count * sizeof(CK_SLOT_ID));
-
- rv = pkcs11_functions->C_GetSlotList(FALSE, slots, &slot_count);
- if (rv != CKR_OK)
- {
- plog("error in C_GetSlotList: %s"
- , enum_show(&pkcs11_return_names, rv));
- free(slots);
- return FALSE;
- }
-
- /* look in every slot for a certificate with a given object ID */
- for (i = 0; i < slot_count; i++)
- {
- slot = slots[i];
- id_found = scx_find_cert_id_in_slot(sc, slot);
- if (id_found)
- break;
- }
- free(slots);
- }
-
- if (id_found)
- {
- DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log("found token with id %s in slot %lu", sc->id, sc->slot);
- DBG_log("pkcs11 session #%ld opened", sc->session)
- )
- }
- else
- {
- plog(" no certificate with id %s found on smartcard", sc->id);
- }
- return id_found;
-#else
- plog("warning: SMARTCARD support is deactivated in pluto/Makefile!");
- return FALSE;
-#endif
-}
-
-/*
- * log in to a session
- */
-bool scx_login(smartcard_t *sc)
-{
-#ifdef SMARTCARD
- CK_RV rv;
-
- if (sc->logged_in)
- {
- DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log("pkcs11 session #%ld login already done", sc->session)
- )
- return TRUE;
- }
-
- if (sc->pin.ptr == NULL)
- {
- plog("unable to log in without PIN!");
- return FALSE;
- }
-
- if (!sc->session_opened)
- {
- plog("session not opened");
- return FALSE;
- }
-
- rv = pkcs11_functions->C_Login(sc->session, CKU_USER
- , (CK_UTF8CHAR *) sc->pin.ptr, sc->pin.len);
- if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN)
- {
- plog("unable to login: %s"
- , enum_show(&pkcs11_return_names, rv));
- return FALSE;
- }
- DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log("pkcs11 session #%ld login successful", sc->session)
- )
- sc->logged_in = TRUE;
- return TRUE;
-#else
- return FALSE;
-#endif
-}
-
-#ifdef SMARTCARD
-/*
- * logout from a session
- */
-static void scx_logout(smartcard_t *sc)
-{
- CK_RV rv;
-
- rv = pkcs11_functions->C_Logout(sc->session);
- if (rv != CKR_OK)
- plog("error in C_Logout: %s"
- , enum_show(&pkcs11_return_names, rv));
- else
- DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log("pkcs11 session #%ld logout", sc->session)
- )
- sc->logged_in = FALSE;
-}
-#endif
-
-
-/*
- * Release context and disconnect from card
- */
-void scx_release_context(smartcard_t *sc)
-{
-#ifdef SMARTCARD
- CK_RV rv;
-
- if (!scx_initialized)
- return;
-
- if (sc->session_opened)
- {
- if (sc->logged_in)
- scx_logout(sc);
-
- sc->session_opened = FALSE;
-
- rv = pkcs11_functions->C_CloseSession(sc->session);
- if (rv != CKR_OK)
- plog("error in C_CloseSession: %s"
- , enum_show(&pkcs11_return_names, rv));
- else
- DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log("pkcs11 session #%ld closed", sc->session)
- )
- }
-#endif
-}
-
-/*
- * Load host certificate from smartcard
- */
-cert_t* scx_load_cert(const char *filename, smartcard_t **scp, bool *cached)
-{
-#ifdef SMARTCARD /* compile with smartcard support */
- const char *number_slot_id = filename + strlen(SCX_TOKEN);
- CK_OBJECT_HANDLE object;
- smartcard_t *sc;
- cert_t *cert = NULL;
-
- /* return the smartcard object */
- *scp = sc = scx_add(scx_parse_number_slot_id(number_slot_id));
-
- /* is there a cached smartcard certificate? */
- *cached = sc->last_cert &&
- (time(NULL) - sc->last_load) < SCX_CERT_CACHE_INTERVAL;
-
- if (*cached)
- {
- plog(" using cached cert from smartcard #%d (%s, id: %s, label: '%s')"
- , sc->number
- , scx_print_slot(sc, "")
- , sc->id
- , sc->label);
- return sc->last_cert;
- }
-
- if (!scx_establish_context(sc))
- {
- scx_release_context(sc);
- return NULL;
- }
-
- /* find the certificate object */
- if (!scx_pkcs11_find_object(sc->session, &object, CKO_CERTIFICATE, sc->id))
- {
- scx_release_context(sc);
- return NULL;
- }
-
- /* retrieve the certificate object */
- cert = scx_find_cert_object(sc->session, object, sc);
- if (cert == NULL)
- {
- scx_release_context(sc);
- return NULL;
- }
-
- if (!pkcs11_keep_state)
- {
- scx_release_context(sc);
- }
- plog(" loaded cert from smartcard #%d (%s, id: %s, label: '%s')"
- , sc->number
- , scx_print_slot(sc, "")
- , sc->id
- , sc->label);
-
- return cert;
-#else
- plog(" warning: SMARTCARD support is deactivated in pluto/Makefile!");
- return NULL;
-#endif
-}
-
-/*
- * parse slot number and key id
- * the following syntax is allowed
- * number slot id
- * %smartcard 1 - -
- * %smartcard#2 2 - -
- * %smartcard0 - 0 -
- * %smartcard:45 - - 45
- * %smartcard0:45 - 0 45
- */
-smartcard_t* scx_parse_number_slot_id(const char *number_slot_id)
-{
- int len = strlen(number_slot_id);
- smartcard_t *sc = malloc_thing(smartcard_t);
-
- /* assign default values */
- *sc = empty_sc;
-
- if (len == 0) /* default: use certificate #1 */
- {
- sc->number = 1;
- }
- else if (*number_slot_id == '#') /* #number scheme */
- {
- err_t ugh;
- unsigned long ul;
-
- ugh = atoul(number_slot_id+1, len-1 , 10, &ul);
- if (ugh == NULL)
- sc->number = (int)ul;
- else
- plog("error parsing smartcard number: %s", ugh);
- }
- else /* slot:id scheme */
- {
- int slot_len = len;
- char *p = strchr(number_slot_id, ':');
-
- if (p != NULL)
- {
- int id_len = len - (p + 1 - number_slot_id);
- slot_len -= (1 + id_len);
-
- if (id_len > 0) /* we have an id */
- sc->id = p + 1;
- }
- if (slot_len > 0) /* we have a slot */
- {
- err_t ugh = NULL;
- unsigned long ul;
-
- ugh = atoul(number_slot_id, slot_len, 10, &ul);
- if (ugh == NULL)
- {
- sc->slot = ul;
- sc->any_slot = FALSE;
- }
- else
- plog("error parsing smartcard slot number: %s", ugh);
- }
- }
- /* unshare the id string */
- sc->id = clone_str(sc->id);
- return sc;
-}
-
-/*
- * Verify pin on card
- */
-bool scx_verify_pin(smartcard_t *sc)
-{
-#ifdef SMARTCARD
- CK_RV rv;
-
- if (!sc->pinpad)
- sc->valid = FALSE;
-
- if (sc->pin.ptr == NULL)
- {
- plog("unable to verify without PIN");
- return FALSE;
- }
-
- /* establish context */
- if (!scx_establish_context(sc))
- {
- scx_release_context(sc);
- return FALSE;
- }
-
- rv = pkcs11_functions->C_Login(sc->session, CKU_USER,
- (CK_UTF8CHAR *) sc->pin.ptr, sc->pin.len);
- if (rv == CKR_OK || rv == CKR_USER_ALREADY_LOGGED_IN)
- {
- sc->valid = TRUE;
- sc->logged_in = TRUE;
- DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log((rv == CKR_OK)
- ? "PIN code correct"
- : "already logged in, no PIN entry required");
- DBG_log("pkcs11 session #%ld login successful", sc->session)
- )
- }
- else
- {
- DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log("PIN code incorrect")
- )
- }
- if (!pkcs11_keep_state)
- scx_release_context(sc);
-#else
- sc->valid = FALSE;
-#endif
- return sc->valid;
-}
-
-/*
- * Sign hash on smartcard
- */
-bool scx_sign_hash(smartcard_t *sc, const u_char *in, size_t inlen, u_char *out,
- size_t outlen)
-{
-#ifdef SMARTCARD
- CK_RV rv;
- CK_OBJECT_HANDLE object;
- CK_ULONG siglen = (CK_ULONG)outlen;
- CK_BBOOL sign_flag, decrypt_flag;
- CK_ATTRIBUTE attr[] = {
- { CKA_SIGN, &sign_flag, sizeof(sign_flag) },
- { CKA_DECRYPT, &decrypt_flag, sizeof(decrypt_flag) }
- };
-
- if (!sc->logged_in)
- return FALSE;
-
- if (!scx_pkcs11_find_object(sc->session, &object, CKO_PRIVATE_KEY, sc->id))
- {
- plog("unable to find private key with id '%s'", sc->id);
- return FALSE;
- }
-
- rv = pkcs11_functions->C_GetAttributeValue(sc->session, object, attr, 2);
- if (rv != CKR_OK)
- {
- plog("couldn't read the private key attributes: %s"
- , enum_show(&pkcs11_return_names, rv));
- return FALSE;
- }
- DBG(DBG_CONTROL,
- DBG_log("RSA key flags: sign = %s, decrypt = %s"
- , (sign_flag)? "true":"false"
- , (decrypt_flag)? "true":"false")
- )
-
- if (sign_flag)
- {
- CK_MECHANISM mech = { CKM_RSA_PKCS, NULL_PTR, 0 };
-
- rv = pkcs11_functions->C_SignInit(sc->session, &mech, object);
- if (rv != CKR_OK)
- {
- plog("error in C_SignInit: %s"
- , enum_show(&pkcs11_return_names, rv));
- return FALSE;
- }
-
- rv = pkcs11_functions->C_Sign(sc->session, (CK_BYTE_PTR)in, inlen
- , out, &siglen);
- if (rv != CKR_OK)
- {
- plog("error in C_Sign: %s"
- , enum_show(&pkcs11_return_names, rv));
- return FALSE;
- }
- }
- else if (decrypt_flag)
- {
- CK_MECHANISM mech = { CKM_RSA_X_509, NULL_PTR, 0 };
- size_t padlen;
- u_char *p = out ;
-
- /* PKCS#1 v1.5 8.1 encryption-block formatting */
- *p++ = 0x00;
- *p++ = 0x01; /* BT (block type) 01 */
- padlen = outlen - 3 - inlen;
- memset(p, 0xFF, padlen);
- p += padlen;
- *p++ = 0x00;
- memcpy(p, in, inlen);
-
- rv = pkcs11_functions->C_DecryptInit(sc->session, &mech, object);
- if (rv != CKR_OK)
- {
- plog("error in C_DecryptInit: %s"
- , enum_show(&pkcs11_return_names, rv));
- return FALSE;
- }
-
- rv = pkcs11_functions->C_Decrypt(sc->session, out, outlen
- , out, &siglen);
- if (rv != CKR_OK)
- {
- plog("error in C_Decrypt: %s"
- , enum_show(&pkcs11_return_names, rv));
- return FALSE;
- }
- }
- else
- {
- plog("private key has neither sign nor decrypt flag set");
- return FALSE;
- }
-
- if (siglen > (CK_ULONG)outlen)
- {
- plog("signature length (%lu) larger than allocated buffer (%d)"
- , siglen, (int)outlen);
- return FALSE;
- }
- return TRUE;
-#else
- return FALSE;
-#endif
-}
-
-/*
- * encrypt data block with an RSA public key
- */
-bool scx_encrypt(smartcard_t *sc, const u_char *in, size_t inlen, u_char *out,
- size_t *outlen)
-{
-#ifdef SMARTCARD
- CK_RV rv;
- CK_OBJECT_HANDLE object;
- CK_ULONG len = (CK_ULONG)(*outlen);
- CK_BBOOL encrypt_flag;
- CK_ATTRIBUTE attr[] = {
- { CKA_MODULUS, NULL_PTR, 0L },
- { CKA_PUBLIC_EXPONENT, NULL_PTR, 0L },
- { CKA_ENCRYPT, &encrypt_flag, sizeof(encrypt_flag) }
- };
- CK_MECHANISM mech = { CKM_RSA_PKCS, NULL_PTR, 0 };
-
- if (!scx_establish_context(sc))
- {
- scx_release_context(sc);
- return FALSE;
- }
-
- if (!scx_pkcs11_find_object(sc->session, &object, CKO_PUBLIC_KEY, sc->id))
- {
- plog("unable to find public key with id '%s'", sc->id);
- return FALSE;
- }
-
- rv = pkcs11_functions->C_GetAttributeValue(sc->session, object, attr, 3);
- if (rv != CKR_OK)
- {
- plog("couldn't read the public key attributes: %s"
- , enum_show(&pkcs11_return_names, rv));
- scx_release_context(sc);
- return FALSE;
- }
-
- if (!encrypt_flag)
- {
- plog("public key cannot be used for encryption");
- scx_release_context(sc);
- return FALSE;
- }
-
- /* there must be enough space left for the PKCS#1 v1.5 padding */
- if (inlen > attr[0].ulValueLen - 11)
- {
- plog("smartcard input data length (%d) exceeds maximum of %lu bytes"
- , (int)inlen, attr[0].ulValueLen - 11);
- if (!pkcs11_keep_state)
- scx_release_context(sc);
- return FALSE;
- }
-
- rv = pkcs11_functions->C_EncryptInit(sc->session, &mech, object);
-
- if (rv != CKR_OK)
- {
- if (rv == CKR_FUNCTION_NOT_SUPPORTED)
- {
- public_key_t *key;
- chunk_t rsa_modulus, rsa_exponent, rsa_key, cipher_text;
- chunk_t plain_text = {(u_char*)in, inlen};
-
- DBG(DBG_CONTROL,
- DBG_log("doing RSA encryption in software")
- )
- attr[0].pValue = malloc(attr[0].ulValueLen);
- attr[1].pValue = malloc(attr[1].ulValueLen);
-
- rv = pkcs11_functions->C_GetAttributeValue(sc->session, object, attr, 2);
- if (rv != CKR_OK)
- {
- plog("couldn't read modulus and public exponent: %s"
- , enum_show(&pkcs11_return_names, rv));
- free(attr[0].pValue);
- free(attr[1].pValue);
- scx_release_context(sc);
- return FALSE;
- }
- rsa_modulus = chunk_create((u_char*) attr[0].pValue,
- (size_t) attr[0].ulValueLen);
- rsa_exponent = chunk_create((u_char*) attr[1].pValue,
- (size_t) attr[1].ulValueLen);
- rsa_key = asn1_wrap(ASN1_SEQUENCE, "mm",
- asn1_integer("m", rsa_modulus),
- asn1_integer("m", rsa_exponent));
- key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
- BUILD_BLOB_ASN1_DER, rsa_key, BUILD_END);
- free(rsa_key.ptr);
- if (key == NULL)
- {
- return FALSE;
- }
- key->encrypt(key, ENCRYPT_RSA_PKCS1, plain_text, &cipher_text);
- key->destroy(key);
-
- if (cipher_text.ptr == NULL)
- {
- plog("smartcard input data length is too large");
- if (!pkcs11_keep_state)
- {
- scx_release_context(sc);
- }
- return FALSE;
- }
-
- memcpy(out, cipher_text.ptr, cipher_text.len);
- *outlen = cipher_text.len;
- free(cipher_text.ptr);
-
- if (!pkcs11_keep_state)
- {
- scx_release_context(sc);
- }
- return TRUE;
- }
- else
- {
- plog("error in C_EncryptInit: %s"
- , enum_show(&pkcs11_return_names, rv));
- scx_release_context(sc);
- return FALSE;
- }
- }
-
- DBG(DBG_CONTROL,
- DBG_log("doing RSA encryption on smartcard")
- )
- rv = pkcs11_functions->C_Encrypt(sc->session, (u_char*)in, inlen
- , out, &len);
- if (rv != CKR_OK)
- {
- plog("error in C_Encrypt: %s"
- , enum_show(&pkcs11_return_names, rv));
- scx_release_context(sc);
- return FALSE;
- }
- if (!pkcs11_keep_state)
- scx_release_context(sc);
-
- *outlen = (size_t)len;
- return TRUE;
-#else
- return FALSE;
-#endif
-}
-/*
- * decrypt a data block with an RSA private key
- */
-bool scx_decrypt(smartcard_t *sc, const u_char *in, size_t inlen, u_char *out,
- size_t *outlen)
-{
-#ifdef SMARTCARD
- CK_RV rv;
- CK_OBJECT_HANDLE object;
- CK_ULONG len = (CK_ULONG)(*outlen);
- CK_BBOOL decrypt_flag;
- CK_ATTRIBUTE attr[] = {
- { CKA_DECRYPT, &decrypt_flag, sizeof(decrypt_flag) }
- };
- CK_MECHANISM mech = { CKM_RSA_PKCS, NULL_PTR, 0 };
-
- if (!scx_establish_context(sc) || !scx_login(sc))
- {
- scx_release_context(sc);
- return FALSE;
- }
-
- if (!scx_pkcs11_find_object(sc->session, &object, CKO_PRIVATE_KEY, sc->id))
- {
- plog("unable to find private key with id '%s'", sc->id);
- return FALSE;
- }
-
- rv = pkcs11_functions->C_GetAttributeValue(sc->session, object, attr, 1);
- if (rv != CKR_OK)
- {
- plog("couldn't read the private key attributes: %s"
- , enum_show(&pkcs11_return_names, rv));
- return FALSE;
- }
-
- if (!decrypt_flag)
- {
- plog("private key cannot be used for decryption");
- scx_release_context(sc);
- return FALSE;
- }
-
- DBG(DBG_CONTROL,
- DBG_log("doing RSA decryption on smartcard")
- )
- rv = pkcs11_functions->C_DecryptInit(sc->session, &mech, object);
- if (rv != CKR_OK)
- {
- plog("error in C_DecryptInit: %s"
- , enum_show(&pkcs11_return_names, rv));
- scx_release_context(sc);
- return FALSE;
- }
-
- rv = pkcs11_functions->C_Decrypt(sc->session, (u_char*)in, inlen
- , out, &len);
- if (rv != CKR_OK)
- {
- plog("error in C_Decrypt: %s"
- , enum_show(&pkcs11_return_names, rv));
- scx_release_context(sc);
- return FALSE;
- }
- if (!pkcs11_keep_state)
- scx_release_context(sc);
-
- *outlen = (size_t)len;
- return TRUE;
-#else
- return FALSE;
-#endif
-}
-
-/* receive an encrypted data block via whack,
- * decrypt it using a private RSA key and
- * return the decrypted data block via whack
- */
-bool scx_op_via_whack(const char* msg, int inbase, int outbase, sc_op_t op,
- const char* keyid, int whackfd)
-{
- char inbuf[RSA_MAX_OCTETS];
- char outbuf[2*RSA_MAX_OCTETS + 1];
- size_t outlen = sizeof(inbuf);
- size_t inlen;
- smartcard_t *sc,*sc_new;
-
- const char *number_slot_id = "";
-
- err_t ugh = ttodata(msg, 0, inbase, inbuf, sizeof(inbuf), &inlen);
-
- /* no prefix - use default base */
- if (ugh != NULL && inbase == 0)
- ugh = ttodata(msg, 0, DEFAULT_BASE, inbuf, sizeof(inbuf), &inlen);
-
- if (ugh != NULL)
- {
- plog("format error in smartcard input data: %s", ugh);
- return FALSE;
- }
-
- if (keyid != NULL)
- {
- number_slot_id = (strneq(keyid, SCX_TOKEN, strlen(SCX_TOKEN)))
- ? keyid + strlen(SCX_TOKEN) : keyid;
- }
-
- sc_new = scx_parse_number_slot_id(number_slot_id);
- sc = scx_add(sc_new);
- if (sc == sc_new)
- scx_share(sc);
-
- DBG((op == SC_OP_ENCRYPT)? DBG_PRIVATE:DBG_RAW,
- DBG_dump("smartcard input data:\n", inbuf, inlen)
- )
-
- if (op == SC_OP_DECRYPT)
- {
- if (!sc->valid && whackfd != NULL_FD)
- scx_get_pin(sc, whackfd);
-
- if (!sc->valid)
- {
- loglog(RC_NOVALIDPIN, "cannot decrypt without valid PIN");
- return FALSE;
- }
- }
-
- DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log("using RSA key from smartcard (slot: %d, id: %s)"
- , (int)sc->slot, sc->id)
- )
-
- switch (op)
- {
- case SC_OP_ENCRYPT:
- if (!scx_encrypt(sc, inbuf, inlen, inbuf, &outlen))
- return FALSE;
- break;
- case SC_OP_DECRYPT:
- if (!scx_decrypt(sc, inbuf, inlen, inbuf, &outlen))
- return FALSE;
- break;
- default:
- break;
- }
-
- DBG((op == SC_OP_DECRYPT)? DBG_PRIVATE:DBG_RAW,
- DBG_dump("smartcard output data:\n", inbuf, outlen)
- )
-
- if (outbase == 0) /* use default base */
- outbase = DEFAULT_BASE;
-
- if (outbase == 256) /* ascii plain text */
- whack_log(RC_COMMENT, "%.*s", (int)outlen, inbuf);
- else
- {
- outlen = datatot(inbuf, outlen, outbase, outbuf, sizeof(outbuf));
- if (outlen == 0)
- {
- plog("error in output format conversion");
- return FALSE;
- }
- whack_log(RC_COMMENT, "%s", outbuf);
- }
- return TRUE;
-}
-
- /*
- * get length of RSA key in bytes
- */
-size_t scx_get_keylength(smartcard_t *sc)
-{
-#ifdef SMARTCARD
- CK_RV rv;
- CK_OBJECT_HANDLE object;
- CK_ATTRIBUTE attr[] = {{ CKA_MODULUS, NULL_PTR, 0}};
-
- if (!sc->logged_in)
- return FALSE;
-
- if (!scx_pkcs11_find_object(sc->session, &object, CKO_PRIVATE_KEY, sc->id))
- {
- plog("unable to find private key with id '%s'", sc->id);
- return FALSE;
- }
-
- /* get the length of the private key */
- rv = pkcs11_functions->C_GetAttributeValue(sc->session, object
- , (CK_ATTRIBUTE_PTR)&attr, 1);
- if (rv != CKR_OK)
- {
- plog("failed to get key length: %s"
- , enum_show(&pkcs11_return_names, rv));
- return FALSE;
- }
-
- return attr[0].ulValueLen; /*Return key length in bytes */
-#else
- return 0;
-#endif
-}
-
-/*
- * prompt for pin and verify it
- */
-bool scx_get_pin(smartcard_t *sc, int whackfd)
-{
-#ifdef SMARTCARD
- char pin[BUF_LEN];
- int i, n;
-
- whack_log(RC_ENTERSECRET, "need PIN for #%d (%s, id: %s, label: '%s')"
- , sc->number, scx_print_slot(sc, ""), sc->id, sc->label);
-
- for (i = 0; i < SCX_MAX_PIN_TRIALS; i++)
- {
- if (i > 0)
- whack_log(RC_ENTERSECRET, "invalid PIN, please try again");
-
- n = read(whackfd, pin, BUF_LEN);
-
- if (n == -1)
- {
- whack_log(RC_LOG_SERIOUS, "read(whackfd) failed");
- return FALSE;
- }
-
- if (strlen(pin) == 0)
- {
- whack_log(RC_LOG_SERIOUS, "no PIN entered, aborted");
- return FALSE;
- }
-
- sc->pin.ptr = pin;
- sc->pin.len = strlen(pin);
-
- /* verify the pin */
- if (scx_verify_pin(sc))
- {
- sc->pin = chunk_create(pin, strlen(pin));
- sc->pin = chunk_clone(sc->pin);
- break;
- }
-
- /* wrong pin - we try another round */
- sc->pin = chunk_empty;
- }
-
- if (sc->valid)
- whack_log(RC_SUCCESS, "valid PIN");
- else
- whack_log(RC_LOG_SERIOUS, "invalid PIN, too many trials");
-#else
- sc->valid = FALSE;
- whack_log(RC_LOG_SERIOUS, "SMARTCARD support is deactivated in pluto/Makefile!");
-#endif
- return sc->valid;
-}
-
-
-/*
- * free the pin code
- */
-void scx_free_pin(chunk_t *pin)
-{
- if (pin->ptr != NULL)
- {
- /* clear pin field in memory */
- memset(pin->ptr, '\0', pin->len);
- free(pin->ptr);
- *pin = chunk_empty;
- }
-}
-
-/*
- * frees a smartcard record
- */
-void scx_free(smartcard_t *sc)
-{
- if (sc != NULL)
- {
- scx_release_context(sc);
- cert_release(sc->last_cert);
- free(sc->id);
- free(sc->label);
- scx_free_pin(&sc->pin);
- free(sc);
- }
-}
-
-/* release of a smartcard record decreases the count by one
- " the record is freed when the counter reaches zero
- */
-void scx_release(smartcard_t *sc)
-{
- if (sc != NULL && --sc->count == 0)
- {
- smartcard_t **pp = &smartcards;
- while (*pp != sc)
- pp = &(*pp)->next;
- *pp = sc->next;
- scx_free(sc);
- }
-}
-
-/*
- * compare two smartcard records by comparing their slots and ids
- */
-static bool scx_same(smartcard_t *a, smartcard_t *b)
-{
- if (a->number && b->number)
- {
- /* same number */
- return a->number == b->number;
- }
- else
- {
- /* same id and/or same slot */
- return (!a->id || (b->id && streq(a->id, b->id)))
- && (a->any_slot || b->any_slot || a->slot == b->slot);
- }
-}
-
-/* for each link pointing to the smartcard record
- " increase the count by one
- */
-void scx_share(smartcard_t *sc)
-{
- if (sc != NULL)
- sc->count++;
-}
-
-/*
- * adds a smartcard record to the chained list
- */
-smartcard_t* scx_add(smartcard_t *smartcard)
-{
- smartcard_t *sc = smartcards;
- smartcard_t **psc = &smartcards;
-
- while (sc != NULL)
- {
- if (scx_same(smartcard, sc)) /* already in chain, free smartcard record */
- {
- scx_free(smartcard);
- return sc;
- }
- psc = &sc->next;
- sc = sc->next;
- }
-
- /* insert new smartcard record at the end of the chain */
- *psc = smartcard;
- smartcard->number = ++sc_number;
- smartcard->count = 1;
- DBG(DBG_CONTROL | DBG_PARSING,
- DBG_log(" smartcard #%d added", sc_number)
- )
- return smartcard;
-}
-
-/*
- * get the smartcard that belongs to an X.509 certificate
- */
-smartcard_t* scx_get(cert_t *cert)
-{
- smartcard_t *sc = smartcards;
-
- while (sc != NULL)
- {
- if (sc->last_cert == cert)
- {
- return sc;
- }
- sc = sc->next;
- }
- return NULL;
-}
-
-/*
- * prints either the slot number or 'any slot'
- */
-char *scx_print_slot(smartcard_t *sc, const char *whitespace)
-{
- char *buf = temporary_cyclic_buffer();
-
- if (sc->any_slot)
- snprintf(buf, BUF_LEN, "any slot");
- else
- snprintf(buf, BUF_LEN, "slot: %s%lu", whitespace, sc->slot);
- return buf;
-}
-
-/*
- * list all smartcard info records in a chained list
- */
-void scx_list(bool utc)
-{
- smartcard_t *sc = smartcards;
-
- if (sc != NULL)
- {
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, "List of Smartcard Objects:");
- }
-
- while (sc != NULL)
- {
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, " %s, session %s, logged %s, has %s"
- , scx_print_slot(sc, " ")
- , sc->session_opened? "opened" : "closed"
- , sc->logged_in? "in" : "out"
- , sc->pinpad? "pin pad"
- : ((sc->pin.ptr == NULL)? "no pin"
- : sc->valid? "valid pin" : "invalid pin"));
- if (sc->id != NULL)
- whack_log(RC_COMMENT, " id: %s", sc->id);
- if (sc->label != NULL)
- whack_log(RC_COMMENT, " label: '%s'", sc->label);
- if (sc->last_cert)
- {
- certificate_t *certificate = sc->last_cert->cert;
-
- whack_log(RC_COMMENT, " subject: '%Y'",
- certificate->get_subject(certificate));
- }
- sc = sc->next;
- }
-}
diff --git a/src/pluto/smartcard.h b/src/pluto/smartcard.h
deleted file mode 100644
index 7a2229794..000000000
--- a/src/pluto/smartcard.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/* Support of smartcards and cryptotokens
- * Copyright (C) 2003 Christoph Gysin, Simon Zwahlen
- * Copyright (C) 2004 David Buechi, Michael Meier
- * Zuercher Hochschule Winterthur
- *
- * 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.
- */
-
-#ifndef _SMARTCARD_H
-#define _SMARTCARD_H
-
-#include "certs.h"
-
-#define SCX_TOKEN "%smartcard"
-#define SCX_CERT_CACHE_INTERVAL 60 /* seconds */
-#define SCX_MAX_PIN_TRIALS 3
-
-/* smartcard operations, update copy in whack.h */
-
-#ifndef SC_OP_T
-#define SC_OP_T
-typedef enum {
- SC_OP_NONE = 0,
- SC_OP_ENCRYPT = 1,
- SC_OP_DECRYPT = 2,
- SC_OP_SIGN = 3,
-} sc_op_t;
-#endif /* SC_OP_T */
-
-/* smartcard record */
-
-typedef struct smartcard smartcard_t;
-
-struct smartcard {
- smartcard_t *next;
- time_t last_load;
- cert_t *last_cert;
- int count;
- int number;
- unsigned long slot;
- char *id;
- char *label;
- chunk_t pin;
- bool pinpad;
- bool valid;
- bool session_opened;
- bool logged_in;
- bool any_slot;
- long session;
-};
-
-extern const smartcard_t empty_sc;
-
-/* keep a PKCS#11 login during the lifetime of pluto
- * flag set in plutomain.c and used in ipsec_doi.c and ocsp.c
- */
-extern bool pkcs11_keep_state;
-
-/* allow other applications access to pluto's PKCS#11 interface
- * via whack. Could be used e.g. for disk encryption
- */
-extern bool pkcs11_proxy;
-
-extern smartcard_t* scx_parse_number_slot_id(const char *number_slot_id);
-extern void scx_init(const char *module, const char *init_args);
-extern void scx_finalize(void);
-extern bool scx_establish_context(smartcard_t *sc);
-extern bool scx_login(smartcard_t *sc);
-extern bool scx_on_smartcard(const char *filename);
-extern cert_t* scx_load_cert(const char *filename, smartcard_t **scp, bool *cached);
-extern bool scx_verify_pin(smartcard_t *sc);
-extern void scx_share(smartcard_t *sc);
-extern bool scx_sign_hash(smartcard_t *sc, const u_char *in, size_t inlen
- , u_char *out, size_t outlen);
-extern bool scx_encrypt(smartcard_t *sc, const u_char *in, size_t inlen
- , u_char *out, size_t *outlen);
-extern bool scx_decrypt(smartcard_t *sc, const u_char *in, size_t inlen
- , u_char *out, size_t *outlen);
-extern bool scx_op_via_whack(const char* msg, int inbase, int outbase
- , sc_op_t op, const char *keyid, int whackfd);
-extern bool scx_get_pin(smartcard_t *sc, int whackfd);
-extern size_t scx_get_keylength(smartcard_t *sc);
-extern smartcard_t* scx_add(smartcard_t *sc);
-extern smartcard_t* scx_get(cert_t *cert);
-extern void scx_release(smartcard_t *sc);
-extern void scx_release_context(smartcard_t *sc);
-extern void scx_free_pin(chunk_t *pin);
-extern void scx_free(smartcard_t *sc);
-extern void scx_list(bool utc);
-extern char *scx_print_slot(smartcard_t *sc, const char *whitespace);
-
-#endif /* _SMARTCARD_H */
diff --git a/src/pluto/spdb.c b/src/pluto/spdb.c
deleted file mode 100644
index 06fe7d7c8..000000000
--- a/src/pluto/spdb.c
+++ /dev/null
@@ -1,2315 +0,0 @@
-/* Security Policy Data Base (such as it is)
- * Copyright (C) 1998-2001 D. Hugh Redelmeier.
- *
- * 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 <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/queue.h>
-
-#include <freeswan.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "connections.h"
-#include "state.h"
-#include "packet.h"
-#include "keys.h"
-#include "kernel.h"
-#include "log.h"
-#include "spdb.h"
-#include "whack.h"
-#include "crypto.h"
-#include "alg_info.h"
-#include "kernel_alg.h"
-#include "ike_alg.h"
-#include "db_ops.h"
-#include "nat_traversal.h"
-
-#define AD(x) x, countof(x) /* Array Description */
-#define AD_NULL NULL, 0
-
-/**************** Oakely (main mode) SA database ****************/
-
-/* array of proposals to be conjoined (can only be one for Oakley) */
-
-static struct db_prop oakley_pc[] =
- { { PROTO_ISAKMP, AD_NULL } };
-
-/* array of proposal conjuncts (can only be one) */
-
-static struct db_prop_conj oakley_props[] = { { AD(oakley_pc) } };
-
-/* the sadb entry */
-struct db_sa oakley_sadb = { AD(oakley_props) };
-
-/**************** IPsec (quick mode) SA database ****************/
-
-/* arrays of attributes for transforms */
-
-static struct db_attr espsha1_attr[] = {
- { AUTH_ALGORITHM, AUTH_ALGORITHM_HMAC_SHA1 },
- };
-
-static struct db_attr ah_HMAC_SHA1_attr[] = {
- { AUTH_ALGORITHM, AUTH_ALGORITHM_HMAC_SHA1 },
- };
-
-/* arrays of transforms, each in in preference order */
-
-static struct db_trans espa_trans[] = {
- { ESP_3DES, AD(espsha1_attr) },
- };
-
-static struct db_trans esp_trans[] = {
- { ESP_3DES, AD_NULL },
- };
-
-#ifdef SUPPORT_ESP_NULL
-static struct db_trans espnull_trans[] = {
- { ESP_NULL, AD(espsha1_attr) },
- };
-#endif /* SUPPORT_ESP_NULL */
-
-static struct db_trans ah_trans[] = {
- { AH_SHA, AD(ah_HMAC_SHA1_attr) },
- };
-
-static struct db_trans ipcomp_trans[] = {
- { IPCOMP_DEFLATE, AD_NULL },
- };
-
-/* arrays of proposals to be conjoined */
-
-static struct db_prop ah_pc[] = {
- { PROTO_IPSEC_AH, AD(ah_trans) },
- };
-
-#ifdef SUPPORT_ESP_NULL
-static struct db_prop espnull_pc[] = {
- { PROTO_IPSEC_ESP, AD(espnull_trans) },
- };
-#endif /* SUPPORT_ESP_NULL */
-
-static struct db_prop esp_pc[] = {
- { PROTO_IPSEC_ESP, AD(espa_trans) },
- };
-
-static struct db_prop ah_esp_pc[] = {
- { PROTO_IPSEC_AH, AD(ah_trans) },
- { PROTO_IPSEC_ESP, AD(esp_trans) },
- };
-
-static struct db_prop compress_pc[] = {
- { PROTO_IPCOMP, AD(ipcomp_trans) },
- };
-
-static struct db_prop ah_compress_pc[] = {
- { PROTO_IPSEC_AH, AD(ah_trans) },
- { PROTO_IPCOMP, AD(ipcomp_trans) },
- };
-
-#ifdef SUPPORT_ESP_NULL
-static struct db_prop espnull_compress_pc[] = {
- { PROTO_IPSEC_ESP, AD(espnull_trans) },
- { PROTO_IPCOMP, AD(ipcomp_trans) },
- };
-#endif /* SUPPORT_ESP_NULL */
-
-static struct db_prop esp_compress_pc[] = {
- { PROTO_IPSEC_ESP, AD(espa_trans) },
- { PROTO_IPCOMP, AD(ipcomp_trans) },
- };
-
-static struct db_prop ah_esp_compress_pc[] = {
- { PROTO_IPSEC_AH, AD(ah_trans) },
- { PROTO_IPSEC_ESP, AD(esp_trans) },
- { PROTO_IPCOMP, AD(ipcomp_trans) },
- };
-
-/* arrays of proposal alternatives (each element is a conjunction) */
-
-static struct db_prop_conj ah_props[] = {
- { AD(ah_pc) },
-#ifdef SUPPORT_ESP_NULL
- { AD(espnull_pc) }
-#endif
- };
-
-static struct db_prop_conj esp_props[] =
- { { AD(esp_pc) } };
-
-static struct db_prop_conj ah_esp_props[] =
- { { AD(ah_esp_pc) } };
-
-static struct db_prop_conj compress_props[] = {
- { AD(compress_pc) },
- };
-
-static struct db_prop_conj ah_compress_props[] = {
- { AD(ah_compress_pc) },
-#ifdef SUPPORT_ESP_NULL
- { AD(espnull_compress_pc) }
-#endif
- };
-
-static struct db_prop_conj esp_compress_props[] =
- { { AD(esp_compress_pc) } };
-
-static struct db_prop_conj ah_esp_compress_props[] =
- { { AD(ah_esp_compress_pc) } };
-
-/* The IPsec sadb is subscripted by a bitset (subset of policy)
- * with members from { POLICY_ENCRYPT, POLICY_AUTHENTICATE, POLICY_COMPRESS }
- * shifted right by POLICY_IPSEC_SHIFT.
- */
-struct db_sa ipsec_sadb[1 << 3] = {
- { AD_NULL }, /* none */
- { AD(esp_props) }, /* POLICY_ENCRYPT */
- { AD(ah_props) }, /* POLICY_AUTHENTICATE */
- { AD(ah_esp_props) }, /* POLICY_ENCRYPT+POLICY_AUTHENTICATE */
- { AD(compress_props) }, /* POLICY_COMPRESS */
- { AD(esp_compress_props) }, /* POLICY_ENCRYPT+POLICY_COMPRESS */
- { AD(ah_compress_props) }, /* POLICY_AUTHENTICATE+POLICY_COMPRESS */
- { AD(ah_esp_compress_props) }, /* POLICY_ENCRYPT+POLICY_AUTHENTICATE+POLICY_COMPRESS */
- };
-
-#undef AD
-#undef AD_NULL
-
-/* output an attribute (within an SA) */
-static bool
-out_attr(int type
-, unsigned long val
-, struct_desc *attr_desc
-, enum_names **attr_val_descs USED_BY_DEBUG
-, pb_stream *pbs)
-{
- struct isakmp_attribute attr;
-
- if (val >> 16 == 0)
- {
- /* short value: use TV form */
- attr.isaat_af_type = type | ISAKMP_ATTR_AF_TV;
- attr.isaat_lv = val;
- if (!out_struct(&attr, attr_desc, pbs, NULL))
- return FALSE;
- }
- else
- {
- /* This is a real fudge! Since we rarely use long attributes
- * and since this is the only place where we can cause an
- * ISAKMP message length to be other than a multiple of 4 octets,
- * we force the length of the value to be a multiple of 4 octets.
- * Furthermore, we only handle values up to 4 octets in length.
- * Voila: a fixed format!
- */
- pb_stream val_pbs;
- u_int32_t nval = htonl(val);
-
- attr.isaat_af_type = type | ISAKMP_ATTR_AF_TLV;
- if (!out_struct(&attr, attr_desc, pbs, &val_pbs)
- || !out_raw(&nval, sizeof(nval), &val_pbs, "long attribute value"))
- return FALSE;
- close_output_pbs(&val_pbs);
- }
- DBG(DBG_EMITTING,
- enum_names *d = attr_val_descs[type];
-
- if (d != NULL)
- DBG_log(" [%lu is %s]"
- , val, enum_show(d, val)));
- return TRUE;
-}
-#define return_on(var, val) do { var=val;goto return_out; } while(0)
-/* Output an SA, as described by a db_sa.
- * This has the side-effect of allocating SPIs for us.
- */
-bool
-out_sa(pb_stream *outs
-, struct db_sa *sadb
-, struct state *st
-, bool oakley_mode
-, u_int8_t np)
-{
- pb_stream sa_pbs;
- int pcn;
- bool ret = FALSE;
- bool ah_spi_generated = FALSE
- , esp_spi_generated = FALSE
- , ipcomp_cpi_generated = FALSE;
-#if !defined NO_KERNEL_ALG || !defined NO_IKE_ALG
- struct db_context *db_ctx = NULL;
-#endif
-
- /* SA header out */
- {
- struct isakmp_sa sa;
-
- sa.isasa_np = np;
- st->st_doi = sa.isasa_doi = ISAKMP_DOI_IPSEC; /* all we know */
- if (!out_struct(&sa, &isakmp_sa_desc, outs, &sa_pbs))
- return_on(ret, FALSE);
- }
-
- /* within SA: situation out */
- st->st_situation = SIT_IDENTITY_ONLY;
- if (!out_struct(&st->st_situation, &ipsec_sit_desc, &sa_pbs, NULL))
- return_on(ret, FALSE);
-
- /* within SA: Proposal Payloads
- *
- * Multiple Proposals with the same number are simultaneous
- * (conjuncts) and must deal with different protocols (AH or ESP).
- * Proposals with different numbers are alternatives (disjuncts),
- * in preference order.
- * Proposal numbers must be monotonic.
- * See RFC 2408 "ISAKMP" 4.2
- */
-
- for (pcn = 0; pcn != sadb->prop_conj_cnt; pcn++)
- {
- struct db_prop_conj *pc = &sadb->prop_conjs[pcn];
- int pn;
-
- for (pn = 0; pn != pc->prop_cnt; pn++)
- {
- struct db_prop *p = &pc->props[pn];
- pb_stream proposal_pbs;
- struct isakmp_proposal proposal;
- struct_desc *trans_desc = NULL;
- struct_desc *attr_desc = NULL;
- enum_names **attr_val_descs = NULL;
- int tn;
- bool tunnel_mode;
-
- tunnel_mode = (pn == pc->prop_cnt-1)
- && (st->st_policy & POLICY_TUNNEL);
-
- /* Proposal header */
- proposal.isap_np = pcn == sadb->prop_conj_cnt-1 && pn == pc->prop_cnt-1
- ? ISAKMP_NEXT_NONE : ISAKMP_NEXT_P;
- proposal.isap_proposal = pcn;
- proposal.isap_protoid = p->protoid;
- proposal.isap_spisize = oakley_mode ? 0
- : p->protoid == PROTO_IPCOMP ? IPCOMP_CPI_SIZE
- : IPSEC_DOI_SPI_SIZE;
-
- /* In quick mode ONLY, create proposal for runtime kernel algos.
- * Replace ESP proposals with runtime created one
- */
- if (!oakley_mode && p->protoid == PROTO_IPSEC_ESP)
- {
- DBG(DBG_CONTROL | DBG_CRYPT,
- if (st->st_connection->alg_info_esp)
- {
- static char buf[BUF_LEN]="";
-
- alg_info_snprint(buf, sizeof (buf),
- (struct alg_info *)st->st_connection->alg_info_esp);
- DBG_log("esp proposal: %s", buf);
- }
- )
- db_ctx = kernel_alg_db_new(st->st_connection->alg_info_esp, st->st_policy);
- p = db_prop_get(db_ctx);
-
- if (!p || p->trans_cnt == 0)
- {
- loglog(RC_LOG_SERIOUS,
- "empty IPSEC SA proposal to send "
- "(no kernel algorithms for esp selection)");
- return_on(ret, FALSE);
- }
- }
-
- if (oakley_mode && p->protoid == PROTO_ISAKMP)
- {
- DBG(DBG_CONTROL | DBG_CRYPT,
- if (st->st_connection->alg_info_ike)
- {
- static char buf[BUF_LEN]="";
-
- alg_info_snprint(buf, sizeof (buf),
- (struct alg_info *)st->st_connection->alg_info_ike);
- DBG_log("ike proposal: %s", buf);
- }
- )
- db_ctx = ike_alg_db_new(st->st_connection, st->st_policy);
- p = db_prop_get(db_ctx);
-
- if (!p || p->trans_cnt == 0)
- {
- loglog(RC_LOG_SERIOUS,
- "empty ISAKMP SA proposal to send "
- "(no algorithms for ike selection?)");
- return_on(ret, FALSE);
- }
- }
-
- proposal.isap_notrans = p->trans_cnt;
- if (!out_struct(&proposal, &isakmp_proposal_desc, &sa_pbs, &proposal_pbs))
- return_on(ret, FALSE);
-
- /* Per-protocols stuff:
- * Set trans_desc.
- * Set attr_desc.
- * Set attr_val_descs.
- * If not oakley_mode, emit SPI.
- * We allocate SPIs on demand.
- * All ESPs in an SA will share a single SPI.
- * All AHs in an SAwill share a single SPI.
- * AHs' SPI will be distinct from ESPs'.
- * This latter is needed because KLIPS doesn't
- * use the protocol when looking up a (dest, protocol, spi).
- * ??? If multiple ESPs are composed, how should their SPIs
- * be allocated?
- */
- {
- ipsec_spi_t *spi_ptr = NULL;
- int proto = 0;
- bool *spi_generated = NULL;
-
- switch (p->protoid)
- {
- case PROTO_ISAKMP:
- passert(oakley_mode);
- trans_desc = &isakmp_isakmp_transform_desc;
- attr_desc = &isakmp_oakley_attribute_desc;
- attr_val_descs = oakley_attr_val_descs;
- /* no SPI needed */
- break;
- case PROTO_IPSEC_AH:
- passert(!oakley_mode);
- trans_desc = &isakmp_ah_transform_desc;
- attr_desc = &isakmp_ipsec_attribute_desc;
- attr_val_descs = ipsec_attr_val_descs;
- spi_ptr = &st->st_ah.our_spi;
- spi_generated = &ah_spi_generated;
- proto = IPPROTO_AH;
- break;
- case PROTO_IPSEC_ESP:
- passert(!oakley_mode);
- trans_desc = &isakmp_esp_transform_desc;
- attr_desc = &isakmp_ipsec_attribute_desc;
- attr_val_descs = ipsec_attr_val_descs;
- spi_ptr = &st->st_esp.our_spi;
- spi_generated = &esp_spi_generated;
- proto = IPPROTO_ESP;
- break;
- case PROTO_IPCOMP:
- passert(!oakley_mode);
- trans_desc = &isakmp_ipcomp_transform_desc;
- attr_desc = &isakmp_ipsec_attribute_desc;
- attr_val_descs = ipsec_attr_val_descs;
-
- /* a CPI isn't quite the same as an SPI
- * so we use specialized code to emit it.
- */
- if (!ipcomp_cpi_generated)
- {
- st->st_ipcomp.our_spi = get_my_cpi(
- &st->st_connection->spd, tunnel_mode);
- if (st->st_ipcomp.our_spi == 0)
- return_on(ret, FALSE); /* problem generating CPI */
-
- ipcomp_cpi_generated = TRUE;
- }
- /* CPI is stored in network low order end of an
- * ipsec_spi_t. So we start a couple of bytes in.
- */
- if (!out_raw((u_char *)&st->st_ipcomp.our_spi
- + IPSEC_DOI_SPI_SIZE - IPCOMP_CPI_SIZE
- , IPCOMP_CPI_SIZE
- , &proposal_pbs, "CPI"))
- return_on(ret, FALSE);
- break;
- default:
- bad_case(p->protoid);
- }
- if (spi_ptr != NULL)
- {
- if (!*spi_generated)
- {
- *spi_ptr = get_ipsec_spi(0
- , proto
- , &st->st_connection->spd
- , tunnel_mode);
- if (*spi_ptr == 0)
- return_on(ret, FALSE);
- *spi_generated = TRUE;
- }
- if (!out_raw((u_char *)spi_ptr, IPSEC_DOI_SPI_SIZE
- , &proposal_pbs, "SPI"))
- return_on(ret, FALSE);
- }
- }
-
- /* within proposal: Transform Payloads */
- for (tn = 0; tn != p->trans_cnt; tn++)
- {
- struct db_trans *t = &p->trans[tn];
- pb_stream trans_pbs;
- struct isakmp_transform trans;
- int an;
-
- trans.isat_np = (tn == p->trans_cnt - 1)
- ? ISAKMP_NEXT_NONE : ISAKMP_NEXT_T;
- trans.isat_transnum = tn;
- trans.isat_transid = t->transid;
- if (!out_struct(&trans, trans_desc, &proposal_pbs, &trans_pbs))
- return_on(ret, FALSE);
-
- /* Within transform: Attributes. */
-
- /* For Phase 2 / Quick Mode, GROUP_DESCRIPTION is
- * automatically generated because it must be the same
- * in every transform. Except IPCOMP.
- */
- if (p->protoid != PROTO_IPCOMP && st->st_pfs_group != NULL)
- {
- passert(!oakley_mode);
- passert(st->st_pfs_group != &unset_group);
- out_attr(GROUP_DESCRIPTION, st->st_pfs_group->algo_id
- , attr_desc, attr_val_descs
- , &trans_pbs);
- }
-
- /* automatically generate duration
- * and, for Phase 2 / Quick Mode, encapsulation.
- */
- if (oakley_mode)
- {
- out_attr(OAKLEY_LIFE_TYPE, OAKLEY_LIFE_SECONDS
- , attr_desc, attr_val_descs
- , &trans_pbs);
- out_attr(OAKLEY_LIFE_DURATION
- , st->st_connection->sa_ike_life_seconds
- , attr_desc, attr_val_descs
- , &trans_pbs);
- }
- else
- {
- /* RFC 2407 (IPSEC DOI) 4.5 specifies that
- * the default is "unspecified (host-dependent)".
- * This makes little sense, so we always specify it.
- *
- * Unlike other IPSEC transforms, IPCOMP defaults
- * to Transport Mode, so we can exploit the default
- * (draft-shacham-ippcp-rfc2393bis-05.txt 4.1).
- */
- if (p->protoid != PROTO_IPCOMP
- || st->st_policy & POLICY_TUNNEL)
- {
-#ifndef I_KNOW_TRANSPORT_MODE_HAS_SECURITY_CONCERN_BUT_I_WANT_IT
- if ((st->nat_traversal & NAT_T_DETECTED)
- && !(st->st_policy & POLICY_TUNNEL))
- {
- /* Inform user that we will not respect policy and only
- * propose Tunnel Mode
- */
- loglog(RC_LOG_SERIOUS, "NAT-Traversal: "
- "Transport Mode not allowed due to security concerns -- "
- "using Tunnel mode");
- }
-#endif
- out_attr(ENCAPSULATION_MODE
-#ifdef I_KNOW_TRANSPORT_MODE_HAS_SECURITY_CONCERN_BUT_I_WANT_IT
- , NAT_T_ENCAPSULATION_MODE(st, st->st_policy)
-#else
- /* If NAT-T is detected, use UDP_TUNNEL as long as Transport
- * Mode has security concerns.
- *
- * User has been informed of that
- */
- , NAT_T_ENCAPSULATION_MODE(st, POLICY_TUNNEL)
-#endif
- , attr_desc, attr_val_descs
- , &trans_pbs);
- }
- out_attr(SA_LIFE_TYPE, SA_LIFE_TYPE_SECONDS
- , attr_desc, attr_val_descs
- , &trans_pbs);
- out_attr(SA_LIFE_DURATION
- , st->st_connection->sa_ipsec_life_seconds
- , attr_desc, attr_val_descs
- , &trans_pbs);
- }
-
- /* spit out attributes from table */
- for (an = 0; an != t->attr_cnt; an++)
- {
- struct db_attr *a = &t->attrs[an];
-
- out_attr(a->type, a->val
- , attr_desc, attr_val_descs
- , &trans_pbs);
- }
-
- close_output_pbs(&trans_pbs);
- }
- close_output_pbs(&proposal_pbs);
- }
- /* end of a conjunction of proposals */
- }
- close_output_pbs(&sa_pbs);
- ret = TRUE;
-
-return_out:
-
-#if !defined NO_KERNEL_ALG || !defined NO_IKE_ALG
- if (db_ctx)
- db_destroy(db_ctx);
-#endif
- return ret;
-}
-
-/* Handle long form of duration attribute.
- * The code is can only handle values that can fit in unsigned long.
- * "Clamping" is probably an acceptable way to impose this limitation.
- */
-static u_int32_t decode_long_duration(pb_stream *pbs)
-{
- u_int32_t val = 0;
-
- /* ignore leading zeros */
- while (pbs_left(pbs) != 0 && *pbs->cur == '\0')
- pbs->cur++;
-
- if (pbs_left(pbs) > sizeof(val))
- {
- /* "clamp" too large value to max representable value */
- val = UINT32_MAX;
- DBG(DBG_PARSING, DBG_log(" too large duration clamped to: %lu"
- , (unsigned long)val));
- }
- else
- {
- /* decode number */
- while (pbs_left(pbs) != 0)
- val = (val << BITS_PER_BYTE) | *pbs->cur++;
- DBG(DBG_PARSING, DBG_log(" long duration: %lu", (unsigned long)val));
- }
- return val;
-}
-
-/* Preparse the body of an ISAKMP SA Payload and
- * return body of ISAKMP Proposal Payload
- *
- * Only IPsec DOI is accepted (what is the ISAKMP DOI?).
- * Error response is rudimentary.
- */
-notification_t
-preparse_isakmp_sa_body(const struct isakmp_sa *sa
- , pb_stream *sa_pbs
- , u_int32_t *ipsecdoisit
- , pb_stream *proposal_pbs
- , struct isakmp_proposal *proposal)
-{
- /* DOI */
- if (sa->isasa_doi != ISAKMP_DOI_IPSEC)
- {
- loglog(RC_LOG_SERIOUS, "Unknown/unsupported DOI %s", enum_show(&doi_names, sa->isasa_doi));
- /* XXX Could send notification back */
- return ISAKMP_DOI_NOT_SUPPORTED;
- }
-
- /* Situation */
- if (!in_struct(ipsecdoisit, &ipsec_sit_desc, sa_pbs, NULL))
- {
- return ISAKMP_SITUATION_NOT_SUPPORTED;
- }
- if (*ipsecdoisit != SIT_IDENTITY_ONLY)
- {
- loglog(RC_LOG_SERIOUS, "unsupported IPsec DOI situation (%s)"
- , bitnamesof(sit_bit_names, *ipsecdoisit));
- /* XXX Could send notification back */
- return ISAKMP_SITUATION_NOT_SUPPORTED;
- }
-
- /* The rules for ISAKMP SAs are scattered.
- * RFC 2409 "IKE" section 5 says that there
- * can only be one SA, and it can have only one proposal in it.
- * There may well be multiple transforms.
- */
- if (!in_struct(proposal, &isakmp_proposal_desc, sa_pbs, proposal_pbs))
- {
- return ISAKMP_PAYLOAD_MALFORMED;
- }
- if (proposal->isap_np != ISAKMP_NEXT_NONE)
- {
- loglog(RC_LOG_SERIOUS, "Proposal Payload must be alone in Oakley SA; found %s following Proposal"
- , enum_show(&payload_names, proposal->isap_np));
- return ISAKMP_PAYLOAD_MALFORMED;
- }
-
- if (proposal->isap_protoid != PROTO_ISAKMP)
- {
- loglog(RC_LOG_SERIOUS, "unexpected Protocol ID (%s) found in Oakley Proposal"
- , enum_show(&protocol_names, proposal->isap_protoid));
- return ISAKMP_INVALID_PROTOCOL_ID;
- }
-
- /* Just what should we accept for the SPI field?
- * The RFC is sort of contradictory. We will ignore the SPI
- * as long as it is of the proper size.
- *
- * From RFC2408 2.4 Identifying Security Associations:
- * During phase 1 negotiations, the initiator and responder cookies
- * determine the ISAKMP SA. Therefore, the SPI field in the Proposal
- * payload is redundant and MAY be set to 0 or it MAY contain the
- * transmitting entity's cookie.
- *
- * From RFC2408 3.5 Proposal Payload:
- * o SPI Size (1 octet) - Length in octets of the SPI as defined by
- * the Protocol-Id. In the case of ISAKMP, the Initiator and
- * Responder cookie pair from the ISAKMP Header is the ISAKMP SPI,
- * therefore, the SPI Size is irrelevant and MAY be from zero (0) to
- * sixteen (16). If the SPI Size is non-zero, the content of the
- * SPI field MUST be ignored. If the SPI Size is not a multiple of
- * 4 octets it will have some impact on the SPI field and the
- * alignment of all payloads in the message. The Domain of
- * Interpretation (DOI) will dictate the SPI Size for other
- * protocols.
- */
- if (proposal->isap_spisize == 0)
- {
- /* empty (0) SPI -- fine */
- }
- else if (proposal->isap_spisize <= MAX_ISAKMP_SPI_SIZE)
- {
- u_char junk_spi[MAX_ISAKMP_SPI_SIZE];
-
- if (!in_raw(junk_spi, proposal->isap_spisize, proposal_pbs, "Oakley SPI"))
- return ISAKMP_PAYLOAD_MALFORMED;
- }
- else
- {
- loglog(RC_LOG_SERIOUS, "invalid SPI size (%u) in Oakley Proposal"
- , (unsigned)proposal->isap_spisize);
- return ISAKMP_INVALID_SPI;
- }
- return ISAKMP_NOTHING_WRONG;
-}
-
-static struct {
- u_int8_t *start;
- u_int8_t *cur;
- u_int8_t *roof;
-} backup;
-
-/**
- * Backup the pointer into a pb_stream
- */
-void backup_pbs(pb_stream *pbs)
-{
- backup.start = pbs->start;
- backup.cur = pbs->cur;
- backup.roof = pbs->roof;
-}
-
-/**
- * Restore the pointer into a pb_stream
- */
-void restore_pbs(pb_stream *pbs)
-{
- pbs->start = backup.start;
- pbs->cur = backup.cur;
- pbs->roof = backup.roof;
-}
-
-/**
- * Parse an ISAKMP Proposal Payload for RSA and PSK authentication policies
- */
-notification_t parse_isakmp_policy(pb_stream *proposal_pbs, u_int notrans,
- lset_t *policy)
-{
- int last_transnum = -1;
-
- *policy = LEMPTY;
-
- while (notrans--)
- {
- pb_stream trans_pbs;
- u_char *attr_start;
- size_t attr_len;
- struct isakmp_transform trans;
-
- if (!in_struct(&trans, &isakmp_isakmp_transform_desc, proposal_pbs, &trans_pbs))
- {
- return ISAKMP_BAD_PROPOSAL_SYNTAX;
- }
- if (trans.isat_transnum <= last_transnum)
- {
- /* picky, picky, picky */
- loglog(RC_LOG_SERIOUS, "Transform Numbers are not monotonically increasing"
- " in Oakley Proposal");
- return ISAKMP_BAD_PROPOSAL_SYNTAX;
- }
- last_transnum = trans.isat_transnum;
-
- if (trans.isat_transid != KEY_IKE)
- {
- loglog(RC_LOG_SERIOUS, "expected KEY_IKE but found %s in Oakley Transform"
- , enum_show(&isakmp_transformid_names, trans.isat_transid));
- return ISAKMP_INVALID_TRANSFORM_ID;
- }
-
- attr_start = trans_pbs.cur;
- attr_len = pbs_left(&trans_pbs);
-
- /* preprocess authentication attributes only */
- while (pbs_left(&trans_pbs) != 0)
- {
- struct isakmp_attribute a;
- pb_stream attr_pbs;
-
- if (!in_struct(&a, &isakmp_oakley_attribute_desc, &trans_pbs, &attr_pbs))
- {
- return ISAKMP_BAD_PROPOSAL_SYNTAX;
- }
- passert((a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK) < 32);
-
- switch (a.isaat_af_type)
- {
- case OAKLEY_AUTHENTICATION_METHOD | ISAKMP_ATTR_AF_TV:
- switch (a.isaat_lv)
- {
- case OAKLEY_PRESHARED_KEY:
- *policy |= POLICY_PSK;
- break;
- case OAKLEY_RSA_SIG:
- case OAKLEY_ECDSA_256:
- case OAKLEY_ECDSA_384:
- case OAKLEY_ECDSA_521:
- *policy |= POLICY_PUBKEY;
- break;
- case XAUTHInitPreShared:
- *policy |= POLICY_XAUTH_SERVER;
- /* fall through */
- case XAUTHRespPreShared:
- *policy |= POLICY_XAUTH_PSK;
- break;
- case XAUTHInitRSA:
- *policy |= POLICY_XAUTH_SERVER;
- /* fall through */
- case XAUTHRespRSA:
- *policy |= POLICY_XAUTH_RSASIG;
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
- }
- }
- DBG(DBG_CONTROL|DBG_PARSING,
- DBG_log("preparse_isakmp_policy: peer requests %s authentication"
- , prettypolicy(*policy))
- )
- return ISAKMP_NOTHING_WRONG;
-}
-
-/**
- * Check that we can find a preshared secret
- */
-static err_t find_preshared_key(struct state* st)
-{
- err_t ugh = NULL;
- connection_t *c = st->st_connection;
-
- if (get_preshared_secret(c) == NULL)
- {
- char his_id[BUF_LEN];
-
- if (his_id_was_instantiated(c))
- {
- strcpy(his_id, "%any");
- }
- else
- {
- snprintf(his_id, sizeof(his_id), "%Y", c->spd.that.id);
- }
- ugh = builddiag("Can't authenticate: no preshared key found "
- "for '%Y' and '%s'", c->spd.this.id, his_id);
- }
- return ugh;
-}
-
-/* Parse the body of an ISAKMP SA Payload (i.e. Phase 1 / Main Mode).
- * Various shortcuts are taken. In particular, the policy, such as
- * it is, is hardwired.
- *
- * If r_sa is non-NULL, the body of an SA representing the selected
- * proposal is emitted.
- *
- * This routine is used by main_inI1_outR1() and main_inR1_outI2().
- */
-notification_t parse_isakmp_sa_body(u_int32_t ipsecdoisit,
- pb_stream *proposal_pbs,
- struct isakmp_proposal *proposal,
- pb_stream *r_sa_pbs,
- struct state *st,
- bool initiator)
-{
- connection_t *c = st->st_connection;
- unsigned no_trans_left;
-
- /* for each transform payload... */
- no_trans_left = proposal->isap_notrans;
-
- for (;;)
- {
- pb_stream trans_pbs;
- u_char *attr_start;
- size_t attr_len;
- struct isakmp_transform trans;
- lset_t seen_attrs = 0;
- lset_t seen_durations = 0;
- u_int16_t life_type = 0;
- struct oakley_trans_attrs ta = { .encrypter = NULL };
- err_t ugh = NULL; /* set to diagnostic when problem detected */
-
- /* initialize only optional field in ta */
- ta.life_seconds = OAKLEY_ISAKMP_SA_LIFETIME_DEFAULT; /* When this SA expires (seconds) */
-
- if (no_trans_left == 0)
- {
- loglog(RC_LOG_SERIOUS, "number of Transform Payloads disagrees with Oakley Proposal Payload");
- return ISAKMP_BAD_PROPOSAL_SYNTAX;
- }
-
- in_struct(&trans, &isakmp_isakmp_transform_desc, proposal_pbs, &trans_pbs);
- attr_start = trans_pbs.cur;
- attr_len = pbs_left(&trans_pbs);
-
- /* process all the attributes that make up the transform */
-
- while (pbs_left(&trans_pbs) != 0)
- {
- struct isakmp_attribute a;
- pb_stream attr_pbs;
- u_int32_t val; /* room for larger values */
-
- if (!in_struct(&a, &isakmp_oakley_attribute_desc, &trans_pbs, &attr_pbs))
- return ISAKMP_BAD_PROPOSAL_SYNTAX;
-
- passert((a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK) < 32);
-
- if (LHAS(seen_attrs, a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK))
- {
- loglog(RC_LOG_SERIOUS, "repeated %s attribute in Oakley Transform %u"
- , enum_show(&oakley_attr_names, a.isaat_af_type)
- , trans.isat_transnum);
- return ISAKMP_BAD_PROPOSAL_SYNTAX;
- }
-
- seen_attrs |= LELEM(a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK);
-
- val = a.isaat_lv;
-
- DBG(DBG_PARSING,
- {
- enum_names *vdesc = oakley_attr_val_descs
- [a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK];
-
- if (vdesc != NULL)
- {
- const char *nm = enum_name(vdesc, val);
-
- if (nm != NULL)
- DBG_log(" [%u is %s]", (unsigned)val, nm);
- }
- });
-
- switch (a.isaat_af_type)
- {
- case OAKLEY_ENCRYPTION_ALGORITHM | ISAKMP_ATTR_AF_TV:
- if (ike_alg_get_crypter(val))
- {
- ta.encrypt = val;
- ta.encrypter = ike_alg_get_crypter(val);
- ta.enckeylen = ta.encrypter->keydeflen;
- }
- else
- {
- ugh = builddiag("%s is not supported"
- , enum_show(&oakley_enc_names, val));
- }
- break;
-
- case OAKLEY_HASH_ALGORITHM | ISAKMP_ATTR_AF_TV:
- if (ike_alg_get_hasher(val))
- {
- ta.hash = val;
- ta.hasher = ike_alg_get_hasher(val);
- }
- else
- {
- ugh = builddiag("%s is not supported"
- , enum_show(&oakley_hash_names, val));
- }
- break;
-
- case OAKLEY_AUTHENTICATION_METHOD | ISAKMP_ATTR_AF_TV:
- {
- /* check that authentication method is acceptable */
- lset_t iap = st->st_policy & POLICY_ID_AUTH_MASK;
-
- /* is the initiator the XAUTH client? */
- bool xauth_init = ( initiator && (st->st_policy & POLICY_XAUTH_SERVER) == LEMPTY)
- || (!initiator && (st->st_policy & POLICY_XAUTH_SERVER) != LEMPTY);
-
- switch (val)
- {
- case OAKLEY_PRESHARED_KEY:
- if ((iap & POLICY_PSK) == LEMPTY)
- {
- ugh = "policy does not allow pre-shared key authentication";
- }
- else
- {
- ugh = find_preshared_key(st);
- ta.auth = OAKLEY_PRESHARED_KEY;
- }
- break;
- case XAUTHInitPreShared:
- if ((iap & POLICY_XAUTH_PSK) == LEMPTY || !xauth_init)
- {
- ugh = "policy does not allow XAUTHInitPreShared authentication";
- }
- else
- {
- ugh = find_preshared_key(st);
- ta.auth = XAUTHInitPreShared;
- }
- break;
- case XAUTHRespPreShared:
- if ((iap & POLICY_XAUTH_PSK) == LEMPTY || xauth_init)
- {
- ugh = "policy does not allow XAUTHRespPreShared authentication";
- }
- else
- {
- ugh = find_preshared_key(st);
- ta.auth = XAUTHRespPreShared;
- }
- break;
- case OAKLEY_RSA_SIG:
- case OAKLEY_ECDSA_256:
- case OAKLEY_ECDSA_384:
- case OAKLEY_ECDSA_521:
- if ((iap & POLICY_PUBKEY) == LEMPTY)
- {
- ugh = "policy does not allow public key authentication";
- }
- else
- {
- ta.auth = val;
- }
- break;
- case XAUTHInitRSA:
- if ((iap & POLICY_XAUTH_RSASIG) == LEMPTY || !xauth_init)
- {
- ugh = "policy does not allow XAUTHInitRSA authentication";
- }
- else
- {
- ta.auth = XAUTHInitRSA;
- }
- break;
- case XAUTHRespRSA:
- if ((iap & POLICY_XAUTH_RSASIG) == LEMPTY || xauth_init)
- {
- ugh = "policy does not allow XAUTHRespRSA authentication";
- }
- else
- {
- ta.auth = XAUTHRespRSA;
- }
- break;
- default:
- ugh = builddiag("Pluto does not support %s authentication"
- , enum_show(&oakley_auth_names, val));
- break;
- }
- }
- break;
-
- case OAKLEY_GROUP_DESCRIPTION | ISAKMP_ATTR_AF_TV:
- ta.group = ike_alg_get_dh_group(val);
- if (ta.group == NULL)
- {
- ugh = builddiag("%s is not supported"
- , enum_show(&oakley_group_names, val));
- }
- break;
-
- case OAKLEY_LIFE_TYPE | ISAKMP_ATTR_AF_TV:
- switch (val)
- {
- case OAKLEY_LIFE_SECONDS:
- case OAKLEY_LIFE_KILOBYTES:
- if (LHAS(seen_durations, val))
- {
- loglog(RC_LOG_SERIOUS
- , "attribute OAKLEY_LIFE_TYPE value %s repeated"
- , enum_show(&oakley_lifetime_names, val));
- return ISAKMP_BAD_PROPOSAL_SYNTAX;
- }
- seen_durations |= LELEM(val);
- life_type = val;
- break;
- default:
- ugh = builddiag("unknown value %s"
- , enum_show(&oakley_lifetime_names, val));
- break;
- }
- break;
-
- case OAKLEY_LIFE_DURATION | ISAKMP_ATTR_AF_TLV:
- val = decode_long_duration(&attr_pbs);
- /* fall through */
- case OAKLEY_LIFE_DURATION | ISAKMP_ATTR_AF_TV:
- if (!LHAS(seen_attrs, OAKLEY_LIFE_TYPE))
- {
- ugh = "OAKLEY_LIFE_DURATION attribute not preceded by OAKLEY_LIFE_TYPE attribute";
- break;
- }
- seen_attrs &= ~(LELEM(OAKLEY_LIFE_DURATION) | LELEM(OAKLEY_LIFE_TYPE));
-
- switch (life_type)
- {
- case OAKLEY_LIFE_SECONDS:
- if (val > OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM)
- {
-#ifdef CISCO_QUIRKS
- plog("peer requested %lu seconds"
- " which exceeds our limit %d seconds"
- , (long) val
- , OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM);
- plog("lifetime reduced to %d seconds "
- "(todo: IPSEC_RESPONDER_LIFETIME notification)"
- , OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM);
- val = OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM;
-#else
- ugh = builddiag("peer requested %lu seconds"
- " which exceeds our limit %d seconds"
- , (long) val
- , OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM);
-#endif
- }
- ta.life_seconds = val;
- break;
- case OAKLEY_LIFE_KILOBYTES:
- ta.life_kilobytes = val;
- break;
- default:
- bad_case(life_type);
- }
- break;
-
- case OAKLEY_KEY_LENGTH | ISAKMP_ATTR_AF_TV:
- if ((seen_attrs & LELEM(OAKLEY_ENCRYPTION_ALGORITHM)) == 0)
- {
- ugh = "OAKLEY_KEY_LENGTH attribute not preceded by "
- "OAKLEY_ENCRYPTION_ALGORITHM attribute";
- break;
- }
- if (ta.encrypter == NULL)
- {
- ugh = "NULL encrypter with seen OAKLEY_ENCRYPTION_ALGORITHM";
- break;
- }
- /*
- * check if this keylen is compatible with specified algorithm
- */
- if (val
- && (val < ta.encrypter->keyminlen || val > ta.encrypter->keymaxlen))
- {
- ugh = "peer proposed key length not valid for "
- "encryption algorithm specified";
- }
- ta.enckeylen = val;
- break;
-#if 0 /* not yet supported */
- case OAKLEY_GROUP_TYPE | ISAKMP_ATTR_AF_TV:
- case OAKLEY_PRF | ISAKMP_ATTR_AF_TV:
- case OAKLEY_FIELD_SIZE | ISAKMP_ATTR_AF_TV:
-
- case OAKLEY_GROUP_PRIME | ISAKMP_ATTR_AF_TV:
- case OAKLEY_GROUP_PRIME | ISAKMP_ATTR_AF_TLV:
- case OAKLEY_GROUP_GENERATOR_ONE | ISAKMP_ATTR_AF_TV:
- case OAKLEY_GROUP_GENERATOR_ONE | ISAKMP_ATTR_AF_TLV:
- case OAKLEY_GROUP_GENERATOR_TWO | ISAKMP_ATTR_AF_TV:
- case OAKLEY_GROUP_GENERATOR_TWO | ISAKMP_ATTR_AF_TLV:
- case OAKLEY_GROUP_CURVE_A | ISAKMP_ATTR_AF_TV:
- case OAKLEY_GROUP_CURVE_A | ISAKMP_ATTR_AF_TLV:
- case OAKLEY_GROUP_CURVE_B | ISAKMP_ATTR_AF_TV:
- case OAKLEY_GROUP_CURVE_B | ISAKMP_ATTR_AF_TLV:
- case OAKLEY_GROUP_ORDER | ISAKMP_ATTR_AF_TV:
- case OAKLEY_GROUP_ORDER | ISAKMP_ATTR_AF_TLV:
-#endif
- default:
- /* fix compiler warning */
- memset(&ta, 0, sizeof(ta));
- ugh = "unsupported OAKLEY attribute";
- break;
- }
-
- if (ugh != NULL)
- {
- loglog(RC_LOG_SERIOUS, "%s. Attribute %s"
- , ugh, enum_show(&oakley_attr_names, a.isaat_af_type));
- break;
- }
- }
-
- /*
- * ML: at last check for allowed transforms in alg_info_ike
- * (ALG_INFO_F_STRICT flag)
- */
- if (ugh == NULL)
- {
- if (!ike_alg_ok_final(ta.encrypt, ta.enckeylen, ta.hash,
- ta.group ? ta.group->algo_id : -1, c->alg_info_ike))
- {
- ugh = "OAKLEY proposal refused";
- }
- }
-
- if (ugh == NULL)
- {
- /* a little more checking is in order */
- {
- lset_t missing
- = ~seen_attrs
- & (LELEM(OAKLEY_ENCRYPTION_ALGORITHM)
- | LELEM(OAKLEY_HASH_ALGORITHM)
- | LELEM(OAKLEY_AUTHENTICATION_METHOD)
- | LELEM(OAKLEY_GROUP_DESCRIPTION));
-
- if (missing)
- {
- loglog(RC_LOG_SERIOUS, "missing mandatory attribute(s) %s in Oakley Transform %u"
- , bitnamesof(oakley_attr_bit_names, missing)
- , trans.isat_transnum);
- return ISAKMP_BAD_PROPOSAL_SYNTAX;
- }
- }
- /* We must have liked this transform.
- * Lets finish early and leave.
- */
-
- DBG(DBG_PARSING | DBG_CRYPT
- , DBG_log("Oakley Transform %u accepted", trans.isat_transnum));
-
- if (r_sa_pbs != NULL)
- {
- struct isakmp_proposal r_proposal = *proposal;
- pb_stream r_proposal_pbs;
- struct isakmp_transform r_trans = trans;
- pb_stream r_trans_pbs;
-
- /* Situation */
- if (!out_struct(&ipsecdoisit, &ipsec_sit_desc, r_sa_pbs, NULL))
- impossible();
-
- /* Proposal */
-#ifdef EMIT_ISAKMP_SPI
- r_proposal.isap_spisize = COOKIE_SIZE;
-#else
- r_proposal.isap_spisize = 0;
-#endif
- r_proposal.isap_notrans = 1;
- if (!out_struct(&r_proposal, &isakmp_proposal_desc, r_sa_pbs, &r_proposal_pbs))
- impossible();
-
- /* SPI */
-#ifdef EMIT_ISAKMP_SPI
- if (!out_raw(my_cookie, COOKIE_SIZE, &r_proposal_pbs, "SPI"))
- impossible();
- r_proposal.isap_spisize = COOKIE_SIZE;
-#else
- /* none (0) */
-#endif
-
- /* Transform */
- r_trans.isat_np = ISAKMP_NEXT_NONE;
- if (!out_struct(&r_trans, &isakmp_isakmp_transform_desc, &r_proposal_pbs, &r_trans_pbs))
- impossible();
-
- if (!out_raw(attr_start, attr_len, &r_trans_pbs, "attributes"))
- impossible();
- close_output_pbs(&r_trans_pbs);
- close_output_pbs(&r_proposal_pbs);
- close_output_pbs(r_sa_pbs);
- }
-
- /* copy over the results */
- st->st_oakley = ta;
- return ISAKMP_NOTHING_WRONG;
- }
-
- /* on to next transform */
- no_trans_left--;
-
- if (trans.isat_np == ISAKMP_NEXT_NONE)
- {
- if (no_trans_left != 0)
- {
- loglog(RC_LOG_SERIOUS, "number of Transform Payloads disagrees with Oakley Proposal Payload");
- return ISAKMP_BAD_PROPOSAL_SYNTAX;
- }
- break;
- }
- if (trans.isat_np != ISAKMP_NEXT_T)
- {
- loglog(RC_LOG_SERIOUS, "unexpected %s payload in Oakley Proposal"
- , enum_show(&payload_names, proposal->isap_np));
- return ISAKMP_BAD_PROPOSAL_SYNTAX;
- }
- }
- loglog(RC_LOG_SERIOUS, "no acceptable Oakley Transform");
- return ISAKMP_NO_PROPOSAL_CHOSEN;
-}
-
-/* Parse the body of an IPsec SA Payload (i.e. Phase 2 / Quick Mode).
- *
- * The main routine is parse_ipsec_sa_body; other functions defined
- * between here and there are just helpers.
- *
- * Various shortcuts are taken. In particular, the policy, such as
- * it is, is hardwired.
- *
- * If r_sa is non-NULL, the body of an SA representing the selected
- * proposal is emitted into it.
- *
- * If "selection" is true, the SA is supposed to represent the
- * single transform that the peer has accepted.
- * ??? We only check that it is acceptable, not that it is one that we offered!
- *
- * Only IPsec DOI is accepted (what is the ISAKMP DOI?).
- * Error response is rudimentary.
- *
- * Since all ISAKMP groups in all SA Payloads must match, st->st_pfs_group
- * holds this across multiple payloads.
- * &unset_group signifies not yet "set"; NULL signifies NONE.
- *
- * This routine is used by quick_inI1_outR1() and quick_inR1_outI2().
- */
-
-static const struct ipsec_trans_attrs null_ipsec_trans_attrs = {
- 0, /* transid (NULL, for now) */
- 0, /* spi */
- SA_LIFE_DURATION_DEFAULT, /* life_seconds */
- SA_LIFE_DURATION_K_DEFAULT, /* life_kilobytes */
- ENCAPSULATION_MODE_UNSPECIFIED, /* encapsulation */
- AUTH_ALGORITHM_NONE, /* auth */
- 0, /* key_len */
- 0, /* key_rounds */
-};
-
-static bool parse_ipsec_transform(struct isakmp_transform *trans,
- struct ipsec_trans_attrs *attrs,
- pb_stream *prop_pbs,
- pb_stream *trans_pbs,
- struct_desc *trans_desc,
- int previous_transnum, /* or -1 if none */
- bool selection, bool is_last, bool is_ipcomp,
- struct state *st) /* current state object */
-{
- lset_t seen_attrs = 0;
- lset_t seen_durations = 0;
- u_int16_t life_type = 0;
- const struct dh_desc *pfs_group = NULL;
-
- if (!in_struct(trans, trans_desc, prop_pbs, trans_pbs))
- {
- return FALSE;
- }
- if (trans->isat_transnum <= previous_transnum)
- {
- loglog(RC_LOG_SERIOUS, "Transform Numbers in Proposal are not monotonically increasing");
- return FALSE;
- }
-
- switch (trans->isat_np)
- {
- case ISAKMP_NEXT_T:
- if (is_last)
- {
- loglog(RC_LOG_SERIOUS, "Proposal Payload has more Transforms than specified");
- return FALSE;
- }
- break;
- case ISAKMP_NEXT_NONE:
- if (!is_last)
- {
- loglog(RC_LOG_SERIOUS, "Proposal Payload has fewer Transforms than specified");
- return FALSE;
- }
- break;
- default:
- loglog(RC_LOG_SERIOUS, "expecting Transform Payload, but found %s in Proposal"
- , enum_show(&payload_names, trans->isat_np));
- return FALSE;
- }
-
- *attrs = null_ipsec_trans_attrs;
- attrs->transid = trans->isat_transid;
-
- while (pbs_left(trans_pbs) != 0)
- {
- struct isakmp_attribute a;
- pb_stream attr_pbs;
- enum_names *vdesc;
- u_int32_t val; /* room for larger value */
- bool ipcomp_inappropriate = is_ipcomp; /* will get reset if OK */
-
- if (!in_struct(&a, &isakmp_ipsec_attribute_desc, trans_pbs, &attr_pbs))
- return FALSE;
-
- passert((a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK) < 32);
-
- if (LHAS(seen_attrs, a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK))
- {
- loglog(RC_LOG_SERIOUS, "repeated %s attribute in IPsec Transform %u"
- , enum_show(&ipsec_attr_names, a.isaat_af_type)
- , trans->isat_transnum);
- return FALSE;
- }
-
- seen_attrs |= LELEM(a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK);
-
- val = a.isaat_lv;
-
- vdesc = ipsec_attr_val_descs[a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK];
- if (vdesc != NULL)
- {
- if (enum_name(vdesc, val) == NULL)
- {
- loglog(RC_LOG_SERIOUS, "invalid value %u for attribute %s in IPsec Transform"
- , (unsigned)val, enum_show(&ipsec_attr_names, a.isaat_af_type));
- return FALSE;
- }
- DBG(DBG_PARSING
- , if ((a.isaat_af_type & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV)
- DBG_log(" [%u is %s]"
- , (unsigned)val, enum_show(vdesc, val)));
- }
-
- switch (a.isaat_af_type)
- {
- case SA_LIFE_TYPE | ISAKMP_ATTR_AF_TV:
- ipcomp_inappropriate = FALSE;
- if (LHAS(seen_durations, val))
- {
- loglog(RC_LOG_SERIOUS, "attribute SA_LIFE_TYPE value %s repeated in message"
- , enum_show(&sa_lifetime_names, val));
- return FALSE;
- }
- seen_durations |= LELEM(val);
- life_type = val;
- break;
- case SA_LIFE_DURATION | ISAKMP_ATTR_AF_TLV:
- val = decode_long_duration(&attr_pbs);
- /* fall through */
- case SA_LIFE_DURATION | ISAKMP_ATTR_AF_TV:
- ipcomp_inappropriate = FALSE;
- if (!LHAS(seen_attrs, SA_LIFE_DURATION))
- {
- loglog(RC_LOG_SERIOUS, "SA_LIFE_DURATION IPsec attribute not preceded by SA_LIFE_TYPE attribute");
- return FALSE;
- }
- seen_attrs &= ~(LELEM(SA_LIFE_DURATION) | LELEM(SA_LIFE_TYPE));
-
- switch (life_type)
- {
- case SA_LIFE_TYPE_SECONDS:
- /* silently limit duration to our maximum */
- attrs->life_seconds = val <= SA_LIFE_DURATION_MAXIMUM
- ? val : SA_LIFE_DURATION_MAXIMUM;
- break;
- case SA_LIFE_TYPE_KBYTES:
- attrs->life_kilobytes = val;
- break;
- default:
- bad_case(life_type);
- }
- break;
- case GROUP_DESCRIPTION | ISAKMP_ATTR_AF_TV:
- if (is_ipcomp)
- {
- /* Accept reluctantly. Should not happen, according to
- * draft-shacham-ippcp-rfc2393bis-05.txt 4.1.
- */
- ipcomp_inappropriate = FALSE;
- loglog(RC_COMMENT
- , "IPCA (IPcomp SA) contains GROUP_DESCRIPTION."
- " Ignoring inapproprate attribute.");
- }
- pfs_group = ike_alg_get_dh_group(val);
- if (pfs_group == NULL)
- {
- loglog(RC_LOG_SERIOUS, "only OAKLEY_GROUP_MODP1024 and OAKLEY_GROUP_MODP1536 supported for PFS");
- return FALSE;
- }
- break;
- case ENCAPSULATION_MODE | ISAKMP_ATTR_AF_TV:
- ipcomp_inappropriate = FALSE;
- switch (val)
- {
- case ENCAPSULATION_MODE_TUNNEL:
- case ENCAPSULATION_MODE_TRANSPORT:
- if (st->nat_traversal & NAT_T_DETECTED)
- {
- loglog(RC_LOG_SERIOUS
- , "%s must only be used if NAT-Traversal is not detected"
- , enum_name(&enc_mode_names, val));
- /*
- * Accept it anyway because SSH-Sentinel does not
- * use UDP_TUNNEL or UDP_TRANSPORT for the diagnostic.
- *
- * remove when SSH-Sentinel is fixed
- */
-#ifdef I_DONT_CARE_OF_SSH_SENTINEL
- return FALSE;
-#endif
- }
- attrs->encapsulation = val;
- break;
- case ENCAPSULATION_MODE_UDP_TRANSPORT_DRAFTS:
-#ifndef I_KNOW_TRANSPORT_MODE_HAS_SECURITY_CONCERN_BUT_I_WANT_IT
- loglog(RC_LOG_SERIOUS
- , "NAT-Traversal: Transport mode disabled due to security concerns");
- return FALSE;
-#endif
- case ENCAPSULATION_MODE_UDP_TUNNEL_DRAFTS:
- if (st->nat_traversal & NAT_T_WITH_RFC_VALUES)
- {
- loglog(RC_LOG_SERIOUS
- , "%s must only be used with old IETF drafts"
- , enum_name(&enc_mode_names, val));
- return FALSE;
- }
- else if (st->nat_traversal & NAT_T_DETECTED)
- {
- attrs->encapsulation = val
- - ENCAPSULATION_MODE_UDP_TUNNEL_DRAFTS
- + ENCAPSULATION_MODE_TUNNEL;
- }
- else
- {
- loglog(RC_LOG_SERIOUS
- , "%s must only be used if NAT-Traversal is detected"
- , enum_name(&enc_mode_names, val));
- return FALSE;
- }
- break;
- case ENCAPSULATION_MODE_UDP_TRANSPORT_RFC:
-#ifndef I_KNOW_TRANSPORT_MODE_HAS_SECURITY_CONCERN_BUT_I_WANT_IT
- loglog(RC_LOG_SERIOUS
- , "NAT-Traversal: Transport mode disabled due "
- "to security concerns");
- return FALSE;
-#endif
- case ENCAPSULATION_MODE_UDP_TUNNEL_RFC:
- if ((st->nat_traversal & NAT_T_DETECTED)
- && (st->nat_traversal & NAT_T_WITH_RFC_VALUES))
- {
- attrs->encapsulation = val
- - ENCAPSULATION_MODE_UDP_TUNNEL_RFC
- + ENCAPSULATION_MODE_TUNNEL;
- }
- else if (st->nat_traversal & NAT_T_DETECTED)
- {
- loglog(RC_LOG_SERIOUS
- , "%s must only be used with NAT-T RFC"
- , enum_name(&enc_mode_names, val));
- return FALSE;
- }
- else
- {
- loglog(RC_LOG_SERIOUS
- , "%s must only be used if NAT-Traversal is detected"
- , enum_name(&enc_mode_names, val));
- return FALSE;
- }
- break;
- default:
- loglog(RC_LOG_SERIOUS
- , "unknown ENCAPSULATION_MODE %d in IPSec SA", val);
- return FALSE;
- }
- break;
- case AUTH_ALGORITHM | ISAKMP_ATTR_AF_TV:
- attrs->auth = val;
- break;
- case KEY_LENGTH | ISAKMP_ATTR_AF_TV:
- attrs->key_len = val;
- break;
- case KEY_ROUNDS | ISAKMP_ATTR_AF_TV:
- attrs->key_rounds = val;
- break;
-#if 0 /* not yet implemented */
- case COMPRESS_DICT_SIZE | ISAKMP_ATTR_AF_TV:
- break;
- case COMPRESS_PRIVATE_ALG | ISAKMP_ATTR_AF_TV:
- break;
-
- case SA_LIFE_DURATION | ISAKMP_ATTR_AF_TLV:
- break;
- case COMPRESS_PRIVATE_ALG | ISAKMP_ATTR_AF_TLV:
- break;
-#endif
- default:
- loglog(RC_LOG_SERIOUS, "unsupported IPsec attribute %s"
- , enum_show(&ipsec_attr_names, a.isaat_af_type));
- return FALSE;
- }
- if (ipcomp_inappropriate)
- {
- loglog(RC_LOG_SERIOUS, "IPsec attribute %s inappropriate for IPCOMP"
- , enum_show(&ipsec_attr_names, a.isaat_af_type));
- return FALSE;
- }
- }
-
- /* Although an IPCOMP SA (IPCA) ought not to have a pfs_group,
- * if it does, demand that it be consistent.
- * See draft-shacham-ippcp-rfc2393bis-05.txt 4.1.
- */
- if (!is_ipcomp || pfs_group != NULL)
- {
- if (st->st_pfs_group == &unset_group)
- st->st_pfs_group = pfs_group;
-
- if (st->st_pfs_group != pfs_group)
- {
- loglog(RC_LOG_SERIOUS, "GROUP_DESCRIPTION inconsistent with that of %s in IPsec SA"
- , selection? "the Proposal" : "a previous Transform");
- return FALSE;
- }
- }
-
- if (LHAS(seen_attrs, SA_LIFE_DURATION))
- {
- loglog(RC_LOG_SERIOUS, "SA_LIFE_TYPE IPsec attribute not followed by SA_LIFE_DURATION attribute in message");
- return FALSE;
- }
-
- if (!LHAS(seen_attrs, ENCAPSULATION_MODE))
- {
- if (is_ipcomp)
- {
- /* draft-shacham-ippcp-rfc2393bis-05.txt 4.1:
- * "If the Encapsulation Mode is unspecified,
- * the default value of Transport Mode is assumed."
- * This contradicts/overrides the DOI (quuoted below).
- */
- attrs->encapsulation = ENCAPSULATION_MODE_TRANSPORT;
- }
- else
- {
- /* ??? Technically, RFC 2407 (IPSEC DOI) 4.5 specifies that
- * the default is "unspecified (host-dependent)".
- * This makes little sense, so we demand that it be specified.
- */
- loglog(RC_LOG_SERIOUS, "IPsec Transform must specify ENCAPSULATION_MODE");
- return FALSE;
- }
- }
-
- /* ??? should check for key_len and/or key_rounds if required */
-
- return TRUE;
-}
-
-static void
-echo_proposal(
- struct isakmp_proposal r_proposal, /* proposal to emit */
- struct isakmp_transform r_trans, /* winning transformation within it */
- u_int8_t np, /* Next Payload for proposal */
- pb_stream *r_sa_pbs, /* SA PBS into which to emit */
- struct ipsec_proto_info *pi, /* info about this protocol instance */
- struct_desc *trans_desc, /* descriptor for this transformation */
- pb_stream *trans_pbs, /* PBS for incoming transform */
- struct spd_route *sr, /* host details for the association */
- bool tunnel_mode) /* true for inner most tunnel SA */
-{
- pb_stream r_proposal_pbs;
- pb_stream r_trans_pbs;
-
- /* Proposal */
- r_proposal.isap_np = np;
- r_proposal.isap_notrans = 1;
- if (!out_struct(&r_proposal, &isakmp_proposal_desc, r_sa_pbs, &r_proposal_pbs))
- impossible();
-
- /* allocate and emit our CPI/SPI */
- if (r_proposal.isap_protoid == PROTO_IPCOMP)
- {
- /* CPI is stored in network low order end of an
- * ipsec_spi_t. So we start a couple of bytes in.
- * Note: we may fail to generate a satisfactory CPI,
- * but we'll ignore that.
- */
- pi->our_spi = get_my_cpi(sr, tunnel_mode);
- out_raw((u_char *) &pi->our_spi
- + IPSEC_DOI_SPI_SIZE - IPCOMP_CPI_SIZE
- , IPCOMP_CPI_SIZE
- , &r_proposal_pbs, "CPI");
- }
- else
- {
- pi->our_spi = get_ipsec_spi(pi->attrs.spi
- , r_proposal.isap_protoid == PROTO_IPSEC_AH ?
- IPPROTO_AH : IPPROTO_ESP
- , sr
- , tunnel_mode);
- /* XXX should check for errors */
- out_raw((u_char *) &pi->our_spi, IPSEC_DOI_SPI_SIZE
- , &r_proposal_pbs, "SPI");
- }
-
- /* Transform */
- r_trans.isat_np = ISAKMP_NEXT_NONE;
- if (!out_struct(&r_trans, trans_desc, &r_proposal_pbs, &r_trans_pbs))
- impossible();
-
- /* Transform Attributes: pure echo */
- trans_pbs->cur = trans_pbs->start + sizeof(struct isakmp_transform);
- if (!out_raw(trans_pbs->cur, pbs_left(trans_pbs)
- , &r_trans_pbs, "attributes"))
- impossible();
-
- close_output_pbs(&r_trans_pbs);
- close_output_pbs(&r_proposal_pbs);
-}
-
-notification_t
-parse_ipsec_sa_body(
- pb_stream *sa_pbs, /* body of input SA Payload */
- const struct isakmp_sa *sa, /* header of input SA Payload */
- pb_stream *r_sa_pbs, /* if non-NULL, where to emit body of winning SA */
- bool selection, /* if this SA is a selection, only one transform may appear */
- struct state *st) /* current state object */
-{
- const connection_t *c = st->st_connection;
- u_int32_t ipsecdoisit;
- pb_stream next_proposal_pbs;
-
- struct isakmp_proposal next_proposal;
- ipsec_spi_t next_spi;
-
- bool next_full = TRUE;
-
- /* DOI */
- if (sa->isasa_doi != ISAKMP_DOI_IPSEC)
- {
- loglog(RC_LOG_SERIOUS, "Unknown or unsupported DOI %s", enum_show(&doi_names, sa->isasa_doi));
- /* XXX Could send notification back */
- return ISAKMP_DOI_NOT_SUPPORTED;
- }
-
- /* Situation */
- if (!in_struct(&ipsecdoisit, &ipsec_sit_desc, sa_pbs, NULL))
- return ISAKMP_SITUATION_NOT_SUPPORTED;
-
- if (ipsecdoisit != SIT_IDENTITY_ONLY)
- {
- loglog(RC_LOG_SERIOUS, "unsupported IPsec DOI situation (%s)"
- , bitnamesof(sit_bit_names, ipsecdoisit));
- /* XXX Could send notification back */
- return ISAKMP_SITUATION_NOT_SUPPORTED;
- }
-
- /* The rules for IPsec SAs are scattered.
- * RFC 2408 "ISAKMP" section 4.2 gives some info.
- * There may be multiple proposals. Those with identical proposal
- * numbers must be considered as conjuncts. Those with different
- * numbers are disjuncts.
- * Each proposal may have several transforms, each considered
- * an alternative.
- * Each transform may have several attributes, all applying.
- *
- * To handle the way proposals are combined, we need to do a
- * look-ahead.
- */
-
- if (!in_struct(&next_proposal, &isakmp_proposal_desc, sa_pbs, &next_proposal_pbs))
- return ISAKMP_BAD_PROPOSAL_SYNTAX;
-
- /* for each conjunction of proposals... */
- while (next_full)
- {
- int propno = next_proposal.isap_proposal;
- pb_stream ah_prop_pbs, esp_prop_pbs, ipcomp_prop_pbs;
- struct isakmp_proposal ah_proposal = {0, 0, 0, 0, 0, 0, 0};
- struct isakmp_proposal esp_proposal = {0, 0, 0, 0, 0, 0, 0};
- struct isakmp_proposal ipcomp_proposal = {0, 0, 0, 0, 0, 0, 0};
- ipsec_spi_t ah_spi = 0;
- ipsec_spi_t esp_spi = 0;
- ipsec_spi_t ipcomp_cpi = 0;
- bool ah_seen = FALSE;
- bool esp_seen = FALSE;
- bool ipcomp_seen = FALSE;
- bool tunnel_mode = FALSE;
- int inner_proto = 0;
- u_int16_t well_known_cpi = 0;
-
- pb_stream ah_trans_pbs, esp_trans_pbs, ipcomp_trans_pbs;
- struct isakmp_transform ah_trans, esp_trans, ipcomp_trans;
- struct ipsec_trans_attrs ah_attrs, esp_attrs, ipcomp_attrs;
-
- /* for each proposal in the conjunction */
- do {
-
- if (next_proposal.isap_protoid == PROTO_IPCOMP)
- {
- /* IPCOMP CPI */
- if (next_proposal.isap_spisize == IPSEC_DOI_SPI_SIZE)
- {
- /* This code is to accommodate those peculiar
- * implementations that send a CPI in the bottom of an
- * SPI-sized field.
- * See draft-shacham-ippcp-rfc2393bis-05.txt 4.1
- */
- u_int8_t filler[IPSEC_DOI_SPI_SIZE - IPCOMP_CPI_SIZE];
-
- if (!in_raw(filler, sizeof(filler)
- , &next_proposal_pbs, "CPI filler")
- || !all_zero(filler, sizeof(filler)))
- return ISAKMP_INVALID_SPI;
- }
- else if (next_proposal.isap_spisize != IPCOMP_CPI_SIZE)
- {
- loglog(RC_LOG_SERIOUS, "IPsec Proposal with improper CPI size (%u)"
- , next_proposal.isap_spisize);
- return ISAKMP_INVALID_SPI;
- }
-
- /* We store CPI in the low order of a network order
- * ipsec_spi_t. So we start a couple of bytes in.
- */
- zero(&next_spi);
- if (!in_raw((u_char *)&next_spi
- + IPSEC_DOI_SPI_SIZE - IPCOMP_CPI_SIZE
- , IPCOMP_CPI_SIZE, &next_proposal_pbs, "CPI"))
- return ISAKMP_INVALID_SPI;
-
- /* If sanity ruled, CPIs would have to be such that
- * the SAID (the triple (CPI, IPCOM, destination IP))
- * would be unique, just like for SPIs. But there is a
- * perversion where CPIs can be well-known and consequently
- * the triple is not unique. We hide this fact from
- * ourselves by fudging the top 16 bits to make
- * the property true internally!
- */
- switch (ntohl(next_spi))
- {
- case IPCOMP_DEFLATE:
- well_known_cpi = ntohl(next_spi);
- next_spi = uniquify_his_cpi(next_spi, st);
- if (next_spi == 0)
- {
- loglog(RC_LOG_SERIOUS
- , "IPsec Proposal contains well-known CPI that I cannot uniquify");
- return ISAKMP_INVALID_SPI;
- }
- break;
- default:
- if (ntohl(next_spi) < IPCOMP_FIRST_NEGOTIATED
- || ntohl(next_spi) > IPCOMP_LAST_NEGOTIATED)
- {
- loglog(RC_LOG_SERIOUS, "IPsec Proposal contains CPI from non-negotiated range (0x%lx)"
- , (unsigned long) ntohl(next_spi));
- return ISAKMP_INVALID_SPI;
- }
- break;
- }
- }
- else
- {
- /* AH or ESP SPI */
- if (next_proposal.isap_spisize != IPSEC_DOI_SPI_SIZE)
- {
- loglog(RC_LOG_SERIOUS, "IPsec Proposal with improper SPI size (%u)"
- , next_proposal.isap_spisize);
- return ISAKMP_INVALID_SPI;
- }
-
- if (!in_raw((u_char *)&next_spi, sizeof(next_spi), &next_proposal_pbs, "SPI"))
- return ISAKMP_INVALID_SPI;
-
- /* SPI value 0 is invalid and values 1-255 are reserved to IANA.
- * RFC 2402 (ESP) 2.4, RFC 2406 (AH) 2.1
- * IPCOMP???
- */
- if (ntohl(next_spi) < IPSEC_DOI_SPI_MIN)
- {
- loglog(RC_LOG_SERIOUS, "IPsec Proposal contains invalid SPI (0x%lx)"
- , (unsigned long) ntohl(next_spi));
- return ISAKMP_INVALID_SPI;
- }
- }
-
- if (next_proposal.isap_notrans == 0)
- {
- loglog(RC_LOG_SERIOUS, "IPsec Proposal contains no Transforms");
- return ISAKMP_BAD_PROPOSAL_SYNTAX;
- }
-
- switch (next_proposal.isap_protoid)
- {
- case PROTO_IPSEC_AH:
- if (ah_seen)
- {
- loglog(RC_LOG_SERIOUS, "IPsec SA contains two simultaneous AH Proposals");
- return ISAKMP_BAD_PROPOSAL_SYNTAX;
- }
- ah_seen = TRUE;
- ah_prop_pbs = next_proposal_pbs;
- ah_proposal = next_proposal;
- ah_spi = next_spi;
- break;
-
- case PROTO_IPSEC_ESP:
- if (esp_seen)
- {
- loglog(RC_LOG_SERIOUS, "IPsec SA contains two simultaneous ESP Proposals");
- return ISAKMP_BAD_PROPOSAL_SYNTAX;
- }
- esp_seen = TRUE;
- esp_prop_pbs = next_proposal_pbs;
- esp_proposal = next_proposal;
- esp_spi = next_spi;
- break;
-
- case PROTO_IPCOMP:
- if (ipcomp_seen)
- {
- loglog(RC_LOG_SERIOUS, "IPsec SA contains two simultaneous IPCOMP Proposals");
- return ISAKMP_BAD_PROPOSAL_SYNTAX;
- }
- ipcomp_seen = TRUE;
- ipcomp_prop_pbs = next_proposal_pbs;
- ipcomp_proposal = next_proposal;
- ipcomp_cpi = next_spi;
- break;
-
- default:
- loglog(RC_LOG_SERIOUS, "unexpected Protocol ID (%s) in IPsec Proposal"
- , enum_show(&protocol_names, next_proposal.isap_protoid));
- return ISAKMP_INVALID_PROTOCOL_ID;
- }
-
- /* refill next_proposal */
- if (next_proposal.isap_np == ISAKMP_NEXT_NONE)
- {
- next_full = FALSE;
- break;
- }
- else if (next_proposal.isap_np != ISAKMP_NEXT_P)
- {
- loglog(RC_LOG_SERIOUS, "unexpected in Proposal: %s"
- , enum_show(&payload_names, next_proposal.isap_np));
- return ISAKMP_BAD_PROPOSAL_SYNTAX;
- }
-
- if (!in_struct(&next_proposal, &isakmp_proposal_desc, sa_pbs, &next_proposal_pbs))
- return ISAKMP_BAD_PROPOSAL_SYNTAX;
- } while (next_proposal.isap_proposal == propno);
-
- /* Now that we have all conjuncts, we should try
- * the Cartesian product of eachs tranforms!
- * At the moment, we take short-cuts on account of
- * our rudimentary hard-wired policy.
- * For now, we find an acceptable AH (if any)
- * and then an acceptable ESP. The only interaction
- * is that the ESP acceptance can know whether there
- * was an acceptable AH and hence not require an AUTH.
- */
-
- if (ah_seen)
- {
- int previous_transnum = -1;
- int tn;
-
- for (tn = 0; tn != ah_proposal.isap_notrans; tn++)
- {
- int ok_transid = 0;
- bool ok_auth = FALSE;
-
- if (!parse_ipsec_transform(&ah_trans
- , &ah_attrs
- , &ah_prop_pbs
- , &ah_trans_pbs
- , &isakmp_ah_transform_desc
- , previous_transnum
- , selection
- , tn == ah_proposal.isap_notrans - 1
- , FALSE
- , st))
- return ISAKMP_BAD_PROPOSAL_SYNTAX;
-
- previous_transnum = ah_trans.isat_transnum;
-
- /* we must understand ah_attrs.transid
- * COMBINED with ah_attrs.auth.
- * See RFC 2407 "IPsec DOI" section 4.4.3
- * The following combinations are legal,
- * but we don't implement all of them:
- * It seems as if each auth algorithm
- * only applies to one ah transid.
- * AH_MD5, AUTH_ALGORITHM_HMAC_MD5
- * AH_MD5, AUTH_ALGORITHM_KPDK (unimplemented)
- * AH_SHA, AUTH_ALGORITHM_HMAC_SHA1
- * AH_DES, AUTH_ALGORITHM_DES_MAC (unimplemented)
- */
- switch (ah_attrs.auth)
- {
- case AUTH_ALGORITHM_NONE:
- loglog(RC_LOG_SERIOUS, "AUTH_ALGORITHM attribute missing in AH Transform");
- return ISAKMP_BAD_PROPOSAL_SYNTAX;
-
- case AUTH_ALGORITHM_HMAC_MD5:
- ok_auth = TRUE;
- /* fall through */
- case AUTH_ALGORITHM_KPDK:
- ok_transid = AH_MD5;
- break;
-
- case AUTH_ALGORITHM_HMAC_SHA1:
- ok_auth = TRUE;
- ok_transid = AH_SHA;
- break;
-
- case AUTH_ALGORITHM_DES_MAC:
- ok_transid = AH_DES;
- break;
- }
- if (ah_attrs.transid != ok_transid)
- {
- loglog(RC_LOG_SERIOUS, "%s attribute inappropriate in %s Transform"
- , enum_name(&auth_alg_names, ah_attrs.auth)
- , enum_show(&ah_transform_names, ah_attrs.transid));
- return ISAKMP_BAD_PROPOSAL_SYNTAX;
- }
- if (!ok_auth)
- {
- DBG(DBG_CONTROL | DBG_CRYPT
- , DBG_log("%s attribute unsupported"
- " in %s Transform from %s"
- , enum_name(&auth_alg_names, ah_attrs.auth)
- , enum_show(&ah_transform_names, ah_attrs.transid)
- , ip_str(&c->spd.that.host_addr)));
- continue; /* try another */
- }
- break; /* we seem to be happy */
- }
- if (tn == ah_proposal.isap_notrans)
- continue; /* we didn't find a nice one */
- ah_attrs.spi = ah_spi;
- inner_proto = IPPROTO_AH;
- if (ah_attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL)
- tunnel_mode = TRUE;
- }
-
- if (esp_seen)
- {
- int previous_transnum = -1;
- int tn;
-
- for (tn = 0; tn != esp_proposal.isap_notrans; tn++)
- {
- if (!parse_ipsec_transform(&esp_trans
- , &esp_attrs
- , &esp_prop_pbs
- , &esp_trans_pbs
- , &isakmp_esp_transform_desc
- , previous_transnum
- , selection
- , tn == esp_proposal.isap_notrans - 1
- , FALSE
- , st))
- return ISAKMP_BAD_PROPOSAL_SYNTAX;
-
- previous_transnum = esp_trans.isat_transnum;
-
- /* set default key length for AES encryption */
- if (!esp_attrs.key_len && esp_attrs.transid == ESP_AES)
- {
- esp_attrs.key_len = 128; /* bits */
- }
-
- if (!kernel_alg_esp_enc_ok(esp_attrs.transid, esp_attrs.key_len
- ,c->alg_info_esp))
- {
- switch (esp_attrs.transid)
- {
- case ESP_3DES:
- break;
-#ifdef SUPPORT_ESP_NULL /* should be about as secure as AH-only */
- case ESP_NULL:
- if (esp_attrs.auth == AUTH_ALGORITHM_NONE)
- {
- loglog(RC_LOG_SERIOUS, "ESP_NULL requires auth algorithm");
- return BAD_PROPOSAL_SYNTAX;
- }
- if (st->st_policy & POLICY_ENCRYPT)
- {
- DBG(DBG_CONTROL | DBG_CRYPT
- , DBG_log("ESP_NULL Transform Proposal from %s"
- " does not satisfy POLICY_ENCRYPT"
- , ip_str(&c->spd.that.host_addr)));
- continue; /* try another */
- }
- break;
-#endif
- default:
- DBG(DBG_CONTROL | DBG_CRYPT
- , DBG_log("unsupported ESP Transform %s from %s"
- , enum_show(&esp_transform_names, esp_attrs.transid)
- , ip_str(&c->spd.that.host_addr)));
- continue; /* try another */
- }
- }
-
- if (!kernel_alg_esp_auth_ok(esp_attrs.auth, c->alg_info_esp))
- {
- switch (esp_attrs.auth)
- {
- case AUTH_ALGORITHM_NONE:
- if (!ah_seen)
- {
- DBG(DBG_CONTROL | DBG_CRYPT
- , DBG_log("ESP from %s must either have AUTH or be combined with AH"
- , ip_str(&c->spd.that.host_addr)));
- continue; /* try another */
- }
- break;
- case AUTH_ALGORITHM_HMAC_MD5:
- case AUTH_ALGORITHM_HMAC_SHA1:
- break;
- default:
- DBG(DBG_CONTROL | DBG_CRYPT
- , DBG_log("unsupported ESP auth alg %s from %s"
- , enum_show(&auth_alg_names, esp_attrs.auth)
- , ip_str(&c->spd.that.host_addr)));
- continue; /* try another */
- }
- }
-
- /* A last check for allowed transforms in alg_info_esp
- * (ALG_INFO_F_STRICT flag)
- */
- if (!kernel_alg_esp_ok_final(esp_attrs.transid, esp_attrs.key_len
- ,esp_attrs.auth, c->alg_info_esp))
- {
- continue;
- }
-
- if (ah_seen && ah_attrs.encapsulation != esp_attrs.encapsulation)
- {
- /* ??? This should be an error, but is it? */
- DBG(DBG_CONTROL | DBG_CRYPT
- , DBG_log("AH and ESP transforms disagree about encapsulation; TUNNEL presumed"));
- }
-
- break; /* we seem to be happy */
- }
- if (tn == esp_proposal.isap_notrans)
- continue; /* we didn't find a nice one */
-
- esp_attrs.spi = esp_spi;
- inner_proto = IPPROTO_ESP;
- if (esp_attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL)
- tunnel_mode = TRUE;
- }
- else if (st->st_policy & POLICY_ENCRYPT)
- {
- DBG(DBG_CONTROL | DBG_CRYPT
- , DBG_log("policy for \"%s\" requires encryption but ESP not in Proposal from %s"
- , c->name, ip_str(&c->spd.that.host_addr)));
- continue; /* we needed encryption, but didn't find ESP */
- }
- else if ((st->st_policy & POLICY_AUTHENTICATE) && !ah_seen)
- {
- DBG(DBG_CONTROL | DBG_CRYPT
- , DBG_log("policy for \"%s\" requires authentication"
- " but none in Proposal from %s"
- , c->name, ip_str(&c->spd.that.host_addr)));
- continue; /* we need authentication, but we found neither ESP nor AH */
- }
-
- if (ipcomp_seen)
- {
- int previous_transnum = -1;
- int tn;
-
-#ifdef NEVER /* we think IPcomp is working now */
- /**** FUDGE TO PREVENT UNREQUESTED IPCOMP:
- **** NEEDED BECAUSE OUR IPCOMP IS EXPERIMENTAL (UNSTABLE).
- ****/
- if (!(st->st_policy & POLICY_COMPRESS))
- {
- plog("compression proposed by %s, but policy for \"%s\" forbids it"
- , ip_str(&c->spd.that.host_addr), c->name);
- continue; /* unwanted compression proposal */
- }
-#endif
- if (!can_do_IPcomp)
- {
- plog("compression proposed by %s, but kernel does not support IPCOMP"
- , ip_str(&c->spd.that.host_addr));
- continue;
- }
-
- if (well_known_cpi != 0 && !ah_seen && !esp_seen)
- {
- plog("illegal proposal: bare IPCOMP used with well-known CPI");
- return ISAKMP_BAD_PROPOSAL_SYNTAX;
- }
-
- for (tn = 0; tn != ipcomp_proposal.isap_notrans; tn++)
- {
- if (!parse_ipsec_transform(&ipcomp_trans
- , &ipcomp_attrs
- , &ipcomp_prop_pbs
- , &ipcomp_trans_pbs
- , &isakmp_ipcomp_transform_desc
- , previous_transnum
- , selection
- , tn == ipcomp_proposal.isap_notrans - 1
- , TRUE
- , st))
- return ISAKMP_BAD_PROPOSAL_SYNTAX;
-
- previous_transnum = ipcomp_trans.isat_transnum;
-
- if (well_known_cpi != 0 && ipcomp_attrs.transid != well_known_cpi)
- {
- plog("illegal proposal: IPCOMP well-known CPI disagrees with transform");
- return ISAKMP_BAD_PROPOSAL_SYNTAX;
- }
-
- switch (ipcomp_attrs.transid)
- {
- case IPCOMP_DEFLATE: /* all we can handle! */
- break;
-
- default:
- DBG(DBG_CONTROL | DBG_CRYPT
- , DBG_log("unsupported IPCOMP Transform %s from %s"
- , enum_show(&ipcomp_transformid_names, ipcomp_attrs.transid)
- , ip_str(&c->spd.that.host_addr)));
- continue; /* try another */
- }
-
- if (ah_seen && ah_attrs.encapsulation != ipcomp_attrs.encapsulation)
- {
- /* ??? This should be an error, but is it? */
- DBG(DBG_CONTROL | DBG_CRYPT
- , DBG_log("AH and IPCOMP transforms disagree about encapsulation; TUNNEL presumed"));
- } else if (esp_seen && esp_attrs.encapsulation != ipcomp_attrs.encapsulation)
- {
- /* ??? This should be an error, but is it? */
- DBG(DBG_CONTROL | DBG_CRYPT
- , DBG_log("ESP and IPCOMP transforms disagree about encapsulation; TUNNEL presumed"));
- }
-
- break; /* we seem to be happy */
- }
- if (tn == ipcomp_proposal.isap_notrans)
- continue; /* we didn't find a nice one */
- ipcomp_attrs.spi = ipcomp_cpi;
- inner_proto = IPPROTO_COMP;
- if (ipcomp_attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL)
- tunnel_mode = TRUE;
- }
-
- /* Eureka: we liked what we saw -- accept it. */
-
- if (r_sa_pbs != NULL)
- {
- /* emit what we've accepted */
-
- /* Situation */
- if (!out_struct(&ipsecdoisit, &ipsec_sit_desc, r_sa_pbs, NULL))
- impossible();
-
- /* AH proposal */
- if (ah_seen)
- echo_proposal(ah_proposal
- , ah_trans
- , esp_seen || ipcomp_seen? ISAKMP_NEXT_P : ISAKMP_NEXT_NONE
- , r_sa_pbs
- , &st->st_ah
- , &isakmp_ah_transform_desc
- , &ah_trans_pbs
- , &st->st_connection->spd
- , tunnel_mode && inner_proto == IPPROTO_AH);
-
- /* ESP proposal */
- if (esp_seen)
- echo_proposal(esp_proposal
- , esp_trans
- , ipcomp_seen? ISAKMP_NEXT_P : ISAKMP_NEXT_NONE
- , r_sa_pbs
- , &st->st_esp
- , &isakmp_esp_transform_desc
- , &esp_trans_pbs
- , &st->st_connection->spd
- , tunnel_mode && inner_proto == IPPROTO_ESP);
-
- /* IPCOMP proposal */
- if (ipcomp_seen)
- echo_proposal(ipcomp_proposal
- , ipcomp_trans
- , ISAKMP_NEXT_NONE
- , r_sa_pbs
- , &st->st_ipcomp
- , &isakmp_ipcomp_transform_desc
- , &ipcomp_trans_pbs
- , &st->st_connection->spd
- , tunnel_mode && inner_proto == IPPROTO_COMP);
-
- close_output_pbs(r_sa_pbs);
- }
-
- /* save decoded version of winning SA in state */
-
- st->st_ah.present = ah_seen;
- if (ah_seen)
- st->st_ah.attrs = ah_attrs;
-
- st->st_esp.present = esp_seen;
- if (esp_seen)
- st->st_esp.attrs = esp_attrs;
-
- st->st_ipcomp.present = ipcomp_seen;
- if (ipcomp_seen)
- st->st_ipcomp.attrs = ipcomp_attrs;
-
- return ISAKMP_NOTHING_WRONG;
- }
-
- loglog(RC_LOG_SERIOUS, "no acceptable Proposal in IPsec SA");
- return ISAKMP_NO_PROPOSAL_CHOSEN;
-}
diff --git a/src/pluto/spdb.h b/src/pluto/spdb.h
deleted file mode 100644
index 8a0bffbbd..000000000
--- a/src/pluto/spdb.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/* Security Policy Data Base (such as it is)
- * Copyright (C) 1998, 1999 D. Hugh Redelmeier.
- *
- * 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.
- */
-
-#ifndef _SPDB_H
-#define _SPDB_H
-
-#include "packet.h"
-
-/* database of SA properties */
-
-/* Attribute type and value pair.
- * Note: only "basic" values are represented so far.
- */
-struct db_attr {
- u_int16_t type; /* ISAKMP_ATTR_AF_TV is implied; 0 for end */
- u_int16_t val;
-};
-
-/* transform */
-struct db_trans {
- u_int8_t transid; /* Transform-Id */
- struct db_attr *attrs; /* array */
- int attr_cnt; /* number of elements */
-};
-
-/* proposal */
-struct db_prop {
- u_int8_t protoid; /* Protocol-Id */
- struct db_trans *trans; /* array (disjunction) */
- int trans_cnt; /* number of elements */
- /* SPI size and value isn't part of DB */
-};
-
-/* conjunction of proposals */
-struct db_prop_conj {
- struct db_prop *props; /* array */
- int prop_cnt; /* number of elements */
-};
-
-/* security association */
-struct db_sa {
- struct db_prop_conj *prop_conjs; /* array */
- int prop_conj_cnt; /* number of elements */
- /* Hardwired for now;
- * DOI: ISAKMP_DOI_IPSEC
- * Situation: SIT_IDENTITY_ONLY
- */
-};
-
-/* The oakley sadb */
-extern struct db_sa oakley_sadb;
-
-/* The ipsec sadb is subscripted by a bitset with members
- * from POLICY_ENCRYPT, POLICY_AUTHENTICATE, POLICY_COMPRESS
- */
-extern struct db_sa ipsec_sadb[1 << 3];
-
-/* forward declaration */
-struct state;
-
-extern bool out_sa(
- pb_stream *outs,
- struct db_sa *sadb,
- struct state *st,
- bool oakley_mode,
- u_int8_t np);
-
-extern notification_t preparse_isakmp_sa_body(
- const struct isakmp_sa *sa, /* header of input SA Payload */
- pb_stream *sa_pbs, /* body of input SA Payload */
- u_int32_t *ipsecdoisit, /* IPsec DOI SIT bitset */
- pb_stream *proposal_pbs, /* body of proposal Payload */
- struct isakmp_proposal *proposal);
-
-extern notification_t parse_isakmp_policy(
- pb_stream *proposal_pbs, /* body of proposal Payload */
- u_int notrans, /* number of transforms */
- lset_t *policy); /* RSA, PSK or XAUTH policy */
-
-extern notification_t parse_isakmp_sa_body(
- u_int32_t ipsecdoisit, /* IPsec DOI SIT bitset */
- pb_stream *proposal_pbs, /* body of proposal Payload */
- struct isakmp_proposal *proposal,
- pb_stream *r_sa_pbs, /* if non-NULL, where to emit winning SA */
- struct state *st, /* current state object */
- bool initiator); /* is caller initiator? */
-
-extern notification_t parse_ipsec_sa_body(
- pb_stream *sa_pbs, /* body of input SA Payload */
- const struct isakmp_sa *sa, /* header of input SA Payload */
- pb_stream *r_sa_pbs, /* if non-NULL, where to emit winning SA */
- bool selection, /* if this SA is a selection, only one transform can appear */
- struct state *st); /* current state object */
-
-extern void backup_pbs(pb_stream *pbs);
-extern void restore_pbs(pb_stream *pbs);
-
-#endif /* _SPDB_H */
-
diff --git a/src/pluto/state.c b/src/pluto/state.c
deleted file mode 100644
index f5185888e..000000000
--- a/src/pluto/state.c
+++ /dev/null
@@ -1,952 +0,0 @@
-/* routines for state objects
- * Copyright (C) 1997 Angelos D. Keromytis.
- * Copyright (C) 1998-2001 D. Hugh Redelmeier.
- * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <fcntl.h>
-#include <sys/queue.h>
-
-#include <freeswan.h>
-
-#include <library.h>
-#include <crypto/rngs/rng.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "connections.h"
-#include "state.h"
-#include "kernel.h"
-#include "log.h"
-#include "packet.h" /* so we can calculate sizeof(struct isakmp_hdr) */
-#include "keys.h" /* for free_public_key */
-#include "timer.h"
-#include "whack.h"
-#include "demux.h" /* needs packet.h */
-#include "ipsec_doi.h" /* needs demux.h and state.h */
-#include "crypto.h"
-
-/*
- * Global variables: had to go somewhere, might as well be this file.
- */
-
-u_int16_t pluto_port = IKE_UDP_PORT; /* Pluto's port */
-
-/*
- * This file has the functions that handle the
- * state hash table and the Message ID list.
- */
-
-/* Message-IDs
- *
- * A Message ID is contained in each IKE message header.
- * For Phase 1 exchanges (Main and Aggressive), it will be zero.
- * For other exchanges, which must be under the protection of an
- * ISAKMP SA, the Message ID must be unique within that ISAKMP SA.
- * Effectively, this labels the message as belonging to a particular
- * exchange.
- * BTW, we feel this uniqueness allows rekeying to be somewhat simpler
- * than specified by draft-jenkins-ipsec-rekeying-06.txt.
- *
- * A MessageID is a 32 bit unsigned number. We represent the value
- * internally in network order -- they are just blobs to us.
- * They are unsigned numbers to make hashing and comparing easy.
- *
- * The following mechanism is used to allocate message IDs. This
- * requires that we keep track of which numbers have already been used
- * so that we don't allocate one in use.
- */
-
-struct msgid_list
-{
- msgid_t msgid; /* network order */
- struct msgid_list *next;
-};
-
-bool reserve_msgid(struct state *isakmp_sa, msgid_t msgid)
-{
- struct msgid_list *p;
-
- passert(msgid != MAINMODE_MSGID);
- passert(IS_ISAKMP_ENCRYPTED(isakmp_sa->st_state));
-
- for (p = isakmp_sa->st_used_msgids; p != NULL; p = p->next)
- if (p->msgid == msgid)
- return FALSE;
-
- p = malloc_thing(struct msgid_list);
- p->msgid = msgid;
- p->next = isakmp_sa->st_used_msgids;
- isakmp_sa->st_used_msgids = p;
- return TRUE;
-}
-
-msgid_t generate_msgid(struct state *isakmp_sa)
-{
- int timeout = 100; /* only try so hard for unique msgid */
- msgid_t msgid;
- rng_t *rng;
-
- passert(IS_ISAKMP_ENCRYPTED(isakmp_sa->st_state));
- rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
-
- for (;;)
- {
- rng->get_bytes(rng, sizeof(msgid), (void *) &msgid);
- if (msgid != 0 && reserve_msgid(isakmp_sa, msgid))
- {
- break;
- }
- if (--timeout == 0)
- {
- plog("gave up looking for unique msgid; using 0x%08lx"
- , (unsigned long) msgid);
- break;
- }
- }
- rng->destroy(rng);
- return msgid;
-}
-
-
-/* state table functions */
-
-#define STATE_TABLE_SIZE 32
-
-static struct state *statetable[STATE_TABLE_SIZE];
-
-static struct state **state_hash(const u_char *icookie, const u_char *rcookie,
- const ip_address *peer)
-{
- u_int i = 0, j;
- const unsigned char *byte_ptr;
- size_t length = addrbytesptr(peer, &byte_ptr);
-
- DBG(DBG_RAW | DBG_CONTROL,
- DBG_dump("ICOOKIE:", icookie, COOKIE_SIZE);
- DBG_dump("RCOOKIE:", rcookie, COOKIE_SIZE);
- DBG_dump("peer:", byte_ptr, length));
-
- /* XXX the following hash is pretty pathetic */
-
- for (j = 0; j < COOKIE_SIZE; j++)
- i = i * 407 + icookie[j] + rcookie[j];
-
- for (j = 0; j < length; j++)
- i = i * 613 + byte_ptr[j];
-
- i = i % STATE_TABLE_SIZE;
-
- DBG(DBG_CONTROL, DBG_log("state hash entry %d", i));
-
- return &statetable[i];
-}
-
-/* Get a state object.
- * Caller must schedule an event for this object so that it doesn't leak.
- * Caller must insert_state().
- */
-struct state *new_state(void)
-{
- /* initialized all to zero & NULL */
- static const struct state blank_state = {
- .st_serialno = 0,
- };
- static so_serial_t next_so = SOS_FIRST;
- struct state *st;
-
- st = clone_thing(blank_state);
- st->st_serialno = next_so++;
- passert(next_so > SOS_FIRST); /* overflow can't happen! */
- st->st_whack_sock = NULL_FD;
- DBG(DBG_CONTROL, DBG_log("creating state object #%lu at %p",
- st->st_serialno, (void *) st));
- return st;
-}
-
-/*
- * Initialize the state table (and mask*).
- */
-void init_states(void)
-{
- int i;
-
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- statetable[i] = (struct state *) NULL;
-}
-
-/* Find the state object with this serial number.
- * This allows state object references that don't turn into dangerous
- * dangling pointers: reference a state by its serial number.
- * Returns NULL if there is no such state.
- * If this turns out to be a significant CPU hog, it could be
- * improved to use a hash table rather than sequential seartch.
- */
-struct state *state_with_serialno(so_serial_t sn)
-{
- if (sn >= SOS_FIRST)
- {
- struct state *st;
- int i;
-
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
- if (st->st_serialno == sn)
- return st;
- }
- return NULL;
-}
-
-/* Insert a state object in the hash table. The object is inserted
- * at the beginning of list.
- * Needs cookies, connection, and msgid.
- */
-void insert_state(struct state *st)
-{
- struct state **p = state_hash(st->st_icookie, st->st_rcookie
- , &st->st_connection->spd.that.host_addr);
-
- passert(st->st_hashchain_prev == NULL && st->st_hashchain_next == NULL);
-
- if (*p != NULL)
- {
- passert((*p)->st_hashchain_prev == NULL);
- (*p)->st_hashchain_prev = st;
- }
- st->st_hashchain_next = *p;
- *p = st;
-
- /* Ensure that somebody is in charge of killing this state:
- * if no event is scheduled for it, schedule one to discard the state.
- * If nothing goes wrong, this event will be replaced by
- * a more appropriate one.
- */
- if (st->st_event == NULL)
- event_schedule(EVENT_SO_DISCARD, 0, st);
-}
-
-/* unlink a state object from the hash table, but don't free it
- */
-void unhash_state(struct state *st)
-{
- /* unlink from forward chain */
- struct state **p = st->st_hashchain_prev == NULL
- ? state_hash(st->st_icookie, st->st_rcookie
- , &st->st_connection->spd.that.host_addr)
- : &st->st_hashchain_prev->st_hashchain_next;
-
- /* unlink from forward chain */
- passert(*p == st);
- *p = st->st_hashchain_next;
-
- /* unlink from backward chain */
- if (st->st_hashchain_next != NULL)
- {
- passert(st->st_hashchain_next->st_hashchain_prev == st);
- st->st_hashchain_next->st_hashchain_prev = st->st_hashchain_prev;
- }
-
- st->st_hashchain_next = st->st_hashchain_prev = NULL;
-}
-
-/* Free the Whack socket file descriptor.
- * This has the side effect of telling Whack that we're done.
- */
-void release_whack(struct state *st)
-{
- close_any(st->st_whack_sock);
-}
-
-/**
- * Delete a state object
- */
-void delete_state(struct state *st)
-{
- connection_t *const c = st->st_connection;
- struct state *old_cur_state = cur_state == st? NULL : cur_state;
-
- set_cur_state(st);
-
- /* If DPD is enabled on this state object, clear any pending events */
- if(st->st_dpd_event != NULL)
- delete_dpd_event(st);
-
- /* if there is a suspended state transition, disconnect us */
- if (st->st_suspended_md != NULL)
- {
- passert(st->st_suspended_md->st == st);
- st->st_suspended_md->st = NULL;
- }
-
- /* tell the other side of any IPSEC SAs that are going down */
- if (IS_IPSEC_SA_ESTABLISHED(st->st_state)
- || IS_ISAKMP_SA_ESTABLISHED(st->st_state))
- send_delete(st);
-
- delete_event(st); /* delete any pending timer event */
-
- /* Ditch anything pending on ISAKMP SA being established.
- * Note: this must be done before the unhash_state to prevent
- * flush_pending_by_state inadvertently and prematurely
- * deleting our connection.
- */
- flush_pending_by_state(st);
-
- /* effectively, this deletes any ISAKMP SA that this state represents */
- unhash_state(st);
-
- /* tell kernel to delete any IPSEC SA
- * ??? we ought to tell peer to delete IPSEC SAs
- */
- if (IS_IPSEC_SA_ESTABLISHED(st->st_state))
- delete_ipsec_sa(st, FALSE);
- else if (IS_ONLY_INBOUND_IPSEC_SA_ESTABLISHED(st->st_state))
- delete_ipsec_sa(st, TRUE);
-
- if (c->newest_ipsec_sa == st->st_serialno)
- c->newest_ipsec_sa = SOS_NOBODY;
-
- if (c->newest_isakmp_sa == st->st_serialno)
- c->newest_isakmp_sa = SOS_NOBODY;
-
- st->st_connection = NULL; /* we might be about to free it */
- cur_state = old_cur_state; /* without st_connection, st isn't complete */
- connection_discard(c);
-
- release_whack(st);
-
- /* from here on we are just freeing RAM */
-
- {
- struct msgid_list *p = st->st_used_msgids;
-
- while (p != NULL)
- {
- struct msgid_list *q = p;
- p = p->next;
- free(q);
- }
- }
-
- unreference_key(&st->st_peer_pubkey);
-
- DESTROY_IF(st->st_dh);
-
- chunk_clear(&st->st_tpacket);
- chunk_clear(&st->st_rpacket);
- chunk_clear(&st->st_p1isa);
- chunk_clear(&st->st_gi);
- chunk_clear(&st->st_gr);
- chunk_clear(&st->st_shared);
- chunk_clear(&st->st_ni);
- chunk_clear(&st->st_nr);
- chunk_clear(&st->st_skeyid);
- chunk_clear(&st->st_skeyid_d);
- chunk_clear(&st->st_skeyid_a);
- chunk_clear(&st->st_skeyid_e);
- chunk_clear(&st->st_enc_key);
-
- free(st->st_ah.our_keymat);
- free(st->st_ah.peer_keymat);
- free(st->st_esp.our_keymat);
- free(st->st_esp.peer_keymat);
-
- free(st);
-}
-
-/**
- * Is a connection in use by some state?
- */
-bool states_use_connection(connection_t *c)
-{
- /* are there any states still using it? */
- struct state *st = NULL;
- int i;
-
- for (i = 0; st == NULL && i < STATE_TABLE_SIZE; i++)
- for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
- if (st->st_connection == c)
- return TRUE;
-
- return FALSE;
-}
-
-/**
- * Delete all states that were created for a given connection.
- * if relations == TRUE, then also delete states that share
- * the same phase 1 SA.
- */
-void delete_states_by_connection(connection_t *c, bool relations)
-{
- int pass;
- /* this kludge avoids an n^2 algorithm */
- enum connection_kind ck = c->kind;
- struct spd_route *sr;
-
- /* save this connection's isakmp SA, since it will get set to later SOS_NOBODY */
- so_serial_t parent_sa = c->newest_isakmp_sa;
-
- if (ck == CK_INSTANCE)
- c->kind = CK_GOING_AWAY;
-
- /* We take two passes so that we delete any ISAKMP SAs last.
- * This allows Delete Notifications to be sent.
- * ?? We could probably double the performance by caching any
- * ISAKMP SA states found in the first pass, avoiding a second.
- */
- for (pass = 0; pass != 2; pass++)
- {
- int i;
-
- /* For each hash chain... */
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- {
- struct state *st;
-
- /* For each state in the hash chain... */
- for (st = statetable[i]; st != NULL; )
- {
- struct state *this = st;
-
- st = st->st_hashchain_next; /* before this is deleted */
-
-
- if ((this->st_connection == c
- || (relations && parent_sa != SOS_NOBODY
- && this->st_clonedfrom == parent_sa))
- && (pass == 1 || !IS_ISAKMP_SA_ESTABLISHED(this->st_state)))
- {
- struct state *old_cur_state
- = cur_state == this? NULL : cur_state;
-#ifdef DEBUG
- lset_t old_cur_debugging = cur_debugging;
-#endif
-
- set_cur_state(this);
- plog("deleting state (%s)"
- , enum_show(&state_names, this->st_state));
- delete_state(this);
- cur_state = old_cur_state;
-#ifdef DEBUG
- cur_debugging = old_cur_debugging;
-#endif
- }
- }
- }
- }
-
- sr = &c->spd;
- while (sr != NULL)
- {
- passert(sr->eroute_owner == SOS_NOBODY);
- passert(sr->routing != RT_ROUTED_TUNNEL);
- sr = sr->next;
- }
- c->kind = ck;
-}
-
-/**
- * Walk through the state table, and delete each state whose phase 1 (IKE)
- * peer is among those given.
- */
-void delete_states_by_peer(ip_address *peer)
-{
- char peerstr[ADDRTOT_BUF];
- int i;
-
- addrtot(peer, 0, peerstr, sizeof(peerstr));
-
- /* For each hash chain... */
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- {
- struct state *st;
-
- /* For each state in the hash chain... */
- for (st = statetable[i]; st != NULL; )
- {
- struct state *this = st;
- struct spd_route *sr;
- connection_t *c = this->st_connection;
-
- st = st->st_hashchain_next; /* before this is deleted */
-
- /* ??? Is it not the case that the peer is the same for all spds? */
- for (sr = &c->spd; sr != NULL; sr = sr->next)
- {
- if (sameaddr(&sr->that.host_addr, peer))
- {
- plog("peer %s for connection %s deleting - claimed to have crashed"
- , peerstr
- , c->name);
- delete_states_by_connection(c, TRUE);
- if (c->kind == CK_INSTANCE)
- delete_connection(c, TRUE);
- break; /* can only delete it once */
- }
- }
- }
- }
-}
-
-/* Duplicate a Phase 1 state object, to create a Phase 2 object.
- * Caller must schedule an event for this object so that it doesn't leak.
- * Caller must insert_state().
- */
-struct state *duplicate_state(struct state *st)
-{
- struct state *nst;
-
- DBG(DBG_CONTROL, DBG_log("duplicating state object #%lu",
- st->st_serialno));
-
- /* record use of the Phase 1 state */
- st->st_outbound_count++;
- st->st_outbound_time = now();
-
- nst = new_state();
-
- memcpy(nst->st_icookie, st->st_icookie, COOKIE_SIZE);
- memcpy(nst->st_rcookie, st->st_rcookie, COOKIE_SIZE);
-
- nst->st_connection = st->st_connection;
- nst->st_doi = st->st_doi;
- nst->st_situation = st->st_situation;
- nst->st_clonedfrom = st->st_serialno;
- nst->st_oakley = st->st_oakley;
- nst->st_modecfg = st->st_modecfg;
- nst->st_skeyid_d = chunk_clone(st->st_skeyid_d);
- nst->st_skeyid_a = chunk_clone(st->st_skeyid_a);
- nst->st_skeyid_e = chunk_clone(st->st_skeyid_e);
- nst->st_enc_key = chunk_clone(st->st_enc_key);
-
- return nst;
-}
-
-#if 1
-void for_each_state(void *(f)(struct state *, void *data), void *data)
-{
- struct state *st, *ocs = cur_state;
- int i;
- for (i=0; i<STATE_TABLE_SIZE; i++) {
- for (st = statetable[i]; st != NULL; st = st->st_hashchain_next) {
- set_cur_state(st);
- f(st, data);
- }
- }
- cur_state = ocs;
-}
-#endif
-
-/**
- * Find a state object.
- */
-struct state *find_state(const u_char *icookie, const u_char *rcookie,
- const ip_address *peer, msgid_t msgid)
-{
- struct state *st = *state_hash(icookie, rcookie, peer);
-
- while (st != (struct state *) NULL)
- {
- if (sameaddr(peer, &st->st_connection->spd.that.host_addr)
- && memeq(icookie, st->st_icookie, COOKIE_SIZE)
- && memeq(rcookie, st->st_rcookie, COOKIE_SIZE)
- && msgid == st->st_msgid)
- {
- break;
- }
- else
- {
- st = st->st_hashchain_next;
- }
- }
- DBG(DBG_CONTROL,
- if (st == NULL)
- DBG_log("state object not found");
- else
- DBG_log("state object #%lu found, in %s"
- , st->st_serialno
- , enum_show(&state_names, st->st_state)));
-
- return st;
-}
-
-/**
- * Find the state that sent a packet
- * ??? this could be expensive -- it should be rate-limited to avoid DoS
- */
-struct state *find_sender(size_t packet_len, u_char *packet)
-{
- int i;
- struct state *st;
-
- if (packet_len >= sizeof(struct isakmp_hdr))
- {
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- {
- for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
- {
- if (st->st_tpacket.ptr != NULL
- && st->st_tpacket.len == packet_len
- && memeq(st->st_tpacket.ptr, packet, packet_len))
- {
- return st;
- }
- }
- }
- }
- return NULL;
-}
-
-struct state *find_phase2_state_to_delete(const struct state *p1st,
- u_int8_t protoid, ipsec_spi_t spi,
- bool *bogus)
-{
- struct state *st;
- int i;
-
- *bogus = FALSE;
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- {
- for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
- {
- if (IS_IPSEC_SA_ESTABLISHED(st->st_state)
- && p1st->st_connection->host_pair == st->st_connection->host_pair
- && same_peer_ids(p1st->st_connection, st->st_connection, NULL))
- {
- struct ipsec_proto_info *pr = protoid == PROTO_IPSEC_AH
- ? &st->st_ah : &st->st_esp;
-
- if (pr->present)
- {
- if (pr->attrs.spi == spi)
- return st;
- if (pr->our_spi == spi)
- *bogus = TRUE;
- }
- }
- }
- }
- return NULL;
-}
-
-/**
- * Find newest Phase 1 negotiation state object for suitable for connection c
- */
-struct state *find_phase1_state(const connection_t *c, lset_t ok_states)
-{
- struct state
- *st,
- *best = NULL;
- int i;
-
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
- if (LHAS(ok_states, st->st_state)
- && c->host_pair == st->st_connection->host_pair
- && same_peer_ids(c, st->st_connection, NULL)
- && (best == NULL || best->st_serialno < st->st_serialno))
- best = st;
-
- return best;
-}
-
-void state_eroute_usage(ip_subnet *ours, ip_subnet *his, unsigned long count,
- time_t nw)
-{
- struct state *st;
- int i;
-
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- {
- for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
- {
- connection_t *c = st->st_connection;
-
- /* XXX spd-enum */
- if (IS_IPSEC_SA_ESTABLISHED(st->st_state)
- && c->spd.eroute_owner == st->st_serialno
- && c->spd.routing == RT_ROUTED_TUNNEL
- && samesubnet(&c->spd.this.client, ours)
- && samesubnet(&c->spd.that.client, his))
- {
- if (st->st_outbound_count != count)
- {
- st->st_outbound_count = count;
- st->st_outbound_time = nw;
- }
- return;
- }
- }
- }
- DBG(DBG_CONTROL,
- {
- char ourst[SUBNETTOT_BUF];
- char hist[SUBNETTOT_BUF];
-
- subnettot(ours, 0, ourst, sizeof(ourst));
- subnettot(his, 0, hist, sizeof(hist));
- DBG_log("unknown tunnel eroute %s -> %s found in scan"
- , ourst, hist);
- });
-}
-
-void fmt_state(bool all, struct state *st, time_t n, char *state_buf,
- size_t state_buf_len, char *state_buf2, size_t state_buf2_len)
-{
- /* what the heck is interesting about a state? */
- const connection_t *c = st->st_connection;
-
- long delta = st->st_event->ev_time >= n
- ? (long)(st->st_event->ev_time - n)
- : -(long)(n - st->st_event->ev_time);
-
- char inst[CONN_INST_BUF];
- const char *np1 = c->newest_isakmp_sa == st->st_serialno
- ? "; newest ISAKMP" : "";
- const char *np2 = c->newest_ipsec_sa == st->st_serialno
- ? "; newest IPSEC" : "";
- /* XXX spd-enum */
- const char *eo = c->spd.eroute_owner == st->st_serialno
- ? "; eroute owner" : "";
- const char *dpd = (all && st->st_dpd && c->dpd_action != DPD_ACTION_NONE)
- ? "; DPD active" : "";
-
- passert(st->st_event != 0);
-
- fmt_conn_instance(c, inst);
-
- snprintf(state_buf, state_buf_len
- , "#%lu: \"%s\"%s %s (%s); %N in %lds%s%s%s%s"
- , st->st_serialno
- , c->name, inst
- , enum_name(&state_names, st->st_state)
- , state_story[st->st_state]
- , timer_event_names, st->st_event->ev_type
- , delta
- , np1, np2, eo, dpd);
-
- /* print out SPIs if SAs are established */
- if (state_buf2_len != 0)
- state_buf2[0] = '\0'; /* default to empty */
- if (IS_IPSEC_SA_ESTABLISHED(st->st_state))
- {
-
- bool tunnel;
- char buf[SATOT_BUF*6 + 2*20 + 1];
- const char *p_end = buf + sizeof(buf);
- char *p = buf;
-
-# define add_said(adst, aspi, aproto) { \
- ip_said s; \
- \
- initsaid(adst, aspi, aproto, &s); \
- if (p < p_end - 1) \
- { \
- *p++ = ' '; \
- p += satot(&s, 0, p, p_end - p) - 1; \
- } \
- }
-
-# define add_sa_info(st, inbound) { \
- u_int bytes; \
- time_t use_time; \
- \
- if (get_sa_info(st, inbound, &bytes, &use_time)) \
- { \
- p += snprintf(p, p_end - p, " (%'u bytes", bytes); \
- if (bytes > 0 && use_time != UNDEFINED_TIME) \
- p += snprintf(p, p_end - p, ", %ds ago", (int)(now - use_time)); \
- p += snprintf(p, p_end - p, ")"); \
- } \
- }
-
- *p = '\0';
- if (st->st_ah.present)
- {
- add_said(&c->spd.that.host_addr, st->st_ah.attrs.spi, SA_AH);
- add_said(&c->spd.this.host_addr, st->st_ah.our_spi, SA_AH);
- }
- if (st->st_esp.present)
- {
- time_t now = time_monotonic(NULL);
-
- add_said(&c->spd.that.host_addr, st->st_esp.attrs.spi, SA_ESP);
- add_sa_info(st, FALSE);
- add_said(&c->spd.this.host_addr, st->st_esp.our_spi, SA_ESP);
- add_sa_info(st, TRUE);
- }
- if (st->st_ipcomp.present)
- {
- add_said(&c->spd.that.host_addr, st->st_ipcomp.attrs.spi, SA_COMP);
- add_said(&c->spd.this.host_addr, st->st_ipcomp.our_spi, SA_COMP);
- }
- tunnel = st->st_ah.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL
- || st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL
- || st->st_ipcomp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL;
- p += snprintf(p, p_end - p, "; %s", tunnel? "tunnel":"transport");
-
- snprintf(state_buf2, state_buf2_len
- , "#%lu: \"%s\"%s%s"
- , st->st_serialno
- , c->name, inst
- , buf);
-
-# undef add_said
-# undef add_sa_info
- }
-}
-
-/*
- * sorting logic is:
- *
- * name
- * type
- * instance#
- * isakmp_sa (XXX probably wrong)
- *
- */
-static int state_compare(const void *a, const void *b)
-{
- const struct state *sap = *(const struct state *const *)a;
- connection_t *ca = sap->st_connection;
- const struct state *sbp = *(const struct state *const *)b;
- connection_t *cb = sbp->st_connection;
-
- /* DBG_log("comparing %s to %s", ca->name, cb->name); */
-
- return connection_compare(ca, cb);
-}
-
-void show_states_status(bool all, const char *name)
-{
- time_t n = now();
- int i;
- char state_buf[LOG_WIDTH];
- char state_buf2[LOG_WIDTH];
- int count;
- struct state **array;
-
- /* make count of states */
- count = 0;
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- {
- struct state *st;
-
- for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
- {
- if (name == NULL || streq(name, st->st_connection->name))
- count++;
- }
- }
-
- /* build the array */
- array = malloc(sizeof(struct state *)*count);
- count = 0;
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- {
- struct state *st;
-
- for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
- {
- if (name == NULL || streq(name, st->st_connection->name))
- array[count++]=st;
- }
- }
-
- /* sort it! */
- qsort(array, count, sizeof(struct state *), state_compare);
-
- /* now print sorted results */
- for (i = 0; i < count; i++)
- {
- struct state *st;
-
- st = array[i];
-
- fmt_state(all, st, n
- , state_buf, sizeof(state_buf)
- , state_buf2, sizeof(state_buf2));
- whack_log(RC_COMMENT, state_buf);
- if (state_buf2[0] != '\0')
- whack_log(RC_COMMENT, state_buf2);
-
- /* show any associated pending Phase 2s */
- if (IS_PHASE1(st->st_state))
- show_pending_phase2(st->st_connection->host_pair, st);
- }
- if (count > 0)
- whack_log(RC_COMMENT, BLANK_FORMAT); /* spacer */
-
- /* free the array */
- free(array);
-}
-
-/* Muck with high-order 16 bits of this SPI in order to make
- * the corresponding SAID unique.
- * Its low-order 16 bits hold a well-known IPCOMP CPI.
- * Oh, and remember that SPIs are stored in network order.
- * Kludge!!! So I name it with the non-English word "uniquify".
- * If we can't find one easily, return 0 (a bad SPI,
- * no matter what order) indicating failure.
- */
-ipsec_spi_t uniquify_his_cpi(ipsec_spi_t cpi, struct state *st)
-{
- int tries = 0;
- int i;
- rng_t *rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
-
-startover:
-
- /* network order makes first two bytes our target */
- rng->get_bytes(rng, 2, (u_char *)&cpi);
-
- /* Make sure that the result is unique.
- * Hard work. If there is no unique value, we'll loop forever!
- */
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- {
- struct state *s;
-
- for (s = statetable[i]; s != NULL; s = s->st_hashchain_next)
- {
- if (s->st_ipcomp.present
- && sameaddr(&s->st_connection->spd.that.host_addr
- , &st->st_connection->spd.that.host_addr)
- && cpi == s->st_ipcomp.attrs.spi)
- {
- if (++tries == 20)
- {
- rng->destroy(rng);
- return 0; /* FAILURE */
- }
- goto startover;
- }
- }
- }
- rng->destroy(rng);
- return cpi;
-}
-
-/*
- * Local Variables:
- * c-basic-offset:4
- * End:
- */
diff --git a/src/pluto/state.h b/src/pluto/state.h
deleted file mode 100644
index a307d9f69..000000000
--- a/src/pluto/state.h
+++ /dev/null
@@ -1,274 +0,0 @@
-/* state and event objects
- * Copyright (C) 1997 Angelos D. Keromytis.
- * Copyright (C) 1998-2001 D. Hugh Redelmeier.
- * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#ifndef _STATE_H
-#define _STATE_H
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <time.h>
-
-#include <crypto/diffie_hellman.h>
-
-#include "defs.h"
-#include "connections.h"
-
-/* Message ID mechanism.
- *
- * A Message ID is contained in each IKE message header.
- * For Phase 1 exchanges (Main and Aggressive), it will be zero.
- * For other exchanges, which must be under the protection of an
- * ISAKMP SA, the Message ID must be unique within that ISAKMP SA.
- * Effectively, this labels the message as belonging to a particular
- * exchange.
- *
- * RFC2408 "ISAKMP" 3.1 "ISAKMP Header Format" (near end) states that
- * the Message ID must be unique. We interpret this to be "unique within
- * one ISAKMP SA".
- *
- * BTW, we feel this uniqueness allows rekeying to be somewhat simpler
- * than specified by draft-jenkins-ipsec-rekeying-06.txt.
- */
-
-typedef u_int32_t msgid_t; /* Network order! */
-#define MAINMODE_MSGID ((msgid_t) 0)
-
-struct state; /* forward declaration of tag */
-extern bool reserve_msgid(struct state *isakmp_sa, msgid_t msgid);
-extern msgid_t generate_msgid(struct state *isakmp_sa);
-
-
-/* Oakley (Phase 1 / Main Mode) transform and attributes
- * This is a flattened/decoded version of what is represented
- * in the Transaction Payload.
- * Names are chosen to match corresponding names in state.
- */
-struct oakley_trans_attrs {
- u_int16_t encrypt; /* Encryption algorithm */
- u_int16_t enckeylen; /* encryption key len (bits) */
- const struct encrypt_desc *encrypter; /* package of encryption routines */
- u_int16_t hash; /* Hash algorithm */
- const struct hash_desc *hasher; /* package of hashing routines */
- u_int16_t auth; /* Authentication method */
- const struct dh_desc *group; /* Diffie-Hellman group */
- time_t life_seconds; /* When this SA expires (seconds) */
- u_int32_t life_kilobytes; /* When this SA is exhausted (kilobytes) */
-#if 0 /* not yet */
- u_int16_t prf; /* Pseudo Random Function */
-#endif
-};
-
-/* IPsec (Phase 2 / Quick Mode) transform and attributes
- * This is a flattened/decoded version of what is represented
- * by a Transaction Payload. There may be one for AH, one
- * for ESP, and a funny one for IPCOMP.
- */
-struct ipsec_trans_attrs {
- u_int8_t transid; /* transform id */
- ipsec_spi_t spi; /* his SPI */
- time_t life_seconds; /* When this SA expires */
- u_int32_t life_kilobytes; /* When this SA expires */
- u_int16_t encapsulation;
- u_int16_t auth;
- u_int16_t key_len;
- u_int16_t key_rounds;
-#if 0 /* not implemented yet */
- u_int16_t cmprs_dict_sz;
- u_int32_t cmprs_alg;
-#endif
-};
-
-/* IPsec per protocol state information */
-struct ipsec_proto_info {
- bool present; /* was this transform specified? */
- struct ipsec_trans_attrs attrs;
- ipsec_spi_t our_spi;
- u_int16_t keymat_len; /* same for both */
- u_char *our_keymat;
- u_char *peer_keymat;
-};
-
-/* state object: record the state of a (possibly nascent) SA
- *
- * Invariants (violated only during short transitions):
- * - each state object will be in statetable exactly once.
- * - each state object will always have a pending event.
- * This prevents leaks.
- */
-struct state
-{
- so_serial_t st_serialno; /* serial number (for seniority) */
- so_serial_t st_clonedfrom; /* serial number of parent */
-
- struct connection *st_connection; /* connection for this SA */
-
- int st_whack_sock; /* fd for our Whack TCP socket.
- * Single copy: close when freeing struct.
- */
-
- struct msg_digest *st_suspended_md; /* suspended state-transition */
-
- struct oakley_trans_attrs st_oakley;
-
- struct ipsec_proto_info st_ah;
- struct ipsec_proto_info st_esp;
- struct ipsec_proto_info st_ipcomp;
- ipsec_spi_t st_tunnel_in_spi; /* KLUDGE */
- ipsec_spi_t st_tunnel_out_spi; /* KLUDGE */
-
- const struct dh_desc *st_pfs_group; /* group for Phase 2 PFS */
-
- u_int32_t st_doi; /* Domain of Interpretation */
- u_int32_t st_situation;
-
- lset_t st_policy; /* policy for IPsec SA */
-
- msgid_t st_msgid; /* MSG-ID from header. Network Order! */
-
- /* only for a state representing an ISAKMP SA */
- struct msgid_list *st_used_msgids; /* used-up msgids */
-
-/* symmetric stuff */
-
- /* initiator stuff */
- chunk_t st_gi; /* Initiator public value */
- u_int8_t st_icookie[COOKIE_SIZE];/* Initiator Cookie */
- chunk_t st_ni; /* Ni nonce */
-
- /* responder stuff */
- chunk_t st_gr; /* Responder public value */
- u_int8_t st_rcookie[COOKIE_SIZE];/* Responder Cookie */
- chunk_t st_nr; /* Nr nonce */
-
-
- /* my stuff */
-
- chunk_t st_tpacket; /* Transmitted packet */
-
- /* Phase 2 ID payload info about my user */
- u_int8_t st_myuserprotoid; /* IDcx.protoid */
- u_int16_t st_myuserport;
-
- /* his stuff */
-
- chunk_t st_rpacket; /* Received packet */
-
- /* Phase 2 ID payload info about peer's user */
- u_int8_t st_peeruserprotoid; /* IDcx.protoid */
- u_int16_t st_peeruserport;
-
-/* end of symmetric stuff */
-
- diffie_hellman_t *st_dh; /* Our local DH secret value */
- chunk_t st_shared; /* Derived shared secret
- * Note: during Quick Mode,
- * presence indicates PFS
- * selected.
- */
-
- /* In a Phase 1 state, preserve peer's public key after authentication */
- struct pubkey *st_peer_pubkey;
-
- enum state_kind st_state; /* State of exchange */
- u_int8_t st_retransmit; /* Number of retransmits */
- unsigned long st_try; /* number of times rekeying attempted */
- /* 0 means the only time */
- time_t st_margin; /* life after EVENT_SA_REPLACE */
- unsigned long st_outbound_count; /* traffic through eroute */
- time_t st_outbound_time; /* time of last change to st_outbound_count */
- chunk_t st_p1isa; /* Phase 1 initiator SA (Payload) for HASH */
- chunk_t st_skeyid; /* Key material */
- chunk_t st_skeyid_d; /* KM for non-ISAKMP key derivation */
- chunk_t st_skeyid_a; /* KM for ISAKMP authentication */
- chunk_t st_skeyid_e; /* KM for ISAKMP encryption */
- u_char st_iv[MAX_DIGEST_LEN]; /* IV for encryption */
- u_char st_new_iv[MAX_DIGEST_LEN];
- u_char st_ph1_iv[MAX_DIGEST_LEN]; /* IV at end if phase 1 */
- unsigned int st_iv_len;
- unsigned int st_new_iv_len;
- unsigned int st_ph1_iv_len;
-
- chunk_t st_enc_key; /* Oakley Encryption key */
-
- struct event *st_event; /* backpointer for certain events */
- struct state *st_hashchain_next; /* Next in list */
- struct state *st_hashchain_prev; /* Previous in list */
-
- struct {
- bool vars_set;
- bool started;
- } st_modecfg;
-
- struct {
- int attempt;
- bool started;
- bool status;
- } st_xauth;
-
- u_int32_t nat_traversal;
- ip_address nat_oa;
-
- /* RFC 3706 Dead Peer Detection */
- bool st_dpd; /* Peer supports DPD */
- time_t st_last_dpd; /* Time of last DPD transmit */
- u_int32_t st_dpd_seqno; /* Next R_U_THERE to send */
- u_int32_t st_dpd_expectseqno; /* Next R_U_THERE_ACK to receive */
- u_int32_t st_dpd_peerseqno; /* global variables */
- struct event *st_dpd_event; /* backpointer for DPD events */
-
- u_int32_t st_seen_vendorid; /* Bit field about recognized Vendor ID */
-};
-
-/* global variables */
-
-extern u_int16_t pluto_port; /* Pluto's port */
-
-extern bool states_use_connection(struct connection *c);
-
-/* state functions */
-
-extern struct state *new_state(void);
-extern void init_states(void);
-extern void insert_state(struct state *st);
-extern void unhash_state(struct state *st);
-extern void release_whack(struct state *st);
-extern void state_eroute_usage(ip_subnet *ours, ip_subnet *his
- , unsigned long count, time_t nw);
-extern void delete_state(struct state *st);
-extern void delete_states_by_connection(struct connection *c, bool relations);
-
-extern struct state
- *duplicate_state(struct state *st),
- *find_state(const u_char *icookie
- , const u_char *rcookie
- , const ip_address *peer
- , msgid_t msgid),
- *state_with_serialno(so_serial_t sn),
- *find_phase2_state_to_delete(const struct state *p1st, u_int8_t protoid
- , ipsec_spi_t spi, bool *bogus),
- *find_phase1_state(const struct connection *c, lset_t ok_states),
- *find_sender(size_t packet_len, u_char *packet);
-
-extern void show_states_status(bool all, const char *name);
-extern void for_each_state(void *(f)(struct state *, void *data), void *data);
-extern ipsec_spi_t uniquify_his_cpi(ipsec_spi_t cpi, struct state *st);
-extern void fmt_state(bool all, struct state *st, time_t n
- , char *state_buf, size_t state_buf_len
- , char *state_buf2, size_t state_buf_len2);
-extern void delete_states_by_peer(ip_address *peer);
-
-#endif /* _STATE_H */
diff --git a/src/pluto/timer.c b/src/pluto/timer.c
deleted file mode 100644
index 1d34d2c54..000000000
--- a/src/pluto/timer.c
+++ /dev/null
@@ -1,551 +0,0 @@
-/* timer event handling
- * Copyright (C) 1997 Angelos D. Keromytis.
- * Copyright (C) 1998-2001 D. Hugh Redelmeier.
- * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <time.h>
-#include <unistd.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/queue.h>
-
-#include <freeswan.h>
-
-#include <library.h>
-#include <crypto/rngs/rng.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "connections.h"
-#include "state.h"
-#include "demux.h"
-#include "ipsec_doi.h" /* needs demux.h and state.h */
-#include "kernel.h"
-#include "server.h"
-#include "log.h"
-#include "timer.h"
-#include "whack.h"
-#include "nat_traversal.h"
-
-/**
- * monotonic version of time(3)
- */
-time_t now(void)
-{
- return time_monotonic(NULL);
-}
-
-/* This file has the event handling routines. Events are
- * kept as a linked list of event structures. These structures
- * have information like event type, expiration time and a pointer
- * to event specific data (for example, to a state structure).
- */
-
-static struct event *evlist = (struct event *) NULL;
-
-/**
- * This routine places an event in the event list.
- */
-void event_schedule(enum event_type type, time_t tm, struct state *st)
-{
- struct event *ev = malloc_thing(struct event);
-
- ev->ev_type = type;
- ev->ev_time = tm + now();
- ev->ev_state = st;
-
- /* If the event is associated with a state, put a backpointer to the
- * event in the state object, so we can find and delete the event
- * if we need to (for example, if we receive a reply).
- */
- if (st != NULL)
- {
- if (type == EVENT_DPD || type == EVENT_DPD_TIMEOUT)
- {
- passert(st->st_dpd_event == NULL);
- st->st_dpd_event = ev;
- }
- else
- {
- passert(st->st_event == NULL);
- st->st_event = ev;
- }
- }
-
- DBG(DBG_CONTROL,
- if (st == NULL)
- DBG_log("inserting event %N, timeout in %lu seconds"
- , timer_event_names, type, (unsigned long)tm);
- else
- DBG_log("inserting event %N, timeout in %lu seconds for #%lu"
- , timer_event_names, type, (unsigned long)tm
- , ev->ev_state->st_serialno));
-
- if (evlist == (struct event *) NULL
- || evlist->ev_time >= ev->ev_time)
- {
- ev->ev_next = evlist;
- evlist = ev;
- }
- else
- {
- struct event *evt;
-
- for (evt = evlist; evt->ev_next != NULL; evt = evt->ev_next)
- if (evt->ev_next->ev_time >= ev->ev_time)
- break;
-
-#ifdef NEVER /* this seems to be overkill */
- DBG(DBG_CONTROL,
- if (evt->ev_state == NULL)
- DBG_log("event added after event %N"
- , timer_event_names, evt->ev_type);
- else
- DBG_log("event added after event %N for #%lu"
- , timer_event_names, evt->ev_type,
- , evt->ev_state->st_serialno));
-#endif /* NEVER */
-
- ev->ev_next = evt->ev_next;
- evt->ev_next = ev;
- }
-}
-
-/**
- * Generate the secret value for responder cookies, and
- * schedule an event for refresh.
- */
-bool init_secret(void)
-{
- rng_t *rng;
-
- rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
-
- if (rng == NULL)
- {
- plog("secret initialization failed, no RNG supported");
- return FALSE;
- }
- rng->get_bytes(rng, sizeof(secret_of_the_day), secret_of_the_day);
- rng->destroy(rng);
- event_schedule(EVENT_REINIT_SECRET, EVENT_REINIT_SECRET_DELAY, NULL);
- return true;
-}
-
-/**
- * Handle the first event on the list.
- */
-void handle_timer_event(void)
-{
- time_t tm;
- struct event *ev = evlist;
- int type;
- struct state *st;
- connection_t *c = NULL;
- ip_address peer;
-
- if (ev == (struct event *) NULL) /* Just paranoid */
- {
- DBG(DBG_CONTROL, DBG_log("empty event list, yet we're called"));
- return;
- }
-
- type = ev->ev_type;
- st = ev->ev_state;
-
- tm = now();
-
- if (tm < ev->ev_time)
- {
- DBG(DBG_CONTROL, DBG_log("called while no event expired (%lu/%lu, %N)"
- , (unsigned long)tm, (unsigned long)ev->ev_time
- , timer_event_names, type));
-
- /* This will happen if the most close-to-expire event was
- * a retransmission or cleanup, and we received a packet
- * at the same time as the event expired. Due to the processing
- * order in call_server(), the packet processing will happen first,
- * and the event will be removed.
- */
- return;
- }
-
- evlist = evlist->ev_next; /* Ok, we'll handle this event */
-
- DBG(DBG_CONTROL,
- if (evlist != (struct event *) NULL)
- DBG_log("event after this is %N in %ld seconds"
- , timer_event_names, evlist->ev_type
- , (long) (evlist->ev_time - tm)));
-
- /* for state-associated events, pick up the state pointer
- * and remove the backpointer from the state object.
- * We'll eventually either schedule a new event, or delete the state.
- */
- passert(GLOBALS_ARE_RESET());
- if (st != NULL)
- {
- c = st->st_connection;
- if (type == EVENT_DPD || type == EVENT_DPD_TIMEOUT)
- {
- passert(st->st_dpd_event == ev);
- st->st_dpd_event = NULL;
- }
- else
- {
- passert(st->st_event == ev);
- st->st_event = NULL;
- }
- peer = c->spd.that.host_addr;
- set_cur_state(st);
- }
-
- switch (type)
- {
- case EVENT_REINIT_SECRET:
- passert(st == NULL);
- DBG(DBG_CONTROL, DBG_log("event EVENT_REINIT_SECRET handled"));
- init_secret();
- break;
-
- case EVENT_LOG_DAILY:
- daily_log_event();
- break;
-
- case EVENT_RETRANSMIT:
- /* Time to retransmit, or give up.
- *
- * Generally, we'll only try to send the message
- * MAXIMUM_RETRANSMISSIONS times. Each time we double
- * our patience.
- *
- * As a special case, if this is the first initiating message
- * of a Main Mode exchange, and we have been directed to try
- * forever, we'll extend the number of retransmissions to
- * MAXIMUM_RETRANSMISSIONS_INITIAL times, with all these
- * extended attempts having the same patience. The intention
- * is to reduce the bother when nobody is home.
- */
- {
- time_t delay = 0;
-
- DBG(DBG_CONTROL, DBG_log(
- "handling event EVENT_RETRANSMIT for %s \"%s\" #%lu"
- , ip_str(&peer), c->name, st->st_serialno));
-
- if (st->st_retransmit < MAXIMUM_RETRANSMISSIONS)
- delay = EVENT_RETRANSMIT_DELAY_0 << (st->st_retransmit + 1);
- else if (st->st_state == STATE_MAIN_I1
- && c->sa_keying_tries == 0
- && st->st_retransmit < MAXIMUM_RETRANSMISSIONS_INITIAL)
- delay = EVENT_RETRANSMIT_DELAY_0 << MAXIMUM_RETRANSMISSIONS;
-
- if (delay != 0)
- {
- st->st_retransmit++;
- whack_log(RC_RETRANSMISSION
- , "%s: retransmission; will wait %lus for response"
- , enum_name(&state_names, st->st_state)
- , (unsigned long)delay);
- send_packet(st, "EVENT_RETRANSMIT");
- event_schedule(EVENT_RETRANSMIT, delay, st);
- }
- else
- {
- /* check if we've tried rekeying enough times.
- * st->st_try == 0 means that this should be the only try.
- * c->sa_keying_tries == 0 means that there is no limit.
- */
- unsigned long try = st->st_try;
- unsigned long try_limit = c->sa_keying_tries;
- const char *details = "";
-
- switch (st->st_state)
- {
- case STATE_MAIN_I3:
- details = ". Possible authentication failure:"
- " no acceptable response to our"
- " first encrypted message";
- break;
- case STATE_MAIN_I1:
- details = ". No response (or no acceptable response) to our"
- " first IKE message";
- break;
- case STATE_QUICK_I1:
- if (c->newest_ipsec_sa == SOS_NOBODY)
- details = ". No acceptable response to our"
- " first Quick Mode message:"
- " perhaps peer likes no proposal";
- break;
- default:
- break;
- }
- loglog(RC_NORETRANSMISSION
- , "max number of retransmissions (%d) reached %s%s"
- , st->st_retransmit
- , enum_show(&state_names, st->st_state), details);
- if (try != 0 && try != try_limit)
- {
- /* A lot like EVENT_SA_REPLACE, but over again.
- * Since we know that st cannot be in use,
- * we can delete it right away.
- */
- char story[80]; /* arbitrary limit */
-
- try++;
- snprintf(story, sizeof(story), try_limit == 0
- ? "starting keying attempt %ld of an unlimited number"
- : "starting keying attempt %ld of at most %ld"
- , try, try_limit);
-
- if (st->st_whack_sock != NULL_FD)
- {
- /* Release whack because the observer will get bored. */
- loglog(RC_COMMENT, "%s, but releasing whack"
- , story);
- release_pending_whacks(st, story);
- }
- else
- {
- /* no whack: just log to syslog */
- plog("%s", story);
- }
- ipsecdoi_replace(st, try);
- }
- delete_state(st);
- }
- }
- break;
-
- case EVENT_SA_REPLACE:
- case EVENT_SA_REPLACE_IF_USED:
- {
- so_serial_t newest = IS_PHASE1(st->st_state)
- ? c->newest_isakmp_sa : c->newest_ipsec_sa;
-
- if (newest != st->st_serialno
- && newest != SOS_NOBODY)
- {
- /* not very interesting: no need to replace */
- DBG(DBG_LIFECYCLE
- , plog("not replacing stale %s SA: #%lu will do"
- , IS_PHASE1(st->st_state)? "ISAKMP" : "IPsec"
- , newest));
- }
- else if (type == EVENT_SA_REPLACE_IF_USED
- && st->st_outbound_time <= tm - c->sa_rekey_margin)
- {
- /* we observed no recent use: no need to replace
- *
- * The sampling effects mean that st_outbound_time
- * could be up to SHUNT_SCAN_INTERVAL more recent
- * than actual traffic because the sampler looks at change
- * over that interval.
- * st_outbound_time could also not yet reflect traffic
- * in the last SHUNT_SCAN_INTERVAL.
- * We expect that SHUNT_SCAN_INTERVAL is smaller than
- * c->sa_rekey_margin so that the effects of this will
- * be unimportant.
- * This is just an optimization: correctness is not
- * at stake.
- *
- * Note: we are abusing the DBG mechanism to control
- * normal log output.
- */
- DBG(DBG_LIFECYCLE
- , plog("not replacing stale %s SA: inactive for %lus"
- , IS_PHASE1(st->st_state)? "ISAKMP" : "IPsec"
- , (unsigned long)(tm - st->st_outbound_time)));
- }
- else
- {
- DBG(DBG_LIFECYCLE
- , plog("replacing stale %s SA"
- , IS_PHASE1(st->st_state)? "ISAKMP" : "IPsec"));
- ipsecdoi_replace(st, 1);
- }
- delete_dpd_event(st);
- event_schedule(EVENT_SA_EXPIRE, st->st_margin, st);
- }
- break;
-
- case EVENT_SA_EXPIRE:
- {
- const char *satype;
- so_serial_t latest;
-
- if (IS_PHASE1(st->st_state))
- {
- satype = "ISAKMP";
- latest = c->newest_isakmp_sa;
- }
- else
- {
- satype = "IPsec";
- latest = c->newest_ipsec_sa;
- }
-
- if (st->st_serialno != latest)
- {
- /* not very interesting: already superseded */
- DBG(DBG_LIFECYCLE
- , plog("%s SA expired (superseded by #%lu)"
- , satype, latest));
- }
- else
- {
- plog("%s SA expired (%s)", satype
- , (c->policy & POLICY_DONT_REKEY)
- ? "--dontrekey"
- : "LATEST!"
- );
- }
- }
- /* FALLTHROUGH */
- case EVENT_SO_DISCARD:
- /* Delete this state object. It must be in the hash table. */
- delete_state(st);
- break;
-
- case EVENT_DPD:
- dpd_outI(st);
- break;
- case EVENT_DPD_TIMEOUT:
- dpd_timeout(st);
- break;
- case EVENT_NAT_T_KEEPALIVE:
- nat_traversal_ka_event();
- break;
- default:
- loglog(RC_LOG_SERIOUS, "INTERNAL ERROR: ignoring unknown expiring event %N"
- , timer_event_names, type);
- }
-
- free(ev);
- reset_cur_state();
-}
-
-/**
- * Return the time until the next event in the queue
- * expires (never negative), or -1 if no jobs in queue.
- */
-long next_event(void)
-{
- time_t tm;
-
- if (evlist == (struct event *) NULL)
- return -1;
-
- tm = now();
-
- DBG(DBG_CONTROL,
- if (evlist->ev_state == NULL)
- DBG_log("next event %N in %ld seconds"
- , timer_event_names, evlist->ev_type
- , (long)evlist->ev_time - (long)tm);
- else
- DBG_log("next event %N in %ld seconds for #%lu"
- , timer_event_names, evlist->ev_type
- , (long)evlist->ev_time - (long)tm
- , evlist->ev_state->st_serialno));
-
- if (evlist->ev_time - tm <= 0)
- return 0;
- else
- return evlist->ev_time - tm;
-}
-
-/**
- * Delete an event.
- */
-void delete_event(struct state *st)
-{
- if (st->st_event != (struct event *) NULL)
- {
- struct event **ev;
-
- for (ev = &evlist; ; ev = &(*ev)->ev_next)
- {
- if (*ev == NULL)
- {
- DBG(DBG_CONTROL, DBG_log("event %N to be deleted not found",
- timer_event_names, st->st_event->ev_type));
- break;
- }
- if ((*ev) == st->st_event)
- {
- *ev = (*ev)->ev_next;
-
- if (st->st_event->ev_type == EVENT_RETRANSMIT)
- {
- st->st_retransmit = 0;
- }
- free(st->st_event);
- st->st_event = (struct event *) NULL;
-
- break;
- }
- }
- }
-}
-
-/**
- * Delete a DPD event.
- */
-void delete_dpd_event(struct state *st)
-{
- if (st->st_dpd_event != (struct event *) NULL)
- {
- struct event **ev;
-
- for (ev = &evlist; ; ev = &(*ev)->ev_next)
- {
- if (*ev == NULL)
- {
- DBG(DBG_CONTROL, DBG_log("event %N to be deleted not found",
- timer_event_names, st->st_dpd_event->ev_type));
- break;
- }
- if ((*ev) == st->st_dpd_event)
- {
- *ev = (*ev)->ev_next;
- free(st->st_dpd_event);
- st->st_dpd_event = (struct event *) NULL;
- break;
- }
- }
- }
-}
-
-/**
- * Free remaining events
- */
-void free_events(void)
-{
- struct event *ev_tmp, *ev;
-
- ev = evlist;
- evlist = NULL;
-
- while (ev)
- {
- ev_tmp = ev;
- ev = ev->ev_next;
- free(ev_tmp);
- }
-}
-
diff --git a/src/pluto/timer.h b/src/pluto/timer.h
deleted file mode 100644
index c8e9b727c..000000000
--- a/src/pluto/timer.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* timing machinery
- * Copyright (C) 1998-2001 D. Hugh Redelmeier.
- *
- * 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.
- */
-
-extern time_t now(void); /* careful version of time(2) */
-
-struct state; /* forward declaration */
-
-struct event
-{
- time_t ev_time;
- int ev_type; /* Event type */
- struct state *ev_state; /* Pointer to relevant state (if any) */
- struct event *ev_next; /* Pointer to next event */
-};
-
-extern void event_schedule(enum event_type type, time_t tm, struct state *st);
-extern void handle_timer_event(void);
-extern long next_event(void);
-extern void delete_event(struct state *st);
-extern void delete_dpd_event(struct state *st);
-extern void daily_log_event(void);
-extern void free_events(void);
-extern bool init_secret(void);
diff --git a/src/pluto/vendor.c b/src/pluto/vendor.c
deleted file mode 100644
index 6cc599d8d..000000000
--- a/src/pluto/vendor.c
+++ /dev/null
@@ -1,511 +0,0 @@
-/* ISAKMP VendorID
- * Copyright (C) 2002-2005 Mathieu Lafon - Arkoon Network Security
- * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <sys/queue.h>
-#include <freeswan.h>
-
-#include <library.h>
-#include <crypto/hashers/hasher.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "log.h"
-#include "connections.h"
-#include "packet.h"
-#include "demux.h"
-#include "whack.h"
-#include "vendor.h"
-#include "kernel.h"
-#include "nat_traversal.h"
-
-/**
- * Unknown/Special VID:
- *
- * SafeNet SoftRemote 8.0.0:
- * 47bbe7c993f1fc13b4e6d0db565c68e5010201010201010310382e302e3020284275696c6420313029000000
- * >> 382e302e3020284275696c6420313029 = '8.0.0 (Build 10)'
- * da8e937880010000
- *
- * SafeNet SoftRemote 9.0.1
- * 47bbe7c993f1fc13b4e6d0db565c68e5010201010201010310392e302e3120284275696c6420313229000000
- * >> 392e302e3120284275696c6420313229 = '9.0.1 (Build 12)'
- * da8e937880010000
- *
- * Netscreen:
- * d6b45f82f24bacb288af59a978830ab7
- * cf49908791073fb46439790fdeb6aeed981101ab0000000500000300
- *
- * Cisco:
- * 1f07f70eaa6514d3b0fa96542a500300 (VPN 3000 version 3.0.0)
- * 1f07f70eaa6514d3b0fa96542a500301 (VPN 3000 version 3.0.1)
- * 1f07f70eaa6514d3b0fa96542a500305 (VPN 3000 version 3.0.5)
- * 1f07f70eaa6514d3b0fa96542a500407 (VPN 3000 version 4.0.7)
- * (Can you see the pattern?)
- * afcad71368a1f1c96b8696fc77570100 (Non-RFC Dead Peer Detection ?)
- * c32364b3b4f447eb17c488ab2a480a57
- * 6d761ddc26aceca1b0ed11fabbb860c4
- * 5946c258f99a1a57b03eb9d1759e0f24 (From a Cisco VPN 3k)
- * ebbc5b00141d0c895e11bd395902d690 (From a Cisco VPN 3k)
- *
- * Microsoft L2TP (???):
- * 47bbe7c993f1fc13b4e6d0db565c68e5010201010201010310382e312e3020284275696c6420313029000000
- * >> 382e312e3020284275696c6420313029 = '8.1.0 (Build 10)'
- * 3025dbd21062b9e53dc441c6aab5293600000000
- * da8e937880010000
- *
- * 3COM-superstack
- * da8e937880010000
- * 404bf439522ca3f6
- *
-
- * If someone know what they mean, mail me.
- */
-
-#define MAX_LOG_VID_LEN 32
-
-#define VID_KEEP 0x0000
-#define VID_MD5HASH 0x0001
-#define VID_STRING 0x0002
-#define VID_FSWAN_HASH 0x0004
-
-#define VID_SUBSTRING_DUMPHEXA 0x0100
-#define VID_SUBSTRING_DUMPASCII 0x0200
-#define VID_SUBSTRING_MATCH 0x0400
-#define VID_SUBSTRING (VID_SUBSTRING_DUMPHEXA | VID_SUBSTRING_DUMPASCII | VID_SUBSTRING_MATCH)
-
-struct vid_struct {
- enum known_vendorid id;
- unsigned short flags;
- const char *data;
- const char *descr;
- chunk_t vid;
-};
-
-#define DEC_MD5_VID_D(id,str,descr) \
- { VID_##id, VID_MD5HASH, str, descr, { NULL, 0 } },
-#define DEC_MD5_VID(id,str) \
- { VID_##id, VID_MD5HASH, str, NULL, { NULL, 0 } },
-
-static struct vid_struct _vid_tab[] = {
-
- /* Implementation names */
-
- { VID_OPENPGP, VID_STRING, "OpenPGP10171", "OpenPGP", { NULL, 0 } },
-
- DEC_MD5_VID(KAME_RACOON, "KAME/racoon")
-
- { VID_MS_NT5, VID_MD5HASH | VID_SUBSTRING_DUMPHEXA,
- "MS NT5 ISAKMPOAKLEY", NULL, { NULL, 0 } },
-
- DEC_MD5_VID(SSH_SENTINEL, "SSH Sentinel")
- DEC_MD5_VID(SSH_SENTINEL_1_1, "SSH Sentinel 1.1")
- DEC_MD5_VID(SSH_SENTINEL_1_2, "SSH Sentinel 1.2")
- DEC_MD5_VID(SSH_SENTINEL_1_3, "SSH Sentinel 1.3")
- DEC_MD5_VID(SSH_SENTINEL_1_4, "SSH Sentinel 1.4")
- DEC_MD5_VID(SSH_SENTINEL_1_4_1, "SSH Sentinel 1.4.1")
-
- /* These ones come from SSH vendors.txt */
- DEC_MD5_VID(SSH_IPSEC_1_1_0,
- "Ssh Communications Security IPSEC Express version 1.1.0")
- DEC_MD5_VID(SSH_IPSEC_1_1_1,
- "Ssh Communications Security IPSEC Express version 1.1.1")
- DEC_MD5_VID(SSH_IPSEC_1_1_2,
- "Ssh Communications Security IPSEC Express version 1.1.2")
- DEC_MD5_VID(SSH_IPSEC_1_2_1,
- "Ssh Communications Security IPSEC Express version 1.2.1")
- DEC_MD5_VID(SSH_IPSEC_1_2_2,
- "Ssh Communications Security IPSEC Express version 1.2.2")
- DEC_MD5_VID(SSH_IPSEC_2_0_0,
- "SSH Communications Security IPSEC Express version 2.0.0")
- DEC_MD5_VID(SSH_IPSEC_2_1_0,
- "SSH Communications Security IPSEC Express version 2.1.0")
- DEC_MD5_VID(SSH_IPSEC_2_1_1,
- "SSH Communications Security IPSEC Express version 2.1.1")
- DEC_MD5_VID(SSH_IPSEC_2_1_2,
- "SSH Communications Security IPSEC Express version 2.1.2")
- DEC_MD5_VID(SSH_IPSEC_3_0_0,
- "SSH Communications Security IPSEC Express version 3.0.0")
- DEC_MD5_VID(SSH_IPSEC_3_0_1,
- "SSH Communications Security IPSEC Express version 3.0.1")
- DEC_MD5_VID(SSH_IPSEC_4_0_0,
- "SSH Communications Security IPSEC Express version 4.0.0")
- DEC_MD5_VID(SSH_IPSEC_4_0_1,
- "SSH Communications Security IPSEC Express version 4.0.1")
- DEC_MD5_VID(SSH_IPSEC_4_1_0,
- "SSH Communications Security IPSEC Express version 4.1.0")
- DEC_MD5_VID(SSH_IPSEC_4_2_0,
- "SSH Communications Security IPSEC Express version 4.2.0")
-
- /* note: md5('CISCO-UNITY') = 12f5f28c457168a9702d9fe274cc02d4 */
- { VID_CISCO_UNITY, VID_KEEP, NULL, "Cisco-Unity",
- { "\x12\xf5\xf2\x8c\x45\x71\x68\xa9\x70\x2d\x9f\xe2\x74\xcc\x01\x00", 16 } },
-
- { VID_CISCO3K, VID_KEEP | VID_SUBSTRING_MATCH, NULL, "Cisco VPN 3000 Series" ,
- { "\x1f\x07\xf7\x0e\xaa\x65\x14\xd3\xb0\xfa\x96\x54\x2a\x50", 14 } },
-
- { VID_CISCO_IOS, VID_KEEP | VID_SUBSTRING_MATCH,
- NULL, "Cisco IOS Device", { "\x3e\x98\x40\x48", 4 } },
-
- /*
- * Timestep VID seen:
- * - 54494d455354455020312053475720313532302033313520322e303145303133
- * = 'TIMESTEP 1 SGW 1520 315 2.01E013'
- */
- { VID_TIMESTEP, VID_STRING | VID_SUBSTRING_DUMPASCII, "TIMESTEP",
- NULL, { NULL, 0 } },
-
- /*
- * Netscreen:
- * 4865617274426561745f4e6f74696679386b0100 (HeartBeat_Notify + 386b0100)
- */
- { VID_MISC_HEARTBEAT_NOTIFY, VID_STRING | VID_SUBSTRING_DUMPHEXA,
- "HeartBeat_Notify", "HeartBeat Notify", { NULL, 0 } },
- /*
- * MacOS X
- */
- { VID_MACOSX, VID_STRING|VID_SUBSTRING_DUMPHEXA, "Mac OSX 10.x",
- "\x4d\xf3\x79\x28\xe9\xfc\x4f\xd1\xb3\x26\x21\x70\xd5\x15\xc6\x62", { NULL, 0 } },
-
- /* NCP */
- { VID_NCP_SERVER, VID_KEEP | VID_SUBSTRING_MATCH, NULL, "NCP Server",
- { "\xc6\xf5\x7a\xc3\x98\xf4\x93\x20\x81\x45\xb7\x58", 12 } },
- { VID_NCP_CLIENT, VID_KEEP | VID_SUBSTRING_MATCH, NULL, "NCP Client",
- { "\xeb\x4c\x1b\x78\x8a\xfd\x4a\x9c\xb7\x73\x0a\x68", 12 } },
-
- /*
- * Windows Vista (and Windows Server 2008?)
- */
- DEC_MD5_VID(VISTA_AUTHIP, "MS-Negotiation Discovery Capable")
- DEC_MD5_VID(VISTA_AUTHIP2, "IKE CGA version 1")
- DEC_MD5_VID(VISTA_AUTHIP3, "MS-MamieExists")
-
- /*
- * strongSwan
- */
- DEC_MD5_VID(STRONGSWAN, "strongSwan")
-
- DEC_MD5_VID(STRONGSWAN_4_3_5, "strongSwan 4.3.5")
- DEC_MD5_VID(STRONGSWAN_4_3_4, "strongSwan 4.3.4")
- DEC_MD5_VID(STRONGSWAN_4_3_3, "strongSwan 4.3.3")
- DEC_MD5_VID(STRONGSWAN_4_3_2, "strongSwan 4.3.2")
- DEC_MD5_VID(STRONGSWAN_4_3_1, "strongSwan 4.3.1")
- DEC_MD5_VID(STRONGSWAN_4_3_0, "strongSwan 4.3.0")
- DEC_MD5_VID(STRONGSWAN_4_2_17,"strongSwan 4.2.17")
- DEC_MD5_VID(STRONGSWAN_4_2_16,"strongSwan 4.2.16")
- DEC_MD5_VID(STRONGSWAN_4_2_15,"strongSwan 4.2.15")
- DEC_MD5_VID(STRONGSWAN_4_2_14,"strongSwan 4.2.14")
- DEC_MD5_VID(STRONGSWAN_4_2_13,"strongSwan 4.2.13")
- DEC_MD5_VID(STRONGSWAN_4_2_12,"strongSwan 4.2.12")
- DEC_MD5_VID(STRONGSWAN_4_2_11,"strongSwan 4.2.11")
- DEC_MD5_VID(STRONGSWAN_4_2_10,"strongSwan 4.2.10")
- DEC_MD5_VID(STRONGSWAN_4_2_9, "strongSwan 4.2.9")
- DEC_MD5_VID(STRONGSWAN_4_2_8, "strongSwan 4.2.8")
- DEC_MD5_VID(STRONGSWAN_4_2_7, "strongSwan 4.2.7")
- DEC_MD5_VID(STRONGSWAN_4_2_6, "strongSwan 4.2.6")
- DEC_MD5_VID(STRONGSWAN_4_2_5, "strongSwan 4.2.5")
- DEC_MD5_VID(STRONGSWAN_4_2_4, "strongSwan 4.2.4")
- DEC_MD5_VID(STRONGSWAN_4_2_3, "strongSwan 4.2.3")
- DEC_MD5_VID(STRONGSWAN_4_2_2, "strongSwan 4.2.2")
- DEC_MD5_VID(STRONGSWAN_4_2_1, "strongSwan 4.2.1")
- DEC_MD5_VID(STRONGSWAN_4_2_0, "strongSwan 4.2.0")
- DEC_MD5_VID(STRONGSWAN_4_1_11,"strongSwan 4.1.11")
- DEC_MD5_VID(STRONGSWAN_4_1_10,"strongSwan 4.1.10")
- DEC_MD5_VID(STRONGSWAN_4_1_9, "strongSwan 4.1.9")
- DEC_MD5_VID(STRONGSWAN_4_1_8, "strongSwan 4.1.8")
- DEC_MD5_VID(STRONGSWAN_4_1_7, "strongSwan 4.1.7")
- DEC_MD5_VID(STRONGSWAN_4_1_6, "strongSwan 4.1.6")
- DEC_MD5_VID(STRONGSWAN_4_1_5, "strongSwan 4.1.5")
- DEC_MD5_VID(STRONGSWAN_4_1_4, "strongSwan 4.1.4")
- DEC_MD5_VID(STRONGSWAN_4_1_3, "strongSwan 4.1.3")
- DEC_MD5_VID(STRONGSWAN_4_1_2, "strongSwan 4.1.2")
- DEC_MD5_VID(STRONGSWAN_4_1_1, "strongSwan 4.1.1")
- DEC_MD5_VID(STRONGSWAN_4_1_0, "strongSwan 4.1.0")
-
- DEC_MD5_VID(STRONGSWAN_2_8_11,"strongSwan 2.8.11")
- DEC_MD5_VID(STRONGSWAN_2_8_10,"strongSwan 2.8.10")
- DEC_MD5_VID(STRONGSWAN_2_8_9, "strongSwan 2.8.9")
- DEC_MD5_VID(STRONGSWAN_2_8_8, "strongSwan 2.8.8")
- DEC_MD5_VID(STRONGSWAN_2_8_7, "strongSwan 2.8.7")
- DEC_MD5_VID(STRONGSWAN_2_8_6, "strongSwan 2.8.6")
- DEC_MD5_VID(STRONGSWAN_2_8_5, "strongSwan 2.8.5")
- DEC_MD5_VID(STRONGSWAN_2_8_4, "strongSwan 2.8.4")
- DEC_MD5_VID(STRONGSWAN_2_8_3, "strongSwan 2.8.3")
- DEC_MD5_VID(STRONGSWAN_2_8_2, "strongSwan 2.8.2")
- DEC_MD5_VID(STRONGSWAN_2_8_1, "strongSwan 2.8.1")
- DEC_MD5_VID(STRONGSWAN_2_8_0, "strongSwan 2.8.0")
-
- /* NAT-Traversal */
-
- DEC_MD5_VID(NATT_STENBERG_01, "draft-stenberg-ipsec-nat-traversal-01")
- DEC_MD5_VID(NATT_STENBERG_02, "draft-stenberg-ipsec-nat-traversal-02")
- DEC_MD5_VID(NATT_HUTTUNEN, "ESPThruNAT")
- DEC_MD5_VID(NATT_HUTTUNEN_ESPINUDP, "draft-huttunen-ipsec-esp-in-udp-00.txt")
- DEC_MD5_VID(NATT_IETF_00, "draft-ietf-ipsec-nat-t-ike-00")
- DEC_MD5_VID(NATT_IETF_02, "draft-ietf-ipsec-nat-t-ike-02")
- /* hash in draft-ietf-ipsec-nat-t-ike-02 contains '\n'... Accept both */
- DEC_MD5_VID_D(NATT_IETF_02_N, "draft-ietf-ipsec-nat-t-ike-02\n", "draft-ietf-ipsec-nat-t-ike-02_n")
- DEC_MD5_VID(NATT_IETF_03, "draft-ietf-ipsec-nat-t-ike-03")
- DEC_MD5_VID(NATT_RFC, "RFC 3947")
-
- /* misc */
-
- { VID_MISC_XAUTH, VID_KEEP, NULL, "XAUTH",
- { "\x09\x00\x26\x89\xdf\xd6\xb7\x12", 8 } },
-
- { VID_MISC_DPD, VID_KEEP, NULL, "Dead Peer Detection",
- { "\xaf\xca\xd7\x13\x68\xa1\xf1\xc9\x6b\x86\x96\xfc\x77\x57\x01\x00", 16 } },
-
- DEC_MD5_VID(MISC_FRAGMENTATION, "FRAGMENTATION")
-
- DEC_MD5_VID(INITIAL_CONTACT, "Vid-Initial-Contact")
-
- /**
- * Cisco VPN 3000
- */
- { VID_MISC_FRAGMENTATION, VID_MD5HASH | VID_SUBSTRING_DUMPHEXA,
- "FRAGMENTATION", NULL, { NULL, 0 } },
-
- /* -- */
- { 0, 0, NULL, NULL, { NULL, 0 } }
-
-};
-
-static const char _hexdig[] = "0123456789abcdef";
-
-static int _vid_struct_init = 0;
-
-void init_vendorid(void)
-{
- hasher_t *hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
- struct vid_struct *vid;
-
- for (vid = _vid_tab; vid->id; vid++)
- {
- if (vid->flags & VID_STRING)
- {
- /** VendorID is a string **/
- vid->vid = chunk_create((u_char *)vid->data, strlen(vid->data));
- vid->vid = chunk_clone(vid->vid);
- }
- else if (vid->flags & VID_MD5HASH)
- {
- chunk_t vid_data = { (u_char *)vid->data, strlen(vid->data) };
-
- /** VendorID is a string to hash with MD5 **/
- hasher->allocate_hash(hasher, vid_data, &vid->vid);
- }
-
- if (vid->descr == NULL)
- {
- /** Find something to display **/
- vid->descr = vid->data;
- }
- }
- hasher->destroy(hasher);
- _vid_struct_init = 1;
-}
-
-void free_vendorid(void)
-{
- struct vid_struct *vid;
-
- for (vid = _vid_tab; vid->id; vid++)
- {
- if (vid->flags & (VID_STRING | VID_MD5HASH | VID_FSWAN_HASH))
- {
- free(vid->vid.ptr);
- }
- }
-}
-
-static void handle_known_vendorid (struct msg_digest *md, const char *vidstr,
- size_t len, struct vid_struct *vid)
-{
- char vid_dump[128];
- bool vid_useful = FALSE;
- size_t i, j;
-
- switch (vid->id)
- {
- /* Remote side is a strongSwan host */
- case VID_STRONGSWAN:
- vid_useful = TRUE;
- break;
-
- /* Remote side supports OpenPGP certificates */
- case VID_OPENPGP:
- md->openpgp = TRUE;
- vid_useful = TRUE;
- break;
-
- /* Remote side is a Windows 2000+ host */
- case VID_MS_NT5:
- md->ms_nt5 = TRUE;
- vid_useful = TRUE;
- break;
-
- /*
- * Use most recent supported NAT-Traversal method and ignore the
- * other ones (implementations will send all supported methods but
- * only one will be used)
- *
- * Note: most recent == higher id in vendor.h
- */
- case VID_NATT_IETF_00:
- if (!nat_traversal_support_non_ike)
- break;
- if ((nat_traversal_enabled) && (!md->nat_traversal_vid))
- {
- md->nat_traversal_vid = vid->id;
- vid_useful = TRUE;
- }
- break;
- case VID_NATT_IETF_02:
- case VID_NATT_IETF_02_N:
- case VID_NATT_IETF_03:
- case VID_NATT_RFC:
- if (nat_traversal_support_port_floating
- && md->nat_traversal_vid < vid->id)
- {
- md->nat_traversal_vid = vid->id;
- vid_useful = TRUE;
- }
- break;
-
- /* Remote side would like to do DPD with us on this connection */
- case VID_MISC_DPD:
- md->dpd = TRUE;
- vid_useful = TRUE;
- break;
- case VID_MISC_XAUTH:
- vid_useful = TRUE;
- break;
- default:
- break;
- }
-
- if (vid->flags & VID_SUBSTRING_DUMPHEXA)
- {
- /* Dump description + Hexa */
- memset(vid_dump, 0, sizeof(vid_dump));
- snprintf(vid_dump, sizeof(vid_dump), "%s ",
- vid->descr ? vid->descr : "");
- for (i = strlen(vid_dump), j = vid->vid.len;
- j < len && i < sizeof(vid_dump) - 2;
- i += 2, j++)
- {
- vid_dump[i] = _hexdig[(vidstr[j] >> 4) & 0xF];
- vid_dump[i+1] = _hexdig[vidstr[j] & 0xF];
- }
- }
- else if (vid->flags & VID_SUBSTRING_DUMPASCII)
- {
- /* Dump ASCII content */
- memset(vid_dump, 0, sizeof(vid_dump));
- for (i = 0; i < len && i < sizeof(vid_dump) - 1; i++)
- {
- vid_dump[i] = (isprint(vidstr[i])) ? vidstr[i] : '.';
- }
- }
- else
- {
- /* Dump description (descr) */
- snprintf(vid_dump, sizeof(vid_dump), "%s",
- vid->descr ? vid->descr : "");
- }
-
- loglog(RC_LOG_SERIOUS, "%s Vendor ID payload [%s]",
- vid_useful ? "received" : "ignoring", vid_dump);
-}
-
-void handle_vendorid (struct msg_digest *md, const char *vid, size_t len)
-{
- struct vid_struct *pvid;
-
- if (!_vid_struct_init)
- init_vendorid();
-
- /*
- * Find known VendorID in _vid_tab
- */
- for (pvid = _vid_tab; pvid->id; pvid++)
- {
- if (pvid->vid.ptr && vid && pvid->vid.len && len)
- {
- if (pvid->vid.len == len)
- {
- if (memeq(pvid->vid.ptr, vid, len))
- {
- handle_known_vendorid(md, vid, len, pvid);
- return;
- }
- }
- else if ((pvid->vid.len < len) && (pvid->flags & VID_SUBSTRING))
- {
- if (memeq(pvid->vid.ptr, vid, pvid->vid.len))
- {
- handle_known_vendorid(md, vid, len, pvid);
- return;
- }
- }
- }
- }
-
- /*
- * Unknown VendorID. Log the beginning.
- */
- {
- char log_vid[2*MAX_LOG_VID_LEN+1];
- size_t i;
-
- memset(log_vid, 0, sizeof(log_vid));
-
- for (i = 0; i < len && i < MAX_LOG_VID_LEN; i++)
- {
- log_vid[2*i] = _hexdig[(vid[i] >> 4) & 0xF];
- log_vid[2*i+1] = _hexdig[vid[i] & 0xF];
- }
- loglog(RC_LOG_SERIOUS, "ignoring Vendor ID payload [%s%s]",
- log_vid, (len>MAX_LOG_VID_LEN) ? "..." : "");
- }
-}
-
-/**
- * Add a vendor id payload to the msg
- */
-bool out_vendorid (u_int8_t np, pb_stream *outs, enum known_vendorid vid)
-{
- struct vid_struct *pvid;
-
- if (!_vid_struct_init)
- init_vendorid();
-
- for (pvid = _vid_tab; pvid->id && pvid->id != vid; pvid++);
-
- if (pvid->id != vid)
- return STF_INTERNAL_ERROR; /* not found */
- if (!pvid->vid.ptr)
- return STF_INTERNAL_ERROR; /* not initialized */
-
- DBG(DBG_EMITTING,
- DBG_log("out_vendorid(): sending [%s]", pvid->descr)
- )
- return out_generic_raw(np, &isakmp_vendor_id_desc, outs,
- pvid->vid.ptr, pvid->vid.len, "V_ID");
-}
-
diff --git a/src/pluto/vendor.h b/src/pluto/vendor.h
deleted file mode 100644
index ac6b0d420..000000000
--- a/src/pluto/vendor.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/* FreeS/WAN ISAKMP VendorID
- * Copyright (C) 2002-2003 Mathieu Lafon - Arkoon Network Security
- *
- * 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.
- */
-
-#ifndef _VENDOR_H_
-#define _VENDOR_H_
-
-enum known_vendorid {
-/* 1 - 100 : Implementation names */
- VID_OPENPGP = 1,
- VID_KAME_RACOON = 2,
- VID_MS_NT5 = 3,
- VID_SSH_SENTINEL = 4,
- VID_SSH_SENTINEL_1_1 = 5,
- VID_SSH_SENTINEL_1_2 = 6,
- VID_SSH_SENTINEL_1_3 = 7,
- VID_SSH_SENTINEL_1_4 = 8,
- VID_SSH_SENTINEL_1_4_1 = 9,
- VID_SSH_IPSEC_1_1_0 = 10,
- VID_SSH_IPSEC_1_1_1 = 11,
- VID_SSH_IPSEC_1_1_2 = 12,
- VID_SSH_IPSEC_1_2_1 = 13,
- VID_SSH_IPSEC_1_2_2 = 14,
- VID_SSH_IPSEC_2_0_0 = 15,
- VID_SSH_IPSEC_2_1_0 = 16,
- VID_SSH_IPSEC_2_1_1 = 17,
- VID_SSH_IPSEC_2_1_2 = 18,
- VID_SSH_IPSEC_3_0_0 = 19,
- VID_SSH_IPSEC_3_0_1 = 20,
- VID_SSH_IPSEC_4_0_0 = 21,
- VID_SSH_IPSEC_4_0_1 = 22,
- VID_SSH_IPSEC_4_1_0 = 23,
- VID_SSH_IPSEC_4_2_0 = 24,
- VID_CISCO_UNITY = 25,
- VID_CISCO3K = 26,
- VID_CISCO_IOS = 27,
- VID_TIMESTEP = 28,
- VID_SAFENET = 29,
- VID_MACOSX = 30,
- VID_NCP_SERVER = 31,
- VID_NCP_CLIENT = 32,
- VID_VISTA_AUTHIP = 33,
- VID_VISTA_AUTHIP2 = 34,
- VID_VISTA_AUTHIP3 = 35,
-
- VID_STRONGSWAN = 36,
-
- VID_STRONGSWAN_2_8_0 = 37,
- VID_STRONGSWAN_2_8_1 = 38,
- VID_STRONGSWAN_2_8_2 = 39,
- VID_STRONGSWAN_2_8_3 = 40,
- VID_STRONGSWAN_2_8_4 = 41,
- VID_STRONGSWAN_2_8_5 = 42,
- VID_STRONGSWAN_2_8_6 = 43,
- VID_STRONGSWAN_2_8_7 = 44,
- VID_STRONGSWAN_2_8_8 = 45,
- VID_STRONGSWAN_2_8_9 = 46,
- VID_STRONGSWAN_2_8_10 = 47,
- VID_STRONGSWAN_2_8_11 = 48,
-
- VID_STRONGSWAN_4_1_0 = 88,
- VID_STRONGSWAN_4_1_1 = 89,
- VID_STRONGSWAN_4_1_2 = 90,
- VID_STRONGSWAN_4_1_3 = 91,
- VID_STRONGSWAN_4_1_4 = 92,
- VID_STRONGSWAN_4_1_5 = 93,
- VID_STRONGSWAN_4_1_6 = 94,
- VID_STRONGSWAN_4_1_7 = 95,
- VID_STRONGSWAN_4_1_8 = 96,
- VID_STRONGSWAN_4_1_9 = 97,
- VID_STRONGSWAN_4_1_10 = 98,
- VID_STRONGSWAN_4_1_11 = 99,
- VID_STRONGSWAN_4_2_0 =100,
- VID_STRONGSWAN_4_2_1 =101,
- VID_STRONGSWAN_4_2_2 =102,
- VID_STRONGSWAN_4_2_3 =103,
- VID_STRONGSWAN_4_2_4 =104,
- VID_STRONGSWAN_4_2_5 =105,
- VID_STRONGSWAN_4_2_6 =106,
- VID_STRONGSWAN_4_2_7 =107,
- VID_STRONGSWAN_4_2_8 =108,
- VID_STRONGSWAN_4_2_9 =109,
- VID_STRONGSWAN_4_2_10 =110,
- VID_STRONGSWAN_4_2_11 =111,
- VID_STRONGSWAN_4_2_12 =112,
- VID_STRONGSWAN_4_2_13 =113,
- VID_STRONGSWAN_4_2_14 =114,
- VID_STRONGSWAN_4_2_15 =115,
- VID_STRONGSWAN_4_2_16 =116,
- VID_STRONGSWAN_4_2_17 =117,
- VID_STRONGSWAN_4_3_0 =118,
- VID_STRONGSWAN_4_3_1 =119,
- VID_STRONGSWAN_4_3_2 =120,
- VID_STRONGSWAN_4_3_3 =121,
- VID_STRONGSWAN_4_3_4 =122,
- VID_STRONGSWAN_4_3_5 =123,
-
- /* 101 - 200 : NAT-Traversal */
- VID_NATT_STENBERG_01 =151,
- VID_NATT_STENBERG_02 =152,
- VID_NATT_HUTTUNEN =153,
- VID_NATT_HUTTUNEN_ESPINUDP =154,
- VID_NATT_IETF_00 =155,
- VID_NATT_IETF_02_N =156,
- VID_NATT_IETF_02 =157,
- VID_NATT_IETF_03 =158,
- VID_NATT_RFC =159,
-
- /* 201 - 300 : Misc */
- VID_MISC_XAUTH =201,
- VID_MISC_DPD =202,
- VID_MISC_HEARTBEAT_NOTIFY =203,
- VID_MISC_FRAGMENTATION =204,
- VID_INITIAL_CONTACT =205,
- VID_CISCO3K_FRAGMENTATION =206
-};
-
-void init_vendorid(void);
-void free_vendorid(void);
-
-struct msg_digest;
-void handle_vendorid (struct msg_digest *md, const char *vid, size_t len);
-
-bool out_vendorid (u_int8_t np, pb_stream *outs, enum known_vendorid vid);
-
-#endif /* _VENDOR_H_ */
-
diff --git a/src/pluto/virtual.c b/src/pluto/virtual.c
deleted file mode 100644
index 3e8d5fcba..000000000
--- a/src/pluto/virtual.c
+++ /dev/null
@@ -1,325 +0,0 @@
-/* FreeS/WAN Virtual IP Management
- * Copyright (C) 2002 Mathieu Lafon - Arkoon Network Security
- *
- * 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 <freeswan.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <sys/queue.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "log.h"
-#include "connections.h"
-#include "whack.h"
-#include "virtual.h"
-
-#define F_VIRTUAL_NO 1
-#define F_VIRTUAL_DHCP 2
-#define F_VIRTUAL_IKE_CONFIG 4
-#define F_VIRTUAL_PRIVATE 8
-#define F_VIRTUAL_ALL 16
-#define F_VIRTUAL_HOST 32
-
-struct virtual_t {
- unsigned short flags;
- unsigned short n_net;
- ip_subnet net[0];
-};
-
-static ip_subnet *private_net_ok=NULL, *private_net_ko=NULL;
-static unsigned short private_net_ok_len=0, private_net_ko_len=0;
-
-/**
- * read %v4:x.x.x.x/y or %v6:xxxxxxxxx/yy
- * or %v4:!x.x.x.x/y if dstko not NULL
- */
-static bool
-_read_subnet(const char *src, size_t len, ip_subnet *dst, ip_subnet *dstko,
- bool *isok)
-{
- bool ok;
- int af;
-
- if ((len > 4) && (strneq(src, "%v4:", 4)))
- {
- af = AF_INET;
- }
- else if ((len > 4) && (strneq(src, "%v6:", 4)))
- {
- af = AF_INET6;
- }
- else
- {
- return FALSE;
- }
-
- ok = (src[4] != '!');
- src += ok ? 4 : 5;
- len -= ok ? 4 : 5;
-
- if (!len)
- return FALSE;
- if (!ok && !dstko)
- return FALSE;
-
- passert ( ((ok)?(dst):(dstko))!=NULL );
-
- if (ttosubnet(src, len, af, ((ok)?(dst):(dstko))))
- {
- return FALSE;
- }
- if (isok)
- *isok = ok;
- return TRUE;
-}
-
-void
-init_virtual_ip(const char *private_list)
-{
- const char *next, *str=private_list;
- unsigned short ign = 0, i_ok, i_ko;
- ip_subnet sub;
- bool ok;
-
- /** Count **/
- private_net_ok_len=0;
- private_net_ko_len=0;
-
- while (str)
- {
- next = strchr(str,',');
- if (!next)
- next = str + strlen(str);
- if (_read_subnet(str, next-str, &sub, &sub, &ok))
- if (ok)
- private_net_ok_len++;
- else
- private_net_ko_len++;
- else
- ign++;
- str = *next ? next+1 : NULL;
- }
-
- if (!ign)
- {
- /** Allocate **/
- if (private_net_ok_len)
- {
- private_net_ok = (ip_subnet *)malloc(private_net_ok_len * sizeof(ip_subnet));
- }
- if (private_net_ko_len)
- {
- private_net_ko = (ip_subnet *)malloc(private_net_ko_len * sizeof(ip_subnet));
- }
- if ((private_net_ok_len && !private_net_ok)
- || (private_net_ko_len && !private_net_ko))
- {
- loglog(RC_LOG_SERIOUS,
- "can't alloc in init_virtual_ip");
- free(private_net_ok);
- private_net_ok = NULL;
- free(private_net_ko);
- private_net_ko = NULL;
- }
- else
- {
- /** Fill **/
- str = private_list;
- i_ok = 0;
- i_ko = 0;
-
- while (str)
- {
- next = strchr(str,',');
- if (!next)
- next = str + strlen(str);
- if (_read_subnet(str, next-str,
- &(private_net_ok[i_ok]), &(private_net_ko[i_ko]), &ok))
- {
- if (ok)
- i_ok++;
- else
- i_ko++;
- }
- str = *next ? next+1 : NULL;
- }
- }
- }
- else
- loglog(RC_LOG_SERIOUS,
- "%d bad entries in virtual_private - none loaded", ign);
-}
-
-/**
- * virtual string must be :
- * {vhost,vnet}:[%method]*
- *
- * vhost = accept only a host (/32)
- * vnet = accept any network
- *
- * %no = no virtual IP (accept public IP)
- * %dhcp = accept DHCP SA (0.0.0.0/0) of affected IP [not implemented]
- * %ike = accept affected IKE Config Mode IP [not implemented]
- * %priv = accept system-wide private net list
- * %v4:x = accept ipv4 in list 'x'
- * %v6:x = accept ipv6 in list 'x'
- * %all = accept all ips [only for testing]
- *
- * ex: vhost:%no,%dhcp,%priv,%v4:192.168.1.0/24
- */
-struct virtual_t
-*create_virtual(const connection_t *c, const char *string)
-{
- unsigned short flags=0, n_net=0, i;
- const char *str = string, *next, *first_net=NULL;
- ip_subnet sub;
- struct virtual_t *v;
-
- if (!string || string[0] == '\0')
- return NULL;
-
- if (strlen(string) >= 6 && strneq(string,"vhost:",6))
- {
- flags |= F_VIRTUAL_HOST;
- str += 6;
- }
- else if (strlen(string) >= 5 && strneq(string,"vnet:",5))
- str += 5;
- else
- goto fail;
-
- /**
- * Parse string : fill flags & count subnets
- */
- while ((str) && (*str))
- {
- next = strchr(str,',');
- if (!next) next = str + strlen(str);
- if (next-str == 3 && strneq(str, "%no", 3))
- flags |= F_VIRTUAL_NO;
-#if 0
- else if (next-str == 4 && strneq(str, "%ike", 4))
- flags |= F_VIRTUAL_IKE_CONFIG;
- else if (next-str == 5 && strneq(str, "%dhcp", 5))
- flags |= F_VIRTUAL_DHCP;
-#endif
- else if (next-str == 5 && strneq(str, "%priv", 5))
- flags |= F_VIRTUAL_PRIVATE;
- else if (next-str == 4 && strneq(str, "%all", 4))
- flags |= F_VIRTUAL_ALL;
- else if (_read_subnet(str, next-str, &sub, NULL, NULL))
- {
- n_net++;
- if (!first_net)
- first_net = str;
- }
- else
- goto fail;
-
- str = *next ? next+1 : NULL;
- }
-
- v = (struct virtual_t *)malloc(sizeof(struct virtual_t) +
- (n_net * sizeof(ip_subnet)));
- if (!v) goto fail;
-
- v->flags = flags;
- v->n_net = n_net;
- if (n_net && first_net)
- {
- /**
- * Save subnets in newly allocated struct
- */
- for (str = first_net, i = 0; str && *str; )
- {
- next = strchr(str,',');
- if (!next) next = str + strlen(str);
- if (_read_subnet(str, next-str, &(v->net[i]), NULL, NULL))
- i++;
- str = *next ? next+1 : NULL;
- }
- }
-
- return v;
-
-fail:
- plog("invalid virtual string [%s] - "
- "virtual selection disabled for connection '%s'", string, c->name);
- return NULL;
-}
-
-bool
-is_virtual_end(const struct end *that)
-{
- return ((that->virt)?TRUE:FALSE);
-}
-
-bool
-is_virtual_connection(const connection_t *c)
-{
- return ((c->spd.that.virt)?TRUE:FALSE);
-}
-
-static bool net_in_list(const ip_subnet *peer_net, const ip_subnet *list,
- unsigned short len)
-{
- unsigned short i;
-
- if (!list || !len)
- return FALSE;
-
- for (i = 0; i < len; i++)
- {
- if (subnetinsubnet(peer_net, &(list[i])))
- return TRUE;
- }
- return FALSE;
-}
-
-bool is_virtual_net_allowed(const connection_t *c, const ip_subnet *peer_net,
- const ip_address *his_addr)
-{
- if (c->spd.that.virt == NULL)
- return FALSE;
-
- if ((c->spd.that.virt->flags & F_VIRTUAL_HOST)
- && !subnetishost(peer_net))
- return FALSE;
-
- if ((c->spd.that.virt->flags & F_VIRTUAL_NO)
- && subnetishost(peer_net) && addrinsubnet(his_addr, peer_net))
- return TRUE;
-
- if ((c->spd.that.virt->flags & F_VIRTUAL_PRIVATE)
- && net_in_list(peer_net, private_net_ok, private_net_ok_len)
- && !net_in_list(peer_net, private_net_ko, private_net_ko_len))
- return TRUE;
-
- if (c->spd.that.virt->n_net
- && net_in_list(peer_net, c->spd.that.virt->net, c->spd.that.virt->n_net))
- return TRUE;
-
- if (c->spd.that.virt->flags & F_VIRTUAL_ALL)
- {
- /** %all must only be used for testing - log it **/
- loglog(RC_LOG_SERIOUS, "Warning - "
- "v%s:%%all must only be used for testing",
- (c->spd.that.virt->flags & F_VIRTUAL_HOST) ? "host" : "net");
- return TRUE;
- }
-
- return FALSE;
-}
-
diff --git a/src/pluto/virtual.h b/src/pluto/virtual.h
deleted file mode 100644
index e64407c81..000000000
--- a/src/pluto/virtual.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* FreeS/WAN Virtual IP Management
- * Copyright (C) 2002 Mathieu Lafon - Arkoon Network Security
- *
- * 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.
- */
-
-#ifndef _VIRTUAL_IP_H
-#define _VIRTUAL_IP_H
-
-extern void init_virtual_ip(const char *private_list);
-
-extern struct virtual_t *create_virtual(const struct connection *c,
- const char *string);
-
-extern bool is_virtual_end(const struct end *that);
-extern bool is_virtual_connection(const struct connection *c);
-extern bool is_virtual_net_allowed(const struct connection *c,
- const ip_subnet *peer_net, const ip_address *his_addr);
-
-#endif /* _VIRTUAL_IP_H */
-
diff --git a/src/pluto/whack_attribute.c b/src/pluto/whack_attribute.c
deleted file mode 100644
index 6a12f0c09..000000000
--- a/src/pluto/whack_attribute.c
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * Copyright (C) 2010 Tobias Brunner
- * Copyright (C) 2008 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include "whack_attribute.h"
-
-#include "log.h"
-
-/* these are defined as constants in constant.h but redefined as enum values in
- * attributes/attributes.h */
-#undef INTERNAL_IP4_SERVER
-#undef INTERNAL_IP6_SERVER
-
-#include <hydra.h>
-#include <attributes/mem_pool.h>
-#include <utils/linked_list.h>
-#include <threading/rwlock.h>
-
-typedef struct private_whack_attribute_t private_whack_attribute_t;
-
-/**
- * private data of whack_attribute
- */
-struct private_whack_attribute_t {
-
- /**
- * public functions
- */
- whack_attribute_t public;
-
- /**
- * list of pools, contains mem_pool_t
- */
- linked_list_t *pools;
-
- /**
- * rwlock to lock access to pools
- */
- rwlock_t *lock;
-};
-
-/**
- * global object
- */
-whack_attribute_t *whack_attr;
-
-/**
- * compare pools by name
- */
-static bool pool_match(mem_pool_t *current, char *name)
-{
- return name && streq(name, current->get_name(current));
-}
-
-/**
- * find a pool by name
- */
-static mem_pool_t *find_pool(private_whack_attribute_t *this, char *name)
-{
- mem_pool_t *found;
- if (this->pools->find_first(this->pools, (linked_list_match_t)pool_match,
- (void**)&found, name) == SUCCESS)
- {
- return found;
- }
- return NULL;
-}
-
-METHOD(attribute_provider_t, acquire_address, host_t*,
- private_whack_attribute_t *this, char *name, identification_t *id,
- host_t *requested)
-{
- mem_pool_t *pool;
- host_t *addr = NULL;
- this->lock->read_lock(this->lock);
- pool = find_pool(this, name);
- if (pool)
- {
- addr = pool->acquire_address(pool, id, requested);
- }
- this->lock->unlock(this->lock);
- return addr;
-}
-
-METHOD(attribute_provider_t, release_address, bool,
- private_whack_attribute_t *this, char *name, host_t *address,
- identification_t *id)
-{
- mem_pool_t *pool;
- bool found = FALSE;
- this->lock->read_lock(this->lock);
- pool = find_pool(this, name);
- if (pool)
- {
- found = pool->release_address(pool, address, id);
- }
- this->lock->unlock(this->lock);
- return found;
-}
-
-METHOD(whack_attribute_t, add_pool, bool,
- private_whack_attribute_t *this, const char *name,
- const whack_end_t *right)
-{
- mem_pool_t *pool;
- host_t *base = NULL;
- u_int32_t bits = 0;
-
- /* named pool */
- if (right->sourceip_mask <= 0)
- {
- return FALSE;
- }
-
- /* if %config, add an empty pool, otherwise */
- if (right->sourceip)
- {
- DBG(DBG_CONTROL,
- DBG_log("adding virtual IP address pool '%s': %s/%d",
- name, right->sourceip, right->sourceip_mask);
- );
- base = host_create_from_string(right->sourceip, 0);
- if (!base)
- {
- loglog(RC_LOG_SERIOUS, "virtual IP address invalid, discarded");
- return FALSE;
- }
- bits = right->sourceip_mask;
- }
- pool = mem_pool_create((char*)name, base, bits);
- DESTROY_IF(base);
-
- this->lock->write_lock(this->lock);
- this->pools->insert_last(this->pools, pool);
- this->lock->unlock(this->lock);
- return TRUE;
-}
-
-METHOD(whack_attribute_t, del_pool, void,
- private_whack_attribute_t *this, char *name)
-{
- enumerator_t *enumerator;
- mem_pool_t *pool;
-
- this->lock->write_lock(this->lock);
- enumerator = this->pools->create_enumerator(this->pools);
- while (enumerator->enumerate(enumerator, &pool))
- {
- if (streq(name, pool->get_name(pool)))
- {
- DBG(DBG_CONTROL,
- DBG_log("deleting virtual IP address pool '%s'", name)
- );
- this->pools->remove_at(this->pools, enumerator);
- pool->destroy(pool);
- break;
- }
- }
- enumerator->destroy(enumerator);
- this->lock->unlock(this->lock);
-}
-
-/**
- * Pool enumerator filter function, converts pool_t to name, size, ...
- */
-static bool pool_filter(void *lock, mem_pool_t **poolp, const char **name,
- void *d1, u_int *size, void *d2, u_int *online,
- void *d3, u_int *offline)
-{
- mem_pool_t *pool = *poolp;
- *name = pool->get_name(pool);
- *size = pool->get_size(pool);
- *online = pool->get_online(pool);
- *offline = pool->get_offline(pool);
- return TRUE;
-}
-
-METHOD(whack_attribute_t, create_pool_enumerator, enumerator_t*,
- private_whack_attribute_t *this)
-{
- this->lock->read_lock(this->lock);
- return enumerator_create_filter(this->pools->create_enumerator(this->pools),
- (void*)pool_filter,
- this->lock, (void*)this->lock->unlock);
-}
-
-METHOD(whack_attribute_t, create_lease_enumerator, enumerator_t*,
- private_whack_attribute_t *this, char *name)
-{
- mem_pool_t *pool;
- this->lock->read_lock(this->lock);
- pool = find_pool(this, name);
- if (!pool)
- {
- this->lock->unlock(this->lock);
- return NULL;
- }
- return enumerator_create_cleaner(pool->create_lease_enumerator(pool),
- (void*)this->lock->unlock, this->lock);
-}
-
-/**
- * see header file
- */
-void whack_attribute_finalize()
-{
- private_whack_attribute_t *this;
-
- if (whack_attr)
- {
- this = (private_whack_attribute_t*)whack_attr;
- hydra->attributes->remove_provider(hydra->attributes,
- &this->public.provider);
- this->lock->destroy(this->lock);
- this->pools->destroy_offset(this->pools, offsetof(mem_pool_t, destroy));
- free(this);
- }
-}
-
-/**
- * see header file
- */
-void whack_attribute_initialize()
-{
- private_whack_attribute_t *this;
-
- INIT(this,
- .public = {
- .provider = {
- .acquire_address = _acquire_address,
- .release_address = _release_address,
- .create_attribute_enumerator = enumerator_create_empty,
- },
- .add_pool = _add_pool,
- .del_pool = _del_pool,
- .create_pool_enumerator = _create_pool_enumerator,
- .create_lease_enumerator = _create_lease_enumerator,
- },
- .pools = linked_list_create(),
- .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
- );
-
- hydra->attributes->add_provider(hydra->attributes, &this->public.provider);
-
- whack_attr = &this->public;
-}
-
-/**
- * list leases of a single pool
- */
-static void pool_leases(char *pool, host_t *address,
- identification_t *identification,
- u_int size, u_int online, u_int offline)
-{
-
- enumerator_t *enumerator;
- identification_t *id;
- host_t *lease;
- bool on, found = FALSE;
-
- whack_log(RC_COMMENT, "Leases in pool '%s', usage: %lu/%lu, %lu online",
- pool, online + offline, size, online);
- enumerator = whack_attr->create_lease_enumerator(whack_attr, pool);
- while (enumerator && enumerator->enumerate(enumerator, &id, &lease, &on))
- {
- if ((!address && !identification) ||
- (address && address->ip_equals(address, lease)) ||
- (identification && identification->equals(identification, id)))
- {
- whack_log(RC_COMMENT, " %15H %s '%Y'",
- lease, on ? "online" : "offline", id);
- found = TRUE;
- }
- }
- enumerator->destroy(enumerator);
- if (!found)
- {
- whack_log(RC_COMMENT, " no matching leases found");
- }
-}
-
-/**
- * see header file
- */
-void list_leases(char *name, char *addr, char *id)
-{
- identification_t *identification = NULL;
- host_t *address = NULL;
- bool found = FALSE;
- enumerator_t *enumerator;
- u_int size, online, offline;
- char *pool;
-
- if (addr)
- {
- address = host_create_from_string(addr, 0);
- }
- if (id)
- {
- identification = identification_create_from_string(id);
- }
-
- enumerator = whack_attr->create_pool_enumerator(whack_attr);
- while (enumerator->enumerate(enumerator, &pool, &size, &online, &offline))
- {
- if (!name || streq(name, pool))
- {
- pool_leases(pool, address, identification, size, online, offline);
- found = TRUE;
- }
- }
- enumerator->destroy(enumerator);
- if (!found)
- {
- if (name)
- {
- whack_log(RC_COMMENT, "pool '%s' not found", name);
- }
- else
- {
- whack_log(RC_COMMENT, "no pools found");
- }
- }
- DESTROY_IF(identification);
- DESTROY_IF(address);
-}
-
-/**
- * see header file
- */
-void show_pools(const char *name)
-{
- enumerator_t *enumerator;
- u_int size, online, offline;
- char *pool;
- bool first = TRUE;
-
- enumerator = whack_attr->create_pool_enumerator(whack_attr);
- while (enumerator->enumerate(enumerator, &pool, &size, &online, &offline))
- {
- if (name && !streq(name, pool))
- {
- continue;
- }
- if (first)
- {
- first = FALSE;
- whack_log(RC_COMMENT, "Virtual IP pools (size/online/offline):");
- }
- whack_log(RC_COMMENT, "\"%s\": %u/%u/%u", pool, size, online, offline);
- }
- enumerator->destroy(enumerator);
-}
diff --git a/src/pluto/whack_attribute.h b/src/pluto/whack_attribute.h
deleted file mode 100644
index 58441b973..000000000
--- a/src/pluto/whack_attribute.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2010 Tobias Brunner
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup whack_attribute
- * @{ @ingroup pluto
- */
-
-#ifndef WHACK_ATTRIBUTE_H_
-#define WHACK_ATTRIBUTE_H_
-
-#include <whack.h>
-#include <attributes/attribute_provider.h>
-
-typedef struct whack_attribute_t whack_attribute_t;
-
-/**
- * Whack attribute provider (basically an in-memory IP address pool)
- */
-struct whack_attribute_t {
-
- /**
- * Implements attribute provider interface
- */
- attribute_provider_t provider;
-
- /**
- * Add a virtual IP address pool.
- *
- * @param name name of the pool
- * @param right "right" end of whack message
- * @return TRUE, if the pool was successfully added
- */
- bool (*add_pool)(whack_attribute_t *this, const char *name,
- const whack_end_t *right);
-
- /**
- * Remove a virtual IP address pool.
- *
- * @param name name of the pool
- */
- void (*del_pool)(whack_attribute_t *this, char *name);
-
- /**
- * Create an enumerator over installed pools.
- *
- * Enumerator enumerates over
- * char *pool, u_int size, u_int offline, u_int online.
- *
- * @return enumerator
- */
- enumerator_t* (*create_pool_enumerator)(whack_attribute_t *this);
-
- /**
- * Create an enumerator over the leases of a pool.
- *
- * Enumerator enumerates over
- * identification_t *id, host_t *address, bool online
- *
- * @param name name of the pool to enumerate
- * @return enumerator, NULL if pool not found
- */
- enumerator_t* (*create_lease_enumerator)(whack_attribute_t *this,
- char *name);
-};
-
-/**
- * Global object to manage pools. Set between calls to
- * whack_attribute_initialize() and whack_attribute_finalize().
- */
-extern whack_attribute_t *whack_attr;
-
-/**
- * Initialize the whack attribute provider
- */
-void whack_attribute_initialize();
-
-/**
- * Finalize the whack attribute provider
- */
-void whack_attribute_finalize();
-
-/**
- * List the leases matching the given parameters.
- *
- * @param name name of the pool, NULL for all pools
- * @param addr ip address of the lease to list, NULL to ignore
- * @param id id of the lease to list, NULL to ignore
- */
-void list_leases(char *name, char *addr, char *id);
-
-/**
- * List either all pools or the pool with a given name
- *
- * @param name name of the pool, NULL for all pools
- */
-void show_pools(const char *name);
-
-#endif /** WHACK_ATTRIBUTE_H_ @}*/
diff --git a/src/pluto/x509.c b/src/pluto/x509.c
deleted file mode 100644
index f017e5775..000000000
--- a/src/pluto/x509.c
+++ /dev/null
@@ -1,463 +0,0 @@
-/* Support of X.509 certificates
- * Copyright (C) 2000 Andreas Hess, Patric Lichtsteiner, Roger Wegmann
- * Copyright (C) 2001 Marco Bertossa, Andreas Schleiss
- * Copyright (C) 2002 Mario Strasser
- * Copyright (C) 2000-2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <time.h>
-#include <sys/types.h>
-
-#include <freeswan.h>
-
-#include <asn1/asn1.h>
-#include <crypto/hashers/hasher.h>
-#include <utils/enumerator.h>
-#include <utils/identification.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "log.h"
-#include "x509.h"
-#include "crl.h"
-#include "ca.h"
-#include "certs.h"
-#include "keys.h"
-#include "whack.h"
-#include "fetch.h"
-#include "ocsp.h"
-
-/**
- * Check for equality between two key identifiers
- */
-bool same_keyid(chunk_t a, chunk_t b)
-{
- if (a.ptr == NULL || b.ptr == NULL)
- {
- return FALSE;
- }
- return chunk_equals(a, b);
-}
-
-/**
- * Stores a chained list of end certs and CA certs
- */
-void store_x509certs(linked_list_t *certs, bool strict)
-{
- cert_t *x509cert, *cacerts = NULL;
- certificate_t *cert;
- enumerator_t *enumerator;
-
- /* first extract CA certs, ignoring self-signed root CA certs */
-
- enumerator = certs->create_enumerator(certs);
- while (enumerator->enumerate(enumerator, &cert))
- {
- x509_t *x509 = (x509_t*)cert;
- x509_flag_t flags;
-
- flags = x509->get_flags(x509);
- if (flags & X509_CA)
- {
- /* we don't accept self-signed CA certs */
- if (flags & X509_SELF_SIGNED)
- {
- plog("self-signed cacert rejected");
- }
- else
- {
- /* insertion into temporary chain of candidate CA certs */
- x509cert = malloc_thing(cert_t);
- *x509cert = cert_empty;
- x509cert->cert = cert->get_ref(cert);
- x509cert->next = cacerts;
- cacerts = x509cert;
- }
- }
- }
- enumerator->destroy(enumerator);
-
- /* now verify the candidate CA certs */
-
- while (cacerts)
- {
- cert_t *cert = cacerts;
-
- cacerts = cacerts->next;
-
- if (trust_authcert_candidate(cert, cacerts))
- {
- add_authcert(cert, X509_CA);
- }
- else
- {
- plog("intermediate cacert rejected");
- cert_free(cert);
- }
- }
-
- /* now verify the end certificates */
-
- enumerator = certs->create_enumerator(certs);
- while (enumerator->enumerate(enumerator, &cert))
- {
- time_t valid_until;
- x509_t *x509 = (x509_t*)cert;
-
- if (!(x509->get_flags(x509) & X509_CA))
- {
- x509cert = malloc_thing(cert_t);
- *x509cert = cert_empty;
- x509cert->cert = cert->get_ref(cert);
-
- if (verify_x509cert(x509cert, strict, &valid_until))
- {
- DBG(DBG_CONTROL | DBG_PARSING,
- DBG_log("public key validated")
- )
- add_public_key_from_cert(x509cert, valid_until, DAL_SIGNED);
- }
- else
- {
- plog("X.509 certificate rejected");
- cert_free(x509cert);
- }
- }
- }
- enumerator->destroy(enumerator);
-}
-
-/**
- * Check if a signature over binary blob is genuine
- */
-bool x509_check_signature(chunk_t tbs, chunk_t sig, int algorithm,
- certificate_t *issuer_cert)
-{
- bool success;
- public_key_t *key;
- signature_scheme_t scheme;
-
- scheme = signature_scheme_from_oid(algorithm);
- if (scheme == SIGN_UNKNOWN)
- {
- return FALSE;
- }
-
- key = issuer_cert->get_public_key(issuer_cert);
- if (key == NULL)
- {
- return FALSE;
- }
- success = key->verify(key, scheme, tbs, sig);
- key->destroy(key);
-
- return success;
-}
-
-/**
- * Build an ASN.1 encoded PKCS#1 signature over a binary blob
- */
-chunk_t x509_build_signature(chunk_t tbs, int algorithm, private_key_t *key,
- bool bit_string)
-{
- chunk_t signature;
- signature_scheme_t scheme = signature_scheme_from_oid(algorithm);
-
- if (scheme == SIGN_UNKNOWN || !key->sign(key, scheme, tbs, &signature))
- {
- return chunk_empty;
- }
- return (bit_string) ? asn1_bitstring("m", signature)
- : asn1_wrap(ASN1_OCTET_STRING, "m", signature);
-}
-
-/**
- * Verifies a X.509 certificate
- */
-bool verify_x509cert(cert_t *cert, bool strict, time_t *until)
-{
- int pathlen, pathlen_constraint;
-
- *until = 0;
-
- for (pathlen = -1; pathlen <= X509_MAX_PATH_LEN; pathlen++)
- {
- certificate_t *certificate = cert->cert;
- identification_t *subject = certificate->get_subject(certificate);
- identification_t *issuer = certificate->get_issuer(certificate);
- x509_t *x509 = (x509_t*)certificate;
- chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
- cert_t *issuer_cert;
- time_t notBefore, notAfter;
- bool valid;
-
- DBG(DBG_CONTROL,
- DBG_log("subject: '%Y'", subject);
- DBG_log("issuer: '%Y'", issuer);
- if (authKeyID.ptr)
- {
- DBG_log("authkey: %#B", &authKeyID);
- }
- )
-
- valid = certificate->get_validity(certificate, NULL,
- &notBefore, &notAfter);
- if (*until == UNDEFINED_TIME || notAfter < *until)
- {
- *until = notAfter;
- }
- if (!valid)
- {
- plog("certificate is invalid (valid from %T to %T)",
- &notBefore, FALSE, &notAfter, FALSE);
- return FALSE;
- }
- DBG(DBG_CONTROL,
- DBG_log("certificate is valid")
- )
-
- lock_authcert_list("verify_x509cert");
- issuer_cert = get_authcert(issuer, authKeyID, X509_CA);
- if (issuer_cert == NULL)
- {
- plog("issuer cacert not found");
- unlock_authcert_list("verify_x509cert");
- return FALSE;
- }
- DBG(DBG_CONTROL,
- DBG_log("issuer cacert found")
- )
-
- if (!certificate->issued_by(certificate, issuer_cert->cert))
- {
- plog("certificate signature is invalid");
- unlock_authcert_list("verify_x509cert");
- return FALSE;
- }
- DBG(DBG_CONTROL,
- DBG_log("certificate signature is valid")
- )
- unlock_authcert_list("verify_x509cert");
-
- /* check path length constraint */
- pathlen_constraint = x509->get_constraint(x509, X509_PATH_LEN);
- if (pathlen_constraint != X509_NO_CONSTRAINT &&
- pathlen > pathlen_constraint)
- {
- plog("path length of %d violates constraint of %d",
- pathlen, pathlen_constraint);
- return FALSE;
- }
-
- /* check if cert is a self-signed root ca */
- if (pathlen >= 0 && (x509->get_flags(x509) & X509_SELF_SIGNED))
- {
- DBG(DBG_CONTROL,
- DBG_log("reached self-signed root ca with a path length of %d",
- pathlen)
- )
- return TRUE;
- }
- else
- {
- time_t nextUpdate = *until;
- time_t revocationDate = UNDEFINED_TIME;
- crl_reason_t revocationReason = CRL_REASON_UNSPECIFIED;
-
- /* first check certificate revocation using ocsp */
- cert_status_t status = verify_by_ocsp(cert, &nextUpdate
- , &revocationDate, &revocationReason);
-
- /* if ocsp service is not available then fall back to crl */
- if ((status == CERT_UNDEFINED)
- || (status == CERT_UNKNOWN && strict))
- {
- status = verify_by_crl(cert, &nextUpdate, &revocationDate
- , &revocationReason);
- }
-
- switch (status)
- {
- case CERT_GOOD:
- /* if status information is stale */
- if (strict && nextUpdate < time(NULL))
- {
- DBG(DBG_CONTROL,
- DBG_log("certificate is good but status is stale")
- )
- remove_x509_public_key(cert);
- return FALSE;
- }
- DBG(DBG_CONTROL,
- DBG_log("certificate is good")
- )
-
- /* with strict crl policy the public key must have the same
- * lifetime as the validity of the ocsp status or crl lifetime
- */
- if (strict && nextUpdate < *until)
- {
- *until = nextUpdate;
- }
- break;
- case CERT_REVOKED:
- plog("certificate was revoked on %T, reason: %N"
- , &revocationDate, TRUE
- , crl_reason_names, revocationReason);
- remove_x509_public_key(cert);
- return FALSE;
- case CERT_UNKNOWN:
- case CERT_UNDEFINED:
- default:
- plog("certificate status unknown");
- if (strict)
- {
- remove_x509_public_key(cert);
- return FALSE;
- }
- break;
- }
- }
-
- /* go up one step in the trust chain */
- cert = issuer_cert;
- }
- plog("maximum path length of %d exceeded", X509_MAX_PATH_LEN);
- return FALSE;
-}
-
-/**
- * List all X.509 certs in a chained list
- */
-void list_x509cert_chain(const char *caption, cert_t* cert,
- x509_flag_t flags, bool utc)
-{
- bool first = TRUE;
- time_t now;
-
- /* determine the current time */
- time(&now);
-
- while (cert)
- {
- certificate_t *certificate = cert->cert;
- x509_t *x509 = (x509_t*)certificate;
-
- if (certificate->get_type(certificate) == CERT_X509 &&
- (flags == X509_NONE || (flags & x509->get_flags(x509))))
- {
- enumerator_t *enumerator;
- char buf[BUF_LEN];
- char *pos = buf;
- int len = BUF_LEN, pathlen;
- bool first_altName = TRUE;
- identification_t *id;
- time_t notBefore, notAfter;
- public_key_t *key;
- chunk_t serial, keyid, subjkey, authkey;
-
- if (first)
- {
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, "List of X.509 %s Certificates:", caption);
- first = FALSE;
- }
- whack_log(RC_COMMENT, " ");
-
- enumerator = x509->create_subjectAltName_enumerator(x509);
- while (enumerator->enumerate(enumerator, &id))
- {
- int written;
-
- if (first_altName)
- {
- written = snprintf(pos, len, "%Y", id);
- first_altName = FALSE;
- }
- else
- {
- written = snprintf(pos, len, ", %Y", id);
- }
- if (written < 0 || written >= len)
- {
- break;
- }
- pos += written;
- len -= written;
- }
- enumerator->destroy(enumerator);
- if (!first_altName)
- {
- whack_log(RC_COMMENT, " altNames: %s", buf);
- }
-
- whack_log(RC_COMMENT, " subject: \"%Y\"",
- certificate->get_subject(certificate));
- whack_log(RC_COMMENT, " issuer: \"%Y\"",
- certificate->get_issuer(certificate));
- serial = chunk_skip_zero(x509->get_serial(x509));
- whack_log(RC_COMMENT, " serial: %#B", &serial);
-
- /* list validity */
- certificate->get_validity(certificate, &now, &notBefore, &notAfter);
- whack_log(RC_COMMENT, " validity: not before %T %s",
- &notBefore, utc,
- (notBefore < now)?"ok":"fatal (not valid yet)");
- whack_log(RC_COMMENT, " not after %T %s",
- &notAfter, utc,
- check_expiry(notAfter, CA_CERT_WARNING_INTERVAL, TRUE));
-
- key = certificate->get_public_key(certificate);
- if (key)
- {
- whack_log(RC_COMMENT, " pubkey: %N %4d bits%s",
- key_type_names, key->get_type(key),
- key->get_keysize(key),
- cert->smartcard ? ", on smartcard" :
- (has_private_key(cert)? ", has private key" : ""));
-
- if (key->get_fingerprint(key, KEYID_PUBKEY_INFO_SHA1, &keyid))
- {
- whack_log(RC_COMMENT, " keyid: %#B", &keyid);
- }
- if (key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &subjkey))
- {
- whack_log(RC_COMMENT, " subjkey: %#B", &subjkey);
- }
- key->destroy(key);
- }
-
- /* list optional authorityKeyIdentifier */
- authkey = x509->get_authKeyIdentifier(x509);
- if (authkey.ptr)
- {
- whack_log(RC_COMMENT, " authkey: %#B", &authkey);
- }
-
- /* list optional pathLenConstraint */
- pathlen = x509->get_constraint(x509, X509_PATH_LEN);
- if (pathlen != X509_NO_CONSTRAINT)
- {
- whack_log(RC_COMMENT, " pathlen: %d", pathlen);
- }
-
- }
- cert = cert->next;
- }
-}
-
diff --git a/src/pluto/x509.h b/src/pluto/x509.h
deleted file mode 100644
index 3101724a6..000000000
--- a/src/pluto/x509.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* Support of X.509 certificates
- * Copyright (C) 2000 Andreas Hess, Patric Lichtsteiner, Roger Wegmann
- * Copyright (C) 2001 Marco Bertossa, Andreas Schleiss
- * Copyright (C) 2002 Mario Strasser
- * Copyright (C) 2000-2009 Andreas Steffen, Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#ifndef _X509_H
-#define _X509_H
-
-#include <utils/identification.h>
-#include <utils/linked_list.h>
-#include <credentials/keys/private_key.h>
-#include <credentials/certificates/x509.h>
-
-#include "constants.h"
-#include "certs.h"
-
-#define X509_MAX_PATH_LEN 7
-
-extern bool same_keyid(chunk_t a, chunk_t b);
-extern bool x509_check_signature(chunk_t tbs, chunk_t sig, int algorithm,
- certificate_t *issuer_cert);
-extern chunk_t x509_build_signature(chunk_t tbs, int algorithm,
- private_key_t *key, bool bit_string);
-extern bool verify_x509cert(cert_t *cert, bool strict, time_t *until);
-extern void store_x509certs(linked_list_t *certs, bool strict);
-extern void list_x509cert_chain(const char *caption, cert_t* cert,
- x509_flag_t flags, bool utc);
-extern void list_x509_end_certs(bool utc);
-
-#endif /* _X509_H */
diff --git a/src/pluto/xauth/xauth_manager.c b/src/pluto/xauth/xauth_manager.c
deleted file mode 100644
index 2e57ccefa..000000000
--- a/src/pluto/xauth/xauth_manager.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2010 Andreas Steffen
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include "xauth_manager.h"
-
-typedef struct private_xauth_manager_t private_xauth_manager_t;
-
-/**
- * private data of xauth_manager
- */
-struct private_xauth_manager_t {
-
- /**
- * public functions
- */
- xauth_manager_t public;
-
- /**
- * list of registered secret providers
- */
- linked_list_t *providers;
-
- /**
- * list of registered secret verifiers
- */
- linked_list_t *verifiers;
-};
-
-METHOD(xauth_manager_t, get_secret, bool,
- private_xauth_manager_t *this, connection_t *c, chunk_t *secret)
-{
- xauth_provider_t *provider;
- enumerator_t *enumerator;
- bool success = FALSE;
-
- *secret = chunk_empty;
-
- enumerator = this->providers->create_enumerator(this->providers);
- while (enumerator->enumerate(enumerator, &provider))
- {
- if (provider->get_secret(provider, c, secret))
- {
- success = TRUE;
- break;
- }
- }
- enumerator->destroy(enumerator);
- return success;
-}
-
-METHOD(xauth_manager_t, verify_secret, bool,
- private_xauth_manager_t *this, connection_t *c, chunk_t secret)
-{
- xauth_verifier_t *verifier;
- enumerator_t *enumerator;
- bool success = FALSE;
-
- enumerator = this->verifiers->create_enumerator(this->verifiers);
- while (enumerator->enumerate(enumerator, &verifier))
- {
- if (verifier->verify_secret(verifier, c, secret))
- {
- success = TRUE;
- break;
- }
- }
- enumerator->destroy(enumerator);
- return success;
-}
-
-METHOD(xauth_manager_t, add_provider, void,
- private_xauth_manager_t *this, xauth_provider_t *provider)
-{
- this->providers->insert_last(this->providers, provider);
-}
-
-METHOD(xauth_manager_t, add_verifier, void,
- private_xauth_manager_t *this, xauth_verifier_t *verifier)
-{
- this->verifiers->insert_last(this->verifiers, verifier);
-}
-
-METHOD(xauth_manager_t, destroy, void,
- private_xauth_manager_t *this)
-{
- this->providers->destroy_offset(this->providers,
- offsetof(xauth_provider_t, destroy));
- this->verifiers->destroy_offset(this->verifiers,
- offsetof(xauth_verifier_t, destroy));
- free(this);
-}
-
-/*
- * Described in header.
- */
-xauth_manager_t *xauth_manager_create()
-{
- private_xauth_manager_t *this;
-
- INIT(this,
- .public = {
- .get_secret = _get_secret,
- .verify_secret = _verify_secret,
- .add_provider = _add_provider,
- .add_verifier = _add_verifier,
- .destroy = _destroy,
- }
- );
-
- this->providers = linked_list_create();
- this->verifiers = linked_list_create();
-
- return &this->public;
-}
-
diff --git a/src/pluto/xauth/xauth_manager.h b/src/pluto/xauth/xauth_manager.h
deleted file mode 100644
index 843eb2ff0..000000000
--- a/src/pluto/xauth/xauth_manager.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2010 Andreas Steffen
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup xauth_manager xauth_manager
- * @{ @ingroup xauth
- */
-
-#ifndef XAUTH_MANAGER_H_
-#define XAUTH_MANAGER_H_
-
-#include "xauth_provider.h"
-#include "xauth_verifier.h"
-
-typedef struct xauth_manager_t xauth_manager_t;
-
-/**
- * An xauth_manager registers xauth_providers and xauth_verifiers.
- */
-struct xauth_manager_t {
-
- /**
- * Register an xauth_provider
- *
- * @param provider xauth_provider to be registered
- */
- void (*add_provider)(xauth_manager_t *this, xauth_provider_t *provider);
-
- /**
- * Register an xauth_verifier
- *
- * @param verifier xauth_verifier to be registered
- */
- void (*add_verifier)(xauth_manager_t *this, xauth_verifier_t *verifier);
-
- /**
- * Use registered providers to retrieve an XAUTH user secret
- * based on connection information.
- *
- * @param c connection information
- * @param secret secret if found, chunk_empty otherwise
- * @return TRUE if a matching secret was found
- */
- bool (*get_secret)(xauth_manager_t *this, connection_t *c, chunk_t *secret);
-
- /**
- * Use registered verifiers to verify an XAUTH user secret
- * based on connection information
- *
- * @param c connection information
- * @param secret secret to be compared
- * @return TRUE if secret matches
- */
- bool (*verify_secret)(xauth_manager_t *this, connection_t *c, chunk_t secret);
-
- /**
- * Destroy an xauth_verifier instance.
- */
- void (*destroy)(xauth_manager_t *this);
-};
-
-/**
- * Create an xauth_manager instance.
- */
-xauth_manager_t *xauth_manager_create();
-
-#endif /** XAUTH_MANAGER_H_ @}*/
-
diff --git a/src/pluto/xauth/xauth_provider.h b/src/pluto/xauth/xauth_provider.h
deleted file mode 100644
index 90adbff50..000000000
--- a/src/pluto/xauth/xauth_provider.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2010 Andreas Steffen
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup xauth_provider xauth_provider
- * @{ @ingroup xauth
- */
-
-#ifndef XAUTH_PROVIDER_H_
-#define XAUTH_PROVIDER_H_
-
-#include <library.h>
-
-#include <connections.h>
-
-typedef struct xauth_provider_t xauth_provider_t;
-
-/**
- * An xauth provider retrieves xauth user secrets on the client side.
- */
-struct xauth_provider_t {
-
- /**
- * Retrieve an XAUTH user secret based on connection information.
- *
- * @param c connection information
- * @param secret secret if found, chunk_empty otherwise
- * @return TRUE if a matching secret was found
- */
- bool (*get_secret)(xauth_provider_t *this, connection_t *c, chunk_t *secret);
-
- /**
- * Destroy an xauth_provider instance.
- */
- void (*destroy)(xauth_provider_t *this);
-};
-
-/**
- * Create an xauth_provider instance.
- */
-xauth_provider_t *xauth_provider_create();
-
-#endif /** XAUTH_PROVIDER_H_ @}*/
-
diff --git a/src/pluto/xauth/xauth_verifier.h b/src/pluto/xauth/xauth_verifier.h
deleted file mode 100644
index 7c9ff3a7f..000000000
--- a/src/pluto/xauth/xauth_verifier.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2010 Andreas Steffen
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup xauth_verifier xauth_verifier
- * @{ @ingroup xauth
- */
-
-#ifndef XAUTH_VERIFIER_H_
-#define XAUTH_VERIFIER_H_
-
-#include <library.h>
-
-#include <connections.h>
-
-typedef struct xauth_verifier_t xauth_verifier_t;
-
-/**
- * An xauth verifier verifies xauth user secrets on the server side.
- */
-struct xauth_verifier_t {
-
- /**
- * Verify an XAUTH user secret base on connection information
- *
- * @param c connection information
- * @param secret secret to be compared
- * @return TRUE if secret matches
- */
- bool (*verify_secret)(xauth_verifier_t *this, connection_t *c, chunk_t secret);
-
- /**
- * Destroy an xauth_verifier instance.
- */
- void (*destroy)(xauth_verifier_t *this);
-};
-
-/**
- * Create an xauth_verifier instance.
- */
-xauth_verifier_t *xauth_verifier_create();
-
-#endif /** XAUTH_VERIFIER_H_ @}*/
-
diff --git a/src/scepclient/Makefile.am b/src/scepclient/Makefile.am
index 897b49ac3..930f3dd80 100644
--- a/src/scepclient/Makefile.am
+++ b/src/scepclient/Makefile.am
@@ -1,54 +1,19 @@
ipsec_PROGRAMS = scepclient
-scepclient_SOURCES = scepclient.c scep.c scep.h loglite.c
+scepclient_SOURCES = \
+scepclient.c scep.c scep.h
scepclient.o : $(top_builddir)/config.status
-PLUTODIR=$(top_srcdir)/src/pluto
-OPENACDIR=$(top_srcdir)/src/openac
-WHACKDIR=$(top_srcdir)/src/whack
-LIBFREESWANDIR=$(top_srcdir)/src/libfreeswan
-LIBSTRONGSWANDIR=$(top_srcdir)/src/libstrongswan
-LIBHYDRADIR=$(top_srcdir)/src/libhydra
-LIBCRYPTODIR=$(top_srcdir)/src/libcrypto
-
INCLUDES = \
--I$(LIBFREESWANDIR) \
--I$(LIBSTRONGSWANDIR) \
--I$(LIBHYDRADIR) \
--I$(PLUTODIR) \
--I$(LIBCRYPTODIR) \
--I$(WHACKDIR)
+-I$(top_srcdir)/src/libstrongswan \
+-I$(top_srcdir)/src/libhydra
AM_CFLAGS = \
-DIPSEC_CONFDIR=\"${sysconfdir}\" \
--DPLUGINS=\""${scepclient_plugins}\"" \
--DDEBUG -DNO_PLUTO
-
-LIBSTRONGSWANBUILDDIR=$(top_builddir)/src/libstrongswan
-LIBFREESWANBUILDDIR=$(top_builddir)/src/libfreeswan
+-DPLUGINS=\""${scepclient_plugins}\""
scepclient_LDADD = \
-constants.o defs.o lex.o pkcs7.o \
-$(LIBSTRONGSWANBUILDDIR)/libstrongswan.la \
-$(LIBFREESWANBUILDDIR)/libfreeswan.a
-
-# This compile option activates smartcard support
-if USE_SMARTCARD
- AM_CFLAGS += -DSMARTCARD
- scepclient_LDADD += $(DLLIB)
-endif
+$(top_builddir)/src/libstrongswan/libstrongswan.la
dist_man_MANS = scepclient.8
-constants.o : $(PLUTODIR)/constants.c $(PLUTODIR)/constants.h
- $(COMPILE) $(INCLUDES) -c -o $@ $<
-
-defs.o : $(PLUTODIR)/defs.c $(PLUTODIR)/defs.h
- $(COMPILE) $(INCLUDES) -c -o $@ $<
-
-lex.o : $(PLUTODIR)/lex.c $(PLUTODIR)/lex.h
- $(COMPILE) $(INCLUDES) -c -o $@ $<
-
-pkcs7.o : $(PLUTODIR)/pkcs7.c $(PLUTODIR)/pkcs7.h
- $(COMPILE) $(INCLUDES) -c -o $@ $<
-
diff --git a/src/scepclient/Makefile.in b/src/scepclient/Makefile.in
index 576a8fb17..c2814a4e6 100644
--- a/src/scepclient/Makefile.in
+++ b/src/scepclient/Makefile.in
@@ -35,10 +35,6 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
ipsec_PROGRAMS = scepclient$(EXEEXT)
-
-# This compile option activates smartcard support
-@USE_SMARTCARD_TRUE@am__append_1 = -DSMARTCARD
-@USE_SMARTCARD_TRUE@am__append_2 = $(DLLIB)
subdir = src/scepclient
DIST_COMMON = $(dist_man_MANS) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in
@@ -55,19 +51,16 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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__installdirs = "$(DESTDIR)$(ipsecdir)" "$(DESTDIR)$(man8dir)"
PROGRAMS = $(ipsec_PROGRAMS)
-am_scepclient_OBJECTS = scepclient.$(OBJEXT) scep.$(OBJEXT) \
- loglite.$(OBJEXT)
+am_scepclient_OBJECTS = scepclient.$(OBJEXT) scep.$(OBJEXT)
scepclient_OBJECTS = $(am_scepclient_OBJECTS)
-am__DEPENDENCIES_1 =
-@USE_SMARTCARD_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
-scepclient_DEPENDENCIES = constants.o defs.o lex.o pkcs7.o \
- $(LIBSTRONGSWANBUILDDIR)/libstrongswan.la \
- $(LIBFREESWANBUILDDIR)/libfreeswan.a $(am__DEPENDENCIES_2)
-DEFAULT_INCLUDES = -I.@am__isrc@
+scepclient_DEPENDENCIES = \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -117,6 +110,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -211,11 +205,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -232,11 +229,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -252,6 +250,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -261,7 +260,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -289,30 +287,20 @@ top_srcdir = @top_srcdir@
urandom_device = @urandom_device@
xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
-scepclient_SOURCES = scepclient.c scep.c scep.h loglite.c
-PLUTODIR = $(top_srcdir)/src/pluto
-OPENACDIR = $(top_srcdir)/src/openac
-WHACKDIR = $(top_srcdir)/src/whack
-LIBFREESWANDIR = $(top_srcdir)/src/libfreeswan
-LIBSTRONGSWANDIR = $(top_srcdir)/src/libstrongswan
-LIBHYDRADIR = $(top_srcdir)/src/libhydra
-LIBCRYPTODIR = $(top_srcdir)/src/libcrypto
+scepclient_SOURCES = \
+scepclient.c scep.c scep.h
+
INCLUDES = \
--I$(LIBFREESWANDIR) \
--I$(LIBSTRONGSWANDIR) \
--I$(LIBHYDRADIR) \
--I$(PLUTODIR) \
--I$(LIBCRYPTODIR) \
--I$(WHACKDIR)
-
-AM_CFLAGS = -DIPSEC_CONFDIR=\"${sysconfdir}\" \
- -DPLUGINS=\""${scepclient_plugins}\"" -DDEBUG -DNO_PLUTO \
- $(am__append_1)
-LIBSTRONGSWANBUILDDIR = $(top_builddir)/src/libstrongswan
-LIBFREESWANBUILDDIR = $(top_builddir)/src/libfreeswan
-scepclient_LDADD = constants.o defs.o lex.o pkcs7.o \
- $(LIBSTRONGSWANBUILDDIR)/libstrongswan.la \
- $(LIBFREESWANBUILDDIR)/libfreeswan.a $(am__append_2)
+-I$(top_srcdir)/src/libstrongswan \
+-I$(top_srcdir)/src/libhydra
+
+AM_CFLAGS = \
+-DIPSEC_CONFDIR=\"${sysconfdir}\" \
+-DPLUGINS=\""${scepclient_plugins}\""
+
+scepclient_LDADD = \
+$(top_builddir)/src/libstrongswan/libstrongswan.la
+
dist_man_MANS = scepclient.8
all: all-am
@@ -401,7 +389,6 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loglite.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scep.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scepclient.Po@am__quote@
@@ -690,18 +677,6 @@ uninstall-man: uninstall-man8
scepclient.o : $(top_builddir)/config.status
-constants.o : $(PLUTODIR)/constants.c $(PLUTODIR)/constants.h
- $(COMPILE) $(INCLUDES) -c -o $@ $<
-
-defs.o : $(PLUTODIR)/defs.c $(PLUTODIR)/defs.h
- $(COMPILE) $(INCLUDES) -c -o $@ $<
-
-lex.o : $(PLUTODIR)/lex.c $(PLUTODIR)/lex.h
- $(COMPILE) $(INCLUDES) -c -o $@ $<
-
-pkcs7.o : $(PLUTODIR)/pkcs7.c $(PLUTODIR)/pkcs7.h
- $(COMPILE) $(INCLUDES) -c -o $@ $<
-
# 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/scepclient/loglite.c b/src/scepclient/loglite.c
deleted file mode 100644
index 96dc54390..000000000
--- a/src/scepclient/loglite.c
+++ /dev/null
@@ -1,350 +0,0 @@
-/* error logging functions
- * Copyright (C) 1997 Angelos D. Keromytis.
- * Copyright (C) 1998-2001 D. Hugh Redelmeier.
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <stdarg.h>
-#include <syslog.h>
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-#include <signal.h> /* used only if MSG_NOSIGNAL not defined */
-#include <libgen.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <freeswan.h>
-#include <debug.h>
-
-#include <constants.h>
-#include <defs.h>
-#include <log.h>
-#include <whack.h>
-
-bool
- log_to_stderr = FALSE, /* should log go to stderr? */
- log_to_syslog = TRUE; /* should log go to syslog? */
-
-/**
- * @brief scepclient dbg function
- */
-static void scepclient_dbg(debug_t group, level_t level, char *fmt, ...)
-{
- int priority = LOG_INFO;
- int debug_level;
- char buffer[8192];
- char *current = buffer, *next;
- va_list args;
-
- if (cur_debugging & DBG_PRIVATE)
- {
- debug_level = 4;
- }
- else if (cur_debugging & DBG_RAW)
- {
- debug_level = 3;
- }
- else if (cur_debugging & DBG_PARSING)
- {
- debug_level = 2;
- }
- else
- {
- debug_level = 1;
- }
-
- if (level <= debug_level)
- {
- if (log_to_stderr)
- {
- if (level > 1)
- {
- fprintf(stderr, "| ");
- }
- va_start(args, fmt);
- vfprintf(stderr, fmt, args);
- va_end(args);
- fprintf(stderr, "\n");
- }
- if (log_to_syslog)
- {
- /* write in memory buffer first */
- va_start(args, fmt);
- vsnprintf(buffer, sizeof(buffer), fmt, args);
- va_end(args);
-
- /* do a syslog with every line */
- while (current)
- {
- next = strchr(current, '\n');
- if (next)
- {
- *(next++) = '\0';
- }
- syslog(priority, "%s%s\n", (level > 1)? "| ":"", current);
- current = next;
- }
- }
- }
-}
-
-void init_log(const char *program)
-{
- /* enable scepclient bugging hook */
- dbg = scepclient_dbg;
-
- if (log_to_stderr)
- {
- setbuf(stderr, NULL);
- }
- if (log_to_syslog)
- {
- openlog(program, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_AUTHPRIV);
- }
-}
-
-void close_log(void)
-{
- if (log_to_syslog)
- closelog();
-}
-
-void plog(const char *message, ...)
-{
- va_list args;
- char m[LOG_WIDTH]; /* longer messages will be truncated */
-
- va_start(args, message);
- vsnprintf(m, sizeof(m), message, args);
- va_end(args);
-
- if (log_to_stderr)
- fprintf(stderr, "%s\n", m);
- if (log_to_syslog)
- syslog(LOG_WARNING, "%s", m);
-}
-
-void loglog(int mess_no, const char *message, ...)
-{
- va_list args;
- char m[LOG_WIDTH]; /* longer messages will be truncated */
-
- va_start(args, message);
- vsnprintf(m, sizeof(m), message, args);
- va_end(args);
-
- if (log_to_stderr)
- fprintf(stderr, "%s\n", m);
- if (log_to_syslog)
- syslog(LOG_WARNING, "%s", m);
-}
-
-void log_errno_routine(int e, const char *message, ...)
-{
- va_list args;
- char m[LOG_WIDTH]; /* longer messages will be truncated */
-
- va_start(args, message);
- vsnprintf(m, sizeof(m), message, args);
- va_end(args);
-
- if (log_to_stderr)
- fprintf(stderr, "ERROR: %s. Errno %d: %s\n", m, e, strerror(e));
- if (log_to_syslog)
- syslog(LOG_ERR, "ERROR: %s. Errno %d: %s", m, e, strerror(e));
-}
-
-void exit_log(const char *message, ...)
-{
- va_list args;
- char m[LOG_WIDTH]; /* longer messages will be truncated */
-
- va_start(args, message);
- vsnprintf(m, sizeof(m), message, args);
- va_end(args);
-
- if (log_to_stderr)
- fprintf(stderr, "FATAL ERROR: %s\n", m);
- if (log_to_syslog)
- syslog(LOG_ERR, "FATAL ERROR: %s", m);
- exit(1);
-}
-
-void exit_log_errno_routine(int e, const char *message, ...)
-{
- va_list args;
- char m[LOG_WIDTH]; /* longer messages will be truncated */
-
- va_start(args, message);
- vsnprintf(m, sizeof(m), message, args);
- va_end(args);
-
- if (log_to_stderr)
- fprintf(stderr, "FATAL ERROR: %s. Errno %d: %s\n", m, e, strerror(e));
- if (log_to_syslog)
- syslog(LOG_ERR, "FATAL ERROR: %s. Errno %d: %s", m, e, strerror(e));
- exit(1);
-}
-
-void whack_log(int mess_no, const char *message, ...)
-{
- va_list args;
- char m[LOG_WIDTH]; /* longer messages will be truncated */
-
- va_start(args, message);
- vsnprintf(m, sizeof(m), message, args);
- va_end(args);
-
- fprintf(stderr, "%s\n", m);
-}
-
-/* Build up a diagnostic in a static buffer.
- * Although this would be a generally useful function, it is very
- * hard to come up with a discipline that prevents different uses
- * from interfering. It is intended that by limiting it to building
- * diagnostics, we will avoid this problem.
- * Juggling is performed to allow an argument to be a previous
- * result: the new string may safely depend on the old one. This
- * restriction is not checked in any way: violators will produce
- * confusing results (without crashing!).
- */
-char diag_space[sizeof(diag_space)];
-
-err_t builddiag(const char *fmt, ...)
-{
- static char diag_space[LOG_WIDTH]; /* longer messages will be truncated */
- char t[sizeof(diag_space)]; /* build result here first */
- va_list args;
-
- va_start(args, fmt);
- t[0] = '\0'; /* in case nothing terminates string */
- vsnprintf(t, sizeof(t), fmt, args);
- va_end(args);
- strcpy(diag_space, t);
- return diag_space;
-}
-
-/* Debugging message support */
-
-#ifdef DEBUG
-
-void switch_fail(int n, const char *file_str, unsigned long line_no)
-{
- char buf[30];
-
- snprintf(buf, sizeof(buf), "case %d unexpected", n);
- passert_fail(buf, file_str, line_no);
-}
-
-void passert_fail(const char *pred_str, const char *file_str, unsigned long line_no)
-{
- /* we will get a possibly unplanned prefix. Hope it works */
- loglog(RC_LOG_SERIOUS, "ASSERTION FAILED at %s:%lu: %s", file_str, line_no, pred_str);
- abort(); /* exiting correctly doesn't always work */
-}
-
-lset_t
- base_debugging = DBG_NONE, /* default to reporting nothing */
- cur_debugging = DBG_NONE;
-
-void pexpect_log(const char *pred_str, const char *file_str, unsigned long line_no)
-{
- /* we will get a possibly unplanned prefix. Hope it works */
- loglog(RC_LOG_SERIOUS, "EXPECTATION FAILED at %s:%lu: %s", file_str, line_no, pred_str);
-}
-
-/* log a debugging message (prefixed by "| ") */
-
-void DBG_log(const char *message, ...)
-{
- va_list args;
- char m[LOG_WIDTH]; /* longer messages will be truncated */
-
- va_start(args, message);
- vsnprintf(m, sizeof(m), message, args);
- va_end(args);
-
- if (log_to_stderr)
- fprintf(stderr, "| %s\n", m);
- if (log_to_syslog)
- syslog(LOG_DEBUG, "| %s", m);
-}
-
-/* dump raw bytes in hex to stderr (for lack of any better destination) */
-
-void DBG_dump(const char *label, const void *p, size_t len)
-{
-# define DUMP_LABEL_WIDTH 20 /* arbitrary modest boundary */
-# define DUMP_WIDTH (4 * (1 + 4 * 3) + 1)
- char buf[DUMP_LABEL_WIDTH + DUMP_WIDTH];
- char *bp;
- const unsigned char *cp = p;
-
- bp = buf;
-
- if (label != NULL && label[0] != '\0')
- {
- /* Handle the label. Care must be taken to avoid buffer overrun. */
- size_t llen = strlen(label);
-
- if (llen + 1 > sizeof(buf))
- {
- DBG_log("%s", label);
- }
- else
- {
- strcpy(buf, label);
- if (buf[llen-1] == '\n')
- {
- buf[llen-1] = '\0'; /* get rid of newline */
- DBG_log("%s", buf);
- }
- else if (llen < DUMP_LABEL_WIDTH)
- {
- bp = buf + llen;
- }
- else
- {
- DBG_log("%s", buf);
- }
- }
- }
-
- do {
- int i, j;
-
- for (i = 0; len!=0 && i!=4; i++)
- {
- *bp++ = ' ';
- for (j = 0; len!=0 && j!=4; len--, j++)
- {
- static const char hexdig[] = "0123456789abcdef";
-
- *bp++ = ' ';
- *bp++ = hexdig[(*cp >> 4) & 0xF];
- *bp++ = hexdig[*cp & 0xF];
- cp++;
- }
- }
- *bp = '\0';
- DBG_log("%s", buf);
- bp = buf;
- } while (len != 0);
-# undef DUMP_LABEL_WIDTH
-# undef DUMP_WIDTH
-}
-
-#endif /* DEBUG */
diff --git a/src/scepclient/scep.c b/src/scepclient/scep.c
index 29f6eab70..8b2fd179a 100644
--- a/src/scepclient/scep.c
+++ b/src/scepclient/scep.c
@@ -1,11 +1,5 @@
-/**
- * @file scep.c
- * @brief SCEP specific functions
- *
- * Contains functions to build SCEP request's and to parse SCEP reply's.
- */
-
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -23,32 +17,17 @@
#include <string.h>
#include <stdlib.h>
-#include <freeswan.h>
-
#include <library.h>
+#include <debug.h>
#include <asn1/asn1.h>
#include <asn1/asn1_parser.h>
#include <asn1/oid.h>
+#include <crypto/pkcs9.h>
#include <crypto/rngs/rng.h>
#include <crypto/hashers/hasher.h>
-#include "../pluto/constants.h"
-#include "../pluto/defs.h"
-#include "../pluto/fetch.h"
-#include "../pluto/log.h"
-
#include "scep.h"
-static const chunk_t ASN1_messageType_oid = chunk_from_chars(
- 0x06, 0x0A, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, 0x09, 0x02
-);
-static const chunk_t ASN1_senderNonce_oid = chunk_from_chars(
- 0x06, 0x0A, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, 0x09, 0x05
-);
-static const chunk_t ASN1_transId_oid = chunk_from_chars(
- 0x06, 0x0A, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, 0x09, 0x07
-);
-
static const char *pkiStatus_values[] = { "0", "2", "3" };
static const char *pkiStatus_names[] = {
@@ -86,170 +65,60 @@ const scep_attributes_t empty_scep_attributes = {
{ NULL, 0 } , /* recipientNonce */
};
-/* ASN.1 definition of the X.501 atttribute type */
-
-static const asn1Object_t attributesObjects[] = {
- { 0, "attributes", ASN1_SET, ASN1_LOOP }, /* 0 */
- { 1, "attribute", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */
- { 2, "type", ASN1_OID, ASN1_BODY }, /* 2 */
- { 2, "values", ASN1_SET, ASN1_LOOP }, /* 3 */
- { 3, "value", ASN1_EOC, ASN1_RAW }, /* 4 */
- { 2, "end loop", ASN1_EOC, ASN1_END }, /* 5 */
- { 0, "end loop", ASN1_EOC, ASN1_END }, /* 6 */
- { 0, "exit", ASN1_EOC, ASN1_EXIT }
-};
-#define ATTRIBUTE_OBJ_TYPE 2
-#define ATTRIBUTE_OBJ_VALUE 4
-
/**
- * Extract and store an attribute
+ * Extract X.501 attributes
*/
-static bool extract_attribute(int oid, chunk_t object, u_int level,
- scep_attributes_t *attrs)
+void extract_attributes(pkcs7_t *pkcs7, scep_attributes_t *attrs)
{
- asn1_t type = ASN1_EOC;
- const char *name = "none";
+ pkcs9_t *attributes = pkcs7->get_attributes(pkcs7);
+ chunk_t attr;
- switch (oid)
+ attr = attributes->get_attribute(attributes, OID_PKI_MESSAGE_TYPE);
+ if (attr.ptr)
{
- case OID_PKCS9_CONTENT_TYPE:
- type = ASN1_OID;
- name = "contentType";
- break;
- case OID_PKCS9_SIGNING_TIME:
- type = ASN1_UTCTIME;
- name = "signingTime";
- break;
- case OID_PKCS9_MESSAGE_DIGEST:
- type = ASN1_OCTET_STRING;
- name = "messageDigest";
- break;
- case OID_PKI_MESSAGE_TYPE:
- type = ASN1_PRINTABLESTRING;
- name = "messageType";
- break;
- case OID_PKI_STATUS:
- type = ASN1_PRINTABLESTRING;
- name = "pkiStatus";
- break;
- case OID_PKI_FAIL_INFO:
- type = ASN1_PRINTABLESTRING;
- name = "failInfo";
- break;
- case OID_PKI_SENDER_NONCE:
- type = ASN1_OCTET_STRING;
- name = "senderNonce";
- break;
- case OID_PKI_RECIPIENT_NONCE:
- type = ASN1_OCTET_STRING;
- name = "recipientNonce";
- break;
- case OID_PKI_TRANS_ID:
- type = ASN1_PRINTABLESTRING;
- name = "transID";
- break;
- default:
- break;
- }
-
- if (type == ASN1_EOC)
- return TRUE;
-
- if (!asn1_parse_simple_object(&object, type, level+1, name))
- return FALSE;
+ scep_msg_t m;
- switch (oid)
- {
- case OID_PKCS9_CONTENT_TYPE:
- break;
- case OID_PKCS9_SIGNING_TIME:
- break;
- case OID_PKCS9_MESSAGE_DIGEST:
- break;
- case OID_PKI_MESSAGE_TYPE:
+ for (m = SCEP_CertRep_MSG; m < SCEP_Unknown_MSG; m++)
{
- scep_msg_t m;
-
- for (m = SCEP_CertRep_MSG; m < SCEP_Unknown_MSG; m++)
+ if (strncmp(msgType_values[m], attr.ptr, attr.len) == 0)
{
- if (strncmp(msgType_values[m], object.ptr, object.len) == 0)
- attrs->msgType = m;
+ attrs->msgType = m;
}
- DBG(DBG_CONTROL,
- DBG_log("messageType: %s", msgType_names[attrs->msgType])
- )
}
- break;
- case OID_PKI_STATUS:
- {
- pkiStatus_t s;
+ DBG2(DBG_APP, "messageType: %s", msgType_names[attrs->msgType]);
+ }
+ attr = attributes->get_attribute(attributes, OID_PKI_STATUS);
+ if (attr.ptr)
+ {
+ pkiStatus_t s;
- for (s = SCEP_SUCCESS; s < SCEP_UNKNOWN; s++)
+ for (s = SCEP_SUCCESS; s < SCEP_UNKNOWN; s++)
+ {
+ if (strncmp(pkiStatus_values[s], attr.ptr, attr.len) == 0)
{
- if (strncmp(pkiStatus_values[s], object.ptr, object.len) == 0)
- attrs->pkiStatus = s;
+ attrs->pkiStatus = s;
}
- DBG(DBG_CONTROL,
- DBG_log("pkiStatus: %s", pkiStatus_names[attrs->pkiStatus])
- )
}
- break;
- case OID_PKI_FAIL_INFO:
- if (object.len == 1
- && *object.ptr >= '0' && *object.ptr <= '4')
+ DBG2(DBG_APP, "pkiStatus: %s", pkiStatus_names[attrs->pkiStatus]);
+ }
+ attr = attributes->get_attribute(attributes, OID_PKI_FAIL_INFO);
+ if (attr.ptr)
+ {
+ if (attr.len == 1 && *attr.ptr >= '0' && *attr.ptr <= '4')
{
- attrs->failInfo = (failInfo_t)(*object.ptr - '0');
+ attrs->failInfo = (failInfo_t)(*attr.ptr - '0');
}
if (attrs->failInfo != SCEP_unknown_REASON)
- plog("failInfo: %s", failInfo_reasons[attrs->failInfo]);
- break;
- case OID_PKI_SENDER_NONCE:
- attrs->senderNonce = object;
- break;
- case OID_PKI_RECIPIENT_NONCE:
- attrs->recipientNonce = object;
- break;
- case OID_PKI_TRANS_ID:
- attrs->transID = object;
- }
- return TRUE;
-}
-
-/**
- * Parse X.501 attributes
- */
-bool parse_attributes(chunk_t blob, scep_attributes_t *attrs)
-{
- asn1_parser_t *parser;
- chunk_t object;
- int oid = OID_UNKNOWN;
- int objectID;
- bool success = FALSE;
-
- parser = asn1_parser_create(attributesObjects, blob);
- DBG(DBG_CONTROL | DBG_PARSING,
- DBG_log("parsing attributes")
- )
-
- while (parser->iterate(parser, &objectID, &object))
- {
- switch (objectID)
{
- case ATTRIBUTE_OBJ_TYPE:
- oid = asn1_known_oid(object);
- break;
- case ATTRIBUTE_OBJ_VALUE:
- if (!extract_attribute(oid, object, parser->get_level(parser), attrs))
- {
- goto end;
- }
+ DBG1(DBG_APP, "failInfo: %s", failInfo_reasons[attrs->failInfo]);
}
}
- success = parser->success(parser);
-
-end:
- parser->destroy(parser);
- return success;
+ attrs->senderNonce = attributes->get_attribute(attributes,
+ OID_PKI_SENDER_NONCE);
+ attrs->recipientNonce = attributes->get_attribute(attributes,
+ OID_PKI_RECIPIENT_NONCE);
+ attrs->transID = attributes->get_attribute(attributes,
+ OID_PKI_TRANS_ID);
}
/**
@@ -262,7 +131,11 @@ chunk_t scep_generate_pkcs10_fingerprint(chunk_t pkcs10)
hasher_t *hasher;
hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
- hasher->get_hash(hasher, pkcs10, digest.ptr);
+ if (!hasher || !hasher->get_hash(hasher, pkcs10, digest.ptr))
+ {
+ DESTROY_IF(hasher);
+ return chunk_empty;
+ }
hasher->destroy(hasher);
return chunk_to_hex(digest, NULL, FALSE);
@@ -288,8 +161,11 @@ void scep_generate_transaction_id(public_key_t *key, chunk_t *transID,
asn1_bitstring("m", keyEncoding));
hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
- hasher->get_hash(hasher, keyInfo, digest.ptr);
- hasher->destroy(hasher);
+ if (!hasher || !hasher->get_hash(hasher, keyInfo, digest.ptr))
+ {
+ memset(digest.ptr, 0, digest.len);
+ }
+ DESTROY_IF(hasher);
free(keyInfo.ptr);
/* is the most significant bit of the digest set? */
@@ -308,46 +184,13 @@ void scep_generate_transaction_id(public_key_t *key, chunk_t *transID,
memcpy(pos, digest.ptr, digest.len);
/* the transaction id is the serial number in hex format */
- transID->len = 2*digest.len;
- transID->ptr = malloc(transID->len + 1);
- datatot(digest.ptr, digest.len, 16, transID->ptr, transID->len + 1);
+ *transID = chunk_to_hex(digest, NULL, TRUE);
}
/**
- * Builds a transId attribute
+ * Adds a senderNonce attribute to the given pkcs9 attribute list
*/
-chunk_t scep_transId_attribute(chunk_t transID)
-{
- return asn1_wrap(ASN1_SEQUENCE, "cm"
- , ASN1_transId_oid
- , asn1_wrap(ASN1_SET, "m"
- , asn1_simple_object(ASN1_PRINTABLESTRING, transID)
- )
- );
-}
-
-/**
- * Builds a messageType attribute
- */
-chunk_t scep_messageType_attribute(scep_msg_t m)
-{
- chunk_t msgType = {
- (u_char*)msgType_values[m],
- strlen(msgType_values[m])
- };
-
- return asn1_wrap(ASN1_SEQUENCE, "cm"
- , ASN1_messageType_oid
- , asn1_wrap(ASN1_SET, "m"
- , asn1_simple_object(ASN1_PRINTABLESTRING, msgType)
- )
- );
-}
-
-/**
- * Builds a senderNonce attribute
- */
-chunk_t scep_senderNonce_attribute(void)
+static bool add_senderNonce_attribute(pkcs9_t *pkcs9)
{
const size_t nonce_len = 16;
u_char nonce_buf[nonce_len];
@@ -355,41 +198,58 @@ chunk_t scep_senderNonce_attribute(void)
rng_t *rng;
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
- rng->get_bytes(rng, nonce_len, nonce_buf);
+ if (!rng || !rng->get_bytes(rng, nonce_len, nonce_buf))
+ {
+ DESTROY_IF(rng);
+ return FALSE;
+ }
rng->destroy(rng);
- return asn1_wrap(ASN1_SEQUENCE, "cm"
- , ASN1_senderNonce_oid
- , asn1_wrap(ASN1_SET, "m"
- , asn1_simple_object(ASN1_OCTET_STRING, senderNonce)
- )
- );
+ pkcs9->set_attribute(pkcs9, OID_PKI_SENDER_NONCE, senderNonce);
+ return TRUE;
}
/**
* Builds a pkcs7 enveloped and signed scep request
*/
chunk_t scep_build_request(chunk_t data, chunk_t transID, scep_msg_t msg,
- certificate_t *enc_cert, int enc_alg,
- certificate_t *signer_cert, int digest_alg,
- private_key_t *private_key)
+ certificate_t *enc_cert, encryption_algorithm_t enc_alg,
+ size_t key_size, certificate_t *signer_cert,
+ hash_algorithm_t digest_alg, private_key_t *private_key)
{
- chunk_t envelopedData, attributes, request;
-
- envelopedData = pkcs7_build_envelopedData(data, enc_cert, enc_alg);
-
- attributes = asn1_wrap(ASN1_SET, "mmmmm"
- , pkcs7_contentType_attribute()
- , pkcs7_messageDigest_attribute(envelopedData
- , digest_alg)
- , scep_transId_attribute(transID)
- , scep_messageType_attribute(msg)
- , scep_senderNonce_attribute());
-
- request = pkcs7_build_signedData(envelopedData, attributes
- , signer_cert, digest_alg, private_key);
- free(envelopedData.ptr);
- free(attributes.ptr);
+ chunk_t request, msgType = {
+ (u_char*)msgType_values[msg],
+ strlen(msgType_values[msg]),
+ };
+ pkcs7_t *pkcs7;
+ pkcs9_t *pkcs9;
+
+ pkcs7 = pkcs7_create_from_data(data);
+ if (!pkcs7->build_envelopedData(pkcs7, enc_cert, enc_alg, key_size))
+ {
+ pkcs7->destroy(pkcs7);
+ return chunk_empty;
+ }
+
+ pkcs9 = pkcs9_create();
+ pkcs9->set_attribute(pkcs9, OID_PKI_TRANS_ID, transID);
+ pkcs9->set_attribute(pkcs9, OID_PKI_MESSAGE_TYPE, msgType);
+ if (!add_senderNonce_attribute(pkcs9))
+ {
+ pkcs9->destroy(pkcs9);
+ pkcs7->destroy(pkcs7);
+ return chunk_empty;
+ }
+
+ pkcs7->set_attributes(pkcs7, pkcs9);
+ pkcs7->set_certificate(pkcs7, signer_cert->get_ref(signer_cert));
+ if (!pkcs7->build_signedData(pkcs7, private_key, digest_alg))
+ {
+ pkcs7->destroy(pkcs7);
+ return chunk_empty;
+ }
+ request = pkcs7->get_contentInfo(pkcs7);
+ pkcs7->destroy(pkcs7);
return request;
}
@@ -406,11 +266,12 @@ static char* escape_http_request(chunk_t req)
int n = 0;
/* compute and allocate the size of the base64-encoded request */
- int len = 1 + 4*((req.len + 2)/3);
+ int len = 1 + 4 * ((req.len + 2) / 3);
char *encoded_req = malloc(len);
/* do the base64 conversion */
- len = datatot(req.ptr, req.len, 64, encoded_req, len);
+ chunk_t base64 = chunk_to_base64(req, encoded_req);
+ len = base64.len + 1;
/* compute newline characters to be inserted every 64 characters */
lines = (len - 2) / 64;
@@ -420,10 +281,12 @@ static char* escape_http_request(chunk_t req)
while (*p1 != '\0')
{
if (*p1++ == '+')
+ {
plus++;
+ }
}
- escaped_req = malloc(len + 3*(lines + plus));
+ escaped_req = malloc(len + 3 * (lines + plus));
/* escape special characters in the request */
p1 = encoded_req;
@@ -466,9 +329,7 @@ bool scep_http_request(const char *url, chunk_t pkcs7, scep_op_t op,
/* initialize response */
*response = chunk_empty;
- DBG(DBG_CONTROL,
- DBG_log("sending scep request to '%s'", url)
- )
+ DBG2(DBG_APP, "sending scep request to '%s'", url);
if (op == SCEP_PKI_OPERATION)
{
@@ -500,6 +361,7 @@ bool scep_http_request(const char *url, chunk_t pkcs7, scep_op_t op,
snprintf(complete_url, len, "%s?operation=%s", url, operation);
status = lib->fetcher->fetch(lib->fetcher, complete_url, response,
+ FETCH_HTTP_VERSION_1_0,
FETCH_REQUEST_DATA, pkcs7,
FETCH_REQUEST_TYPE, "",
FETCH_REQUEST_HEADER, "Expect:",
@@ -513,10 +375,11 @@ bool scep_http_request(const char *url, chunk_t pkcs7, scep_op_t op,
/* form complete url */
len = strlen(url) + 32 + strlen(operation) + 1;
complete_url = malloc(len);
- snprintf(complete_url, len, "%s?operation=%s&message=CAIdentifier"
- , url, operation);
+ snprintf(complete_url, len, "%s?operation=%s&message=CAIdentifier",
+ url, operation);
status = lib->fetcher->fetch(lib->fetcher, complete_url, response,
+ FETCH_HTTP_VERSION_1_0,
FETCH_END);
}
@@ -524,22 +387,23 @@ bool scep_http_request(const char *url, chunk_t pkcs7, scep_op_t op,
return (status == SUCCESS);
}
-err_t scep_parse_response(chunk_t response, chunk_t transID, contentInfo_t *data,
+err_t scep_parse_response(chunk_t response, chunk_t transID, pkcs7_t **data,
scep_attributes_t *attrs, certificate_t *signer_cert)
{
- chunk_t attributes;
+ pkcs7_t *pkcs7;
- if (!pkcs7_parse_signedData(response, data, NULL, &attributes, signer_cert))
+ pkcs7 = pkcs7_create_from_chunk(response, 0);
+ if (!pkcs7 || !pkcs7->parse_signedData(pkcs7, signer_cert))
{
+ DESTROY_IF(pkcs7);
return "error parsing the scep response";
}
- if (!parse_attributes(attributes, attrs))
- {
- return "error parsing the scep response attributes";
- }
+ extract_attributes(pkcs7, attrs);
if (!chunk_equals(transID, attrs->transID))
{
+ pkcs7->destroy(pkcs7);
return "transaction ID of scep response does not match";
}
+ *data = pkcs7;
return NULL;
}
diff --git a/src/scepclient/scep.h b/src/scepclient/scep.h
index f64c6b1cc..6227faba4 100644
--- a/src/scepclient/scep.h
+++ b/src/scepclient/scep.h
@@ -1,11 +1,5 @@
-/**
- * @file scep.h
- * @brief SCEP specific functions
- *
- * Contains functions to build and parse SCEP requests and replies
- */
-
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -23,11 +17,9 @@
#ifndef _SCEP_H
#define _SCEP_H
+#include <crypto/pkcs7.h>
#include <credentials/certificates/certificate.h>
-#include "../pluto/defs.h"
-#include "../pluto/pkcs7.h"
-
/* supported SCEP operation types */
typedef enum {
SCEP_PKI_OPERATION,
@@ -74,22 +66,22 @@ typedef struct {
extern const scep_attributes_t empty_scep_attributes;
-extern bool parse_attributes(chunk_t blob, scep_attributes_t *attrs);
-extern void scep_generate_transaction_id(public_key_t *key,
- chunk_t *transID,
- chunk_t *serialNumber);
-extern chunk_t scep_generate_pkcs10_fingerprint(chunk_t pkcs10);
-extern chunk_t scep_transId_attribute(chunk_t transaction_id);
-extern chunk_t scep_messageType_attribute(scep_msg_t m);
-extern chunk_t scep_senderNonce_attribute(void);
-extern chunk_t scep_build_request(chunk_t data, chunk_t transID, scep_msg_t msg,
- certificate_t *enc_cert, int enc_alg,
- certificate_t *signer_cert, int digest_alg,
- private_key_t *private_key);
-extern bool scep_http_request(const char *url, chunk_t pkcs7, scep_op_t op,
- bool http_get_request, chunk_t *response);
-extern err_t scep_parse_response(chunk_t response, chunk_t transID,
- contentInfo_t *data, scep_attributes_t *attrs,
- certificate_t *signer_cert);
+bool parse_attributes(chunk_t blob, scep_attributes_t *attrs);
+void scep_generate_transaction_id(public_key_t *key,
+ chunk_t *transID,
+ chunk_t *serialNumber);
+chunk_t scep_generate_pkcs10_fingerprint(chunk_t pkcs10);
+chunk_t scep_transId_attribute(chunk_t transaction_id);
+chunk_t scep_messageType_attribute(scep_msg_t m);
+chunk_t scep_senderNonce_attribute(void);
+chunk_t scep_build_request(chunk_t data, chunk_t transID, scep_msg_t msg,
+ certificate_t *enc_cert, encryption_algorithm_t enc_alg,
+ size_t key_size, certificate_t *signer_cert,
+ hash_algorithm_t digest_alg, private_key_t *private_key);
+bool scep_http_request(const char *url, chunk_t pkcs7, scep_op_t op,
+ bool http_get_request, chunk_t *response);
+err_t scep_parse_response(chunk_t response, chunk_t transID,
+ pkcs7_t **data, scep_attributes_t *attrs,
+ certificate_t *signer_cert);
#endif /* _SCEP_H */
diff --git a/src/scepclient/scepclient.8 b/src/scepclient/scepclient.8
index 72750e155..bf71bf85c 100644
--- a/src/scepclient/scepclient.8
+++ b/src/scepclient/scepclient.8
@@ -1,5 +1,5 @@
-.\"
-.TH "IPSEC_SCEPCLIENT" "8" "29 September 2005" "Jan Hutter, Martin Willi" ""
+.\"
+.TH "IPSEC_SCEPCLIENT" "8" "2012-05-11" "strongSwan" ""
.SH "NAME"
ipsec scepclient \- Client for the SCEP protocol
.SH "SYNOPSIS"
@@ -7,7 +7,7 @@ ipsec scepclient \- Client for the SCEP protocol
.sp
.B ipsec scepclient
.B \-\-help
-.br
+.br
.B ipsec scepclient
.B \-\-version
.SH "DESCRIPTION"
@@ -19,7 +19,7 @@ is designed to be used for certificate enrollment on machines using the OpenSour
.SH "FEATURES"
.BR scepclient
implements the following features of SCEP:
-.br
+.br
.IP "\-" 4
Automatic enrollment of client certificate using a preshared secret
.IP "\-" 4
@@ -31,7 +31,7 @@ Acquisition of CA certificate(s)
.B \-v, \-\-version
.RS 4
Display the version of ipsec scepclient.
-.PP
+.PP
.RE
.B \-h, \-\-help
.RS 4
@@ -43,17 +43,17 @@ Display usage of ipsec scepclient.
.RS 4
Full HTTP URL of the SCEP server to be used for certificate enrollment and CA certificate acquisition.
.RE
-.PP
+.PP
.B \-+, \-\-optionsfrom \fIfilename\fP
.RS 4
Reads additional options from \fIfilename\fP.
.RE
-.PP
+.PP
.B \-f, \-\-force
.RS 4
Overwrite existing output file[s].
.RE
-.PP
+.PP
.B \-q, \-\-quiet
.RS 4
Do not write log output to stderr.
@@ -62,7 +62,9 @@ Do not write log output to stderr.
.SS Options for CA Certificate Acquisition
.B \-o, \-\-out cacert[=\fIfilename\fP]
.RS 4
-Output file of acquired CA certificate. If more then one CA certificate is available, \fIfilename\fP is used as prefix for the resulting files.
+Output file of acquired CA certificate. If more then one CA certificate is
+available, \fIfilename\fP is used as prefix for the resulting files (refer to
+EXAMPLES below for details).
.br
The default \fIfilename\fP is $CONFDIR/ipsec.d/cacerts/caCert.der.
.RE
@@ -70,41 +72,50 @@ The default \fIfilename\fP is $CONFDIR/ipsec.d/cacerts/caCert.der.
.SS Options For Certificate Enrollment
.B \-i, \-\-in \fItype\fP[=\fIfilename\fP]
.RS 4
-Input file for certificate enrollment. This option can be specified multiple times to specify input files for every \fItype\fP.
-Input files can bei either DER or PEM encoded.
-.PP
+Input file for certificate enrollment. This option can be specified multiple times to specify input files for every \fItype\fP.
+Input files can be either DER or PEM encoded.
+.PP
Supported values for \fItype\fP:
.IP "\fBpkcs1\fP" 12
RSA private key in PKCS#1 file format. If no input of this type is specified, a RSA key gets generated.
.br
The default \fIfilename\fP is $CONFDIR/ipsec.d/private/myKey.der.
+.IP "\fBpkcs10\fP" 12
+PKCS#10 certificate request to be used in the SCEP request. If no input of this type is specified, a request is generated.
+.br
+The default \fIfilename\fP is $CONFDIR/ipsec.d/req/myReq.der.
.IP "\fBcacert\-enc\fP" 12
-CA certificate to encrypt the SCEP request. Has to be specified for certificate enrollment.
-.br
+CA certificate to encrypt the SCEP request. Has to be specified for certificate enrollment.
+.br
The default \fIfilename\fP is $CONFDIR/ipsec.d/cacerts/caCert.der.
.IP "\fBcacert\-sig\fP" 12
-CA certificate to check signature of SCEP reply. Has to be specified for certificate enrollment.
-.br
+CA certificate to check signature of SCEP reply. Has to be specified for certificate enrollment.
+.br
The default \fIfilename\fP is $CONFDIR/ipsec.d/cacerts/caCert.der.
+.IP "\fBcert-self\fP" 12
+Certificate to be used in the SCEP request. If it is not specified a
+self-signed certificate is generated automatically.
+.br
+The default \fIfilename\fP is $CONFDIR/ipsec.d/certs/selfCert.der.
.RE
-.PP
+.PP
.B \-k, \-\-keylength \fIbits\fP
.RS 4
sets the key length for RSA key generation. The default length for a generated rsa key is set to 2048 bit.
.RE
-.PP
+.PP
.B \-D, \-\-days \fIdays\fP
.RS 4
Validity of the self-signed X.509 certificate in days. The default is 1825 days (5 years).
.RE
-.PP
+.PP
.B \-S, \-\-startdate \fIYYMMDDHHMMSS\fPZ
.RS 4
-defines the \fBnotBefore\fP date when the X.509 certificate becomes valid.
+defines the \fBnotBefore\fP date when the X.509 certificate becomes valid.
The date has the format \fIYYMMDDHHMMSS\fP and must be specified in UTC (Zulu time).
If the \fB--startdate\fP option is not specified then the current date is taken as a default.
.RE
-.PP
+.PP
.B \-E, \-\-enddate \fIYYMMDDHHMMSS\fPZ
.RS 4
defines the \fBnotAfter\fP date when the X.509 certificate will expire.
@@ -118,12 +129,12 @@ adding the validity interval specified by the \fB--days\fP option to the \fBnotB
Distinguished name as comma separated list of relative distinguished names. Use quotation marks for a distinguished name containing spaces. If the \fB\-\-dn\fP parameter is missing then the default "C=CH, O=Linux strongSwan, CN=\fIhostname\fP"
is used with \fIhostname\fP being the return value of the \fIgethostname\fP() function.
.RE
-.PP
+.PP
.B \-s, \-\-subjectAltName \fItype\fP=\fIvalue\fP
.RS 4
Include subjectAltName in certificate request. This option can be specified multiple times to specify a subjectAltName
for every \fItype\fP.
-.PP
+.PP
Supported values for \fItype\fP:
.IP "\fBemail\fP" 12
subjectAltName is a email address.
@@ -132,25 +143,35 @@ subjectAltName is a hostname.
.IP "\fBip\fP" 12
subjectAltName is a IP address.
.RE
-.PP
+.PP
.B \-p, \-\-password \fIpw\fP
.RS 4
Password to be included as a \fIchallenge password\fP in SCEP request.
If \fIpw\fP is \fB%prompt\fP', the password gets prompted for on the command line.
.IP
\- In automatic mode, this password corresponds to the preshared secret for the given enrollment.
-.IP
+.IP
\- In manual mode, this password can be used to later revoke the corresponding certificate.
.RE
-.PP
-.B \-a, \-\-algorithm \fIalgo\fP
+.PP
+.B \-a, \-\-algorithm [\fItype\fP=]\fIalgo\fP
.RS 4
-Change symmetric algorithm to use for encryption of certificate Request.
-The default is \fB3des\-cbc\fP.
-.PP
-Supported values for \fIalgo\fP:
+Change the algorithms to be used when generating and transporting (PKCS#7)
+certificate requests (PKCS#10).
+.PP
+Supported values for \fItype\fP:
+.IP "\fBenc\fP" 12
+symmetric encryption algorithm in PKCS#7
+.IP "\fBdgst\fP" 12
+hash algorithm for message digest in PKCS#7
+.IP "\fBsig\fP" 12
+hash algorithm for the signature in PKCS#10
+.PP
+If \fItype\fP is not specified \fBenc\fP is assumed.
+.PP
+Supported values for \fIalgo\fP (\fBenc\fP):
.IP "\fBdes\fP" 12
-DES-CBC encryption (key size = 56 bit).
+DES-CBC encryption (key size = 56 bit). Default.
.IP "\fB3des\fP" 12
Triple DES-EDE-CBC encryption (key size = 168 bit).
.IP "\fBaes128\fP" 12
@@ -165,56 +186,60 @@ Camellia-CBC encryption (key size = 128 bit).
Camelllia-CBC encryption (key size = 192 bit).
.IP "\fBcamellia256\fP" 12
Camellia-CBC encryption (key size = 256 bit).
+.PP
+Supported values for \fIalgo\fP (\fBdgst\fP or \fBsig\fP):
+.PP
+\fBmd5\fP (default), \fBsha1\fP, \fBsha256\fP, \fBsha384\fP, \fBsha512\fP
.RE
-.PP
+.PP
.B \-o, \-\-out \fItype\fP[=\fIfilename\fP]
.RS 4
Output file for certificate enrollment. This option can be specified multiple times to specify output files for every \fItype\fP.
-.PP
+.PP
Supported values for \fItype\fP:
.IP "\fBpkcs1\fP" 12
RSA private key in PKCS#1 file format. If specified, the RSA key used for enrollment is stored in file \fIfilename\fP.
If none of the \fItypes\fP listed below are specified, \fBscepclient\fP will stop after outputting this file.
-.br
+.br
The default \fIfilename\fP is $CONFDIR/ipsec.d/private/myKey.der.
.IP "\fBpkcs10\fP" 12
PKCS#10 certificate request. If specified, the PKCS#10 request used or certificate enrollment is stored in file \fIfilename\fP.
-If none of the \fItypes\fP listed below are specified, \fBscepclient\fP will stop after outputting this file.
-.br
+If none of the \fItypes\fP listed below are specified, \fBscepclient\fP will stop after outputting this file.
+.br
The default \fIfilename\fP is $CONFDIR/ipsec.d/req/myReq.der.
.IP "\fBpkcs7\fP" 12
PKCS#7 SCEP request as it is sent using HTTP to the SCEP server. If specified, this SCEP request is stored in file \fIfilename\fP.
If none of \fItypes\fP listed below is not specified, \fBscepclient\fP will stop after outputting this file.
-.br
+.br
The default \fIfilename\fP is $CONFDIR/ipsec.d/req/pkcs7.der.
.IP "\fBcert-self\fP" 12
Self-signed certificate. If specified the self-signed certificate is stored in file \fIfilename\fP.
-.br
+.br
The default \fIfilename\fP is $CONFDIR/ipsec.d/certs/selfCert.der.
.IP "\fBcert\fP" 12
Enrolled certificate. This \fItype\fP must be specified for certificate enrollment.
The enrolled certificate is stored in file \fIfilename\fP.
-.br
+.br
The default \fIfilename\fP is set to $CONFDIR/ipsec.d/certs/myCert.der.
.RE
-.PP
+.PP
.B \-m, \-\-method \fImethod\fP
.RS 4
Change HTTP request method for certificate enrollment. Default is \fBget\fP.
-.PP
+.PP
Supported values for \fImethod\fP:
.IP "\fBpost\fP" 12
Certificate enrollment using HTTP POST. Must be supported by the given SCEP server.
.IP "\fBget\fP" 12
Certificate enrollment using HTTP GET.
.RE
-.PP
+.PP
.B \-t, \-\-interval \fIseconds\fP
.RS 4
Set interval time in seconds when polling in manual mode.
The default interval is set to 5 seconds.
.RE
-.PP
+.PP
.B \-x, \-\-maxpolltime \fIseconds\fP
.RS 4
Set max time in seconds to poll in manual mode.
@@ -222,64 +247,41 @@ The default max time is set to unlimited.
.RE
.SS Debugging Output Options:
-.B \-A, \-\-debug\-all
-.RS 4
-Log everything except private data.
-.RE
-.PP
-.B \-P, \-\-debug\-parsing
-.RS 4
-Log parsing relevant stuff.
-.RE
-.PP
-.B \-R, \-\-debug\-raw
+.B \-l, \-\-debug \fIlevel\fP
.RS 4
-Log raw hex dumps.
-.RE
-.PP
-.B \-C, \-\-debug\-control
-.RS 4
-Log information about control flow.
-.RE
-.PP
-.B \-M, \-\-debug\-controlmore
-.RS 4
-Log more detailed information about control flow.
-.RE
-.PP
-.B \-X, \-\-debug\-private
-.RS 4
-Log sensitive data (e.g. private keys).
+Changes the log level (-1..4, default: 1)
.RE
.SH "EXAMPLES"
.B ipsec scepclient \-\-out caCert \-\-url http://scepserver/cgi\-bin/pkiclient.exe \-f
.RS 4
Acquire CA certificate from SCEP server and store it in the default file $CONFDIR/ipsec.d/cacerts/caCert.der.
-If more then one CA certificate is returned, store them in files named caCert.der\-1', caCert.der\-2', etc.
-.br
-Existing files are overwritten.
+If more then one CA certificate is returned, store them in files named
+\'caCert\-1.der\', \'caCert\-2.der\', etc.
+If an RA certificate is returned, store it in a file named \'caCert\-ra.der\'.
+If more than one RA certificate is returned, store them in files named
+\'caCert\-ra\-1.der\', \'caCert\-ra\-2.der\', etc.
.RE
-.PP
+.PP
.B ipsec scepclient \-\-out pkcs1=joeKey.der \-k 1024
.RS 4
Generate RSA private key with key length of 1024 bit and store it in file joeKey.der.
.RE
-.PP
+.PP
.B ipsec scepclient \-\-in pkcs1=joeKey.der \-\-out pkcs10=joeReq.der \e
-.br
+.br
.B \-\-dn \*(rqC=AT, CN=John Doe\*(rq \-s email=john@doe.com \-p mypassword
.RS 4
Generate a PKCS#10 request and store it in file joeReq.der. Use the RSA private key joeKey.der
-created earlier to sign the PKCS#10\-Request. In addition to the distinguished name include a
+created earlier to sign the PKCS#10\-Request. In addition to the distinguished name include a
email\-subjectAltName and a challenge password in the request.
.RE
-.PP
+.PP
.B ipsec scepclient \-\-out pkcs1=joeKey.der \-\-out cert==joeCert.der \e
-.br
+.br
.B \-\-dn \*(rqC=CH, CN=John Doe\*(rq \-k 512 \-p 5xH2pnT7wq \e
-.br
+.br
.B \-\-url http://scep.hsr.ch/cgi\-bin/pkiclient.exe \e
-.br
+.br
.B \-\-in cacert\-enc=caCert.der \-\-in cacert\-sig=caCert.der
.RS 4
Generate a new RSA key for the request and store it in joeKey.der. Then enroll a certificate and store as joeCert.der.
@@ -292,9 +294,9 @@ caCert.der.
\fB\-\-optionsfrom\fP seems to have parsing problems reading option files containing strings in quotation marks.
.SH "COPYRIGHT"
Copyright (C) 2005 Jan Hutter, Martin Willi
-.br
+.br
Hochschule fuer Technik Rapperswil
-.PP
+.PP
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>.
-.PP
+.PP
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.
diff --git a/src/scepclient/scepclient.c b/src/scepclient/scepclient.c
index 0b54eeee3..78b0d7e7a 100644
--- a/src/scepclient/scepclient.c
+++ b/src/scepclient/scepclient.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -13,17 +14,6 @@
* for more details.
*/
-/**
- * @file main.c
- * @brief scepclient main program
- */
-
-/**
- * @mainpage SCEP for Linux strongSwan
- *
- * Documentation of SCEP for Linux StrongSwan
- */
-
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@@ -32,8 +22,8 @@
#include <ctype.h>
#include <unistd.h>
#include <time.h>
-
-#include <freeswan.h>
+#include <limits.h>
+#include <syslog.h>
#include <library.h>
#include <debug.h>
@@ -52,18 +42,18 @@
#include <credentials/certificates/pkcs10.h>
#include <plugins/plugin.h>
-#include "../pluto/constants.h"
-#include "../pluto/defs.h"
-#include "../pluto/log.h"
-#include "../pluto/certs.h"
-#include "../pluto/pkcs7.h"
-
#include "scep.h"
/*
* definition of some defaults
*/
+/* some paths */
+#define REQ_PATH IPSEC_CONFDIR "/ipsec.d/reqs"
+#define HOST_CERT_PATH IPSEC_CONFDIR "/ipsec.d/certs"
+#define CA_CERT_PATH IPSEC_CONFDIR "/ipsec.d/cacerts"
+#define PRIVATE_KEY_PATH IPSEC_CONFDIR "/ipsec.d/private"
+
/* default name of DER-encoded PKCS#1 private key file */
#define DEFAULT_FILENAME_PKCS1 "myKey.der"
@@ -100,6 +90,9 @@
/* default distinguished name */
#define DEFAULT_DN "C=CH, O=Linux strongSwan, CN="
+/* minimum RSA key size */
+#define RSA_MIN_OCTETS (512 / BITS_PER_BYTE)
+
/* challenge password buffer size */
#define MAX_PASSWORD_LENGTH 256
@@ -125,7 +118,6 @@ options_t *options;
/*
* Global variables
*/
-
chunk_t pkcs1;
chunk_t pkcs7;
chunk_t challengePassword;
@@ -148,13 +140,118 @@ certificate_t *x509_ca_enc = NULL;
certificate_t *x509_ca_sig = NULL;
certificate_t *pkcs10_req = NULL;
+/* logging */
+static bool log_to_stderr = TRUE;
+static bool log_to_syslog = TRUE;
+static level_t default_loglevel = 1;
+
+/**
+ * logging function for scepclient
+ */
+static void scepclient_dbg(debug_t group, level_t level, char *fmt, ...)
+{
+ char buffer[8192];
+ char *current = buffer, *next;
+ va_list args;
+
+ if (level <= default_loglevel)
+ {
+ if (log_to_stderr)
+ {
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ }
+ if (log_to_syslog)
+ {
+ /* write in memory buffer first */
+ va_start(args, fmt);
+ vsnprintf(buffer, sizeof(buffer), fmt, args);
+ va_end(args);
+
+ /* do a syslog with every line */
+ while (current)
+ {
+ next = strchr(current, '\n');
+ if (next)
+ {
+ *(next++) = '\0';
+ }
+ syslog(LOG_INFO, "%s\n", current);
+ current = next;
+ }
+ }
+ }
+}
+
+/**
+ * Initialize logging to stderr/syslog
+ */
+static void init_log(const char *program)
+{
+ dbg = scepclient_dbg;
+
+ if (log_to_stderr)
+ {
+ setbuf(stderr, NULL);
+ }
+ if (log_to_syslog)
+ {
+ openlog(program, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_AUTHPRIV);
+ }
+}
+
+/**
+ * join two paths if filename is not absolute
+ */
+static void join_paths(char *target, size_t target_size, char *parent,
+ char *filename)
+{
+ if (*filename == '/' || *filename == '.')
+ {
+ snprintf(target, target_size, "%s", filename);
+ }
+ else
+ {
+ snprintf(target, target_size, "%s/%s", parent, filename);
+ }
+}
+
+/**
+ * add a suffix to a given filename, properly handling extensions like '.der'
+ */
+static void add_path_suffix(char *target, size_t target_size, char *filename,
+ char *suffix_fmt, ...)
+{
+ char suffix[PATH_MAX], *start, *dot;
+ va_list args;
+
+ va_start(args, suffix_fmt);
+ vsnprintf(suffix, sizeof(suffix), suffix_fmt, args);
+ va_end(args);
+
+ start = strrchr(filename, '/');
+ start = start ?: filename;
+ dot = strrchr(start, '.');
+
+ if (!dot || dot == start || dot[1] == '\0')
+ { /* no extension add suffix at the end */
+ snprintf(target, target_size, "%s%s", filename, suffix);
+ }
+ else
+ { /* add the suffix between the filename and the extension */
+ snprintf(target, target_size, "%.*s%s%s", (int)(dot - filename),
+ filename, suffix, dot);
+ }
+}
+
/**
* @brief exit scepclient
*
* @param status 0 = OK, 1 = general discomfort
*/
-static void
-exit_scepclient(err_t message, ...)
+static void exit_scepclient(err_t message, ...)
{
int status = 0;
@@ -183,7 +280,7 @@ exit_scepclient(err_t message, ...)
if (message != NULL && *message != '\0')
{
va_list args;
- char m[LOG_WIDTH]; /* longer messages will be truncated */
+ char m[8192];
va_start(args, message);
vsnprintf(m, sizeof(m), message, args);
@@ -193,7 +290,6 @@ exit_scepclient(err_t message, ...)
status = -1;
}
library_deinit();
- close_log();
exit(status);
}
@@ -201,8 +297,7 @@ exit_scepclient(err_t message, ...)
* @brief prints the program version and exits
*
*/
-static void
-version(void)
+static void version(void)
{
printf("scepclient %s\n", scepclient_version);
exit_scepclient(NULL);
@@ -214,22 +309,27 @@ version(void)
* If message is set, program is exitet with 1 (error)
* @param message message in case of an error
*/
-static void
-usage(const char *message)
+static void usage(const char *message)
{
fprintf(stderr,
"Usage: scepclient\n"
" --help (-h) show usage and exit\n"
" --version (-v) show version and exit\n"
" --quiet (-q) do not write log output to stderr\n"
- " --in (-i) <type>[=<filename>] use <filename> of <type> for input \n"
- " <type> = pkcs1 | cacert-enc | cacert-sig\n"
- " - if no pkcs1 input is defined, a \n"
- " RSA key will be generated\n"
+ " --in (-i) <type>[=<filename>] use <filename> of <type> for input\n"
+ " <type> = pkcs1 | pkcs10 | cert-self\n"
+ " cacert-enc | cacert-sig\n"
+ " - if no pkcs1 input is defined, an RSA\n"
+ " key will be generated\n"
+ " - if no pkcs10 input is defined, a\n"
+ " PKCS#10 request will be generated\n"
+ " - if no cert-self input is defined, a\n"
+ " self-signed certificate will be generated\n"
" - if no filename is given, default is used\n"
" --out (-o) <type>[=<filename>] write output of <type> to <filename>\n"
" multiple outputs are allowed\n"
- " <type> = pkcs1 | pkcs10 | pkcs7 | cert-self | cert | cacert\n"
+ " <type> = pkcs1 | pkcs10 | pkcs7 | cert-self |\n"
+ " cert | cacert\n"
" - type cacert defines filename prefix of\n"
" received CA certificate(s)\n"
" - if no filename is given, default is used\n"
@@ -238,7 +338,7 @@ usage(const char *message)
"\n"
"Options for key generation (pkcs1):\n"
" --keylength (-k) <bits> key length for RSA key generation\n"
- "(default: 2048 bits)\n"
+ " (default: 2048 bits)\n"
"\n"
"Options for validity:\n"
" --days (-D) <days> validity in days\n"
@@ -250,27 +350,26 @@ usage(const char *message)
" --subjectAltName (-s) <t>=<v> include subjectAltName in certificate request\n"
" <t> = email | dns | ip \n"
" --password (-p) <pw> challenge password\n"
- " - if pw is '%%prompt', password gets prompted for\n"
- " --algorithm (-a) <algo> use specified algorithm for PKCS#7 encryption\n"
- " <algo> = des | 3des (default) | aes128| aes192 | \n"
- " aes256 | camellia128 | camellia192 | camellia256\n"
+ " - use '%%prompt' as pw for a password prompt\n"
+ " --algorithm (-a) [<type>=]<algo> algorithm to be used for PKCS#7 encryption,\n"
+ " PKCS#7 digest or PKCS#10 signature\n"
+ " <type> = enc | dgst | sig\n"
+ " - if no type is given enc is assumed\n"
+ " <algo> = des (default) | 3des | aes128 |\n"
+ " aes192 | aes256 | camellia128 |\n"
+ " camellia192 | camellia256\n"
+ " <algo> = md5 (default) | sha1 | sha256 |\n"
+ " sha384 | sha512\n"
"\n"
"Options for enrollment (cert):\n"
" --url (-u) <url> url of the SCEP server\n"
" --method (-m) post | get http request type\n"
- " --interval (-t) <seconds> manual mode poll interval in seconds (default 20s)\n"
+ " --interval (-t) <seconds> poll interval in seconds (default 20s)\n"
" --maxpolltime (-x) <seconds> max poll time in seconds when in manual mode\n"
" (default: unlimited)\n"
-#ifdef DEBUG
"\n"
"Debugging output:\n"
- " --debug-all (-A) show everything except private\n"
- " --debug-parsing (-P) show parsing relevant stuff\n"
- " --debug-raw (-R) show raw hex dumps\n"
- " --debug-control (-C) show control flow output\n"
- " --debug-controlmore (-M) show more control flow\n"
- " --debug-private (-X) show sensitive data (private keys, etc.)\n"
-#endif
+ " --debug (-l) <level> changes the log level (-1..4, default: 1)\n"
);
exit_scepclient(message);
}
@@ -295,7 +394,7 @@ int main(int argc, char **argv)
CERT_SELF = 0x08,
CERT = 0x10,
CACERT_ENC = 0x20,
- CACERT_SIG = 0x40
+ CACERT_SIG = 0x40,
} scep_filetype_t;
/* filetype to read from, defaults to "generate a key" */
@@ -306,6 +405,8 @@ int main(int argc, char **argv)
/* input files */
char *file_in_pkcs1 = DEFAULT_FILENAME_PKCS1;
+ char *file_in_pkcs10 = DEFAULT_FILENAME_PKCS10;
+ char *file_in_cert_self = DEFAULT_FILENAME_CERT_SELF;
char *file_in_cacert_enc = DEFAULT_FILENAME_CACERT_ENC;
char *file_in_cacert_sig = DEFAULT_FILENAME_CACERT_SIG;
@@ -337,14 +438,15 @@ int main(int argc, char **argv)
/* challenge password */
char challenge_password_buffer[MAX_PASSWORD_LENGTH];
- /* symmetric encryption algorithm used by pkcs7, default is 3DES */
- int pkcs7_symmetric_cipher = OID_3DES_EDE_CBC;
+ /* symmetric encryption algorithm used by pkcs7, default is DES */
+ encryption_algorithm_t pkcs7_symmetric_cipher = ENCR_DES;
+ size_t pkcs7_key_size = 0;
- /* digest algorithm used by pkcs7, default is SHA-1 */
- int pkcs7_digest_alg = OID_SHA1;
+ /* digest algorithm used by pkcs7, default is MD5 */
+ hash_algorithm_t pkcs7_digest_alg = HASH_MD5;
- /* signature algorithm used by pkcs10, default is SHA-1 */
- hash_algorithm_t pkcs10_signature_alg = HASH_SHA1;
+ /* signature algorithm used by pkcs10, default is MD5 */
+ hash_algorithm_t pkcs10_signature_alg = HASH_MD5;
/* URL of the SCEP-Server */
char *scep_url = NULL;
@@ -388,7 +490,6 @@ int main(int argc, char **argv)
scep_response = chunk_empty;
subjectAltNames = linked_list_create();
options = options_create();
- log_to_stderr = TRUE;
for (;;)
{
@@ -398,6 +499,7 @@ int main(int argc, char **argv)
{ "version", no_argument, NULL, 'v' },
{ "optionsfrom", required_argument, NULL, '+' },
{ "quiet", no_argument, NULL, 'q' },
+ { "debug", required_argument, NULL, 'l' },
{ "in", required_argument, NULL, 'i' },
{ "out", required_argument, NULL, 'o' },
{ "force", no_argument, NULL, 'f' },
@@ -413,14 +515,6 @@ int main(int argc, char **argv)
{ "method", required_argument, NULL, 'm' },
{ "interval", required_argument, NULL, 't' },
{ "maxpolltime", required_argument, NULL, 'x' },
-#ifdef DEBUG
- { "debug-all", no_argument, NULL, 'A' },
- { "debug-parsing", no_argument, NULL, 'P'},
- { "debug-raw", no_argument, NULL, 'R'},
- { "debug-control", no_argument, NULL, 'C'},
- { "debug-controlmore", no_argument, NULL, 'M'},
- { "debug-private", no_argument, NULL, 'X'},
-#endif
{ 0,0,0,0 }
};
@@ -429,20 +523,24 @@ int main(int argc, char **argv)
switch (c)
{
- case EOF: /* end of flags */
- break;
+ case EOF: /* end of flags */
+ break;
+
+ case 'h': /* --help */
+ usage(NULL);
- case 'h': /* --help */
- usage(NULL);
+ case 'v': /* --version */
+ version();
- case 'v': /* --version */
- version();
+ case 'q': /* --quiet */
+ log_to_stderr = FALSE;
+ continue;
- case 'q': /* --quiet */
- log_to_stderr = FALSE;
- continue;
+ case 'l': /* --debug <level> */
+ default_loglevel = atoi(optarg);
+ continue;
- case 'i': /* --in <type> [= <filename>] */
+ case 'i': /* --in <type> [= <filename>] */
{
char *filename = strstr(optarg, "=");
@@ -459,6 +557,12 @@ int main(int argc, char **argv)
if (filename)
file_in_pkcs1 = filename;
}
+ else if (strcaseeq("pkcs10", optarg))
+ {
+ filetype_in |= PKCS10;
+ if (filename)
+ file_in_pkcs10 = filename;
+ }
else if (strcaseeq("cacert-enc", optarg))
{
filetype_in |= CACERT_ENC;
@@ -469,7 +573,13 @@ int main(int argc, char **argv)
{
filetype_in |= CACERT_SIG;
if (filename)
- file_in_cacert_sig = filename;
+ file_in_cacert_sig = filename;
+ }
+ else if (strcaseeq("cert-self", optarg))
+ {
+ filetype_in |= CERT_SELF;
+ if (filename)
+ file_in_cert_self = filename;
}
else
{
@@ -478,7 +588,7 @@ int main(int argc, char **argv)
continue;
}
- case 'o': /* --out <type> [= <filename>] */
+ case 'o': /* --out <type> [= <filename>] */
{
char *filename = strstr(optarg, "=");
@@ -532,18 +642,18 @@ int main(int argc, char **argv)
continue;
}
- case 'f': /* --force */
- force = TRUE;
- continue;
+ case 'f': /* --force */
+ force = TRUE;
+ continue;
- case '+': /* --optionsfrom <filename> */
- if (!options->from(options, optarg, &argc, &argv, optind))
- {
- exit_scepclient("optionsfrom failed");
- }
- continue;
+ case '+': /* --optionsfrom <filename> */
+ if (!options->from(options, optarg, &argc, &argv, optind))
+ {
+ exit_scepclient("optionsfrom failed");
+ }
+ continue;
- case 'k': /* --keylength <length> */
+ case 'k': /* --keylength <length> */
{
div_t q;
@@ -561,45 +671,56 @@ int main(int argc, char **argv)
continue;
}
- case 'D': /* --days */
- if (optarg == NULL || !isdigit(optarg[0]))
- usage("missing number of days");
- {
- char *endptr;
- long days = strtol(optarg, &endptr, 0);
+ case 'D': /* --days */
+ if (optarg == NULL || !isdigit(optarg[0]))
+ {
+ usage("missing number of days");
+ }
+ else
+ {
+ char *endptr;
+ long days = strtol(optarg, &endptr, 0);
- if (*endptr != '\0' || endptr == optarg
- || days <= 0)
- usage("<days> must be a positive number");
- validity = 24*3600*days;
- }
- continue;
+ if (*endptr != '\0' || endptr == optarg
+ || days <= 0)
+ usage("<days> must be a positive number");
+ validity = 24*3600*days;
+ }
+ continue;
- case 'S': /* --startdate */
- if (optarg == NULL || strlen(optarg) != 13 || optarg[12] != 'Z')
- usage("date format must be YYMMDDHHMMSSZ");
- {
- chunk_t date = { optarg, 13 };
- notBefore = asn1_to_time(&date, ASN1_UTCTIME);
- }
- continue;
+ case 'S': /* --startdate */
+ if (optarg == NULL || strlen(optarg) != 13 || optarg[12] != 'Z')
+ {
+ usage("date format must be YYMMDDHHMMSSZ");
+ }
+ else
+ {
+ chunk_t date = { optarg, 13 };
+ notBefore = asn1_to_time(&date, ASN1_UTCTIME);
+ }
+ continue;
- case 'E': /* --enddate */
- if (optarg == NULL || strlen(optarg) != 13 || optarg[12] != 'Z')
- usage("date format must be YYMMDDHHMMSSZ");
- {
- chunk_t date = { optarg, 13 };
- notAfter = asn1_to_time(&date, ASN1_UTCTIME);
- }
- continue;
+ case 'E': /* --enddate */
+ if (optarg == NULL || strlen(optarg) != 13 || optarg[12] != 'Z')
+ {
+ usage("date format must be YYMMDDHHMMSSZ");
+ }
+ else
+ {
+ chunk_t date = { optarg, 13 };
+ notAfter = asn1_to_time(&date, ASN1_UTCTIME);
+ }
+ continue;
- case 'd': /* --dn */
- if (distinguishedName)
- usage("only one distinguished name allowed");
- distinguishedName = optarg;
- continue;
+ case 'd': /* --dn */
+ if (distinguishedName)
+ {
+ usage("only one distinguished name allowed");
+ }
+ distinguishedName = optarg;
+ continue;
- case 's': /* --subjectAltName */
+ case 's': /* --subjectAltName */
{
char *value = strstr(optarg, "=");
@@ -612,7 +733,7 @@ int main(int argc, char **argv)
}
if (strcaseeq("email", optarg) ||
- strcaseeq("dns", optarg) ||
+ strcaseeq("dns", optarg) ||
strcaseeq("ip", optarg))
{
subjectAltNames->insert_last(subjectAltNames,
@@ -626,111 +747,137 @@ int main(int argc, char **argv)
}
}
- case 'p': /* --password */
- if (challengePassword.len > 0)
- {
- usage("only one challenge password allowed");
- }
- if (strcaseeq("%prompt", optarg))
- {
- printf("Challenge password: ");
- if (fgets(challenge_password_buffer, sizeof(challenge_password_buffer)-1, stdin))
+ case 'p': /* --password */
+ if (challengePassword.len > 0)
+ {
+ usage("only one challenge password allowed");
+ }
+ if (strcaseeq("%prompt", optarg))
{
- challengePassword.ptr = challenge_password_buffer;
- /* discard the terminating '\n' from the input */
- challengePassword.len = strlen(challenge_password_buffer) - 1;
+ printf("Challenge password: ");
+ if (fgets(challenge_password_buffer,
+ sizeof(challenge_password_buffer) - 1, stdin))
+ {
+ challengePassword.ptr = challenge_password_buffer;
+ /* discard the terminating '\n' from the input */
+ challengePassword.len = strlen(challenge_password_buffer) - 1;
+ }
+ else
+ {
+ usage("challenge password could not be read");
+ }
}
else
{
- usage("challenge password could not be read");
+ challengePassword.ptr = optarg;
+ challengePassword.len = strlen(optarg);
}
- }
- else
- {
- challengePassword.ptr = optarg;
- challengePassword.len = strlen(optarg);
- }
- continue;
-
- case 'u': /* -- url */
- if (scep_url)
- {
- usage("only one URL argument allowed");
- }
- scep_url = optarg;
- continue;
+ continue;
- case 'm': /* --method */
- if (strcaseeq("get", optarg))
- {
- http_get_request = TRUE;
- }
- else if (strcaseeq("post", optarg))
- {
- http_get_request = FALSE;
- }
- else
- {
- usage("invalid http request method specified");
- }
- continue;
+ case 'u': /* -- url */
+ if (scep_url)
+ {
+ usage("only one URL argument allowed");
+ }
+ scep_url = optarg;
+ continue;
- case 't': /* --interval */
- poll_interval = atoi(optarg);
- if (poll_interval <= 0)
- {
- usage("invalid interval specified");
- }
- continue;
+ case 'm': /* --method */
+ if (strcaseeq("get", optarg))
+ {
+ http_get_request = TRUE;
+ }
+ else if (strcaseeq("post", optarg))
+ {
+ http_get_request = FALSE;
+ }
+ else
+ {
+ usage("invalid http request method specified");
+ }
+ continue;
- case 'x': /* --maxpolltime */
- max_poll_time = atoi(optarg);
- continue;
+ case 't': /* --interval */
+ poll_interval = atoi(optarg);
+ if (poll_interval <= 0)
+ {
+ usage("invalid interval specified");
+ }
+ continue;
- case 'a': /*--algorithm */
- {
- const proposal_token_t *token;
+ case 'x': /* --maxpolltime */
+ max_poll_time = atoi(optarg);
+ continue;
- token = proposal_get_token(optarg, strlen(optarg));
- if (token == NULL || token->type != ENCRYPTION_ALGORITHM)
+ case 'a': /*--algorithm [<type>=]algo */
{
- usage("invalid algorithm specified");
- }
- pkcs7_symmetric_cipher = encryption_algorithm_to_oid(
- token->algorithm, token->keysize);
- if (pkcs7_symmetric_cipher == OID_UNKNOWN)
- {
- usage("unsupported encryption algorithm specified");
+ const proposal_token_t *token;
+ char *type = optarg;
+ char *algo = strstr(optarg, "=");
+
+ if (algo)
+ {
+ *algo = '\0';
+ algo++;
+ }
+ else
+ {
+ type = "enc";
+ algo = optarg;
+ }
+
+ if (strcaseeq("enc", type))
+ {
+ token = lib->proposal->get_token(lib->proposal, algo);
+ if (token == NULL || token->type != ENCRYPTION_ALGORITHM)
+ {
+ usage("invalid algorithm specified");
+ }
+ pkcs7_symmetric_cipher = token->algorithm;
+ pkcs7_key_size = token->keysize;
+ if (encryption_algorithm_to_oid(token->algorithm,
+ token->keysize) == OID_UNKNOWN)
+ {
+ usage("unsupported encryption algorithm specified");
+ }
+ }
+ else if (strcaseeq("dgst", type) ||
+ strcaseeq("sig", type))
+ {
+ hash_algorithm_t hash;
+
+ token = lib->proposal->get_token(lib->proposal, algo);
+ if (token == NULL || token->type != INTEGRITY_ALGORITHM)
+ {
+ usage("invalid algorithm specified");
+ }
+ hash = hasher_algorithm_from_integrity(token->algorithm,
+ NULL);
+ if (hash == OID_UNKNOWN)
+ {
+ usage("invalid algorithm specified");
+ }
+ if (strcaseeq("dgst", type))
+ {
+ pkcs7_digest_alg = hash;
+ }
+ else
+ {
+ pkcs10_signature_alg = hash;
+ }
+ }
+ else
+ {
+ usage("invalid --algorithm type");
+ }
+ continue;
}
- continue;
- }
-#ifdef DEBUG
- case 'A': /* --debug-all */
- base_debugging |= DBG_ALL;
- continue;
- case 'P': /* debug parsing */
- base_debugging |= DBG_PARSING;
- continue;
- case 'R': /* debug raw */
- base_debugging |= DBG_RAW;
- continue;
- case 'C': /* debug control */
- base_debugging |= DBG_CONTROL;
- continue;
- case 'M': /* debug control more */
- base_debugging |= DBG_CONTROLMORE;
- continue;
- case 'X': /* debug private */
- base_debugging |= DBG_PRIVATE;
- continue;
-#endif
- default:
- usage("unknown option");
+ default:
+ usage("unknown option");
}
/* break from loop */
break;
}
- cur_debugging = base_debugging;
init_log("scepclient");
@@ -740,12 +887,12 @@ int main(int argc, char **argv)
{
exit_scepclient("plugin loading failed");
}
- DBG1(DBG_LIB, " loaded plugins: %s",
+ DBG1(DBG_APP, " loaded plugins: %s",
lib->plugins->loaded_plugins(lib->plugins));
if ((filetype_out == 0) && (!request_ca_certificate))
{
- usage ("--out filetype required");
+ usage("--out filetype required");
}
if (request_ca_certificate && (filetype_out > 0 || filetype_in > 0))
{
@@ -767,7 +914,8 @@ int main(int argc, char **argv)
/* get CA cert */
if (request_ca_certificate)
{
- char *path = concatenate_paths(CA_CERT_PATH, file_out_ca_cert);
+ char ca_path[PATH_MAX];
+ pkcs7_t *pkcs7;
if (!scep_http_request(scep_url, chunk_empty, SCEP_GET_CA_CERT,
http_get_request, &scep_response))
@@ -775,9 +923,77 @@ int main(int argc, char **argv)
exit_scepclient("did not receive a valid scep response");
}
- if (!chunk_write(scep_response, path, "ca cert", 0022, force))
+ join_paths(ca_path, sizeof(ca_path), CA_CERT_PATH, file_out_ca_cert);
+
+ pkcs7 = pkcs7_create_from_chunk(scep_response, 0);
+ if (!pkcs7 || !pkcs7->parse_signedData(pkcs7, NULL))
+ { /* no PKCS#7 encoded CA+RA certificates, assume simple CA cert */
+ DESTROY_IF(pkcs7);
+ if (!chunk_write(scep_response, ca_path, "ca cert", 0022, force))
+ {
+ exit_scepclient("could not write ca cert file '%s'", ca_path);
+ }
+ }
+ else
{
- exit_scepclient("could not write ca cert file '%s'", path);
+ enumerator_t *enumerator;
+ certificate_t *cert;
+ int ra_certs = 0, ca_certs = 0;
+ int ra_index = 1, ca_index = 1;
+
+ enumerator = pkcs7->create_certificate_enumerator(pkcs7);
+ while (enumerator->enumerate(enumerator, &cert))
+ {
+ x509_t *x509 = (x509_t*)cert;
+ if (x509->get_flags(x509) & X509_CA)
+ {
+ ca_certs++;
+ }
+ else
+ {
+ ra_certs++;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ enumerator = pkcs7->create_certificate_enumerator(pkcs7);
+ while (enumerator->enumerate(enumerator, &cert))
+ {
+ x509_t *x509 = (x509_t*)cert;
+ bool ca_cert = x509->get_flags(x509) & X509_CA;
+ char cert_path[PATH_MAX], *path = ca_path;
+
+ if (ca_cert && ca_certs > 1)
+ {
+ add_path_suffix(cert_path, sizeof(cert_path), ca_path,
+ "-%.1d", ca_index++);
+ path = cert_path;
+ }
+ else if (!ca_cert)
+ { /* use CA name as base for RA certs */
+ if (ra_certs > 1)
+ {
+ add_path_suffix(cert_path, sizeof(cert_path), ca_path,
+ "-ra-%.1d", ra_index++);
+ }
+ else
+ {
+ add_path_suffix(cert_path, sizeof(cert_path), ca_path,
+ "-ra");
+ }
+ path = cert_path;
+ }
+
+ if (!cert->get_encoding(cert, CERT_ASN1_DER, &encoding) ||
+ !chunk_write(encoding, path,
+ ca_cert ? "ca cert" : "ra cert", 0022, force))
+ {
+ exit_scepclient("could not write cert file '%s'", path);
+ }
+ chunk_free(&encoding);
+ }
+ enumerator->destroy(enumerator);
+ pkcs7->destroy(pkcs7);
}
exit_scepclient(NULL); /* no further output required */
}
@@ -787,7 +1003,9 @@ int main(int argc, char **argv)
*/
if (filetype_in & PKCS1) /* load an RSA key pair from file */
{
- char *path = concatenate_paths(PRIVATE_KEY_PATH, file_in_pkcs1);
+ char path[PATH_MAX];
+
+ join_paths(path, sizeof(path), PRIVATE_KEY_PATH, file_in_pkcs1);
private_key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
BUILD_FROM_FILE, path, BUILD_END);
@@ -807,8 +1025,8 @@ int main(int argc, char **argv)
/* check for minimum key length */
if (private_key->get_keysize(private_key) < RSA_MIN_OCTETS / BITS_PER_BYTE)
{
- exit_scepclient("length of RSA key has to be at least %d bits"
- ,RSA_MIN_OCTETS * BITS_PER_BYTE);
+ exit_scepclient("length of RSA key has to be at least %d bits",
+ RSA_MIN_OCTETS * BITS_PER_BYTE);
}
/*
@@ -816,13 +1034,19 @@ int main(int argc, char **argv)
*/
if (filetype_in & PKCS10)
{
- /* user wants to load a pkcs10 request
- * operation is not yet supported
- * would require a PKCS#10 parsing function
+ char path[PATH_MAX];
- pkcs10 = pkcs10_read_from_file(file_in_pkcs10);
+ join_paths(path, sizeof(path), REQ_PATH, file_in_pkcs10);
- */
+ pkcs10_req = lib->creds->create(lib->creds, CRED_CERTIFICATE,
+ CERT_PKCS10_REQUEST, BUILD_FROM_FILE,
+ path, BUILD_END);
+ if (!pkcs10_req)
+ {
+ exit_scepclient("could not read certificate request '%s'", path);
+ }
+ subject = pkcs10_req->get_subject(pkcs10_req);
+ subject = subject->clone(subject);
}
else
{
@@ -840,41 +1064,39 @@ int main(int argc, char **argv)
distinguishedName = buf;
}
- DBG(DBG_CONTROL,
- DBG_log("dn: '%s'", distinguishedName);
- )
+ DBG2(DBG_APP, "dn: '%s'", distinguishedName);
subject = identification_create_from_string(distinguishedName);
if (subject->get_type(subject) != ID_DER_ASN1_DN)
{
exit_scepclient("parsing of distinguished name failed");
}
- DBG(DBG_CONTROL,
- DBG_log("building pkcs10 object:")
- )
+ DBG2(DBG_APP, "building pkcs10 object:");
pkcs10_req = lib->creds->create(lib->creds, CRED_CERTIFICATE,
- CERT_PKCS10_REQUEST,
- BUILD_SIGNING_KEY, private_key,
- BUILD_SUBJECT, subject,
- BUILD_SUBJECT_ALTNAMES, subjectAltNames,
- BUILD_CHALLENGE_PWD, challengePassword,
- BUILD_DIGEST_ALG, pkcs10_signature_alg,
- BUILD_END);
+ CERT_PKCS10_REQUEST,
+ BUILD_SIGNING_KEY, private_key,
+ BUILD_SUBJECT, subject,
+ BUILD_SUBJECT_ALTNAMES, subjectAltNames,
+ BUILD_CHALLENGE_PWD, challengePassword,
+ BUILD_DIGEST_ALG, pkcs10_signature_alg,
+ BUILD_END);
if (!pkcs10_req)
{
exit_scepclient("generating pkcs10 request failed");
}
- pkcs10_req->get_encoding(pkcs10_req, CERT_ASN1_DER, &pkcs10_encoding);
- fingerprint = scep_generate_pkcs10_fingerprint(pkcs10_encoding);
- plog(" fingerprint: %s", fingerprint.ptr);
}
+ pkcs10_req->get_encoding(pkcs10_req, CERT_ASN1_DER, &pkcs10_encoding);
+ fingerprint = scep_generate_pkcs10_fingerprint(pkcs10_encoding);
+ DBG1(DBG_APP, " fingerprint: %s", fingerprint.ptr);
/*
* output of PKCS#10 file
*/
if (filetype_out & PKCS10)
{
- char *path = concatenate_paths(REQ_PATH, file_out_pkcs10);
+ char path[PATH_MAX];
+
+ join_paths(path, sizeof(path), REQ_PATH, file_out_pkcs10);
if (!chunk_write(pkcs10_encoding, path, "pkcs10", 0022, force))
{
@@ -893,11 +1115,11 @@ int main(int argc, char **argv)
*/
if (filetype_out & PKCS1)
{
- char *path = concatenate_paths(PRIVATE_KEY_PATH, file_out_pkcs1);
+ char path[PATH_MAX];
+
+ join_paths(path, sizeof(path), PRIVATE_KEY_PATH, file_out_pkcs1);
- DBG(DBG_CONTROL,
- DBG_log("building pkcs1 object:")
- )
+ DBG2(DBG_APP, "building pkcs1 object:");
if (!private_key->get_encoding(private_key, PRIVKEY_ASN1_DER, &pkcs1) ||
!chunk_write(pkcs1, path, "pkcs1", 0066, force))
{
@@ -912,24 +1134,41 @@ int main(int argc, char **argv)
}
scep_generate_transaction_id(public_key, &transID, &serialNumber);
- plog(" transaction ID: %.*s", (int)transID.len, transID.ptr);
-
- notBefore = notBefore ? notBefore : time(NULL);
- notAfter = notAfter ? notAfter : (notBefore + validity);
-
- /* generate a self-signed X.509 certificate */
- x509_signer = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
- BUILD_SIGNING_KEY, private_key,
- BUILD_PUBLIC_KEY, public_key,
- BUILD_SUBJECT, subject,
- BUILD_NOT_BEFORE_TIME, notBefore,
- BUILD_NOT_AFTER_TIME, notAfter,
- BUILD_SERIAL, serialNumber,
- BUILD_SUBJECT_ALTNAMES, subjectAltNames,
- BUILD_END);
- if (!x509_signer)
+ DBG1(DBG_APP, " transaction ID: %.*s", (int)transID.len, transID.ptr);
+
+ /*
+ * read or generate self-signed X.509 certificate
+ */
+ if (filetype_in & CERT_SELF)
+ {
+ char path[PATH_MAX];
+
+ join_paths(path, sizeof(path), HOST_CERT_PATH, file_in_cert_self);
+
+ x509_signer = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_FROM_FILE, path, BUILD_END);
+ if (!x509_signer)
+ {
+ exit_scepclient("could not read certificate file '%s'", path);
+ }
+ }
+ else
{
- exit_scepclient("generating certificate failed");
+ notBefore = notBefore ? notBefore : time(NULL);
+ notAfter = notAfter ? notAfter : (notBefore + validity);
+ x509_signer = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_SIGNING_KEY, private_key,
+ BUILD_PUBLIC_KEY, public_key,
+ BUILD_SUBJECT, subject,
+ BUILD_NOT_BEFORE_TIME, notBefore,
+ BUILD_NOT_AFTER_TIME, notAfter,
+ BUILD_SERIAL, serialNumber,
+ BUILD_SUBJECT_ALTNAMES, subjectAltNames,
+ BUILD_END);
+ if (!x509_signer)
+ {
+ exit_scepclient("generating certificate failed");
+ }
}
/*
@@ -937,7 +1176,9 @@ int main(int argc, char **argv)
*/
if (filetype_out & CERT_SELF)
{
- char *path = concatenate_paths(HOST_CERT_PATH, file_out_cert_self);
+ char path[PATH_MAX];
+
+ join_paths(path, sizeof(path), HOST_CERT_PATH, file_out_cert_self);
if (!x509_signer->get_encoding(x509_signer, CERT_ASN1_DER, &encoding))
{
@@ -960,7 +1201,9 @@ int main(int argc, char **argv)
* load ca encryption certificate
*/
{
- char *path = concatenate_paths(CA_CERT_PATH, file_in_cacert_enc);
+ char path[PATH_MAX];
+
+ join_paths(path, sizeof(path), CA_CERT_PATH, file_in_cacert_enc);
x509_ca_enc = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
BUILD_FROM_FILE, path, BUILD_END);
@@ -985,13 +1228,15 @@ int main(int argc, char **argv)
}
else
{
- DBG(DBG_CONTROL,
- DBG_log("building pkcs7 request")
- )
+ DBG2(DBG_APP, "building pkcs7 request");
pkcs7 = scep_build_request(pkcs10_encoding,
- transID, SCEP_PKCSReq_MSG,
- x509_ca_enc, pkcs7_symmetric_cipher,
- x509_signer, pkcs7_digest_alg, private_key);
+ transID, SCEP_PKCSReq_MSG, x509_ca_enc,
+ pkcs7_symmetric_cipher, pkcs7_key_size,
+ x509_signer, pkcs7_digest_alg, private_key);
+ if (!pkcs7.ptr)
+ {
+ exit_scepclient("failed to build pkcs7 request");
+ }
}
/*
@@ -999,11 +1244,14 @@ int main(int argc, char **argv)
*/
if (filetype_out & PKCS7)
{
- char *path = concatenate_paths(REQ_PATH, file_out_pkcs7);
+ char path[PATH_MAX];
+
+ join_paths(path, sizeof(path), REQ_PATH, file_out_pkcs7);
if (!chunk_write(pkcs7, path, "pkcs7 encrypted request", 0022, force))
+ {
exit_scepclient("could not write pkcs7 file '%s'", path);
-;
+ }
filetype_out &= ~PKCS7; /* delete PKCS7 flag */
}
@@ -1020,14 +1268,12 @@ int main(int argc, char **argv)
bool stored = FALSE;
certificate_t *cert;
enumerator_t *enumerator;
- char *path = concatenate_paths(CA_CERT_PATH, file_in_cacert_sig);
+ char path[PATH_MAX];
time_t poll_start = 0;
+ pkcs7_t *data = NULL;
+ scep_attributes_t attrs = empty_scep_attributes;
- linked_list_t *certs = linked_list_create();
- chunk_t envelopedData = chunk_empty;
- chunk_t certData = chunk_empty;
- contentInfo_t data = empty_contentInfo;
- scep_attributes_t attrs = empty_scep_attributes;
+ join_paths(path, sizeof(path), CA_CERT_PATH, file_in_cacert_sig);
x509_ca_sig = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
BUILD_FROM_FILE, path, BUILD_END);
@@ -1037,12 +1283,12 @@ int main(int argc, char **argv)
}
if (!scep_http_request(scep_url, pkcs7, SCEP_PKI_OPERATION,
- http_get_request, &scep_response))
+ http_get_request, &scep_response))
{
exit_scepclient("did not receive a valid scep response");
}
- ugh = scep_parse_response(scep_response, transID, &data, &attrs
- , x509_ca_sig);
+ ugh = scep_parse_response(scep_response, transID, &data, &attrs,
+ x509_ca_sig);
if (ugh != NULL)
{
exit_scepclient(ugh);
@@ -1053,8 +1299,8 @@ int main(int argc, char **argv)
{
identification_t *issuer = x509_ca_sig->get_subject(x509_ca_sig);
- plog(" scep request pending, polling every %d seconds"
- , poll_interval);
+ DBG1(DBG_APP, " scep request pending, polling every %d seconds",
+ poll_interval);
poll_start = time_monotonic(NULL);
issuerAndSubject = asn1_wrap(ASN1_SEQUENCE, "cc",
issuer->get_encoding(issuer),
@@ -1062,36 +1308,38 @@ int main(int argc, char **argv)
}
while (attrs.pkiStatus == SCEP_PENDING)
{
- if (max_poll_time > 0
- && (time_monotonic(NULL) - poll_start >= max_poll_time))
+ if (max_poll_time > 0 &&
+ (time_monotonic(NULL) - poll_start >= max_poll_time))
{
exit_scepclient("maximum poll time reached: %d seconds"
, max_poll_time);
}
- DBG(DBG_CONTROL,
- DBG_log("going to sleep for %d seconds", poll_interval)
- )
+ DBG2(DBG_APP, "going to sleep for %d seconds", poll_interval);
sleep(poll_interval);
free(scep_response.ptr);
+ data->destroy(data);
- DBG(DBG_CONTROL,
- DBG_log("fingerprint: %.*s", (int)fingerprint.len, fingerprint.ptr);
- DBG_log("transaction ID: %.*s", (int)transID.len, transID.ptr)
- )
+ DBG2(DBG_APP, "fingerprint: %.*s",
+ (int)fingerprint.len, fingerprint.ptr);
+ DBG2(DBG_APP, "transaction ID: %.*s",
+ (int)transID.len, transID.ptr);
chunk_free(&getCertInitial);
- getCertInitial = scep_build_request(issuerAndSubject
- , transID, SCEP_GetCertInitial_MSG
- , x509_ca_enc, pkcs7_symmetric_cipher
- , x509_signer, pkcs7_digest_alg, private_key);
-
+ getCertInitial = scep_build_request(issuerAndSubject,
+ transID, SCEP_GetCertInitial_MSG, x509_ca_enc,
+ pkcs7_symmetric_cipher, pkcs7_key_size,
+ x509_signer, pkcs7_digest_alg, private_key);
+ if (!getCertInitial.ptr)
+ {
+ exit_scepclient("failed to build scep request");
+ }
if (!scep_http_request(scep_url, getCertInitial, SCEP_PKI_OPERATION,
http_get_request, &scep_response))
{
exit_scepclient("did not receive a valid scep response");
}
- ugh = scep_parse_response(scep_response, transID, &data, &attrs
- , x509_ca_sig);
+ ugh = scep_parse_response(scep_response, transID, &data, &attrs,
+ x509_ca_sig);
if (ugh != NULL)
{
exit_scepclient(ugh);
@@ -1100,31 +1348,25 @@ int main(int argc, char **argv)
if (attrs.pkiStatus != SCEP_SUCCESS)
{
+ data->destroy(data);
exit_scepclient("reply status is not 'SUCCESS'");
}
- envelopedData = data.content;
-
- if (data.type != OID_PKCS7_DATA
- || !asn1_parse_simple_object(&envelopedData, ASN1_OCTET_STRING, 0, "data"))
- {
- exit_scepclient("contentInfo is not of type 'data'");
- }
- if (!pkcs7_parse_envelopedData(envelopedData, &certData
- , serialNumber, private_key))
+ if (!data->parse_envelopedData(data, serialNumber, private_key))
{
+ data->destroy(data);
exit_scepclient("could not decrypt envelopedData");
}
- if (!pkcs7_parse_signedData(certData, NULL, certs, NULL, NULL))
+ if (!data->parse_signedData(data, NULL))
{
+ data->destroy(data);
exit_scepclient("error parsing the scep response");
}
- chunk_free(&certData);
/* store the end entity certificate */
- path = concatenate_paths(HOST_CERT_PATH, file_out_cert);
+ join_paths(path, sizeof(path), HOST_CERT_PATH, file_out_cert);
- enumerator = certs->create_enumerator(certs);
+ enumerator = data->create_certificate_enumerator(data);
while (enumerator->enumerate(enumerator, &cert))
{
x509_t *x509 = (x509_t*)cert;
@@ -1144,7 +1386,8 @@ int main(int argc, char **argv)
stored = TRUE;
}
}
- certs->destroy_offset(certs, offsetof(certificate_t, destroy));
+ enumerator->destroy(enumerator);
+ data->destroy(data);
filetype_out &= ~CERT; /* delete CERT flag */
}
diff --git a/src/starter/Android.mk b/src/starter/Android.mk
index a82fe9385..c7e81d284 100644
--- a/src/starter/Android.mk
+++ b/src/starter/Android.mk
@@ -4,30 +4,22 @@ include $(CLEAR_VARS)
# copy-n-paste from Makefile.am (update for LEX/YACC)
LOCAL_SRC_FILES := \
parser.c lexer.c ipsec-parser.h netkey.c args.h netkey.h \
-starterwhack.c starterwhack.h starterstroke.c invokepluto.c confread.c \
-starterstroke.h interfaces.c invokepluto.h confread.h interfaces.h args.c \
-keywords.c files.h keywords.h cmp.c starter.c cmp.h exec.c invokecharon.c \
-exec.h invokecharon.h loglite.c klips.c klips.h
+starterstroke.c confread.c \
+starterstroke.h confread.h args.c \
+keywords.c files.h keywords.h cmp.c starter.c cmp.h invokecharon.c \
+invokecharon.h klips.c klips.h
# build starter ----------------------------------------------------------------
LOCAL_C_INCLUDES += \
$(libvstr_PATH) \
$(strongswan_PATH)/src/libhydra \
- $(strongswan_PATH)/src/libfreeswan \
$(strongswan_PATH)/src/libstrongswan \
- $(strongswan_PATH)/src/libfreeswan \
- $(strongswan_PATH)/src/pluto \
- $(strongswan_PATH)/src/whack \
$(strongswan_PATH)/src/stroke
LOCAL_CFLAGS := $(strongswan_CFLAGS) -DSTART_CHARON \
-DPLUGINS='"$(strongswan_STARTER_PLUGINS)"'
-ifneq ($(strongswan_BUILD_PLUTO),)
-LOCAL_CFLAGS += -DSTART_PLUTO
-endif
-
LOCAL_MODULE := starter
LOCAL_MODULE_TAGS := optional
@@ -37,11 +29,8 @@ LOCAL_ARM_MODE := arm
LOCAL_PRELINK_MODULE := false
LOCAL_REQUIRED_MODULES := stroke
-ifneq ($(strongswan_BUILD_PLUTO),)
-LOCAL_REQUIRED_MODULES += whack
-endif
-LOCAL_SHARED_LIBRARIES += libstrongswan libhydra libfreeswan
+LOCAL_SHARED_LIBRARIES += libstrongswan libhydra
include $(BUILD_EXECUTABLE)
diff --git a/src/starter/Makefile.am b/src/starter/Makefile.am
index 94ddf5aba..c220c2e63 100644
--- a/src/starter/Makefile.am
+++ b/src/starter/Makefile.am
@@ -1,18 +1,15 @@
ipsec_PROGRAMS = starter
starter_SOURCES = \
parser.y lexer.l ipsec-parser.h netkey.c args.h netkey.h \
-starterwhack.c starterwhack.h starterstroke.c invokepluto.c confread.c \
-starterstroke.h interfaces.c invokepluto.h confread.h interfaces.h args.c \
-keywords.c files.h keywords.h cmp.c starter.c cmp.h exec.c invokecharon.c \
-exec.h invokecharon.h loglite.c klips.c klips.h
+starterstroke.c confread.c \
+starterstroke.h confread.h args.c \
+keywords.c files.h keywords.h cmp.c starter.c cmp.h invokecharon.c \
+invokecharon.h klips.c klips.h
INCLUDES = \
-I${linux_headers} \
-I$(top_srcdir)/src/libstrongswan \
--I$(top_srcdir)/src/libfreeswan \
-I$(top_srcdir)/src/libhydra \
--I$(top_srcdir)/src/pluto \
--I$(top_srcdir)/src/whack \
-I$(top_srcdir)/src/stroke
AM_CFLAGS = \
@@ -27,18 +24,11 @@ AM_CFLAGS = \
AM_YFLAGS = -v -d
-starter_LDADD = defs.o $(top_builddir)/src/libfreeswan/libfreeswan.a $(top_builddir)/src/libstrongswan/libstrongswan.la $(top_builddir)/src/libhydra/libhydra.la $(SOCKLIB)
+starter_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la $(top_builddir)/src/libhydra/libhydra.la $(SOCKLIB) $(PTHREADLIB)
EXTRA_DIST = keywords.txt ipsec.conf Android.mk
MAINTAINERCLEANFILES = keywords.c
BUILT_SOURCES = parser.h
-PLUTODIR=$(top_srcdir)/src/pluto
-SCEPCLIENTDIR=$(top_srcdir)/src/scepclient
-
-if USE_PLUTO
- AM_CFLAGS += -DSTART_PLUTO
-endif
-
if USE_CHARON
AM_CFLAGS += -DSTART_CHARON
endif
@@ -54,11 +44,8 @@ endif
keywords.c: $(srcdir)/keywords.txt $(srcdir)/keywords.h
$(GPERF) -m 10 -C -G -D -t < $(srcdir)/keywords.txt > $@
-defs.o: $(PLUTODIR)/defs.c $(PLUTODIR)/defs.h
- $(COMPILE) -c -o $@ $(PLUTODIR)/defs.c
-
install-exec-local :
- test -e "$(DESTDIR)${sysconfdir}/ipsec.d" || $(INSTALL) -o -d "$(DESTDIR)$(sysconfdir)/ipsec.d" || true
+ test -e "$(DESTDIR)${sysconfdir}/ipsec.d" || $(INSTALL) -d "$(DESTDIR)$(sysconfdir)/ipsec.d" || true
test -e "$(DESTDIR)${sysconfdir}/ipsec.d/cacerts" || $(INSTALL) -d "$(DESTDIR)$(sysconfdir)/ipsec.d/cacerts" || true
test -e "$(DESTDIR)${sysconfdir}/ipsec.d/ocspcerts" || $(INSTALL) -d "$(DESTDIR)$(sysconfdir)/ipsec.d/ocspcerts" || true
test -e "$(DESTDIR)${sysconfdir}/ipsec.d/certs" || $(INSTALL) -d "$(DESTDIR)$(sysconfdir)/ipsec.d/certs" || true
diff --git a/src/starter/Makefile.in b/src/starter/Makefile.in
index f2c0cc38e..a6d55c5e2 100644
--- a/src/starter/Makefile.in
+++ b/src/starter/Makefile.in
@@ -35,10 +35,9 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
ipsec_PROGRAMS = starter$(EXEEXT)
-@USE_PLUTO_TRUE@am__append_1 = -DSTART_PLUTO
-@USE_CHARON_TRUE@am__append_2 = -DSTART_CHARON
-@USE_LOAD_WARNING_TRUE@am__append_3 = -DLOAD_WARNING
-@USE_TOOLS_TRUE@am__append_4 = -DGENERATE_SELFCERT
+@USE_CHARON_TRUE@am__append_1 = -DSTART_CHARON
+@USE_LOAD_WARNING_TRUE@am__append_2 = -DLOAD_WARNING
+@USE_TOOLS_TRUE@am__append_3 = -DGENERATE_SELFCERT
subdir = src/starter
DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
lexer.c parser.c parser.h
@@ -55,23 +54,22 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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__installdirs = "$(DESTDIR)$(ipsecdir)"
PROGRAMS = $(ipsec_PROGRAMS)
am_starter_OBJECTS = parser.$(OBJEXT) lexer.$(OBJEXT) netkey.$(OBJEXT) \
- starterwhack.$(OBJEXT) starterstroke.$(OBJEXT) \
- invokepluto.$(OBJEXT) confread.$(OBJEXT) interfaces.$(OBJEXT) \
- args.$(OBJEXT) keywords.$(OBJEXT) cmp.$(OBJEXT) \
- starter.$(OBJEXT) exec.$(OBJEXT) invokecharon.$(OBJEXT) \
- loglite.$(OBJEXT) klips.$(OBJEXT)
+ starterstroke.$(OBJEXT) confread.$(OBJEXT) args.$(OBJEXT) \
+ keywords.$(OBJEXT) cmp.$(OBJEXT) starter.$(OBJEXT) \
+ invokecharon.$(OBJEXT) klips.$(OBJEXT)
starter_OBJECTS = $(am_starter_OBJECTS)
am__DEPENDENCIES_1 =
-starter_DEPENDENCIES = defs.o \
- $(top_builddir)/src/libfreeswan/libfreeswan.a \
+starter_DEPENDENCIES = \
$(top_builddir)/src/libstrongswan/libstrongswan.la \
- $(top_builddir)/src/libhydra/libhydra.la $(am__DEPENDENCIES_1)
-DEFAULT_INCLUDES = -I.@am__isrc@
+ $(top_builddir)/src/libhydra/libhydra.la $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -104,6 +102,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -198,11 +197,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -219,11 +221,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -239,6 +242,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -248,7 +252,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -278,18 +281,15 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
starter_SOURCES = \
parser.y lexer.l ipsec-parser.h netkey.c args.h netkey.h \
-starterwhack.c starterwhack.h starterstroke.c invokepluto.c confread.c \
-starterstroke.h interfaces.c invokepluto.h confread.h interfaces.h args.c \
-keywords.c files.h keywords.h cmp.c starter.c cmp.h exec.c invokecharon.c \
-exec.h invokecharon.h loglite.c klips.c klips.h
+starterstroke.c confread.c \
+starterstroke.h confread.h args.c \
+keywords.c files.h keywords.h cmp.c starter.c cmp.h invokecharon.c \
+invokecharon.h klips.c klips.h
INCLUDES = \
-I${linux_headers} \
-I$(top_srcdir)/src/libstrongswan \
--I$(top_srcdir)/src/libfreeswan \
-I$(top_srcdir)/src/libhydra \
--I$(top_srcdir)/src/pluto \
--I$(top_srcdir)/src/whack \
-I$(top_srcdir)/src/stroke
AM_CFLAGS = -DIPSEC_DIR=\"${ipsecdir}\" \
@@ -297,14 +297,12 @@ AM_CFLAGS = -DIPSEC_DIR=\"${ipsecdir}\" \
-DIPSEC_EAPDIR=\"${eapdir}\" -DDEV_RANDOM=\"${random_device}\" \
-DDEV_URANDOM=\"${urandom_device}\" \
-DPLUGINS=\""${starter_plugins}\"" -DDEBUG $(am__append_1) \
- $(am__append_2) $(am__append_3) $(am__append_4)
+ $(am__append_2) $(am__append_3)
AM_YFLAGS = -v -d
-starter_LDADD = defs.o $(top_builddir)/src/libfreeswan/libfreeswan.a $(top_builddir)/src/libstrongswan/libstrongswan.la $(top_builddir)/src/libhydra/libhydra.la $(SOCKLIB)
+starter_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la $(top_builddir)/src/libhydra/libhydra.la $(SOCKLIB) $(PTHREADLIB)
EXTRA_DIST = keywords.txt ipsec.conf Android.mk
MAINTAINERCLEANFILES = keywords.c
BUILT_SOURCES = parser.h
-PLUTODIR = $(top_srcdir)/src/pluto
-SCEPCLIENTDIR = $(top_srcdir)/src/scepclient
all: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) all-am
@@ -401,19 +399,14 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/args.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmp.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/confread.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exec.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/interfaces.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/invokecharon.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/invokepluto.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keywords.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/klips.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lexer.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loglite.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netkey.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/starter.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/starterstroke.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/starterwhack.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@@ -660,11 +653,8 @@ uninstall-am: uninstall-ipsecPROGRAMS
keywords.c: $(srcdir)/keywords.txt $(srcdir)/keywords.h
$(GPERF) -m 10 -C -G -D -t < $(srcdir)/keywords.txt > $@
-defs.o: $(PLUTODIR)/defs.c $(PLUTODIR)/defs.h
- $(COMPILE) -c -o $@ $(PLUTODIR)/defs.c
-
install-exec-local :
- test -e "$(DESTDIR)${sysconfdir}/ipsec.d" || $(INSTALL) -o -d "$(DESTDIR)$(sysconfdir)/ipsec.d" || true
+ test -e "$(DESTDIR)${sysconfdir}/ipsec.d" || $(INSTALL) -d "$(DESTDIR)$(sysconfdir)/ipsec.d" || true
test -e "$(DESTDIR)${sysconfdir}/ipsec.d/cacerts" || $(INSTALL) -d "$(DESTDIR)$(sysconfdir)/ipsec.d/cacerts" || true
test -e "$(DESTDIR)${sysconfdir}/ipsec.d/ocspcerts" || $(INSTALL) -d "$(DESTDIR)$(sysconfdir)/ipsec.d/ocspcerts" || true
test -e "$(DESTDIR)${sysconfdir}/ipsec.d/certs" || $(INSTALL) -d "$(DESTDIR)$(sysconfdir)/ipsec.d/certs" || true
diff --git a/src/starter/args.c b/src/starter/args.c
index 65d0a753c..2416960bd 100644
--- a/src/starter/args.c
+++ b/src/starter/args.c
@@ -17,11 +17,8 @@
#include <stdlib.h>
#include <string.h>
-#include <freeswan.h>
-
-#include "../pluto/constants.h"
-#include "../pluto/defs.h"
-#include "../pluto/log.h"
+#include <library.h>
+#include <debug.h>
#include "keywords.h"
#include "confread.h"
@@ -64,6 +61,7 @@ static const char *LST_unique[] = {
"yes",
"replace",
"keep",
+ "never",
NULL
};
@@ -89,13 +87,6 @@ static const char *LST_startup[] = {
NULL
};
-static const char *LST_packetdefault[] = {
- "drop",
- "reject",
- "pass",
- NULL
-};
-
static const char *LST_keyexchange[] = {
"ike",
"ikev1",
@@ -103,55 +94,17 @@ static const char *LST_keyexchange[] = {
NULL
};
-static const char *LST_pfsgroup[] = {
- "modp1024",
- "modp1536",
- "modp2048",
- "modp3072",
- "modp4096",
- "modp6144",
- "modp8192",
- "ecp192",
- "ecp224",
- "ecp256",
- "ecp384",
- "ecp521",
- NULL
-};
-
-static const char *LST_plutodebug[] = {
- "none",
- "all",
- "raw",
- "crypt",
- "parsing",
- "emitting",
- "control",
- "lifecycle",
- "klips",
- "kernel",
- "dns",
- "natt",
- "oppo",
- "controlmore",
- "private",
- NULL
-};
-
-static const char *LST_klipsdebug[] = {
- "tunnel",
- "tunnel-xmit",
- "pfkey",
- "xform",
- "eroute",
- "spi",
- "radij",
- "esp",
- "ah",
- "ipcomp",
- "verbose",
- "all",
- "none",
+static const char *LST_authby[] = {
+ "psk",
+ "secret",
+ "pubkey",
+ "rsa",
+ "rsasig",
+ "ecdsa",
+ "ecdsasig",
+ "xauthpsk",
+ "xauthrsasig",
+ "never",
NULL
};
@@ -164,49 +117,23 @@ typedef struct {
static const token_info_t token_info[] =
{
/* config setup keywords */
- { ARG_LST, offsetof(starter_config_t, setup.interfaces), NULL },
- { ARG_STR, offsetof(starter_config_t, setup.dumpdir), NULL },
- { ARG_ENUM, offsetof(starter_config_t, setup.charonstart), LST_bool },
- { ARG_ENUM, offsetof(starter_config_t, setup.plutostart), LST_bool },
-
- /* pluto/charon keywords */
- { ARG_LST, offsetof(starter_config_t, setup.plutodebug), LST_plutodebug },
{ ARG_STR, offsetof(starter_config_t, setup.charondebug), NULL },
- { ARG_STR, offsetof(starter_config_t, setup.prepluto), NULL },
- { ARG_STR, offsetof(starter_config_t, setup.postpluto), NULL },
- { ARG_STR, offsetof(starter_config_t, setup.plutostderrlog), NULL },
{ ARG_ENUM, offsetof(starter_config_t, setup.uniqueids), LST_unique },
- { ARG_UINT, offsetof(starter_config_t, setup.overridemtu), NULL },
- { ARG_TIME, offsetof(starter_config_t, setup.crlcheckinterval), NULL },
{ ARG_ENUM, offsetof(starter_config_t, setup.cachecrls), LST_bool },
{ ARG_ENUM, offsetof(starter_config_t, setup.strictcrlpolicy), LST_strict },
- { ARG_ENUM, offsetof(starter_config_t, setup.nocrsend), LST_bool },
- { ARG_ENUM, offsetof(starter_config_t, setup.nat_traversal), LST_bool },
- { ARG_TIME, offsetof(starter_config_t, setup.keep_alive), NULL },
- { ARG_ENUM, offsetof(starter_config_t, setup.force_keepalive), LST_bool },
- { ARG_STR, offsetof(starter_config_t, setup.virtual_private), NULL },
- { ARG_STR, offsetof(starter_config_t, setup.pkcs11module), NULL },
- { ARG_STR, offsetof(starter_config_t, setup.pkcs11initargs), NULL },
- { ARG_ENUM, offsetof(starter_config_t, setup.pkcs11keepstate), LST_bool },
- { ARG_ENUM, offsetof(starter_config_t, setup.pkcs11proxy), LST_bool },
-
- /* KLIPS keywords */
- { ARG_LST, offsetof(starter_config_t, setup.klipsdebug), LST_klipsdebug },
- { ARG_ENUM, offsetof(starter_config_t, setup.fragicmp), LST_bool },
- { ARG_STR, offsetof(starter_config_t, setup.packetdefault), LST_packetdefault },
- { ARG_ENUM, offsetof(starter_config_t, setup.hidetos), LST_bool },
+ { ARG_MISC, 0, NULL /* KW_PKCS11_DEPRECATED */ },
+ { ARG_MISC, 0, NULL /* KW_SETUP_DEPRECATED */ },
/* conn section keywords */
{ ARG_STR, offsetof(starter_conn_t, name), NULL },
{ ARG_ENUM, offsetof(starter_conn_t, startup), LST_startup },
{ ARG_ENUM, offsetof(starter_conn_t, keyexchange), LST_keyexchange },
{ ARG_MISC, 0, NULL /* KW_TYPE */ },
- { ARG_MISC, 0, NULL /* KW_PFS */ },
{ ARG_MISC, 0, NULL /* KW_COMPRESS */ },
{ ARG_ENUM, offsetof(starter_conn_t, install_policy), LST_bool },
+ { ARG_ENUM, offsetof(starter_conn_t, aggressive), LST_bool },
{ ARG_MISC, 0, NULL /* KW_AUTH */ },
- { ARG_MISC, 0, NULL /* KW_AUTHBY */ },
- { ARG_MISC, 0, NULL /* KW_EAP */ },
+ { ARG_STR, offsetof(starter_conn_t, authby), LST_authby },
{ ARG_STR, offsetof(starter_conn_t, eap_identity), NULL },
{ ARG_STR, offsetof(starter_conn_t, aaa_identity), NULL },
{ ARG_MISC, 0, NULL /* KW_MOBIKE */ },
@@ -224,7 +151,6 @@ static const token_info_t token_info[] =
{ ARG_MISC, 0, NULL /* KW_REAUTH */ },
{ ARG_STR, offsetof(starter_conn_t, ike), NULL },
{ ARG_STR, offsetof(starter_conn_t, esp), NULL },
- { ARG_STR, offsetof(starter_conn_t, pfsgroup), LST_pfsgroup },
{ ARG_TIME, offsetof(starter_conn_t, dpd_delay), NULL },
{ ARG_TIME, offsetof(starter_conn_t, dpd_timeout), NULL },
{ ARG_ENUM, offsetof(starter_conn_t, dpd_action), LST_dpd_action },
@@ -241,28 +167,27 @@ static const token_info_t token_info[] =
{ ARG_MISC, 0, NULL /* KW_MARK_IN */ },
{ ARG_MISC, 0, NULL /* KW_MARK_OUT */ },
{ ARG_MISC, 0, NULL /* KW_TFC */ },
+ { ARG_MISC, 0, NULL /* KW_PFS_DEPRECATED */ },
+ { ARG_MISC, 0, NULL /* KW_CONN_DEPRECATED */ },
/* ca section keywords */
{ ARG_STR, offsetof(starter_ca_t, name), NULL },
{ ARG_ENUM, offsetof(starter_ca_t, startup), LST_startup },
{ ARG_STR, offsetof(starter_ca_t, cacert), NULL },
- { ARG_STR, offsetof(starter_ca_t, ldaphost), NULL },
- { ARG_STR, offsetof(starter_ca_t, ldapbase), NULL },
{ ARG_STR, offsetof(starter_ca_t, crluri), NULL },
{ ARG_STR, offsetof(starter_ca_t, crluri2), NULL },
{ ARG_STR, offsetof(starter_ca_t, ocspuri), NULL },
{ ARG_STR, offsetof(starter_ca_t, ocspuri2), NULL },
{ ARG_STR, offsetof(starter_ca_t, certuribase), NULL },
+ { ARG_MISC, 0, NULL /* KW_CA_DEPRECATED */ },
/* end keywords */
{ ARG_STR, offsetof(starter_end_t, host), NULL },
{ ARG_UINT, offsetof(starter_end_t, ikeport), NULL },
- { ARG_MISC, 0, NULL /* KW_NEXTHOP */ },
- { ARG_STR, offsetof(starter_end_t, subnet), NULL },
- { ARG_MISC, 0, NULL /* KW_SUBNETWITHIN */ },
+ { ARG_STR, offsetof(starter_end_t, subnet), NULL },
{ ARG_MISC, 0, NULL /* KW_PROTOPORT */ },
{ ARG_STR, offsetof(starter_end_t, sourceip), NULL },
- { ARG_MISC, 0, NULL /* KW_NATIP */ },
+ { ARG_STR, offsetof(starter_end_t, dns), NULL },
{ ARG_ENUM, offsetof(starter_end_t, firewall), LST_bool },
{ ARG_ENUM, offsetof(starter_end_t, hostaccess), LST_bool },
{ ARG_ENUM, offsetof(starter_end_t, allow_any), LST_bool },
@@ -279,7 +204,8 @@ static const token_info_t token_info[] =
{ ARG_STR, offsetof(starter_end_t, ca), NULL },
{ ARG_STR, offsetof(starter_end_t, ca2), NULL },
{ ARG_STR, offsetof(starter_end_t, groups), NULL },
- { ARG_STR, offsetof(starter_end_t, iface), NULL }
+ { ARG_STR, offsetof(starter_end_t, groups2), NULL },
+ { ARG_MISC, 0, NULL /* KW_END_DEPRECATED */ },
};
static void free_list(char **list)
@@ -298,7 +224,7 @@ char** new_list(char *value)
char *val, *b, *e, *end, **ret;
int count;
- val = value ? clone_str(value) : NULL;
+ val = strdupnull(value);
if (!val)
{
return NULL;
@@ -326,7 +252,7 @@ char** new_list(char *value)
for (e = b; (*e != '\0'); e++);
if (e != b)
{
- ret[count++] = clone_str(b);
+ ret[count++] = strdupnull(b);
}
b = e + 1;
}
@@ -347,23 +273,20 @@ bool assign_arg(kw_token_t token, kw_token_t first, kw_list_t *kw, char *base,
int index = -1; /* used for enumeration arguments */
- lset_t *seen = (lset_t *)base; /* seen flags are at the top of the struct */
- lset_t f = LELEM(token - first); /* compute flag position of argument */
+ seen_t *seen = (seen_t*)base; /* seen flags are at the top of the struct */
*assigned = FALSE;
- DBG(DBG_CONTROLMORE,
- DBG_log(" %s=%s", kw->entry->name, kw->value)
- )
+ DBG3(DBG_APP, " %s=%s", kw->entry->name, kw->value);
- if (*seen & f)
+ if (*seen & SEEN_KW(token, first))
{
- plog("# duplicate '%s' option", kw->entry->name);
+ DBG1(DBG_APP, "# duplicate '%s' option", kw->entry->name);
return FALSE;
}
/* set flag that this argument has been seen */
- *seen |= f;
+ *seen |= SEEN_KW(token, first);
/* is there a keyword list? */
if (list != NULL && token_info[token].type != ARG_LST)
@@ -377,7 +300,7 @@ bool assign_arg(kw_token_t token, kw_token_t first, kw_list_t *kw, char *base,
}
if (!match)
{
- plog("# bad value: %s=%s", kw->entry->name, kw->value);
+ DBG1(DBG_APP, "# bad value: %s=%s", kw->entry->name, kw->value);
return FALSE;
}
}
@@ -385,14 +308,14 @@ bool assign_arg(kw_token_t token, kw_token_t first, kw_list_t *kw, char *base,
switch (token_info[token].type)
{
case ARG_NONE:
- plog("# option '%s' not supported yet", kw->entry->name);
+ DBG1(DBG_APP, "# option '%s' not supported yet", kw->entry->name);
return FALSE;
case ARG_ENUM:
{
if (index < 0)
{
- plog("# bad enumeration value: %s=%s (%d)"
- , kw->entry->name, kw->value, index);
+ DBG1(DBG_APP, "# bad enumeration value: %s=%s (%d)",
+ kw->entry->name, kw->value, index);
return FALSE;
}
@@ -418,7 +341,8 @@ bool assign_arg(kw_token_t token, kw_token_t first, kw_list_t *kw, char *base,
if (*endptr != '\0')
{
- plog("# bad integer value: %s=%s", kw->entry->name, kw->value);
+ DBG1(DBG_APP, "# bad integer value: %s=%s", kw->entry->name,
+ kw->value);
return FALSE;
}
}
@@ -435,7 +359,8 @@ bool assign_arg(kw_token_t token, kw_token_t first, kw_list_t *kw, char *base,
{
if (*endptr != '\0')
{
- plog("# bad integer value: %s=%s", kw->entry->name, kw->value);
+ DBG1(DBG_APP, "# bad integer value: %s=%s", kw->entry->name,
+ kw->value);
return FALSE;
}
}
@@ -443,7 +368,8 @@ bool assign_arg(kw_token_t token, kw_token_t first, kw_list_t *kw, char *base,
{
if ((*endptr != '%') || (endptr[1] != '\0') || endptr == kw->value)
{
- plog("# bad percent value: %s=%s", kw->entry->name, kw->value);
+ DBG1(DBG_APP, "# bad percent value: %s=%s", kw->entry->name,
+ kw->value);
return FALSE;
}
}
@@ -459,7 +385,8 @@ bool assign_arg(kw_token_t token, kw_token_t first, kw_list_t *kw, char *base,
if (*endptr != '\0')
{
- plog("# bad integer value: %s=%s", kw->entry->name, kw->value);
+ DBG1(DBG_APP, "# bad integer value: %s=%s", kw->entry->name,
+ kw->value);
return FALSE;
}
}
@@ -494,7 +421,8 @@ bool assign_arg(kw_token_t token, kw_token_t first, kw_list_t *kw, char *base,
break;
}
}
- plog("# bad duration value: %s=%s", kw->entry->name, kw->value);
+ DBG1(DBG_APP, "# bad duration value: %s=%s", kw->entry->name,
+ kw->value);
return FALSE;
}
case ARG_STR:
@@ -505,7 +433,7 @@ bool assign_arg(kw_token_t token, kw_token_t first, kw_list_t *kw, char *base,
free(*cp);
/* assign the new string */
- *cp = clone_str(kw->value);
+ *cp = strdupnull(kw->value);
}
break;
case ARG_LST:
@@ -537,7 +465,8 @@ bool assign_arg(kw_token_t token, kw_token_t first, kw_list_t *kw, char *base,
}
if (!match)
{
- plog("# bad value: %s=%s", kw->entry->name, *lst);
+ DBG1(DBG_APP, "# bad value: %s=%s",
+ kw->entry->name, *lst);
return FALSE;
}
}
@@ -604,7 +533,7 @@ void clone_args(kw_token_t first, kw_token_t last, char *base1, char *base2)
char **cp1 = (char **)(base1 + token_info[token].offset);
char **cp2 = (char **)(base2 + token_info[token].offset);
- *cp1 = clone_str(*cp2);
+ *cp1 = strdupnull(*cp2);
}
}
}
diff --git a/src/starter/cmp.c b/src/starter/cmp.c
index 0727cf5f0..aaba7b11d 100644
--- a/src/starter/cmp.c
+++ b/src/starter/cmp.c
@@ -14,62 +14,39 @@
#include <string.h>
-#include <freeswan.h>
-
-#include "../pluto/constants.h"
-#include "../pluto/defs.h"
-
#include "confread.h"
#include "args.h"
-#include "interfaces.h"
#include "cmp.h"
#define VARCMP(obj) if (c1->obj != c2->obj) return FALSE
-#define ADDCMP(obj) if (!sameaddr(&c1->obj,&c2->obj)) return FALSE
-#define SUBCMP(obj) if (!samesubnet(&c1->obj,&c2->obj)) return FALSE
#define STRCMP(obj) if (strcmp(c1->obj,c2->obj)) return FALSE
-static bool
-starter_cmp_end(starter_end_t *c1, starter_end_t *c2)
+static bool starter_cmp_end(starter_end_t *c1, starter_end_t *c2)
{
if ((c1 == NULL) || (c2 == NULL))
return FALSE;
- if (c2->dns_failed)
- {
- c2->addr = c1->addr;
- }
- else
- {
- ADDCMP(addr);
- }
- VARCMP(ikeport);
- ADDCMP(nexthop);
- VARCMP(has_client);
- VARCMP(has_client_wildcard);
- VARCMP(has_port_wildcard);
- VARCMP(has_natip);
- VARCMP(has_virt);
VARCMP(modecfg);
VARCMP(port);
VARCMP(protocol);
return cmp_args(KW_END_FIRST, KW_END_LAST, (char *)c1, (char *)c2);
- }
+}
-bool
-starter_cmp_conn(starter_conn_t *c1, starter_conn_t *c2)
+bool starter_cmp_conn(starter_conn_t *c1, starter_conn_t *c2)
{
if ((c1 == NULL) || (c2 == NULL))
return FALSE;
- VARCMP(policy);
- VARCMP(addr_family);
- VARCMP(tunnel_addr_family);
+ VARCMP(mode);
+ VARCMP(proxy_mode);
+ VARCMP(options);
VARCMP(mark_in.value);
VARCMP(mark_in.mask);
VARCMP(mark_out.value);
VARCMP(mark_in.mask);
+ VARCMP(tfc);
+ VARCMP(sa_keying_tries);
if (!starter_cmp_end(&c1->left, &c2->left))
return FALSE;
@@ -79,8 +56,7 @@ starter_cmp_conn(starter_conn_t *c1, starter_conn_t *c2)
return cmp_args(KW_CONN_NAME, KW_CONN_LAST, (char *)c1, (char *)c2);
}
-bool
-starter_cmp_ca(starter_ca_t *c1, starter_ca_t *c2)
+bool starter_cmp_ca(starter_ca_t *c1, starter_ca_t *c2)
{
if (c1 == NULL || c2 == NULL)
return FALSE;
@@ -88,28 +64,3 @@ starter_cmp_ca(starter_ca_t *c1, starter_ca_t *c2)
return cmp_args(KW_CA_NAME, KW_CA_LAST, (char *)c1, (char *)c2);
}
-bool
-starter_cmp_klips(starter_config_t *c1, starter_config_t *c2)
-{
- if ((c1 == NULL) || (c2 == NULL))
- return FALSE;
-
- return cmp_args(KW_KLIPS_FIRST, KW_KLIPS_LAST, (char *)c1, (char *)c2);
-}
-
-bool
-starter_cmp_pluto(starter_config_t *c1, starter_config_t *c2)
-{
- if ((c1 == NULL) || (c2 == NULL))
- return FALSE;
-
- return cmp_args(KW_PLUTO_FIRST, KW_PLUTO_LAST, (char *)c1, (char *)c2);
-}
-
-bool
-starter_cmp_defaultroute(defaultroute_t *d1, defaultroute_t *d2)
-{
- if ((d1 == NULL) || (d2 == NULL))
- return FALSE;
- return memcmp(d1, d2, sizeof(defaultroute_t)) == 0;
-}
diff --git a/src/starter/cmp.h b/src/starter/cmp.h
index cda6e44b9..c33ce8ec2 100644
--- a/src/starter/cmp.h
+++ b/src/starter/cmp.h
@@ -15,13 +15,8 @@
#ifndef _STARTER_CMP_H_
#define _STARTER_CMP_H_
-#include "interfaces.h"
-
-extern bool starter_cmp_conn(starter_conn_t *c1, starter_conn_t *c2);
-extern bool starter_cmp_ca(starter_ca_t *c1, starter_ca_t *c2);
-extern bool starter_cmp_klips(starter_config_t *c1, starter_config_t *c2);
-extern bool starter_cmp_pluto(starter_config_t *c1, starter_config_t *c2);
-extern bool starter_cmp_defaultroute(defaultroute_t *d1, defaultroute_t *d2);
+bool starter_cmp_conn(starter_conn_t *c1, starter_conn_t *c2);
+bool starter_cmp_ca(starter_ca_t *c1, starter_ca_t *c2);
#endif
diff --git a/src/starter/confread.c b/src/starter/confread.c
index 627601e88..6544b1ccd 100644
--- a/src/starter/confread.c
+++ b/src/starter/confread.c
@@ -19,26 +19,24 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
+#include <netdb.h>
-#include <freeswan.h>
-
-#include <eap/eap.h>
-
-#include "../pluto/constants.h"
-#include "../pluto/defs.h"
-#include "../pluto/log.h"
+#include <library.h>
+#include <debug.h>
#include "keywords.h"
#include "confread.h"
#include "args.h"
#include "files.h"
-#include "interfaces.h"
-/* strings containing a colon are interpreted as an IPv6 address */
-#define ip_version(string) (strchr(string, '.') ? AF_INET : AF_INET6)
+#define IKE_LIFETIME_DEFAULT 10800 /* 3 hours */
+#define IPSEC_LIFETIME_DEFAULT 3600 /* 1 hour */
+#define SA_REPLACEMENT_MARGIN_DEFAULT 540 /* 9 minutes */
+#define SA_REPLACEMENT_FUZZ_DEFAULT 100 /* 100% of margin */
+#define SA_REPLACEMENT_RETRIES_DEFAULT 3
static const char ike_defaults[] = "aes128-sha1-modp2048,3des-sha1-modp1536";
-static const char esp_defaults[] = "aes128-sha1,3des-sha1";
+static const char esp_defaults[] = "aes128-sha1-modp2048,3des-sha1-modp1536";
static const char firewall_defaults[] = "ipsec _updown iptables";
@@ -47,12 +45,53 @@ static bool daemon_exists(char *daemon, char *path)
struct stat st;
if (stat(path, &st) != 0)
{
- plog("Disabling %sstart option, '%s' not found", daemon, path);
+ DBG1(DBG_APP, "Disabling %sstart option, '%s' not found", daemon, path);
return FALSE;
}
return TRUE;
}
+/**
+ * Process deprecated keywords
+ */
+static bool is_deprecated(kw_token_t token, kw_list_t *kw, char *name)
+{
+ switch (token)
+ {
+ case KW_SETUP_DEPRECATED:
+ case KW_PKCS11_DEPRECATED:
+ DBG1(DBG_APP, "# deprecated keyword '%s' in config setup",
+ kw->entry->name);
+ break;
+ case KW_CONN_DEPRECATED:
+ case KW_END_DEPRECATED:
+ case KW_PFS_DEPRECATED:
+ DBG1(DBG_APP, "# deprecated keyword '%s' in conn '%s'",
+ kw->entry->name, name);
+ break;
+ case KW_CA_DEPRECATED:
+ DBG1(DBG_APP, "# deprecated keyword '%s' in ca '%s'",
+ kw->entry->name, name);
+ break;
+ default:
+ return FALSE;
+ }
+ /* additional messages for some */
+ switch (token)
+ {
+ case KW_PKCS11_DEPRECATED:
+ DBG1(DBG_APP, " use the 'pkcs11' plugin instead", kw->entry->name);
+ break;
+ case KW_PFS_DEPRECATED:
+ DBG1(DBG_APP, " PFS is enabled by specifying a DH group in the "
+ "'esp' cipher suite", kw->entry->name);
+ break;
+ default:
+ break;
+ }
+ return TRUE;
+}
+
static void default_values(starter_config_t *cfg)
{
if (cfg == NULL)
@@ -60,7 +99,7 @@ static void default_values(starter_config_t *cfg)
memset(cfg, 0, sizeof(struct starter_config));
- /* is there enough space for all seen flags? */
+ /* is there enough space for all seen flags? */
assert(KW_SETUP_LAST - KW_SETUP_FIRST <
sizeof(cfg->setup.seen) * BITS_PER_BYTE);
assert(KW_CONN_LAST - KW_CONN_FIRST <
@@ -70,66 +109,52 @@ static void default_values(starter_config_t *cfg)
assert(KW_CA_LAST - KW_CA_FIRST <
sizeof(cfg->ca_default.seen) * BITS_PER_BYTE);
- cfg->setup.seen = LEMPTY;
- cfg->setup.fragicmp = TRUE;
- cfg->setup.hidetos = TRUE;
+ cfg->setup.seen = SEEN_NONE;
cfg->setup.uniqueids = TRUE;
- cfg->setup.interfaces = new_list("%defaultroute");
#ifdef START_CHARON
cfg->setup.charonstart = TRUE;
#endif
-#ifdef START_PLUTO
- cfg->setup.plutostart = TRUE;
-#endif
- cfg->conn_default.seen = LEMPTY;
+ cfg->conn_default.seen = SEEN_NONE;
cfg->conn_default.startup = STARTUP_NO;
cfg->conn_default.state = STATE_IGNORE;
- cfg->conn_default.policy = POLICY_ENCRYPT | POLICY_TUNNEL | POLICY_PUBKEY |
- POLICY_PFS | POLICY_MOBIKE;
+ cfg->conn_default.mode = MODE_TUNNEL;
+ cfg->conn_default.options = SA_OPTION_MOBIKE;
- cfg->conn_default.ike = clone_str(ike_defaults);
- cfg->conn_default.esp = clone_str(esp_defaults);
- cfg->conn_default.sa_ike_life_seconds = OAKLEY_ISAKMP_SA_LIFETIME_DEFAULT;
- cfg->conn_default.sa_ipsec_life_seconds = PLUTO_SA_LIFE_DURATION_DEFAULT;
+ cfg->conn_default.ike = strdupnull(ike_defaults);
+ cfg->conn_default.esp = strdupnull(esp_defaults);
+ cfg->conn_default.sa_ike_life_seconds = IKE_LIFETIME_DEFAULT;
+ cfg->conn_default.sa_ipsec_life_seconds = IPSEC_LIFETIME_DEFAULT;
cfg->conn_default.sa_rekey_margin = SA_REPLACEMENT_MARGIN_DEFAULT;
cfg->conn_default.sa_rekey_fuzz = SA_REPLACEMENT_FUZZ_DEFAULT;
cfg->conn_default.sa_keying_tries = SA_REPLACEMENT_RETRIES_DEFAULT;
- cfg->conn_default.addr_family = AF_INET;
- cfg->conn_default.tunnel_addr_family = AF_INET;
- cfg->conn_default.install_policy = TRUE;
- cfg->conn_default.dpd_delay = 30; /* seconds */
- cfg->conn_default.dpd_timeout = 150; /* seconds */
+ cfg->conn_default.install_policy = TRUE;
+ cfg->conn_default.dpd_delay = 30; /* seconds */
+ cfg->conn_default.dpd_timeout = 150; /* seconds */
- cfg->conn_default.left.seen = LEMPTY;
- cfg->conn_default.right.seen = LEMPTY;
+ cfg->conn_default.left.seen = SEEN_NONE;
+ cfg->conn_default.right.seen = SEEN_NONE;
cfg->conn_default.left.sendcert = CERT_SEND_IF_ASKED;
cfg->conn_default.right.sendcert = CERT_SEND_IF_ASKED;
- anyaddr(AF_INET, &cfg->conn_default.left.addr);
- anyaddr(AF_INET, &cfg->conn_default.left.nexthop);
- anyaddr(AF_INET, &cfg->conn_default.right.addr);
- anyaddr(AF_INET, &cfg->conn_default.right.nexthop);
cfg->conn_default.left.ikeport = 500;
cfg->conn_default.right.ikeport = 500;
- cfg->ca_default.seen = LEMPTY;
+ cfg->ca_default.seen = SEEN_NONE;
}
-#define KW_POLICY_FLAG(sy, sn, fl) \
- if (streq(kw->value, sy)) { conn->policy |= fl; } \
- else if (streq(kw->value, sn)) { conn->policy &= ~fl; } \
- else { plog("# bad policy value: %s=%s", kw->entry->name, kw->value); cfg->err++; }
+#define KW_SA_OPTION_FLAG(sy, sn, fl) \
+ if (streq(kw->value, sy)) { conn->options |= fl; } \
+ else if (streq(kw->value, sn)) { conn->options &= ~fl; } \
+ else { DBG1(DBG_APP, "# bad option value: %s=%s", kw->entry->name, kw->value); cfg->err++; }
static void load_setup(starter_config_t *cfg, config_parsed_t *cfgp)
{
kw_list_t *kw;
- DBG(DBG_CONTROL,
- DBG_log("Loading config setup")
- )
+ DBG2(DBG_APP, "Loading config setup");
for (kw = cfgp->config_setup; kw; kw = kw->next)
{
@@ -139,45 +164,49 @@ static void load_setup(starter_config_t *cfg, config_parsed_t *cfgp)
if ((int)token < KW_SETUP_FIRST || token > KW_SETUP_LAST)
{
- plog("# unsupported keyword '%s' in config setup", kw->entry->name);
+ DBG1(DBG_APP, "# unsupported keyword '%s' in config setup",
+ kw->entry->name);
cfg->err++;
continue;
}
+ if (is_deprecated(token, kw, ""))
+ {
+ cfg->non_fatal_err++;
+ continue;
+ }
+
if (!assign_arg(token, KW_SETUP_FIRST, kw, (char *)cfg, &assigned))
{
- plog(" bad argument value in config setup");
+ DBG1(DBG_APP, " bad argument value in config setup");
cfg->err++;
continue;
}
}
- /* verify the executables are actually available (some distros split
- * packages but enabled both) */
+ /* verify the executables are actually available */
#ifdef START_CHARON
cfg->setup.charonstart = cfg->setup.charonstart &&
daemon_exists("charon", CHARON_CMD);
#else
cfg->setup.charonstart = FALSE;
#endif
-#ifdef START_PLUTO
- cfg->setup.plutostart = cfg->setup.plutostart &&
- daemon_exists("pluto", PLUTO_CMD);
-#else
- cfg->setup.plutostart = FALSE;
-#endif
}
static void kw_end(starter_conn_t *conn, starter_end_t *end, kw_token_t token,
kw_list_t *kw, char *conn_name, starter_config_t *cfg)
{
- err_t ugh = NULL;
bool assigned = FALSE;
- bool has_port_wildcard; /* set if port is %any */
char *name = kw->entry->name;
char *value = kw->value;
+ if (is_deprecated(token, kw, conn_name))
+ {
+ cfg->non_fatal_err++;
+ return;
+ }
+
if (!assign_arg(token, KW_END_FIRST, kw, (char *)end, &assigned))
goto err;
@@ -185,157 +214,25 @@ static void kw_end(starter_conn_t *conn, starter_end_t *end, kw_token_t token,
switch (token)
{
case KW_HOST:
- free(end->host);
- end->host = NULL;
- if (streq(value, "%defaultroute"))
+ if (value && strlen(value) > 0 && value[0] == '%')
{
- if (cfg->defaultroute.defined)
+ if (streq(value, "%defaultroute"))
{
- end->addr = cfg->defaultroute.addr;
- end->nexthop = cfg->defaultroute.nexthop;
+ value = "%any";
}
- else if (!cfg->defaultroute.supported)
- {
- plog("%%defaultroute not supported, fallback to %%any");
- }
- else
- {
- plog("# default route not known: %s=%s", name, value);
- goto err;
- }
- }
- else if (streq(value, "%any") || streq(value, "%any4"))
- {
- anyaddr(conn->addr_family, &end->addr);
- }
- else if (streq(value, "%any6"))
- {
- conn->addr_family = AF_INET6;
- anyaddr(conn->addr_family, &end->addr);
- }
- else if (streq(value, "%group"))
- {
- ip_address any;
-
- conn->policy |= POLICY_GROUP | POLICY_TUNNEL;
- anyaddr(conn->addr_family, &end->addr);
- anyaddr(conn->tunnel_addr_family, &any);
- end->has_client = TRUE;
- }
- else
- {
- /* check for allow_any prefix */
- if (value[0] == '%')
- {
+ if (!streq(value, "%any") && !streq(value, "%any4") &&
+ !streq(value, "%any6"))
+ { /* allow_any prefix */
end->allow_any = TRUE;
value++;
}
- conn->addr_family = ip_version(value);
- ugh = ttoaddr(value, 0, conn->addr_family, &end->addr);
- if (ugh != NULL)
- {
- plog("# bad addr: %s=%s [%s]", name, value, ugh);
- if (streq(ugh, "does not look numeric and name lookup failed"))
- {
- end->dns_failed = TRUE;
- anyaddr(conn->addr_family, &end->addr);
- }
- else
- {
- goto err;
- }
- }
- end->host = clone_str(value);
- }
- break;
- case KW_SUBNET:
- if ((strlen(value) >= 6 && strncmp(value,"vhost:",6) == 0)
- || (strlen(value) >= 5 && strncmp(value,"vnet:",5) == 0))
- {
- /* used by pluto only */
- end->has_virt = TRUE;
- }
- else
- {
- ip_subnet net;
- char *pos;
- int len = 0;
-
- end->has_client = TRUE;
- conn->tunnel_addr_family = ip_version(value);
-
- pos = strchr(value, ',');
- if (pos)
- {
- len = pos - value;
- }
- ugh = ttosubnet(value, len, ip_version(value), &net);
- if (ugh != NULL)
- {
- plog("# bad subnet: %s=%s [%s]", name, value, ugh);
- goto err;
- }
}
+ free(end->host);
+ end->host = strdupnull(value);
break;
case KW_SOURCEIP:
- if (end->has_natip)
- {
- plog("# natip and sourceip cannot be defined at the same time");
- goto err;
- }
- if (value[0] == '%')
- {
- if (streq(value, "%modeconfig") || streq(value, "%modecfg") ||
- streq(value, "%config") || streq(value, "%cfg"))
- {
- /* request ip via config payload */
- free(end->sourceip);
- end->sourceip = NULL;
- end->sourceip_mask = 1;
- }
- else
- { /* %poolname, strip %, serve ip requests */
- free(end->sourceip);
- end->sourceip = clone_str(value+1);
- end->sourceip_mask = 0;
- }
- end->modecfg = TRUE;
- }
- else
- {
- char *pos;
- ip_address addr;
- ip_subnet net;
-
- conn->tunnel_addr_family = ip_version(value);
- pos = strchr(value, '/');
-
- if (pos)
- { /* CIDR notation, address pool */
- ugh = ttosubnet(value, 0, conn->tunnel_addr_family, &net);
- if (ugh != NULL)
- {
- plog("# bad subnet: %s=%s [%s]", name, value, ugh);
- goto err;
- }
- *pos = '\0';
- free(end->sourceip);
- end->sourceip = clone_str(value);
- end->sourceip_mask = atoi(pos + 1);
- }
- else
- { /* fixed srcip */
- ugh = ttoaddr(value, 0, conn->tunnel_addr_family, &addr);
- if (ugh != NULL)
- {
- plog("# bad addr: %s=%s [%s]", name, value, ugh);
- goto err;
- }
- end->sourceip_mask = (conn->tunnel_addr_family == AF_INET) ?
- 32 : 128;
- }
- }
- conn->policy |= POLICY_TUNNEL;
+ conn->mode = MODE_TUNNEL;
+ conn->proxy_mode = FALSE;
break;
case KW_SENDCERT:
if (end->sendcert == CERT_YES_SEND)
@@ -357,139 +254,97 @@ static void kw_end(starter_conn_t *conn, starter_end_t *end, kw_token_t token,
/* individual processing of keywords that were not assigned automatically */
switch (token)
{
- case KW_NEXTHOP:
- if (streq(value, "%defaultroute"))
+ case KW_PROTOPORT:
+ {
+ struct protoent *proto;
+ struct servent *svc;
+ char *sep, *port = "", *endptr;
+ long int p;
+
+ sep = strchr(value, '/');
+ if (sep)
+ { /* protocol/port */
+ *sep = '\0';
+ port = sep + 1;
+ }
+
+ if (streq(value, "%any"))
{
- if (cfg->defaultroute.defined)
+ end->protocol = 0;
+ }
+ else
+ {
+ proto = getprotobyname(value);
+ if (proto)
{
- end->nexthop = cfg->defaultroute.nexthop;
+ end->protocol = proto->p_proto;
}
else
{
- plog("# default route not known: %s=%s", name, value);
- goto err;
+ p = strtol(value, &endptr, 0);
+ if ((*value && *endptr) || p < 0 || p > 0xff)
+ {
+ DBG1(DBG_APP, "# bad protocol: %s=%s", name, value);
+ goto err;
+ }
+ end->protocol = (u_int8_t)p;
}
}
- else if (streq(value, "%direct"))
+ if (streq(port, "%any"))
{
- ugh = anyaddr(conn->addr_family, &end->nexthop);
+ end->port = 0;
}
else
{
- conn->addr_family = ip_version(value);
- ugh = ttoaddr(value, 0, conn->addr_family, &end->nexthop);
- }
- if (ugh != NULL)
- {
- plog("# bad addr: %s=%s [%s]", name, value, ugh);
- goto err;
- }
- break;
- case KW_SUBNETWITHIN:
- {
- ip_subnet net;
-
- end->has_client = TRUE;
- end->has_client_wildcard = TRUE;
- conn->tunnel_addr_family = ip_version(value);
-
- ugh = ttosubnet(value, 0, ip_version(value), &net);
- if (ugh != NULL)
- {
- plog("# bad subnet: %s=%s [%s]", name, value, ugh);
- goto err;
- }
- end->subnet = clone_str(value);
- break;
- }
- case KW_PROTOPORT:
- ugh = ttoprotoport(value, 0, &end->protocol, &end->port, &has_port_wildcard);
- end->has_port_wildcard = has_port_wildcard;
- break;
- case KW_NATIP:
- if (end->sourceip)
- {
- plog("# natip and sourceip cannot be defined at the same time");
- goto err;
- }
- if (streq(value, "%defaultroute"))
- {
- char buf[64];
-
- if (cfg->defaultroute.defined)
+ svc = getservbyname(port, NULL);
+ if (svc)
{
- addrtot(&cfg->defaultroute.addr, 0, buf, sizeof(buf));
- end->sourceip = clone_str(buf);
+ end->port = ntohs(svc->s_port);
}
else
{
- plog("# default route not known: %s=%s", name, value);
- goto err;
+ p = strtol(port, &endptr, 0);
+ if ((*port && *endptr) || p < 0 || p > 0xffff)
+ {
+ DBG1(DBG_APP, "# bad port: %s=%s", name, value);
+ goto err;
+ }
+ end->port = (u_int16_t)p;
}
}
- else
- {
- ip_address addr;
-
- conn->tunnel_addr_family = ip_version(value);
- ugh = ttoaddr(value, 0, conn->tunnel_addr_family, &addr);
- if (ugh != NULL)
- {
- plog("# bad addr: %s=%s [%s]", name, value, ugh);
- goto err;
- }
- end->sourceip = clone_str(value);
+ if (sep)
+ { /* restore the original text in case also= is used */
+ *sep = '/';
}
- end->has_natip = TRUE;
- conn->policy |= POLICY_TUNNEL;
break;
+ }
default:
break;
}
return;
err:
- plog(" bad argument value in conn '%s'", conn_name);
+ DBG1(DBG_APP, " bad argument value in conn '%s'", conn_name);
cfg->err++;
}
/*
- * handles left|right=<FQDN> DNS resolution failure
- */
-static void handle_dns_failure(const char *label, starter_end_t *end,
- starter_config_t *cfg, starter_conn_t *conn)
-{
- if (end->dns_failed)
- {
- if (end->allow_any)
- {
- plog("# fallback to %s=%%any due to '%%' prefix or %sallowany=yes",
- label, label);
- }
- else if (!end->host || conn->keyexchange == KEY_EXCHANGE_IKEV1)
- {
- /* declare an error */
- cfg->err++;
- }
- }
-}
-
-/*
* handles left|rightfirewall and left|rightupdown parameters
*/
static void handle_firewall(const char *label, starter_end_t *end,
starter_config_t *cfg)
{
- if (end->firewall && (end->seen & LELEM(KW_FIREWALL - KW_END_FIRST)))
+ if (end->firewall && (end->seen & SEEN_KW(KW_FIREWALL, KW_END_FIRST)))
{
if (end->updown != NULL)
{
- plog("# cannot have both %sfirewall and %supdown", label, label);
+ DBG1(DBG_APP, "# cannot have both %sfirewall and %supdown", label,
+ label);
cfg->err++;
}
else
{
- end->updown = clone_str(firewall_defaults);
+ end->updown = strdupnull(firewall_defaults);
end->firewall = FALSE;
}
}
@@ -497,16 +352,16 @@ static void handle_firewall(const char *label, starter_end_t *end,
static bool handle_mark(char *value, mark_t *mark)
{
- char *pos, *endptr;
+ char *sep, *endptr;
- pos = strchr(value, '/');
- if (pos)
+ sep = strchr(value, '/');
+ if (sep)
{
- *pos = '\0';
- mark->mask = strtoul(pos+1, &endptr, 0);
+ *sep = '\0';
+ mark->mask = strtoul(sep+1, &endptr, 0);
if (*endptr != '\0')
{
- plog("# invalid mark mask: %s", pos+1);
+ DBG1(DBG_APP, "# invalid mark mask: %s", sep+1);
return FALSE;
}
}
@@ -523,10 +378,16 @@ static bool handle_mark(char *value, mark_t *mark)
mark->value = strtoul(value, &endptr, 0);
if (*endptr != '\0')
{
- plog("# invalid mark value: %s", value);
+ DBG1(DBG_APP, "# invalid mark value: %s", value);
return FALSE;
}
}
+ if (sep)
+ { /* restore the original text in case also= is used */
+ *sep = '/';
+ }
+ /* apply the mask to ensure the value is in range */
+ mark->value &= mark->mask;
return TRUE;
}
@@ -566,28 +427,32 @@ static void load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg
{
also_t *also = malloc_thing(also_t);
- also->name = clone_str(kw->value);
+ also->name = strdupnull(kw->value);
also->next = conn->also;
conn->also = also;
- DBG(DBG_CONTROL,
- DBG_log(" also=%s", kw->value)
- )
+ DBG2(DBG_APP, " also=%s", kw->value);
}
continue;
}
if (token < KW_CONN_FIRST || token > KW_CONN_LAST)
{
- plog("# unsupported keyword '%s' in conn '%s'"
- , kw->entry->name, conn_name);
+ DBG1(DBG_APP, "# unsupported keyword '%s' in conn '%s'",
+ kw->entry->name, conn_name);
cfg->err++;
continue;
}
+ if (is_deprecated(token, kw, conn_name))
+ {
+ cfg->non_fatal_err++;
+ continue;
+ }
+
if (!assign_arg(token, KW_CONN_FIRST, kw, (char *)conn, &assigned))
{
- plog(" bad argument value in conn '%s'", conn_name);
+ DBG1(DBG_APP, " bad argument value in conn '%s'", conn_name);
cfg->err++;
continue;
}
@@ -598,125 +463,42 @@ static void load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg
switch (token)
{
case KW_TYPE:
- conn->policy &= ~(POLICY_TUNNEL | POLICY_SHUNT_MASK);
+ conn->mode = MODE_TRANSPORT;
+ conn->proxy_mode = FALSE;
if (streq(kw->value, "tunnel"))
{
- conn->policy |= POLICY_TUNNEL;
+ conn->mode = MODE_TUNNEL;
}
else if (streq(kw->value, "beet"))
{
- conn->policy |= POLICY_BEET;
+ conn->mode = MODE_BEET;
}
else if (streq(kw->value, "transport_proxy"))
{
- conn->policy |= POLICY_PROXY;
+ conn->mode = MODE_TRANSPORT;
+ conn->proxy_mode = TRUE;
}
else if (streq(kw->value, "passthrough") || streq(kw->value, "pass"))
{
- conn->policy |= POLICY_SHUNT_PASS;
+ conn->mode = MODE_PASS;
}
- else if (streq(kw->value, "drop"))
+ else if (streq(kw->value, "drop") || streq(kw->value, "reject"))
{
- conn->policy |= POLICY_SHUNT_DROP;
+ conn->mode = MODE_DROP;
}
- else if (streq(kw->value, "reject"))
+ else if (!streq(kw->value, "transport"))
{
- conn->policy |= POLICY_SHUNT_REJECT;
- }
- else if (strcmp(kw->value, "transport") != 0)
- {
- plog("# bad policy value: %s=%s", kw->entry->name, kw->value);
+ DBG1(DBG_APP, "# bad policy value: %s=%s", kw->entry->name,
+ kw->value);
cfg->err++;
}
break;
- case KW_PFS:
- KW_POLICY_FLAG("yes", "no", POLICY_PFS)
- break;
case KW_COMPRESS:
- KW_POLICY_FLAG("yes", "no", POLICY_COMPRESS)
+ KW_SA_OPTION_FLAG("yes", "no", SA_OPTION_COMPRESS)
break;
case KW_AUTH:
- KW_POLICY_FLAG("ah", "esp", POLICY_AUTHENTICATE)
- break;
- case KW_AUTHBY:
- conn->policy &= ~(POLICY_ID_AUTH_MASK | POLICY_ENCRYPT);
-
- if (!streq(kw->value, "never"))
- {
- char *value = kw->value;
- char *second = strchr(kw->value, '|');
-
- if (second != NULL)
- {
- *second = '\0';
- }
-
- /* also handles the cases secret|rsasig and rsasig|secret */
- for (;;)
- {
- if (streq(value, "rsa") || streq(value, "rsasig") ||
- streq(value, "ecdsa") || streq(value, "ecdsasig") ||
- streq(value, "pubkey"))
- {
- conn->policy |= POLICY_PUBKEY | POLICY_ENCRYPT;
- }
- else if (streq(value, "secret") || streq(value, "psk"))
- {
- conn->policy |= POLICY_PSK | POLICY_ENCRYPT;
- }
- else if (streq(value, "xauthrsasig"))
- {
- conn->policy |= POLICY_XAUTH_RSASIG | POLICY_ENCRYPT;
- }
- else if (streq(value, "xauthpsk") || streq(value, "eap"))
- {
- conn->policy |= POLICY_XAUTH_PSK | POLICY_ENCRYPT;
- }
- else
- {
- plog("# bad policy value: %s=%s", kw->entry->name, kw->value);
- cfg->err++;
- break;
- }
- if (second == NULL)
- {
- break;
- }
- value = second;
- second = NULL; /* traverse the loop no more than twice */
- }
- }
- break;
- case KW_EAP:
- {
- char *sep;
-
- /* check for vendor-type format */
- sep = strchr(kw->value, '-');
- if (sep)
- {
- *(sep++) = '\0';
- conn->eap_type = atoi(kw->value);
- conn->eap_vendor = atoi(sep);
- if (conn->eap_type == 0 || conn->eap_vendor == 0)
- {
- plog("# invalid EAP type: %s=%s", kw->entry->name, kw->value);
- cfg->err++;
- }
- break;
- }
- conn->eap_type = eap_type_from_string(kw->value);
- if (conn->eap_type == 0)
- {
- conn->eap_type = atoi(kw->value);
- if (conn->eap_type == 0)
- {
- plog("# unknown EAP type: %s=%s", kw->entry->name, kw->value);
- cfg->err++;
- }
- }
+ KW_SA_OPTION_FLAG("ah", "esp", SA_OPTION_AUTHENTICATE)
break;
- }
case KW_MARK:
if (!handle_mark(kw->value, &conn->mark_in))
{
@@ -749,7 +531,8 @@ static void load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg
conn->tfc = strtoul(kw->value, &endptr, 10);
if (*endptr != '\0')
{
- plog("# bad integer value: %s=%s", kw->entry->name, kw->value);
+ DBG1(DBG_APP, "# bad integer value: %s=%s", kw->entry->name,
+ kw->value);
cfg->err++;
}
}
@@ -766,36 +549,35 @@ static void load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg
conn->sa_keying_tries = strtoul(kw->value, &endptr, 10);
if (*endptr != '\0')
{
- plog("# bad integer value: %s=%s", kw->entry->name, kw->value);
+ DBG1(DBG_APP, "# bad integer value: %s=%s", kw->entry->name,
+ kw->value);
cfg->err++;
}
}
break;
case KW_REKEY:
- KW_POLICY_FLAG("no", "yes", POLICY_DONT_REKEY)
+ KW_SA_OPTION_FLAG("no", "yes", SA_OPTION_DONT_REKEY)
break;
case KW_REAUTH:
- KW_POLICY_FLAG("no", "yes", POLICY_DONT_REAUTH)
+ KW_SA_OPTION_FLAG("no", "yes", SA_OPTION_DONT_REAUTH)
break;
case KW_MOBIKE:
- KW_POLICY_FLAG("yes", "no", POLICY_MOBIKE)
+ KW_SA_OPTION_FLAG("yes", "no", SA_OPTION_MOBIKE)
break;
case KW_FORCEENCAPS:
- KW_POLICY_FLAG("yes", "no", POLICY_FORCE_ENCAP)
+ KW_SA_OPTION_FLAG("yes", "no", SA_OPTION_FORCE_ENCAP)
break;
case KW_MODECONFIG:
- KW_POLICY_FLAG("push", "pull", POLICY_MODECFG_PUSH)
+ KW_SA_OPTION_FLAG("push", "pull", SA_OPTION_MODECFG_PUSH)
break;
case KW_XAUTH:
- KW_POLICY_FLAG("server", "client", POLICY_XAUTH_SERVER)
+ KW_SA_OPTION_FLAG("server", "client", SA_OPTION_XAUTH_SERVER)
break;
default:
break;
}
}
- handle_dns_failure("left", &conn->left, cfg, conn);
- handle_dns_failure("right", &conn->right, cfg, conn);
handle_firewall("left", &conn->left, cfg);
handle_firewall("right", &conn->right, cfg);
}
@@ -806,7 +588,7 @@ static void load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg
static void conn_default(char *name, starter_conn_t *conn, starter_conn_t *def)
{
memcpy(conn, def, sizeof(starter_conn_t));
- conn->name = clone_str(name);
+ conn->name = strdupnull(name);
clone_args(KW_CONN_FIRST, KW_CONN_LAST, (char *)conn, (char *)def);
clone_args(KW_END_FIRST, KW_END_LAST, (char *)&conn->left, (char *)&def->left);
@@ -836,27 +618,32 @@ static void load_ca(starter_ca_t *ca, kw_list_t *kw, starter_config_t *cfg)
{
also_t *also = malloc_thing(also_t);
- also->name = clone_str(kw->value);
+ also->name = strdupnull(kw->value);
also->next = ca->also;
ca->also = also;
- DBG(DBG_CONTROL,
- DBG_log(" also=%s", kw->value)
- )
+ DBG2(DBG_APP, " also=%s", kw->value);
}
continue;
}
if (token < KW_CA_FIRST || token > KW_CA_LAST)
{
- plog("# unsupported keyword '%s' in ca '%s'", kw->entry->name, ca_name);
+ DBG1(DBG_APP, "# unsupported keyword '%s' in ca '%s'",
+ kw->entry->name, ca_name);
cfg->err++;
continue;
}
+ if (is_deprecated(token, kw, ca_name))
+ {
+ cfg->non_fatal_err++;
+ continue;
+ }
+
if (!assign_arg(token, KW_CA_FIRST, kw, (char *)ca, &assigned))
{
- plog(" bad argument value in ca '%s'", ca_name);
+ DBG1(DBG_APP, " bad argument value in ca '%s'", ca_name);
cfg->err++;
}
}
@@ -872,7 +659,7 @@ static void load_ca(starter_ca_t *ca, kw_list_t *kw, starter_config_t *cfg)
static void ca_default(char *name, starter_ca_t *ca, starter_ca_t *def)
{
memcpy(ca, def, sizeof(starter_ca_t));
- ca->name = clone_str(name);
+ ca->name = strdupnull(name);
clone_args(KW_CA_FIRST, KW_CA_LAST, (char *)ca, (char *)def);
}
@@ -889,13 +676,12 @@ static void load_also_conns(starter_conn_t *conn, also_t *also,
if (kw == NULL)
{
- plog(" conn '%s' cannot include '%s'", conn->name, also->name);
+ DBG1(DBG_APP, " conn '%s' cannot include '%s'", conn->name,
+ also->name);
}
else
{
- DBG(DBG_CONTROL,
- DBG_log("conn '%s' includes '%s'", conn->name, also->name)
- )
+ DBG2(DBG_APP, "conn '%s' includes '%s'", conn->name, also->name);
/* only load if no error occurred in the first round */
if (cfg->err == 0)
load_conn(conn, kw, cfg);
@@ -918,7 +704,7 @@ static kw_list_t* find_also_conn(const char* name, starter_conn_t *conn,
{
if (conn->visit == c->visit)
{
- plog("# detected also loop");
+ DBG1(DBG_APP, "# detected also loop");
cfg->err++;
return NULL;
}
@@ -929,7 +715,7 @@ static kw_list_t* find_also_conn(const char* name, starter_conn_t *conn,
c = c->next;
}
- plog("# also '%s' not found", name);
+ DBG1(DBG_APP, "# also '%s' not found", name);
cfg->err++;
return NULL;
}
@@ -945,13 +731,12 @@ static void load_also_cas(starter_ca_t *ca, also_t *also, starter_config_t *cfg)
if (kw == NULL)
{
- plog(" ca '%s' cannot include '%s'", ca->name, also->name);
+ DBG1(DBG_APP, " ca '%s' cannot include '%s'", ca->name,
+ also->name);
}
else
{
- DBG(DBG_CONTROL,
- DBG_log("ca '%s' includes '%s'", ca->name, also->name)
- )
+ DBG2(DBG_APP, "ca '%s' includes '%s'", ca->name, also->name);
/* only load if no error occurred in the first round */
if (cfg->err == 0)
load_ca(ca, kw, cfg);
@@ -974,7 +759,7 @@ static kw_list_t* find_also_ca(const char* name, starter_ca_t *ca,
{
if (ca->visit == c->visit)
{
- plog("# detected also loop");
+ DBG1(DBG_APP, "# detected also loop");
cfg->err++;
return NULL;
}
@@ -985,7 +770,7 @@ static kw_list_t* find_also_ca(const char* name, starter_ca_t *ca,
c = c->next;
}
- plog("# also '%s' not found", name);
+ DBG1(DBG_APP, "# also '%s' not found", name);
cfg->err++;
return NULL;
}
@@ -1086,9 +871,6 @@ starter_config_t* confread_load(const char *file)
/* set default values */
default_values(cfg);
- /* determine default route */
- get_defaultroute(&cfg->defaultroute);
-
/* load config setup section */
load_setup(cfg, cfgp);
@@ -1100,15 +882,13 @@ starter_config_t* confread_load(const char *file)
{
if (streq(sca->name, "%default"))
{
- DBG(DBG_CONTROL,
- DBG_log("Loading ca %%default")
- )
+ DBG2(DBG_APP, "Loading ca %%default");
load_ca(&cfg->ca_default, sca->kw, cfg);
}
}
/* parameters defined in ca %default sections can be overloads */
- cfg->ca_default.seen = LEMPTY;
+ cfg->ca_default.seen = SEEN_NONE;
/* load other ca sections */
for (sca = cfgp->ca_first; sca; sca = sca->next)
@@ -1119,9 +899,7 @@ starter_config_t* confread_load(const char *file)
if (streq(sca->name, "%default"))
continue;
- DBG(DBG_CONTROL,
- DBG_log("Loading ca '%s'", sca->name)
- )
+ DBG2(DBG_APP, "Loading ca '%s'", sca->name);
ca = malloc_thing(starter_ca_t);
ca_default(sca->name, ca, &cfg->ca_default);
@@ -1169,17 +947,15 @@ starter_config_t* confread_load(const char *file)
{
if (streq(sconn->name, "%default"))
{
- DBG(DBG_CONTROL,
- DBG_log("Loading conn %%default")
- )
+ DBG2(DBG_APP, "Loading conn %%default");
load_conn(&cfg->conn_default, sconn->kw, cfg);
}
}
- /* parameter defined in conn %default sections can be overloaded */
- cfg->conn_default.seen = LEMPTY;
- cfg->conn_default.right.seen = LEMPTY;
- cfg->conn_default.left.seen = LEMPTY;
+ /* parameters defined in conn %default sections can be overloaded */
+ cfg->conn_default.seen = SEEN_NONE;
+ cfg->conn_default.right.seen = SEEN_NONE;
+ cfg->conn_default.left.seen = SEEN_NONE;
/* load other conn sections */
for (sconn = cfgp->conn_first; sconn; sconn = sconn->next)
@@ -1190,9 +966,7 @@ starter_config_t* confread_load(const char *file)
if (streq(sconn->name, "%default"))
continue;
- DBG(DBG_CONTROL,
- DBG_log("Loading conn '%s'", sconn->name)
- )
+ DBG2(DBG_APP, "Loading conn '%s'", sconn->name);
conn = malloc_thing(starter_conn_t);
conn_default(sconn->name, conn, &cfg->conn_default);
@@ -1245,8 +1019,8 @@ starter_config_t* confread_load(const char *file)
total_err = cfg->err + cfg->non_fatal_err;
if (total_err > 0)
{
- plog("### %d parsing error%s (%d fatal) ###"
- , total_err, (total_err > 1)?"s":"", cfg->err);
+ DBG1(DBG_APP, "### %d parsing error%s (%d fatal) ###",
+ total_err, (total_err > 1)?"s":"", cfg->err);
}
return cfg;
diff --git a/src/starter/confread.h b/src/starter/confread.h
index 9cb919ce5..3f2079883 100644
--- a/src/starter/confread.h
+++ b/src/starter/confread.h
@@ -16,12 +16,14 @@
#ifndef _IPSEC_CONFREAD_H_
#define _IPSEC_CONFREAD_H_
-#ifndef _FREESWAN_H
-#include <freeswan.h>
-#endif
+#include <kernel/kernel_ipsec.h>
#include "ipsec-parser.h"
-#include "interfaces.h"
+
+/** to mark seen keywords */
+typedef u_int64_t seen_t;
+#define SEEN_NONE 0;
+#define SEEN_KW(kw, base) ((seen_t)1 << ((kw) - (base)))
typedef enum {
STARTUP_NO,
@@ -39,9 +41,10 @@ typedef enum {
} starter_state_t;
typedef enum {
- KEY_EXCHANGE_IKE,
- KEY_EXCHANGE_IKEV1,
- KEY_EXCHANGE_IKEV2
+ /* shared with ike_version_t */
+ KEY_EXCHANGE_IKE = 0,
+ KEY_EXCHANGE_IKEV1 = 1,
+ KEY_EXCHANGE_IKEV2 = 2,
} keyexchange_t;
typedef enum {
@@ -50,10 +53,40 @@ typedef enum {
STRICT_IFURI
} strict_t;
+typedef enum {
+ CERT_ALWAYS_SEND,
+ CERT_SEND_IF_ASKED,
+ CERT_NEVER_SEND,
+ CERT_YES_SEND, /* synonym for CERT_ALWAYS_SEND */
+ CERT_NO_SEND, /* synonym for CERT_NEVER_SEND */
+} certpolicy_t;
+
+typedef enum {
+ DPD_ACTION_NONE,
+ DPD_ACTION_CLEAR,
+ DPD_ACTION_HOLD,
+ DPD_ACTION_RESTART,
+ DPD_ACTION_UNKNOW,
+} dpd_action_t;
+
+typedef enum {
+ /* IPsec options */
+ SA_OPTION_AUTHENTICATE = 1 << 0, /* use AH instead of ESP? */
+ SA_OPTION_COMPRESS = 1 << 1, /* use IPComp */
+
+ /* IKE and other other options */
+ SA_OPTION_DONT_REKEY = 1 << 2, /* don't rekey state either Phase */
+ SA_OPTION_DONT_REAUTH = 1 << 3, /* don't reauthenticate on rekeying, IKEv2 only */
+ SA_OPTION_MODECFG_PUSH = 1 << 4, /* is modecfg pushed by server? */
+ SA_OPTION_XAUTH_SERVER = 1 << 5, /* are we an XAUTH server? */
+ SA_OPTION_MOBIKE = 1 << 6, /* enable MOBIKE for IKEv2 */
+ SA_OPTION_FORCE_ENCAP = 1 << 7, /* force UDP encapsulation */
+} sa_option_t;
+
typedef struct starter_end starter_end_t;
struct starter_end {
- lset_t seen;
+ seen_t seen;
char *auth;
char *auth2;
char *id;
@@ -64,29 +97,21 @@ struct starter_end {
char *ca;
char *ca2;
char *groups;
+ char *groups2;
char *cert_policy;
- char *iface;
char *host;
- ip_address addr;
u_int ikeport;
- ip_address nexthop;
char *subnet;
- bool has_client;
- bool has_client_wildcard;
- bool has_port_wildcard;
- bool has_natip;
- bool has_virt;
bool modecfg;
certpolicy_t sendcert;
bool firewall;
bool hostaccess;
bool allow_any;
- bool dns_failed;
char *updown;
u_int16_t port;
u_int8_t protocol;
char *sourceip;
- int sourceip_mask;
+ char *dns;
};
typedef struct also also_t;
@@ -100,7 +125,7 @@ struct also {
typedef struct starter_conn starter_conn_t;
struct starter_conn {
- lset_t seen;
+ seen_t seen;
char *name;
also_t *also;
kw_list_t *kw;
@@ -109,35 +134,34 @@ struct starter_conn {
starter_state_t state;
keyexchange_t keyexchange;
- u_int32_t eap_type;
- u_int32_t eap_vendor;
char *eap_identity;
char *aaa_identity;
char *xauth_identity;
- lset_t policy;
+ char *authby;
+ ipsec_mode_t mode;
+ bool proxy_mode;
+ sa_option_t options;
time_t sa_ike_life_seconds;
time_t sa_ipsec_life_seconds;
time_t sa_rekey_margin;
- u_int64_t sa_ipsec_life_bytes;
- u_int64_t sa_ipsec_margin_bytes;
- u_int64_t sa_ipsec_life_packets;
- u_int64_t sa_ipsec_margin_packets;
+ u_int64_t sa_ipsec_life_bytes;
+ u_int64_t sa_ipsec_margin_bytes;
+ u_int64_t sa_ipsec_life_packets;
+ u_int64_t sa_ipsec_margin_packets;
unsigned long sa_keying_tries;
unsigned long sa_rekey_fuzz;
u_int32_t reqid;
mark_t mark_in;
mark_t mark_out;
u_int32_t tfc;
- sa_family_t addr_family;
- sa_family_t tunnel_addr_family;
bool install_policy;
+ bool aggressive;
starter_end_t left, right;
unsigned long id;
char *esp;
char *ike;
- char *pfsgroup;
time_t dpd_delay;
time_t dpd_timeout;
@@ -158,7 +182,7 @@ struct starter_conn {
typedef struct starter_ca starter_ca_t;
struct starter_ca {
- lset_t seen;
+ seen_t seen;
char *name;
also_t *also;
kw_list_t *kw;
@@ -167,13 +191,11 @@ struct starter_ca {
starter_state_t state;
char *cacert;
- char *ldaphost;
- char *ldapbase;
char *crluri;
char *crluri2;
char *ocspuri;
char *ocspuri2;
- char *certuribase;
+ char *certuribase;
bool strict;
@@ -184,43 +206,14 @@ typedef struct starter_config starter_config_t;
struct starter_config {
struct {
- lset_t seen;
- char **interfaces;
- char *dumpdir;
- bool charonstart;
- bool plutostart;
-
- /* pluto/charon keywords */
- char **plutodebug;
+ seen_t seen;
+ bool charonstart;
char *charondebug;
- char *prepluto;
- char *postpluto;
- char *plutostderrlog;
bool uniqueids;
- u_int overridemtu;
- time_t crlcheckinterval;
bool cachecrls;
strict_t strictcrlpolicy;
- bool nocrsend;
- bool nat_traversal;
- time_t keep_alive;
- u_int force_keepalive;
- char *virtual_private;
- char *pkcs11module;
- char *pkcs11initargs;
- bool pkcs11keepstate;
- bool pkcs11proxy;
-
- /* KLIPS keywords */
- char **klipsdebug;
- bool fragicmp;
- char *packetdefault;
- bool hidetos;
} setup;
- /* information about the default route */
- defaultroute_t defaultroute;
-
/* number of encountered parsing errors */
u_int err;
u_int non_fatal_err;
diff --git a/src/starter/exec.c b/src/starter/exec.c
deleted file mode 100644
index d4c4f0657..000000000
--- a/src/starter/exec.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/* strongSwan IPsec exec helper function
- * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <stdio.h>
-
-#include <freeswan.h>
-
-#include "../pluto/constants.h"
-#include "../pluto/defs.h"
-#include "../pluto/log.h"
-
-#include "exec.h"
-
-#define BUF_SIZE 2048
-
-/**
- * TODO:
- * o log stdout with LOG_LEVEL_INFO and stderr with LOG_LEVEL_ERR
- */
-
-int
-starter_exec(const char *fmt, ...)
-{
- va_list args;
- static char buf[BUF_SIZE];
- int r;
-
- va_start (args, fmt);
- vsnprintf(buf, BUF_SIZE-1, fmt, args);
- buf[BUF_SIZE - 1] = '\0';
- va_end(args);
- r = system(buf);
- DBG(DBG_CONTROL,
- DBG_log("starter_exec(%s) = %d", buf, r)
- )
- return r;
-}
-
diff --git a/src/starter/exec.h b/src/starter/exec.h
deleted file mode 100644
index 6a6414578..000000000
--- a/src/starter/exec.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* strongSwan IPsec starter exec helper function
- * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security
- *
- * 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.
- */
-
-#ifndef _STARTER_EXEC_H_
-#define _STARTER_EXEC_H_
-
-extern int starter_exec (const char *fmt, ...);
-
-#endif /* _STARTER_EXEC_H_ */
-
diff --git a/src/starter/files.h b/src/starter/files.h
index 88857c0b2..96b76fdf1 100644
--- a/src/starter/files.h
+++ b/src/starter/files.h
@@ -24,10 +24,6 @@
#define CONFIG_FILE IPSEC_CONFDIR "/ipsec.conf"
#define SECRETS_FILE IPSEC_CONFDIR "/ipsec.secrets"
-#define PLUTO_CMD IPSEC_DIR "/pluto"
-#define PLUTO_CTL_FILE IPSEC_PIDDIR "/pluto.ctl"
-#define PLUTO_PID_FILE IPSEC_PIDDIR "/pluto.pid"
-
#define CHARON_CMD IPSEC_DIR "/charon"
#define CHARON_CTL_FILE IPSEC_PIDDIR "/charon.ctl"
#define CHARON_PID_FILE IPSEC_PIDDIR "/charon.pid"
diff --git a/src/starter/interfaces.c b/src/starter/interfaces.c
deleted file mode 100644
index 4a2ae0a57..000000000
--- a/src/starter/interfaces.c
+++ /dev/null
@@ -1,213 +0,0 @@
-/* strongSwan IPsec interfaces management
- * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security
- * 2009 Heiko Hund - Astaro AG
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <freeswan.h>
-
-#include <constants.h>
-#include <defs.h>
-#include <log.h>
-
-#include "interfaces.h"
-#include "exec.h"
-#include "files.h"
-
-#ifdef START_PLUTO
-
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <linux/rtnetlink.h>
-#ifdef HAVE_SYS_SOCKIO_H
-#include <sys/sockio.h>
-#endif
-
-/*
- * Get the default route information via rtnetlink
- */
-void
-get_defaultroute(defaultroute_t *defaultroute)
-{
- union {
- struct {
- struct nlmsghdr nh;
- struct rtmsg rt;
- } m;
- char buf[4096];
- } rtu;
-
- struct nlmsghdr *nh;
- uint32_t best_metric = ~0;
- ssize_t msglen;
- int fd;
-
- memset(&rtu, 0, sizeof(rtu));
- rtu.m.nh.nlmsg_len = NLMSG_LENGTH(sizeof(rtu.m.rt));
- rtu.m.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
- rtu.m.nh.nlmsg_type = RTM_GETROUTE;
- rtu.m.rt.rtm_family = AF_INET;
- rtu.m.rt.rtm_table = RT_TABLE_UNSPEC;
- rtu.m.rt.rtm_protocol = RTPROT_UNSPEC;
- rtu.m.rt.rtm_type = RTN_UNICAST;
-
- fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
- if (fd == -1)
- {
- plog("could not create rtnetlink socket");
- return;
- }
-
- if (send(fd, &rtu, rtu.m.nh.nlmsg_len, 0) == -1)
- {
- plog("could not write to rtnetlink socket");
- close(fd);
- return;
- }
-
- msglen = recv(fd, &rtu, sizeof(rtu), MSG_WAITALL);
- if (msglen == -1)
- {
- plog("could not read from rtnetlink socket");
- close(fd);
- return;
- }
-
- close(fd);
-
- for (nh = &rtu.m.nh; NLMSG_OK(nh, msglen); nh = NLMSG_NEXT(nh, msglen))
- {
- struct rtmsg *rt;
- struct rtattr *rta;
- uint32_t rtalen, metric = 0;
- struct in_addr gw = { .s_addr = INADDR_ANY };
- int iface_idx = -1;
-
- if (nh->nlmsg_type == NLMSG_ERROR)
- {
- plog("error from rtnetlink");
- return;
- }
-
- if (nh->nlmsg_type == NLMSG_DONE)
- break;
-
- rt = NLMSG_DATA(nh);
- if ( rt->rtm_dst_len != 0
- || (rt->rtm_table != RT_TABLE_MAIN
- && rt->rtm_table != RT_TABLE_DEFAULT) )
- continue;
-
- rta = RTM_RTA(rt);
- rtalen = RTM_PAYLOAD(nh);
- while ( RTA_OK(rta, rtalen) )
- {
- switch (rta->rta_type)
- {
- case RTA_GATEWAY:
- gw = *(struct in_addr *) RTA_DATA(rta);
- break;
- case RTA_OIF:
- iface_idx = *(int *) RTA_DATA(rta);
- break;
- case RTA_PRIORITY:
- metric = *(uint32_t *) RTA_DATA(rta);
- break;
- }
- rta = RTA_NEXT(rta, rtalen);
- }
-
- if (metric < best_metric
- && iface_idx != -1)
- {
- struct ifreq req;
-
- fd = socket(AF_INET, SOCK_DGRAM, 0);
- if (fd < 0)
- {
- plog("could not open AF_INET socket");
- break;
- }
- memset(&req, 0, sizeof(req));
- req.ifr_ifindex = iface_idx;
- if (ioctl(fd, SIOCGIFNAME, &req) < 0 ||
- ioctl(fd, SIOCGIFADDR, &req) < 0)
- {
- plog("could not read interface data, ignoring route");
- close(fd);
- break;
- }
-
- strncpy(defaultroute->iface, req.ifr_name, IFNAMSIZ);
- defaultroute->iface[IFNAMSIZ-1] = '\0';
- defaultroute->addr.u.v4 = *((struct sockaddr_in *) &req.ifr_addr);
- defaultroute->nexthop.u.v4.sin_family = AF_INET;
-
- if (gw.s_addr == INADDR_ANY)
- {
- if (ioctl(fd, SIOCGIFDSTADDR, &req) < 0 ||
- ((struct sockaddr_in*) &req.ifr_dstaddr)->sin_addr.s_addr == INADDR_ANY)
- {
- DBG_log("Ignoring default route to device %s because we can't get it's destination",
- req.ifr_name);
- close(fd);
- break;
- }
-
- defaultroute->nexthop.u.v4 = *((struct sockaddr_in *) &req.ifr_dstaddr);
- }
- else
- defaultroute->nexthop.u.v4.sin_addr = gw;
-
- close(fd);
-
- DBG(DBG_CONTROL,
- char addr[20];
- char nexthop[20];
- addrtot(&defaultroute->addr, 0, addr, sizeof(addr));
- addrtot(&defaultroute->nexthop, 0, nexthop, sizeof(nexthop));
-
- DBG_log(
- ( !defaultroute->defined
- ? "Default route found: iface=%s, addr=%s, nexthop=%s"
- : "Better default route: iface=%s, addr=%s, nexthop=%s"
- ), defaultroute->iface, addr, nexthop
- )
- );
-
- best_metric = metric;
- defaultroute->defined = TRUE;
- }
- }
- defaultroute->supported = TRUE;
-
- if (!defaultroute->defined)
- plog("no default route - cannot cope with %%defaultroute!!!");
-}
-
-#else /* !START_PLUTO */
-
-/**
- * Pluto disabled, fall back to %any
- */
-void
-get_defaultroute(defaultroute_t *defaultroute)
-{
- defaultroute->supported = FALSE;
-}
-#endif /* START_PLUTO */
-
diff --git a/src/starter/interfaces.h b/src/starter/interfaces.h
deleted file mode 100644
index ff8535f0e..000000000
--- a/src/starter/interfaces.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* strongSwan IPsec interfaces management
- * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security
- *
- * 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.
- */
-
-#ifndef _STARTER_INTERFACES_H_
-#define _STARTER_INTERFACES_H_
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <net/if.h>
-
-#include "../pluto/constants.h"
-
-typedef struct {
- bool defined;
- bool supported;
- char iface[IFNAMSIZ];
- ip_address addr;
- ip_address nexthop;
-} defaultroute_t;
-
-extern void get_defaultroute(defaultroute_t *defaultroute);
-
-
-#endif /* _STARTER_INTERFACES_H_ */
-
diff --git a/src/starter/invokecharon.c b/src/starter/invokecharon.c
index e88939415..102d1589e 100644
--- a/src/starter/invokecharon.c
+++ b/src/starter/invokecharon.c
@@ -23,11 +23,8 @@
#include <stdlib.h>
#include <errno.h>
-#include <freeswan.h>
-
-#include "../pluto/constants.h"
-#include "../pluto/defs.h"
-#include "../pluto/log.h"
+#include <library.h>
+#include <debug.h>
#include "confread.h"
#include "invokecharon.h"
@@ -49,19 +46,19 @@ void starter_charon_sigchild(pid_t pid, int status)
if (status == SS_RC_LIBSTRONGSWAN_INTEGRITY ||
status == SS_RC_DAEMON_INTEGRITY)
{
- plog("charon has quit: integrity test of %s failed",
- (status == 64) ? "libstrongswan" : "charon");
+ DBG1(DBG_APP, "charon has quit: integrity test of %s failed",
+ (status == 64) ? "libstrongswan" : "charon");
_stop_requested = 1;
}
else if (status == SS_RC_INITIALIZATION_FAILED)
{
- plog("charon has quit: initialization failed");
+ DBG1(DBG_APP, "charon has quit: initialization failed");
_stop_requested = 1;
}
if (!_stop_requested)
{
- plog("charon has died -- restart scheduled (%dsec)"
- , CHARON_RESTART_DELAY);
+ DBG1(DBG_APP, "charon has died -- restart scheduled (%dsec)",
+ CHARON_RESTART_DELAY);
alarm(CHARON_RESTART_DELAY); // restart in 5 sec
}
unlink(CHARON_PID_FILE);
@@ -91,7 +88,7 @@ int starter_stop_charon (void)
else if (i == 40)
{
kill(pid, SIGKILL);
- plog("starter_stop_charon(): charon does not respond, sending KILL");
+ DBG1(DBG_APP, "starter_stop_charon(): charon does not respond, sending KILL");
}
else
{
@@ -101,15 +98,15 @@ int starter_stop_charon (void)
}
if (_charon_pid == 0)
{
- plog("charon stopped after %d ms", 200*i);
+ DBG1(DBG_APP, "charon stopped after %d ms", 200*i);
return 0;
}
- plog("starter_stop_charon(): can't stop charon !!!");
+ DBG1(DBG_APP, "starter_stop_charon(): can't stop charon !!!");
return -1;
}
else
{
- plog("stater_stop_charon(): charon was not started...");
+ DBG1(DBG_APP, "stater_stop_charon(): charon was not started...");
}
return -1;
}
@@ -175,7 +172,7 @@ int starter_start_charon (starter_config_t *cfg, bool no_fork, bool attach_gdb)
if (_charon_pid)
{
- plog("starter_start_charon(): charon already started...");
+ DBG1(DBG_APP, "starter_start_charon(): charon already started...");
return -1;
}
else
@@ -187,34 +184,36 @@ int starter_start_charon (starter_config_t *cfg, bool no_fork, bool attach_gdb)
switch (pid)
{
case -1:
- plog("can't fork(): %s", strerror(errno));
+ DBG1(DBG_APP, "can't fork(): %s", strerror(errno));
return -1;
case 0:
/* child */
setsid();
+ closefrom(3);
sigprocmask(SIG_SETMASK, 0, NULL);
/* disable glibc's malloc checker, conflicts with leak detective */
setenv("MALLOC_CHECK_", "0", 1);
execv(arg[0], arg);
- plog("can't execv(%s,...): %s", arg[0], strerror(errno));
+ DBG1(DBG_APP, "can't execv(%s,...): %s", arg[0], strerror(errno));
exit(1);
default:
/* father */
- _charon_pid = pid;
- for (i = 0; i < 500 && _charon_pid; i++)
+ _charon_pid = pid;
+ for (i = 0; i < 500 && _charon_pid; i++)
{
/* wait for charon for a maximum of 500 x 20 ms = 10 s */
usleep(20000);
if (stat(CHARON_PID_FILE, &stb) == 0)
{
- plog("charon (%d) started after %d ms", _charon_pid, 20*(i+1));
+ DBG1(DBG_APP, "charon (%d) started after %d ms",
+ _charon_pid, 20*(i+1));
return 0;
}
}
if (_charon_pid)
{
/* If charon is started but with no ctl file, stop it */
- plog("charon too long to start... - kill kill");
+ DBG1(DBG_APP, "charon too long to start... - kill kill");
for (i = 0; i < 20 && (pid = _charon_pid) != 0; i++)
{
if (i == 0)
@@ -234,7 +233,7 @@ int starter_start_charon (starter_config_t *cfg, bool no_fork, bool attach_gdb)
}
else
{
- plog("charon refused to be started");
+ DBG1(DBG_APP, "charon refused to be started");
}
return -1;
}
diff --git a/src/starter/invokepluto.c b/src/starter/invokepluto.c
deleted file mode 100644
index 70c0692ea..000000000
--- a/src/starter/invokepluto.c
+++ /dev/null
@@ -1,327 +0,0 @@
-/* strongSwan Pluto launcher
- * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security
- *
- * 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 <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <signal.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <fcntl.h>
-
-#include <freeswan.h>
-
-#include "../pluto/constants.h"
-#include "../pluto/defs.h"
-#include "../pluto/log.h"
-
-#include "confread.h"
-#include "invokepluto.h"
-#include "files.h"
-#include "starterwhack.h"
-#
-static int _pluto_pid = 0;
-static int _stop_requested;
-
-pid_t
-starter_pluto_pid(void)
-{
- return _pluto_pid;
-}
-
-void
-starter_pluto_sigchild(pid_t pid, int status)
-{
- if (pid == _pluto_pid)
- {
- _pluto_pid = 0;
- if (status == SS_RC_LIBSTRONGSWAN_INTEGRITY ||
- status == SS_RC_DAEMON_INTEGRITY)
- {
- plog("pluto has quit: integrity test of %s failed",
- (status == 64) ? "libstrongswan" : "pluto");
- _stop_requested = 1;
- }
- else if (status == SS_RC_INITIALIZATION_FAILED)
- {
- plog("pluto has quit: initialization failed");
- _stop_requested = 1;
- }
- if (!_stop_requested)
- {
- plog("pluto has died -- restart scheduled (%dsec)"
- , PLUTO_RESTART_DELAY);
- alarm(PLUTO_RESTART_DELAY); // restart in 5 sec
- }
- unlink(PLUTO_PID_FILE);
- }
-}
-
-int
-starter_stop_pluto (void)
-{
- int i;
- pid_t pid = _pluto_pid;
-
- if (pid)
- {
- _stop_requested = 1;
-
- if (starter_whack_shutdown() == 0)
- {
- for (i = 0; i < 400; i++)
- {
- usleep(20000); /* sleep for 20 ms */
- if (_pluto_pid == 0)
- {
- plog("pluto stopped after %d ms", 20*(i+1));
- return 0;
- }
- }
- }
- /* be more and more aggressive */
- for (i = 0; i < 20 && (pid = _pluto_pid) != 0; i++)
- {
-
- if (i < 10)
- {
- kill(pid, SIGTERM);
- }
- if (i == 10)
- {
- kill(pid, SIGKILL);
- plog("starter_stop_pluto(): pluto does not respond, sending KILL");
- }
- else
- {
- kill(pid, SIGKILL);
- }
- usleep(100000); /* sleep for 100 ms */
- }
- if (_pluto_pid == 0)
- {
- plog("pluto stopped after %d ms", 8000 + 100*i);
- return 0;
- }
- plog("starter_stop_pluto(): can't stop pluto !!!");
- return -1;
- }
- else
- {
- plog("stater_stop_pluto(): pluto is not started...");
- }
- return -1;
-}
-
-#define ADD_DEBUG(v) { \
- for (l = cfg->setup.plutodebug; l && *l; l++) if (streq(*l, v)) \
- arg[argc++] = "--debug-" v; \
- }
-
-int
-starter_start_pluto (starter_config_t *cfg, bool no_fork, bool attach_gdb)
-{
- struct stat stb;
- int i;
- pid_t pid;
- char **l;
- int argc = 2;
- char *arg[] = {
- PLUTO_CMD, "--nofork"
- , NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
- , NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
- , NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
- , NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
- };
-
- printf ("starter_start_pluto entered\n");
-
- if (attach_gdb)
- {
- argc = 0;
- arg[argc++] = "/usr/bin/gdb";
- arg[argc++] = "--args";
- arg[argc++] = PLUTO_CMD;
- arg[argc++] = "--nofork";
- }
- if (cfg->setup.plutostderrlog || no_fork)
- {
- arg[argc++] = "--stderrlog";
- }
- if (cfg->setup.uniqueids)
- {
- arg[argc++] = "--uniqueids";
- }
- ADD_DEBUG("none")
- ADD_DEBUG("all")
- ADD_DEBUG("raw")
- ADD_DEBUG("crypt")
- ADD_DEBUG("parsing")
- ADD_DEBUG("emitting")
- ADD_DEBUG("control")
- ADD_DEBUG("lifecycle")
- ADD_DEBUG("klips")
- ADD_DEBUG("kernel")
- ADD_DEBUG("dns")
- ADD_DEBUG("natt")
- ADD_DEBUG("oppo")
- ADD_DEBUG("controlmore")
- ADD_DEBUG("private")
- if (cfg->setup.crlcheckinterval > 0)
- {
- static char buf1[15];
-
- arg[argc++] = "--crlcheckinterval";
- snprintf(buf1, sizeof(buf1), "%d", (int)cfg->setup.crlcheckinterval);
- arg[argc++] = buf1;
- }
- if (cfg->setup.cachecrls)
- {
- arg[argc++] = "--cachecrls";
- }
- if (cfg->setup.strictcrlpolicy)
- {
- arg[argc++] = "--strictcrlpolicy";
- }
- if (cfg->setup.nocrsend)
- {
- arg[argc++] = "--nocrsend";
- }
- if (cfg->setup.nat_traversal)
- {
- arg[argc++] = "--nat_traversal";
- }
- if (cfg->setup.force_keepalive)
- {
- arg[argc++] = "--force_keepalive";
- }
- if (cfg->setup.keep_alive)
- {
- static char buf2[15];
-
- arg[argc++] = "--keep_alive";
- snprintf(buf2, sizeof(buf2), "%d", (int)cfg->setup.keep_alive);
- arg[argc++] = buf2;
- }
- if (cfg->setup.virtual_private)
- {
- arg[argc++] = "--virtual_private";
- arg[argc++] = cfg->setup.virtual_private;
- }
- if (cfg->setup.pkcs11module)
- {
- arg[argc++] = "--pkcs11module";
- arg[argc++] = cfg->setup.pkcs11module;
- }
- if (cfg->setup.pkcs11initargs)
- {
- arg[argc++] = "--pkcs11initargs";
- arg[argc++] = cfg->setup.pkcs11initargs;
- }
- if (cfg->setup.pkcs11keepstate)
- {
- arg[argc++] = "--pkcs11keepstate";
- }
- if (cfg->setup.pkcs11proxy)
- {
- arg[argc++] = "--pkcs11proxy";
- }
-
- if (_pluto_pid)
- {
- plog("starter_start_pluto(): pluto already started...");
- return -1;
- }
- else
- {
- unlink(PLUTO_CTL_FILE);
- _stop_requested = 0;
-
- if (cfg->setup.prepluto)
- ignore_result(system(cfg->setup.prepluto));
-
- pid = fork();
- switch (pid)
- {
- case -1:
- plog("can't fork(): %s", strerror(errno));
- return -1;
- case 0:
- /* child */
- if (cfg->setup.plutostderrlog)
- {
- int f = creat(cfg->setup.plutostderrlog, 00644);
-
- /* redirect stderr to file */
- if (f < 0)
- {
- plog("couldn't open stderr redirection file '%s'",
- cfg->setup.plutostderrlog);
- }
- else
- {
- dup2(f, 2);
- }
- }
- setsid();
- sigprocmask(SIG_SETMASK, 0, NULL);
- /* disable glibc's malloc checker, conflicts with leak detective */
- setenv("MALLOC_CHECK_", "0", 1);
- execv(arg[0], arg);
- plog("can't execv(%s,...): %s", arg[0], strerror(errno));
- exit(1);
- default:
- /* father */
- _pluto_pid = pid;
- for (i = 0; i < 500 && _pluto_pid; i++)
- {
- /* wait for pluto for a maximum of 500 x 20 ms = 10 s */
- usleep(20000);
- if (stat(PLUTO_CTL_FILE, &stb) == 0)
- {
- plog("pluto (%d) started after %d ms", _pluto_pid, 20*(i+1));
- if (cfg->setup.postpluto)
- {
- ignore_result(system(cfg->setup.postpluto));
- }
- return 0;
- }
- }
- if (_pluto_pid)
- {
- /* If pluto is started but with no ctl file, stop it */
- plog("pluto too long to start... - kill kill");
- for (i = 0; i < 20 && (pid = _pluto_pid) != 0; i++)
- {
- if (i < 10)
- {
- kill(pid, SIGTERM);
- }
- else
- {
- kill(pid, SIGKILL);
- }
- usleep(20000); /* sleep for 20 ms */
- }
- }
- else
- {
- plog("pluto refused to be started");
- }
- return -1;
- }
- }
- return -1;
-}
diff --git a/src/starter/invokepluto.h b/src/starter/invokepluto.h
deleted file mode 100644
index c87f50c2a..000000000
--- a/src/starter/invokepluto.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* strongSwan pluto launcher
- * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security
- *
- * 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.
- */
-
-#ifndef _STARTER_PLUTO_H_
-#define _STARTER_PLUTO_H_
-
-#define PLUTO_RESTART_DELAY 5
-
-extern void starter_pluto_sigchild (pid_t pid, int status);
-extern pid_t starter_pluto_pid (void);
-extern int starter_stop_pluto (void);
-extern int starter_start_pluto (struct starter_config *cfg, bool no_fork, bool attach_gdb);
-
-#endif /* _STARTER_PLUTO_H_ */
-
diff --git a/src/starter/ipsec.conf b/src/starter/ipsec.conf
index b1e5d5e0c..a33d68c0a 100644
--- a/src/starter/ipsec.conf
+++ b/src/starter/ipsec.conf
@@ -3,20 +3,14 @@
# basic configuration
config setup
- # plutodebug=all
- # crlcheckinterval=600
# strictcrlpolicy=yes
- # cachecrls=yes
- # nat_traversal=yes
- # charonstart=no
- # plutostart=no
+ # uniqueids = no
# Add connections here.
# Sample VPN connections
#conn sample-self-signed
-# left=%defaultroute
# leftsubnet=10.1.0.0/16
# leftcert=selfCert.der
# leftsendcert=never
@@ -26,11 +20,9 @@ config setup
# auto=start
#conn sample-with-ca-cert
-# left=%defaultroute
# leftsubnet=10.1.0.0/16
# leftcert=myCert.pem
# right=192.168.0.2
# rightsubnet=10.2.0.0/16
# rightid="C=CH, O=Linux strongSwan CN=peer name"
-# keyexchange=ikev2
# auto=start
diff --git a/src/starter/keywords.c b/src/starter/keywords.c
index edb55ae7f..7615a81d2 100644
--- a/src/starter/keywords.c
+++ b/src/starter/keywords.c
@@ -30,7 +30,7 @@ error "gperf generated tables don't work with this execution character set. Plea
#endif
-/* strongSwan keywords
+/*
* Copyright (C) 2005 Andreas Steffen
* Hochschule fuer Technik Rapperswil, Switzerland
*
@@ -54,12 +54,12 @@ struct kw_entry {
kw_token_t token;
};
-#define TOTAL_KEYWORDS 131
+#define TOTAL_KEYWORDS 134
#define MIN_WORD_LENGTH 3
#define MAX_WORD_LENGTH 17
#define MIN_HASH_VALUE 9
-#define MAX_HASH_VALUE 246
-/* maximum key range = 238, duplicates = 0 */
+#define MAX_HASH_VALUE 220
+/* maximum key range = 212, duplicates = 0 */
#ifdef __GNUC__
__inline
@@ -75,32 +75,32 @@ hash (str, len)
{
static const unsigned char asso_values[] =
{
- 247, 247, 247, 247, 247, 247, 247, 247, 247, 247,
- 247, 247, 247, 247, 247, 247, 247, 247, 247, 247,
- 247, 247, 247, 247, 247, 247, 247, 247, 247, 247,
- 247, 247, 247, 247, 247, 247, 247, 247, 247, 247,
- 247, 247, 247, 247, 247, 247, 247, 247, 247, 12,
- 126, 247, 247, 247, 247, 247, 247, 247, 247, 247,
- 247, 247, 247, 247, 247, 247, 247, 247, 247, 247,
- 247, 247, 247, 247, 247, 247, 247, 247, 247, 247,
- 247, 247, 247, 247, 247, 247, 247, 247, 247, 247,
- 247, 247, 247, 247, 247, 51, 247, 11, 1, 92,
- 43, 0, 6, 0, 110, 0, 247, 120, 56, 37,
- 27, 72, 43, 1, 16, 0, 5, 75, 1, 247,
- 247, 11, 5, 247, 247, 247, 247, 247, 247, 247,
- 247, 247, 247, 247, 247, 247, 247, 247, 247, 247,
- 247, 247, 247, 247, 247, 247, 247, 247, 247, 247,
- 247, 247, 247, 247, 247, 247, 247, 247, 247, 247,
- 247, 247, 247, 247, 247, 247, 247, 247, 247, 247,
- 247, 247, 247, 247, 247, 247, 247, 247, 247, 247,
- 247, 247, 247, 247, 247, 247, 247, 247, 247, 247,
- 247, 247, 247, 247, 247, 247, 247, 247, 247, 247,
- 247, 247, 247, 247, 247, 247, 247, 247, 247, 247,
- 247, 247, 247, 247, 247, 247, 247, 247, 247, 247,
- 247, 247, 247, 247, 247, 247, 247, 247, 247, 247,
- 247, 247, 247, 247, 247, 247, 247, 247, 247, 247,
- 247, 247, 247, 247, 247, 247, 247, 247, 247, 247,
- 247, 247, 247, 247, 247, 247
+ 221, 221, 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221, 221, 62,
+ 117, 221, 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 0, 221, 27, 0, 79,
+ 26, 0, 6, 0, 92, 0, 221, 44, 58, 36,
+ 36, 73, 33, 5, 16, 0, 7, 87, 0, 221,
+ 221, 11, 3, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221
};
register int hval = len;
@@ -123,166 +123,167 @@ hash (str, len)
static const struct kw_entry wordlist[] =
{
- {"pfs", KW_PFS},
- {"right", KW_RIGHT},
+ {"pfs", KW_PFS_DEPRECATED},
+ {"aggressive", KW_AGGRESSIVE},
{"rightgroups", KW_RIGHTGROUPS},
+ {"right", KW_RIGHT},
{"lifetime", KW_KEYLIFE},
{"left", KW_LEFT},
{"rightsubnet", KW_RIGHTSUBNET},
{"rightikeport", KW_RIGHTIKEPORT},
{"rightsendcert", KW_RIGHTSENDCERT},
{"leftcert", KW_LEFTCERT},
- {"keep_alive", KW_KEEP_ALIVE},
{"keyingtries", KW_KEYINGTRIES},
- {"leftsendcert", KW_LEFTSENDCERT},
{"keylife", KW_KEYLIFE},
+ {"leftsendcert", KW_LEFTSENDCERT},
{"lifebytes", KW_LIFEBYTES},
- {"lifepackets", KW_LIFEPACKETS},
{"leftrsasigkey", KW_LEFTRSASIGKEY},
{"leftcertpolicy", KW_LEFTCERTPOLICY},
{"leftgroups", KW_LEFTGROUPS},
- {"leftca", KW_LEFTCA},
- {"rightallowany", KW_RIGHTALLOWANY},
- {"uniqueids", KW_UNIQUEIDS},
- {"leftprotoport", KW_LEFTPROTOPORT},
+ {"rightid", KW_RIGHTID},
+ {"rightdns", KW_RIGHTDNS},
+ {"me_peerid", KW_ME_PEERID},
+ {"reqid", KW_REQID},
+ {"keep_alive", KW_SETUP_DEPRECATED},
{"rightrsasigkey", KW_RIGHTRSASIGKEY},
- {"virtual_private", KW_VIRTUAL_PRIVATE},
+ {"leftprotoport", KW_LEFTPROTOPORT},
{"certuribase", KW_CERTURIBASE},
- {"rightsubnetwithin", KW_RIGHTSUBNETWITHIN},
- {"interfaces", KW_INTERFACES},
- {"reqid", KW_REQID},
- {"rightid", KW_RIGHTID},
- {"strictcrlpolicy", KW_STRICTCRLPOLICY},
+ {"lifepackets", KW_LIFEPACKETS},
+ {"uniqueids", KW_UNIQUEIDS},
{"rightsourceip", KW_RIGHTSOURCEIP},
+ {"ike", KW_IKE},
{"type", KW_TYPE},
- {"inactivity", KW_INACTIVITY},
- {"leftnexthop", KW_LEFTNEXTHOP},
- {"mark_in", KW_MARK_IN},
+ {"leftdns", KW_LEFTDNS},
+ {"leftnexthop", KW_LEFT_DEPRECATED},
+ {"rightallowany", KW_RIGHTALLOWANY},
+ {"rightsubnetwithin", KW_RIGHTSUBNET},
{"rightprotoport", KW_RIGHTPROTOPORT},
- {"margintime", KW_REKEYMARGIN},
- {"marginbytes", KW_MARGINBYTES},
- {"marginpackets", KW_MARGINPACKETS},
- {"leftnatip", KW_LEFTNATIP},
{"mediated_by", KW_MEDIATED_BY},
- {"ldapbase", KW_LDAPBASE},
+ {"strictcrlpolicy", KW_STRICTCRLPOLICY},
+ {"virtual_private", KW_SETUP_DEPRECATED},
+ {"interfaces", KW_SETUP_DEPRECATED},
+ {"rekey", KW_REKEY},
+ {"ikelifetime", KW_IKELIFETIME},
+ {"rekeyfuzz", KW_REKEYFUZZ},
+ {"leftid", KW_LEFTID},
+ {"leftca", KW_LEFTCA},
+ {"leftikeport", KW_LEFTIKEPORT},
+ {"esp", KW_ESP},
{"leftfirewall", KW_LEFTFIREWALL},
{"rightfirewall", KW_RIGHTFIREWALL},
- {"crluri", KW_CRLURI},
- {"mobike", KW_MOBIKE},
- {"rightnatip", KW_RIGHTNATIP},
- {"rightnexthop", KW_RIGHTNEXTHOP},
{"mediation", KW_MEDIATION},
- {"leftallowany", KW_LEFTALLOWANY},
+ {"mobike", KW_MOBIKE},
+ {"crluri", KW_CRLURI},
+ {"rightnexthop", KW_RIGHT_DEPRECATED},
+ {"inactivity", KW_INACTIVITY},
{"leftupdown", KW_LEFTUPDOWN},
- {"overridemtu", KW_OVERRIDEMTU},
- {"aaa_identity", KW_AAA_IDENTITY},
- {"esp", KW_ESP},
- {"crluri1", KW_CRLURI},
+ {"mark_in", KW_MARK_IN},
+ {"leftallowany", KW_LEFTALLOWANY},
+ {"ldapbase", KW_CA_DEPRECATED},
+ {"margintime", KW_REKEYMARGIN},
+ {"marginbytes", KW_MARGINBYTES},
+ {"mark", KW_MARK},
+ {"marginpackets", KW_MARGINPACKETS},
{"lefthostaccess", KW_LEFTHOSTACCESS},
- {"leftsubnet", KW_LEFTSUBNET},
- {"leftid", KW_LEFTID},
- {"forceencaps", KW_FORCEENCAPS},
- {"eap", KW_EAP},
- {"nat_traversal", KW_NAT_TRAVERSAL},
- {"me_peerid", KW_ME_PEERID},
+ {"klipsdebug", KW_SETUP_DEPRECATED},
{"rightcert", KW_RIGHTCERT},
- {"installpolicy", KW_INSTALLPOLICY},
- {"authby", KW_AUTHBY},
- {"klipsdebug", KW_KLIPSDEBUG},
- {"rightca", KW_RIGHTCA},
- {"mark_out", KW_MARK_OUT},
- {"rightupdown", KW_RIGHTUPDOWN},
+ {"eap", KW_CONN_DEPRECATED},
+ {"overridemtu", KW_SETUP_DEPRECATED},
+ {"forceencaps", KW_FORCEENCAPS},
{"keyexchange", KW_KEYEXCHANGE},
{"ocspuri", KW_OCSPURI},
- {"compress", KW_COMPRESS},
+ {"aaa_identity", KW_AAA_IDENTITY},
+ {"force_keepalive", KW_SETUP_DEPRECATED},
{"rightcertpolicy", KW_RIGHTCERTPOLICY},
- {"cacert", KW_CACERT},
- {"eap_identity", KW_EAP_IDENTITY},
- {"hidetos", KW_HIDETOS},
- {"ike", KW_IKE},
- {"leftsubnetwithin", KW_LEFTSUBNETWITHIN},
+ {"hidetos", KW_SETUP_DEPRECATED},
{"righthostaccess", KW_RIGHTHOSTACCESS},
- {"packetdefault", KW_PACKETDEFAULT},
+ {"eap_identity", KW_EAP_IDENTITY},
+ {"leftsubnet", KW_LEFTSUBNET},
{"dpdaction", KW_DPDACTION},
- {"ocspuri1", KW_OCSPURI},
- {"pfsgroup", KW_PFSGROUP},
- {"rightauth", KW_RIGHTAUTH},
- {"also", KW_ALSO},
+ {"dpdtimeout", KW_DPDTIMEOUT},
+ {"rightca", KW_RIGHTCA},
+ {"compress", KW_COMPRESS},
+ {"installpolicy", KW_INSTALLPOLICY},
+ {"pfsgroup", KW_PFS_DEPRECATED},
+ {"nat_traversal", KW_SETUP_DEPRECATED},
+ {"authby", KW_AUTHBY},
{"leftsourceip", KW_LEFTSOURCEIP},
{"rightid2", KW_RIGHTID2},
- {"dumpdir", KW_DUMPDIR},
- {"rekey", KW_REKEY},
- {"ikelifetime", KW_IKELIFETIME},
- {"dpdtimeout", KW_DPDTIMEOUT},
- {"ldaphost", KW_LDAPHOST},
- {"rekeyfuzz", KW_REKEYFUZZ},
+ {"cacert", KW_CACERT},
+ {"rekeymargin", KW_REKEYMARGIN},
+ {"rightauth", KW_RIGHTAUTH},
+ {"rightgroups2", KW_RIGHTGROUPS2},
+ {"mark_out", KW_MARK_OUT},
{"leftcert2", KW_LEFTCERT2},
- {"leftikeport", KW_LEFTIKEPORT},
- {"crlcheckinterval", KW_CRLCHECKINTERVAL},
- {"plutostderrlog", KW_PLUTOSTDERRLOG},
- {"plutostart", KW_PLUTOSTART},
- {"rightauth2", KW_RIGHTAUTH2},
- {"leftca2", KW_LEFTCA2},
- {"mark", KW_MARK},
- {"force_keepalive", KW_FORCE_KEEPALIVE},
- {"auto", KW_AUTO},
- {"charondebug", KW_CHARONDEBUG},
+ {"packetdefault", KW_SETUP_DEPRECATED},
+ {"rightupdown", KW_RIGHTUPDOWN},
+ {"also", KW_ALSO},
{"dpddelay", KW_DPDDELAY},
{"xauth_identity", KW_XAUTH_IDENTITY},
- {"charonstart", KW_CHARONSTART},
- {"fragicmp", KW_FRAGICMP},
- {"prepluto", KW_PREPLUTO},
- {"closeaction", KW_CLOSEACTION},
+ {"ldaphost", KW_CA_DEPRECATED},
+ {"crluri1", KW_CRLURI},
+ {"leftsubnetwithin", KW_LEFTSUBNET},
+ {"dumpdir", KW_SETUP_DEPRECATED},
+ {"crlcheckinterval", KW_SETUP_DEPRECATED},
+ {"leftgroups2", KW_LEFTGROUPS2},
+ {"rightauth2", KW_RIGHTAUTH2},
{"leftid2", KW_LEFTID2},
- {"plutodebug", KW_PLUTODEBUG},
+ {"leftca2", KW_LEFTCA2},
+ {"plutostderrlog", KW_SETUP_DEPRECATED},
+ {"plutostart", KW_SETUP_DEPRECATED},
+ {"fragicmp", KW_SETUP_DEPRECATED},
+ {"ocspuri1", KW_OCSPURI},
+ {"charondebug", KW_CHARONDEBUG},
{"tfc", KW_TFC},
- {"auth", KW_AUTH},
- {"rekeymargin", KW_REKEYMARGIN},
+ {"auto", KW_AUTO},
+ {"charonstart", KW_SETUP_DEPRECATED},
+ {"plutodebug", KW_SETUP_DEPRECATED},
{"modeconfig", KW_MODECONFIG},
+ {"prepluto", KW_SETUP_DEPRECATED},
+ {"nocrsend", KW_SETUP_DEPRECATED},
+ {"auth", KW_AUTH},
{"leftauth", KW_LEFTAUTH},
- {"xauth", KW_XAUTH},
{"cachecrls", KW_CACHECRLS},
+ {"pkcs11module", KW_PKCS11_DEPRECATED},
{"crluri2", KW_CRLURI2},
- {"postpluto", KW_POSTPLUTO},
- {"nocrsend", KW_NOCRSEND},
- {"leftauth2", KW_LEFTAUTH2},
+ {"pkcs11initargs", KW_PKCS11_DEPRECATED},
+ {"pkcs11keepstate", KW_PKCS11_DEPRECATED},
{"rightca2", KW_RIGHTCA2},
+ {"closeaction", KW_CLOSEACTION},
{"rightcert2", KW_RIGHTCERT2},
- {"pkcs11module", KW_PKCS11MODULE},
+ {"pkcs11proxy", KW_PKCS11_DEPRECATED},
+ {"xauth", KW_XAUTH},
+ {"postpluto", KW_SETUP_DEPRECATED},
{"reauth", KW_REAUTH},
- {"pkcs11initargs", KW_PKCS11INITARGS},
- {"pkcs11keepstate", KW_PKCS11KEEPSTATE},
- {"ocspuri2", KW_OCSPURI2},
- {"pkcs11proxy", KW_PKCS11PROXY}
+ {"leftauth2", KW_LEFTAUTH2},
+ {"ocspuri2", KW_OCSPURI2}
};
static const short lookup[] =
{
-1, -1, -1, -1, -1, -1, -1, -1, -1, 0,
- 1, 2, -1, -1, 3, 4, 5, 6, 7, 8,
- -1, 9, 10, 11, 12, -1, 13, -1, 14, -1,
- 15, 16, 17, -1, 18, 19, 20, -1, -1, -1,
- 21, 22, 23, 24, 25, -1, -1, -1, 26, 27,
- 28, -1, 29, -1, -1, -1, 30, -1, 31, 32,
- 33, 34, 35, -1, 36, 37, -1, 38, -1, 39,
- 40, -1, -1, 41, 42, 43, -1, -1, 44, 45,
- 46, -1, 47, -1, 48, 49, 50, 51, 52, 53,
- -1, 54, 55, -1, -1, -1, 56, -1, 57, 58,
- 59, 60, -1, 61, -1, -1, 62, 63, 64, 65,
- 66, -1, 67, 68, 69, 70, -1, 71, 72, 73,
- 74, -1, 75, 76, 77, 78, 79, 80, 81, 82,
- 83, -1, 84, 85, 86, 87, 88, 89, 90, 91,
- 92, 93, 94, -1, 95, 96, 97, 98, -1, -1,
- 99, 100, -1, -1, 101, -1, 102, -1, -1, 103,
- -1, 104, 105, -1, 106, -1, -1, -1, -1, -1,
- 107, 108, -1, -1, -1, -1, -1, 109, -1, -1,
- -1, -1, 110, -1, 111, -1, -1, -1, -1, -1,
- -1, -1, -1, 112, 113, 114, -1, 115, -1, 116,
- -1, 117, -1, -1, 118, 119, -1, -1, -1, 120,
- -1, -1, -1, -1, -1, 121, 122, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 123, -1, 124, -1,
- -1, -1, -1, -1, -1, -1, 125, 126, 127, 128,
- -1, -1, 129, -1, -1, -1, 130
+ 1, 2, 3, -1, 4, -1, -1, 5, 6, 7,
+ 8, 9, 10, -1, 11, 12, 13, -1, -1, -1,
+ 14, 15, 16, 17, 18, 19, 20, 21, -1, -1,
+ -1, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 31, 32, -1, 33, 34, 35, 36, -1, 37, 38,
+ 39, 40, 41, -1, 42, -1, 43, -1, 44, 45,
+ -1, -1, -1, -1, -1, -1, 46, 47, 48, 49,
+ 50, 51, -1, -1, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, -1, 65, -1,
+ 66, 67, 68, 69, 70, 71, 72, 73, -1, 74,
+ 75, 76, 77, 78, -1, -1, -1, 79, 80, -1,
+ 81, 82, 83, -1, 84, 85, 86, 87, 88, 89,
+ -1, 90, 91, 92, 93, 94, 95, -1, -1, 96,
+ -1, 97, -1, 98, -1, 99, 100, -1, 101, -1,
+ 102, -1, -1, -1, 103, -1, 104, 105, -1, 106,
+ -1, -1, 107, 108, -1, 109, 110, 111, -1, -1,
+ -1, 112, -1, 113, -1, -1, -1, -1, -1, -1,
+ -1, 114, 115, -1, 116, -1, 117, -1, -1, -1,
+ 118, -1, -1, 119, 120, -1, -1, 121, 122, 123,
+ 124, -1, -1, -1, 125, 126, 127, 128, -1, -1,
+ -1, 129, -1, 130, -1, -1, -1, 131, -1, 132,
+ 133
};
#ifdef __GNUC__
diff --git a/src/starter/keywords.h b/src/starter/keywords.h
index 02be919ea..537bceb07 100644
--- a/src/starter/keywords.h
+++ b/src/starter/keywords.h
@@ -1,4 +1,4 @@
-/* strongSwan keywords
+/*
* Copyright (C) 2005 Andreas Steffen
* Hochschule fuer Technik Rapperswil, Switzerland
*
@@ -18,58 +18,26 @@
typedef enum {
/* config setup keywords */
- KW_INTERFACES,
- KW_DUMPDIR,
- KW_CHARONSTART,
- KW_PLUTOSTART,
-
- /* pluto/charon keywords */
- KW_PLUTODEBUG,
KW_CHARONDEBUG,
- KW_PREPLUTO,
- KW_POSTPLUTO,
- KW_PLUTOSTDERRLOG,
KW_UNIQUEIDS,
- KW_OVERRIDEMTU,
- KW_CRLCHECKINTERVAL,
KW_CACHECRLS,
KW_STRICTCRLPOLICY,
- KW_NOCRSEND,
- KW_NAT_TRAVERSAL,
- KW_KEEP_ALIVE,
- KW_FORCE_KEEPALIVE,
- KW_VIRTUAL_PRIVATE,
- KW_PKCS11MODULE,
- KW_PKCS11INITARGS,
- KW_PKCS11KEEPSTATE,
- KW_PKCS11PROXY,
-
-#define KW_PLUTO_FIRST KW_PLUTODEBUG
-#define KW_PLUTO_LAST KW_PKCS11PROXY
-
- /* KLIPS keywords */
- KW_KLIPSDEBUG,
- KW_FRAGICMP,
- KW_PACKETDEFAULT,
- KW_HIDETOS,
-
-#define KW_KLIPS_FIRST KW_KLIPSDEBUG
-#define KW_KLIPS_LAST KW_HIDETOS
-
-#define KW_SETUP_FIRST KW_INTERFACES
-#define KW_SETUP_LAST KW_HIDETOS
+ KW_PKCS11_DEPRECATED,
+ KW_SETUP_DEPRECATED,
+
+#define KW_SETUP_FIRST KW_CHARONDEBUG
+#define KW_SETUP_LAST KW_SETUP_DEPRECATED
/* conn section keywords */
KW_CONN_NAME,
KW_CONN_SETUP,
KW_KEYEXCHANGE,
KW_TYPE,
- KW_PFS,
KW_COMPRESS,
KW_INSTALLPOLICY,
+ KW_AGGRESSIVE,
KW_AUTH,
KW_AUTHBY,
- KW_EAP,
KW_EAP_IDENTITY,
KW_AAA_IDENTITY,
KW_MOBIKE,
@@ -87,7 +55,6 @@ typedef enum {
KW_REAUTH,
KW_IKE,
KW_ESP,
- KW_PFSGROUP,
KW_DPDDELAY,
KW_DPDTIMEOUT,
KW_DPDACTION,
@@ -104,34 +71,33 @@ typedef enum {
KW_MARK_IN,
KW_MARK_OUT,
KW_TFC,
+ KW_PFS_DEPRECATED,
+ KW_CONN_DEPRECATED,
#define KW_CONN_FIRST KW_CONN_SETUP
-#define KW_CONN_LAST KW_TFC
+#define KW_CONN_LAST KW_CONN_DEPRECATED
- /* ca section keywords */
+ /* ca section keywords */
KW_CA_NAME,
KW_CA_SETUP,
KW_CACERT,
- KW_LDAPHOST,
- KW_LDAPBASE,
KW_CRLURI,
KW_CRLURI2,
KW_OCSPURI,
KW_OCSPURI2,
KW_CERTURIBASE,
+ KW_CA_DEPRECATED,
#define KW_CA_FIRST KW_CA_SETUP
-#define KW_CA_LAST KW_CERTURIBASE
+#define KW_CA_LAST KW_CA_DEPRECATED
- /* end keywords */
+ /* end keywords */
KW_HOST,
KW_IKEPORT,
- KW_NEXTHOP,
KW_SUBNET,
- KW_SUBNETWITHIN,
KW_PROTOPORT,
KW_SOURCEIP,
- KW_NATIP,
+ KW_DNS,
KW_FIREWALL,
KW_HOSTACCESS,
KW_ALLOWANY,
@@ -148,20 +114,19 @@ typedef enum {
KW_CA,
KW_CA2,
KW_GROUPS,
- KW_IFACE,
+ KW_GROUPS2,
+ KW_END_DEPRECATED,
#define KW_END_FIRST KW_HOST
-#define KW_END_LAST KW_IFACE
+#define KW_END_LAST KW_END_DEPRECATED
- /* left end keywords */
+ /* left end keywords */
KW_LEFT,
KW_LEFTIKEPORT,
- KW_LEFTNEXTHOP,
KW_LEFTSUBNET,
- KW_LEFTSUBNETWITHIN,
KW_LEFTPROTOPORT,
KW_LEFTSOURCEIP,
- KW_LEFTNATIP,
+ KW_LEFTDNS,
KW_LEFTFIREWALL,
KW_LEFTHOSTACCESS,
KW_LEFTALLOWANY,
@@ -178,19 +143,19 @@ typedef enum {
KW_LEFTCA,
KW_LEFTCA2,
KW_LEFTGROUPS,
+ KW_LEFTGROUPS2,
+ KW_LEFT_DEPRECATED,
#define KW_LEFT_FIRST KW_LEFT
-#define KW_LEFT_LAST KW_LEFTGROUPS
+#define KW_LEFT_LAST KW_LEFT_DEPRECATED
- /* right end keywords */
+ /* right end keywords */
KW_RIGHT,
KW_RIGHTIKEPORT,
- KW_RIGHTNEXTHOP,
KW_RIGHTSUBNET,
- KW_RIGHTSUBNETWITHIN,
KW_RIGHTPROTOPORT,
KW_RIGHTSOURCEIP,
- KW_RIGHTNATIP,
+ KW_RIGHTDNS,
KW_RIGHTFIREWALL,
KW_RIGHTHOSTACCESS,
KW_RIGHTALLOWANY,
@@ -207,13 +172,15 @@ typedef enum {
KW_RIGHTCA,
KW_RIGHTCA2,
KW_RIGHTGROUPS,
+ KW_RIGHTGROUPS2,
+ KW_RIGHT_DEPRECATED,
#define KW_RIGHT_FIRST KW_RIGHT
-#define KW_RIGHT_LAST KW_RIGHTGROUPS
+#define KW_RIGHT_LAST KW_RIGHT_DEPRECATED
/* general section keywords */
KW_ALSO,
- KW_AUTO
+ KW_AUTO,
} kw_token_t;
diff --git a/src/starter/keywords.txt b/src/starter/keywords.txt
index 548fa2f70..8366f5209 100644
--- a/src/starter/keywords.txt
+++ b/src/starter/keywords.txt
@@ -1,5 +1,5 @@
%{
-/* strongSwan keywords
+/*
* Copyright (C) 2005 Andreas Steffen
* Hochschule fuer Technik Rapperswil, Switzerland
*
@@ -24,61 +24,37 @@ struct kw_entry {
kw_token_t token;
};
%%
-interfaces, KW_INTERFACES
-dumpdir, KW_DUMPDIR
-charonstart, KW_CHARONSTART
-plutostart, KW_PLUTOSTART
-klipsdebug, KW_KLIPSDEBUG
-plutodebug, KW_PLUTODEBUG
+# regular keywords
charondebug, KW_CHARONDEBUG
-prepluto, KW_PREPLUTO
-postpluto, KW_POSTPLUTO
-plutostderrlog, KW_PLUTOSTDERRLOG
-fragicmp, KW_FRAGICMP
-packetdefault, KW_PACKETDEFAULT
-hidetos, KW_HIDETOS
uniqueids, KW_UNIQUEIDS
-overridemtu, KW_OVERRIDEMTU
-crlcheckinterval, KW_CRLCHECKINTERVAL
cachecrls, KW_CACHECRLS
strictcrlpolicy, KW_STRICTCRLPOLICY
-nocrsend, KW_NOCRSEND
-nat_traversal, KW_NAT_TRAVERSAL
-keep_alive, KW_KEEP_ALIVE
-force_keepalive, KW_FORCE_KEEPALIVE
-virtual_private, KW_VIRTUAL_PRIVATE
-eap, KW_EAP
-eap_identity, KW_EAP_IDENTITY
-aaa_identity, KW_AAA_IDENTITY
-mobike, KW_MOBIKE
-forceencaps, KW_FORCEENCAPS
-pkcs11module, KW_PKCS11MODULE
-pkcs11initargs, KW_PKCS11INITARGS
-pkcs11keepstate, KW_PKCS11KEEPSTATE
-pkcs11proxy, KW_PKCS11PROXY
keyexchange, KW_KEYEXCHANGE
type, KW_TYPE
-pfs, KW_PFS
compress, KW_COMPRESS
installpolicy, KW_INSTALLPOLICY
+aggressive, KW_AGGRESSIVE
auth, KW_AUTH
authby, KW_AUTHBY
+eap_identity, KW_EAP_IDENTITY
+aaa_identity, KW_AAA_IDENTITY
+mobike, KW_MOBIKE
+forceencaps, KW_FORCEENCAPS
+ikelifetime, KW_IKELIFETIME
+lifetime, KW_KEYLIFE
keylife, KW_KEYLIFE
rekeymargin, KW_REKEYMARGIN
-lifetime, KW_KEYLIFE
margintime, KW_REKEYMARGIN
lifebytes, KW_LIFEBYTES
marginbytes, KW_MARGINBYTES
lifepackets, KW_LIFEPACKETS
marginpackets, KW_MARGINPACKETS
-ikelifetime, KW_IKELIFETIME
keyingtries, KW_KEYINGTRIES
rekeyfuzz, KW_REKEYFUZZ
rekey, KW_REKEY
reauth, KW_REAUTH
-esp, KW_ESP
ike, KW_IKE
-pfsgroup, KW_PFSGROUP
+esp, KW_ESP
dpddelay, KW_DPDDELAY
dpdtimeout, KW_DPDTIMEOUT
dpdaction, KW_DPDACTION
@@ -96,8 +72,6 @@ mark_in, KW_MARK_IN
mark_out, KW_MARK_OUT
tfc, KW_TFC
cacert, KW_CACERT
-ldaphost, KW_LDAPHOST
-ldapbase, KW_LDAPBASE
crluri, KW_CRLURI
crluri1, KW_CRLURI
crluri2, KW_CRLURI2
@@ -107,20 +81,19 @@ ocspuri2, KW_OCSPURI2
certuribase, KW_CERTURIBASE
left, KW_LEFT
leftikeport, KW_LEFTIKEPORT
-leftnexthop, KW_LEFTNEXTHOP
leftsubnet, KW_LEFTSUBNET
-leftsubnetwithin, KW_LEFTSUBNETWITHIN
+leftsubnetwithin, KW_LEFTSUBNET
leftprotoport, KW_LEFTPROTOPORT
leftsourceip, KW_LEFTSOURCEIP
-leftnatip, KW_LEFTNATIP
+leftdns, KW_LEFTDNS
leftfirewall, KW_LEFTFIREWALL
lefthostaccess, KW_LEFTHOSTACCESS
leftallowany, KW_LEFTALLOWANY
leftupdown, KW_LEFTUPDOWN
-leftid, KW_LEFTID
-leftid2, KW_LEFTID2
leftauth, KW_LEFTAUTH
leftauth2, KW_LEFTAUTH2
+leftid, KW_LEFTID
+leftid2, KW_LEFTID2
leftrsasigkey, KW_LEFTRSASIGKEY
leftcert, KW_LEFTCERT
leftcert2, KW_LEFTCERT2
@@ -129,22 +102,22 @@ leftsendcert, KW_LEFTSENDCERT
leftca, KW_LEFTCA
leftca2, KW_LEFTCA2
leftgroups, KW_LEFTGROUPS
+leftgroups2, KW_LEFTGROUPS2
right, KW_RIGHT
rightikeport, KW_RIGHTIKEPORT
-rightnexthop, KW_RIGHTNEXTHOP
rightsubnet, KW_RIGHTSUBNET
-rightsubnetwithin, KW_RIGHTSUBNETWITHIN
+rightsubnetwithin, KW_RIGHTSUBNET
rightprotoport, KW_RIGHTPROTOPORT
rightsourceip, KW_RIGHTSOURCEIP
-rightnatip, KW_RIGHTNATIP
+rightdns, KW_RIGHTDNS
rightfirewall, KW_RIGHTFIREWALL
righthostaccess, KW_RIGHTHOSTACCESS
rightallowany, KW_RIGHTALLOWANY
rightupdown, KW_RIGHTUPDOWN
-rightid, KW_RIGHTID
-rightid2, KW_RIGHTID2
rightauth, KW_RIGHTAUTH
rightauth2, KW_RIGHTAUTH2
+rightid, KW_RIGHTID
+rightid2, KW_RIGHTID2
rightrsasigkey, KW_RIGHTRSASIGKEY
rightcert, KW_RIGHTCERT
rightcert2, KW_RIGHTCERT2
@@ -153,5 +126,37 @@ rightsendcert, KW_RIGHTSENDCERT
rightca, KW_RIGHTCA
rightca2, KW_RIGHTCA2
rightgroups, KW_RIGHTGROUPS
+rightgroups2, KW_RIGHTGROUPS2
also, KW_ALSO
auto, KW_AUTO
+# deprecated/removed keywords
+interfaces, KW_SETUP_DEPRECATED
+dumpdir, KW_SETUP_DEPRECATED
+charonstart, KW_SETUP_DEPRECATED
+plutostart, KW_SETUP_DEPRECATED
+klipsdebug, KW_SETUP_DEPRECATED
+plutodebug, KW_SETUP_DEPRECATED
+prepluto, KW_SETUP_DEPRECATED
+postpluto, KW_SETUP_DEPRECATED
+plutostderrlog, KW_SETUP_DEPRECATED
+fragicmp, KW_SETUP_DEPRECATED
+packetdefault, KW_SETUP_DEPRECATED
+hidetos, KW_SETUP_DEPRECATED
+overridemtu, KW_SETUP_DEPRECATED
+crlcheckinterval, KW_SETUP_DEPRECATED
+nocrsend, KW_SETUP_DEPRECATED
+nat_traversal, KW_SETUP_DEPRECATED
+keep_alive, KW_SETUP_DEPRECATED
+force_keepalive, KW_SETUP_DEPRECATED
+virtual_private, KW_SETUP_DEPRECATED
+pkcs11module, KW_PKCS11_DEPRECATED
+pkcs11initargs, KW_PKCS11_DEPRECATED
+pkcs11keepstate, KW_PKCS11_DEPRECATED
+pkcs11proxy, KW_PKCS11_DEPRECATED
+ldaphost, KW_CA_DEPRECATED
+ldapbase, KW_CA_DEPRECATED
+pfs, KW_PFS_DEPRECATED
+pfsgroup, KW_PFS_DEPRECATED
+eap, KW_CONN_DEPRECATED
+leftnexthop, KW_LEFT_DEPRECATED
+rightnexthop, KW_RIGHT_DEPRECATED
diff --git a/src/starter/klips.c b/src/starter/klips.c
index 79bd25c44..484b7e281 100644
--- a/src/starter/klips.c
+++ b/src/starter/klips.c
@@ -16,16 +16,12 @@
#include <sys/stat.h>
#include <stdlib.h>
-#include <freeswan.h>
-
-#include "../pluto/constants.h"
-#include "../pluto/defs.h"
-#include "../pluto/log.h"
+#include <library.h>
+#include <debug.h>
#include "files.h"
-bool
-starter_klips_init(void)
+bool starter_klips_init(void)
{
struct stat stb;
@@ -40,9 +36,7 @@ starter_klips_init(void)
/* now test again */
if (stat(PROC_KLIPS, &stb) != 0)
{
- DBG(DBG_CONTROL,
- DBG_log("kernel appears to lack the KLIPS IPsec stack")
- )
+ DBG2(DBG_APP, "kernel appears to lack the KLIPS IPsec stack");
return FALSE;
}
}
@@ -52,29 +46,25 @@ starter_klips_init(void)
ignore_result(system("modprobe -qv ipsec_blowfish"));
ignore_result(system("modprobe -qv ipsec_sha2"));
- DBG(DBG_CONTROL,
- DBG_log("Found KLIPS IPsec stack")
- )
-
+ DBG2(DBG_APP, "found KLIPS IPsec stack");
return TRUE;
}
-void
-starter_klips_cleanup(void)
+void starter_klips_cleanup(void)
{
if (system("type eroute > /dev/null 2>&1") == 0)
{
ignore_result(system("spi --clear"));
ignore_result(system("eroute --clear"));
}
- else if (system("type setkey > /dev/null 2>&1") == 0)
+ else if (system("type setkey > /dev/null 2>&1") == 0)
{
ignore_result(system("setkey -F"));
ignore_result(system("setkey -FP"));
}
else
{
- plog("WARNING: cannot flush IPsec state/policy database");
+ DBG1(DBG_APP, "WARNING: cannot flush IPsec state/policy database");
}
}
diff --git a/src/starter/loglite.c b/src/starter/loglite.c
deleted file mode 100644
index c88b33bfd..000000000
--- a/src/starter/loglite.c
+++ /dev/null
@@ -1,297 +0,0 @@
-/* error logging functions
- * Copyright (C) 1997 Angelos D. Keromytis.
- * Copyright (C) 1998-2001 D. Hugh Redelmeier.
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <stdarg.h>
-#include <syslog.h>
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-#include <signal.h> /* used only if MSG_NOSIGNAL not defined */
-#include <libgen.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <freeswan.h>
-
-#include <constants.h>
-#include <defs.h>
-#include <log.h>
-#include <whack.h>
-
-#ifndef LOG_AUTHPRIV
-#define LOG_AUTHPRIV LOG_AUTH
-#endif
-
-bool
- log_to_stderr = FALSE, /* should log go to stderr? */
- log_to_syslog = TRUE; /* should log go to syslog? */
-
-void
-init_log(const char *program)
-{
- if (log_to_stderr)
- setbuf(stderr, NULL);
- if (log_to_syslog)
- openlog(program, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_AUTHPRIV);
-}
-
-void
-close_log(void)
-{
- if (log_to_syslog)
- closelog();
-}
-
-void
-plog(const char *message, ...)
-{
- va_list args;
- char m[LOG_WIDTH]; /* longer messages will be truncated */
-
- va_start(args, message);
- vsnprintf(m, sizeof(m), message, args);
- va_end(args);
-
- if (log_to_stderr)
- fprintf(stderr, "%s\n", m);
- if (log_to_syslog)
- syslog(LOG_WARNING, "%s", m);
-}
-
-void
-loglog(int mess_no, const char *message, ...)
-{
- va_list args;
- char m[LOG_WIDTH]; /* longer messages will be truncated */
-
- va_start(args, message);
- vsnprintf(m, sizeof(m), message, args);
- va_end(args);
-
- if (log_to_stderr)
- fprintf(stderr, "%s\n", m);
- if (log_to_syslog)
- syslog(LOG_WARNING, "%s", m);
-}
-
-void
-log_errno_routine(int e, const char *message, ...)
-{
- va_list args;
- char m[LOG_WIDTH]; /* longer messages will be truncated */
-
- va_start(args, message);
- vsnprintf(m, sizeof(m), message, args);
- va_end(args);
-
- if (log_to_stderr)
- fprintf(stderr, "ERROR: %s. Errno %d: %s\n", m, e, strerror(e));
- if (log_to_syslog)
- syslog(LOG_ERR, "ERROR: %s. Errno %d: %s", m, e, strerror(e));
-}
-
-void
-exit_log(const char *message, ...)
-{
- va_list args;
- char m[LOG_WIDTH]; /* longer messages will be truncated */
-
- va_start(args, message);
- vsnprintf(m, sizeof(m), message, args);
- va_end(args);
-
- if (log_to_stderr)
- fprintf(stderr, "FATAL ERROR: %s\n", m);
- if (log_to_syslog)
- syslog(LOG_ERR, "FATAL ERROR: %s", m);
- exit(1);
-}
-
-void
-exit_log_errno_routine(int e, const char *message, ...)
-{
- va_list args;
- char m[LOG_WIDTH]; /* longer messages will be truncated */
-
- va_start(args, message);
- vsnprintf(m, sizeof(m), message, args);
- va_end(args);
-
- if (log_to_stderr)
- fprintf(stderr, "FATAL ERROR: %s. Errno %d: %s\n", m, e, strerror(e));
- if (log_to_syslog)
- syslog(LOG_ERR, "FATAL ERROR: %s. Errno %d: %s", m, e, strerror(e));
- exit(1);
-}
-
-void
-whack_log(int mess_no, const char *message, ...)
-{
- va_list args;
- char m[LOG_WIDTH]; /* longer messages will be truncated */
-
- va_start(args, message);
- vsnprintf(m, sizeof(m), message, args);
- va_end(args);
-
- fprintf(stderr, "%s\n", m);
-}
-
-/* Build up a diagnostic in a static buffer.
- * Although this would be a generally useful function, it is very
- * hard to come up with a discipline that prevents different uses
- * from interfering. It is intended that by limiting it to building
- * diagnostics, we will avoid this problem.
- * Juggling is performed to allow an argument to be a previous
- * result: the new string may safely depend on the old one. This
- * restriction is not checked in any way: violators will produce
- * confusing results (without crashing!).
- */
-char diag_space[sizeof(diag_space)];
-
-err_t
-builddiag(const char *fmt, ...)
-{
- static char diag_space[LOG_WIDTH]; /* longer messages will be truncated */
- char t[sizeof(diag_space)]; /* build result here first */
- va_list args;
-
- va_start(args, fmt);
- t[0] = '\0'; /* in case nothing terminates string */
- vsnprintf(t, sizeof(t), fmt, args);
- va_end(args);
- strcpy(diag_space, t);
- return diag_space;
-}
-
-/* Debugging message support */
-
-#ifdef DEBUG
-
-void
-switch_fail(int n, const char *file_str, unsigned long line_no)
-{
- char buf[30];
-
- snprintf(buf, sizeof(buf), "case %d unexpected", n);
- passert_fail(buf, file_str, line_no);
-}
-
-void
-passert_fail(const char *pred_str, const char *file_str, unsigned long line_no)
-{
- /* we will get a possibly unplanned prefix. Hope it works */
- loglog(RC_LOG_SERIOUS, "ASSERTION FAILED at %s:%lu: %s", file_str, line_no, pred_str);
- abort(); /* exiting correctly doesn't always work */
-}
-
-lset_t
- base_debugging = DBG_NONE, /* default to reporting nothing */
- cur_debugging = DBG_NONE;
-
-void
-pexpect_log(const char *pred_str, const char *file_str, unsigned long line_no)
-{
- /* we will get a possibly unplanned prefix. Hope it works */
- loglog(RC_LOG_SERIOUS, "EXPECTATION FAILED at %s:%lu: %s", file_str, line_no, pred_str);
-}
-
-/* log a debugging message (prefixed by "| ") */
-
-void
-DBG_log(const char *message, ...)
-{
- va_list args;
- char m[LOG_WIDTH]; /* longer messages will be truncated */
-
- va_start(args, message);
- vsnprintf(m, sizeof(m), message, args);
- va_end(args);
-
- if (log_to_stderr)
- fprintf(stderr, "| %s\n", m);
- if (log_to_syslog)
- syslog(LOG_DEBUG, "| %s", m);
-}
-
-/* dump raw bytes in hex to stderr (for lack of any better destination) */
-
-void
-DBG_dump(const char *label, const void *p, size_t len)
-{
-# define DUMP_LABEL_WIDTH 20 /* arbitrary modest boundary */
-# define DUMP_WIDTH (4 * (1 + 4 * 3) + 1)
- char buf[DUMP_LABEL_WIDTH + DUMP_WIDTH];
- char *bp;
- const unsigned char *cp = p;
-
- bp = buf;
-
- if (label != NULL && label[0] != '\0')
- {
- /* Handle the label. Care must be taken to avoid buffer overrun. */
- size_t llen = strlen(label);
-
- if (llen + 1 > sizeof(buf))
- {
- DBG_log("%s", label);
- }
- else
- {
- strcpy(buf, label);
- if (buf[llen-1] == '\n')
- {
- buf[llen-1] = '\0'; /* get rid of newline */
- DBG_log("%s", buf);
- }
- else if (llen < DUMP_LABEL_WIDTH)
- {
- bp = buf + llen;
- }
- else
- {
- DBG_log("%s", buf);
- }
- }
- }
-
- do {
- int i, j;
-
- for (i = 0; len!=0 && i!=4; i++)
- {
- *bp++ = ' ';
- for (j = 0; len!=0 && j!=4; len--, j++)
- {
- static const char hexdig[] = "0123456789abcdef";
-
- *bp++ = ' ';
- *bp++ = hexdig[(*cp >> 4) & 0xF];
- *bp++ = hexdig[*cp & 0xF];
- cp++;
- }
- }
- *bp = '\0';
- DBG_log("%s", buf);
- bp = buf;
- } while (len != 0);
-# undef DUMP_LABEL_WIDTH
-# undef DUMP_WIDTH
-}
-
-#endif /* DEBUG */
diff --git a/src/starter/netkey.c b/src/starter/netkey.c
index 6646195cb..25f68e505 100644
--- a/src/starter/netkey.c
+++ b/src/starter/netkey.c
@@ -16,17 +16,13 @@
#include <sys/stat.h>
#include <stdlib.h>
-#include <freeswan.h>
+#include <library.h>
#include <hydra.h>
-
-#include "../pluto/constants.h"
-#include "../pluto/defs.h"
-#include "../pluto/log.h"
+#include <debug.h>
#include "files.h"
-bool
-starter_netkey_init(void)
+bool starter_netkey_init(void)
{
struct stat stb;
@@ -41,9 +37,7 @@ starter_netkey_init(void)
/* now test again */
if (stat(PROC_NETKEY, &stb) != 0)
{
- DBG(DBG_CONTROL,
- DBG_log("kernel appears to lack the native netkey IPsec stack")
- )
+ DBG2(DBG_APP, "kernel appears to lack the native netkey IPsec stack");
return FALSE;
}
}
@@ -58,15 +52,19 @@ starter_netkey_init(void)
ignore_result(system("modprobe -qv xfrm_user"));
}
- DBG(DBG_CONTROL,
- DBG_log("Found netkey IPsec stack")
- )
+ DBG2(DBG_APP, "found netkey IPsec stack");
return TRUE;
}
-void
-starter_netkey_cleanup(void)
+void starter_netkey_cleanup(void)
{
+ if (!lib->plugins->load(lib->plugins, NULL,
+ 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/parser.c b/src/starter/parser.c
index ef668027d..beb752a51 100644
--- a/src/starter/parser.c
+++ b/src/starter/parser.c
@@ -88,11 +88,9 @@
#include <stdlib.h>
#include <string.h>
-#include <freeswan.h>
+#include <library.h>
+#include <debug.h>
-#include "../pluto/constants.h"
-#include "../pluto/defs.h"
-#include "../pluto/log.h"
#include "ipsec-parser.h"
#define YYERROR_VERBOSE
@@ -123,7 +121,7 @@ extern kw_entry_t *in_word_set (char *str, unsigned int len);
/* Line 189 of yacc.c */
-#line 127 "parser.c"
+#line 125 "parser.c"
/* Enabling traces. */
#ifndef YYDEBUG
@@ -182,12 +180,12 @@ typedef union YYSTYPE
{
/* Line 214 of yacc.c */
-#line 54 "parser.y"
+#line 52 "parser.y"
char *s;
/* Line 214 of yacc.c */
-#line 191 "parser.c"
+#line 189 "parser.c"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
@@ -199,7 +197,7 @@ typedef union YYSTYPE
/* Line 264 of yacc.c */
-#line 203 "parser.c"
+#line 201 "parser.c"
#ifdef short
# undef short
@@ -487,8 +485,8 @@ static const yytype_int8 yyrhs[] =
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static const yytype_uint8 yyrline[] =
{
- 0, 65, 65, 66, 70, 75, 74, 80, 79, 96,
- 95, 111, 110, 116, 120, 121, 125, 150, 154
+ 0, 63, 63, 64, 68, 73, 72, 78, 77, 94,
+ 93, 109, 108, 114, 118, 119, 123, 148, 152
};
#endif
@@ -1402,7 +1400,7 @@ yyreduce:
case 4:
/* Line 1455 of yacc.c */
-#line 71 "parser.y"
+#line 69 "parser.y"
{
free((yyvsp[(2) - (3)].s));
}
@@ -1411,7 +1409,7 @@ yyreduce:
case 5:
/* Line 1455 of yacc.c */
-#line 75 "parser.y"
+#line 73 "parser.y"
{
_parser_kw = &(_parser_cfg->config_setup);
_parser_kw_last = NULL;
@@ -1421,11 +1419,11 @@ yyreduce:
case 7:
/* Line 1455 of yacc.c */
-#line 80 "parser.y"
+#line 78 "parser.y"
{
section_list_t *section = malloc_thing(section_list_t);
-
- section->name = clone_str((yyvsp[(2) - (3)].s));
+
+ section->name = strdupnull((yyvsp[(2) - (3)].s));
section->kw = NULL;
section->next = NULL;
_parser_kw = &(section->kw);
@@ -1442,10 +1440,10 @@ yyreduce:
case 9:
/* Line 1455 of yacc.c */
-#line 96 "parser.y"
+#line 94 "parser.y"
{
section_list_t *section = malloc_thing(section_list_t);
- section->name = clone_str((yyvsp[(2) - (3)].s));
+ section->name = strdupnull((yyvsp[(2) - (3)].s));
section->kw = NULL;
section->next = NULL;
_parser_kw = &(section->kw);
@@ -1462,7 +1460,7 @@ yyreduce:
case 11:
/* Line 1455 of yacc.c */
-#line 111 "parser.y"
+#line 109 "parser.y"
{
extern void _parser_y_include (const char *f);
_parser_y_include((yyvsp[(2) - (2)].s));
@@ -1473,7 +1471,7 @@ yyreduce:
case 16:
/* Line 1455 of yacc.c */
-#line 126 "parser.y"
+#line 124 "parser.y"
{
kw_list_t *new;
kw_entry_t *entry = in_word_set((yyvsp[(1) - (3)].s), strlen((yyvsp[(1) - (3)].s)));
@@ -1487,7 +1485,7 @@ yyreduce:
{
new = (kw_list_t *)malloc_thing(kw_list_t);
new->entry = entry;
- new->value = clone_str((yyvsp[(3) - (3)].s));
+ new->value = strdupnull((yyvsp[(3) - (3)].s));
new->next = NULL;
if (_parser_kw_last)
_parser_kw_last->next = new;
@@ -1503,7 +1501,7 @@ yyreduce:
case 17:
/* Line 1455 of yacc.c */
-#line 151 "parser.y"
+#line 149 "parser.y"
{
free((yyvsp[(1) - (2)].s));
}
@@ -1512,7 +1510,7 @@ yyreduce:
/* Line 1455 of yacc.c */
-#line 1516 "parser.c"
+#line 1514 "parser.c"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -1724,7 +1722,7 @@ yyreturn:
/* Line 1675 of yacc.c */
-#line 157 "parser.y"
+#line 155 "parser.y"
void yyerror(const char *s)
@@ -1794,7 +1792,7 @@ config_parsed_t *parser_load_conf(const char *file)
if (err)
{
- plog("%s", parser_errstring);
+ DBG1(DBG_APP, "%s", parser_errstring);
if (cfg)
parser_free_conf(cfg);
diff --git a/src/starter/parser.h b/src/starter/parser.h
index f0e666bb5..eff532f6d 100644
--- a/src/starter/parser.h
+++ b/src/starter/parser.h
@@ -71,7 +71,7 @@ typedef union YYSTYPE
{
/* Line 1676 of yacc.c */
-#line 54 "parser.y"
+#line 52 "parser.y"
char *s;
diff --git a/src/starter/parser.y b/src/starter/parser.y
index dfaec9ee8..424e3a9fd 100644
--- a/src/starter/parser.y
+++ b/src/starter/parser.y
@@ -17,11 +17,9 @@
#include <stdlib.h>
#include <string.h>
-#include <freeswan.h>
+#include <library.h>
+#include <debug.h>
-#include "../pluto/constants.h"
-#include "../pluto/defs.h"
-#include "../pluto/log.h"
#include "ipsec-parser.h"
#define YYERROR_VERBOSE
@@ -63,7 +61,7 @@ extern kw_entry_t *in_word_set (char *str, unsigned int len);
config_file:
config_file section_or_include
- | /* NULL */
+ | /* NULL */
;
section_or_include:
@@ -79,8 +77,8 @@ section_or_include:
| CONN STRING EOL
{
section_list_t *section = malloc_thing(section_list_t);
-
- section->name = clone_str($2);
+
+ section->name = strdupnull($2);
section->kw = NULL;
section->next = NULL;
_parser_kw = &(section->kw);
@@ -95,7 +93,7 @@ section_or_include:
| CA STRING EOL
{
section_list_t *section = malloc_thing(section_list_t);
- section->name = clone_str($2);
+ section->name = strdupnull($2);
section->kw = NULL;
section->next = NULL;
_parser_kw = &(section->kw);
@@ -136,7 +134,7 @@ statement_kw:
{
new = (kw_list_t *)malloc_thing(kw_list_t);
new->entry = entry;
- new->value = clone_str($3);
+ new->value = strdupnull($3);
new->next = NULL;
if (_parser_kw_last)
_parser_kw_last->next = new;
@@ -223,7 +221,7 @@ config_parsed_t *parser_load_conf(const char *file)
if (err)
{
- plog("%s", parser_errstring);
+ DBG1(DBG_APP, "%s", parser_errstring);
if (cfg)
parser_free_conf(cfg);
diff --git a/src/starter/starter.c b/src/starter/starter.c
index 44e21431c..c6efcb2f4 100644
--- a/src/starter/starter.c
+++ b/src/starter/starter.c
@@ -12,12 +12,14 @@
* for more details.
*/
+#include <sys/select.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
+#include <syslog.h>
#include <unistd.h>
#include <sys/time.h>
#include <time.h>
@@ -26,25 +28,100 @@
#include <fcntl.h>
#include <pwd.h>
#include <grp.h>
+#include <pthread.h>
-#include <freeswan.h>
#include <library.h>
#include <hydra.h>
-
-#include "../pluto/constants.h"
-#include "../pluto/defs.h"
-#include "../pluto/log.h"
+#include <utils/backtrace.h>
+#include <threading/thread.h>
+#include <debug.h>
#include "confread.h"
#include "files.h"
-#include "starterwhack.h"
#include "starterstroke.h"
-#include "invokepluto.h"
#include "invokecharon.h"
#include "netkey.h"
#include "klips.h"
#include "cmp.h"
-#include "interfaces.h"
+
+#ifndef LOG_AUTHPRIV
+#define LOG_AUTHPRIV LOG_AUTH
+#endif
+
+#define CHARON_RESTART_DELAY 5
+
+/* logging */
+static bool log_to_stderr = TRUE;
+static bool log_to_syslog = TRUE;
+static level_t current_loglevel = 1;
+
+/**
+ * logging function for scepclient
+ */
+static void starter_dbg(debug_t group, level_t level, char *fmt, ...)
+{
+ char buffer[8192];
+ char *current = buffer, *next;
+ va_list args;
+
+ if (level <= current_loglevel)
+ {
+ if (log_to_stderr)
+ {
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ }
+ if (log_to_syslog)
+ {
+ /* write in memory buffer first */
+ va_start(args, fmt);
+ vsnprintf(buffer, sizeof(buffer), fmt, args);
+ va_end(args);
+
+ /* do a syslog with every line */
+ while (current)
+ {
+ next = strchr(current, '\n');
+ if (next)
+ {
+ *(next++) = '\0';
+ }
+ syslog(LOG_INFO, "%s\n", current);
+ current = next;
+ }
+ }
+ }
+}
+
+/**
+ * Initialize logging to stderr/syslog
+ */
+static void init_log(const char *program)
+{
+ dbg = starter_dbg;
+
+ if (log_to_stderr)
+ {
+ setbuf(stderr, NULL);
+ }
+ if (log_to_syslog)
+ {
+ openlog(program, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_AUTHPRIV);
+ }
+}
+
+/**
+ * Deinitialize logging to syslog
+ */
+static void close_log()
+{
+ if (log_to_syslog)
+ {
+ closelog();
+ }
+}
/**
* Return codes defined by Linux Standard Base Core Specification 3.1
@@ -68,7 +145,10 @@
static unsigned int _action_ = 0;
-static void fsig(int signal)
+/**
+ * Handle signals in the main thread
+ */
+static void signal_handler(int signal)
{
switch (signal)
{
@@ -80,27 +160,19 @@ static void fsig(int signal)
while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
{
- if (pid == starter_pluto_pid())
- {
- name = " (Pluto)";
- }
if (pid == starter_charon_pid())
{
name = " (Charon)";
}
if (WIFSIGNALED(status))
{
- DBG(DBG_CONTROL,
- DBG_log("child %d%s has been killed by sig %d\n",
- pid, name?name:"", WTERMSIG(status))
- )
+ DBG2(DBG_APP, "child %d%s has been killed by sig %d\n",
+ pid, name?name:"", WTERMSIG(status));
}
else if (WIFSTOPPED(status))
{
- DBG(DBG_CONTROL,
- DBG_log("child %d%s has been stopped by sig %d\n",
- pid, name?name:"", WSTOPSIG(status))
- )
+ DBG2(DBG_APP, "child %d%s has been stopped by sig %d\n",
+ pid, name?name:"", WSTOPSIG(status));
}
else if (WIFEXITED(status))
{
@@ -109,20 +181,12 @@ static void fsig(int signal)
{
_action_ = FLAG_ACTION_QUIT;
}
- DBG(DBG_CONTROL,
- DBG_log("child %d%s has quit (exit code %d)\n",
- pid, name?name:"", exit_status)
- )
+ DBG2(DBG_APP, "child %d%s has quit (exit code %d)\n",
+ pid, name?name:"", exit_status);
}
else
{
- DBG(DBG_CONTROL,
- DBG_log("child %d%s has quit", pid, name?name:"")
- )
- }
- if (pid == starter_pluto_pid())
- {
- starter_pluto_sigchild(pid, exit_status);
+ DBG2(DBG_APP, "child %d%s has quit", pid, name?name:"");
}
if (pid == starter_charon_pid())
{
@@ -132,12 +196,7 @@ static void fsig(int signal)
}
break;
- case SIGPIPE:
- /** ignore **/
- break;
-
case SIGALRM:
- _action_ |= FLAG_ACTION_START_PLUTO;
_action_ |= FLAG_ACTION_START_CHARON;
break;
@@ -157,11 +216,27 @@ static void fsig(int signal)
break;
default:
- plog("fsig(): unknown signal %d -- investigate", signal);
+ DBG1(DBG_APP, "fsig(): unknown signal %d -- investigate", signal);
break;
}
}
+/**
+ * Handle fatal signals raised by threads
+ */
+static void fatal_signal_handler(int signal)
+{
+ backtrace_t *backtrace;
+
+ DBG1(DBG_APP, "thread %u received %d", thread_current_id(), signal);
+ backtrace = backtrace_create(2);
+ backtrace->log(backtrace, stderr, TRUE);
+ backtrace->destroy(backtrace);
+
+ DBG1(DBG_APP, "killing ourself, received critical signal");
+ abort();
+}
+
#ifdef GENERATE_SELFCERT
static void generate_selfcert()
{
@@ -244,7 +319,7 @@ static bool check_pid(char *pid_file)
return TRUE;
}
}
- plog("removing pidfile '%s', process not running", pid_file);
+ DBG1(DBG_APP, "removing pidfile '%s', process not running", pid_file);
unlink(pid_file);
}
return FALSE;
@@ -252,8 +327,8 @@ static bool check_pid(char *pid_file)
static void usage(char *name)
{
- fprintf(stderr, "Usage: starter [--nofork] [--auto-update <sec>] "
- "[--debug|--debug-more|--debug-all]\n");
+ fprintf(stderr, "Usage: starter [--nofork] [--auto-update <sec>]\n"
+ " [--debug|--debug-more|--debug-all|--nolog]\n");
exit(LSB_RC_INVALID_ARGUMENT);
}
@@ -264,21 +339,18 @@ int main (int argc, char **argv)
starter_conn_t *conn, *conn2;
starter_ca_t *ca, *ca2;
+ struct sigaction action;
struct stat stb;
int i;
int id = 1;
- struct timeval tv;
+ struct timespec ts;
unsigned long auto_update = 0;
time_t last_reload;
bool no_fork = FALSE;
bool attach_gdb = FALSE;
bool load_warning = FALSE;
- /* global variables defined in log.h */
- log_to_stderr = TRUE;
- base_debugging = DBG_NONE;
-
library_init(NULL);
atexit(library_deinit);
@@ -290,15 +362,19 @@ int main (int argc, char **argv)
{
if (streq(argv[i], "--debug"))
{
- base_debugging |= DBG_CONTROL;
+ current_loglevel = 2;
}
else if (streq(argv[i], "--debug-more"))
{
- base_debugging |= DBG_CONTROLMORE;
+ current_loglevel = 3;
}
else if (streq(argv[i], "--debug-all"))
{
- base_debugging |= DBG_ALL;
+ current_loglevel = 4;
+ }
+ else if (streq(argv[i], "--nolog"))
+ {
+ current_loglevel = 0;
}
else if (streq(argv[i], "--nofork"))
{
@@ -321,20 +397,12 @@ int main (int argc, char **argv)
}
}
- /* Init */
init_log("ipsec_starter");
- cur_debugging = base_debugging;
-
- signal(SIGHUP, fsig);
- signal(SIGCHLD, fsig);
- signal(SIGPIPE, fsig);
- signal(SIGINT, fsig);
- signal(SIGTERM, fsig);
- signal(SIGQUIT, fsig);
- signal(SIGALRM, fsig);
- signal(SIGUSR1, fsig);
- plog("Starting strongSwan "VERSION" IPsec [starter]...");
+ DBG1(DBG_APP, "Starting %sSwan "VERSION" IPsec [starter]...",
+ lib->settings->get_bool(lib->settings,
+ "charon.i_dont_care_about_security_and_use_aggressive_mode_psk",
+ FALSE) ? "weak" : "strong");
#ifdef LOAD_WARNING
load_warning = TRUE;
@@ -342,34 +410,24 @@ int main (int argc, char **argv)
if (lib->settings->get_bool(lib->settings, "starter.load_warning", load_warning))
{
- if (lib->settings->get_str(lib->settings, "charon.load", NULL) ||
- lib->settings->get_str(lib->settings, "pluto.load", NULL))
+ if (lib->settings->get_str(lib->settings, "charon.load", NULL))
{
- plog("!! Your strongswan.conf contains manual plugin load options for");
- plog("!! pluto and/or charon. This is recommended for experts only, see");
- plog("!! http://wiki.strongswan.org/projects/strongswan/wiki/PluginLoad");
+ DBG1(DBG_APP, "!! Your strongswan.conf contains manual plugin load options for charon.");
+ DBG1(DBG_APP, "!! This is recommended for experts only, see");
+ DBG1(DBG_APP, "!! http://wiki.strongswan.org/projects/strongswan/wiki/PluginLoad");
}
}
/* verify that we can start */
if (getuid() != 0)
{
- plog("permission denied (must be superuser)");
+ DBG1(DBG_APP, "permission denied (must be superuser)");
exit(LSB_RC_NOT_ALLOWED);
}
- if (check_pid(PLUTO_PID_FILE))
- {
- plog("pluto is already running (%s exists) -- skipping pluto start",
- PLUTO_PID_FILE);
- }
- else
- {
- _action_ |= FLAG_ACTION_START_PLUTO;
- }
if (check_pid(CHARON_PID_FILE))
{
- plog("charon is already running (%s exists) -- skipping charon start",
+ DBG1(DBG_APP, "charon is already running (%s exists) -- skipping charon start",
CHARON_PID_FILE);
}
else
@@ -378,20 +436,20 @@ int main (int argc, char **argv)
}
if (stat(DEV_RANDOM, &stb) != 0)
{
- plog("unable to start strongSwan IPsec -- no %s!", DEV_RANDOM);
+ DBG1(DBG_APP, "unable to start strongSwan IPsec -- no %s!", DEV_RANDOM);
exit(LSB_RC_FAILURE);
}
if (stat(DEV_URANDOM, &stb)!= 0)
{
- plog("unable to start strongSwan IPsec -- no %s!", DEV_URANDOM);
+ DBG1(DBG_APP, "unable to start strongSwan IPsec -- no %s!", DEV_URANDOM);
exit(LSB_RC_FAILURE);
}
cfg = confread_load(CONFIG_FILE);
if (cfg == NULL || cfg->err > 0)
{
- plog("unable to start strongSwan -- fatal errors in config");
+ DBG1(DBG_APP, "unable to start strongSwan -- fatal errors in config");
if (cfg)
{
confread_free(cfg);
@@ -402,11 +460,11 @@ int main (int argc, char **argv)
/* determine if we have a native netkey IPsec stack */
if (!starter_netkey_init())
{
- plog("no netkey IPsec stack detected");
+ DBG1(DBG_APP, "no netkey IPsec stack detected");
if (!starter_klips_init())
{
- plog("no KLIPS IPsec stack detected");
- plog("no known IPsec stack detected, ignoring!");
+ DBG1(DBG_APP, "no KLIPS IPsec stack detected");
+ DBG1(DBG_APP, "no known IPsec stack detected, ignoring!");
}
}
@@ -414,7 +472,7 @@ int main (int argc, char **argv)
if (check_pid(STARTER_PID_FILE))
{
- plog("starter is already running (%s exists) -- no fork done",
+ DBG1(DBG_APP, "starter is already running (%s exists) -- no fork done",
STARTER_PID_FILE);
confread_free(cfg);
exit(LSB_RC_SUCCESS);
@@ -435,6 +493,7 @@ int main (int argc, char **argv)
{
int fnull;
+ close_log();
closefrom(3);
fnull = open("/dev/null", O_RDWR);
@@ -447,10 +506,11 @@ int main (int argc, char **argv)
}
setsid();
+ init_log("ipsec_starter");
}
break;
case -1:
- plog("can't fork: %s", strerror(errno));
+ DBG1(DBG_APP, "can't fork: %s", strerror(errno));
break;
default:
confread_free(cfg);
@@ -469,24 +529,46 @@ int main (int argc, char **argv)
}
}
- /* load plugins */
- if (!lib->plugins->load(lib->plugins, NULL,
- lib->settings->get_str(lib->settings, "starter.load", PLUGINS)))
- {
- exit(LSB_RC_FAILURE);
- }
+ /* we handle these signals only in pselect() */
+ memset(&action, 0, sizeof(action));
+ sigemptyset(&action.sa_mask);
+ sigaddset(&action.sa_mask, SIGHUP);
+ sigaddset(&action.sa_mask, SIGINT);
+ sigaddset(&action.sa_mask, SIGTERM);
+ sigaddset(&action.sa_mask, SIGQUIT);
+ sigaddset(&action.sa_mask, SIGALRM);
+ sigaddset(&action.sa_mask, SIGUSR1);
+ pthread_sigmask(SIG_SETMASK, &action.sa_mask, NULL);
+
+ /* install a handler for fatal signals */
+ action.sa_handler = fatal_signal_handler;
+ sigaction(SIGSEGV, &action, NULL);
+ sigaction(SIGILL, &action, NULL);
+ sigaction(SIGBUS, &action, NULL);
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &action, NULL);
+
+ /* install main signal handler */
+ action.sa_handler = signal_handler;
+ sigaction(SIGHUP, &action, NULL);
+ sigaction(SIGINT, &action, NULL);
+ sigaction(SIGTERM, &action, NULL);
+ sigaction(SIGQUIT, &action, NULL);
+ sigaction(SIGALRM, &action, NULL);
+ sigaction(SIGUSR1, &action, NULL);
+ /* this is not blocked above as we want to receive it asynchronously */
+ sigaction(SIGCHLD, &action, NULL);
+
+ /* empty mask for pselect() call below */
+ sigemptyset(&action.sa_mask);
for (;;)
{
/*
- * Stop pluto/charon (if started) and exit
+ * Stop charon (if started) and exit
*/
if (_action_ & FLAG_ACTION_QUIT)
{
- if (starter_pluto_pid())
- {
- starter_stop_pluto();
- }
if (starter_charon_pid())
{
starter_stop_charon();
@@ -494,8 +576,7 @@ int main (int argc, char **argv)
starter_netkey_cleanup();
confread_free(cfg);
unlink(STARTER_PID_FILE);
- plog("ipsec starter stopped");
- lib->plugins->unload(lib->plugins);
+ DBG1(DBG_APP, "ipsec starter stopped");
close_log();
exit(LSB_RC_SUCCESS);
}
@@ -505,7 +586,7 @@ int main (int argc, char **argv)
*/
if (_action_ & FLAG_ACTION_RELOAD)
{
- if (starter_pluto_pid() || starter_charon_pid())
+ if (starter_charon_pid())
{
for (conn = cfg->conn_first; conn; conn = conn->next)
{
@@ -515,10 +596,6 @@ int main (int argc, char **argv)
{
starter_stroke_del_conn(conn);
}
- if (starter_pluto_pid())
- {
- starter_whack_del_conn(conn);
- }
conn->state = STATE_TO_ADD;
}
}
@@ -530,10 +607,6 @@ int main (int argc, char **argv)
{
starter_stroke_del_ca(ca);
}
- if (starter_pluto_pid())
- {
- starter_whack_del_ca(ca);
- }
ca->state = STATE_TO_ADD;
}
}
@@ -546,96 +619,68 @@ int main (int argc, char **argv)
*/
if (_action_ & FLAG_ACTION_UPDATE)
{
- DBG(DBG_CONTROL,
- DBG_log("Reloading config...")
- );
+ DBG2(DBG_APP, "Reloading config...");
new_cfg = confread_load(CONFIG_FILE);
if (new_cfg && (new_cfg->err + new_cfg->non_fatal_err == 0))
{
/* Switch to new config. New conn will be loaded below */
- if (!starter_cmp_defaultroute(&new_cfg->defaultroute
- , &cfg->defaultroute))
- {
- _action_ |= FLAG_ACTION_LISTEN;
- }
- if (!starter_cmp_pluto(cfg, new_cfg))
- {
- plog("Pluto has changed");
- if (starter_pluto_pid())
- starter_stop_pluto();
- _action_ &= ~FLAG_ACTION_LISTEN;
- _action_ |= FLAG_ACTION_START_PLUTO;
- }
- else
+ /* Look for new connections that are already loaded */
+ for (conn = cfg->conn_first; conn; conn = conn->next)
{
- /* Only reload conn and ca sections if pluto is not killed */
-
- /* Look for new connections that are already loaded */
- for (conn = cfg->conn_first; conn; conn = conn->next)
+ if (conn->state == STATE_ADDED)
{
- if (conn->state == STATE_ADDED)
+ for (conn2 = new_cfg->conn_first; conn2; conn2 = conn2->next)
{
- for (conn2 = new_cfg->conn_first; conn2; conn2 = conn2->next)
+ if (conn2->state == STATE_TO_ADD && starter_cmp_conn(conn, conn2))
{
- if (conn2->state == STATE_TO_ADD && starter_cmp_conn(conn, conn2))
- {
- conn->state = STATE_REPLACED;
- conn2->state = STATE_ADDED;
- conn2->id = conn->id;
- break;
- }
+ conn->state = STATE_REPLACED;
+ conn2->state = STATE_ADDED;
+ conn2->id = conn->id;
+ break;
}
}
}
+ }
- /* Remove conn sections that have become unused */
- for (conn = cfg->conn_first; conn; conn = conn->next)
+ /* Remove conn sections that have become unused */
+ for (conn = cfg->conn_first; conn; conn = conn->next)
+ {
+ if (conn->state == STATE_ADDED)
{
- if (conn->state == STATE_ADDED)
+ if (starter_charon_pid())
{
- if (starter_charon_pid())
- {
- starter_stroke_del_conn(conn);
- }
- if (starter_pluto_pid())
- {
- starter_whack_del_conn(conn);
- }
+ starter_stroke_del_conn(conn);
}
}
+ }
- /* Look for new ca sections that are already loaded */
- for (ca = cfg->ca_first; ca; ca = ca->next)
+ /* Look for new ca sections that are already loaded */
+ for (ca = cfg->ca_first; ca; ca = ca->next)
+ {
+ if (ca->state == STATE_ADDED)
{
- if (ca->state == STATE_ADDED)
+ for (ca2 = new_cfg->ca_first; ca2; ca2 = ca2->next)
{
- for (ca2 = new_cfg->ca_first; ca2; ca2 = ca2->next)
+ if (ca2->state == STATE_TO_ADD && starter_cmp_ca(ca, ca2))
{
- if (ca2->state == STATE_TO_ADD && starter_cmp_ca(ca, ca2))
- {
- ca->state = STATE_REPLACED;
- ca2->state = STATE_ADDED;
- break;
- }
+ ca->state = STATE_REPLACED;
+ ca2->state = STATE_ADDED;
+ break;
}
}
}
+ }
- /* Remove ca sections that have become unused */
- for (ca = cfg->ca_first; ca; ca = ca->next)
+ /* Remove ca sections that have become unused */
+ for (ca = cfg->ca_first; ca; ca = ca->next)
+ {
+ if (ca->state == STATE_ADDED)
{
- if (ca->state == STATE_ADDED)
+ if (starter_charon_pid())
{
- if (starter_charon_pid())
- {
- starter_stroke_del_ca(ca);
- }
- if (starter_pluto_pid())
- {
- starter_whack_del_ca(ca);
- }
+ starter_stroke_del_ca(ca);
}
}
}
@@ -644,7 +689,7 @@ int main (int argc, char **argv)
}
else
{
- plog("can't reload config file due to errors -- keeping old one");
+ DBG1(DBG_APP, "can't reload config file due to errors -- keeping old one");
if (new_cfg)
{
confread_free(new_cfg);
@@ -655,77 +700,43 @@ int main (int argc, char **argv)
}
/*
- * Start pluto
+ * Start charon
*/
- if (_action_ & FLAG_ACTION_START_PLUTO)
+ if (_action_ & FLAG_ACTION_START_CHARON)
{
- if (cfg->setup.plutostart && !starter_pluto_pid())
+ if (cfg->setup.charonstart && !starter_charon_pid())
{
- DBG(DBG_CONTROL,
- DBG_log("Attempting to start pluto...")
- );
-
- if (starter_start_pluto(cfg, no_fork, attach_gdb) == 0)
- {
- starter_whack_listen();
- }
- else
+ DBG2(DBG_APP, "Attempting to start charon...");
+ if (starter_start_charon(cfg, no_fork, attach_gdb))
{
/* schedule next try */
- alarm(PLUTO_RESTART_DELAY);
+ alarm(CHARON_RESTART_DELAY);
}
+ starter_stroke_configure(cfg);
}
- _action_ &= ~FLAG_ACTION_START_PLUTO;
+ _action_ &= ~FLAG_ACTION_START_CHARON;
for (ca = cfg->ca_first; ca; ca = ca->next)
{
if (ca->state == STATE_ADDED)
+ {
ca->state = STATE_TO_ADD;
+ }
}
for (conn = cfg->conn_first; conn; conn = conn->next)
{
if (conn->state == STATE_ADDED)
- conn->state = STATE_TO_ADD;
- }
- }
-
- /*
- * Start charon
- */
- if (_action_ & FLAG_ACTION_START_CHARON)
- {
- if (cfg->setup.charonstart && !starter_charon_pid())
- {
- DBG(DBG_CONTROL,
- DBG_log("Attempting to start charon...")
- );
- if (starter_start_charon(cfg, no_fork, attach_gdb))
{
- /* schedule next try */
- alarm(PLUTO_RESTART_DELAY);
+ conn->state = STATE_TO_ADD;
}
- starter_stroke_configure(cfg);
- }
- _action_ &= ~FLAG_ACTION_START_CHARON;
- }
-
- /*
- * Tell pluto to reread its interfaces
- */
- if (_action_ & FLAG_ACTION_LISTEN)
- {
- if (starter_pluto_pid())
- {
- starter_whack_listen();
- _action_ &= ~FLAG_ACTION_LISTEN;
}
}
/*
* Add stale conn and ca sections
*/
- if (starter_pluto_pid() || starter_charon_pid())
+ if (starter_charon_pid())
{
for (ca = cfg->ca_first; ca; ca = ca->next)
{
@@ -735,10 +746,6 @@ int main (int argc, char **argv)
{
starter_stroke_add_ca(ca);
}
- if (starter_pluto_pid())
- {
- starter_whack_add_ca(ca);
- }
ca->state = STATE_ADDED;
}
}
@@ -756,44 +763,20 @@ int main (int argc, char **argv)
{
starter_stroke_add_conn(cfg, conn);
}
- if (starter_pluto_pid())
- {
- starter_whack_add_conn(conn);
- }
conn->state = STATE_ADDED;
if (conn->startup == STARTUP_START)
{
- if (conn->keyexchange != KEY_EXCHANGE_IKEV1)
+ if (starter_charon_pid())
{
- if (starter_charon_pid())
- {
- starter_stroke_initiate_conn(conn);
- }
- }
- else
- {
- if (starter_pluto_pid())
- {
- starter_whack_initiate_conn(conn);
- }
+ starter_stroke_initiate_conn(conn);
}
}
else if (conn->startup == STARTUP_ROUTE)
{
- if (conn->keyexchange != KEY_EXCHANGE_IKEV1)
- {
- if (starter_charon_pid())
- {
- starter_stroke_route_conn(conn);
- }
- }
- else
+ if (starter_charon_pid())
{
- if (starter_pluto_pid())
- {
- starter_whack_route_conn(conn);
- }
+ starter_stroke_route_conn(conn);
}
}
}
@@ -807,15 +790,16 @@ int main (int argc, char **argv)
{
time_t now = time_monotonic(NULL);
- tv.tv_sec = (now < last_reload + auto_update)
- ? (last_reload + auto_update-now) : 0;
- tv.tv_usec = 0;
+ ts.tv_sec = (now < last_reload + auto_update) ?
+ (last_reload + auto_update - now) : 0;
+ ts.tv_nsec = 0;
}
/*
* Wait for something to happen
*/
- if (select(0, NULL, NULL, NULL, auto_update ? &tv : NULL) == 0)
+ if (pselect(0, NULL, NULL, NULL, auto_update ? &ts : NULL,
+ &action.sa_mask) == 0)
{
/* timeout -> auto_update */
_action_ |= FLAG_ACTION_UPDATE;
diff --git a/src/starter/starterstroke.c b/src/starter/starterstroke.c
index ae04c20dd..d6ad3eb89 100644
--- a/src/starter/starterstroke.c
+++ b/src/starter/starterstroke.c
@@ -1,4 +1,4 @@
-/* Stroke for charon is the counterpart to whack from pluto
+/*
* Copyright (C) 2006 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -26,11 +26,8 @@
#include <credentials/auth_cfg.h>
-#include <freeswan.h>
-
-#include <constants.h>
-#include <defs.h>
-#include <log.h>
+#include <library.h>
+#include <debug.h>
#include <stroke_msg.h>
@@ -73,12 +70,12 @@ static int send_stroke_msg (stroke_msg_t *msg)
if (sock < 0)
{
- plog("socket() failed: %s", strerror(errno));
+ DBG1(DBG_APP, "socket() failed: %s", strerror(errno));
return -1;
}
if (connect(sock, (struct sockaddr *)&ctl_addr, offsetof(struct sockaddr_un, sun_path) + strlen(ctl_addr.sun_path)) < 0)
{
- plog("connect(charon_ctl) failed: %s", strerror(errno));
+ DBG1(DBG_APP, "connect(charon_ctl) failed: %s", strerror(errno));
close(sock);
return -1;
}
@@ -86,18 +83,18 @@ static int send_stroke_msg (stroke_msg_t *msg)
/* send message */
if (write(sock, msg, msg->length) != msg->length)
{
- plog("write(charon_ctl) failed: %s", strerror(errno));
+ DBG1(DBG_APP, "write(charon_ctl) failed: %s", strerror(errno));
close(sock);
return -1;
}
while ((byte_count = read(sock, buffer, sizeof(buffer)-1)) > 0)
{
buffer[byte_count] = '\0';
- plog("%s", buffer);
+ DBG1(DBG_APP, "%s", buffer);
}
if (byte_count < 0)
{
- plog("read() failed: %s", strerror(errno));
+ DBG1(DBG_APP, "read() failed: %s", strerror(errno));
}
close(sock);
@@ -117,47 +114,8 @@ static char* connection_name(starter_conn_t *conn)
return conn->name;
}
-static void ip_address2string(ip_address *addr, char *buffer, size_t len)
-{
- switch (((struct sockaddr*)addr)->sa_family)
- {
- case AF_INET6:
- {
- struct sockaddr_in6* sin6 = (struct sockaddr_in6*)addr;
- u_int8_t zeroes[IPV6_LEN];
-
- memset(zeroes, 0, IPV6_LEN);
- if (memcmp(zeroes, &(sin6->sin6_addr.s6_addr), IPV6_LEN) &&
- inet_ntop(AF_INET6, &sin6->sin6_addr, buffer, len))
- {
- return;
- }
- snprintf(buffer, len, "%%any6");
- break;
- }
- case AF_INET:
- {
- struct sockaddr_in* sin = (struct sockaddr_in*)addr;
- u_int8_t zeroes[IPV4_LEN];
-
- memset(zeroes, 0, IPV4_LEN);
- if (memcmp(zeroes, &(sin->sin_addr.s_addr), IPV4_LEN) &&
- inet_ntop(AF_INET, &sin->sin_addr, buffer, len))
- {
- return;
- }
- /* fall through to default */
- }
- default:
- snprintf(buffer, len, "%%any");
- break;
- }
-}
-
static void starter_stroke_add_end(stroke_msg_t *msg, stroke_end_t *msg_end, starter_end_t *conn_end)
{
- char buffer[INET6_ADDRSTRLEN];
-
msg_end->auth = push_string(msg, conn_end->auth);
msg_end->auth2 = push_string(msg, conn_end->auth2);
msg_end->id = push_string(msg, conn_end->id);
@@ -169,6 +127,7 @@ static void starter_stroke_add_end(stroke_msg_t *msg, stroke_end_t *msg_end, sta
msg_end->ca = push_string(msg, conn_end->ca);
msg_end->ca2 = push_string(msg, conn_end->ca2);
msg_end->groups = push_string(msg, conn_end->groups);
+ msg_end->groups2 = push_string(msg, conn_end->groups2);
msg_end->updown = push_string(msg, conn_end->updown);
if (conn_end->host)
{
@@ -176,16 +135,16 @@ static void starter_stroke_add_end(stroke_msg_t *msg, stroke_end_t *msg_end, sta
}
else
{
- ip_address2string(&conn_end->addr, buffer, sizeof(buffer));
- msg_end->address = push_string(msg, buffer);
+ msg_end->address = push_string(msg, "%any");
}
msg_end->ikeport = conn_end->ikeport;
msg_end->subnets = push_string(msg, conn_end->subnet);
msg_end->sourceip = push_string(msg, conn_end->sourceip);
- msg_end->sourceip_mask = conn_end->sourceip_mask;
+ msg_end->dns = push_string(msg, conn_end->dns);
msg_end->sendcert = conn_end->sendcert;
msg_end->hostaccess = conn_end->hostaccess;
- msg_end->tohost = !conn_end->has_client;
+ msg_end->tohost = !conn_end->subnet;
+ msg_end->allow_any = conn_end->allow_any;
msg_end->protocol = conn_end->protocol;
msg_end->port = conn_end->port;
}
@@ -197,60 +156,18 @@ int starter_stroke_add_conn(starter_config_t *cfg, starter_conn_t *conn)
memset(&msg, 0, sizeof(msg));
msg.type = STR_ADD_CONN;
msg.length = offsetof(stroke_msg_t, buffer);
- msg.add_conn.ikev2 = conn->keyexchange != KEY_EXCHANGE_IKEV1;
+ msg.add_conn.version = conn->keyexchange;
msg.add_conn.name = push_string(&msg, connection_name(conn));
-
- /* PUBKEY is preferred to PSK and EAP */
- if (conn->policy & POLICY_PUBKEY)
- {
- msg.add_conn.auth_method = AUTH_CLASS_PUBKEY;
- }
- else if (conn->policy & POLICY_PSK)
- {
- msg.add_conn.auth_method = AUTH_CLASS_PSK;
- }
- else if (conn->policy & POLICY_XAUTH_PSK)
- {
- msg.add_conn.auth_method = AUTH_CLASS_EAP;
- }
- else
- {
- msg.add_conn.auth_method = AUTH_CLASS_ANY;
- }
- msg.add_conn.eap_type = conn->eap_type;
- msg.add_conn.eap_vendor = conn->eap_vendor;
msg.add_conn.eap_identity = push_string(&msg, conn->eap_identity);
msg.add_conn.aaa_identity = push_string(&msg, conn->aaa_identity);
+ msg.add_conn.xauth_identity = push_string(&msg, conn->xauth_identity);
- if (conn->policy & POLICY_TUNNEL)
- {
- msg.add_conn.mode = MODE_TUNNEL;
- }
- else if (conn->policy & POLICY_BEET)
- {
- msg.add_conn.mode = MODE_BEET;
- }
- else if (conn->policy & POLICY_PROXY)
- {
- msg.add_conn.mode = MODE_TRANSPORT;
- msg.add_conn.proxy_mode = TRUE;
- }
- else if (conn->policy & POLICY_SHUNT_PASS)
- {
- msg.add_conn.mode = MODE_PASS;
- }
- else if (conn->policy & (POLICY_SHUNT_DROP | POLICY_SHUNT_REJECT))
- {
- msg.add_conn.mode = MODE_DROP;
- }
- else
- {
- msg.add_conn.mode = MODE_TRANSPORT;
- }
+ msg.add_conn.mode = conn->mode;
+ msg.add_conn.proxy_mode = conn->proxy_mode;
- if (!(conn->policy & POLICY_DONT_REKEY))
+ if (!(conn->options & SA_OPTION_DONT_REKEY))
{
- msg.add_conn.rekey.reauth = (conn->policy & POLICY_DONT_REAUTH) == LEMPTY;
+ msg.add_conn.rekey.reauth = !(conn->options & SA_OPTION_DONT_REAUTH);
msg.add_conn.rekey.ipsec_lifetime = conn->sa_ipsec_life_seconds;
msg.add_conn.rekey.ike_lifetime = conn->sa_ike_life_seconds;
msg.add_conn.rekey.margin = conn->sa_rekey_margin;
@@ -261,15 +178,17 @@ int starter_stroke_add_conn(starter_config_t *cfg, starter_conn_t *conn)
msg.add_conn.rekey.tries = conn->sa_keying_tries;
msg.add_conn.rekey.fuzz = conn->sa_rekey_fuzz;
}
- msg.add_conn.mobike = (conn->policy & POLICY_MOBIKE) != 0;
- msg.add_conn.force_encap = (conn->policy & POLICY_FORCE_ENCAP) != 0;
- msg.add_conn.ipcomp = (conn->policy & POLICY_COMPRESS) != 0;
+ msg.add_conn.mobike = conn->options & SA_OPTION_MOBIKE;
+ msg.add_conn.force_encap = conn->options & SA_OPTION_FORCE_ENCAP;
+ msg.add_conn.ipcomp = conn->options & SA_OPTION_COMPRESS;
msg.add_conn.install_policy = conn->install_policy;
- msg.add_conn.crl_policy = cfg->setup.strictcrlpolicy;
+ msg.add_conn.aggressive = conn->aggressive;
+ msg.add_conn.crl_policy = (crl_policy_t)cfg->setup.strictcrlpolicy;
msg.add_conn.unique = cfg->setup.uniqueids;
msg.add_conn.algorithms.ike = push_string(&msg, conn->ike);
msg.add_conn.algorithms.esp = push_string(&msg, conn->esp);
msg.add_conn.dpd.delay = conn->dpd_delay;
+ msg.add_conn.dpd.timeout = conn->dpd_timeout;
msg.add_conn.dpd.action = conn->dpd_action;
msg.add_conn.close_action = conn->close_action;
msg.add_conn.inactivity = conn->inactivity;
@@ -286,6 +205,48 @@ int starter_stroke_add_conn(starter_config_t *cfg, starter_conn_t *conn)
starter_stroke_add_end(&msg, &msg.add_conn.me, &conn->left);
starter_stroke_add_end(&msg, &msg.add_conn.other, &conn->right);
+ if (!msg.add_conn.me.auth && !msg.add_conn.other.auth &&
+ conn->authby)
+ { /* leftauth/rightauth not set, use legacy options */
+ if (streq(conn->authby, "rsa") || streq(conn->authby, "rsasig") ||
+ streq(conn->authby, "ecdsa") || streq(conn->authby, "ecdsasig") ||
+ streq(conn->authby, "pubkey"))
+ {
+ msg.add_conn.me.auth = push_string(&msg, "pubkey");
+ msg.add_conn.other.auth = push_string(&msg, "pubkey");
+ }
+ else if (streq(conn->authby, "secret") || streq(conn->authby, "psk"))
+ {
+ msg.add_conn.me.auth = push_string(&msg, "psk");
+ msg.add_conn.other.auth = push_string(&msg, "psk");
+ }
+ else if (streq(conn->authby, "xauthrsasig"))
+ {
+ msg.add_conn.me.auth = push_string(&msg, "pubkey");
+ msg.add_conn.other.auth = push_string(&msg, "pubkey");
+ if (conn->options & SA_OPTION_XAUTH_SERVER)
+ {
+ msg.add_conn.other.auth2 = push_string(&msg, "xauth");
+ }
+ else
+ {
+ msg.add_conn.me.auth2 = push_string(&msg, "xauth");
+ }
+ }
+ else if (streq(conn->authby, "xauthpsk"))
+ {
+ msg.add_conn.me.auth = push_string(&msg, "psk");
+ msg.add_conn.other.auth = push_string(&msg, "psk");
+ if (conn->options & SA_OPTION_XAUTH_SERVER)
+ {
+ msg.add_conn.other.auth2 = push_string(&msg, "xauth");
+ }
+ else
+ {
+ msg.add_conn.me.auth2 = push_string(&msg, "xauth");
+ }
+ }
+ }
return send_stroke_msg(&msg);
}
diff --git a/src/starter/starterstroke.h b/src/starter/starterstroke.h
index f9b01c99a..fd2a3e320 100644
--- a/src/starter/starterstroke.h
+++ b/src/starter/starterstroke.h
@@ -1,5 +1,6 @@
-/* Stroke for charon is the counterpart to whack from pluto
- * Copyright (C) 2006 Martin Willi - Hochschule fuer Technik Rapperswil
+/*
+ * Copyright (C) 2006 Martin Willi
+ * Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -17,12 +18,12 @@
#include "confread.h"
-extern int starter_stroke_add_conn(starter_config_t *cfg, starter_conn_t *conn);
-extern int starter_stroke_del_conn(starter_conn_t *conn);
-extern int starter_stroke_route_conn(starter_conn_t *conn);
-extern int starter_stroke_initiate_conn(starter_conn_t *conn);
-extern int starter_stroke_add_ca(starter_ca_t *ca);
-extern int starter_stroke_del_ca(starter_ca_t *ca);
-extern int starter_stroke_configure(starter_config_t *cfg);
+int starter_stroke_add_conn(starter_config_t *cfg, starter_conn_t *conn);
+int starter_stroke_del_conn(starter_conn_t *conn);
+int starter_stroke_route_conn(starter_conn_t *conn);
+int starter_stroke_initiate_conn(starter_conn_t *conn);
+int starter_stroke_add_ca(starter_ca_t *ca);
+int starter_stroke_del_ca(starter_ca_t *ca);
+int starter_stroke_configure(starter_config_t *cfg);
#endif /* _STARTER_STROKE_H_ */
diff --git a/src/starter/starterwhack.c b/src/starter/starterwhack.c
deleted file mode 100644
index b7d916eae..000000000
--- a/src/starter/starterwhack.c
+++ /dev/null
@@ -1,420 +0,0 @@
-/* strongSwan whack functions to communicate with pluto (whack.c)
- * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security
- *
- * 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 <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-
-#include <freeswan.h>
-
-#include <constants.h>
-#include <defs.h>
-#include <log.h>
-#include <whack.h>
-
-#include "starterwhack.h"
-#include "confread.h"
-#include "files.h"
-
-#define ip_version(string) (strchr(string, '.') ? AF_INET : AF_INET6)
-
-static int pack_str (char **p, char **next, char **roof)
-{
- const char *s = (*p==NULL) ? "" : *p; /* note: NULL becomes ""! */
- size_t len = strlen(s) + 1;
-
- if ((*roof - *next) < len)
- {
- return 0; /* not enough space */
- }
- else
- {
- strcpy(*next, s);
- *next += len;
- *p = NULL; /* don't send pointers on the wire! */
- return 1;
- }
-}
-
-static int send_whack_msg (whack_message_t *msg)
-{
- struct sockaddr_un ctl_addr;
- int sock;
- ssize_t len;
- char *str_next, *str_roof;
-
- ctl_addr.sun_family = AF_UNIX;
- strcpy(ctl_addr.sun_path, PLUTO_CTL_FILE);
-
- /* pack strings */
- str_next = (char *)msg->string;
- str_roof = (char *)&msg->string[sizeof(msg->string)];
-
- if (!pack_str(&msg->name, &str_next, &str_roof)
- || !pack_str(&msg->left.id, &str_next, &str_roof)
- || !pack_str(&msg->left.cert, &str_next, &str_roof)
- || !pack_str(&msg->left.ca, &str_next, &str_roof)
- || !pack_str(&msg->left.groups, &str_next, &str_roof)
- || !pack_str(&msg->left.updown, &str_next, &str_roof)
- || !pack_str(&msg->left.sourceip, &str_next, &str_roof)
- || !pack_str(&msg->left.virt, &str_next, &str_roof)
- || !pack_str(&msg->right.id, &str_next, &str_roof)
- || !pack_str(&msg->right.cert, &str_next, &str_roof)
- || !pack_str(&msg->right.ca, &str_next, &str_roof)
- || !pack_str(&msg->right.groups, &str_next, &str_roof)
- || !pack_str(&msg->right.updown, &str_next, &str_roof)
- || !pack_str(&msg->right.sourceip, &str_next, &str_roof)
- || !pack_str(&msg->right.virt, &str_next, &str_roof)
- || !pack_str(&msg->keyid, &str_next, &str_roof)
- || !pack_str(&msg->myid, &str_next, &str_roof)
- || !pack_str(&msg->cacert, &str_next, &str_roof)
- || !pack_str(&msg->ldaphost, &str_next, &str_roof)
- || !pack_str(&msg->ldapbase, &str_next, &str_roof)
- || !pack_str(&msg->crluri, &str_next, &str_roof)
- || !pack_str(&msg->crluri2, &str_next, &str_roof)
- || !pack_str(&msg->ocspuri, &str_next, &str_roof)
- || !pack_str(&msg->ike, &str_next, &str_roof)
- || !pack_str(&msg->esp, &str_next, &str_roof)
- || !pack_str(&msg->sc_data, &str_next, &str_roof)
- || !pack_str(&msg->whack_lease_ip, &str_next, &str_roof)
- || !pack_str(&msg->whack_lease_id, &str_next, &str_roof)
- || !pack_str(&msg->xauth_identity, &str_next, &str_roof)
- || (str_roof - str_next < msg->keyval.len))
- {
- plog("send_wack_msg(): can't pack strings");
- return -1;
- }
- if (msg->keyval.ptr)
- {
- memcpy(str_next, msg->keyval.ptr, msg->keyval.len);
- }
- msg->keyval.ptr = NULL;
- str_next += msg->keyval.len;
- len = str_next - (char *)msg;
-
- /* connect to pluto ctl */
- sock = socket(AF_UNIX, SOCK_STREAM, 0);
- if (sock < 0)
- {
- plog("socket() failed: %s", strerror(errno));
- return -1;
- }
- if (connect(sock, (struct sockaddr *)&ctl_addr,
- offsetof(struct sockaddr_un, sun_path) + strlen(ctl_addr.sun_path)) < 0)
- {
- plog("connect(pluto_ctl) failed: %s", strerror(errno));
- close(sock);
- return -1;
- }
-
- /* send message */
- if (write(sock, msg, len) != len)
- {
- plog("write(pluto_ctl) failed: %s", strerror(errno));
- close(sock);
- return -1;
- }
-
- /* TODO: read reply */
- close(sock);
- return 0;
-}
-
-static void init_whack_msg(whack_message_t *msg)
-{
- memset(msg, 0, sizeof(whack_message_t));
- msg->magic = WHACK_MAGIC;
-}
-
-static char *connection_name(starter_conn_t *conn, char *buf, size_t size)
-{
- /* if connection name is '%auto', create a new name like conn_xxxxx */
- if (streq(conn->name, "%auto"))
- {
- snprintf(buf, size, "conn_%ld", conn->id);
- return buf;
- }
- return conn->name;
-}
-
-static void set_whack_end(whack_end_t *w, starter_end_t *end, sa_family_t family)
-{
- w->id = end->id;
- w->cert = end->cert;
- w->ca = end->ca;
- w->groups = end->groups;
- w->host_addr = end->addr;
- w->has_client = end->has_client;
- w->sourceip = end->sourceip;
- w->sourceip_mask = end->sourceip_mask;
-
- if (end->sourceip && end->sourceip_mask > 0)
- {
- ttoaddr(end->sourceip, 0, ip_version(end->sourceip), &w->host_srcip);
- w->has_srcip = !end->has_natip;
- }
- else
- {
- anyaddr(AF_INET, &w->host_srcip);
- }
-
- if (family == AF_INET6 && isanyaddr(&end->nexthop))
- {
- anyaddr(AF_INET6, &end->nexthop);
- }
- w->host_nexthop = end->nexthop;
-
- if (w->has_client)
- {
- char *pos;
- int len = 0;
-
- pos = strchr(end->subnet, ',');
- if (pos)
- {
- len = pos - end->subnet;
- }
- ttosubnet(end->subnet, len, ip_version(end->subnet), &w->client);
- }
- else
- {
- if (end->has_virt)
- {
- w->virt = end->subnet;
- }
- w->client.addr.u.v4.sin_family = addrtypeof(&w->host_addr);
- }
-
- w->has_client_wildcard = end->has_client_wildcard;
- w->has_port_wildcard = end->has_port_wildcard;
- w->has_natip = end->has_natip;
- w->allow_any = end->allow_any && !end->dns_failed;
- w->modecfg = end->modecfg;
- w->hostaccess = end->hostaccess;
- w->sendcert = end->sendcert;
- w->updown = end->updown;
- w->host_port = IKE_UDP_PORT;
- w->port = end->port;
- w->protocol = end->protocol;
-
- if (w->port != 0)
- {
- int port = htons(w->port);
-
- setportof(port, &w->host_addr);
- setportof(port, &w->client.addr);
- }
-}
-
-static int
-starter_whack_add_pubkey (starter_conn_t *conn, starter_end_t *end
-, const char *lr)
-{
- const char *err;
- static char keyspace[1024 + 4];
- char buf[ADDRTOT_BUF], name[32];
- whack_message_t msg;
-
- init_whack_msg(&msg);
- connection_name(conn, name, sizeof(name));
-
- msg.whack_key = TRUE;
- msg.pubkey_alg = PUBKEY_ALG_RSA;
- if (end->rsakey)
- {
- /* special values to ignore */
- if (streq(end->rsakey, "")
- || streq(end->rsakey, "%none")
- || streq(end->rsakey, "%cert")
- || streq(end->rsakey, "0x00"))
- {
- return 0;
- }
- err = atobytes(end->rsakey, 0, keyspace, sizeof(keyspace), &msg.keyval.len);
- if (err)
- {
- plog("conn %s/%s: rsakey malformed [%s]", name, lr, err);
- return 1;
- }
- if (end->id)
- {
- msg.keyid = end->id;
- }
- else
- {
- addrtot(&end->addr, 0, buf, sizeof(buf));
- msg.keyid = buf;
- }
- msg.keyval.ptr = keyspace;
- return send_whack_msg(&msg);
- }
- return 0;
-}
-
-int starter_whack_add_conn(starter_conn_t *conn)
-{
- char esp_buf[256], name[32];
- whack_message_t msg;
- int r;
-
- init_whack_msg(&msg);
-
- msg.whack_connection = TRUE;
- msg.name = connection_name(conn, name, sizeof(name));
-
- msg.ikev1 = conn->keyexchange == KEY_EXCHANGE_IKEV1;
- msg.addr_family = conn->addr_family;
- msg.tunnel_addr_family = conn->tunnel_addr_family;
- msg.sa_ike_life_seconds = conn->sa_ike_life_seconds;
- msg.sa_ipsec_life_seconds = conn->sa_ipsec_life_seconds;
- msg.sa_rekey_margin = conn->sa_rekey_margin;
- msg.sa_rekey_fuzz = conn->sa_rekey_fuzz;
- msg.sa_keying_tries = conn->sa_keying_tries;
- msg.policy = conn->policy;
- msg.xauth_identity = conn->xauth_identity;
- msg.reqid = conn->reqid;
- msg.mark_in.value = conn->mark_in.value;
- msg.mark_in.mask = conn->mark_in.mask;
- msg.mark_out.value = conn->mark_out.value;
- msg.mark_out.mask = conn->mark_out.mask;
-
- /*
- * Make sure the IKEv2-only policy bits are unset for IKEv1 connections
- */
- msg.policy &= ~POLICY_DONT_REAUTH;
- msg.policy &= ~POLICY_BEET;
- msg.policy &= ~POLICY_MOBIKE;
- msg.policy &= ~POLICY_FORCE_ENCAP;
-
- set_whack_end(&msg.left, &conn->left, conn->addr_family);
- set_whack_end(&msg.right, &conn->right, conn->addr_family);
-
- msg.esp = conn->esp;
- msg.ike = conn->ike;
- msg.pfsgroup = conn->pfsgroup;
-
- /* taken from pluto/whack.c */
- if (msg.pfsgroup)
- {
- snprintf(esp_buf, sizeof (esp_buf), "%s;%s"
- , msg.esp ? msg.esp : ""
- , msg.pfsgroup ? msg.pfsgroup : "");
- msg.esp = esp_buf;
-
- DBG(DBG_CONTROL,
- DBG_log("Setting --esp=%s", msg.esp)
- )
- }
- msg.dpd_delay = conn->dpd_delay;
- msg.dpd_timeout = conn->dpd_timeout;
- msg.dpd_action = conn->dpd_action;
-/* msg.dpd_count = conn->dpd_count; not supported yet by strongSwan */
-
- r = send_whack_msg(&msg);
-
- if (r == 0 && (conn->policy & POLICY_PUBKEY))
- {
- r += starter_whack_add_pubkey (conn, &conn->left, "left");
- r += starter_whack_add_pubkey (conn, &conn->right, "right");
- }
-
- return r;
-}
-
-int starter_whack_del_conn(starter_conn_t *conn)
-{
- char name[32];
- whack_message_t msg;
-
- init_whack_msg(&msg);
- msg.whack_delete = TRUE;
- msg.name = connection_name(conn, name, sizeof(name));
- return send_whack_msg(&msg);
-}
-
-int starter_whack_route_conn(starter_conn_t *conn)
-{
- char name[32];
- whack_message_t msg;
-
- init_whack_msg(&msg);
- msg.whack_route = TRUE;
- msg.name = connection_name(conn, name, sizeof(name));
- return send_whack_msg(&msg);
-}
-
-int starter_whack_initiate_conn(starter_conn_t *conn)
-{
- char name[32];
- whack_message_t msg;
-
- init_whack_msg(&msg);
- msg.whack_initiate = TRUE;
- msg.whack_async = TRUE;
- msg.name = connection_name(conn, name, sizeof(name));
- return send_whack_msg(&msg);
-}
-
-int starter_whack_listen(void)
-{
- whack_message_t msg;
- init_whack_msg(&msg);
- msg.whack_listen = TRUE;
- return send_whack_msg(&msg);
-}
-
-int starter_whack_shutdown(void)
-{
- whack_message_t msg;
-
- init_whack_msg(&msg);
- msg.whack_shutdown = TRUE;
- return send_whack_msg(&msg);
-}
-
-int starter_whack_add_ca(starter_ca_t *ca)
-{
- whack_message_t msg;
-
- init_whack_msg(&msg);
-
- msg.whack_ca = TRUE;
- msg.name = ca->name;
- msg.cacert = ca->cacert;
- msg.ldaphost = ca->ldaphost;
- msg.ldapbase = ca->ldapbase;
- msg.crluri = ca->crluri;
- msg.crluri2 = ca->crluri2;
- msg.ocspuri = ca->ocspuri;
- msg.whack_strict = ca->strict;
-
- return send_whack_msg(&msg);
-}
-
-int starter_whack_del_ca(starter_ca_t *ca)
-{
- whack_message_t msg;
-
- init_whack_msg(&msg);
-
- msg.whack_delete = TRUE;
- msg.whack_ca = TRUE;
- msg.name = ca->name;
-
- return send_whack_msg(&msg);
-}
diff --git a/src/starter/starterwhack.h b/src/starter/starterwhack.h
deleted file mode 100644
index d56b02421..000000000
--- a/src/starter/starterwhack.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* FreeS/WAN whack functions to communicate with pluto (whack.h)
- * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security
- *
- * 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.
- */
-
-#ifndef _STARTER_WHACK_H_
-#define _STARTER_WHACK_H_
-
-#include "confread.h"
-
-extern int starter_whack_add_conn(starter_conn_t *conn);
-extern int starter_whack_del_conn(starter_conn_t *conn);
-extern int starter_whack_route_conn(starter_conn_t *conn);
-extern int starter_whack_initiate_conn(starter_conn_t *conn);
-extern int starter_whack_listen(void);
-extern int starter_whack_shutdown(void);
-extern int starter_whack_add_ca(starter_ca_t *ca);
-extern int starter_whack_del_ca(starter_ca_t *ca);
-
-#endif /* _STARTER_WHACK_H_ */
-
diff --git a/src/stroke/Makefile.in b/src/stroke/Makefile.in
index 946bacc20..acf9d3485 100644
--- a/src/stroke/Makefile.in
+++ b/src/stroke/Makefile.in
@@ -50,6 +50,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
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__installdirs = "$(DESTDIR)$(ipsecdir)"
@@ -60,7 +61,7 @@ am__DEPENDENCIES_1 =
stroke_DEPENDENCIES = \
$(top_builddir)/src/libstrongswan/libstrongswan.la \
$(am__DEPENDENCIES_1)
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -86,6 +87,7 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BFDLIB = @BFDLIB@
BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@@ -180,11 +182,14 @@ 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@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
-default_pkcs11 = @default_pkcs11@
+dev_headers = @dev_headers@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
@@ -201,11 +206,12 @@ 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@
-libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -221,6 +227,7 @@ mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
p_plugins = @p_plugins@
@@ -230,7 +237,6 @@ pdfdir = @pdfdir@
piddir = @piddir@
pki_plugins = @pki_plugins@
plugindir = @plugindir@
-pluto_plugins = @pluto_plugins@
pool_plugins = @pool_plugins@
prefix = @prefix@
program_transform_name = @program_transform_name@
diff --git a/src/stroke/stroke.c b/src/stroke/stroke.c
index bb299567b..03890b517 100644
--- a/src/stroke/stroke.c
+++ b/src/stroke/stroke.c
@@ -140,8 +140,7 @@ static int add_connection(char *name,
msg.type = STR_ADD_CONN;
msg.add_conn.name = push_string(&msg, name);
- msg.add_conn.ikev2 = 1;
- msg.add_conn.auth_method = 2;
+ msg.add_conn.version = 2;
msg.add_conn.mode = 1;
msg.add_conn.mobike = 1;
msg.add_conn.dpd.action = 1;
@@ -408,7 +407,7 @@ static void exit_usage(char *error)
printf(" where: START and optional END define the clients source IP\n");
printf(" Set loglevel for a logging type:\n");
printf(" stroke loglevel TYPE LEVEL\n");
- printf(" where: TYPE is any|dmn|mgr|ike|chd|job|cfg|knl|net|asn|enc|tnc|imc|imv|pts|tls|lib\n");
+ printf(" where: TYPE is any|dmn|mgr|ike|chd|job|cfg|knl|net|asn|enc|tnc|imc|imv|pts|tls|esp|lib\n");
printf(" LEVEL is -1|0|1|2|3|4\n");
printf(" Show connection status:\n");
printf(" stroke status\n");
diff --git a/src/stroke/stroke_msg.h b/src/stroke/stroke_msg.h
index 434122511..662feed69 100644
--- a/src/stroke/stroke_msg.h
+++ b/src/stroke/stroke_msg.h
@@ -152,16 +152,18 @@ struct stroke_end_t {
char *ca;
char *ca2;
char *groups;
+ char *groups2;
char *cert_policy;
char *updown;
char *address;
u_int16_t ikeport;
char *sourceip;
- int sourceip_mask;
+ char *dns;
char *subnets;
int sendcert;
int hostaccess;
int tohost;
+ int allow_any;
u_int8_t protocol;
u_int16_t port;
};
@@ -242,15 +244,13 @@ struct stroke_msg_t {
/* data for STR_ADD_CONN */
struct {
char *name;
- int ikev2;
- /* next three are deprecated, use stroke_end_t.auth instead */
- int auth_method;
- u_int32_t eap_type;
- u_int32_t eap_vendor;
+ int version;
char *eap_identity;
char *aaa_identity;
+ char *xauth_identity;
int mode;
int mobike;
+ int aggressive;
int force_encap;
int ipcomp;
time_t inactivity;
@@ -280,6 +280,7 @@ struct stroke_msg_t {
} rekey;
struct {
time_t delay;
+ time_t timeout;
int action;
} dpd;
struct {
diff --git a/src/whack/Android.mk b/src/whack/Android.mk
deleted file mode 100644
index bf5ec0e98..000000000
--- a/src/whack/Android.mk
+++ /dev/null
@@ -1,30 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-# copy-n-paste from Makefile.am
-LOCAL_SRC_FILES := \
-whack.c whack.h
-
-# build whack ------------------------------------------------------------------
-
-LOCAL_C_INCLUDES += \
- $(libvstr_PATH) \
- $(strongswan_PATH)/src/libstrongswan \
- $(strongswan_PATH)/src/libfreeswan \
- $(strongswan_PATH)/src/libhydra \
- $(strongswan_PATH)/src/pluto
-
-LOCAL_CFLAGS := $(strongswan_CFLAGS)
-
-LOCAL_MODULE := whack
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_ARM_MODE := arm
-
-LOCAL_PRELINK_MODULE := false
-
-LOCAL_SHARED_LIBRARIES += libstrongswan libfreeswan
-
-include $(BUILD_EXECUTABLE)
-
diff --git a/src/whack/Makefile.am b/src/whack/Makefile.am
deleted file mode 100644
index 23374475e..000000000
--- a/src/whack/Makefile.am
+++ /dev/null
@@ -1,18 +0,0 @@
-ipsec_PROGRAMS = whack
-
-whack_SOURCES = \
-whack.c whack.h
-
-INCLUDES = \
--I$(top_srcdir)/src/libstrongswan \
--I$(top_srcdir)/src/libfreeswan \
--I$(top_srcdir)/src/libhydra \
--I$(top_srcdir)/src/pluto
-
-whack_LDADD = \
-$(top_builddir)/src/libstrongswan/libstrongswan.la \
-$(top_builddir)/src/libfreeswan/libfreeswan.a
-
-AM_CFLAGS = -DDEBUG -DIPSEC_PIDDIR=\"${piddir}\"
-
-EXTRA_DIST = Android.mk
diff --git a/src/whack/whack.c b/src/whack/whack.c
deleted file mode 100644
index a7945d6d8..000000000
--- a/src/whack/whack.c
+++ /dev/null
@@ -1,1959 +0,0 @@
-/* command interface to Pluto
- * Copyright (C) 1997 Angelos D. Keromytis.
- * Copyright (C) 1998-2001 D. Hugh Redelmeier.
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <getopt.h>
-#include <assert.h>
-
-#include <freeswan.h>
-
-#include <utils/optionsfrom.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "whack.h"
-
-static void help(void)
-{
- fprintf(stderr
- , "Usage:\n\n"
- "all forms:"
- " [--optionsfrom <filename>]"
- " [--ctlbase <path>]"
- " [--label <string>]"
- "\n\n"
- "help: whack"
- " [--help]"
- " [--version]"
- "\n\n"
- "connection: whack"
- " --name <connection_name>"
- " \\\n "
- " [--ipv4 | --ipv6]"
- " [--tunnelipv4 | --tunnelipv6]"
- " \\\n "
- " (--host <ip-address> | --id <identity>)"
- " \\\n "
- " [--cert <path>]"
- " [--ca <distinguished name>]"
- " [--sendcert <policy>]"
- " \\\n "
- " [--groups <access control groups>]"
- " \\\n "
- " [--ikeport <port-number>]"
- " [--nexthop <ip-address>]"
- " [--srcip <ip-address>]"
- " \\\n "
- " [--client <subnet> | --clientwithin <address range>]"
- " [--clientprotoport <protocol>/<port>]"
- " \\\n "
- " [--dnskeyondemand]"
- " [--updown <updown>]"
- " \\\n "
- " --to"
- " (--host <ip-address> | --id <identity>)"
- " \\\n "
- " [--cert <path>]"
- " [--ca <distinguished name>]"
- " [--sendcert <policy>]"
- " \\\n "
- " [--ikeport <port-number>]"
- " [--nexthop <ip-address>]"
- " [--srcip <ip-address>]"
- " \\\n "
- " [--client <subnet> | --clientwithin <address range>]"
- " [--clientprotoport <protocol>/<port>]"
- " \\\n "
- " [--dnskeyondemand]"
- " [--updown <updown>]"
- " [--psk]"
- " [--rsasig]"
- " \\\n "
- " [--encrypt]"
- " [--authenticate]"
- " [--compress]"
- " [--tunnel]"
- " [--pfs]"
- " \\\n "
- " [--ikelifetime <seconds>]"
- " [--ipseclifetime <seconds>]"
- " \\\n "
- " [--reykeymargin <seconds>]"
- " [--reykeyfuzz <percentage>]"
- " \\\n "
- " [--keyingtries <count>]"
- " \\\n "
- " [--esp <esp-algos>]"
- " \\\n "
- " [--dontrekey]"
-
- " [--dpdaction (none|clear|hold|restart)]"
- " \\\n "
- " [--dpddelay <seconds> --dpdtimeout <seconds>]"
- " \\\n "
- " [--initiateontraffic|--pass|--drop|--reject]"
- " \\\n "
- " [--failnone|--failpass|--faildrop|--failreject]"
- "\n\n"
- "routing: whack"
- " (--route | --unroute)"
- " --name <connection_name>"
- "\n\n"
- "initiation:"
- "\n "
- " whack"
- " (--initiate | --terminate)"
- " --name <connection_name>"
- " [--asynchronous]"
- "\n\n"
- "opportunistic initiation: whack"
- " [--tunnelipv4 | --tunnelipv6]"
- " \\\n "
- " --oppohere <ip-address>"
- " --oppothere <ip-address>"
- "\n\n"
- "delete: whack"
- " --delete"
- " (--name <connection_name> | --caname <ca name>)"
- "\n\n"
- "deletestate: whack"
- " --deletestate <state_object_number>"
- " --crash <ip-address>"
- "\n\n"
- "pubkey: whack"
- " --keyid <id>"
- " [--addkey]"
- " [--pubkeyrsa <key>]"
- "\n\n"
- "myid: whack"
- " --myid <id>"
- "\n\n"
- "ca: whack"
- " --caname <name>"
- " --cacert <path>"
- " \\\n "
- " [--ldaphost <hostname>]"
- " [--ldapbase <base>]"
- " \\\n "
- " [--crluri <uri>]"
- " [--crluri2 <uri>]"
- " [--ocspuri <uri>]"
- " [--strictcrlpolicy]"
- "\n\n"
-#ifdef DEBUG
- "debug: whack [--name <connection_name>]"
- " \\\n "
- " [--debug-none]"
- " [--debug-all]"
- " \\\n "
- " [--debug-raw]"
- " [--debug-crypt]"
- " [--debug-parsing]"
- " [--debug-emitting]"
- " \\\n "
- " [--debug-control]"
- " [--debug-lifecycle]"
- " [--debug-kernel]"
- " [--debug-dns]"
- " \\\n "
- " [--debug-natt]"
- " [--debug-oppo]"
- " [--debug-controlmore]"
- " [--debug-private]"
- "\n\n"
-#endif
- "leases: whack --leases"
- " [--name <connection_name>]"
- " [--lease-addr <ip-address> | --lease-id <identity>]"
- "\n\n"
- "listen: whack"
- " (--listen | --unlisten)"
- "\n\n"
- "list: whack [--utc]"
- " [--listalgs]"
- " [--listpubkeys]"
- " [--listcerts]"
- " [--listcacerts]"
- " \\\n "
- " [--listacerts]"
- " [--listaacerts]"
- " [--listocspcerts]"
- " [--listgroups]"
- " \\\n "
- " [--listcainfos]"
- " [--listcrls]"
- " [--listocsp]"
- " [--listcards]"
- " [--listplugins]"
- " [--listall]"
- "\n\n"
- "purge: whack"
- " [--purgeocsp]"
- "\n\n"
- "reread: whack"
- " [--rereadsecrets]"
- " [--rereadcacerts]"
- " [--rereadaacerts]"
- " \\\n "
- " [--rereadocspcerts]"
- " [--rereadacerts]"
- " [--rereadcrls]"
- " [--rereadall]"
- "\n\n"
- "status: whack"
- " [--name <connection_name>] --status|--statusall"
- "\n\n"
- "scdecrypt: whack"
- " --scencrypt|scdecrypt <value>"
- " [--inbase <base>]"
- " [--outbase <base>]"
- " [--keyid <id>]"
- "\n\n"
- "shutdown: whack"
- " --shutdown"
- "\n\n"
- "strongSwan "VERSION"\n");
-}
-
-static const char *label = NULL; /* --label operand, saved for diagnostics */
-
-static const char *name = NULL; /* --name operand, saved for diagnostics */
-
-/* options read by optionsfrom */
-options_t *options;
-
-/**
- * exit whack after cleaning up
- */
-static void whack_exit(int status)
-{
- options->destroy(options);
- exit(status);
-}
-
-/**
- * print a string as a diagnostic, then exit whack unhappily
- */
-static void diag(const char *mess)
-{
- if (mess != NULL)
- {
- fprintf(stderr, "whack error: ");
- if (label != NULL)
- {
- fprintf(stderr, "%s ", label);
- }
- if (name != NULL)
- {
- fprintf(stderr, "\"%s\" ", name);
- }
- fprintf(stderr, "%s\n", mess);
- }
- whack_exit(RC_WHACK_PROBLEM);
-}
-
-/* conditially calls diag; prints second arg, if non-NULL, as quoted string */
-static void diagq(err_t ugh, const char *this)
-{
- if (ugh != NULL)
- {
- if (this == NULL)
- {
- diag(ugh);
- }
- else
- {
- char buf[120]; /* arbitrary limit */
-
- snprintf(buf, sizeof(buf), "%s \"%s\"", ugh, this);
- diag(buf);
- }
- }
-}
-
-/* complex combined operands return one of these enumerated values
- * Note: these become flags in an lset_t. Since there are more than
- * 32, we partition them into:
- * - OPT_* options (most random options)
- * - LST_* options (list various internal data)
- * - DBGOPT_* option (DEBUG options)
- * - END_* options (End description options)
- * - CD_* options (Connection Description options)
- * - CA_* options (CA description options)
- */
-enum {
-# define OPT_FIRST OPT_CTLBASE
- OPT_CTLBASE,
- OPT_NAME,
-
- OPT_CD,
-
- OPT_KEYID,
- OPT_ADDKEY,
- OPT_PUBKEYRSA,
-
- OPT_MYID,
-
- OPT_ROUTE,
- OPT_UNROUTE,
-
- OPT_INITIATE,
- OPT_TERMINATE,
- OPT_DELETE,
- OPT_DELETESTATE,
- OPT_LISTEN,
- OPT_UNLISTEN,
-
- OPT_LEASES,
- OPT_LEASEADDR,
- OPT_LEASEID,
-
- OPT_PURGEOCSP,
-
- OPT_REREADSECRETS,
- OPT_REREADCACERTS,
- OPT_REREADAACERTS,
- OPT_REREADOCSPCERTS,
- OPT_REREADACERTS,
- OPT_REREADCRLS,
- OPT_REREADALL,
-
- OPT_STATUS,
- OPT_STATUSALL,
- OPT_SHUTDOWN,
-
- OPT_OPPO_HERE,
- OPT_OPPO_THERE,
-
- OPT_ASYNC,
- OPT_DELETECRASH,
-
-# define OPT_LAST OPT_ASYNC /* last "normal" option */
-
-/* Smartcard options */
-
-# define SC_FIRST SC_ENCRYPT /* first smartcard option */
-
- SC_ENCRYPT,
- SC_DECRYPT,
- SC_INBASE,
- SC_OUTBASE,
-
-# define SC_LAST SC_OUTBASE /* last "smartcard" option */
-
-/* List options */
-
-# define LST_FIRST LST_UTC /* first list option */
- LST_UTC,
- LST_ALGS,
- LST_PUBKEYS,
- LST_CERTS,
- LST_CACERTS,
- LST_ACERTS,
- LST_AACERTS,
- LST_OCSPCERTS,
- LST_GROUPS,
- LST_CAINFOS,
- LST_CRLS,
- LST_OCSP,
- LST_CARDS,
- LST_PLUGINS,
- LST_ALL,
-
-# define LST_LAST LST_ALL /* last list option */
-
-/* Connection End Description options */
-
-# define END_FIRST END_HOST /* first end description */
- END_HOST,
- END_ID,
- END_CERT,
- END_CA,
- END_SENDCERT,
- END_GROUPS,
- END_IKEPORT,
- END_NEXTHOP,
- END_CLIENT,
- END_CLIENTWITHIN,
- END_CLIENTPROTOPORT,
- END_DNSKEYONDEMAND,
- END_SRCIP,
- END_HOSTACCESS,
- END_UPDOWN,
-
-#define END_LAST END_UPDOWN /* last end description*/
-
-/* Connection Description options -- segregated */
-
-# define CD_FIRST CD_TO /* first connection description */
- CD_TO,
-
-# define CD_POLICY_FIRST CD_PSK
- CD_PSK, /* same order as POLICY_* */
- CD_RSASIG, /* same order as POLICY_* */
- CD_ENCRYPT, /* same order as POLICY_* */
- CD_AUTHENTICATE, /* same order as POLICY_* */
- CD_COMPRESS, /* same order as POLICY_* */
- CD_TUNNEL, /* same order as POLICY_* */
- CD_PFS, /* same order as POLICY_* */
- CD_DISABLEARRIVALCHECK, /* same order as POLICY_* */
- CD_SHUNT0, /* same order as POLICY_* */
- CD_SHUNT1, /* same order as POLICY_* */
- CD_FAIL0, /* same order as POLICY_* */
- CD_FAIL1, /* same order as POLICY_* */
- CD_DONT_REKEY, /* same order as POLICY_* */
-
- CD_TUNNELIPV4,
- CD_TUNNELIPV6,
- CD_CONNIPV4,
- CD_CONNIPV6,
-
- CD_IKELIFETIME,
- CD_IPSECLIFETIME,
- CD_RKMARGIN,
- CD_RKFUZZ,
- CD_KTRIES,
- CD_DPDACTION,
- CD_DPDDELAY,
- CD_DPDTIMEOUT,
- CD_IKE,
- CD_PFSGROUP,
- CD_ESP,
-
-# define CD_LAST CD_ESP /* last connection description */
-
-/* Certificate Authority (CA) description options */
-
-# define CA_FIRST CA_NAME /* first ca description */
-
- CA_NAME,
- CA_CERT,
- CA_LDAPHOST,
- CA_LDAPBASE,
- CA_CRLURI,
- CA_CRLURI2,
- CA_OCSPURI,
- CA_STRICT
-
-# define CA_LAST CA_STRICT /* last ca description */
-
-#ifdef DEBUG /* must be last so others are less than 32 to fit in lset_t */
-# define DBGOPT_FIRST DBGOPT_NONE
- ,
- /* NOTE: these definitions must match DBG_* and IMPAIR_* in constants.h */
- DBGOPT_NONE,
- DBGOPT_ALL,
-
- DBGOPT_RAW, /* same order as DBG_* */
- DBGOPT_CRYPT, /* same order as DBG_* */
- DBGOPT_PARSING, /* same order as DBG_* */
- DBGOPT_EMITTING, /* same order as DBG_* */
- DBGOPT_CONTROL, /* same order as DBG_* */
- DBGOPT_LIFECYCLE, /* same order as DBG_* */
- DBGOPT_KERNEL, /* same order as DBG_* */
- DBGOPT_DNS, /* same order as DBG_* */
- DBGOPT_NATT, /* same order as DBG_* */
- DBGOPT_OPPO, /* same order as DBG_* */
- DBGOPT_CONTROLMORE, /* same order as DBG_* */
-
- DBGOPT_PRIVATE, /* same order as DBG_* */
-
- DBGOPT_IMPAIR_DELAY_ADNS_KEY_ANSWER, /* same order as IMPAIR_* */
- DBGOPT_IMPAIR_DELAY_ADNS_TXT_ANSWER, /* same order as IMPAIR_* */
- DBGOPT_IMPAIR_BUST_MI2, /* same order as IMPAIR_* */
- DBGOPT_IMPAIR_BUST_MR2 /* same order as IMPAIR_* */
-
-# define DBGOPT_LAST DBGOPT_IMPAIR_BUST_MR2
-#endif
-
-};
-
-/* Carve up space for result from getop_long.
- * Stupidly, the only result is an int.
- * Numeric arg is bit immediately left of basic value.
- *
- */
-#define OPTION_OFFSET 256 /* to get out of the way of letter options */
-#define NUMERIC_ARG (1 << 9) /* expect a numeric argument */
-#define AUX_SHIFT 10 /* amount to shift for aux information */
-
-static const struct option long_opts[] = {
-# define OO OPTION_OFFSET
- /* name, has_arg, flag, val */
-
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, 'v' },
- { "optionsfrom", required_argument, NULL, '+' },
- { "label", required_argument, NULL, 'l' },
-
- { "ctlbase", required_argument, NULL, OPT_CTLBASE + OO },
- { "name", required_argument, NULL, OPT_NAME + OO },
-
- { "keyid", required_argument, NULL, OPT_KEYID + OO },
- { "addkey", no_argument, NULL, OPT_ADDKEY + OO },
- { "pubkeyrsa", required_argument, NULL, OPT_PUBKEYRSA + OO },
-
- { "myid", required_argument, NULL, OPT_MYID + OO },
-
- { "route", no_argument, NULL, OPT_ROUTE + OO },
- { "unroute", no_argument, NULL, OPT_UNROUTE + OO },
-
- { "initiate", no_argument, NULL, OPT_INITIATE + OO },
- { "terminate", no_argument, NULL, OPT_TERMINATE + OO },
- { "delete", no_argument, NULL, OPT_DELETE + OO },
- { "deletestate", required_argument, NULL, OPT_DELETESTATE + OO + NUMERIC_ARG },
- { "crash", required_argument, NULL, OPT_DELETECRASH + OO },
- { "listen", no_argument, NULL, OPT_LISTEN + OO },
- { "unlisten", no_argument, NULL, OPT_UNLISTEN + OO },
-
- { "leases", no_argument, NULL, OPT_LEASES + OO },
- { "lease-addr", required_argument, NULL, OPT_LEASEADDR + OO },
- { "lease-id", required_argument, NULL, OPT_LEASEID + OO },
-
- { "purgeocsp", no_argument, NULL, OPT_PURGEOCSP + OO },
-
- { "rereadsecrets", no_argument, NULL, OPT_REREADSECRETS + OO },
- { "rereadcacerts", no_argument, NULL, OPT_REREADCACERTS + OO },
- { "rereadaacerts", no_argument, NULL, OPT_REREADAACERTS + OO },
- { "rereadocspcerts", no_argument, NULL, OPT_REREADOCSPCERTS + OO },
- { "rereadacerts", no_argument, NULL, OPT_REREADACERTS + OO },
- { "rereadcrls", no_argument, NULL, OPT_REREADCRLS + OO },
- { "rereadall", no_argument, NULL, OPT_REREADALL + OO },
- { "status", no_argument, NULL, OPT_STATUS + OO },
- { "statusall", no_argument, NULL, OPT_STATUSALL + OO },
- { "shutdown", no_argument, NULL, OPT_SHUTDOWN + OO },
-
- { "oppohere", required_argument, NULL, OPT_OPPO_HERE + OO },
- { "oppothere", required_argument, NULL, OPT_OPPO_THERE + OO },
-
- { "asynchronous", no_argument, NULL, OPT_ASYNC + OO },
-
- /* smartcard options */
-
- { "scencrypt", required_argument, NULL, SC_ENCRYPT + OO },
- { "scdecrypt", required_argument, NULL, SC_DECRYPT + OO },
- { "inbase", required_argument, NULL, SC_INBASE + OO },
- { "outbase", required_argument, NULL, SC_OUTBASE + OO },
-
- /* list options */
-
- { "utc", no_argument, NULL, LST_UTC + OO },
- { "listalgs", no_argument, NULL, LST_ALGS + OO },
- { "listpubkeys", no_argument, NULL, LST_PUBKEYS + OO },
- { "listcerts", no_argument, NULL, LST_CERTS + OO },
- { "listcacerts", no_argument, NULL, LST_CACERTS + OO },
- { "listacerts", no_argument, NULL, LST_ACERTS + OO },
- { "listaacerts", no_argument, NULL, LST_AACERTS + OO },
- { "listocspcerts", no_argument, NULL, LST_OCSPCERTS + OO },
- { "listgroups", no_argument, NULL, LST_GROUPS + OO },
- { "listcainfos", no_argument, NULL, LST_CAINFOS + OO },
- { "listcrls", no_argument, NULL, LST_CRLS + OO },
- { "listocsp", no_argument, NULL, LST_OCSP + OO },
- { "listcards", no_argument, NULL, LST_CARDS + OO },
- { "listplugins", no_argument, NULL, LST_PLUGINS + OO },
- { "listall", no_argument, NULL, LST_ALL + OO },
-
- /* options for an end description */
-
- { "host", required_argument, NULL, END_HOST + OO },
- { "id", required_argument, NULL, END_ID + OO },
- { "cert", required_argument, NULL, END_CERT + OO },
- { "ca", required_argument, NULL, END_CA + OO },
- { "sendcert", required_argument, NULL, END_SENDCERT + OO },
- { "groups", required_argument, NULL, END_GROUPS + OO },
- { "ikeport", required_argument, NULL, END_IKEPORT + OO + NUMERIC_ARG },
- { "nexthop", required_argument, NULL, END_NEXTHOP + OO },
- { "client", required_argument, NULL, END_CLIENT + OO },
- { "clientwithin", required_argument, NULL, END_CLIENTWITHIN + OO },
- { "clientprotoport", required_argument, NULL, END_CLIENTPROTOPORT + OO },
- { "dnskeyondemand", no_argument, NULL, END_DNSKEYONDEMAND + OO },
- { "srcip", required_argument, NULL, END_SRCIP + OO },
- { "hostaccess", no_argument, NULL, END_HOSTACCESS + OO },
- { "updown", required_argument, NULL, END_UPDOWN + OO },
-
- /* options for a connection description */
-
- { "to", no_argument, NULL, CD_TO + OO },
-
- { "psk", no_argument, NULL, CD_PSK + OO },
- { "rsasig", no_argument, NULL, CD_RSASIG + OO },
-
- { "encrypt", no_argument, NULL, CD_ENCRYPT + OO },
- { "authenticate", no_argument, NULL, CD_AUTHENTICATE + OO },
- { "compress", no_argument, NULL, CD_COMPRESS + OO },
- { "tunnel", no_argument, NULL, CD_TUNNEL + OO },
- { "tunnelipv4", no_argument, NULL, CD_TUNNELIPV4 + OO },
- { "tunnelipv6", no_argument, NULL, CD_TUNNELIPV6 + OO },
- { "pfs", no_argument, NULL, CD_PFS + OO },
- { "disablearrivalcheck", no_argument, NULL, CD_DISABLEARRIVALCHECK + OO },
- { "initiateontraffic", no_argument, NULL
- , CD_SHUNT0 + (POLICY_SHUNT_TRAP >> POLICY_SHUNT_SHIFT << AUX_SHIFT) + OO },
- { "pass", no_argument, NULL
- , CD_SHUNT0 + (POLICY_SHUNT_PASS >> POLICY_SHUNT_SHIFT << AUX_SHIFT) + OO },
- { "drop", no_argument, NULL
- , CD_SHUNT0 + (POLICY_SHUNT_DROP >> POLICY_SHUNT_SHIFT << AUX_SHIFT) + OO },
- { "reject", no_argument, NULL
- , CD_SHUNT0 + (POLICY_SHUNT_REJECT >> POLICY_SHUNT_SHIFT << AUX_SHIFT) + OO },
- { "failnone", no_argument, NULL
- , CD_FAIL0 + (POLICY_FAIL_NONE >> POLICY_FAIL_SHIFT << AUX_SHIFT) + OO },
- { "failpass", no_argument, NULL
- , CD_FAIL0 + (POLICY_FAIL_PASS >> POLICY_FAIL_SHIFT << AUX_SHIFT) + OO },
- { "faildrop", no_argument, NULL
- , CD_FAIL0 + (POLICY_FAIL_DROP >> POLICY_FAIL_SHIFT << AUX_SHIFT) + OO },
- { "failreject", no_argument, NULL
- , CD_FAIL0 + (POLICY_FAIL_REJECT >> POLICY_FAIL_SHIFT << AUX_SHIFT) + OO },
- { "dontrekey", no_argument, NULL, CD_DONT_REKEY + OO },
- { "ipv4", no_argument, NULL, CD_CONNIPV4 + OO },
- { "ipv6", no_argument, NULL, CD_CONNIPV6 + OO },
-
- { "ikelifetime", required_argument, NULL, CD_IKELIFETIME + OO + NUMERIC_ARG },
- { "ipseclifetime", required_argument, NULL, CD_IPSECLIFETIME + OO + NUMERIC_ARG },
- { "rekeymargin", required_argument, NULL, CD_RKMARGIN + OO + NUMERIC_ARG },
- { "rekeywindow", required_argument, NULL, CD_RKMARGIN + OO + NUMERIC_ARG }, /* OBSOLETE */
- { "rekeyfuzz", required_argument, NULL, CD_RKFUZZ + OO + NUMERIC_ARG },
- { "keyingtries", required_argument, NULL, CD_KTRIES + OO + NUMERIC_ARG },
- { "dpdaction", required_argument, NULL, CD_DPDACTION + OO },
- { "dpddelay", required_argument, NULL, CD_DPDDELAY + OO + NUMERIC_ARG },
- { "dpdtimeout", required_argument, NULL, CD_DPDTIMEOUT + OO + NUMERIC_ARG },
- { "ike", required_argument, NULL, CD_IKE + OO },
- { "pfsgroup", required_argument, NULL, CD_PFSGROUP + OO },
- { "esp", required_argument, NULL, CD_ESP + OO },
-
- /* options for a ca description */
-
- { "caname", required_argument, NULL, CA_NAME + OO },
- { "cacert", required_argument, NULL, CA_CERT + OO },
- { "ldaphost", required_argument, NULL, CA_LDAPHOST + OO },
- { "ldapbase", required_argument, NULL, CA_LDAPBASE + OO },
- { "crluri", required_argument, NULL, CA_CRLURI + OO },
- { "crluri2", required_argument, NULL, CA_CRLURI2 + OO },
- { "ocspuri", required_argument, NULL, CA_OCSPURI + OO },
- { "strictcrlpolicy", no_argument, NULL, CA_STRICT + OO },
-
-#ifdef DEBUG
- { "debug-none", no_argument, NULL, DBGOPT_NONE + OO },
- { "debug-all]", no_argument, NULL, DBGOPT_ALL + OO },
- { "debug-raw", no_argument, NULL, DBGOPT_RAW + OO },
- { "debug-crypt", no_argument, NULL, DBGOPT_CRYPT + OO },
- { "debug-parsing", no_argument, NULL, DBGOPT_PARSING + OO },
- { "debug-emitting", no_argument, NULL, DBGOPT_EMITTING + OO },
- { "debug-control", no_argument, NULL, DBGOPT_CONTROL + OO },
- { "debug-lifecycle", no_argument, NULL, DBGOPT_LIFECYCLE + OO },
- { "debug-klips", no_argument, NULL, DBGOPT_KERNEL + OO },
- { "debug-kernel", no_argument, NULL, DBGOPT_KERNEL + OO },
- { "debug-dns", no_argument, NULL, DBGOPT_DNS + OO },
- { "debug-natt", no_argument, NULL, DBGOPT_NATT + OO },
- { "debug-oppo", no_argument, NULL, DBGOPT_OPPO + OO },
- { "debug-controlmore", no_argument, NULL, DBGOPT_CONTROLMORE + OO },
- { "debug-private", no_argument, NULL, DBGOPT_PRIVATE + OO },
-
- { "impair-delay-adns-key-answer", no_argument, NULL, DBGOPT_IMPAIR_DELAY_ADNS_KEY_ANSWER + OO },
- { "impair-delay-adns-txt-answer", no_argument, NULL, DBGOPT_IMPAIR_DELAY_ADNS_TXT_ANSWER + OO },
- { "impair-bust-mi2", no_argument, NULL, DBGOPT_IMPAIR_BUST_MI2 + OO },
- { "impair-bust-mr2", no_argument, NULL, DBGOPT_IMPAIR_BUST_MR2 + OO },
-#endif
-# undef OO
- { 0,0,0,0 }
-};
-
-struct sockaddr_un ctl_addr = { AF_UNIX, DEFAULT_CTLBASE CTL_SUFFIX };
-
-/* helper variables and function to encode strings from whack message */
-
-static char *next_str,*str_roof;
-
-static bool pack_str(char **p)
-{
- const char *s = *p == NULL? "" : *p; /* note: NULL becomes ""! */
- size_t len = strlen(s) + 1;
-
- if (str_roof - next_str < (ptrdiff_t)len)
- {
- return FALSE; /* fishy: no end found */
- }
- else
- {
- strcpy(next_str, s);
- next_str += len;
- *p = NULL; /* don't send pointers on the wire! */
- return TRUE;
- }
-}
-
-static void check_life_time(time_t life, time_t limit, const char *which,
- const whack_message_t *msg)
-{
- time_t mint = msg->sa_rekey_margin * (100 + msg->sa_rekey_fuzz) / 100;
-
- if (life > limit)
- {
- char buf[200]; /* arbitrary limit */
-
- snprintf(buf, sizeof(buf)
- , "%s [%lu seconds] must be less than %lu seconds"
- , which, (unsigned long)life, (unsigned long)limit);
- diag(buf);
- }
- if ((msg->policy & POLICY_DONT_REKEY) == LEMPTY && life <= mint)
- {
- char buf[200]; /* arbitrary limit */
-
- snprintf(buf, sizeof(buf)
- , "%s [%lu] must be greater than"
- " rekeymargin*(100+rekeyfuzz)/100 [%lu*(100+%lu)/100 = %lu]"
- , which
- , (unsigned long)life
- , (unsigned long)msg->sa_rekey_margin
- , (unsigned long)msg->sa_rekey_fuzz
- , (unsigned long)mint);
- diag(buf);
- }
-}
-
-static void clear_end(whack_end_t *e)
-{
- zero(e);
- e->id = NULL;
- e->cert = NULL;
- e->ca = NULL;
- e->updown = NULL;
- e->host_port = IKE_UDP_PORT;
-}
-
-static void update_ports(whack_message_t *m)
-{
- int port;
-
- if (m->left.port != 0) {
- port = htons(m->left.port);
- setportof(port, &m->left.host_addr);
- setportof(port, &m->left.client.addr);
- }
- if (m->right.port != 0) {
- port = htons(m->right.port);
- setportof(port, &m->right.host_addr);
- setportof(port, &m->right.client.addr);
- }
-}
-
-static void check_end(whack_end_t *this, whack_end_t *that,
- bool default_nexthop, sa_family_t caf, sa_family_t taf)
-{
- if (caf != addrtypeof(&this->host_addr))
- diag("address family of host inconsistent");
-
- if (default_nexthop)
- {
- if (isanyaddr(&that->host_addr))
- diag("our nexthop must be specified when other host is a %any or %opportunistic");
- this->host_nexthop = that->host_addr;
- }
-
- if (caf != addrtypeof(&this->host_nexthop))
- diag("address family of nexthop inconsistent");
-
- if (this->has_client)
- {
- if (taf != subnettypeof(&this->client))
- diag("address family of client subnet inconsistent");
- }
- else
- {
- /* fill in anyaddr-anyaddr as (missing) client subnet */
- ip_address cn;
-
- diagq(anyaddr(caf, &cn), NULL);
- diagq(rangetosubnet(&cn, &cn, &this->client), NULL);
- }
-
- /* fill in anyaddr if source IP is not defined */
- if (!this->has_srcip)
- diagq(anyaddr(caf, &this->host_srcip), optarg);
-
- /* check protocol */
- if (this->protocol != that->protocol)
- diag("the protocol for leftprotoport and rightprotoport must be the same");
-}
-
-static void get_secret(int sock)
-{
- const char *buf = NULL, *secret;
- int len;
-
- fflush(stdout);
- usleep(20000); /* give fflush time for flushing */
-#ifdef HAVE_GETPASS
- buf = getpass("Enter: ");
-#endif
- secret = (buf == NULL)? "" : buf;
-
- /* send the secret to pluto */
- len = strlen(secret) + 1;
- if (write(sock, secret, len) != len)
- {
- int e = errno;
-
- fprintf(stderr, "whack: write() failed (%d %s)\n", e, strerror(e));
- exit(RC_WHACK_PROBLEM);
- }
-}
-
-/* This is a hack for initiating ISAKMP exchanges. */
-
-int main(int argc, char **argv)
-{
- whack_message_t msg;
- char esp_buf[256]; /* uses snprintf */
- lset_t
- opts_seen = LEMPTY,
- sc_seen = LEMPTY,
- lst_seen = LEMPTY,
- cd_seen = LEMPTY,
- ca_seen = LEMPTY,
- end_seen = LEMPTY,
- end_seen_before_to = LEMPTY;
- const char
- *af_used_by = NULL,
- *tunnel_af_used_by = NULL;
-
- /* check division of numbering space */
-#ifdef DEBUG
- assert(OPTION_OFFSET + DBGOPT_LAST < NUMERIC_ARG);
-#else
- assert(OPTION_OFFSET + CA_LAST < NUMERIC_ARG);
-#endif
- assert(OPT_LAST - OPT_FIRST < (sizeof opts_seen * BITS_PER_BYTE));
- assert(SC_LAST - SC_FIRST < (sizeof sc_seen * BITS_PER_BYTE));
- assert(LST_LAST - LST_FIRST < (sizeof lst_seen * BITS_PER_BYTE));
- assert(END_LAST - END_FIRST < (sizeof end_seen * BITS_PER_BYTE));
- assert(CD_LAST - CD_FIRST < (sizeof cd_seen * BITS_PER_BYTE));
- assert(CA_LAST - CA_FIRST < (sizeof ca_seen * BITS_PER_BYTE));
-#ifdef DEBUG /* must be last so others are less than (sizeof cd_seen * BITS_PER_BYTE) to fit in lset_t */
- assert(DBGOPT_LAST - DBGOPT_FIRST < (sizeof cd_seen * BITS_PER_BYTE));
-#endif
- /* check that POLICY bit assignment matches with CD_ */
- assert(LELEM(CD_DONT_REKEY - CD_POLICY_FIRST) == POLICY_DONT_REKEY);
-
- zero(&msg);
-
- clear_end(&msg.right); /* left set from this after --to */
-
- msg.name = NULL;
- msg.keyid = NULL;
- msg.keyval.ptr = NULL;
- msg.esp = NULL;
- msg.ike = NULL;
- msg.pfsgroup = NULL;
-
- /* if a connection is added via whack then we assume IKEv1 */
- msg.ikev1 = TRUE;
-
- msg.sa_ike_life_seconds = OAKLEY_ISAKMP_SA_LIFETIME_DEFAULT;
- msg.sa_ipsec_life_seconds = PLUTO_SA_LIFE_DURATION_DEFAULT;
- msg.sa_rekey_margin = SA_REPLACEMENT_MARGIN_DEFAULT;
- msg.sa_rekey_fuzz = SA_REPLACEMENT_FUZZ_DEFAULT;
- msg.sa_keying_tries = SA_REPLACEMENT_RETRIES_DEFAULT;
-
- msg.addr_family = AF_INET;
- msg.tunnel_addr_family = AF_INET;
-
- msg.cacert = NULL;
- msg.ldaphost = NULL;
- msg.ldapbase = NULL;
- msg.crluri = NULL;
- msg.crluri2 = NULL;
- msg.ocspuri = NULL;
-
- options = options_create();
-
- for (;;)
- {
- int long_index;
- unsigned long opt_whole = 0; /* numeric argument for some flags */
-
- /* Note: we don't like the way short options get parsed
- * by getopt_long, so we simply pass an empty string as
- * the list. It could be "hp:d:c:o:eatfs" "NARXPECK".
- */
- int c = getopt_long(argc, argv, "", long_opts, &long_index) - OPTION_OFFSET;
- int aux = 0;
-
- /* decode a numeric argument, if expected */
- if (0 <= c)
- {
- if (c & NUMERIC_ARG)
- {
- char *endptr;
-
- c -= NUMERIC_ARG;
- opt_whole = strtoul(optarg, &endptr, 0);
-
- if (*endptr != '\0' || endptr == optarg)
- diagq("badly formed numeric argument", optarg);
- }
- if (c >= (1 << AUX_SHIFT))
- {
- aux = c >> AUX_SHIFT;
- c -= aux << AUX_SHIFT;
- }
- }
-
- /* per-class option processing */
- if (0 <= c && c <= OPT_LAST)
- {
- /* OPT_* options get added to opts_seen.
- * Reject repeated options (unless later code intervenes).
- */
- lset_t f = LELEM(c);
-
- if (opts_seen & f)
- diagq("duplicated flag", long_opts[long_index].name);
- opts_seen |= f;
- }
- else if (SC_FIRST <= c && c <= SC_LAST)
- {
- /* SC_* options get added to sc_seen.
- * Reject repeated options (unless later code intervenes).
- */
- lset_t f = LELEM(c - SC_FIRST);
-
- if (sc_seen & f)
- diagq("duplicated flag", long_opts[long_index].name);
- sc_seen |= f;
- }
- else if (LST_FIRST <= c && c <= LST_LAST)
- {
- /* LST_* options get added to lst_seen.
- * Reject repeated options (unless later code intervenes).
- */
- lset_t f = LELEM(c - LST_FIRST);
-
- if (lst_seen & f)
- diagq("duplicated flag", long_opts[long_index].name);
- lst_seen |= f;
- }
-#ifdef DEBUG
- else if (DBGOPT_FIRST <= c && c <= DBGOPT_LAST)
- {
- msg.whack_options = TRUE;
- }
-#endif
- else if (END_FIRST <= c && c <= END_LAST)
- {
- /* END_* options are added to end_seen.
- * Reject repeated options (unless later code intervenes).
- */
- lset_t f = LELEM(c - END_FIRST);
-
- if (end_seen & f)
- diagq("duplicated flag", long_opts[long_index].name);
- end_seen |= f;
- opts_seen |= LELEM(OPT_CD);
- }
- else if (CD_FIRST <= c && c <= CD_LAST)
- {
- /* CD_* options are added to cd_seen.
- * Reject repeated options (unless later code intervenes).
- */
- lset_t f = LELEM(c - CD_FIRST);
-
- if (cd_seen & f)
- diagq("duplicated flag", long_opts[long_index].name);
- cd_seen |= f;
- opts_seen |= LELEM(OPT_CD);
- }
- else if (CA_FIRST <= c && c <= CA_LAST)
- {
- /* CA_* options are added to ca_seen.
- * Reject repeated options (unless later code intervenes).
- */
- lset_t f = LELEM(c - CA_FIRST);
-
- if (ca_seen & f)
- diagq("duplicated flag", long_opts[long_index].name);
- ca_seen |= f;
- }
-
- /* Note: "break"ing from switch terminates loop.
- * most cases should end with "continue".
- */
- switch (c)
- {
- case EOF - OPTION_OFFSET: /* end of flags */
- break;
-
- case 0 - OPTION_OFFSET: /* long option already handled */
- continue;
-
- case ':' - OPTION_OFFSET: /* diagnostic already printed by getopt_long */
- case '?' - OPTION_OFFSET: /* diagnostic already printed by getopt_long */
- diag(NULL); /* print no additional diagnostic, but exit sadly */
- break; /* not actually reached */
-
- case 'h' - OPTION_OFFSET: /* --help */
- help();
- whack_exit(0); /* GNU coding standards say to stop here */
-
- case 'v' - OPTION_OFFSET: /* --version */
- {
- const char **sp = ipsec_copyright_notice();
-
- printf("strongSwan "VERSION"\n");
- for (; *sp != NULL; sp++)
- puts(*sp);
- }
- whack_exit(0); /* GNU coding standards say to stop here */
-
- case 'l' - OPTION_OFFSET: /* --label <string> */
- label = optarg; /* remember for diagnostics */
- continue;
-
- case '+' - OPTION_OFFSET: /* --optionsfrom <filename> */
- if (!options->from(options, optarg, &argc, &argv, optind))
- {
- fprintf(stderr, "optionsfrom failed");
- whack_exit(RC_WHACK_PROBLEM);
- }
- continue;
-
- /* the rest of the options combine in complex ways */
-
- case OPT_CTLBASE: /* --port <ctlbase> */
- if (snprintf(ctl_addr.sun_path, sizeof(ctl_addr.sun_path)
- , "%s%s", optarg, CTL_SUFFIX) == -1)
- diag("<ctlbase>" CTL_SUFFIX " must be fit in a sun_addr");
- continue;
-
- case OPT_NAME: /* --name <connection-name> */
- name = optarg;
- msg.name = optarg;
- continue;
-
- case OPT_KEYID: /* --keyid <identity> */
- msg.whack_key = !msg.whack_sc_op;
- msg.keyid = optarg; /* decoded by Pluto */
- continue;
-
- case OPT_MYID: /* --myid <identity> */
- msg.whack_myid = TRUE;
- msg.myid = optarg; /* decoded by Pluto */
- continue;
-
- case OPT_ADDKEY: /* --addkey */
- msg.whack_addkey = TRUE;
- continue;
-
- case OPT_PUBKEYRSA: /* --pubkeyrsa <key> */
- {
- static char keyspace[RSA_MAX_ENCODING_BYTES]; /* room for 8K bit key */
- char diag_space[TTODATAV_BUF];
- const char *ugh = ttodatav(optarg, 0, 0
- , keyspace, sizeof(keyspace)
- , &msg.keyval.len, diag_space, sizeof(diag_space)
- , TTODATAV_SPACECOUNTS);
-
- if (ugh != NULL)
- {
- char ugh_space[80]; /* perhaps enough space */
-
- snprintf(ugh_space, sizeof(ugh_space)
- , "RSA public-key data malformed (%s)", ugh);
- diagq(ugh_space, optarg);
- }
- msg.pubkey_alg = PUBKEY_ALG_RSA;
- msg.keyval.ptr = keyspace;
- }
- continue;
-
- case OPT_ROUTE: /* --route */
- msg.whack_route = TRUE;
- continue;
-
- case OPT_UNROUTE: /* --unroute */
- msg.whack_unroute = TRUE;
- continue;
-
- case OPT_INITIATE: /* --initiate */
- msg.whack_initiate = TRUE;
- continue;
-
- case OPT_TERMINATE: /* --terminate */
- msg.whack_terminate = TRUE;
- continue;
-
- case OPT_DELETE: /* --delete */
- msg.whack_delete = TRUE;
- continue;
-
- case OPT_DELETESTATE: /* --deletestate <state_object_number> */
- msg.whack_deletestate = TRUE;
- msg.whack_deletestateno = opt_whole;
- continue;
-
- case OPT_DELETECRASH: /* --crash <ip-address> */
- msg.whack_crash = TRUE;
- tunnel_af_used_by = long_opts[long_index].name;
- diagq(ttoaddr(optarg, 0, msg.tunnel_addr_family, &msg.whack_crash_peer), optarg);
- if (isanyaddr(&msg.whack_crash_peer))
- diagq("0.0.0.0 or 0::0 isn't a valid client address", optarg);
- continue;
-
- case OPT_LEASES: /* --leases */
- msg.whack_leases = TRUE;
- continue;
-
- case OPT_LEASEADDR: /* --lease-addr <ip-address> */
- msg.whack_lease_ip = optarg; /* decoded by Pluto */
- continue;
-
- case OPT_LEASEID: /* --lease-id <identity> */
- msg.whack_lease_id = optarg; /* decoded by Pluto */
- continue;
-
- case OPT_LISTEN: /* --listen */
- msg.whack_listen = TRUE;
- continue;
-
- case OPT_UNLISTEN: /* --unlisten */
- msg.whack_unlisten = TRUE;
- continue;
-
- case OPT_PURGEOCSP: /* --purgeocsp */
- msg.whack_purgeocsp = TRUE;
- continue;
-
- case OPT_REREADSECRETS: /* --rereadsecrets */
- case OPT_REREADCACERTS: /* --rereadcacerts */
- case OPT_REREADAACERTS: /* --rereadaacerts */
- case OPT_REREADOCSPCERTS: /* --rereadocspcerts */
- case OPT_REREADACERTS: /* --rereadacerts */
- case OPT_REREADCRLS: /* --rereadcrls */
- msg.whack_reread |= LELEM(c-OPT_REREADSECRETS);
- continue;
-
- case OPT_REREADALL: /* --rereadall */
- msg.whack_reread = REREAD_ALL;
- continue;
-
- case OPT_STATUSALL: /* --statusall */
- msg.whack_statusall = TRUE;
- /* fall through */
-
- case OPT_STATUS: /* --status */
- msg.whack_status = TRUE;
- continue;
-
- case OPT_SHUTDOWN: /* --shutdown */
- msg.whack_shutdown = TRUE;
- continue;
-
- case OPT_OPPO_HERE: /* --oppohere <ip-address> */
- tunnel_af_used_by = long_opts[long_index].name;
- diagq(ttoaddr(optarg, 0, msg.tunnel_addr_family, &msg.oppo_my_client), optarg);
- if (isanyaddr(&msg.oppo_my_client))
- diagq("0.0.0.0 or 0::0 isn't a valid client address", optarg);
- continue;
-
- case OPT_OPPO_THERE: /* --oppohere <ip-address> */
- tunnel_af_used_by = long_opts[long_index].name;
- diagq(ttoaddr(optarg, 0, msg.tunnel_addr_family, &msg.oppo_peer_client), optarg);
- if (isanyaddr(&msg.oppo_peer_client))
- diagq("0.0.0.0 or 0::0 isn't a valid client address", optarg);
- continue;
-
- case OPT_ASYNC:
- msg.whack_async = TRUE;
- continue;
-
- /* Smartcard options */
-
- case SC_ENCRYPT: /* --scencrypt <plaintext data> */
- case SC_DECRYPT: /* --scdecrypt <encrypted data> */
- msg.whack_sc_op = 1 + c - SC_ENCRYPT;
- msg.whack_key = FALSE;
- msg.sc_data = optarg;
- continue;
-
- case SC_INBASE: /* --inform <format> */
- case SC_OUTBASE: /* --outform <format> */
- {
- int base = 0;
-
- if (streq(optarg, "16") || strcaseeq(optarg, "hex"))
- base = 16;
- else if (streq(optarg, "64") || strcaseeq(optarg, "base64"))
- base = 64;
- else if (streq(optarg, "256") || strcaseeq(optarg, "text")
- || strcaseeq(optarg, "ascii"))
- base = 256;
- else
- diagq("not a valid base", optarg);
-
- if (c == SC_INBASE)
- msg.inbase = base;
- else
- msg.outbase = base;
- }
- continue;
-
- /* List options */
-
- case LST_UTC: /* --utc */
- msg.whack_utc = TRUE;
- continue;
-
- case LST_ALGS: /* --listalgs */
- case LST_PUBKEYS: /* --listpubkeys */
- case LST_CERTS: /* --listcerts */
- case LST_CACERTS: /* --listcacerts */
- case LST_ACERTS: /* --listacerts */
- case LST_AACERTS: /* --listaacerts */
- case LST_OCSPCERTS: /* --listocspcerts */
- case LST_GROUPS: /* --listgroups */
- case LST_CAINFOS: /* --listcainfos */
- case LST_CRLS: /* --listcrls */
- case LST_OCSP: /* --listocsp */
- case LST_CARDS: /* --listcards */
- case LST_PLUGINS: /* --listplugins */
- msg.whack_list |= LELEM(c - LST_ALGS);
- continue;
-
- case LST_ALL: /* --listall */
- msg.whack_list = LIST_ALL;
- continue;
-
- /* Connection Description options */
-
- case END_HOST: /* --host <ip-address> */
- {
- lset_t new_policy = LEMPTY;
-
- af_used_by = long_opts[long_index].name;
- diagq(anyaddr(msg.addr_family, &msg.right.host_addr), optarg);
- if (streq(optarg, "%any"))
- {
- }
- else if (streq(optarg, "%opportunistic"))
- {
- /* always use tunnel mode; mark as opportunistic */
- new_policy |= POLICY_TUNNEL | POLICY_OPPO;
- }
- else if (streq(optarg, "%group"))
- {
- /* always use tunnel mode; mark as group */
- new_policy |= POLICY_TUNNEL | POLICY_GROUP;
- }
- else if (streq(optarg, "%opportunisticgroup"))
- {
- /* always use tunnel mode; mark as opportunistic */
- new_policy |= POLICY_TUNNEL | POLICY_OPPO | POLICY_GROUP;
- }
- else
- {
- diagq(ttoaddr(optarg, 0, msg.addr_family
- , &msg.right.host_addr), optarg);
- }
-
- msg.policy |= new_policy;
-
- if (new_policy & (POLICY_OPPO | POLICY_GROUP))
- {
- if (!LHAS(end_seen, END_CLIENT - END_FIRST))
- {
- /* set host to 0.0.0 and --client to 0.0.0.0/0
- * or IPV6 equivalent
- */
- ip_address any;
-
- tunnel_af_used_by = optarg;
- diagq(anyaddr(msg.tunnel_addr_family, &any), optarg);
- diagq(initsubnet(&any, 0, '0', &msg.right.client), optarg);
- }
- msg.right.has_client = TRUE;
- }
- if (new_policy & POLICY_GROUP)
- {
- /* client subnet must not be specified by user:
- * it will come from the group's file.
- */
- if (LHAS(end_seen, END_CLIENT - END_FIRST))
- diag("--host %group clashes with --client");
-
- end_seen |= LELEM(END_CLIENT - END_FIRST);
- }
- if (new_policy & POLICY_OPPO)
- msg.right.key_from_DNS_on_demand = TRUE;
- continue;
- }
- case END_ID: /* --id <identity> */
- msg.right.id = optarg; /* decoded by Pluto */
- continue;
-
- case END_CERT: /* --cert <path> */
- msg.right.cert = optarg; /* decoded by Pluto */
- continue;
-
- case END_CA: /* --ca <distinguished name> */
- msg.right.ca = optarg; /* decoded by Pluto */
- continue;
-
- case END_SENDCERT:
- if (streq(optarg, "yes") || streq(optarg, "always"))
- {
- msg.right.sendcert = CERT_ALWAYS_SEND;
- }
- else if (streq(optarg, "no") || streq(optarg, "never"))
- {
- msg.right.sendcert = CERT_NEVER_SEND;
- }
- else if (streq(optarg, "ifasked"))
- {
- msg.right.sendcert = CERT_SEND_IF_ASKED;
- }
- else
- {
- diagq("whack sendcert value is not legal", optarg);
- }
- continue;
-
- case END_GROUPS:/* --groups <access control groups> */
- msg.right.groups = optarg; /* decoded by Pluto */
- continue;
-
- case END_IKEPORT: /* --ikeport <port-number> */
- if (opt_whole<=0 || opt_whole >= 0x10000)
- diagq("<port-number> must be a number between 1 and 65535", optarg);
- msg.right.host_port = opt_whole;
- continue;
-
- case END_NEXTHOP: /* --nexthop <ip-address> */
- af_used_by = long_opts[long_index].name;
- if (streq(optarg, "%direct"))
- diagq(anyaddr(msg.addr_family
- , &msg.right.host_nexthop), optarg);
- else
- diagq(ttoaddr(optarg, 0, msg.addr_family
- , &msg.right.host_nexthop), optarg);
- continue;
-
- case END_SRCIP: /* --srcip <ip-address> */
- af_used_by = long_opts[long_index].name;
- if (streq(optarg, "%modeconfig") || streq(optarg, "%modecfg"))
- {
- msg.right.modecfg = TRUE;
- }
- else
- {
- diagq(ttoaddr(optarg, 0, msg.addr_family
- , &msg.right.host_srcip), optarg);
- msg.right.has_srcip = TRUE;
- }
- msg.policy |= POLICY_TUNNEL; /* srcip => tunnel */
- continue;
-
- case END_CLIENT: /* --client <subnet> */
- if (end_seen & LELEM(END_CLIENTWITHIN - END_FIRST))
- diag("--client conflicts with --clientwithin");
- tunnel_af_used_by = long_opts[long_index].name;
- if ((strlen(optarg) >= 6 && strncmp(optarg,"vhost:",6) == 0)
- || (strlen(optarg) >= 5 && strncmp(optarg,"vnet:",5) == 0))
- {
- msg.right.virt = optarg;
- }
- else
- {
- diagq(ttosubnet(optarg, 0, msg.tunnel_addr_family, &msg.right.client), optarg);
- msg.right.has_client = TRUE;
- }
- msg.policy |= POLICY_TUNNEL; /* client => tunnel */
- continue;
-
- case END_CLIENTWITHIN: /* --clienwithin <address range> */
- if (end_seen & LELEM(END_CLIENT - END_FIRST))
- diag("--clientwithin conflicts with --client");
- tunnel_af_used_by = long_opts[long_index].name;
- diagq(ttosubnet(optarg, 0, msg.tunnel_addr_family, &msg.right.client), optarg);
- msg.right.has_client = TRUE;
- msg.policy |= POLICY_TUNNEL; /* client => tunnel */
- msg.right.has_client_wildcard = TRUE;
- continue;
-
- case END_CLIENTPROTOPORT: /* --clientprotoport <protocol>/<port> */
- diagq(ttoprotoport(optarg, 0, &msg.right.protocol, &msg.right.port
- , &msg.right.has_port_wildcard), optarg);
- continue;
-
- case END_DNSKEYONDEMAND: /* --dnskeyondemand */
- msg.right.key_from_DNS_on_demand = TRUE;
- continue;
-
- case END_HOSTACCESS: /* --hostaccess */
- msg.right.hostaccess = TRUE;
- continue;
-
- case END_UPDOWN: /* --updown <updown> */
- msg.right.updown = optarg;
- continue;
-
- case CD_TO: /* --to */
- /* process right end, move it to left, reset it */
- if (!LHAS(end_seen, END_HOST - END_FIRST))
- diag("connection missing --host before --to");
- msg.left = msg.right;
- clear_end(&msg.right);
- end_seen_before_to = end_seen;
- end_seen = LEMPTY;
- continue;
-
- case CD_PSK: /* --psk */
- case CD_RSASIG: /* --rsasig */
- case CD_ENCRYPT: /* --encrypt */
- case CD_AUTHENTICATE: /* --authenticate */
- case CD_COMPRESS: /* --compress */
- case CD_TUNNEL: /* --tunnel */
- case CD_PFS: /* --pfs */
- case CD_DISABLEARRIVALCHECK: /* --disablearrivalcheck */
- case CD_DONT_REKEY: /* --donotrekey */
- msg.policy |= LELEM(c - CD_POLICY_FIRST);
- continue;
-
- /* --initiateontraffic
- * --pass
- * --drop
- * --reject
- */
- case CD_SHUNT0:
- msg.policy = (msg.policy & ~POLICY_SHUNT_MASK)
- | ((lset_t)aux << POLICY_SHUNT_SHIFT);
- continue;
-
- /* --failnone
- * --failpass
- * --faildrop
- * --failreject
- */
- case CD_FAIL0:
- msg.policy = (msg.policy & ~POLICY_FAIL_MASK)
- | ((lset_t)aux << POLICY_FAIL_SHIFT);
- continue;
-
- case CD_IKELIFETIME: /* --ikelifetime <seconds> */
- msg.sa_ike_life_seconds = opt_whole;
- continue;
-
- case CD_IPSECLIFETIME: /* --ipseclifetime <seconds> */
- msg.sa_ipsec_life_seconds = opt_whole;
- continue;
-
- case CD_RKMARGIN: /* --rekeymargin <seconds> */
- msg.sa_rekey_margin = opt_whole;
- continue;
-
- case CD_RKFUZZ: /* --rekeyfuzz <percentage> */
- msg.sa_rekey_fuzz = opt_whole;
- continue;
-
- case CD_KTRIES: /* --keyingtries <count> */
- msg.sa_keying_tries = opt_whole;
- continue;
-
- case CD_DPDACTION:
- if (streq(optarg, "none"))
- msg.dpd_action = DPD_ACTION_NONE;
- else if (streq(optarg, "clear"))
- msg.dpd_action = DPD_ACTION_CLEAR;
- else if (streq(optarg, "hold"))
- msg.dpd_action = DPD_ACTION_HOLD;
- else if (streq(optarg, "restart"))
- msg.dpd_action = DPD_ACTION_RESTART;
- else
- msg.dpd_action = DPD_ACTION_UNKNOWN;
- continue;
-
- case CD_DPDDELAY:
- msg.dpd_delay = opt_whole;
- continue;
-
- case CD_DPDTIMEOUT:
- msg.dpd_timeout = opt_whole;
- continue;
-
- case CD_IKE: /* --ike <ike_alg1,ike_alg2,...> */
- msg.ike = optarg;
- continue;
-
- case CD_PFSGROUP: /* --pfsgroup modpXXXX */
- msg.pfsgroup = optarg;
- continue;
-
- case CD_ESP: /* --esp <esp_alg1,esp_alg2,...> */
- msg.esp = optarg;
- continue;
-
- case CD_CONNIPV4:
- if (LHAS(cd_seen, CD_CONNIPV6 - CD_FIRST))
- diag("--ipv4 conflicts with --ipv6");
-
- /* Since this is the default, the flag is redundant.
- * So we don't need to set msg.addr_family
- * and we don't need to check af_used_by
- * and we don't have to consider defaulting tunnel_addr_family.
- */
- continue;
-
- case CD_CONNIPV6:
- if (LHAS(cd_seen, CD_CONNIPV4 - CD_FIRST))
- diag("--ipv6 conflicts with --ipv4");
-
- if (af_used_by != NULL)
- diagq("--ipv6 must precede", af_used_by);
-
- af_used_by = long_opts[long_index].name;
- msg.addr_family = AF_INET6;
-
- /* Consider defaulting tunnel_addr_family to AF_INET6.
- * Do so only if it hasn't yet been specified or used.
- */
- if (LDISJOINT(cd_seen, LELEM(CD_TUNNELIPV4 - CD_FIRST) | LELEM(CD_TUNNELIPV6 - CD_FIRST))
- && tunnel_af_used_by == NULL)
- msg.tunnel_addr_family = AF_INET6;
- continue;
-
- case CD_TUNNELIPV4:
- if (LHAS(cd_seen, CD_TUNNELIPV6 - CD_FIRST))
- diag("--tunnelipv4 conflicts with --tunnelipv6");
-
- if (tunnel_af_used_by != NULL)
- diagq("--tunnelipv4 must precede", af_used_by);
-
- msg.tunnel_addr_family = AF_INET;
- continue;
-
- case CD_TUNNELIPV6:
- if (LHAS(cd_seen, CD_TUNNELIPV4 - CD_FIRST))
- diag("--tunnelipv6 conflicts with --tunnelipv4");
-
- if (tunnel_af_used_by != NULL)
- diagq("--tunnelipv6 must precede", af_used_by);
-
- msg.tunnel_addr_family = AF_INET6;
- continue;
-
- case CA_NAME: /* --caname <name> */
- msg.name = optarg;
- msg.whack_ca = TRUE;
- continue;
- case CA_CERT: /* --cacert <path> */
- msg.cacert = optarg;
- continue;
- case CA_LDAPHOST: /* --ldaphost <hostname> */
- msg.ldaphost = optarg;
- continue;
- case CA_LDAPBASE: /* --ldapbase <base> */
- msg.ldapbase = optarg;
- continue;
- case CA_CRLURI: /* --crluri <uri> */
- msg.crluri = optarg;
- continue;
- case CA_CRLURI2: /* --crluri2 <uri> */
- msg.crluri2 = optarg;
- continue;
- case CA_OCSPURI: /* --ocspuri <uri> */
- msg.ocspuri = optarg;
- continue;
- case CA_STRICT: /* --strictcrlpolicy */
- msg.whack_strict = TRUE;
- continue;
-
-#ifdef DEBUG
- case DBGOPT_NONE: /* --debug-none */
- msg.debugging = DBG_NONE;
- continue;
-
- case DBGOPT_ALL: /* --debug-all */
- msg.debugging |= DBG_ALL; /* note: does not include PRIVATE */
- continue;
-
- case DBGOPT_RAW: /* --debug-raw */
- case DBGOPT_CRYPT: /* --debug-crypt */
- case DBGOPT_PARSING: /* --debug-parsing */
- case DBGOPT_EMITTING: /* --debug-emitting */
- case DBGOPT_CONTROL: /* --debug-control */
- case DBGOPT_LIFECYCLE: /* --debug-lifecycle */
- case DBGOPT_KERNEL: /* --debug-kernel, --debug-klips */
- case DBGOPT_DNS: /* --debug-dns */
- case DBGOPT_NATT: /* --debug-natt */
- case DBGOPT_OPPO: /* --debug-oppo */
- case DBGOPT_CONTROLMORE: /* --debug-controlmore */
- case DBGOPT_PRIVATE: /* --debug-private */
- case DBGOPT_IMPAIR_DELAY_ADNS_KEY_ANSWER: /* --impair-delay-adns-key-answer */
- case DBGOPT_IMPAIR_DELAY_ADNS_TXT_ANSWER: /* --impair-delay-adns-txt-answer */
- case DBGOPT_IMPAIR_BUST_MI2: /* --impair_bust_mi2 */
- case DBGOPT_IMPAIR_BUST_MR2: /* --impair_bust_mr2 */
- msg.debugging |= LELEM(c-DBGOPT_RAW);
- continue;
-#endif
- default:
- assert(FALSE); /* unknown return value */
- }
- break;
- }
-
- if (optind != argc)
- {
- /* If you see this message unexpectedly, perhaps the
- * case for the previous option ended with "break"
- * instead of "continue"
- */
- diagq("unexpected argument", argv[optind]);
- }
-
- /* For each possible form of the command, figure out if an argument
- * suggests whether that form was intended, and if so, whether all
- * required information was supplied.
- */
-
- /* check opportunistic initiation simulation request */
- switch (opts_seen & (LELEM(OPT_OPPO_HERE) | LELEM(OPT_OPPO_THERE)))
- {
- case LELEM(OPT_OPPO_HERE):
- case LELEM(OPT_OPPO_THERE):
- diag("--oppohere and --oppothere must be used together");
- /*NOTREACHED*/
- case LELEM(OPT_OPPO_HERE) | LELEM(OPT_OPPO_THERE):
- msg.whack_oppo_initiate = TRUE;
- if (LIN(cd_seen, LELEM(CD_TUNNELIPV4 - CD_FIRST) | LELEM(CD_TUNNELIPV6 - CD_FIRST)))
- opts_seen &= ~LELEM(OPT_CD);
- break;
- }
-
- /* check leases */
- if (LHAS(opts_seen, OPT_LEASEADDR) && LHAS(opts_seen, OPT_LEASEID))
- {
- diag("--lease-addr and --lease-id cannot be used together");
- }
-
- /* check connection description */
- if (LHAS(opts_seen, OPT_CD))
- {
- if (!LHAS(cd_seen, CD_TO-CD_FIRST))
- diag("connection description option, but no --to");
-
- if (!LHAS(end_seen, END_HOST-END_FIRST))
- diag("connection missing --host after --to");
-
- if (isanyaddr(&msg.left.host_addr)
- && isanyaddr(&msg.right.host_addr))
- diag("hosts cannot both be 0.0.0.0 or 0::0");
-
- if (msg.policy & POLICY_OPPO)
- {
- if ((msg.policy & (POLICY_PSK | POLICY_PUBKEY)) != POLICY_PUBKEY)
- diag("only PUBKEY is supported for opportunism");
- if ((msg.policy & POLICY_PFS) == 0)
- diag("PFS required for opportunism");
- if ((msg.policy & POLICY_ENCRYPT) == 0)
- diag("encryption required for opportunism");
- }
-
- check_end(&msg.left, &msg.right, !LHAS(end_seen_before_to, END_NEXTHOP-END_FIRST)
- , msg.addr_family, msg.tunnel_addr_family);
-
- check_end(&msg.right, &msg.left, !LHAS(end_seen, END_NEXTHOP-END_FIRST)
- , msg.addr_family, msg.tunnel_addr_family);
-
- if (subnettypeof(&msg.left.client) != subnettypeof(&msg.right.client))
- diag("endpoints clash: one is IPv4 and the other is IPv6");
-
- if (NEVER_NEGOTIATE(msg.policy))
- {
- /* we think this is just a shunt (because he didn't specify
- * a host authentication method). If he didn't specify a
- * shunt type, he's probably gotten it wrong.
- */
- if ((msg.policy & POLICY_SHUNT_MASK) == POLICY_SHUNT_TRAP)
- diag("non-shunt connection must have --psk or --rsasig or both");
- }
- else
- {
- /* not just a shunt: a real ipsec connection */
- if ((msg.policy & POLICY_ID_AUTH_MASK) == LEMPTY)
- diag("must specify --rsasig or --psk for a connection");
-
- if (!HAS_IPSEC_POLICY(msg.policy)
- && (msg.left.has_client || msg.right.has_client))
- diag("must not specify clients for ISAKMP-only connection");
- }
-
- msg.whack_connection = TRUE;
- }
-
- /* decide whether --name is mandatory or forbidden */
- if (!LDISJOINT(opts_seen
- , LELEM(OPT_ROUTE) | LELEM(OPT_UNROUTE)
- | LELEM(OPT_INITIATE) | LELEM(OPT_TERMINATE)
- | LELEM(OPT_DELETE) | LELEM(OPT_CD)))
- {
- if (!LHAS(opts_seen, OPT_NAME) && !msg.whack_ca)
- diag("missing --name <connection_name>");
- }
- else if (!msg.whack_options && !msg.whack_status && !msg.whack_leases)
- {
- if (LHAS(opts_seen, OPT_NAME))
- diag("no reason for --name");
- }
-
- if (!LDISJOINT(opts_seen, LELEM(OPT_PUBKEYRSA) | LELEM(OPT_ADDKEY)))
- {
- if (!LHAS(opts_seen, OPT_KEYID))
- diag("--addkey and --pubkeyrsa require --keyid");
- }
-
- if (!(msg.whack_connection || msg.whack_key || msg.whack_myid
- || msg.whack_delete || msg.whack_deletestate
- || msg.whack_initiate || msg.whack_oppo_initiate || msg.whack_terminate
- || msg.whack_route || msg.whack_unroute || msg.whack_listen
- || msg.whack_unlisten || msg.whack_list || msg.whack_purgeocsp
- || msg.whack_reread || msg.whack_ca || msg.whack_status
- || msg.whack_options || msg.whack_shutdown || msg.whack_sc_op
- || msg.whack_leases))
- {
- diag("no action specified; try --help for hints");
- }
-
- update_ports(&msg);
-
- /* tricky quick and dirty check for wild values */
- if (msg.sa_rekey_margin != 0
- && msg.sa_rekey_fuzz * msg.sa_rekey_margin * 4 / msg.sa_rekey_margin / 4
- != msg.sa_rekey_fuzz)
- diag("rekeymargin or rekeyfuzz values are so large that they cause oveflow");
-
- check_life_time (msg.sa_ike_life_seconds, OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM
- , "ikelifetime", &msg);
-
- check_life_time(msg.sa_ipsec_life_seconds, SA_LIFE_DURATION_MAXIMUM
- , "ipseclifetime", &msg);
-
- if (msg.dpd_action == DPD_ACTION_UNKNOWN)
- diag("dpdaction must be \"none\", \"clear\", \"hold\" or \"restart\"");
-
- if (msg.dpd_action != DPD_ACTION_NONE)
- {
- if (msg.dpd_delay <= 0)
- diag("dpddelay must be larger than zero");
-
- if (msg.dpd_timeout <= 0)
- diag("dpdtimeout must be larger than zero");
-
- if (msg.dpd_timeout <= msg.dpd_delay)
- diag("dpdtimeout must be larger than dpddelay");
- }
-
- /* pack strings for inclusion in message */
- next_str = msg.string;
- str_roof = &msg.string[sizeof(msg.string)];
-
- /* build esp message as esp="<esp>;<pfsgroup>" */
- if (msg.pfsgroup) {
- snprintf(esp_buf, sizeof (esp_buf), "%s;%s",
- msg.esp ? msg.esp : "",
- msg.pfsgroup ? msg.pfsgroup : "");
- msg.esp=esp_buf;
- }
- if (!pack_str(&msg.name) /* string 1 */
- || !pack_str(&msg.left.id) /* string 2 */
- || !pack_str(&msg.left.cert) /* string 3 */
- || !pack_str(&msg.left.ca) /* string 4 */
- || !pack_str(&msg.left.groups) /* string 5 */
- || !pack_str(&msg.left.updown) /* string 6 */
- || !pack_str(&msg.left.sourceip) /* string 7 */
- || !pack_str(&msg.left.virt) /* string 8 */
- || !pack_str(&msg.right.id) /* string 9 */
- || !pack_str(&msg.right.cert) /* string 10 */
- || !pack_str(&msg.right.ca) /* string 11 */
- || !pack_str(&msg.right.groups) /* string 12 */
- || !pack_str(&msg.right.updown) /* string 13 */
- || !pack_str(&msg.right.sourceip) /* string 14 */
- || !pack_str(&msg.right.virt) /* string 15 */
- || !pack_str(&msg.keyid) /* string 16 */
- || !pack_str(&msg.myid) /* string 17 */
- || !pack_str(&msg.cacert) /* string 18 */
- || !pack_str(&msg.ldaphost) /* string 19 */
- || !pack_str(&msg.ldapbase) /* string 20 */
- || !pack_str(&msg.crluri) /* string 21 */
- || !pack_str(&msg.crluri2) /* string 22 */
- || !pack_str(&msg.ocspuri) /* string 23 */
- || !pack_str(&msg.ike) /* string 24 */
- || !pack_str(&msg.esp) /* string 25 */
- || !pack_str(&msg.sc_data) /* string 26 */
- || !pack_str(&msg.whack_lease_ip) /* string 27 */
- || !pack_str(&msg.whack_lease_id) /* string 28 */
- || !pack_str(&msg.xauth_identity) /* string 29 */
- || str_roof - next_str < (ptrdiff_t)msg.keyval.len)
- diag("too many bytes of strings to fit in message to pluto");
-
- memcpy(next_str, msg.keyval.ptr, msg.keyval.len);
- msg.keyval.ptr = NULL;
- next_str += msg.keyval.len;
-
- msg.magic = ((opts_seen & ~LELEM(OPT_SHUTDOWN))
- | sc_seen | lst_seen | cd_seen | ca_seen) != LEMPTY
- || msg.whack_options
- ? WHACK_MAGIC : WHACK_BASIC_MAGIC;
-
- /* send message to Pluto */
- if (access(ctl_addr.sun_path, R_OK | W_OK) < 0)
- {
- int e = errno;
-
- switch (e)
- {
- case EACCES:
- fprintf(stderr, "whack: no right to communicate with pluto (access(\"%s\"))\n"
- , ctl_addr.sun_path);
- break;
- case ENOENT:
- fprintf(stderr, "whack: Pluto is not running (no \"%s\")\n"
- , ctl_addr.sun_path);
- break;
- default:
- fprintf(stderr, "whack: access(\"%s\") failed with %d %s\n"
- , ctl_addr.sun_path, errno, strerror(e));
- break;
- }
- whack_exit(RC_WHACK_PROBLEM);
- }
- else
- {
- int sock = socket(AF_UNIX, SOCK_STREAM, 0);
- int exit_status = 0;
- ssize_t len = next_str - (char *)&msg;
-
- if (sock == -1)
- {
- int e = errno;
-
- fprintf(stderr, "whack: socket() failed (%d %s)\n", e, strerror(e));
- whack_exit(RC_WHACK_PROBLEM);
- }
-
- if (connect(sock, (struct sockaddr *)&ctl_addr
- , offsetof(struct sockaddr_un, sun_path) + strlen(ctl_addr.sun_path)) < 0)
- {
- int e = errno;
-
- fprintf(stderr, "whack:%s connect() for \"%s\" failed (%d %s)\n"
- , e == ECONNREFUSED? " is Pluto running? " : ""
- , ctl_addr.sun_path, e, strerror(e));
- whack_exit(RC_WHACK_PROBLEM);
- }
-
- if (write(sock, &msg, len) != len)
- {
- int e = errno;
-
- fprintf(stderr, "whack: write() failed (%d %s)\n", e, strerror(e));
- whack_exit(RC_WHACK_PROBLEM);
- }
-
- /* for now, just copy reply back to stdout */
-
- {
- char buf[4097]; /* arbitrary limit on log line length */
- char *be = buf;
-
- for (;;)
- {
- char *ls = buf;
- ssize_t rl = read(sock, be, (buf + sizeof(buf)-1) - be);
-
- if (rl < 0)
- {
- int e = errno;
-
- fprintf(stderr, "whack: read() failed (%d %s)\n", e, strerror(e));
- whack_exit(RC_WHACK_PROBLEM);
- }
- if (rl == 0)
- {
- if (be != buf)
- fprintf(stderr, "whack: last line from pluto too long or unterminated\n");
- break;
- }
-
- be += rl;
- *be = '\0';
-
- for (;;)
- {
- char *le = strchr(ls, '\n');
-
- if (le == NULL)
- {
- /* move last, partial line to start of buffer */
- memmove(buf, ls, be-ls);
- be -= ls - buf;
- break;
- }
-
- le++; /* include NL in line */
- ignore_result(write(1, ls, le - ls));
-
- /* figure out prefix number
- * and how it should affect our exit status
- */
- {
- unsigned long s = strtoul(ls, NULL, 10);
-
- switch (s)
- {
- case RC_COMMENT:
- case RC_LOG:
- /* ignore */
- break;
- case RC_SUCCESS:
- /* be happy */
- exit_status = 0;
- break;
- case RC_ENTERSECRET:
- get_secret(sock);
- break;
- /* case RC_LOG_SERIOUS: */
- default:
- /* pass through */
- exit_status = s;
- break;
- }
- }
- ls = le;
- }
- }
- }
- whack_exit(exit_status);
- }
- return -1; /* should never be reached */
-}
diff --git a/src/whack/whack.h b/src/whack/whack.h
deleted file mode 100644
index c92eaf3cf..000000000
--- a/src/whack/whack.h
+++ /dev/null
@@ -1,352 +0,0 @@
-/* Structure of messages from whack to Pluto proper.
- * Copyright (C) 1998-2001 D. Hugh Redelmeier.
- *
- * 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.
- */
-
-#ifndef _WHACK_H
-#define _WHACK_H
-
-#include <freeswan.h>
-
-#include <defs.h>
-#include <constants.h>
-
-/* copy of smartcard operations, defined in smartcard.h */
-#ifndef SC_OP_T
-#define SC_OP_T
-typedef enum {
- SC_OP_NONE = 0,
- SC_OP_ENCRYPT = 1,
- SC_OP_DECRYPT = 2,
- SC_OP_SIGN = 3,
-} sc_op_t;
-#endif /* SC_OP_T */
-
-/* Since the message remains on one host, native representation is used.
- * Think of this as horizontal microcode: all selected operations are
- * to be done (in the order declared here).
- *
- * MAGIC is used to help detect version mismatches between whack and Pluto.
- * Whenever the interface (i.e. this struct) changes in form or
- * meaning, change this value (probably by changing the last number).
- *
- * If the command only requires basic actions (status or shutdown),
- * it is likely that the relevant part of the message changes less frequently.
- * Whack uses WHACK_BASIC_MAGIC in those cases.
- *
- * NOTE: no value of WHACK_BASIC_MAGIC may equal any value of WHACK_MAGIC.
- * Otherwise certain version mismatches will not be detected.
- */
-
-#define WHACK_BASIC_MAGIC (((((('w' << 8) + 'h') << 8) + 'k') << 8) + 24)
-#define WHACK_MAGIC (((((('w' << 8) + 'h') << 8) + 'k') << 8) + 30)
-
-typedef struct whack_end whack_end_t;
-
-/* struct whack_end is a lot like connection.h's struct end
- * It differs because it is going to be shipped down a socket
- * and because whack is a separate program from pluto.
- */
-struct whack_end {
- char *id; /* id string (if any) -- decoded by pluto */
- char *cert; /* path string (if any) -- loaded by pluto */
- char *ca; /* distinguished name string (if any) -- parsed by pluto */
- char *groups; /* access control groups (if any) -- parsed by pluto */
- char *sourceip; /* source IP address or pool identifier -- parsed by pluto */
- int sourceip_mask;
- ip_address host_addr;
- ip_address host_nexthop;
- ip_address host_srcip;
- ip_subnet client;
- bool key_from_DNS_on_demand;
- bool has_client;
- bool has_client_wildcard;
- bool has_port_wildcard;
- bool has_srcip;
- bool has_natip;
- bool modecfg;
- bool hostaccess;
- bool allow_any;
- certpolicy_t sendcert;
- char *updown; /* string */
- u_int16_t host_port; /* host order */
- u_int16_t port; /* host order */
- u_int8_t protocol;
- char *virt;
- };
-
-typedef struct whack_message whack_message_t;
-
-struct whack_message {
- unsigned int magic;
-
- /* for WHACK_STATUS: */
- bool whack_status;
- bool whack_statusall;
-
-
- /* for WHACK_SHUTDOWN */
- bool whack_shutdown;
-
- /* END OF BASIC COMMANDS
- * If you change anything earlier in this struct, update WHACK_BASIC_MAGIC.
- */
-
- /* name is used in connection, ca and initiate */
- size_t name_len; /* string 1 */
- char *name;
-
- /* for WHACK_OPTIONS: */
-
- bool whack_options;
-
- lset_t debugging; /* only used #ifdef DEBUG, but don't want layout to change */
-
- /* for WHACK_CONNECTION */
-
- bool whack_connection;
- bool whack_async;
- bool ikev1;
-
- lset_t policy;
- time_t sa_ike_life_seconds;
- time_t sa_ipsec_life_seconds;
- time_t sa_rekey_margin;
- unsigned long sa_rekey_fuzz;
- unsigned long sa_keying_tries;
-
- /* For DPD 3706 - Dead Peer Detection */
- time_t dpd_delay;
- time_t dpd_timeout;
- dpd_action_t dpd_action;
-
-
- /* Assign optional fixed reqid and xfrm marks to IPsec SA */
- u_int32_t reqid;
- struct {
- u_int32_t value;
- u_int32_t mask;
- } mark_in, mark_out;
-
- /* note that each end contains string 2/5.id, string 3/6 cert,
- * and string 4/7 updown
- */
- whack_end_t left;
- whack_end_t right;
-
- /* note: if the client is the gateway, the following must be equal */
- sa_family_t addr_family; /* between gateways */
- sa_family_t tunnel_addr_family; /* between clients */
-
- char *ike; /* ike algo string (separated by commas) */
- char *pfsgroup; /* pfsgroup will be "encapsulated" in esp string for pluto */
- char *esp; /* esp algo string (separated by commas) */
-
- /* for WHACK_KEY: */
- bool whack_key;
- bool whack_addkey;
- char *keyid; /* string 8 */
- enum pubkey_alg pubkey_alg;
- chunk_t keyval; /* chunk */
-
- /* for WHACK_MYID: */
- bool whack_myid;
- char *myid; /* string 7 */
-
- /* for WHACK_ROUTE: */
- bool whack_route;
-
- /* for WHACK_UNROUTE: */
- bool whack_unroute;
-
- /* for WHACK_INITIATE: */
- bool whack_initiate;
-
- /* for WHACK_OPINITIATE */
- bool whack_oppo_initiate;
- ip_address oppo_my_client, oppo_peer_client;
-
- /* for WHACK_TERMINATE: */
- bool whack_terminate;
-
- /* for WHACK_DELETE: */
- bool whack_delete;
-
- /* for WHACK_DELETESTATE: */
- bool whack_deletestate;
- so_serial_t whack_deletestateno;
-
- /* for WHACK_LEASES: */
- bool whack_leases;
- char *whack_lease_ip, *whack_lease_id;
-
- /* for WHACK_LISTEN: */
- bool whack_listen, whack_unlisten;
-
- /* for WHACK_CRASH - note if a remote peer is known to have rebooted */
- bool whack_crash;
- ip_address whack_crash_peer;
-
- /* for WHACK_LIST */
- bool whack_utc;
- lset_t whack_list;
-
- /* for WHACK_PURGEOCSP */
- bool whack_purgeocsp;
-
- /* for WHACK_REREAD */
- u_char whack_reread;
-
- /* for WHACK_CA */
- bool whack_ca;
- bool whack_strict;
-
- char *cacert;
- char *ldaphost;
- char *ldapbase;
- char *crluri;
- char *crluri2;
- char *ocspuri;
-
- /* for WHACK_SC_OP */
- sc_op_t whack_sc_op;
- int inbase, outbase;
- char *sc_data;
-
- /* XAUTH user identity */
- char *xauth_identity;
-
- /* space for strings (hope there is enough room):
- * Note that pointers don't travel on wire.
- * 1 connection name
- * 2 left's id
- * 3 left's cert
- * 4 left's ca
- * 5 left's groups
- * 6 left's updown
- * 7 left's source ip
- * 8 left's virtual ip ranges
- * 9 right's id
- * 10 right's cert
- * 11 right's ca
- * 12 right's groups
- * 13 right's updown
- * 14 right's source ip
- * 15 right's virtual ip ranges
- * 16 keyid
- * 17 myid
- * 18 cacert
- * 19 ldaphost
- * 20 ldapbase
- * 21 crluri
- * 22 crluri2
- * 23 ocspuri
- * 24 ike
- * 25 esp
- * 26 smartcard data
- * 27 whack leases ip argument
- * 28 whack leases id argument
- * 29 xauth identity
- * plus keyval (limit: 8K bits + overhead), a chunk.
- */
- size_t str_size;
- char string[2048];
-};
-
-/* Codes for status messages returned to whack.
- * These are 3 digit decimal numerals. The structure
- * is inspired by section 4.2 of RFC959 (FTP).
- * Since these will end up as the exit status of whack, they
- * must be less than 256.
- * NOTE: ipsec_auto(8) knows about some of these numbers -- change carefully.
- */
-enum rc_type {
- RC_COMMENT, /* non-commital utterance (does not affect exit status) */
- RC_WHACK_PROBLEM, /* whack-detected problem */
- RC_LOG, /* message aimed at log (does not affect exit status) */
- RC_LOG_SERIOUS, /* serious message aimed at log (does not affect exit status) */
- RC_SUCCESS, /* success (exit status 0) */
-
- /* failure, but not definitive */
-
- RC_RETRANSMISSION = 10,
-
- /* improper request */
-
- RC_DUPNAME = 20, /* attempt to reuse a connection name */
- RC_UNKNOWN_NAME, /* connection name unknown or state number */
- RC_ORIENT, /* cannot orient connection: neither end is us */
- RC_CLASH, /* clash between two Road Warrior connections OVERLOADED */
- RC_DEAF, /* need --listen before --initiate */
- RC_ROUTE, /* cannot route */
- RC_RTBUSY, /* cannot unroute: route busy */
- RC_BADID, /* malformed --id */
- RC_NOKEY, /* no key found through DNS */
- RC_NOPEERIP, /* cannot initiate when peer IP is unknown */
- RC_INITSHUNT, /* cannot initiate a shunt-oly connection */
- RC_WILDCARD, /* cannot initiate when ID has wildcards */
- RC_NOVALIDPIN, /* cannot initiate without valid PIN */
-
- /* permanent failure */
-
- RC_BADWHACKMESSAGE = 30,
- RC_NORETRANSMISSION,
- RC_INTERNALERR,
- RC_OPPOFAILURE, /* Opportunism failed */
-
- /* entry of secrets */
- RC_ENTERSECRET = 40,
-
- /* progress: start of range for successful state transition.
- * Actual value is RC_NEW_STATE plus the new state code.
- */
- RC_NEW_STATE = 100,
-
- /* start of range for notification.
- * Actual value is RC_NOTIFICATION plus code for notification
- * that should be generated by this Pluto.
- */
- RC_NOTIFICATION = 200 /* as per IKE notification messages */
-};
-
-/* options of whack --list*** command */
-
-#define LIST_NONE 0x0000 /* don't list anything */
-#define LIST_ALGS 0x0001 /* list all registered IKE algorithms */
-#define LIST_PUBKEYS 0x0002 /* list all public keys */
-#define LIST_CERTS 0x0004 /* list all host/user certs */
-#define LIST_CACERTS 0x0008 /* list all ca certs */
-#define LIST_ACERTS 0x0010 /* list all attribute certs */
-#define LIST_AACERTS 0x0020 /* list all aa certs */
-#define LIST_OCSPCERTS 0x0040 /* list all ocsp certs */
-#define LIST_GROUPS 0x0080 /* list all access control groups */
-#define LIST_CAINFOS 0x0100 /* list all ca information records */
-#define LIST_CRLS 0x0200 /* list all crls */
-#define LIST_OCSP 0x0400 /* list all ocsp cache entries */
-#define LIST_CARDS 0x0800 /* list all smartcard records */
-#define LIST_PLUGINS 0x1000 /* list all plugins with dependencies */
-
-#define LIST_ALL LRANGES(LIST_ALGS, LIST_PLUGINS) /* all list options */
-
-/* options of whack --reread*** command */
-
-#define REREAD_NONE 0x00 /* don't reread anything */
-#define REREAD_SECRETS 0x01 /* reread /etc/ipsec.secrets */
-#define REREAD_CACERTS 0x02 /* reread certs in /etc/ipsec.d/cacerts */
-#define REREAD_AACERTS 0x04 /* reread certs in /etc/ipsec.d/aacerts */
-#define REREAD_OCSPCERTS 0x08 /* reread certs in /etc/ipsec.d/ocspcerts */
-#define REREAD_ACERTS 0x10 /* reread certs in /etc/ipsec.d/acerts */
-#define REREAD_CRLS 0x20 /* reread crls in /etc/ipsec.d/crls */
-
-#define REREAD_ALL LRANGES(REREAD_SECRETS, REREAD_CRLS) /* all reread options */
-
-#endif /* _WHACK_H */