summaryrefslogtreecommitdiff
path: root/src/libcharon
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon')
-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.c138
-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.c (renamed from src/libcharon/plugins/socket_raw/socket_raw_plugin.c)57
-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.in621
-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.c62
-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/nm/nm_creds.c490
-rw-r--r--src/libcharon/plugins/nm/nm_creds.h102
-rw-r--r--src/libcharon/plugins/nm/nm_handler.c186
-rw-r--r--src/libcharon/plugins/nm/nm_handler.h62
-rw-r--r--src/libcharon/plugins/nm/nm_plugin.c142
-rw-r--r--src/libcharon/plugins/nm/nm_service.c704
-rw-r--r--src/libcharon/plugins/nm/nm_service.h55
-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/nm/nm_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.h (renamed from src/libcharon/plugins/socket_raw/socket_raw_plugin.h)22
-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
464 files changed, 35140 insertions, 11082 deletions
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.c b/src/libcharon/network/packet.c
deleted file mode 100644
index 19db362f7..000000000
--- a/src/libcharon/network/packet.c
+++ /dev/null
@@ -1,138 +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 "packet.h"
-
-typedef struct private_packet_t private_packet_t;
-
-/**
- * Private data of an packet_t object.
- */
-struct private_packet_t {
-
- /**
- * Public part of a packet_t object.
- */
- packet_t public;
-
- /**
- * source address
- */
- host_t *source;
-
- /**
- * destination address
- */
- host_t *destination;
-
- /**
- * message data
- */
- chunk_t data;
-};
-
-METHOD(packet_t, set_source, void,
- private_packet_t *this, host_t *source)
-{
- DESTROY_IF(this->source);
- this->source = source;
-}
-
-METHOD(packet_t, set_destination, void,
- private_packet_t *this, host_t *destination)
-{
- DESTROY_IF(this->destination);
- this->destination = destination;
-}
-
-METHOD(packet_t, get_source, host_t*,
- private_packet_t *this)
-{
- return this->source;
-}
-
-METHOD(packet_t, get_destination, host_t*,
- private_packet_t *this)
-{
- return this->destination;
-}
-
-METHOD(packet_t, get_data, chunk_t,
- private_packet_t *this)
-{
- return this->data;
-}
-
-METHOD(packet_t, set_data, void,
- private_packet_t *this, chunk_t data)
-{
- free(this->data.ptr);
- this->data = data;
-}
-
-METHOD(packet_t, destroy, void,
- private_packet_t *this)
-{
- DESTROY_IF(this->source);
- DESTROY_IF(this->destination);
- free(this->data.ptr);
- free(this);
-}
-
-METHOD(packet_t, clone_, packet_t*,
- private_packet_t *this)
-{
- packet_t *other;
-
- other = packet_create();
- if (this->destination != NULL)
- {
- other->set_destination(other, this->destination->clone(this->destination));
- }
- if (this->source != NULL)
- {
- other->set_source(other, this->source->clone(this->source));
- }
- if (this->data.ptr != NULL)
- {
- other->set_data(other, chunk_clone(this->data));
- }
- return other;
-}
-
-/*
- * Documented in header
- */
-packet_t *packet_create(void)
-{
- private_packet_t *this;
-
- INIT(this,
- .public = {
- .set_data = _set_data,
- .get_data = _get_data,
- .set_source = _set_source,
- .get_source = _get_source,
- .set_destination = _set_destination,
- .get_destination = _get_destination,
- .clone = _clone_,
- .destroy = _destroy,
- },
- );
-
- return &this->public;
-}
-
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/socket_raw/socket_raw_plugin.c b/src/libcharon/plugins/android_log/android_log_plugin.c
index 1299c30ca..6757c2210 100644
--- a/src/libcharon/plugins/socket_raw/socket_raw_plugin.c
+++ b/src/libcharon/plugins/android_log/android_log_plugin.c
@@ -1,8 +1,6 @@
/*
- * Copyright (C) 2010 Tobias Brunner
+ * Copyright (C) 2012 Tobias Brunner
* 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,65 +13,64 @@
* for more details.
*/
-#include "socket_raw_plugin.h"
-
-#include "socket_raw_socket.h"
+#include "android_log_plugin.h"
+#include "android_log_logger.h"
#include <daemon.h>
-typedef struct private_socket_raw_plugin_t private_socket_raw_plugin_t;
+typedef struct private_android_log_plugin_t private_android_log_plugin_t;
/**
- * Private data of socket plugin
+ * Private data of an android_log_plugin_t object.
*/
-struct private_socket_raw_plugin_t {
+struct private_android_log_plugin_t {
+
+ /**
+ * Public android_log_plugin_t interface.
+ */
+ android_log_plugin_t public;
/**
- * Implements plugin interface
+ * Android specific logger
*/
- socket_raw_plugin_t public;
+ android_log_logger_t *logger;
+
};
METHOD(plugin_t, get_name, char*,
- private_socket_raw_plugin_t *this)
+ private_android_log_plugin_t *this)
{
- return "socket-raw";
-}
-
-METHOD(plugin_t, get_features, int,
- private_socket_raw_plugin_t *this, plugin_feature_t *features[])
-{
- static plugin_feature_t f[] = {
- PLUGIN_CALLBACK(socket_register, socket_raw_socket_create),
- PLUGIN_PROVIDE(CUSTOM, "socket"),
- };
- *features = f;
- return countof(f);
+ return "android-log";
}
METHOD(plugin_t, destroy, void,
- private_socket_raw_plugin_t *this)
+ private_android_log_plugin_t *this)
{
+ charon->bus->remove_logger(charon->bus, &this->logger->logger);
+ this->logger->destroy(this->logger);
free(this);
}
-/*
- * see header file
+/**
+ * See header
*/
-plugin_t *socket_raw_plugin_create()
+plugin_t *android_log_plugin_create()
{
- private_socket_raw_plugin_t *this;
+ private_android_log_plugin_t *this;
INIT(this,
.public = {
.plugin = {
.get_name = _get_name,
- .get_features = _get_features,
+ .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/libcharon/plugins/eap_dynamic/Makefile.in b/src/libcharon/plugins/eap_dynamic/Makefile.in
new file mode 100644
index 000000000..bf467ebeb
--- /dev/null
+++ b/src/libcharon/plugins/eap_dynamic/Makefile.in
@@ -0,0 +1,621 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/libcharon/plugins/eap_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 \
+ $(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_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
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_eap_dynamic_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_eap_dynamic_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-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
+
+libstrongswan_eap_dynamic_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/eap_dynamic/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/eap_dynamic/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-eap-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)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@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 $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/eap_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/libcharon/plugins/eap_dynamic/eap_dynamic_plugin.c b/src/libcharon/plugins/eap_dynamic/eap_dynamic_plugin.c
new file mode 100644
index 000000000..d6f38b666
--- /dev/null
+++ b/src/libcharon/plugins/eap_dynamic/eap_dynamic_plugin.c
@@ -0,0 +1,62 @@
+/*
+ * 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_plugin.h"
+
+#include "eap_dynamic.h"
+
+#include <daemon.h>
+
+METHOD(plugin_t, get_name, char*,
+ eap_dynamic_plugin_t *this)
+{
+ 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,
+ eap_dynamic_plugin_t *this)
+{
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *eap_dynamic_plugin_create()
+{
+ eap_dynamic_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/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/nm/nm_creds.c b/src/libcharon/plugins/nm/nm_creds.c
deleted file mode 100644
index f8fae9504..000000000
--- a/src/libcharon/plugins/nm/nm_creds.c
+++ /dev/null
@@ -1,490 +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 "nm_creds.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include <daemon.h>
-#include <threading/rwlock.h>
-#include <credentials/certificates/x509.h>
-
-typedef struct private_nm_creds_t private_nm_creds_t;
-
-/**
- * private data of nm_creds
- */
-struct private_nm_creds_t {
-
- /**
- * public functions
- */
- nm_creds_t public;
-
- /**
- * List of trusted certificates, certificate_t*
- */
- linked_list_t *certs;
-
- /**
- * User name
- */
- identification_t *user;
-
- /**
- * User password
- */
- char *pass;
-
- /**
- * Private key decryption password / smartcard pin
- */
- char *keypass;
-
- /**
- * private key ID of smartcard key
- */
- chunk_t keyid;
-
- /**
- * users certificate
- */
- certificate_t *usercert;
-
- /**
- * users private key
- */
- private_key_t *key;
-
- /**
- * read/write lock
- */
- rwlock_t *lock;
-};
-
-/**
- * Enumerator for user certificate
- */
-static enumerator_t *create_usercert_enumerator(private_nm_creds_t *this,
- certificate_type_t cert, key_type_t key)
-{
- public_key_t *public;
-
- if (cert != CERT_ANY && cert != this->usercert->get_type(this->usercert))
- {
- return NULL;
- }
- if (key != KEY_ANY)
- {
- public = this->usercert->get_public_key(this->usercert);
- if (!public)
- {
- return NULL;
- }
- if (public->get_type(public) != key)
- {
- public->destroy(public);
- return NULL;
- }
- public->destroy(public);
- }
- this->lock->read_lock(this->lock);
- return enumerator_create_cleaner(
- enumerator_create_single(this->usercert, NULL),
- (void*)this->lock->unlock, this->lock);
-}
-
-/**
- * CA certificate enumerator data
- */
-typedef struct {
- /** ref to credential credential store */
- private_nm_creds_t *this;
- /** type of key we are looking for */
- key_type_t key;
- /** CA certificate ID */
- identification_t *id;
-} cert_data_t;
-
-/**
- * Destroy CA certificate enumerator data
- */
-static void cert_data_destroy(cert_data_t *data)
-{
- data->this->lock->unlock(data->this->lock);
- free(data);
-}
-
-/**
- * Filter function for certificates enumerator
- */
-static bool cert_filter(cert_data_t *data, certificate_t **in,
- certificate_t **out)
-{
- certificate_t *cert = *in;
- public_key_t *public;
-
- public = cert->get_public_key(cert);
- if (!public)
- {
- return FALSE;
- }
- if (data->key != KEY_ANY && public->get_type(public) != data->key)
- {
- public->destroy(public);
- return FALSE;
- }
- if (data->id && data->id->get_type(data->id) == ID_KEY_ID &&
- public->has_fingerprint(public, data->id->get_encoding(data->id)))
- {
- public->destroy(public);
- *out = cert;
- return TRUE;
- }
- public->destroy(public);
- if (data->id && !cert->has_subject(cert, data->id))
- {
- return FALSE;
- }
- *out = cert;
- return TRUE;
-}
-
-/**
- * Create enumerator for trusted certificates
- */
-static enumerator_t *create_trusted_cert_enumerator(private_nm_creds_t *this,
- key_type_t key, identification_t *id)
-{
- cert_data_t *data;
-
- INIT(data,
- .this = this,
- .id = id,
- .key = key,
- );
-
- this->lock->read_lock(this->lock);
- return enumerator_create_filter(
- this->certs->create_enumerator(this->certs),
- (void*)cert_filter, data, (void*)cert_data_destroy);
-}
-
-METHOD(credential_set_t, create_cert_enumerator, enumerator_t*,
- private_nm_creds_t *this, certificate_type_t cert, key_type_t key,
- identification_t *id, bool trusted)
-{
- if (id && this->usercert &&
- id->equals(id, this->usercert->get_subject(this->usercert)))
- {
- return create_usercert_enumerator(this, cert, key);
- }
- if (cert == CERT_X509 || cert == CERT_ANY)
- {
- return create_trusted_cert_enumerator(this, key, id);
- }
- return NULL;
-}
-
-METHOD(credential_set_t, create_private_enumerator, enumerator_t*,
- private_nm_creds_t *this, key_type_t type, identification_t *id)
-{
- if (this->key == NULL)
- {
- return NULL;
- }
- if (type != KEY_ANY && type != this->key->get_type(this->key))
- {
- return NULL;
- }
- if (id && id->get_type(id) != ID_ANY)
- {
- if (id->get_type(id) != ID_KEY_ID ||
- !this->key->has_fingerprint(this->key, id->get_encoding(id)))
- {
- return NULL;
- }
- }
- this->lock->read_lock(this->lock);
- return enumerator_create_cleaner(enumerator_create_single(this->key, NULL),
- (void*)this->lock->unlock, this->lock);
-}
-
-/**
- * shared key enumerator implementation
- */
-typedef struct {
- enumerator_t public;
- private_nm_creds_t *this;
- shared_key_t *key;
- bool done;
-} shared_enumerator_t;
-
-METHOD(enumerator_t, shared_enumerate, bool,
- shared_enumerator_t *this, shared_key_t **key, id_match_t *me,
- id_match_t *other)
-{
- if (this->done)
- {
- return FALSE;
- }
- *key = this->key;
- if (me)
- {
- *me = ID_MATCH_PERFECT;
- }
- if (other)
- {
- *other = ID_MATCH_ANY;
- }
- this->done = TRUE;
- return TRUE;
-}
-
-METHOD(enumerator_t, shared_destroy, void,
- shared_enumerator_t *this)
-{
- this->key->destroy(this->key);
- this->this->lock->unlock(this->this->lock);
- free(this);
-}
-
-METHOD(credential_set_t, create_shared_enumerator, enumerator_t*,
- private_nm_creds_t *this, shared_key_type_t type, identification_t *me,
- identification_t *other)
-{
- shared_enumerator_t *enumerator;
- chunk_t key;
-
- this->lock->read_lock(this->lock);
-
- switch (type)
- {
- case SHARED_EAP:
- case SHARED_IKE:
- if (!this->pass || !this->user)
- {
- goto no_secret;
- }
- if (me && !me->equals(me, this->user))
- {
- goto no_secret;
- }
- key = chunk_create(this->pass, strlen(this->pass));
- break;
- case SHARED_PRIVATE_KEY_PASS:
- if (!this->keypass)
- {
- goto no_secret;
- }
- key = chunk_create(this->keypass, strlen(this->keypass));
- break;
- case SHARED_PIN:
- if (!this->keypass || !me ||
- !chunk_equals(me->get_encoding(me), this->keyid))
- {
- goto no_secret;
- }
- key = chunk_create(this->keypass, strlen(this->keypass));
- break;
- default:
- goto no_secret;
- }
-
- INIT(enumerator,
- .public = {
- .enumerate = (void*)_shared_enumerate,
- .destroy = _shared_destroy,
- },
- .this = this,
- );
- enumerator->key = shared_key_create(type, chunk_clone(key));
- return &enumerator->public;
-
-no_secret:
- this->lock->unlock(this->lock);
- return NULL;
-}
-
-METHOD(nm_creds_t, add_certificate, void,
- private_nm_creds_t *this, certificate_t *cert)
-{
- this->lock->write_lock(this->lock);
- this->certs->insert_last(this->certs, cert);
- this->lock->unlock(this->lock);
-}
-
-/**
- * Load a certificate file
- */
-static void load_ca_file(private_nm_creds_t *this, char *file)
-{
- certificate_t *cert;
-
- /* We add the CA constraint, as many CAs miss it */
- cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
- BUILD_FROM_FILE, file, BUILD_END);
- if (!cert)
- {
- DBG1(DBG_CFG, "loading CA certificate '%s' failed", file);
- }
- else
- {
- DBG2(DBG_CFG, "loaded CA certificate '%Y'", cert->get_subject(cert));
- x509_t *x509 = (x509_t*)cert;
- if (!(x509->get_flags(x509) & X509_SELF_SIGNED))
- {
- DBG1(DBG_CFG, "%Y is not self signed", cert->get_subject(cert));
- }
- this->certs->insert_last(this->certs, cert);
- }
-}
-
-METHOD(nm_creds_t, load_ca_dir, void,
- private_nm_creds_t *this, char *dir)
-{
- enumerator_t *enumerator;
- char *rel, *abs;
- struct stat st;
-
- enumerator = enumerator_create_directory(dir);
- if (enumerator)
- {
- while (enumerator->enumerate(enumerator, &rel, &abs, &st))
- {
- /* skip '.', '..' and hidden files */
- if (rel[0] != '.')
- {
- if (S_ISDIR(st.st_mode))
- {
- load_ca_dir(this, abs);
- }
- else if (S_ISREG(st.st_mode))
- {
- load_ca_file(this, abs);
- }
- }
- }
- enumerator->destroy(enumerator);
- }
-}
-
-METHOD(nm_creds_t, set_username_password, void,
- private_nm_creds_t *this, identification_t *id, char *password)
-{
- this->lock->write_lock(this->lock);
- DESTROY_IF(this->user);
- this->user = id->clone(id);
- free(this->pass);
- this->pass = strdupnull(password);
- this->lock->unlock(this->lock);
-}
-
-METHOD(nm_creds_t, set_key_password, void,
- private_nm_creds_t *this, char *password)
-{
- this->lock->write_lock(this->lock);
- free(this->keypass);
- this->keypass = strdupnull(password);
- this->lock->unlock(this->lock);
-}
-
-METHOD(nm_creds_t, set_pin, void,
- private_nm_creds_t *this, chunk_t keyid, char *pin)
-{
- this->lock->write_lock(this->lock);
- free(this->keypass);
- free(this->keyid.ptr);
- this->keypass = strdupnull(pin);
- this->keyid = chunk_clone(keyid);
- this->lock->unlock(this->lock);
-}
-
-METHOD(nm_creds_t, set_cert_and_key, void,
- private_nm_creds_t *this, certificate_t *cert, private_key_t *key)
-{
- this->lock->write_lock(this->lock);
- DESTROY_IF(this->key);
- DESTROY_IF(this->usercert);
- this->key = key;
- this->usercert = cert;
- this->lock->unlock(this->lock);
-}
-
-METHOD(nm_creds_t, clear, void,
- private_nm_creds_t *this)
-{
- certificate_t *cert;
-
- while (this->certs->remove_last(this->certs, (void**)&cert) == SUCCESS)
- {
- cert->destroy(cert);
- }
- DESTROY_IF(this->user);
- free(this->pass);
- free(this->keypass);
- free(this->keyid.ptr);
- DESTROY_IF(this->usercert);
- DESTROY_IF(this->key);
- this->key = NULL;
- this->usercert = NULL;
- this->pass = NULL;
- this->user = NULL;
- this->keypass = NULL;
- this->keyid = chunk_empty;
-}
-
-METHOD(nm_creds_t, destroy, void,
- private_nm_creds_t *this)
-{
- clear(this);
- this->certs->destroy(this->certs);
- this->lock->destroy(this->lock);
- free(this);
-}
-
-/*
- * see header file
- */
-nm_creds_t *nm_creds_create()
-{
- private_nm_creds_t *this;
-
- INIT(this,
- .public = {
- .set = {
- .create_private_enumerator = _create_private_enumerator,
- .create_cert_enumerator = _create_cert_enumerator,
- .create_shared_enumerator = _create_shared_enumerator,
- .create_cdp_enumerator = (void*)return_null,
- .cache_cert = (void*)nop,
- },
- .add_certificate = _add_certificate,
- .load_ca_dir = _load_ca_dir,
- .set_username_password = _set_username_password,
- .set_key_password = _set_key_password,
- .set_pin = _set_pin,
- .set_cert_and_key = _set_cert_and_key,
- .clear = _clear,
- .destroy = _destroy,
- },
- .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
- .certs = linked_list_create(),
- );
- return &this->public;
-}
-
diff --git a/src/libcharon/plugins/nm/nm_creds.h b/src/libcharon/plugins/nm/nm_creds.h
deleted file mode 100644
index 91f645c7e..000000000
--- a/src/libcharon/plugins/nm/nm_creds.h
+++ /dev/null
@@ -1,102 +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 nm_creds nm_creds
- * @{ @ingroup nm
- */
-
-#ifndef NM_CREDS_H_
-#define NM_CREDS_H_
-
-#include <credentials/keys/private_key.h>
-#include <credentials/credential_set.h>
-
-typedef struct nm_creds_t nm_creds_t;
-
-/**
- * NetworkManager credentials helper.
- */
-struct nm_creds_t {
-
- /**
- * Implements credential_set_t
- */
- credential_set_t set;
-
- /**
- * Add a trusted gateway certificate to serve by this set.
- *
- * @param cert certificate to serve
- */
- void (*add_certificate)(nm_creds_t *this, certificate_t *cert);
-
- /**
- * Load CA certificates recursively from a directory.
- *
- * @param dir directory to PEM encoded CA certificates
- */
- void (*load_ca_dir)(nm_creds_t *this, char *dir);
-
- /**
- * Set the username/password for authentication.
- *
- * @param id ID of the user
- * @param password password to use for authentication
- */
- void (*set_username_password)(nm_creds_t *this, identification_t *id,
- char *password);
-
- /**
- * Set the passphrase to use for private key decryption.
- *
- * @param password password to use
- */
- void (*set_key_password)(nm_creds_t *this, char *password);
-
- /**
- * Set the PIN to unlock a smartcard.
- *
- * @param keyid keyid of the smartcard key
- * @param pin PIN
- */
- void (*set_pin)(nm_creds_t *this, chunk_t keyid, char *pin);
-
- /**
- * Set the certificate and private key to use for client authentication.
- *
- * @param cert client certificate
- * @param key associated private key
- */
- void (*set_cert_and_key)(nm_creds_t *this, certificate_t *cert,
- private_key_t *key);
-
- /**
- * Clear the stored credentials.
- */
- void (*clear)(nm_creds_t *this);
-
- /**
- * Destroy a nm_creds instance.
- */
- void (*destroy)(nm_creds_t *this);
-};
-
-/**
- * Create a nm_creds instance.
- */
-nm_creds_t *nm_creds_create();
-
-#endif /** NM_CREDS_H_ @}*/
diff --git a/src/libcharon/plugins/nm/nm_handler.c b/src/libcharon/plugins/nm/nm_handler.c
deleted file mode 100644
index 408129ebe..000000000
--- a/src/libcharon/plugins/nm/nm_handler.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 2009 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include "nm_handler.h"
-
-#include <daemon.h>
-
-typedef struct private_nm_handler_t private_nm_handler_t;
-
-/**
- * Private data of an nm_handler_t object.
- */
-struct private_nm_handler_t {
-
- /**
- * Public nm_handler_t interface.
- */
- nm_handler_t public;
-
- /**
- * list of received DNS server attributes, pointer to 4 byte data
- */
- linked_list_t *dns;
-
- /**
- * list of received NBNS server attributes, pointer to 4 byte data
- */
- linked_list_t *nbns;
-};
-
-METHOD(attribute_handler_t, handle, bool,
- private_nm_handler_t *this, identification_t *server,
- configuration_attribute_type_t type, chunk_t data)
-{
- linked_list_t *list;
-
- switch (type)
- {
- case INTERNAL_IP4_DNS:
- list = this->dns;
- break;
- case INTERNAL_IP4_NBNS:
- list = this->nbns;
- break;
- default:
- return FALSE;
- }
- if (data.len != 4)
- {
- return FALSE;
- }
- list->insert_last(list, chunk_clone(data).ptr);
- return TRUE;
-}
-
-/**
- * Implementation of create_attribute_enumerator().enumerate() for WINS
- */
-static bool enumerate_nbns(enumerator_t *this,
- configuration_attribute_type_t *type, chunk_t *data)
-{
- *type = INTERNAL_IP4_NBNS;
- *data = chunk_empty;
- /* done */
- this->enumerate = (void*)return_false;
- return TRUE;
-}
-
-/**
- * Implementation of create_attribute_enumerator().enumerate() for DNS
- */
-static bool enumerate_dns(enumerator_t *this,
- configuration_attribute_type_t *type, chunk_t *data)
-{
- *type = INTERNAL_IP4_DNS;
- *data = chunk_empty;
- /* enumerate WINS server as next attribute ... */
- this->enumerate = (void*)enumerate_nbns;
- return TRUE;
-}
-
-METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*,
- private_nm_handler_t *this, identification_t *server, host_t *vip)
-{
- 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;
-
- return enumerator;
- }
- return enumerator_create_empty();
-}
-
-/**
- * convert plain byte ptrs to handy chunk during enumeration
- */
-static bool filter_chunks(void* null, char **in, chunk_t *out)
-{
- *out = chunk_create(*in, 4);
- return TRUE;
-}
-
-METHOD(nm_handler_t, create_enumerator, enumerator_t*,
- private_nm_handler_t *this, configuration_attribute_type_t type)
-{
- linked_list_t *list;
-
- switch (type)
- {
- case INTERNAL_IP4_DNS:
- list = this->dns;
- break;
- case INTERNAL_IP4_NBNS:
- list = this->nbns;
- break;
- default:
- return enumerator_create_empty();
- }
- return enumerator_create_filter(list->create_enumerator(list),
- (void*)filter_chunks, NULL, NULL);
-}
-
-METHOD(nm_handler_t, reset, void,
- private_nm_handler_t *this)
-{
- void *data;
-
- while (this->dns->remove_last(this->dns, (void**)&data) == SUCCESS)
- {
- free(data);
- }
- while (this->nbns->remove_last(this->nbns, (void**)&data) == SUCCESS)
- {
- free(data);
- }
-}
-
-METHOD(nm_handler_t, destroy, void,
- private_nm_handler_t *this)
-{
- reset(this);
- this->dns->destroy(this->dns);
- this->nbns->destroy(this->nbns);
- free(this);
-}
-
-/**
- * See header
- */
-nm_handler_t *nm_handler_create()
-{
- private_nm_handler_t *this;
-
- INIT(this,
- .public = {
- .handler = {
- .handle = _handle,
- .release = nop,
- .create_attribute_enumerator = _create_attribute_enumerator,
- },
- .create_enumerator = _create_enumerator,
- .reset = _reset,
- .destroy = _destroy,
- },
- .dns = linked_list_create(),
- .nbns = linked_list_create(),
- );
-
- return &this->public;
-}
-
diff --git a/src/libcharon/plugins/nm/nm_handler.h b/src/libcharon/plugins/nm/nm_handler.h
deleted file mode 100644
index bb35ce767..000000000
--- a/src/libcharon/plugins/nm/nm_handler.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2009 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup nm_handler nm_handler
- * @{ @ingroup nm
- */
-
-#ifndef NM_HANDLER_H_
-#define NM_HANDLER_H_
-
-#include <attributes/attribute_handler.h>
-
-typedef struct nm_handler_t nm_handler_t;
-
-/**
- * Handles DNS/NBNS attributes to pass to NM.
- */
-struct nm_handler_t {
-
- /**
- * Implements attribute handler interface
- */
- attribute_handler_t handler;
-
- /**
- * Create an enumerator over received attributes of a given kind.
- *
- * @param type type of attributes to enumerate
- * @return enumerator over attribute data (chunk_t)
- */
- enumerator_t* (*create_enumerator)(nm_handler_t *this,
- configuration_attribute_type_t type);
- /**
- * Reset state, flush all received attributes.
- */
- void (*reset)(nm_handler_t *this);
-
- /**
- * Destroy a nm_handler_t.
- */
- void (*destroy)(nm_handler_t *this);
-};
-
-/**
- * Create a nm_handler instance.
- */
-nm_handler_t *nm_handler_create();
-
-#endif /** NM_HANDLER_H_ @}*/
diff --git a/src/libcharon/plugins/nm/nm_plugin.c b/src/libcharon/plugins/nm/nm_plugin.c
deleted file mode 100644
index 84b7c810a..000000000
--- a/src/libcharon/plugins/nm/nm_plugin.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2008-2009 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include "nm_plugin.h"
-#include "nm_service.h"
-#include "nm_creds.h"
-#include "nm_handler.h"
-
-#include <hydra.h>
-#include <daemon.h>
-#include <processing/jobs/callback_job.h>
-
-#define CAP_DAC_OVERRIDE 1
-
-typedef struct private_nm_plugin_t private_nm_plugin_t;
-
-/**
- * private data of nm plugin
- */
-struct private_nm_plugin_t {
-
- /**
- * implements plugin interface
- */
- nm_plugin_t public;
-
- /**
- * NetworkManager service (VPNPlugin)
- */
- NMStrongswanPlugin *plugin;
-
- /**
- * Glib main loop for a thread, handles DBUS calls
- */
- GMainLoop *loop;
-
- /**
- * credential set registered at the daemon
- */
- nm_creds_t *creds;
-
- /**
- * attribute handler regeisterd at the daemon
- */
- nm_handler_t *handler;
-};
-
-/**
- * NM plugin processing routine, creates and handles NMVPNPlugin
- */
-static job_requeue_t run(private_nm_plugin_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)
-{
- if (this->loop)
- {
- if (g_main_loop_is_running(this->loop))
- {
- g_main_loop_quit(this->loop);
- }
- g_main_loop_unref(this->loop);
- }
- if (this->plugin)
- {
- g_object_unref(this->plugin);
- }
- lib->credmgr->remove_set(lib->credmgr, &this->creds->set);
- hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler);
- this->creds->destroy(this->creds);
- this->handler->destroy(this->handler);
- free(this);
-}
-
-/*
- * see header file
- */
-plugin_t *nm_plugin_create()
-{
- private_nm_plugin_t *this;
-
- g_type_init ();
- if (!g_thread_supported())
- {
- g_thread_init(NULL);
- }
-
- 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);
-
- 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;
- }
-
- /* bypass file permissions to read from users ssh-agent */
- charon->keep_cap(charon, 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));
-
- return &this->public.plugin;
-}
-
diff --git a/src/libcharon/plugins/nm/nm_service.c b/src/libcharon/plugins/nm/nm_service.c
deleted file mode 100644
index a6783fcc3..000000000
--- a/src/libcharon/plugins/nm/nm_service.c
+++ /dev/null
@@ -1,704 +0,0 @@
-/*
- * Copyright (C) 2008-2009 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <nm-setting-vpn.h>
-#include <nm-setting-connection.h>
-#include "nm_service.h"
-
-#include <daemon.h>
-#include <utils/host.h>
-#include <utils/identification.h>
-#include <config/peer_cfg.h>
-#include <credentials/certificates/x509.h>
-
-#include <stdio.h>
-
-G_DEFINE_TYPE(NMStrongswanPlugin, nm_strongswan_plugin, NM_TYPE_VPN_PLUGIN)
-
-/**
- * Private data of NMStrongswanPlugin
- */
-typedef struct {
- /* implements bus listener interface */
- listener_t listener;
- /* IKE_SA we are listening on */
- ike_sa_t *ike_sa;
- /* backref to public plugin */
- NMVPNPlugin *plugin;
- /* credentials to use for authentication */
- nm_creds_t *creds;
- /* attribute handler for DNS/NBNS server information */
- nm_handler_t *handler;
- /* name of the connection */
- char *name;
-} NMStrongswanPluginPrivate;
-
-#define NM_STRONGSWAN_PLUGIN_GET_PRIVATE(o) \
- (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
- NM_TYPE_STRONGSWAN_PLUGIN, NMStrongswanPluginPrivate))
-
-/**
- * convert enumerated handler chunks to a UINT_ARRAY GValue
- */
-static GValue* handler_to_val(nm_handler_t *handler,
- configuration_attribute_type_t type)
-{
- GValue *val;
- GArray *array;
- enumerator_t *enumerator;
- chunk_t chunk;
-
- enumerator = handler->create_enumerator(handler, type);
- array = g_array_new (FALSE, TRUE, sizeof (guint32));
- while (enumerator->enumerate(enumerator, &chunk))
- {
- g_array_append_val (array, *(u_int32_t*)chunk.ptr);
- }
- enumerator->destroy(enumerator);
- val = g_slice_new0 (GValue);
- g_value_init (val, DBUS_TYPE_G_UINT_ARRAY);
- g_value_set_boxed (val, array);
-
- return val;
-}
-
-/**
- * signal IPv4 config to NM, set connection as established
- */
-static void signal_ipv4_config(NMVPNPlugin *plugin,
- ike_sa_t *ike_sa, child_sa_t *child_sa)
-{
- GValue *val;
- GHashTable *config;
- host_t *me;
- nm_handler_t *handler;
-
- config = g_hash_table_new(g_str_hash, g_str_equal);
- 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. */
- val = g_slice_new0 (GValue);
- g_value_init (val, G_TYPE_STRING);
- g_value_set_string (val, "none");
- g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_TUNDEV, val);
-
- val = g_slice_new0(GValue);
- g_value_init(val, G_TYPE_UINT);
- g_value_set_uint(val, *(u_int32_t*)me->get_address(me).ptr);
- g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS, val);
-
- val = g_slice_new0(GValue);
- g_value_init(val, G_TYPE_UINT);
- g_value_set_uint(val, me->get_address(me).len * 8);
- g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_PREFIX, val);
-
- val = handler_to_val(handler, INTERNAL_IP4_DNS);
- g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_DNS, val);
-
- val = handler_to_val(handler, INTERNAL_IP4_NBNS);
- g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_NBNS, val);
-
- handler->reset(handler);
-
- nm_vpn_plugin_set_ip4_config(plugin, config);
-}
-
-/**
- * signal failure to NM, connecting failed
- */
-static void signal_failure(NMVPNPlugin *plugin, NMVPNPluginFailure failure)
-{
- nm_handler_t *handler = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin)->handler;
-
- handler->reset(handler);
-
- /* TODO: NM does not handle this failure!? */
- nm_vpn_plugin_failure(plugin, failure);
- nm_vpn_plugin_set_state(plugin, NM_VPN_SERVICE_STATE_STOPPED);
-}
-
-/**
- * Implementation of listener_t.ike_state_change
- */
-static bool ike_state_change(listener_t *listener, ike_sa_t *ike_sa,
- ike_sa_state_t state)
-{
- NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener;
-
- if (private->ike_sa == ike_sa && state == IKE_DESTROYING)
- {
- signal_failure(private->plugin, NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED);
- return FALSE;
- }
- return TRUE;
-}
-
-/**
- * Implementation of listener_t.child_state_change
- */
-static bool child_state_change(listener_t *listener, ike_sa_t *ike_sa,
- child_sa_t *child_sa, child_sa_state_t state)
-{
- NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener;
-
- if (private->ike_sa == ike_sa && state == CHILD_DESTROYING)
- {
- signal_failure(private->plugin, NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED);
- return FALSE;
- }
- return TRUE;
-}
-
-/**
- * Implementation of listener_t.child_updown
- */
-static bool child_updown(listener_t *listener, ike_sa_t *ike_sa,
- child_sa_t *child_sa, bool up)
-{
- NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener;
-
- if (private->ike_sa == ike_sa)
- {
- if (up)
- { /* disable initiate-failure-detection hooks */
- private->listener.ike_state_change = NULL;
- private->listener.child_state_change = NULL;
- signal_ipv4_config(private->plugin, ike_sa, child_sa);
- }
- else
- {
- signal_failure(private->plugin, NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED);
- return FALSE;
- }
- }
- return TRUE;
-}
-
-/**
- * Implementation of listener_t.ike_rekey
- */
-static bool ike_rekey(listener_t *listener, ike_sa_t *old, ike_sa_t *new)
-{
- NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener;
-
- if (private->ike_sa == old)
- { /* follow a rekeyed IKE_SA */
- private->ike_sa = new;
- }
- return TRUE;
-}
-
-/**
- * Find a certificate for which we have a private key on a smartcard
- */
-static identification_t *find_smartcard_key(NMStrongswanPluginPrivate *priv,
- char *pin)
-{
- enumerator_t *enumerator, *sans;
- identification_t *id = NULL;
- certificate_t *cert;
- x509_t *x509;
- private_key_t *key;
- chunk_t keyid;
-
- enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
- CERT_X509, KEY_ANY, NULL, FALSE);
- while (enumerator->enumerate(enumerator, &cert))
- {
- x509 = (x509_t*)cert;
-
- /* there might be a lot of certificates, filter them by usage */
- if ((x509->get_flags(x509) & X509_CLIENT_AUTH) &&
- !(x509->get_flags(x509) & X509_CA))
- {
- keyid = x509->get_subjectKeyIdentifier(x509);
- if (keyid.ptr)
- {
- /* try to find a private key by the certificate keyid */
- priv->creds->set_pin(priv->creds, keyid, pin);
- key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
- KEY_ANY, BUILD_PKCS11_KEYID, keyid, BUILD_END);
- if (key)
- {
- /* prefer a more convenient subjectAltName */
- sans = x509->create_subjectAltName_enumerator(x509);
- if (!sans->enumerate(sans, &id))
- {
- id = cert->get_subject(cert);
- }
- id = id->clone(id);
- sans->destroy(sans);
-
- DBG1(DBG_CFG, "using smartcard certificate '%Y'", id);
- priv->creds->set_cert_and_key(priv->creds,
- cert->get_ref(cert), key);
- break;
- }
- }
- }
- }
- enumerator->destroy(enumerator);
- return id;
-}
-
-/**
- * Connect function called from NM via DBUS
- */
-static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
- GError **err)
-{
- NMStrongswanPluginPrivate *priv;
- NMSettingConnection *conn;
- NMSettingVPN *vpn;
- identification_t *user = NULL, *gateway = NULL;
- const char *address, *str;
- bool virtual, encap, ipcomp;
- ike_cfg_t *ike_cfg;
- peer_cfg_t *peer_cfg;
- child_cfg_t *child_cfg;
- traffic_selector_t *ts;
- ike_sa_t *ike_sa;
- auth_cfg_t *auth;
- auth_class_t auth_class = AUTH_CLASS_EAP;
- certificate_t *cert = NULL;
- x509_t *x509;
- bool agent = FALSE, smartcard = FALSE;
- lifetime_cfg_t lifetime = {
- .time = {
- .life = 10800 /* 3h */,
- .rekey = 10200 /* 2h50min */,
- .jitter = 300 /* 5min */
- }
- };
-
- /**
- * Read parameters
- */
- priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
- conn = NM_SETTING_CONNECTION(nm_connection_get_setting(connection,
- NM_TYPE_SETTING_CONNECTION));
- vpn = NM_SETTING_VPN(nm_connection_get_setting(connection,
- NM_TYPE_SETTING_VPN));
- if (priv->name)
- {
- free(priv->name);
- }
- priv->name = strdup(nm_setting_connection_get_id(conn));
- DBG1(DBG_CFG, "received initiate for NetworkManager connection %s",
- priv->name);
- DBG4(DBG_CFG, "%s",
- nm_setting_to_string(NM_SETTING(vpn)));
- address = nm_setting_vpn_get_data_item(vpn, "address");
- if (!address || !*address)
- {
- g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
- "Gateway address missing.");
- return FALSE;
- }
- str = nm_setting_vpn_get_data_item(vpn, "virtual");
- virtual = str && streq(str, "yes");
- str = nm_setting_vpn_get_data_item(vpn, "encap");
- encap = str && streq(str, "yes");
- str = nm_setting_vpn_get_data_item(vpn, "ipcomp");
- ipcomp = str && streq(str, "yes");
- str = nm_setting_vpn_get_data_item(vpn, "method");
- if (str)
- {
- if (streq(str, "psk"))
- {
- auth_class = AUTH_CLASS_PSK;
- }
- else if (streq(str, "agent"))
- {
- auth_class = AUTH_CLASS_PUBKEY;
- agent = TRUE;
- }
- else if (streq(str, "key"))
- {
- auth_class = AUTH_CLASS_PUBKEY;
- }
- else if (streq(str, "smartcard"))
- {
- auth_class = AUTH_CLASS_PUBKEY;
- smartcard = TRUE;
- }
- }
-
- /**
- * Register credentials
- */
- priv->creds->clear(priv->creds);
-
- /* gateway/CA cert */
- str = nm_setting_vpn_get_data_item(vpn, "certificate");
- if (str)
- {
- cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
- BUILD_FROM_FILE, str, BUILD_END);
- if (!cert)
- {
- g_set_error(err, NM_VPN_PLUGIN_ERROR,
- NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
- "Loading gateway certificate failed.");
- return FALSE;
- }
- priv->creds->add_certificate(priv->creds, cert);
-
- x509 = (x509_t*)cert;
- if (!(x509->get_flags(x509) & X509_CA))
- { /* For a gateway certificate, we use the cert subject as identity. */
- gateway = cert->get_subject(cert);
- gateway = gateway->clone(gateway);
- DBG1(DBG_CFG, "using gateway certificate, identity '%Y'", gateway);
- }
- }
- else
- {
- /* no certificate defined, fall back to system-wide CA certificates */
- priv->creds->load_ca_dir(priv->creds, NM_CA_DIR);
- }
- if (!gateway)
- {
- /* If the user configured a CA certificate, we use the IP/DNS
- * of the gateway as its identity. This identity will be used for
- * certificate lookup and requires the configured IP/DNS to be
- * included in the gateway certificate. */
- gateway = identification_create_from_string((char*)address);
- DBG1(DBG_CFG, "using CA certificate, gateway identity '%Y'", gateway);
- }
-
- if (auth_class == AUTH_CLASS_EAP)
- {
- /* username/password authentication ... */
- str = nm_setting_vpn_get_data_item(vpn, "user");
- if (str)
- {
- user = identification_create_from_string((char*)str);
- str = nm_setting_vpn_get_secret(vpn, "password");
- priv->creds->set_username_password(priv->creds, user, (char*)str);
- }
- }
-
- if (auth_class == AUTH_CLASS_PUBKEY)
- {
- if (smartcard)
- {
- char *pin;
-
- pin = (char*)nm_setting_vpn_get_secret(vpn, "password");
- if (pin)
- {
- user = find_smartcard_key(priv, pin);
- }
- if (!user)
- {
- g_set_error(err, NM_VPN_PLUGIN_ERROR,
- NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
- "no usable smartcard certificate found.");
- gateway->destroy(gateway);
- return FALSE;
- }
- }
- /* ... or certificate/private key authenitcation */
- else if ((str = nm_setting_vpn_get_data_item(vpn, "usercert")))
- {
- public_key_t *public;
- private_key_t *private = NULL;
-
- cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
- BUILD_FROM_FILE, str, BUILD_END);
- if (!cert)
- {
- g_set_error(err, NM_VPN_PLUGIN_ERROR,
- NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
- "Loading peer certificate failed.");
- gateway->destroy(gateway);
- return FALSE;
- }
- /* try agent */
- str = nm_setting_vpn_get_secret(vpn, "agent");
- if (agent && str)
- {
- public = cert->get_public_key(cert);
- if (public)
- {
- private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
- public->get_type(public),
- BUILD_AGENT_SOCKET, str,
- BUILD_PUBLIC_KEY, public,
- BUILD_END);
- public->destroy(public);
- }
- if (!private)
- {
- g_set_error(err, NM_VPN_PLUGIN_ERROR,
- NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
- "Connecting to SSH agent failed.");
- }
- }
- /* ... or key file */
- str = nm_setting_vpn_get_data_item(vpn, "userkey");
- if (!agent && str)
- {
- char *secret;
-
- secret = (char*)nm_setting_vpn_get_secret(vpn, "password");
- if (secret)
- {
- priv->creds->set_key_password(priv->creds, secret);
- }
- private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
- KEY_RSA, BUILD_FROM_FILE, str, BUILD_END);
- if (!private)
- {
- g_set_error(err, NM_VPN_PLUGIN_ERROR,
- NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
- "Loading private key failed.");
- }
- }
- if (private)
- {
- user = cert->get_subject(cert);
- user = user->clone(user);
- priv->creds->set_cert_and_key(priv->creds, cert, private);
- }
- else
- {
- DESTROY_IF(cert);
- gateway->destroy(gateway);
- return FALSE;
- }
- }
- }
-
- if (!user)
- {
- g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
- "Configuration parameters missing.");
- gateway->destroy(gateway);
- return FALSE;
- }
-
- /**
- * Set up configurations
- */
- ike_cfg = ike_cfg_create(TRUE, encap,
- "0.0.0.0", IKEV2_UDP_PORT, (char*)address, IKEV2_UDP_PORT);
- ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
- peer_cfg = peer_cfg_create(priv->name, 2, ike_cfg,
- CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */
- 36000, 0, /* rekey 10h, reauth none */
- 600, 600, /* jitter, over 10min */
- TRUE, 0, /* mobike, DPD */
- virtual ? host_create_from_string("0.0.0.0", 0) : NULL,
- NULL, FALSE, NULL, NULL); /* pool, mediation */
- auth = auth_cfg_create();
- auth->add(auth, AUTH_RULE_AUTH_CLASS, auth_class);
- auth->add(auth, AUTH_RULE_IDENTITY, user);
- peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE);
- auth = auth_cfg_create();
- auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
- auth->add(auth, AUTH_RULE_IDENTITY, gateway);
- peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
-
- child_cfg = child_cfg_create(priv->name, &lifetime,
- NULL, TRUE, MODE_TUNNEL, /* updown, hostaccess */
- ACTION_NONE, ACTION_NONE, ACTION_NONE, ipcomp,
- 0, 0, NULL, NULL, 0);
- child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
- ts = traffic_selector_create_dynamic(0, 0, 65535);
- child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
- ts = traffic_selector_create_from_string(0, TS_IPV4_ADDR_RANGE,
- "0.0.0.0", 0,
- "255.255.255.255", 65535);
- child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
- peer_cfg->add_child_cfg(peer_cfg, child_cfg);
-
- /**
- * Prepare IKE_SA
- */
- ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
- peer_cfg);
- if (!ike_sa->get_peer_cfg(ike_sa))
- {
- ike_sa->set_peer_cfg(ike_sa, peer_cfg);
- }
- peer_cfg->destroy(peer_cfg);
-
- /**
- * Register listener, enable initiate-failure-detection hooks
- */
- priv->ike_sa = ike_sa;
- priv->listener.ike_state_change = ike_state_change;
- priv->listener.child_state_change = child_state_change;
- charon->bus->add_listener(charon->bus, &priv->listener);
-
- /**
- * Initiate
- */
- if (ike_sa->initiate(ike_sa, child_cfg, 0, NULL, NULL) != SUCCESS)
- {
- charon->bus->remove_listener(charon->bus, &priv->listener);
- charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
-
- g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
- "Initiating failed.");
- return FALSE;
- }
- charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
- return TRUE;
-}
-
-/**
- * NeedSecrets called from NM via DBUS
- */
-static gboolean need_secrets(NMVPNPlugin *plugin, NMConnection *connection,
- char **setting_name, GError **error)
-{
- NMSettingVPN *settings;
- const char *method, *path;
-
- settings = NM_SETTING_VPN(nm_connection_get_setting(connection,
- NM_TYPE_SETTING_VPN));
- method = nm_setting_vpn_get_data_item(settings, "method");
- if (method)
- {
- if (streq(method, "eap"))
- {
- if (nm_setting_vpn_get_secret(settings, "password"))
- {
- return FALSE;
- }
- }
- else if (streq(method, "agent"))
- {
- if (nm_setting_vpn_get_secret(settings, "agent"))
- {
- return FALSE;
- }
- }
- else if (streq(method, "key"))
- {
- path = nm_setting_vpn_get_data_item(settings, "userkey");
- if (path)
- {
- private_key_t *key;
-
- /* try to load/decrypt the private key */
- key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
- KEY_RSA, BUILD_FROM_FILE, path, BUILD_END);
- if (key)
- {
- key->destroy(key);
- return FALSE;
- }
- }
- }
- else if streq(method, "smartcard")
- {
- if (nm_setting_vpn_get_secret(settings, "password"))
- {
- return FALSE;
- }
- }
- }
- *setting_name = NM_SETTING_VPN_SETTING_NAME;
- return TRUE;
-}
-
-/**
- * Disconnect called from NM via DBUS
- */
-static gboolean disconnect(NMVPNPlugin *plugin, GError **err)
-{
- NMStrongswanPluginPrivate *priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
- enumerator_t *enumerator;
- ike_sa_t *ike_sa;
- u_int id;
-
- /* our ike_sa pointer might be invalid, lookup sa */
- enumerator = charon->controller->create_ike_sa_enumerator(
- charon->controller, TRUE);
- while (enumerator->enumerate(enumerator, &ike_sa))
- {
- if (priv->ike_sa == ike_sa)
- {
- id = ike_sa->get_unique_id(ike_sa);
- enumerator->destroy(enumerator);
- charon->controller->terminate_ike(charon->controller, id,
- controller_cb_empty, NULL, 0);
- return TRUE;
- }
- }
- enumerator->destroy(enumerator);
-
- g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_GENERAL,
- "Connection not found.");
- return FALSE;
-}
-
-/**
- * Initializer
- */
-static void nm_strongswan_plugin_init(NMStrongswanPlugin *plugin)
-{
- NMStrongswanPluginPrivate *priv;
-
- priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
- priv->plugin = NM_VPN_PLUGIN(plugin);
- memset(&priv->listener.log, 0, sizeof(listener_t));
- priv->listener.child_updown = child_updown;
- priv->listener.ike_rekey = ike_rekey;
-}
-
-/**
- * Class constructor
- */
-static void nm_strongswan_plugin_class_init(
- NMStrongswanPluginClass *strongswan_class)
-{
- NMVPNPluginClass *parent_class = NM_VPN_PLUGIN_CLASS(strongswan_class);
-
- g_type_class_add_private(G_OBJECT_CLASS(strongswan_class),
- sizeof(NMStrongswanPluginPrivate));
- parent_class->connect = connect_;
- parent_class->need_secrets = need_secrets;
- parent_class->disconnect = disconnect;
-}
-
-/**
- * Object constructor
- */
-NMStrongswanPlugin *nm_strongswan_plugin_new(nm_creds_t *creds,
- nm_handler_t *handler)
-{
- NMStrongswanPlugin *plugin = (NMStrongswanPlugin *)g_object_new (
- NM_TYPE_STRONGSWAN_PLUGIN,
- NM_VPN_PLUGIN_DBUS_SERVICE_NAME, NM_DBUS_SERVICE_STRONGSWAN,
- NULL);
- if (plugin)
- {
- NMStrongswanPluginPrivate *priv;
-
- priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
- priv->creds = creds;
- priv->handler = handler;
- priv->name = NULL;
- }
- return plugin;
-}
-
diff --git a/src/libcharon/plugins/nm/nm_service.h b/src/libcharon/plugins/nm/nm_service.h
deleted file mode 100644
index 828d1a452..000000000
--- a/src/libcharon/plugins/nm/nm_service.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2008-2009 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup nm_service nm_service
- * @{ @ingroup nm
- */
-
-#ifndef NM_SERVICE_H_
-#define NM_SERVICE_H_
-
-#include <glib.h>
-#include <glib-object.h>
-#include <nm-vpn-plugin.h>
-
-#include "nm_creds.h"
-#include "nm_handler.h"
-
-#define NM_TYPE_STRONGSWAN_PLUGIN (nm_strongswan_plugin_get_type ())
-#define NM_STRONGSWAN_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_STRONGSWAN_PLUGIN, NMSTRONGSWANPlugin))
-#define NM_STRONGSWAN_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_STRONGSWAN_PLUGIN, NMSTRONGSWANPluginClass))
-#define NM_IS_STRONGSWAN_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_STRONGSWAN_PLUGIN))
-#define NM_IS_STRONGSWAN_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_STRONGSWAN_PLUGIN))
-#define NM_STRONGSWAN_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_STRONGSWAN_PLUGIN, NMSTRONGSWANPluginClass))
-
-#define NM_DBUS_SERVICE_STRONGSWAN "org.freedesktop.NetworkManager.strongswan"
-#define NM_DBUS_INTERFACE_STRONGSWAN "org.freedesktop.NetworkManager.strongswan"
-#define NM_DBUS_PATH_STRONGSWAN "/org/freedesktop/NetworkManager/strongswan"
-
-typedef struct {
- NMVPNPlugin parent;
-} NMStrongswanPlugin;
-
-typedef struct {
- NMVPNPluginClass parent;
-} NMStrongswanPluginClass;
-
-GType nm_strongswan_plugin_get_type(void);
-
-NMStrongswanPlugin *nm_strongswan_plugin_new(nm_creds_t *creds,
- nm_handler_t *handler);
-
-#endif /** NM_SERVICE_H_ @}*/
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/nm/nm_plugin.h b/src/libcharon/plugins/xauth_eap/xauth_eap_plugin.h
index b64b3edf6..8ba0628b0 100644
--- a/src/libcharon/plugins/nm/nm_plugin.h
+++ b/src/libcharon/plugins/xauth_eap/xauth_eap_plugin.h
@@ -1,6 +1,6 @@
/*
- * Copyright (C) 2008 Martin Willi
- * 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
@@ -14,24 +14,24 @@
*/
/**
- * @defgroup nm nm
+ * @defgroup xauth_eap xauth_eap
* @ingroup cplugins
*
- * @defgroup nm_plugin nm_plugin
- * @{ @ingroup nm
+ * @defgroup xauth_eap_plugin xauth_eap_plugin
+ * @{ @ingroup xauth_eap
*/
-#ifndef NM_PLUGIN_H_
-#define NM_PLUGIN_H_
+#ifndef XAUTH_EAP_PLUGIN_H_
+#define XAUTH_EAP_PLUGIN_H_
#include <plugins/plugin.h>
-typedef struct nm_plugin_t nm_plugin_t;
+typedef struct xauth_eap_plugin_t xauth_eap_plugin_t;
/**
- * NetworkManager integration plugin.
+ * XAuth plugin using EAP to verify credentials.
*/
-struct nm_plugin_t {
+struct xauth_eap_plugin_t {
/**
* implements plugin interface
@@ -39,4 +39,4 @@ struct nm_plugin_t {
plugin_t plugin;
};
-#endif /** NM_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/socket_raw/socket_raw_plugin.h b/src/libcharon/plugins/xauth_pam/xauth_pam_plugin.h
index a692b7594..b75268880 100644
--- a/src/libcharon/plugins/socket_raw/socket_raw_plugin.h
+++ b/src/libcharon/plugins/xauth_pam/xauth_pam_plugin.h
@@ -1,6 +1,6 @@
/*
- * Copyright (C) 2010 Martin Willi
- * Copyright (C) 2010 revosec AG
+ * 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
@@ -14,24 +14,24 @@
*/
/**
- * @defgroup socket_raw socket_raw
+ * @defgroup xauth_pam xauth_pam
* @ingroup cplugins
*
- * @defgroup socket_raw_plugin socket_raw_plugin
- * @{ @ingroup socket_raw
+ * @defgroup xauth_pam_plugin xauth_pam_plugin
+ * @{ @ingroup xauth_pam
*/
-#ifndef SOCKET_RAW_PLUGIN_H_
-#define SOCKET_RAW_PLUGIN_H_
+#ifndef XAUTH_PAM_PLUGIN_H_
+#define XAUTH_PAM_PLUGIN_H_
#include <plugins/plugin.h>
-typedef struct socket_raw_plugin_t socket_raw_plugin_t;
+typedef struct xauth_pam_plugin_t xauth_pam_plugin_t;
/**
- * RAW socket implementation plugin.
+ * XAuth plugin using Pluggable Authentication Modules to verify credentials.
*/
-struct socket_raw_plugin_t {
+struct xauth_pam_plugin_t {
/**
* implements plugin interface
@@ -39,4 +39,4 @@ struct socket_raw_plugin_t {
plugin_t plugin;
};
-#endif /** SOCKET_RAW_PLUGIN_H_ @}*/
+#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_ @}*/