summaryrefslogtreecommitdiff
path: root/src/libcharon
diff options
context:
space:
mode:
authorRené Mayrhofer <rene@mayrhofer.eu.org>2011-03-05 09:20:09 +0100
committerRené Mayrhofer <rene@mayrhofer.eu.org>2011-03-05 09:20:09 +0100
commit568905f488e63e28778f87ac0e38d845f45bae79 (patch)
treed9969a147e36413583ff4bc75542d34c955f8823 /src/libcharon
parentf73fba54dc8b30c6482e1e8abf15bbf455592fcd (diff)
downloadvyos-strongswan-568905f488e63e28778f87ac0e38d845f45bae79.tar.gz
vyos-strongswan-568905f488e63e28778f87ac0e38d845f45bae79.zip
Imported Upstream version 4.5.1
Diffstat (limited to 'src/libcharon')
-rw-r--r--src/libcharon/Makefile.am20
-rw-r--r--src/libcharon/Makefile.in157
-rw-r--r--src/libcharon/bus/bus.c2
-rw-r--r--src/libcharon/config/backend_manager.c74
-rw-r--r--src/libcharon/config/child_cfg.c268
-rw-r--r--src/libcharon/config/child_cfg.h31
-rw-r--r--src/libcharon/config/peer_cfg.c2
-rw-r--r--src/libcharon/config/proposal.c10
-rw-r--r--src/libcharon/daemon.c220
-rw-r--r--src/libcharon/daemon.h19
-rw-r--r--src/libcharon/encoding/generator.c375
-rw-r--r--src/libcharon/encoding/message.c174
-rw-r--r--src/libcharon/encoding/message.h41
-rw-r--r--src/libcharon/encoding/parser.c34
-rw-r--r--src/libcharon/encoding/payloads/auth_payload.c205
-rw-r--r--src/libcharon/encoding/payloads/auth_payload.h24
-rw-r--r--src/libcharon/encoding/payloads/cert_payload.c198
-rw-r--r--src/libcharon/encoding/payloads/cert_payload.h9
-rw-r--r--src/libcharon/encoding/payloads/certreq_payload.c161
-rw-r--r--src/libcharon/encoding/payloads/configuration_attribute.c108
-rw-r--r--src/libcharon/encoding/payloads/cp_payload.c169
-rw-r--r--src/libcharon/encoding/payloads/delete_payload.c21
-rw-r--r--src/libcharon/encoding/payloads/eap_payload.c19
-rw-r--r--src/libcharon/encoding/payloads/id_payload.c220
-rw-r--r--src/libcharon/encoding/payloads/id_payload.h44
-rw-r--r--src/libcharon/encoding/payloads/ike_header.c315
-rw-r--r--src/libcharon/encoding/payloads/ike_header.h22
-rw-r--r--src/libcharon/encoding/payloads/ke_payload.c203
-rw-r--r--src/libcharon/encoding/payloads/ke_payload.h23
-rw-r--r--src/libcharon/encoding/payloads/nonce_payload.c178
-rw-r--r--src/libcharon/encoding/payloads/notify_payload.c207
-rw-r--r--src/libcharon/encoding/payloads/payload.c64
-rw-r--r--src/libcharon/encoding/payloads/payload.h39
-rw-r--r--src/libcharon/encoding/payloads/proposal_substructure.c62
-rw-r--r--src/libcharon/encoding/payloads/proposal_substructure.h6
-rw-r--r--src/libcharon/encoding/payloads/sa_payload.c27
-rw-r--r--src/libcharon/encoding/payloads/sa_payload.h7
-rw-r--r--src/libcharon/encoding/payloads/traffic_selector_substructure.c164
-rw-r--r--src/libcharon/encoding/payloads/transform_attribute.c221
-rw-r--r--src/libcharon/encoding/payloads/transform_substructure.c299
-rw-r--r--src/libcharon/encoding/payloads/transform_substructure.h65
-rw-r--r--src/libcharon/encoding/payloads/ts_payload.c273
-rw-r--r--src/libcharon/encoding/payloads/ts_payload.h34
-rw-r--r--src/libcharon/encoding/payloads/unknown_payload.c172
-rw-r--r--src/libcharon/encoding/payloads/unknown_payload.h18
-rw-r--r--src/libcharon/encoding/payloads/vendor_id_payload.c125
-rw-r--r--src/libcharon/encoding/payloads/vendor_id_payload.h5
-rw-r--r--src/libcharon/plugins/addrblock/Makefile.in4
-rw-r--r--src/libcharon/plugins/addrblock/addrblock_validator.c9
-rw-r--r--src/libcharon/plugins/android/Makefile.in4
-rw-r--r--src/libcharon/plugins/android/android_creds.c2
-rw-r--r--src/libcharon/plugins/android/android_service.c4
-rw-r--r--src/libcharon/plugins/dhcp/Makefile.in4
-rw-r--r--src/libcharon/plugins/dhcp/dhcp_socket.c7
-rw-r--r--src/libcharon/plugins/eap_aka/Makefile.in4
-rw-r--r--src/libcharon/plugins/eap_aka_3gpp2/Makefile.in4
-rw-r--r--src/libcharon/plugins/eap_gtc/Makefile.in4
-rw-r--r--src/libcharon/plugins/eap_identity/Makefile.in4
-rw-r--r--src/libcharon/plugins/eap_md5/Makefile.in4
-rw-r--r--src/libcharon/plugins/eap_mschapv2/Makefile.in4
-rw-r--r--src/libcharon/plugins/eap_radius/Makefile.in4
-rw-r--r--src/libcharon/plugins/eap_sim/Makefile.in4
-rw-r--r--src/libcharon/plugins/eap_sim_file/Makefile.in4
-rw-r--r--src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in4
-rw-r--r--src/libcharon/plugins/eap_simaka_reauth/Makefile.in4
-rw-r--r--src/libcharon/plugins/eap_simaka_sql/Makefile.in4
-rw-r--r--src/libcharon/plugins/eap_tls/Makefile.in4
-rw-r--r--src/libcharon/plugins/eap_tnc/Makefile.in4
-rw-r--r--src/libcharon/plugins/eap_tnc/eap_tnc.c26
-rw-r--r--src/libcharon/plugins/eap_ttls/Makefile.in4
-rw-r--r--src/libcharon/plugins/eap_ttls/eap_ttls_peer.c1
-rw-r--r--src/libcharon/plugins/farp/Makefile.in4
-rw-r--r--src/libcharon/plugins/ha/Makefile.in4
-rw-r--r--src/libcharon/plugins/ha/ha_ctl.c9
-rw-r--r--src/libcharon/plugins/ha/ha_dispatcher.c8
-rw-r--r--src/libcharon/plugins/ha/ha_segments.c14
-rw-r--r--src/libcharon/plugins/ha/ha_socket.c8
-rw-r--r--src/libcharon/plugins/ha/ha_tunnel.c4
-rw-r--r--src/libcharon/plugins/led/Makefile.in4
-rw-r--r--src/libcharon/plugins/load_tester/Makefile.in4
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_config.c4
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_ipsec.c2
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_plugin.c4
-rw-r--r--src/libcharon/plugins/maemo/Makefile.am6
-rw-r--r--src/libcharon/plugins/maemo/Makefile.in11
-rw-r--r--src/libcharon/plugins/maemo/maemo_service.c15
-rw-r--r--src/libcharon/plugins/maemo/org.strongswan.charon.service4
-rw-r--r--src/libcharon/plugins/maemo/org.strongswan.charon.service.in4
-rw-r--r--src/libcharon/plugins/medcli/Makefile.in4
-rw-r--r--src/libcharon/plugins/medcli/medcli_config.c8
-rw-r--r--src/libcharon/plugins/medsrv/Makefile.in4
-rw-r--r--src/libcharon/plugins/nm/Makefile.in4
-rw-r--r--src/libcharon/plugins/nm/nm_creds.c6
-rw-r--r--src/libcharon/plugins/nm/nm_service.c4
-rw-r--r--src/libcharon/plugins/smp/Makefile.in4
-rw-r--r--src/libcharon/plugins/socket_default/Makefile.in4
-rw-r--r--src/libcharon/plugins/socket_dynamic/Makefile.in4
-rw-r--r--src/libcharon/plugins/socket_raw/Makefile.in4
-rw-r--r--src/libcharon/plugins/sql/Makefile.in4
-rw-r--r--src/libcharon/plugins/sql/sql_config.c169
-rw-r--r--src/libcharon/plugins/sql/sql_cred.c246
-rw-r--r--src/libcharon/plugins/sql/sql_plugin.c18
-rw-r--r--src/libcharon/plugins/stroke/Makefile.am3
-rw-r--r--src/libcharon/plugins/stroke/Makefile.in10
-rw-r--r--src/libcharon/plugins/stroke/stroke_ca.c76
-rw-r--r--src/libcharon/plugins/stroke/stroke_config.c103
-rw-r--r--src/libcharon/plugins/stroke/stroke_control.c189
-rw-r--r--src/libcharon/plugins/stroke/stroke_control.h7
-rw-r--r--src/libcharon/plugins/stroke/stroke_cred.c409
-rw-r--r--src/libcharon/plugins/stroke/stroke_list.c130
-rw-r--r--src/libcharon/plugins/stroke/stroke_plugin.c18
-rw-r--r--src/libcharon/plugins/stroke/stroke_shared_key.c140
-rw-r--r--src/libcharon/plugins/stroke/stroke_shared_key.h60
-rw-r--r--src/libcharon/plugins/stroke/stroke_socket.c23
-rw-r--r--src/libcharon/plugins/tnc_imc/Makefile.am7
-rw-r--r--src/libcharon/plugins/tnc_imc/Makefile.in18
-rw-r--r--src/libcharon/plugins/tnc_imc/tnc_imc.c207
-rw-r--r--src/libcharon/plugins/tnc_imc/tnc_imc.h36
-rw-r--r--src/libcharon/plugins/tnc_imc/tnc_imc_bind_function.c83
-rw-r--r--src/libcharon/plugins/tnc_imc/tnc_imc_manager.c238
-rw-r--r--src/libcharon/plugins/tnc_imc/tnc_imc_manager.h32
-rw-r--r--src/libcharon/plugins/tnc_imc/tnc_imc_plugin.c141
-rw-r--r--src/libcharon/plugins/tnc_imv/Makefile.am8
-rw-r--r--src/libcharon/plugins/tnc_imv/Makefile.in21
-rw-r--r--src/libcharon/plugins/tnc_imv/tnc_imv.c208
-rw-r--r--src/libcharon/plugins/tnc_imv/tnc_imv.h36
-rw-r--r--src/libcharon/plugins/tnc_imv/tnc_imv_bind_function.c137
-rw-r--r--src/libcharon/plugins/tnc_imv/tnc_imv_manager.c295
-rw-r--r--src/libcharon/plugins/tnc_imv/tnc_imv_manager.h32
-rw-r--r--src/libcharon/plugins/tnc_imv/tnc_imv_plugin.c137
-rw-r--r--src/libcharon/plugins/tnc_imv/tnc_imv_recommendations.c415
-rw-r--r--src/libcharon/plugins/tnc_imv/tnc_imv_recommendations.h33
-rw-r--r--src/libcharon/plugins/tnccs_11/Makefile.am16
-rw-r--r--src/libcharon/plugins/tnccs_11/Makefile.in92
-rw-r--r--src/libcharon/plugins/tnccs_11/batch/tnccs_batch.c323
-rw-r--r--src/libcharon/plugins/tnccs_11/batch/tnccs_batch.h100
-rw-r--r--src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.c242
-rw-r--r--src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.h71
-rw-r--r--src/libcharon/plugins/tnccs_11/messages/tnccs_error_msg.c191
-rw-r--r--src/libcharon/plugins/tnccs_11/messages/tnccs_error_msg.h80
-rw-r--r--src/libcharon/plugins/tnccs_11/messages/tnccs_msg.c140
-rw-r--r--src/libcharon/plugins/tnccs_11/messages/tnccs_msg.h102
-rw-r--r--src/libcharon/plugins/tnccs_11/messages/tnccs_preferred_language_msg.c137
-rw-r--r--src/libcharon/plugins/tnccs_11/messages/tnccs_preferred_language_msg.h64
-rw-r--r--src/libcharon/plugins/tnccs_11/messages/tnccs_reason_strings_msg.c149
-rw-r--r--src/libcharon/plugins/tnccs_11/messages/tnccs_reason_strings_msg.h64
-rw-r--r--src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.c186
-rw-r--r--src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.h64
-rw-r--r--src/libcharon/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.c118
-rw-r--r--src/libcharon/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.h54
-rw-r--r--src/libcharon/plugins/tnccs_11/tnccs_11.c515
-rw-r--r--src/libcharon/plugins/tnccs_20/Makefile.am21
-rw-r--r--src/libcharon/plugins/tnccs_20/Makefile.in121
-rw-r--r--src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c543
-rw-r--r--src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.h126
-rw-r--r--src/libcharon/plugins/tnccs_20/messages/pb_access_recommendation_msg.c180
-rw-r--r--src/libcharon/plugins/tnccs_20/messages/pb_access_recommendation_msg.h76
-rw-r--r--src/libcharon/plugins/tnccs_20/messages/pb_assessment_result_msg.c172
-rw-r--r--src/libcharon/plugins/tnccs_20/messages/pb_assessment_result_msg.h60
-rw-r--r--src/libcharon/plugins/tnccs_20/messages/pb_error_msg.c346
-rw-r--r--src/libcharon/plugins/tnccs_20/messages/pb_error_msg.h127
-rw-r--r--src/libcharon/plugins/tnccs_20/messages/pb_experimental_msg.c102
-rw-r--r--src/libcharon/plugins/tnccs_20/messages/pb_experimental_msg.h53
-rw-r--r--src/libcharon/plugins/tnccs_20/messages/pb_language_preference_msg.c175
-rw-r--r--src/libcharon/plugins/tnccs_20/messages/pb_language_preference_msg.h60
-rw-r--r--src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.c293
-rw-r--r--src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.h123
-rw-r--r--src/libcharon/plugins/tnccs_20/messages/pb_reason_string_msg.c216
-rw-r--r--src/libcharon/plugins/tnccs_20/messages/pb_reason_string_msg.h69
-rw-r--r--src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.c259
-rw-r--r--src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.h96
-rw-r--r--src/libcharon/plugins/tnccs_20/messages/pb_tnc_msg.c75
-rw-r--r--src/libcharon/plugins/tnccs_20/messages/pb_tnc_msg.h128
-rw-r--r--src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.c287
-rw-r--r--src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.h88
-rw-r--r--src/libcharon/plugins/tnccs_20/tnccs_20.c575
-rw-r--r--src/libcharon/plugins/tnccs_dynamic/Makefile.am17
-rw-r--r--src/libcharon/plugins/tnccs_dynamic/Makefile.in607
-rw-r--r--src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.c146
-rw-r--r--src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.h36
-rw-r--r--src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic_plugin.c47
-rw-r--r--src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic_plugin.h42
-rw-r--r--src/libcharon/plugins/uci/Makefile.in4
-rw-r--r--src/libcharon/plugins/uci/uci_config.c4
-rw-r--r--src/libcharon/plugins/unit_tester/Makefile.in4
-rw-r--r--src/libcharon/plugins/updown/Makefile.in4
-rw-r--r--src/libcharon/processing/jobs/acquire_job.c31
-rw-r--r--src/libcharon/processing/jobs/delete_child_sa_job.c35
-rw-r--r--src/libcharon/processing/jobs/delete_ike_sa_job.c31
-rw-r--r--src/libcharon/processing/jobs/migrate_job.c39
-rw-r--r--src/libcharon/processing/jobs/process_message_job.c29
-rw-r--r--src/libcharon/processing/jobs/rekey_child_sa_job.c33
-rw-r--r--src/libcharon/processing/jobs/rekey_ike_sa_job.c31
-rw-r--r--src/libcharon/processing/jobs/retransmit_job.c31
-rw-r--r--src/libcharon/processing/jobs/roam_job.c29
-rw-r--r--src/libcharon/processing/jobs/send_dpd_job.c29
-rw-r--r--src/libcharon/processing/jobs/send_keepalive_job.c29
-rw-r--r--src/libcharon/processing/jobs/start_action_job.c101
-rw-r--r--src/libcharon/processing/jobs/start_action_job.h49
-rw-r--r--src/libcharon/processing/jobs/update_sa_job.c33
-rw-r--r--src/libcharon/sa/authenticators/authenticator.c20
-rw-r--r--src/libcharon/sa/authenticators/authenticator.h8
-rw-r--r--src/libcharon/sa/authenticators/eap_authenticator.c18
-rw-r--r--src/libcharon/sa/authenticators/eap_authenticator.h8
-rw-r--r--src/libcharon/sa/authenticators/psk_authenticator.c94
-rw-r--r--src/libcharon/sa/authenticators/psk_authenticator.h8
-rw-r--r--src/libcharon/sa/authenticators/pubkey_authenticator.c90
-rw-r--r--src/libcharon/sa/authenticators/pubkey_authenticator.h8
-rw-r--r--src/libcharon/sa/child_sa.c12
-rw-r--r--src/libcharon/sa/child_sa.h3
-rw-r--r--src/libcharon/sa/connect_manager.c5
-rw-r--r--src/libcharon/sa/ike_sa.c79
-rw-r--r--src/libcharon/sa/ike_sa.h3
-rw-r--r--src/libcharon/sa/ike_sa_manager.c474
-rw-r--r--src/libcharon/sa/ike_sa_manager.h18
-rw-r--r--src/libcharon/sa/keymat.c10
-rw-r--r--src/libcharon/sa/keymat.h8
-rw-r--r--src/libcharon/sa/task_manager.c46
-rw-r--r--src/libcharon/sa/task_manager.h10
-rw-r--r--src/libcharon/sa/tasks/child_create.c182
-rw-r--r--src/libcharon/sa/tasks/child_rekey.c7
-rw-r--r--src/libcharon/sa/tasks/ike_auth.c200
-rw-r--r--src/libcharon/sa/tasks/ike_cert_pre.c19
-rw-r--r--src/libcharon/sa/tasks/ike_rekey.c7
-rw-r--r--src/libcharon/tnc/imc/imc.h175
-rw-r--r--src/libcharon/tnc/imc/imc_manager.h116
-rw-r--r--src/libcharon/tnc/imv/imv.h175
-rw-r--r--src/libcharon/tnc/imv/imv_manager.h134
-rw-r--r--src/libcharon/tnc/imv/imv_recommendations.c24
-rw-r--r--src/libcharon/tnc/imv/imv_recommendations.h117
-rw-r--r--src/libcharon/tnc/tnccs/tnccs.c (renamed from src/libcharon/tnccs/tnccs.c)3
-rw-r--r--src/libcharon/tnc/tnccs/tnccs.h (renamed from src/libcharon/tnccs/tnccs.h)40
-rw-r--r--src/libcharon/tnc/tnccs/tnccs_manager.c477
-rw-r--r--src/libcharon/tnc/tnccs/tnccs_manager.h184
-rw-r--r--src/libcharon/tnc/tncif.h106
-rw-r--r--src/libcharon/tnc/tncifimc.h180
-rw-r--r--src/libcharon/tnc/tncifimv.c36
-rw-r--r--src/libcharon/tnc/tncifimv.h248
-rw-r--r--src/libcharon/tnccs/tnccs_manager.c148
-rw-r--r--src/libcharon/tnccs/tnccs_manager.h74
240 files changed, 15901 insertions, 5292 deletions
diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am
index 2b7646327..1e78c9d79 100644
--- a/src/libcharon/Makefile.am
+++ b/src/libcharon/Makefile.am
@@ -53,6 +53,7 @@ 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/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 \
@@ -87,8 +88,12 @@ 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 \
-tnccs/tnccs.c tnccs/tnccs.h \
-tnccs/tnccs_manager.h tnccs/tnccs_manager.c
+tnc/tncif.h tnc/tncifimc.h tnc/tncifimv.h tnc/tncifimv.c \
+tnc/imc/imc.h tnc/imc/imc_manager.h \
+tnc/imv/imv.h tnc/imv/imv_manager.h \
+tnc/imv/imv_recommendations.c tnc/imv/imv_recommendations.h \
+tnc/tnccs/tnccs.c tnc/tnccs/tnccs.h \
+tnc/tnccs/tnccs_manager.c tnc/tnccs/tnccs_manager.h
daemon.lo : $(top_builddir)/config.status
@@ -317,14 +322,14 @@ endif
if USE_TNC_IMC
SUBDIRS += plugins/tnc_imc
if MONOLITHIC
- libcharon_la_LIBADD += plugins/tnc_imc/libstrongswan-tnc_imc.la
+ libcharon_la_LIBADD += plugins/tnc_imc/libstrongswan-tnc-imc.la
endif
endif
if USE_TNC_IMV
SUBDIRS += plugins/tnc_imv
if MONOLITHIC
- libcharon_la_LIBADD += plugins/tnc_imv/libstrongswan-tnc_imv.la
+ libcharon_la_LIBADD += plugins/tnc_imv/libstrongswan-tnc-imv.la
endif
endif
@@ -342,6 +347,13 @@ if MONOLITHIC
endif
endif
+if USE_TNCCS_DYNAMIC
+ SUBDIRS += plugins/tnccs_dynamic
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/tnccs_dynamic/libstrongswan-tnccs-dynamic.la
+endif
+endif
+
if USE_MEDSRV
SUBDIRS += plugins/medsrv
if MONOLITHIC
diff --git a/src/libcharon/Makefile.in b/src/libcharon/Makefile.in
index 8a7a99ddd..6ec4c6ca5 100644
--- a/src/libcharon/Makefile.in
+++ b/src/libcharon/Makefile.in
@@ -96,35 +96,37 @@ host_triplet = @host@
@MONOLITHIC_TRUE@@USE_EAP_TNC_TRUE@am__append_51 = plugins/eap_tnc/libstrongswan-eap-tnc.la
@MONOLITHIC_TRUE@@USE_TLS_TRUE@am__append_52 = $(top_builddir)/src/libtls/libtls.la
@USE_TNC_IMC_TRUE@am__append_53 = plugins/tnc_imc
-@MONOLITHIC_TRUE@@USE_TNC_IMC_TRUE@am__append_54 = plugins/tnc_imc/libstrongswan-tnc_imc.la
+@MONOLITHIC_TRUE@@USE_TNC_IMC_TRUE@am__append_54 = plugins/tnc_imc/libstrongswan-tnc-imc.la
@USE_TNC_IMV_TRUE@am__append_55 = plugins/tnc_imv
-@MONOLITHIC_TRUE@@USE_TNC_IMV_TRUE@am__append_56 = plugins/tnc_imv/libstrongswan-tnc_imv.la
+@MONOLITHIC_TRUE@@USE_TNC_IMV_TRUE@am__append_56 = plugins/tnc_imv/libstrongswan-tnc-imv.la
@USE_TNCCS_11_TRUE@am__append_57 = plugins/tnccs_11
@MONOLITHIC_TRUE@@USE_TNCCS_11_TRUE@am__append_58 = plugins/tnccs_11/libstrongswan-tnccs-11.la
@USE_TNCCS_20_TRUE@am__append_59 = plugins/tnccs_20
@MONOLITHIC_TRUE@@USE_TNCCS_20_TRUE@am__append_60 = plugins/tnccs_20/libstrongswan-tnccs-20.la
-@USE_MEDSRV_TRUE@am__append_61 = plugins/medsrv
-@MONOLITHIC_TRUE@@USE_MEDSRV_TRUE@am__append_62 = plugins/medsrv/libstrongswan-medsrv.la
-@USE_MEDCLI_TRUE@am__append_63 = plugins/medcli
-@MONOLITHIC_TRUE@@USE_MEDCLI_TRUE@am__append_64 = plugins/medcli/libstrongswan-medcli.la
-@USE_NM_TRUE@am__append_65 = plugins/nm
-@MONOLITHIC_TRUE@@USE_NM_TRUE@am__append_66 = plugins/nm/libstrongswan-nm.la
-@USE_DHCP_TRUE@am__append_67 = plugins/dhcp
-@MONOLITHIC_TRUE@@USE_DHCP_TRUE@am__append_68 = plugins/dhcp/libstrongswan-dhcp.la
-@USE_ANDROID_TRUE@am__append_69 = plugins/android
-@MONOLITHIC_TRUE@@USE_ANDROID_TRUE@am__append_70 = plugins/android/libstrongswan-android.la
-@USE_MAEMO_TRUE@am__append_71 = plugins/maemo
-@MONOLITHIC_TRUE@@USE_MAEMO_TRUE@am__append_72 = plugins/maemo/libstrongswan-maemo.la
-@USE_HA_TRUE@am__append_73 = plugins/ha
-@MONOLITHIC_TRUE@@USE_HA_TRUE@am__append_74 = plugins/ha/libstrongswan-ha.la
-@USE_LED_TRUE@am__append_75 = plugins/led
-@MONOLITHIC_TRUE@@USE_LED_TRUE@am__append_76 = plugins/led/libstrongswan-led.la
-@USE_UCI_TRUE@am__append_77 = plugins/uci
-@MONOLITHIC_TRUE@@USE_UCI_TRUE@am__append_78 = plugins/uci/libstrongswan-uci.la
-@USE_ADDRBLOCK_TRUE@am__append_79 = plugins/addrblock
-@MONOLITHIC_TRUE@@USE_ADDRBLOCK_TRUE@am__append_80 = plugins/uci/libstrongswan-addrblock.la
-@USE_UNIT_TESTS_TRUE@am__append_81 = plugins/unit_tester
-@MONOLITHIC_TRUE@@USE_UNIT_TESTS_TRUE@am__append_82 = plugins/unit_tester/libstrongswan-unit-tester.la
+@USE_TNCCS_DYNAMIC_TRUE@am__append_61 = plugins/tnccs_dynamic
+@MONOLITHIC_TRUE@@USE_TNCCS_DYNAMIC_TRUE@am__append_62 = plugins/tnccs_dynamic/libstrongswan-tnccs-dynamic.la
+@USE_MEDSRV_TRUE@am__append_63 = plugins/medsrv
+@MONOLITHIC_TRUE@@USE_MEDSRV_TRUE@am__append_64 = plugins/medsrv/libstrongswan-medsrv.la
+@USE_MEDCLI_TRUE@am__append_65 = plugins/medcli
+@MONOLITHIC_TRUE@@USE_MEDCLI_TRUE@am__append_66 = plugins/medcli/libstrongswan-medcli.la
+@USE_NM_TRUE@am__append_67 = plugins/nm
+@MONOLITHIC_TRUE@@USE_NM_TRUE@am__append_68 = plugins/nm/libstrongswan-nm.la
+@USE_DHCP_TRUE@am__append_69 = plugins/dhcp
+@MONOLITHIC_TRUE@@USE_DHCP_TRUE@am__append_70 = plugins/dhcp/libstrongswan-dhcp.la
+@USE_ANDROID_TRUE@am__append_71 = plugins/android
+@MONOLITHIC_TRUE@@USE_ANDROID_TRUE@am__append_72 = plugins/android/libstrongswan-android.la
+@USE_MAEMO_TRUE@am__append_73 = plugins/maemo
+@MONOLITHIC_TRUE@@USE_MAEMO_TRUE@am__append_74 = plugins/maemo/libstrongswan-maemo.la
+@USE_HA_TRUE@am__append_75 = plugins/ha
+@MONOLITHIC_TRUE@@USE_HA_TRUE@am__append_76 = plugins/ha/libstrongswan-ha.la
+@USE_LED_TRUE@am__append_77 = plugins/led
+@MONOLITHIC_TRUE@@USE_LED_TRUE@am__append_78 = plugins/led/libstrongswan-led.la
+@USE_UCI_TRUE@am__append_79 = plugins/uci
+@MONOLITHIC_TRUE@@USE_UCI_TRUE@am__append_80 = plugins/uci/libstrongswan-uci.la
+@USE_ADDRBLOCK_TRUE@am__append_81 = plugins/addrblock
+@MONOLITHIC_TRUE@@USE_ADDRBLOCK_TRUE@am__append_82 = plugins/uci/libstrongswan-addrblock.la
+@USE_UNIT_TESTS_TRUE@am__append_83 = plugins/unit_tester
+@MONOLITHIC_TRUE@@USE_UNIT_TESTS_TRUE@am__append_84 = plugins/unit_tester/libstrongswan-unit-tester.la
subdir = src/libcharon
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -181,7 +183,8 @@ libcharon_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
$(am__append_60) $(am__append_62) $(am__append_64) \
$(am__append_66) $(am__append_68) $(am__append_70) \
$(am__append_72) $(am__append_74) $(am__append_76) \
- $(am__append_78) $(am__append_80) $(am__append_82)
+ $(am__append_78) $(am__append_80) $(am__append_82) \
+ $(am__append_84)
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 \
@@ -251,8 +254,9 @@ am__libcharon_la_SOURCES_DIST = bus/bus.c bus/bus.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/roam_job.c processing/jobs/roam_job.h \
- processing/jobs/update_sa_job.c \
+ 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 \
@@ -288,8 +292,12 @@ am__libcharon_la_SOURCES_DIST = bus/bus.c bus/bus.h \
sa/tasks/ike_reauth.h sa/tasks/ike_auth_lifetime.c \
sa/tasks/ike_auth_lifetime.h sa/tasks/ike_vendor.c \
sa/tasks/ike_vendor.h sa/tasks/task.c sa/tasks/task.h \
- tnccs/tnccs.c tnccs/tnccs.h tnccs/tnccs_manager.h \
- tnccs/tnccs_manager.c encoding/payloads/endpoint_notify.c \
+ tnc/tncif.h tnc/tncifimc.h tnc/tncifimv.h tnc/tncifimv.c \
+ tnc/imc/imc.h tnc/imc/imc_manager.h tnc/imv/imv.h \
+ tnc/imv/imv_manager.h tnc/imv/imv_recommendations.c \
+ tnc/imv/imv_recommendations.h tnc/tnccs/tnccs.c \
+ tnc/tnccs/tnccs.h tnc/tnccs/tnccs_manager.c \
+ tnc/tnccs/tnccs_manager.h encoding/payloads/endpoint_notify.c \
encoding/payloads/endpoint_notify.h \
processing/jobs/initiate_mediation_job.c \
processing/jobs/initiate_mediation_job.h \
@@ -315,16 +323,17 @@ am_libcharon_la_OBJECTS = bus.lo file_logger.lo sys_logger.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 roam_job.lo update_sa_job.lo \
- inactivity_job.lo authenticator.lo eap_authenticator.lo \
- eap_method.lo eap_manager.lo sim_manager.lo \
- psk_authenticator.lo pubkey_authenticator.lo child_sa.lo \
- ike_sa.lo ike_sa_id.lo ike_sa_manager.lo task_manager.lo \
- keymat.lo trap_manager.lo child_create.lo child_delete.lo \
- child_rekey.lo ike_auth.lo ike_cert_pre.lo ike_cert_post.lo \
- ike_config.lo ike_delete.lo ike_dpd.lo ike_init.lo ike_natd.lo \
- ike_mobike.lo ike_rekey.lo ike_reauth.lo ike_auth_lifetime.lo \
- ike_vendor.lo task.lo tnccs.lo tnccs_manager.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 \
+ sim_manager.lo psk_authenticator.lo pubkey_authenticator.lo \
+ child_sa.lo ike_sa.lo ike_sa_id.lo ike_sa_manager.lo \
+ task_manager.lo keymat.lo trap_manager.lo child_create.lo \
+ child_delete.lo child_rekey.lo ike_auth.lo ike_cert_pre.lo \
+ ike_cert_post.lo ike_config.lo ike_delete.lo ike_dpd.lo \
+ ike_init.lo ike_natd.lo ike_mobike.lo ike_rekey.lo \
+ ike_reauth.lo ike_auth_lifetime.lo ike_vendor.lo task.lo \
+ tncifimv.lo imv_recommendations.lo tnccs.lo tnccs_manager.lo \
$(am__objects_1)
libcharon_la_OBJECTS = $(am_libcharon_la_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@
@@ -366,9 +375,9 @@ DIST_SUBDIRS = . plugins/load_tester plugins/socket_default \
plugins/eap_mschapv2 plugins/eap_radius plugins/eap_tls \
plugins/eap_ttls plugins/eap_tnc plugins/tnc_imc \
plugins/tnc_imv plugins/tnccs_11 plugins/tnccs_20 \
- plugins/medsrv plugins/medcli plugins/nm plugins/dhcp \
- plugins/android plugins/maemo plugins/ha plugins/led \
- plugins/uci plugins/addrblock plugins/unit_tester
+ plugins/tnccs_dynamic plugins/medsrv plugins/medcli plugins/nm \
+ plugins/dhcp plugins/android plugins/maemo plugins/ha \
+ plugins/led plugins/uci plugins/addrblock plugins/unit_tester
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
am__relativize = \
dir0=`pwd`; \
@@ -514,9 +523,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -555,6 +562,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
@@ -635,8 +644,9 @@ libcharon_la_SOURCES = bus/bus.c bus/bus.h bus/listeners/listener.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/roam_job.c processing/jobs/roam_job.h \
- processing/jobs/update_sa_job.c \
+ 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 \
@@ -672,8 +682,12 @@ libcharon_la_SOURCES = bus/bus.c bus/bus.h bus/listeners/listener.h \
sa/tasks/ike_reauth.h sa/tasks/ike_auth_lifetime.c \
sa/tasks/ike_auth_lifetime.h sa/tasks/ike_vendor.c \
sa/tasks/ike_vendor.h sa/tasks/task.c sa/tasks/task.h \
- tnccs/tnccs.c tnccs/tnccs.h tnccs/tnccs_manager.h \
- tnccs/tnccs_manager.c $(am__append_1)
+ tnc/tncif.h tnc/tncifimc.h tnc/tncifimv.h tnc/tncifimv.c \
+ tnc/imc/imc.h tnc/imc/imc_manager.h tnc/imv/imv.h \
+ tnc/imv/imv_manager.h tnc/imv/imv_recommendations.c \
+ tnc/imv/imv_recommendations.h tnc/tnccs/tnccs.c \
+ tnc/tnccs/tnccs.h tnc/tnccs/tnccs_manager.c \
+ tnc/tnccs/tnccs_manager.h $(am__append_1)
INCLUDES = \
-I${linux_headers} \
-I$(top_srcdir)/src/libstrongswan \
@@ -699,7 +713,8 @@ libcharon_la_LIBADD = -lm $(PTHREADLIB) $(DLLIB) $(SOCKLIB) \
$(am__append_60) $(am__append_62) $(am__append_64) \
$(am__append_66) $(am__append_68) $(am__append_70) \
$(am__append_72) $(am__append_74) $(am__append_76) \
- $(am__append_78) $(am__append_80) $(am__append_82)
+ $(am__append_78) $(am__append_80) $(am__append_82) \
+ $(am__append_84)
EXTRA_DIST = Android.mk
@MONOLITHIC_FALSE@SUBDIRS = . $(am__append_3) $(am__append_5) \
@MONOLITHIC_FALSE@ $(am__append_7) $(am__append_9) \
@@ -720,7 +735,7 @@ EXTRA_DIST = Android.mk
@MONOLITHIC_FALSE@ $(am__append_69) $(am__append_71) \
@MONOLITHIC_FALSE@ $(am__append_73) $(am__append_75) \
@MONOLITHIC_FALSE@ $(am__append_77) $(am__append_79) \
-@MONOLITHIC_FALSE@ $(am__append_81)
+@MONOLITHIC_FALSE@ $(am__append_81) $(am__append_83)
# build optional plugins
########################
@@ -743,7 +758,7 @@ EXTRA_DIST = Android.mk
@MONOLITHIC_TRUE@ $(am__append_69) $(am__append_71) \
@MONOLITHIC_TRUE@ $(am__append_73) $(am__append_75) \
@MONOLITHIC_TRUE@ $(am__append_77) $(am__append_79) \
-@MONOLITHIC_TRUE@ $(am__append_81)
+@MONOLITHIC_TRUE@ $(am__append_81) $(am__append_83)
all: all-recursive
.SUFFIXES:
@@ -867,6 +882,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_sa_id.Plo@am__quote@
@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)/imv_recommendations.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inactivity_job.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/initiate_mediation_job.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ke_payload.Plo@am__quote@
@@ -898,11 +914,13 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sender.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sim_manager.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/start_action_job.Plo@am__quote@
@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)/tnccs.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tncifimv.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@
@@ -1283,6 +1301,13 @@ send_keepalive_job.lo: processing/jobs/send_keepalive_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 send_keepalive_job.lo `test -f 'processing/jobs/send_keepalive_job.c' || echo '$(srcdir)/'`processing/jobs/send_keepalive_job.c
+start_action_job.lo: processing/jobs/start_action_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 start_action_job.lo -MD -MP -MF $(DEPDIR)/start_action_job.Tpo -c -o start_action_job.lo `test -f 'processing/jobs/start_action_job.c' || echo '$(srcdir)/'`processing/jobs/start_action_job.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/start_action_job.Tpo $(DEPDIR)/start_action_job.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/start_action_job.c' object='start_action_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 start_action_job.lo `test -f 'processing/jobs/start_action_job.c' || echo '$(srcdir)/'`processing/jobs/start_action_job.c
+
roam_job.lo: processing/jobs/roam_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 roam_job.lo -MD -MP -MF $(DEPDIR)/roam_job.Tpo -c -o roam_job.lo `test -f 'processing/jobs/roam_job.c' || echo '$(srcdir)/'`processing/jobs/roam_job.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/roam_job.Tpo $(DEPDIR)/roam_job.Plo
@@ -1521,19 +1546,33 @@ task.lo: sa/tasks/task.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o task.lo `test -f 'sa/tasks/task.c' || echo '$(srcdir)/'`sa/tasks/task.c
-tnccs.lo: tnccs/tnccs.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tnccs.lo -MD -MP -MF $(DEPDIR)/tnccs.Tpo -c -o tnccs.lo `test -f 'tnccs/tnccs.c' || echo '$(srcdir)/'`tnccs/tnccs.c
+tncifimv.lo: tnc/tncifimv.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tncifimv.lo -MD -MP -MF $(DEPDIR)/tncifimv.Tpo -c -o tncifimv.lo `test -f 'tnc/tncifimv.c' || echo '$(srcdir)/'`tnc/tncifimv.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tncifimv.Tpo $(DEPDIR)/tncifimv.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tnc/tncifimv.c' object='tncifimv.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 tncifimv.lo `test -f 'tnc/tncifimv.c' || echo '$(srcdir)/'`tnc/tncifimv.c
+
+imv_recommendations.lo: tnc/imv/imv_recommendations.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imv_recommendations.lo -MD -MP -MF $(DEPDIR)/imv_recommendations.Tpo -c -o imv_recommendations.lo `test -f 'tnc/imv/imv_recommendations.c' || echo '$(srcdir)/'`tnc/imv/imv_recommendations.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/imv_recommendations.Tpo $(DEPDIR)/imv_recommendations.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tnc/imv/imv_recommendations.c' object='imv_recommendations.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 imv_recommendations.lo `test -f 'tnc/imv/imv_recommendations.c' || echo '$(srcdir)/'`tnc/imv/imv_recommendations.c
+
+tnccs.lo: tnc/tnccs/tnccs.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tnccs.lo -MD -MP -MF $(DEPDIR)/tnccs.Tpo -c -o tnccs.lo `test -f 'tnc/tnccs/tnccs.c' || echo '$(srcdir)/'`tnc/tnccs/tnccs.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tnccs.Tpo $(DEPDIR)/tnccs.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tnccs/tnccs.c' object='tnccs.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tnc/tnccs/tnccs.c' object='tnccs.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 tnccs.lo `test -f 'tnccs/tnccs.c' || echo '$(srcdir)/'`tnccs/tnccs.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 tnccs.lo `test -f 'tnc/tnccs/tnccs.c' || echo '$(srcdir)/'`tnc/tnccs/tnccs.c
-tnccs_manager.lo: tnccs/tnccs_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 tnccs_manager.lo -MD -MP -MF $(DEPDIR)/tnccs_manager.Tpo -c -o tnccs_manager.lo `test -f 'tnccs/tnccs_manager.c' || echo '$(srcdir)/'`tnccs/tnccs_manager.c
+tnccs_manager.lo: tnc/tnccs/tnccs_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 tnccs_manager.lo -MD -MP -MF $(DEPDIR)/tnccs_manager.Tpo -c -o tnccs_manager.lo `test -f 'tnc/tnccs/tnccs_manager.c' || echo '$(srcdir)/'`tnc/tnccs/tnccs_manager.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tnccs_manager.Tpo $(DEPDIR)/tnccs_manager.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tnccs/tnccs_manager.c' object='tnccs_manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tnc/tnccs/tnccs_manager.c' object='tnccs_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 tnccs_manager.lo `test -f 'tnccs/tnccs_manager.c' || echo '$(srcdir)/'`tnccs/tnccs_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 tnccs_manager.lo `test -f 'tnc/tnccs/tnccs_manager.c' || echo '$(srcdir)/'`tnc/tnccs/tnccs_manager.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
diff --git a/src/libcharon/bus/bus.c b/src/libcharon/bus/bus.c
index ab8d0fc48..23931c47d 100644
--- a/src/libcharon/bus/bus.c
+++ b/src/libcharon/bus/bus.c
@@ -227,13 +227,13 @@ static bool log_cb(entry_t *entry, log_data_t *data)
{
entry->blocker = FALSE;
entry->condvar->signal(entry->condvar);
+ entry->calling--;
}
else
{
entry_destroy(entry);
}
va_end(args);
- entry->calling--;
return TRUE;
}
va_end(args);
diff --git a/src/libcharon/config/backend_manager.c b/src/libcharon/config/backend_manager.c
index 90ef58563..e78cb702d 100644
--- a/src/libcharon/config/backend_manager.c
+++ b/src/libcharon/config/backend_manager.c
@@ -96,6 +96,11 @@ static ike_cfg_match_t get_ike_match(ike_cfg_t *cand, host_t *me, host_t *other)
{
match += MATCH_ANY;
}
+ else
+ {
+ me_cand->destroy(me_cand);
+ return MATCH_NONE;
+ }
me_cand->destroy(me_cand);
}
else
@@ -119,6 +124,11 @@ static ike_cfg_match_t get_ike_match(ike_cfg_t *cand, host_t *me, host_t *other)
{
match += MATCH_ANY;
}
+ else
+ {
+ other_cand->destroy(other_cand);
+ return MATCH_NONE;
+ }
other_cand->destroy(other_cand);
}
else
@@ -128,11 +138,8 @@ static ike_cfg_match_t get_ike_match(ike_cfg_t *cand, host_t *me, host_t *other)
return match;
}
-/**
- * implements backend_manager_t.get_ike_cfg.
- */
-static ike_cfg_t *get_ike_cfg(private_backend_manager_t *this,
- host_t *me, host_t *other)
+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;
enumerator_t *enumerator;
@@ -308,12 +315,9 @@ static void insert_sorted(match_entry_t *entry, linked_list_t *list,
}
}
-/**
- * Implements backend_manager_t.create_peer_cfg_enumerator.
- */
-static enumerator_t *create_peer_cfg_enumerator(private_backend_manager_t *this,
- host_t *me, host_t *other, identification_t *my_id,
- identification_t *other_id)
+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)
{
enumerator_t *enumerator;
peer_data_t *data;
@@ -372,10 +376,8 @@ static enumerator_t *create_peer_cfg_enumerator(private_backend_manager_t *this,
(void*)peer_enum_filter_destroy);
}
-/**
- * implements backend_manager_t.get_peer_cfg_by_name.
- */
-static peer_cfg_t *get_peer_cfg_by_name(private_backend_manager_t *this, char *name)
+METHOD(backend_manager_t, get_peer_cfg_by_name, peer_cfg_t*,
+ private_backend_manager_t *this, char *name)
{
backend_t *backend;
peer_cfg_t *config = NULL;
@@ -392,30 +394,24 @@ static peer_cfg_t *get_peer_cfg_by_name(private_backend_manager_t *this, char *n
return config;
}
-/**
- * Implementation of backend_manager_t.remove_backend.
- */
-static void remove_backend(private_backend_manager_t *this, backend_t *backend)
+METHOD(backend_manager_t, remove_backend, void,
+ private_backend_manager_t *this, backend_t *backend)
{
this->lock->write_lock(this->lock);
this->backends->remove(this->backends, backend, NULL);
this->lock->unlock(this->lock);
}
-/**
- * Implementation of backend_manager_t.add_backend.
- */
-static void add_backend(private_backend_manager_t *this, backend_t *backend)
+METHOD(backend_manager_t, add_backend, void,
+ private_backend_manager_t *this, backend_t *backend)
{
this->lock->write_lock(this->lock);
this->backends->insert_last(this->backends, backend);
this->lock->unlock(this->lock);
}
-/**
- * Implementation of backend_manager_t.destroy.
- */
-static void destroy(private_backend_manager_t *this)
+METHOD(backend_manager_t, destroy, void,
+ private_backend_manager_t *this)
{
this->backends->destroy(this->backends);
this->lock->destroy(this->lock);
@@ -424,20 +420,24 @@ static void destroy(private_backend_manager_t *this)
/*
* Described in header-file
+
*/
backend_manager_t *backend_manager_create()
{
- private_backend_manager_t *this = malloc_thing(private_backend_manager_t);
-
- this->public.get_ike_cfg = (ike_cfg_t* (*)(backend_manager_t*, host_t*, host_t*))get_ike_cfg;
- this->public.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_manager_t*,char*))get_peer_cfg_by_name;
- this->public.create_peer_cfg_enumerator = (enumerator_t* (*)(backend_manager_t*,host_t*,host_t*,identification_t*,identification_t*))create_peer_cfg_enumerator;
- this->public.add_backend = (void(*)(backend_manager_t*, backend_t *backend))add_backend;
- this->public.remove_backend = (void(*)(backend_manager_t*, backend_t *backend))remove_backend;
- this->public.destroy = (void (*)(backend_manager_t*))destroy;
+ private_backend_manager_t *this;
- this->backends = linked_list_create();
- this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
+ INIT(this,
+ .public = {
+ .get_ike_cfg = _get_ike_cfg,
+ .get_peer_cfg_by_name = _get_peer_cfg_by_name,
+ .create_peer_cfg_enumerator = _create_peer_cfg_enumerator,
+ .add_backend = _add_backend,
+ .remove_backend = _remove_backend,
+ .destroy = _destroy,
+ },
+ .backends = linked_list_create(),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ );
return &this->public;
}
diff --git a/src/libcharon/config/child_cfg.c b/src/libcharon/config/child_cfg.c
index 1cdfd5949..74949be3c 100644
--- a/src/libcharon/config/child_cfg.c
+++ b/src/libcharon/config/child_cfg.c
@@ -80,6 +80,11 @@ struct private_child_cfg_t {
ipsec_mode_t mode;
/**
+ * action to take to start CHILD_SA
+ */
+ action_t start_action;
+
+ /**
* action to take on DPD
*/
action_t dpd_action;
@@ -118,6 +123,12 @@ struct private_child_cfg_t {
* Optional mark to install outbound CHILD_SA with
*/
mark_t mark_out;
+
+ /**
+ * Traffic Flow Confidentiality padding, if enabled
+ */
+ u_int32_t tfc;
+
/**
* set up IPsec transport SA in MIPv6 proxy mode
*/
@@ -129,26 +140,20 @@ struct private_child_cfg_t {
bool install_policy;
};
-/**
- * Implementation of child_cfg_t.get_name.
- */
-static char *get_name(private_child_cfg_t *this)
+METHOD(child_cfg_t, get_name, char*,
+ private_child_cfg_t *this)
{
return this->name;
}
-/**
- * Implementation of child_cfg_t.add_proposal.
- */
-static void add_proposal(private_child_cfg_t *this, proposal_t *proposal)
+METHOD(child_cfg_t, add_proposal, void,
+ private_child_cfg_t *this, proposal_t *proposal)
{
this->proposals->insert_last(this->proposals, proposal);
}
-/**
- * Implementation of child_cfg_t.get_proposals.
- */
-static linked_list_t* get_proposals(private_child_cfg_t *this, bool strip_dh)
+METHOD(child_cfg_t, get_proposals, linked_list_t*,
+ private_child_cfg_t *this, bool strip_dh)
{
enumerator_t *enumerator;
proposal_t *current;
@@ -169,12 +174,9 @@ static linked_list_t* get_proposals(private_child_cfg_t *this, bool strip_dh)
return proposals;
}
-/**
- * Implementation of child_cfg_t.select_proposal.
- */
-static proposal_t* select_proposal(private_child_cfg_t*this,
- linked_list_t *proposals, bool strip_dh,
- bool private)
+METHOD(child_cfg_t, select_proposal, proposal_t*,
+ private_child_cfg_t*this, linked_list_t *proposals, bool strip_dh,
+ bool private)
{
enumerator_t *stored_enum, *supplied_enum;
proposal_t *stored, *supplied, *selected = NULL;
@@ -219,11 +221,8 @@ static proposal_t* select_proposal(private_child_cfg_t*this,
return selected;
}
-/**
- * Implementation of child_cfg_t.add_traffic_selector.
- */
-static void add_traffic_selector(private_child_cfg_t *this, bool local,
- traffic_selector_t *ts)
+METHOD(child_cfg_t, add_traffic_selector, void,
+ private_child_cfg_t *this, bool local, traffic_selector_t *ts)
{
if (local)
{
@@ -235,12 +234,8 @@ static void add_traffic_selector(private_child_cfg_t *this, bool local,
}
}
-/**
- * Implementation of child_cfg_t.get_traffic_selectors.
- */
-static linked_list_t* get_traffic_selectors(private_child_cfg_t *this, bool local,
- linked_list_t *supplied,
- host_t *host)
+METHOD(child_cfg_t, get_traffic_selectors, linked_list_t*,
+ private_child_cfg_t *this, bool local, linked_list_t *supplied, host_t *host)
{
enumerator_t *e1, *e2;
traffic_selector_t *ts1, *ts2, *selected;
@@ -346,18 +341,14 @@ static linked_list_t* get_traffic_selectors(private_child_cfg_t *this, bool loca
return result;
}
-/**
- * Implementation of child_cfg_t.get_updown.
- */
-static char* get_updown(private_child_cfg_t *this)
+METHOD(child_cfg_t, get_updown, char*,
+ private_child_cfg_t *this)
{
return this->updown;
}
-/**
- * Implementation of child_cfg_t.get_hostaccess.
- */
-static bool get_hostaccess(private_child_cfg_t *this)
+METHOD(child_cfg_t, get_hostaccess, bool,
+ private_child_cfg_t *this)
{
return this->hostaccess;
}
@@ -378,10 +369,8 @@ static u_int64_t apply_jitter(u_int64_t rekey, u_int64_t jitter)
}
#define APPLY_JITTER(l) l.rekey = apply_jitter(l.rekey, l.jitter)
-/**
- * Implementation of child_cfg_t.get_lifetime.
- */
-static lifetime_cfg_t *get_lifetime(private_child_cfg_t *this)
+METHOD(child_cfg_t, get_lifetime, lifetime_cfg_t*,
+ private_child_cfg_t *this)
{
lifetime_cfg_t *lft = malloc_thing(lifetime_cfg_t);
memcpy(lft, &this->lifetime, sizeof(lifetime_cfg_t));
@@ -391,34 +380,32 @@ static lifetime_cfg_t *get_lifetime(private_child_cfg_t *this)
return lft;
}
-/**
- * Implementation of child_cfg_t.get_mode.
- */
-static ipsec_mode_t get_mode(private_child_cfg_t *this)
+METHOD(child_cfg_t, get_mode, ipsec_mode_t,
+ private_child_cfg_t *this)
{
return this->mode;
}
-/**
- * Implementation of child_cfg_t.get_dpd_action.
- */
-static action_t get_dpd_action(private_child_cfg_t *this)
+METHOD(child_cfg_t, get_start_action, action_t,
+ private_child_cfg_t *this)
+{
+ return this->start_action;
+}
+
+METHOD(child_cfg_t, get_dpd_action, action_t,
+ private_child_cfg_t *this)
{
return this->dpd_action;
}
-/**
- * Implementation of child_cfg_t.get_close_action.
- */
-static action_t get_close_action(private_child_cfg_t *this)
+METHOD(child_cfg_t, get_close_action, action_t,
+ private_child_cfg_t *this)
{
return this->close_action;
}
-/**
- * Implementation of child_cfg_t.get_dh_group.
- */
-static diffie_hellman_group_t get_dh_group(private_child_cfg_t *this)
+METHOD(child_cfg_t, get_dh_group, diffie_hellman_group_t,
+ private_child_cfg_t *this)
{
enumerator_t *enumerator;
proposal_t *proposal;
@@ -436,77 +423,64 @@ static diffie_hellman_group_t get_dh_group(private_child_cfg_t *this)
return dh_group;
}
-/**
- * Implementation of child_cfg_t.use_ipcomp.
- */
-static bool use_ipcomp(private_child_cfg_t *this)
+METHOD(child_cfg_t, use_ipcomp, bool,
+ private_child_cfg_t *this)
{
return this->use_ipcomp;
}
-/**
- * Implementation of child_cfg_t.get_inactivity.
- */
-static u_int32_t get_inactivity(private_child_cfg_t *this)
+METHOD(child_cfg_t, get_inactivity, u_int32_t,
+ private_child_cfg_t *this)
{
return this->inactivity;
}
-/**
- * Implementation of child_cfg_t.get_reqid.
- */
-static u_int32_t get_reqid(private_child_cfg_t *this)
+METHOD(child_cfg_t, get_reqid, u_int32_t,
+ private_child_cfg_t *this)
{
return this->reqid;
}
-/**
- * Implementation of child_cfg_t.get_mark.
- */
-static mark_t get_mark(private_child_cfg_t *this, bool inbound)
+METHOD(child_cfg_t, get_mark, mark_t,
+ private_child_cfg_t *this, bool inbound)
{
return inbound ? this->mark_in : this->mark_out;
}
-/**
- * Implementation of child_cfg_t.set_mipv6_options.
- */
-static void set_mipv6_options(private_child_cfg_t *this, bool proxy_mode,
- bool install_policy)
+METHOD(child_cfg_t, get_tfc, u_int32_t,
+ private_child_cfg_t *this)
+{
+ return this->tfc;
+}
+
+METHOD(child_cfg_t, set_mipv6_options, void,
+ private_child_cfg_t *this, bool proxy_mode, bool install_policy)
{
this->proxy_mode = proxy_mode;
this->install_policy = install_policy;
}
-/**
- * Implementation of child_cfg_t.use_proxy_mode.
- */
-static bool use_proxy_mode(private_child_cfg_t *this)
+METHOD(child_cfg_t, use_proxy_mode, bool,
+ private_child_cfg_t *this)
{
return this->proxy_mode;
}
-/**
- * Implementation of child_cfg_t.install_policy.
- */
-static bool install_policy(private_child_cfg_t *this)
+METHOD(child_cfg_t, install_policy, bool,
+ private_child_cfg_t *this)
{
return this->install_policy;
}
-/**
- * Implementation of child_cfg_t.get_ref.
- */
-static child_cfg_t* get_ref(private_child_cfg_t *this)
+METHOD(child_cfg_t, get_ref, child_cfg_t*,
+ private_child_cfg_t *this)
{
ref_get(&this->refcount);
return &this->public;
}
-/**
- * Implements child_cfg_t.destroy.
- */
-static void destroy(private_child_cfg_t *this)
+METHOD(child_cfg_t, destroy, void,
+ private_child_cfg_t *this)
{
if (ref_put(&this->refcount))
{
@@ -527,71 +501,67 @@ static void destroy(private_child_cfg_t *this)
*/
child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime,
char *updown, bool hostaccess,
- ipsec_mode_t mode, action_t dpd_action,
- action_t close_action, bool ipcomp,
- u_int32_t inactivity, u_int32_t reqid,
- mark_t *mark_in, mark_t *mark_out)
+ ipsec_mode_t mode, action_t start_action,
+ action_t dpd_action, action_t close_action,
+ bool ipcomp, u_int32_t inactivity, u_int32_t reqid,
+ mark_t *mark_in, mark_t *mark_out, u_int32_t tfc)
{
- private_child_cfg_t *this = malloc_thing(private_child_cfg_t);
-
- this->public.get_name = (char* (*) (child_cfg_t*))get_name;
- this->public.add_traffic_selector = (void (*)(child_cfg_t*,bool,traffic_selector_t*))add_traffic_selector;
- this->public.get_traffic_selectors = (linked_list_t*(*)(child_cfg_t*,bool,linked_list_t*,host_t*))get_traffic_selectors;
- this->public.add_proposal = (void (*) (child_cfg_t*,proposal_t*))add_proposal;
- this->public.get_proposals = (linked_list_t* (*) (child_cfg_t*,bool))get_proposals;
- this->public.select_proposal = (proposal_t* (*) (child_cfg_t*,linked_list_t*,bool,bool))select_proposal;
- this->public.get_updown = (char* (*) (child_cfg_t*))get_updown;
- this->public.get_hostaccess = (bool (*) (child_cfg_t*))get_hostaccess;
- this->public.get_mode = (ipsec_mode_t (*) (child_cfg_t *))get_mode;
- this->public.get_dpd_action = (action_t (*) (child_cfg_t *))get_dpd_action;
- this->public.get_close_action = (action_t (*) (child_cfg_t *))get_close_action;
- this->public.get_lifetime = (lifetime_cfg_t* (*) (child_cfg_t *))get_lifetime;
- this->public.get_dh_group = (diffie_hellman_group_t(*)(child_cfg_t*)) get_dh_group;
- this->public.set_mipv6_options = (void (*) (child_cfg_t*,bool,bool))set_mipv6_options;
- this->public.use_ipcomp = (bool (*) (child_cfg_t *))use_ipcomp;
- this->public.get_inactivity = (u_int32_t (*) (child_cfg_t *))get_inactivity;
- this->public.get_reqid = (u_int32_t (*) (child_cfg_t *))get_reqid;
- this->public.get_mark = (mark_t (*) (child_cfg_t *,bool))get_mark;
- this->public.use_proxy_mode = (bool (*) (child_cfg_t *))use_proxy_mode;
- this->public.install_policy = (bool (*) (child_cfg_t *))install_policy;
- this->public.get_ref = (child_cfg_t* (*) (child_cfg_t*))get_ref;
- this->public.destroy = (void (*) (child_cfg_t*))destroy;
-
- this->name = strdup(name);
- this->updown = updown ? strdup(updown) : NULL;
- this->hostaccess = hostaccess;
- this->mode = mode;
- this->dpd_action = dpd_action;
- this->close_action = close_action;
- this->use_ipcomp = ipcomp;
- this->inactivity = inactivity;
- this->reqid = reqid;
+ private_child_cfg_t *this;
+
+ INIT(this,
+ .public = {
+ .get_name = _get_name,
+ .add_traffic_selector = _add_traffic_selector,
+ .get_traffic_selectors = _get_traffic_selectors,
+ .add_proposal = _add_proposal,
+ .get_proposals = _get_proposals,
+ .select_proposal = _select_proposal,
+ .get_updown = _get_updown,
+ .get_hostaccess = _get_hostaccess,
+ .get_mode = _get_mode,
+ .get_start_action = _get_start_action,
+ .get_dpd_action = _get_dpd_action,
+ .get_close_action = _get_close_action,
+ .get_lifetime = _get_lifetime,
+ .get_dh_group = _get_dh_group,
+ .set_mipv6_options = _set_mipv6_options,
+ .use_ipcomp = _use_ipcomp,
+ .get_inactivity = _get_inactivity,
+ .get_reqid = _get_reqid,
+ .get_mark = _get_mark,
+ .get_tfc = _get_tfc,
+ .use_proxy_mode = _use_proxy_mode,
+ .install_policy = _install_policy,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .name = strdup(name),
+ .updown = strdupnull(updown),
+ .hostaccess = hostaccess,
+ .mode = mode,
+ .start_action = start_action,
+ .dpd_action = dpd_action,
+ .close_action = close_action,
+ .use_ipcomp = ipcomp,
+ .inactivity = inactivity,
+ .reqid = reqid,
+ .proxy_mode = FALSE,
+ .install_policy = TRUE,
+ .refcount = 1,
+ .proposals = linked_list_create(),
+ .my_ts = linked_list_create(),
+ .other_ts = linked_list_create(),
+ .tfc = tfc,
+ );
if (mark_in)
{
this->mark_in = *mark_in;
}
- else
- {
- this->mark_in.value = 0;
- this->mark_in.mask = 0;
- }
if (mark_out)
{
this->mark_out = *mark_out;
}
- else
- {
- this->mark_out.value = 0;
- this->mark_out.mask = 0;
- }
-
- this->proxy_mode = FALSE;
- this->install_policy = TRUE;
- this->refcount = 1;
- this->proposals = linked_list_create();
- this->my_ts = linked_list_create();
- this->other_ts = linked_list_create();
memcpy(&this->lifetime, lifetime, sizeof(lifetime_cfg_t));
return &this->public;
diff --git a/src/libcharon/config/child_cfg.h b/src/libcharon/config/child_cfg.h
index 1e6fe3fe9..175ced76c 100644
--- a/src/libcharon/config/child_cfg.h
+++ b/src/libcharon/config/child_cfg.h
@@ -32,14 +32,15 @@ typedef struct child_cfg_t child_cfg_t;
#include <kernel/kernel_ipsec.h>
/**
- * Action to take when DPD detected/connection gets closed by peer.
+ * Action to take when connection is loaded, DPD is detected or
+ * connection gets closed by peer.
*/
enum action_t {
/** No action */
ACTION_NONE,
- /** Route config to reestablish on demand */
+ /** Route config to establish or reestablish on demand */
ACTION_ROUTE,
- /** Restart config immediately */
+ /** Start or restart config immediately */
ACTION_RESTART,
};
@@ -169,6 +170,13 @@ struct child_cfg_t {
ipsec_mode_t (*get_mode) (child_cfg_t *this);
/**
+ * Action to take to start CHILD_SA.
+ *
+ * @return start action
+ */
+ action_t (*get_start_action) (child_cfg_t *this);
+
+ /**
* Action to take on DPD.
*
* @return DPD action
@@ -220,6 +228,13 @@ struct child_cfg_t {
mark_t (*get_mark)(child_cfg_t *this, bool inbound);
/**
+ * Get the TFC padding value to use for CHILD_SA.
+ *
+ * @return TFC padding, 0 to disable, -1 for MTU
+ */
+ u_int32_t (*get_tfc)(child_cfg_t *this);
+
+ /**
* Sets two options needed for Mobile IPv6 interoperability
*
* @param proxy_mode use IPsec transport proxy mode (default FALSE)
@@ -276,6 +291,7 @@ struct child_cfg_t {
* @param updown updown script to execute on up/down event
* @param hostaccess TRUE to allow access to the local host
* @param mode mode to propose for CHILD_SA, transport, tunnel or BEET
+ * @param start_action start action
* @param dpd_action DPD action
* @param close_action close action
* @param ipcomp use IPComp, if peer supports it
@@ -283,13 +299,14 @@ struct child_cfg_t {
* @param reqid specific reqid to use for CHILD_SA, 0 for auto assign
* @param mark_in optional inbound mark (can be NULL)
* @param mark_out optional outbound mark (can be NULL)
+ * @param tfc TFC padding size, 0 to disable, -1 to pad to PMTU
* @return child_cfg_t object
*/
child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime,
char *updown, bool hostaccess,
- ipsec_mode_t mode, action_t dpd_action,
- action_t close_action, bool ipcomp,
- u_int32_t inactivity, u_int32_t reqid,
- mark_t *mark_in, mark_t *mark_out);
+ ipsec_mode_t mode, action_t start_action,
+ action_t dpd_action, action_t close_action,
+ bool ipcomp, u_int32_t inactivity, u_int32_t reqid,
+ mark_t *mark_in, mark_t *mark_out, u_int32_t tfc);
#endif /** CHILD_CFG_H_ @}*/
diff --git a/src/libcharon/config/peer_cfg.c b/src/libcharon/config/peer_cfg.c
index 9df14c9ae..6f0c87279 100644
--- a/src/libcharon/config/peer_cfg.c
+++ b/src/libcharon/config/peer_cfg.c
@@ -682,7 +682,7 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
this->use_mobike = mobike;
this->dpd = dpd;
this->virtual_ip = virtual_ip;
- this->pool = pool ? strdup(pool) : NULL;
+ this->pool = strdupnull(pool);
this->local_auth = linked_list_create();
this->remote_auth = linked_list_create();
this->refcount = 1;
diff --git a/src/libcharon/config/proposal.c b/src/libcharon/config/proposal.c
index 5b8294599..86a59bc1b 100644
--- a/src/libcharon/config/proposal.c
+++ b/src/libcharon/config/proposal.c
@@ -560,6 +560,7 @@ static status_t add_string_algo(private_proposal_t *this, chunk_t alg)
if (token == NULL)
{
+ DBG1(DBG_CFG, "algorithm '%.*s' not recognized", alg.len, alg.ptr);
return FAILED;
}
@@ -740,9 +741,10 @@ static void proposal_add_supported_ike(private_proposal_t *this)
integrity_algorithm_t integrity;
pseudo_random_function_t prf;
diffie_hellman_group_t group;
+ const char *plugin_name;
enumerator = lib->crypto->create_crypter_enumerator(lib->crypto);
- while (enumerator->enumerate(enumerator, &encryption))
+ while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
{
switch (encryption)
{
@@ -777,7 +779,7 @@ static void proposal_add_supported_ike(private_proposal_t *this)
enumerator->destroy(enumerator);
enumerator = lib->crypto->create_signer_enumerator(lib->crypto);
- while (enumerator->enumerate(enumerator, &integrity))
+ while (enumerator->enumerate(enumerator, &integrity, &plugin_name))
{
switch (integrity)
{
@@ -796,7 +798,7 @@ static void proposal_add_supported_ike(private_proposal_t *this)
enumerator->destroy(enumerator);
enumerator = lib->crypto->create_prf_enumerator(lib->crypto);
- while (enumerator->enumerate(enumerator, &prf))
+ while (enumerator->enumerate(enumerator, &prf, &plugin_name))
{
switch (prf)
{
@@ -815,7 +817,7 @@ static void proposal_add_supported_ike(private_proposal_t *this)
enumerator->destroy(enumerator);
enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
- while (enumerator->enumerate(enumerator, &group))
+ while (enumerator->enumerate(enumerator, &group, &plugin_name))
{
switch (group)
{
diff --git a/src/libcharon/daemon.c b/src/libcharon/daemon.c
index 4b8e1fadd..4f2831e42 100644
--- a/src/libcharon/daemon.c
+++ b/src/libcharon/daemon.c
@@ -19,14 +19,14 @@
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
-#include <syslog.h>
#include <time.h>
-#include <errno.h>
#ifdef CAPABILITIES
-#ifdef HAVE_SYS_CAPABILITY_H
-#include <sys/capability.h>
-#endif /* HAVE_SYS_CAPABILITY_H */
+# 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"
@@ -34,10 +34,7 @@
#include <library.h>
#include <config/proposal.h>
#include <kernel/kernel_handler.h>
-
-#ifndef LOG_AUTHPRIV /* not defined on OpenSolaris */
-#define LOG_AUTHPRIV LOG_AUTH
-#endif
+#include <processing/jobs/start_action_job.h>
typedef struct private_daemon_t private_daemon_t;
@@ -62,7 +59,7 @@ struct private_daemon_t {
cap_t caps;
#endif /* CAPABILITIES_LIBCAP */
#ifdef CAPABILITIES_NATIVE
- struct __user_cap_data_struct caps;
+ struct __user_cap_data_struct caps[2];
#endif /* CAPABILITIES_NATIVE */
};
@@ -147,9 +144,16 @@ METHOD(daemon_t, keep_cap, void,
cap_set_flag(this->caps, CAP_PERMITTED, 1, &cap, CAP_SET);
#endif /* CAPABILITIES_LIBCAP */
#ifdef CAPABILITIES_NATIVE
- this->caps.effective |= 1 << cap;
- this->caps.permitted |= 1 << cap;
- this->caps.inheritable |= 1 << cap;
+ 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 */
}
@@ -164,9 +168,15 @@ METHOD(daemon_t, drop_capabilities, bool,
#endif /* CAPABILITIES_LIBCAP */
#ifdef CAPABILITIES_NATIVE
struct __user_cap_header_struct header = {
- .version = _LINUX_CAPABILITY_VERSION,
+#if defined(_LINUX_CAPABILITY_VERSION_3)
+ .version = _LINUX_CAPABILITY_VERSION_3,
+#elif defined(_LINUX_CAPABILITY_VERSION_2)
+ .version = _LINUX_CAPABILITY_VERSION_2,
+#else
+ .version = _LINUX_CAPABILITY_VERSION_1,
+#endif
};
- if (capset(&header, &this->caps) != 0)
+ if (capset(&header, this->caps) != 0)
{
return FALSE;
}
@@ -202,155 +212,9 @@ static void print_plugins()
DBG1(DBG_DMN, "loaded plugins: %s", buf);
}
-/**
- * Initialize logging
- */
-static void initialize_loggers(private_daemon_t *this, bool use_stderr,
- level_t levels[])
-{
- sys_logger_t *sys_logger;
- file_logger_t *file_logger;
- enumerator_t *enumerator;
- char *facility, *filename;
- int loggers_defined = 0;
- debug_t group;
- level_t def;
- bool append, ike_name;
- FILE *file;
-
- /* setup sysloggers */
- enumerator = lib->settings->create_section_enumerator(lib->settings,
- "charon.syslog");
- while (enumerator->enumerate(enumerator, &facility))
- {
- loggers_defined++;
-
- ike_name = lib->settings->get_bool(lib->settings,
- "charon.syslog.%s.ike_name", FALSE, facility);
- if (streq(facility, "daemon"))
- {
- sys_logger = sys_logger_create(LOG_DAEMON, ike_name);
- }
- else if (streq(facility, "auth"))
- {
- sys_logger = sys_logger_create(LOG_AUTHPRIV, ike_name);
- }
- else
- {
- continue;
- }
- def = lib->settings->get_int(lib->settings,
- "charon.syslog.%s.default", 1, facility);
- for (group = 0; group < DBG_MAX; group++)
- {
- sys_logger->set_level(sys_logger, group,
- lib->settings->get_int(lib->settings,
- "charon.syslog.%s.%N", def,
- facility, debug_lower_names, group));
- }
- this->public.sys_loggers->insert_last(this->public.sys_loggers,
- sys_logger);
- this->public.bus->add_listener(this->public.bus, &sys_logger->listener);
- }
- enumerator->destroy(enumerator);
-
- /* and file loggers */
- enumerator = lib->settings->create_section_enumerator(lib->settings,
- "charon.filelog");
- while (enumerator->enumerate(enumerator, &filename))
- {
- loggers_defined++;
- if (streq(filename, "stderr"))
- {
- file = stderr;
- }
- else if (streq(filename, "stdout"))
- {
- file = stdout;
- }
- else
- {
- append = lib->settings->get_bool(lib->settings,
- "charon.filelog.%s.append", TRUE, filename);
- file = fopen(filename, append ? "a" : "w");
- if (file == NULL)
- {
- DBG1(DBG_DMN, "opening file %s for logging failed: %s",
- filename, strerror(errno));
- continue;
- }
- if (lib->settings->get_bool(lib->settings,
- "charon.filelog.%s.flush_line", FALSE, filename))
- {
- setlinebuf(file);
- }
- }
- file_logger = file_logger_create(file,
- lib->settings->get_str(lib->settings,
- "charon.filelog.%s.time_format", NULL, filename),
- lib->settings->get_bool(lib->settings,
- "charon.filelog.%s.ike_name", FALSE, filename));
- def = lib->settings->get_int(lib->settings,
- "charon.filelog.%s.default", 1, filename);
- for (group = 0; group < DBG_MAX; group++)
- {
- file_logger->set_level(file_logger, group,
- lib->settings->get_int(lib->settings,
- "charon.filelog.%s.%N", def,
- filename, debug_lower_names, group));
- }
- this->public.file_loggers->insert_last(this->public.file_loggers,
- file_logger);
- this->public.bus->add_listener(this->public.bus, &file_logger->listener);
-
- }
- enumerator->destroy(enumerator);
-
- /* set up legacy style default loggers provided via command-line */
- if (!loggers_defined)
- {
- /* set up default stdout file_logger */
- file_logger = file_logger_create(stdout, NULL, FALSE);
- this->public.bus->add_listener(this->public.bus, &file_logger->listener);
- this->public.file_loggers->insert_last(this->public.file_loggers,
- file_logger);
- /* set up default daemon sys_logger */
- sys_logger = sys_logger_create(LOG_DAEMON, FALSE);
- this->public.bus->add_listener(this->public.bus, &sys_logger->listener);
- this->public.sys_loggers->insert_last(this->public.sys_loggers,
- sys_logger);
- for (group = 0; group < DBG_MAX; group++)
- {
- sys_logger->set_level(sys_logger, group, levels[group]);
- if (use_stderr)
- {
- file_logger->set_level(file_logger, group, levels[group]);
- }
- }
-
- /* set up default auth sys_logger */
- sys_logger = sys_logger_create(LOG_AUTHPRIV, FALSE);
- this->public.bus->add_listener(this->public.bus, &sys_logger->listener);
- this->public.sys_loggers->insert_last(this->public.sys_loggers,
- sys_logger);
- sys_logger->set_level(sys_logger, DBG_ANY, LEVEL_AUDIT);
- }
-}
-
METHOD(daemon_t, initialize, bool,
- private_daemon_t *this, bool syslog, level_t levels[])
+ private_daemon_t *this)
{
- /* for uncritical pseudo random numbers */
- srandom(time(NULL) + getpid());
-
- /* setup bus and it's listeners first to enable log output */
- this->public.bus = bus_create();
- /* set up hook to log dbg message in library via charons message bus */
- dbg_old = dbg;
- dbg = dbg_bus;
-
- initialize_loggers(this, !syslog, levels);
-
DBG1(DBG_DMN, "Starting IKEv2 charon daemon (strongSwan "VERSION")");
if (lib->integrity)
@@ -362,16 +226,6 @@ METHOD(daemon_t, initialize, bool,
DBG1(DBG_DMN, "daemon 'charon': passed file integrity test");
}
- /* load secrets, ca certificates and crls */
- this->public.controller = controller_create();
- this->public.eap = eap_manager_create();
- this->public.sim = sim_manager_create();
- this->public.tnccs = tnccs_manager_create();
- this->public.backends = backend_manager_create();
- this->public.socket = socket_manager_create();
- this->public.traps = trap_manager_create();
- this->kernel_handler = kernel_handler_create();
-
/* load plugins, further infrastructure may need it */
if (!lib->plugins->load(lib->plugins, NULL,
lib->settings->get_str(lib->settings, "charon.load", PLUGINS)))
@@ -393,6 +247,9 @@ METHOD(daemon_t, initialize, bool,
return FALSE;
}
+ /* Queue start_action job */
+ lib->processor->queue_job(lib->processor, (job_t*)start_action_job_create());
+
#ifdef ME
this->public.connect_manager = connect_manager_create();
if (this->public.connect_manager == NULL)
@@ -418,10 +275,20 @@ private_daemon_t *daemon_create()
.drop_capabilities = _drop_capabilities,
.initialize = _initialize,
.start = _start,
+ .bus = bus_create(),
.file_loggers = linked_list_create(),
.sys_loggers = linked_list_create(),
},
);
+ charon = &this->public;
+ this->public.controller = controller_create();
+ this->public.eap = eap_manager_create();
+ this->public.sim = sim_manager_create();
+ this->public.tnccs = tnccs_manager_create();
+ this->public.backends = backend_manager_create();
+ this->public.socket = socket_manager_create();
+ this->public.traps = trap_manager_create();
+ this->kernel_handler = kernel_handler_create();
#ifdef CAPABILITIES
#ifdef CAPABILITIES_LIBCAP
@@ -442,7 +309,6 @@ private_daemon_t *daemon_create()
*/
void libcharon_deinit()
{
-
destroy((private_daemon_t*)charon);
charon = NULL;
}
@@ -455,7 +321,13 @@ bool libcharon_init()
private_daemon_t *this;
this = daemon_create();
- charon = &this->public;
+
+ /* for uncritical pseudo random numbers */
+ srandom(time(NULL) + getpid());
+
+ /* set up hook to log dbg message in library via charons message bus */
+ dbg_old = dbg;
+ dbg = dbg_bus;
lib->printf_hook->add_handler(lib->printf_hook, 'P',
proposal_printf_hook,
diff --git a/src/libcharon/daemon.h b/src/libcharon/daemon.h
index c0c834b43..04f1fc249 100644
--- a/src/libcharon/daemon.h
+++ b/src/libcharon/daemon.h
@@ -149,7 +149,9 @@ typedef struct daemon_t daemon_t;
#include <config/backend_manager.h>
#include <sa/authenticators/eap/eap_manager.h>
#include <sa/authenticators/eap/sim_manager.h>
-#include <tnccs/tnccs_manager.h>
+#include <tnc/imc/imc_manager.h>
+#include <tnc/imv/imv_manager.h>
+#include <tnc/tnccs/tnccs_manager.h>
#ifdef ME
#include <sa/connect_manager.h>
@@ -237,6 +239,16 @@ struct daemon_t {
sim_manager_t *sim;
/**
+ * TNC IMC manager controlling Integrity Measurement Collectors
+ */
+ imc_manager_t *imcs;
+
+ /**
+ * TNC IMV manager controlling Integrity Measurement Verifiers
+ */
+ imv_manager_t *imvs;
+
+ /**
* TNCCS manager to maintain registered TNCCS protocols
*/
tnccs_manager_t *tnccs;
@@ -286,7 +298,7 @@ struct daemon_t {
/**
* Initialize the daemon.
*/
- bool (*initialize)(daemon_t *this, bool syslog, level_t levels[]);
+ bool (*initialize)(daemon_t *this);
/**
* Starts the daemon, i.e. spawns the threads of the thread pool.
@@ -305,6 +317,9 @@ extern daemon_t *charon;
/**
* Initialize libcharon and create the "charon" instance of daemon_t.
*
+ * This function initializes the bus, listeners can be registered before
+ * calling initialize().
+ *
* @return FALSE if integrity check failed
*/
bool libcharon_init();
diff --git a/src/libcharon/encoding/generator.c b/src/libcharon/encoding/generator.c
index 224f76fce..ce3844361 100644
--- a/src/libcharon/encoding/generator.c
+++ b/src/libcharon/encoding/generator.c
@@ -41,6 +41,7 @@
#include <encoding/payloads/cp_payload.h>
#include <encoding/payloads/configuration_attribute.h>
#include <encoding/payloads/eap_payload.h>
+#include <encoding/payloads/unknown_payload.h>
/**
* Generating is done in a data buffer.
@@ -89,20 +90,10 @@ struct private_generator_t {
*/
void *data_struct;
- /*
- * Last payload length position offset in the buffer.
- */
- u_int32_t last_payload_length_position_offset;
-
/**
* Offset of the header length field in the buffer.
*/
- u_int32_t header_length_position_offset;
-
- /**
- * Last SPI size.
- */
- u_int8_t last_spi_size;
+ u_int32_t header_length_offset;
/**
* Attribute format of the last generated transform attribute.
@@ -193,33 +184,6 @@ static void write_bytes_to_buffer(private_generator_t *this, void *bytes,
}
/**
- * Writes a specific amount of byte into the buffer at a specific offset.
- */
-static void write_bytes_to_buffer_at_offset(private_generator_t *this,
- void *bytes, int number_of_bytes, u_int32_t offset)
-{
- int i;
- u_int8_t *read_position = (u_int8_t *)bytes;
- u_int8_t *write_position;
- u_int32_t free_space_after_offset = get_size(this) - offset;
-
- /* check first if enough space for new data is available */
- if (number_of_bytes > free_space_after_offset)
- {
- make_space_available(this,
- (number_of_bytes - free_space_after_offset) * 8);
- }
-
- write_position = this->buffer + offset;
- for (i = 0; i < number_of_bytes; i++)
- {
- *write_position = *read_position;
- read_position++;
- write_position++;
- }
-}
-
-/**
* Generates a U_INT-Field type and writes it to buffer.
*/
static void generate_u_int_type(private_generator_t *this,
@@ -234,10 +198,13 @@ static void generate_u_int_type(private_generator_t *this,
number_of_bits = 4;
break;
case TS_TYPE:
+ case RESERVED_BYTE:
+ case SPI_SIZE:
case U_INT_8:
number_of_bits = 8;
break;
case U_INT_16:
+ case PAYLOAD_LENGTH:
case CONFIGURATION_ATTRIBUTE_LENGTH:
number_of_bits = 16;
break;
@@ -301,6 +268,8 @@ static void generate_u_int_type(private_generator_t *this,
break;
}
case TS_TYPE:
+ case RESERVED_BYTE:
+ case SPI_SIZE:
case U_INT_8:
{
/* 8 bit values are written as they are */
@@ -338,6 +307,7 @@ static void generate_u_int_type(private_generator_t *this,
}
case U_INT_16:
+ case PAYLOAD_LENGTH:
case CONFIGURATION_ATTRIBUTE_LENGTH:
{
u_int16_t val = htons(*((u_int16_t*)(this->data_struct + offset)));
@@ -371,49 +341,6 @@ static void generate_u_int_type(private_generator_t *this,
}
/**
- * Generate a reserved bit or byte
- */
-static void generate_reserved_field(private_generator_t *this, int bits)
-{
- /* only one bit or 8 bit fields are supported */
- if (bits != 1 && bits != 8)
- {
- DBG1(DBG_ENC, "reserved field of %d bits cannot be generated", bits);
- return ;
- }
- make_space_available(this, bits);
-
- if (bits == 1)
- {
- u_int8_t reserved_bit = ~(1 << (7 - this->current_bit));
-
- *(this->out_position) = *(this->out_position) & reserved_bit;
- if (this->current_bit == 0)
- {
- /* memory must be zero */
- *(this->out_position) = 0x00;
- }
- this->current_bit++;
- if (this->current_bit >= 8)
- {
- this->current_bit = this->current_bit % 8;
- this->out_position++;
- }
- }
- else
- {
- if (this->current_bit > 0)
- {
- DBG1(DBG_ENC, "reserved field cannot be written cause "
- "alignement of current bit is %d", this->current_bit);
- return;
- }
- *(this->out_position) = 0x00;
- this->out_position++;
- }
-}
-
-/**
* Generate a FLAG filed
*/
static void generate_flag(private_generator_t *this, u_int32_t offset)
@@ -468,7 +395,7 @@ METHOD(generator_t, get_chunk, chunk_t,
{
chunk_t data;
- *lenpos = (u_int32_t*)(this->buffer + this->header_length_position_offset);
+ *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);
return data;
@@ -484,8 +411,6 @@ METHOD(generator_t, generate_payload, void,
this->data_struct = payload;
payload_type = payload->get_type(payload);
- /* spi size has to get reseted */
- this->last_spi_size = 0;
offset_start = this->out_position - this->buffer;
@@ -505,56 +430,25 @@ METHOD(generator_t, generate_payload, void,
case U_INT_8:
case U_INT_16:
case U_INT_32:
+ case PAYLOAD_LENGTH:
case IKE_SPI:
+ case RESERVED_BYTE:
+ case SPI_SIZE:
case TS_TYPE:
case ATTRIBUTE_TYPE:
case CONFIGURATION_ATTRIBUTE_LENGTH:
- {
generate_u_int_type(this, rules[i].type, rules[i].offset);
break;
- }
case RESERVED_BIT:
- {
- generate_reserved_field(this, 1);
- break;
- }
- case RESERVED_BYTE:
- {
- generate_reserved_field(this, 8);
- break;
- }
case FLAG:
- {
generate_flag(this, rules[i].offset);
break;
- }
- case PAYLOAD_LENGTH:
- {
- this->last_payload_length_position_offset = get_offset(this);
- generate_u_int_type(this, U_INT_16,rules[i].offset);
- break;
- }
case HEADER_LENGTH:
- {
- this->header_length_position_offset = get_offset(this);
- generate_u_int_type(this ,U_INT_32, rules[i].offset);
- break;
- }
- case SPI_SIZE:
- generate_u_int_type(this, U_INT_8, rules[i].offset);
- this->last_spi_size = *((u_int8_t *)(this->data_struct +
- rules[i].offset));
+ this->header_length_offset = get_offset(this);
+ generate_u_int_type(this, U_INT_32, rules[i].offset);
break;
case ADDRESS:
- {
- generate_from_chunk(this, rules[i].offset);
- break;
- }
case SPI:
- {
- generate_from_chunk(this, rules[i].offset);
- break;
- }
case KEY_EXCHANGE_DATA:
case NOTIFICATION_DATA:
case NONCE_DATA:
@@ -566,221 +460,52 @@ METHOD(generator_t, generate_payload, void,
case CONFIGURATION_ATTRIBUTE_VALUE:
case VID_DATA:
case EAP_DATA:
- {
- u_int32_t payload_length_position_offset;
- u_int16_t length_of_payload;
- u_int16_t header_length = 0;
- u_int16_t length_in_network_order;
-
- switch(rules[i].type)
- {
- case KEY_EXCHANGE_DATA:
- header_length = KE_PAYLOAD_HEADER_LENGTH;
- break;
- case NOTIFICATION_DATA:
- header_length = NOTIFY_PAYLOAD_HEADER_LENGTH +
- this->last_spi_size;
- break;
- case NONCE_DATA:
- header_length = NONCE_PAYLOAD_HEADER_LENGTH;
- break;
- case ID_DATA:
- header_length = ID_PAYLOAD_HEADER_LENGTH;
- break;
- case AUTH_DATA:
- header_length = AUTH_PAYLOAD_HEADER_LENGTH;
- break;
- case CERT_DATA:
- header_length = CERT_PAYLOAD_HEADER_LENGTH;
- break;
- case CERTREQ_DATA:
- header_length = CERTREQ_PAYLOAD_HEADER_LENGTH;
- break;
- case SPIS:
- header_length = DELETE_PAYLOAD_HEADER_LENGTH;
- break;
- case VID_DATA:
- header_length = VENDOR_ID_PAYLOAD_HEADER_LENGTH;
- break;
- case CONFIGURATION_ATTRIBUTE_VALUE:
- header_length = CONFIGURATION_ATTRIBUTE_HEADER_LENGTH;
- break;
- case EAP_DATA:
- header_length = EAP_PAYLOAD_HEADER_LENGTH;
- break;
- default:
- break;
- }
+ case ENCRYPTED_DATA:
+ case UNKNOWN_DATA:
generate_from_chunk(this, rules[i].offset);
-
- payload_length_position_offset =
- this->last_payload_length_position_offset;
-
- length_of_payload = header_length +
- ((chunk_t *)(this->data_struct + rules[i].offset))->len;
-
- length_in_network_order = htons(length_of_payload);
- write_bytes_to_buffer_at_offset(this, &length_in_network_order,
- sizeof(u_int16_t), payload_length_position_offset);
break;
- }
case PROPOSALS:
- {
- u_int32_t payload_length_position_offset =
- this->last_payload_length_position_offset;
- /* Length of SA_PAYLOAD is calculated */
- u_int16_t length_of_sa_payload = SA_PAYLOAD_HEADER_LENGTH;
- u_int16_t int16_val;
- linked_list_t *proposals = *((linked_list_t **)
- (this->data_struct + rules[i].offset));
- iterator_t *iterator;
- payload_t *current_proposal;
-
- iterator = proposals->create_iterator(proposals,TRUE);
- while (iterator->iterate(iterator, (void**)&current_proposal))
- {
- u_int32_t before_generate_position_offset;
- u_int32_t after_generate_position_offset;
-
- before_generate_position_offset = get_offset(this);
- generate_payload(this, current_proposal);
- after_generate_position_offset = get_offset(this);
- length_of_sa_payload += (after_generate_position_offset -
- before_generate_position_offset);
- }
- iterator->destroy(iterator);
-
- int16_val = htons(length_of_sa_payload);
- write_bytes_to_buffer_at_offset(this, &int16_val,
- sizeof(u_int16_t),payload_length_position_offset);
- break;
- }
case TRANSFORMS:
- {
- u_int32_t payload_length_position_offset =
- this->last_payload_length_position_offset;
- u_int16_t length_of_proposal =
- PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH + this->last_spi_size;
- u_int16_t int16_val;
- linked_list_t *transforms = *((linked_list_t **)
- (this->data_struct + rules[i].offset));
- iterator_t *iterator;
- payload_t *current_transform;
-
- iterator = transforms->create_iterator(transforms,TRUE);
- while (iterator->iterate(iterator, (void**)&current_transform))
- {
- u_int32_t before_generate_position_offset;
- u_int32_t after_generate_position_offset;
-
- before_generate_position_offset = get_offset(this);
- generate_payload(this, current_transform);
- after_generate_position_offset = get_offset(this);
-
- length_of_proposal += (after_generate_position_offset -
- before_generate_position_offset);
- }
- iterator->destroy(iterator);
-
- int16_val = htons(length_of_proposal);
- write_bytes_to_buffer_at_offset(this, &int16_val,
- sizeof(u_int16_t), payload_length_position_offset);
- break;
- }
case TRANSFORM_ATTRIBUTES:
- {
- u_int32_t transform_length_position_offset =
- this->last_payload_length_position_offset;
- u_int16_t length_of_transform =
- TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
- u_int16_t int16_val;
- linked_list_t *transform_attributes =*((linked_list_t **)
- (this->data_struct + rules[i].offset));
- iterator_t *iterator;
- payload_t *current_attribute;
-
- iterator = transform_attributes->create_iterator(
- transform_attributes, TRUE);
- while (iterator->iterate(iterator, (void**)&current_attribute))
- {
- u_int32_t before_generate_position_offset;
- u_int32_t after_generate_position_offset;
-
- before_generate_position_offset = get_offset(this);
- generate_payload(this, current_attribute);
- after_generate_position_offset = get_offset(this);
-
- length_of_transform += (after_generate_position_offset -
- before_generate_position_offset);
- }
-
- iterator->destroy(iterator);
-
- int16_val = htons(length_of_transform);
- write_bytes_to_buffer_at_offset(this, &int16_val,
- sizeof(u_int16_t),transform_length_position_offset);
- break;
- }
case CONFIGURATION_ATTRIBUTES:
+ case TRAFFIC_SELECTORS:
{
- u_int32_t configurations_length_position_offset =
- this->last_payload_length_position_offset;
- u_int16_t length_of_configurations = CP_PAYLOAD_HEADER_LENGTH;
- u_int16_t int16_val;
- linked_list_t *configuration_attributes = *((linked_list_t **)
- (this->data_struct + rules[i].offset));
- iterator_t *iterator;
- payload_t *current_attribute;
+ linked_list_t *proposals;
+ enumerator_t *enumerator;
+ payload_t *proposal;
- iterator = configuration_attributes->create_iterator(
- configuration_attributes,TRUE);
- while (iterator->iterate(iterator, (void**)&current_attribute))
+ proposals = *((linked_list_t **)
+ (this->data_struct + rules[i].offset));
+ enumerator = proposals->create_enumerator(proposals);
+ while (enumerator->enumerate(enumerator, &proposal))
{
- u_int32_t before_generate_position_offset;
- u_int32_t after_generate_position_offset;
-
- before_generate_position_offset = get_offset(this);
- generate_payload(this, current_attribute);
- after_generate_position_offset = get_offset(this);
-
- length_of_configurations += after_generate_position_offset -
- before_generate_position_offset;
+ generate_payload(this, proposal);
}
-
- iterator->destroy(iterator);
-
- int16_val = htons(length_of_configurations);
- write_bytes_to_buffer_at_offset(this, &int16_val,
- sizeof(u_int16_t),configurations_length_position_offset);
+ enumerator->destroy(enumerator);
break;
}
case ATTRIBUTE_FORMAT:
- {
generate_flag(this, rules[i].offset);
/* Attribute format is a flag which is stored in context*/
this->attribute_format =
*((bool *)(this->data_struct + rules[i].offset));
break;
- }
-
case ATTRIBUTE_LENGTH_OR_VALUE:
- {
- if (this->attribute_format == FALSE)
+ if (this->attribute_format)
{
generate_u_int_type(this, U_INT_16, rules[i].offset);
- /* this field hold the length of the attribute */
- this->attribute_length =
- *((u_int16_t *)(this->data_struct + rules[i].offset));
}
else
{
generate_u_int_type(this, U_INT_16, rules[i].offset);
+ /* this field hold the length of the attribute */
+ this->attribute_length =
+ *((u_int16_t *)(this->data_struct + rules[i].offset));
}
break;
- }
case ATTRIBUTE_VALUE:
{
- if (this->attribute_format == FALSE)
+ if (!this->attribute_format)
{
DBG2(DBG_ENC, "attribute value has not fixed size");
/* the attribute value is generated */
@@ -788,44 +513,6 @@ METHOD(generator_t, generate_payload, void,
}
break;
}
- case TRAFFIC_SELECTORS:
- {
- u_int32_t payload_length_position_offset =
- this->last_payload_length_position_offset;
- u_int16_t length_of_ts_payload = TS_PAYLOAD_HEADER_LENGTH;
- u_int16_t int16_val;
- linked_list_t *traffic_selectors = *((linked_list_t **)
- (this->data_struct + rules[i].offset));
- iterator_t *iterator;
- payload_t *current_tss;
-
- iterator = traffic_selectors->create_iterator(
- traffic_selectors,TRUE);
- while (iterator->iterate(iterator, (void **)&current_tss))
- {
- u_int32_t before_generate_position_offset;
- u_int32_t after_generate_position_offset;
-
- before_generate_position_offset = get_offset(this);
- generate_payload(this, current_tss);
- after_generate_position_offset = get_offset(this);
-
- length_of_ts_payload += (after_generate_position_offset -
- before_generate_position_offset);
- }
- iterator->destroy(iterator);
-
- int16_val = htons(length_of_ts_payload);
- write_bytes_to_buffer_at_offset(this, &int16_val,
- sizeof(u_int16_t),payload_length_position_offset);
- break;
- }
-
- case ENCRYPTED_DATA:
- {
- generate_from_chunk(this, rules[i].offset);
- break;
- }
default:
DBG1(DBG_ENC, "field type %N is not supported",
encoding_type_names, rules[i].type);
diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c
index d41ad4697..dbef340ab 100644
--- a/src/libcharon/encoding/message.c
+++ b/src/libcharon/encoding/message.c
@@ -131,6 +131,7 @@ static payload_rule_t ike_sa_init_r_rules[] = {
{SECURITY_ASSOCIATION, 1, 1, FALSE, FALSE},
{KEY_EXCHANGE, 1, 1, FALSE, FALSE},
{NONCE, 1, 1, FALSE, FALSE},
+ {CERTIFICATE_REQUEST, 1, 1, FALSE, FALSE},
{VENDOR_ID, 0, 10, FALSE, FALSE},
};
@@ -490,6 +491,21 @@ struct private_message_t {
bool is_request;
/**
+ * Higher version supported?
+ */
+ bool version_flag;
+
+ /**
+ * Reserved bits in IKE header
+ */
+ bool reserved[5];
+
+ /**
+ * Sorting of message disabled?
+ */
+ bool sort_disabled;
+
+ /**
* Message ID of this message.
*/
u_int32_t message_id;
@@ -647,18 +663,35 @@ METHOD(message_t, get_request, bool,
return this->is_request;
}
-/**
- * Is this message in an encoded form?
- */
-static bool is_encoded(private_message_t *this)
+METHOD(message_t, set_version_flag, void,
+ private_message_t *this)
{
- chunk_t data = this->packet->get_data(this->packet);
+ this->version_flag = TRUE;
+}
- if (data.ptr == NULL)
+METHOD(message_t, get_reserved_header_bit, bool,
+ private_message_t *this, u_int nr)
+{
+ if (nr < countof(this->reserved))
{
- return FALSE;
+ return this->reserved[nr];
}
- return TRUE;
+ return FALSE;
+}
+
+METHOD(message_t, set_reserved_header_bit, void,
+ private_message_t *this, u_int nr)
+{
+ if (nr < countof(this->reserved))
+ {
+ this->reserved[nr] = TRUE;
+ }
+}
+
+METHOD(message_t, is_encoded, bool,
+ private_message_t *this)
+{
+ return this->packet->get_data(this->packet).ptr != NULL;
}
METHOD(message_t, add_payload, void,
@@ -732,6 +765,12 @@ METHOD(message_t, create_payload_enumerator, enumerator_t*,
return this->payloads->create_enumerator(this->payloads);
}
+METHOD(message_t, remove_payload_at, void,
+ private_message_t *this, enumerator_t *enumerator)
+{
+ this->payloads->remove_at(this->payloads, enumerator);
+}
+
METHOD(message_t, get_payload, payload_t*,
private_message_t *this, payload_type_t type)
{
@@ -1001,6 +1040,12 @@ static encryption_payload_t* wrap_payloads(private_message_t *this)
return encryption;
}
+METHOD(message_t, disable_sort, void,
+ private_message_t *this)
+{
+ this->sort_disabled = TRUE;
+}
+
METHOD(message_t, generate, status_t,
private_message_t *this, aead_t *aead, packet_t **packet)
{
@@ -1012,12 +1057,8 @@ METHOD(message_t, generate, status_t,
chunk_t chunk;
char str[256];
u_int32_t *lenpos;
-
- if (is_encoded(this))
- { /* already generated, return a new packet clone */
- *packet = this->packet->clone(this->packet);
- return SUCCESS;
- }
+ bool *reserved;
+ int i;
if (this->exchange_type == EXCHANGE_TYPE_UNDEFINED)
{
@@ -1039,7 +1080,10 @@ METHOD(message_t, generate, status_t,
return NOT_SUPPORTED;
}
- order_payloads(this);
+ if (!this->sort_disabled)
+ {
+ order_payloads(this);
+ }
DBG1(DBG_ENC, "generating %s", get_string(this, str, sizeof(str)));
@@ -1053,9 +1097,12 @@ METHOD(message_t, generate, status_t,
}
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->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,
this->ike_sa_id->is_initiator(this->ike_sa_id));
ike_header->set_initiator_spi(ike_header,
@@ -1063,6 +1110,16 @@ METHOD(message_t, generate, status_t,
ike_header->set_responder_spi(ike_header,
this->ike_sa_id->get_responder_spi(this->ike_sa_id));
+ for (i = 0; i < countof(this->reserved); i++)
+ {
+ reserved = payload_get_field(&ike_header->payload_interface,
+ RESERVED_BIT, i);
+ if (reserved)
+ {
+ *reserved = this->reserved[i];
+ }
+ }
+
generator = generator_create();
/* generate all payloads with proper next type */
@@ -1131,6 +1188,8 @@ METHOD(message_t, parse_header, status_t,
{
ike_header_t *ike_header;
status_t status;
+ bool *reserved;
+ int i;
DBG2(DBG_ENC, "parsing header of message");
@@ -1165,7 +1224,15 @@ METHOD(message_t, parse_header, status_t,
this->minor_version = ike_header->get_min_version(ike_header);
this->first_payload = ike_header->payload_interface.get_next_type(
&ike_header->payload_interface);
-
+ for (i = 0; i < countof(this->reserved); i++)
+ {
+ reserved = payload_get_field(&ike_header->payload_interface,
+ RESERVED_BIT, i);
+ if (reserved)
+ {
+ this->reserved[i] = *reserved;
+ }
+ }
DBG2(DBG_ENC, "parsed a %N %s", exchange_type_names, this->exchange_type,
this->is_request ? "request" : "response");
@@ -1182,6 +1249,31 @@ METHOD(message_t, parse_header, status_t,
}
/**
+ * Check if a payload is for a mediation extension connectivity check
+ */
+static bool is_connectivity_check(private_message_t *this, payload_t *payload)
+{
+#ifdef ME
+ if (this->exchange_type == INFORMATIONAL &&
+ payload->get_type(payload) == NOTIFY)
+ {
+ notify_payload_t *notify = (notify_payload_t*)payload;
+
+ switch (notify->get_notify_type(notify))
+ {
+ case ME_CONNECTID:
+ case ME_ENDPOINT:
+ case ME_CONNECTAUTH:
+ return TRUE;
+ default:
+ break;
+ }
+ }
+#endif /* !ME */
+ return FALSE;
+}
+
+/**
* Decrypt payload from the encryption payload
*/
static status_t decrypt_payloads(private_message_t *this, aead_t *aead)
@@ -1252,14 +1344,15 @@ static status_t decrypt_payloads(private_message_t *this, aead_t *aead)
}
encryption->destroy(encryption);
}
- if (type != UNKNOWN_PAYLOAD && !was_encrypted)
+ if (payload_is_known(type) && !was_encrypted &&
+ !is_connectivity_check(this, payload))
{
rule = get_payload_rule(this, type);
if (!rule || rule->encrypted)
{
DBG1(DBG_ENC, "payload type %N was not encrypted",
payload_type_names, type);
- status = VERIFY_ERROR;
+ status = FAILED;
break;
}
}
@@ -1274,6 +1367,7 @@ static status_t decrypt_payloads(private_message_t *this, aead_t *aead)
*/
static status_t verify(private_message_t *this)
{
+ bool complete = FALSE;
int i;
DBG2(DBG_ENC, "verifying message structure");
@@ -1291,22 +1385,9 @@ static status_t verify(private_message_t *this)
while (enumerator->enumerate(enumerator, &payload))
{
payload_type_t type;
- unknown_payload_t *unknown;
type = payload->get_type(payload);
- if (type == UNKNOWN_PAYLOAD)
- {
- /* unknown payloads are ignored if they are not critical */
- unknown = (unknown_payload_t*)payload;
- if (unknown->is_critical(unknown))
- {
- DBG1(DBG_ENC, "%N is not supported, but its critical!",
- payload_type_names, type);
- enumerator->destroy(enumerator);
- return NOT_SUPPORTED;
- }
- }
- else if (type == rule->type)
+ if (type == rule->type)
{
found++;
DBG2(DBG_ENC, "found payload of type %N",
@@ -1323,15 +1404,15 @@ static status_t verify(private_message_t *this)
}
enumerator->destroy(enumerator);
- if (found < rule->min_occurence)
+ if (!complete && found < rule->min_occurence)
{
DBG1(DBG_ENC, "payload of type %N not occured %d times (%d)",
payload_type_names, rule->type, rule->min_occurence, found);
return VERIFY_ERROR;
}
- if (rule->sufficient)
+ if (found && rule->sufficient)
{
- return SUCCESS;
+ complete = TRUE;
}
}
return SUCCESS;
@@ -1360,7 +1441,7 @@ METHOD(message_t, parse_body, status_t,
{
DBG1(DBG_ENC, "payload type %N could not be parsed",
payload_type_names, type);
- return PARSE_ERROR;
+ return this->exchange_type == IKE_SA_INIT ? PARSE_ERROR : FAILED;
}
DBG2(DBG_ENC, "verifying payload of type %N", payload_type_names, type);
@@ -1370,7 +1451,7 @@ METHOD(message_t, parse_body, status_t,
DBG1(DBG_ENC, "%N payload verification failed",
payload_type_names, type);
payload->destroy(payload);
- return VERIFY_ERROR;
+ return this->exchange_type == IKE_SA_INIT ? VERIFY_ERROR : FAILED;
}
DBG2(DBG_ENC, "%N payload verified. Adding to payload list",
@@ -1388,14 +1469,11 @@ METHOD(message_t, parse_body, status_t,
type = payload->get_next_type(payload);
}
- if (type == ENCRYPTED)
+ status = decrypt_payloads(this, aead);
+ if (status != SUCCESS)
{
- status = decrypt_payloads(this, aead);
- if (status != SUCCESS)
- {
- DBG1(DBG_ENC, "could not decrypt payloads");
- return status;
- }
+ DBG1(DBG_ENC, "could not decrypt payloads");
+ return status;
}
status = verify(this);
@@ -1443,14 +1521,20 @@ message_t *message_create_from_packet(packet_t *packet)
.get_first_payload_type = _get_first_payload_type,
.set_request = _set_request,
.get_request = _get_request,
+ .set_version_flag = _set_version_flag,
+ .get_reserved_header_bit = _get_reserved_header_bit,
+ .set_reserved_header_bit = _set_reserved_header_bit,
.add_payload = _add_payload,
.add_notify = _add_notify,
+ .disable_sort = _disable_sort,
.generate = _generate,
+ .is_encoded = _is_encoded,
.set_source = _set_source,
.get_source = _get_source,
.set_destination = _set_destination,
.get_destination = _get_destination,
.create_payload_enumerator = _create_payload_enumerator,
+ .remove_payload_at = _remove_payload_at,
.get_payload = _get_payload,
.get_notify = _get_notify,
.parse_header = _parse_header,
@@ -1459,6 +1543,8 @@ 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,
diff --git a/src/libcharon/encoding/message.h b/src/libcharon/encoding/message.h
index 8c1cbcd09..51197308c 100644
--- a/src/libcharon/encoding/message.h
+++ b/src/libcharon/encoding/message.h
@@ -154,6 +154,26 @@ struct message_t {
bool (*get_request) (message_t *this);
/**
+ * Set the version flag in the IKE header.
+ */
+ void (*set_version_flag)(message_t *this);
+
+ /**
+ * Get a reserved bit in the IKE header.
+ *
+ * @param nr reserved bit to get in IKE header, 0-4
+ * @return TRUE if bit is set
+ */
+ bool (*get_reserved_header_bit)(message_t *this, u_int nr);
+
+ /**
+ * Set a reserved bit in the IKE header.
+ *
+ * @param nr reserved bit to set in IKE header, 0-4
+ */
+ void (*set_reserved_header_bit)(message_t *this, u_int nr);
+
+ /**
* Append a payload to the message.
*
* If the payload must be encrypted is not specified here. Encryption
@@ -181,6 +201,11 @@ struct message_t {
chunk_t data);
/**
+ * Disable automatic payload sorting for this message.
+ */
+ void (*disable_sort)(message_t *this);
+
+ /**
* Parses header of message.
*
* Begins parisng of a message created via message_create_from_packet().
@@ -206,8 +231,6 @@ struct message_t {
* @param aead aead transform to verify/decrypt message
* @return
* - SUCCESS if parsing successful
- * - NOT_SUPPORTED if ciritcal unknown payloads found
- * - NOT_SUPPORTED if message type is not supported!
* - PARSE_ERROR if message parsing failed
* - VERIFY_ERROR if message verification failed (bad syntax)
* - FAILED if integrity check failed
@@ -235,6 +258,13 @@ struct message_t {
status_t (*generate) (message_t *this, aead_t *aead, packet_t **packet);
/**
+ * Check if the message has already been encoded using generate().
+ *
+ * @return TRUE if message has been encoded
+ */
+ bool (*is_encoded)(message_t *this);
+
+ /**
* Gets the source host informations.
*
* @warning Returned host_t object is not getting cloned,
@@ -282,6 +312,13 @@ struct message_t {
enumerator_t * (*create_payload_enumerator) (message_t *this);
/**
+ * Remove the payload at the current enumerator position.
+ *
+ * @param enumerator enumerator created by create_payload_enumerator()
+ */
+ void (*remove_payload_at)(message_t *this, enumerator_t *enumerator);
+
+ /**
* Find a payload of a specific type.
*
* Returns the first occurance.
diff --git a/src/libcharon/encoding/parser.c b/src/libcharon/encoding/parser.c
index 9aa34b1bc..32cefb9e7 100644
--- a/src/libcharon/encoding/parser.c
+++ b/src/libcharon/encoding/parser.c
@@ -387,12 +387,6 @@ static status_t parse_payload(private_parser_t *this,
DBG3(DBG_ENC, "parsing payload from %b",
this->byte_pos, this->input_roof - this->byte_pos);
- if (pld->get_type(pld) == UNKNOWN_PAYLOAD)
- {
- DBG1(DBG_ENC, " payload type %d is unknown, handling as %N",
- payload_type, payload_type_names, UNKNOWN_PAYLOAD);
- }
-
/* base pointer for output, avoids casting in every rule */
output = pld;
@@ -415,6 +409,7 @@ static status_t parse_payload(private_parser_t *this,
break;
}
case U_INT_8:
+ case RESERVED_BYTE:
{
if (!parse_uint8(this, rule_number, output + rule->offset))
{
@@ -433,6 +428,7 @@ static status_t parse_payload(private_parser_t *this,
break;
}
case U_INT_32:
+ case HEADER_LENGTH:
{
if (!parse_uint32(this, rule_number, output + rule->offset))
{
@@ -451,23 +447,6 @@ static status_t parse_payload(private_parser_t *this,
break;
}
case RESERVED_BIT:
- {
- if (!parse_bit(this, rule_number, NULL))
- {
- pld->destroy(pld);
- return PARSE_ERROR;
- }
- break;
- }
- case RESERVED_BYTE:
- {
- if (!parse_uint8(this, rule_number, NULL))
- {
- pld->destroy(pld);
- return PARSE_ERROR;
- }
- break;
- }
case FLAG:
{
if (!parse_bit(this, rule_number, output + rule->offset))
@@ -493,15 +472,6 @@ static status_t parse_payload(private_parser_t *this,
}
break;
}
- case HEADER_LENGTH:
- {
- if (!parse_uint32(this, rule_number, output + rule->offset))
- {
- pld->destroy(pld);
- return PARSE_ERROR;
- }
- break;
- }
case SPI_SIZE:
{
if (!parse_uint8(this, rule_number, output + rule->offset))
diff --git a/src/libcharon/encoding/payloads/auth_payload.c b/src/libcharon/encoding/payloads/auth_payload.c
index d31208abb..cb44a997c 100644
--- a/src/libcharon/encoding/payloads/auth_payload.c
+++ b/src/libcharon/encoding/payloads/auth_payload.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005-2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -18,7 +19,6 @@
#include <encoding/payloads/encodings.h>
-
typedef struct private_auth_payload_t private_auth_payload_t;
/**
@@ -43,6 +43,16 @@ struct private_auth_payload_t {
bool critical;
/**
+ * Reserved bits
+ */
+ bool reserved_bit[7];
+
+ /**
+ * Reserved bytes
+ */
+ u_int8_t reserved_byte[3];
+
+ /**
* Length of this payload.
*/
u_int16_t payload_length;
@@ -66,27 +76,27 @@ struct private_auth_payload_t {
*/
encoding_rule_t auth_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
- { U_INT_8, offsetof(private_auth_payload_t, next_payload) },
+ { U_INT_8, offsetof(private_auth_payload_t, next_payload) },
/* the critical bit */
- { FLAG, offsetof(private_auth_payload_t, critical) },
- /* 7 Bit reserved bits, nowhere stored */
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
+ { FLAG, offsetof(private_auth_payload_t, critical) },
+ /* 7 Bit reserved bits */
+ { RESERVED_BIT, offsetof(private_auth_payload_t, reserved_bit[0]) },
+ { RESERVED_BIT, offsetof(private_auth_payload_t, reserved_bit[1]) },
+ { RESERVED_BIT, offsetof(private_auth_payload_t, reserved_bit[2]) },
+ { RESERVED_BIT, offsetof(private_auth_payload_t, reserved_bit[3]) },
+ { RESERVED_BIT, offsetof(private_auth_payload_t, reserved_bit[4]) },
+ { RESERVED_BIT, offsetof(private_auth_payload_t, reserved_bit[5]) },
+ { RESERVED_BIT, offsetof(private_auth_payload_t, reserved_bit[6]) },
/* Length of the whole payload*/
- { PAYLOAD_LENGTH, offsetof(private_auth_payload_t, payload_length)},
+ { PAYLOAD_LENGTH, offsetof(private_auth_payload_t, payload_length) },
/* 1 Byte AUTH type*/
- { U_INT_8, offsetof(private_auth_payload_t, auth_method) },
+ { U_INT_8, offsetof(private_auth_payload_t, auth_method) },
/* 3 reserved bytes */
- { RESERVED_BYTE, 0 },
- { RESERVED_BYTE, 0 },
- { RESERVED_BYTE, 0 },
+ { RESERVED_BYTE, offsetof(private_auth_payload_t, reserved_byte[0]) },
+ { 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) }
+ { AUTH_DATA, offsetof(private_auth_payload_t, auth_data) }
};
/*
@@ -103,125 +113,73 @@ encoding_rule_t auth_payload_encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
-/**
- * Implementation of payload_t.verify.
- */
-static status_t verify(private_auth_payload_t *this)
+METHOD(payload_t, verify, status_t,
+ private_auth_payload_t *this)
{
- if (this->auth_method == 0 ||
- (this->auth_method >= 4 && this->auth_method <= 8) ||
- (this->auth_method >= 12 && this->auth_method <= 200))
- {
- /* reserved IDs */
- return FAILED;
- }
return SUCCESS;
}
-/**
- * Implementation of auth_payload_t.get_encoding_rules.
- */
-static void get_encoding_rules(private_auth_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, void,
+ private_auth_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = auth_payload_encodings;
- *rule_count = sizeof(auth_payload_encodings) / sizeof(encoding_rule_t);
+ *rule_count = countof(auth_payload_encodings);
}
-/**
- * Implementation of payload_t.get_type.
- */
-static payload_type_t get_payload_type(private_auth_payload_t *this)
+METHOD(payload_t, get_type, payload_type_t,
+ private_auth_payload_t *this)
{
return AUTHENTICATION;
}
-/**
- * Implementation of payload_t.get_next_type.
- */
-static payload_type_t get_next_type(private_auth_payload_t *this)
+METHOD(payload_t, get_next_type, payload_type_t,
+ private_auth_payload_t *this)
{
- return (this->next_payload);
+ return this->next_payload;
}
-/**
- * Implementation of payload_t.set_next_type.
- */
-static void set_next_type(private_auth_payload_t *this,payload_type_t type)
+METHOD(payload_t, set_next_type, void,
+ private_auth_payload_t *this, payload_type_t type)
{
this->next_payload = type;
}
-/**
- * Implementation of payload_t.get_length.
- */
-static size_t get_length(private_auth_payload_t *this)
+METHOD(payload_t, get_length, size_t,
+ private_auth_payload_t *this)
{
return this->payload_length;
}
-/**
- * Implementation of auth_payload_t.set_auth_method.
- */
-static void set_auth_method (private_auth_payload_t *this, auth_method_t method)
+METHOD(auth_payload_t, set_auth_method, void,
+ private_auth_payload_t *this, auth_method_t method)
{
this->auth_method = method;
}
-/**
- * Implementation of auth_payload_t.get_auth_method.
- */
-static auth_method_t get_auth_method (private_auth_payload_t *this)
+METHOD(auth_payload_t, get_auth_method, auth_method_t,
+ private_auth_payload_t *this)
{
- return (this->auth_method);
+ return this->auth_method;
}
-/**
- * Implementation of auth_payload_t.set_data.
- */
-static void set_data (private_auth_payload_t *this, chunk_t data)
+METHOD(auth_payload_t, set_data, void,
+ private_auth_payload_t *this, chunk_t data)
{
- if (this->auth_data.ptr != NULL)
- {
- chunk_free(&(this->auth_data));
- }
- this->auth_data.ptr = clalloc(data.ptr,data.len);
- this->auth_data.len = data.len;
+ free(this->auth_data.ptr);
+ this->auth_data = chunk_clone(data);
this->payload_length = AUTH_PAYLOAD_HEADER_LENGTH + this->auth_data.len;
}
-/**
- * Implementation of auth_payload_t.get_data.
- */
-static chunk_t get_data (private_auth_payload_t *this)
+METHOD(auth_payload_t, get_data, chunk_t,
+ private_auth_payload_t *this)
{
- return (this->auth_data);
+ return this->auth_data;
}
-/**
- * Implementation of auth_payload_t.get_data_clone.
- */
-static chunk_t get_data_clone (private_auth_payload_t *this)
+METHOD2(payload_t, auth_payload_t, destroy, void,
+ private_auth_payload_t *this)
{
- chunk_t cloned_data;
- if (this->auth_data.ptr == NULL)
- {
- return (this->auth_data);
- }
- cloned_data.ptr = clalloc(this->auth_data.ptr,this->auth_data.len);
- cloned_data.len = this->auth_data.len;
- return cloned_data;
-}
-
-/**
- * Implementation of payload_t.destroy and auth_payload_t.destroy.
- */
-static void destroy(private_auth_payload_t *this)
-{
- if (this->auth_data.ptr != NULL)
- {
- chunk_free(&(this->auth_data));
- }
-
+ free(this->auth_data.ptr);
free(this);
}
@@ -230,30 +188,27 @@ static void destroy(private_auth_payload_t *this)
*/
auth_payload_t *auth_payload_create()
{
- private_auth_payload_t *this = malloc_thing(private_auth_payload_t);
-
- /* interface functions */
- this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
- this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
- this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
- this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
- this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
- this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
- this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
-
- /* public functions */
- this->public.destroy = (void (*) (auth_payload_t *)) destroy;
- this->public.set_auth_method = (void (*) (auth_payload_t *,auth_method_t)) set_auth_method;
- this->public.get_auth_method = (auth_method_t (*) (auth_payload_t *)) get_auth_method;
- this->public.set_data = (void (*) (auth_payload_t *,chunk_t)) set_data;
- this->public.get_data_clone = (chunk_t (*) (auth_payload_t *)) get_data_clone;
- this->public.get_data = (chunk_t (*) (auth_payload_t *)) get_data;
-
- /* private variables */
- this->critical = FALSE;
- this->next_payload = NO_PAYLOAD;
- this->payload_length =AUTH_PAYLOAD_HEADER_LENGTH;
- this->auth_data = chunk_empty;
-
- return (&(this->public));
+ private_auth_payload_t *this;
+
+ INIT(this,
+ .public = {
+ .payload_interface = {
+ .verify = _verify,
+ .get_encoding_rules = _get_encoding_rules,
+ .get_length = _get_length,
+ .get_next_type = _get_next_type,
+ .set_next_type = _set_next_type,
+ .get_type = _get_type,
+ .destroy = _destroy,
+ },
+ .set_auth_method = _set_auth_method,
+ .get_auth_method = _get_auth_method,
+ .set_data = _set_data,
+ .get_data = _get_data,
+ .destroy = _destroy,
+ },
+ .next_payload = NO_PAYLOAD,
+ .payload_length = AUTH_PAYLOAD_HEADER_LENGTH,
+ );
+ return &this->public;
}
diff --git a/src/libcharon/encoding/payloads/auth_payload.h b/src/libcharon/encoding/payloads/auth_payload.h
index 37ee149db..e4c4e6ae3 100644
--- a/src/libcharon/encoding/payloads/auth_payload.h
+++ b/src/libcharon/encoding/payloads/auth_payload.h
@@ -62,29 +62,31 @@ struct auth_payload_t {
/**
* Set the AUTH data.
*
- * Data gets cloned.
- *
- * @param data AUTH data as chunk_t
+ * @param data AUTH data as chunk_t, gets cloned
*/
void (*set_data) (auth_payload_t *this, chunk_t data);
/**
* Get the AUTH data.
*
- * Returned data are a copy of the internal one.
- *
- * @return AUTH data as chunk_t
+ * @return AUTH data as chunk_t, internal data
*/
- chunk_t (*get_data_clone) (auth_payload_t *this);
+ chunk_t (*get_data) (auth_payload_t *this);
/**
- * Get the AUTH data.
+ * Get the value of a reserved bit.
*
- * Returned data are NOT copied
+ * @param nr number of the reserved bit, 0-6
+ * @return TRUE if bit was set, FALSE to clear
+ */
+ bool (*get_reserved_bit)(auth_payload_t *this, u_int nr);
+
+ /**
+ * Set one of the reserved bits.
*
- * @return AUTH data as chunk_t
+ * @param nr number of the reserved bit, 0-6
*/
- chunk_t (*get_data) (auth_payload_t *this);
+ void (*set_reserved_bit)(auth_payload_t *this, u_int nr);
/**
* Destroys an auth_payload_t object.
diff --git a/src/libcharon/encoding/payloads/cert_payload.c b/src/libcharon/encoding/payloads/cert_payload.c
index 80239f654..c42cec680 100644
--- a/src/libcharon/encoding/payloads/cert_payload.c
+++ b/src/libcharon/encoding/payloads/cert_payload.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2008 Tobias Brunner
- * Copyright (C) 2005-2007 Martin Willi
+ * Copyright (C) 2005-2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -43,9 +44,9 @@ typedef struct private_cert_payload_t private_cert_payload_t;
/**
* Private data of an cert_payload_t object.
- *
*/
struct private_cert_payload_t {
+
/**
* Public cert_payload_t interface.
*/
@@ -62,6 +63,11 @@ struct private_cert_payload_t {
bool critical;
/**
+ * reserved bits
+ */
+ bool reserved[7];
+
+ /**
* Length of this payload.
*/
u_int16_t payload_length;
@@ -91,23 +97,23 @@ struct private_cert_payload_t {
*/
encoding_rule_t cert_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
- { U_INT_8, offsetof(private_cert_payload_t, next_payload) },
+ { U_INT_8, offsetof(private_cert_payload_t, next_payload) },
/* the critical bit */
- { FLAG, offsetof(private_cert_payload_t, critical) },
+ { FLAG, offsetof(private_cert_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
+ { RESERVED_BIT, offsetof(private_cert_payload_t, reserved[0]) },
+ { RESERVED_BIT, offsetof(private_cert_payload_t, reserved[1]) },
+ { RESERVED_BIT, offsetof(private_cert_payload_t, reserved[2]) },
+ { RESERVED_BIT, offsetof(private_cert_payload_t, reserved[3]) },
+ { RESERVED_BIT, offsetof(private_cert_payload_t, reserved[4]) },
+ { RESERVED_BIT, offsetof(private_cert_payload_t, reserved[5]) },
+ { RESERVED_BIT, offsetof(private_cert_payload_t, reserved[6]) },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_cert_payload_t, payload_length)},
/* 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) }
+ { CERT_DATA, offsetof(private_cert_payload_t, data) }
};
/*
@@ -123,25 +129,23 @@ encoding_rule_t cert_payload_encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
-/**
- * Implementation of payload_t.verify.
- */
-static status_t verify(private_cert_payload_t *this)
+METHOD(payload_t, verify, status_t,
+ private_cert_payload_t *this)
{
if (this->encoding == ENC_X509_HASH_AND_URL ||
this->encoding == ENC_X509_HASH_AND_URL_BUNDLE)
{
+ int i;
+
/* coarse verification of "Hash and URL" encoded certificates */
if (this->data.len <= 20)
{
DBG1(DBG_ENC, "invalid payload length for hash-and-url (%d), ignore",
- this->data.len);
+ this->data.len);
this->invalid_hash_and_url = TRUE;
return SUCCESS;
}
-
- int i = 20; /* skipping the hash */
- for (; i < this->data.len; ++i)
+ for (i = 20; i < this->data.len; ++i)
{
if (this->data.ptr[i] == '\0')
{
@@ -151,94 +155,81 @@ static status_t verify(private_cert_payload_t *this)
else if (!isprint(this->data.ptr[i]))
{
DBG1(DBG_ENC, "non printable characters in url of hash-and-url"
- " encoded certificate payload, ignore");
+ " encoded certificate payload, ignore");
this->invalid_hash_and_url = TRUE;
return SUCCESS;
}
}
-
/* URL is not null terminated, correct that */
- chunk_t data = chunk_alloc(this->data.len + 1);
- memcpy(data.ptr, this->data.ptr, this->data.len);
- data.ptr[this->data.len] = '\0';
- chunk_free(&this->data);
- this->data = data;
+ this->data = chunk_cat("mc", this->data, chunk_from_chars(0));
}
return SUCCESS;
}
-/**
- * Implementation of cert_payload_t.get_encoding_rules.
- */
-static void get_encoding_rules(private_cert_payload_t *this,
- encoding_rule_t **rules, size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, void,
+ private_cert_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = cert_payload_encodings;
- *rule_count = sizeof(cert_payload_encodings) / sizeof(encoding_rule_t);
+ *rule_count = countof(cert_payload_encodings);
}
-/**
- * Implementation of payload_t.get_type.
- */
-static payload_type_t get_payload_type(private_cert_payload_t *this)
+METHOD(payload_t, get_type, payload_type_t,
+ private_cert_payload_t *this)
{
return CERTIFICATE;
}
-/**
- * Implementation of payload_t.get_next_type.
- */
-static payload_type_t get_next_type(private_cert_payload_t *this)
+METHOD(payload_t, get_next_type, payload_type_t,
+ private_cert_payload_t *this)
{
return this->next_payload;
}
-/**
- * Implementation of payload_t.set_next_type.
- */
-static void set_next_type(private_cert_payload_t *this,payload_type_t type)
+METHOD(payload_t, set_next_type, void,
+ private_cert_payload_t *this, payload_type_t type)
{
this->next_payload = type;
}
-/**
- * Implementation of payload_t.get_length.
- */
-static size_t get_length(private_cert_payload_t *this)
+METHOD(payload_t, get_length, size_t,
+ private_cert_payload_t *this)
{
return this->payload_length;
}
-/**
- * Implementation of cert_payload_t.get_cert_encoding.
- */
-static cert_encoding_t get_cert_encoding(private_cert_payload_t *this)
+METHOD(cert_payload_t, get_cert_encoding, cert_encoding_t,
+ private_cert_payload_t *this)
{
return this->encoding;
}
-/**
- * Implementation of cert_payload_t.get_cert.
- */
-static certificate_t *get_cert(private_cert_payload_t *this)
+METHOD(cert_payload_t, get_cert, certificate_t*,
+ private_cert_payload_t *this)
{
- if (this->encoding != ENC_X509_SIGNATURE)
+ int type;
+
+ switch (this->encoding)
{
- return NULL;
+ case ENC_X509_SIGNATURE:
+ type = CERT_X509;
+ break;
+ case ENC_CRL:
+ type = CERT_X509_CRL;
+ break;
+ default:
+ return NULL;
}
- return lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
- BUILD_BLOB_ASN1_DER, this->data,
- BUILD_END);
+ return lib->creds->create(lib->creds, CRED_CERTIFICATE, type,
+ BUILD_BLOB_ASN1_DER, this->data, BUILD_END);
}
-/**
- * Implementation of cert_payload_t.get_hash.
- */
-static chunk_t get_hash(private_cert_payload_t *this)
+METHOD(cert_payload_t, get_hash, chunk_t,
+ private_cert_payload_t *this)
{
chunk_t hash = chunk_empty;
+
if ((this->encoding != ENC_X509_HASH_AND_URL &&
- this->encoding != ENC_X509_HASH_AND_URL_BUNDLE) ||
+ this->encoding != ENC_X509_HASH_AND_URL_BUNDLE) ||
this->invalid_hash_and_url)
{
return hash;
@@ -248,13 +239,11 @@ static chunk_t get_hash(private_cert_payload_t *this)
return hash;
}
-/**
- * Implementation of cert_payload_t.get_url.
- */
-static char *get_url(private_cert_payload_t *this)
+METHOD(cert_payload_t, get_url, char*,
+ private_cert_payload_t *this)
{
if ((this->encoding != ENC_X509_HASH_AND_URL &&
- this->encoding != ENC_X509_HASH_AND_URL_BUNDLE) ||
+ this->encoding != ENC_X509_HASH_AND_URL_BUNDLE) ||
this->invalid_hash_and_url)
{
return NULL;
@@ -262,12 +251,10 @@ static char *get_url(private_cert_payload_t *this)
return (char*)this->data.ptr + 20;
}
-/**
- * Implementation of payload_t.destroy and cert_payload_t.destroy.
- */
-static void destroy(private_cert_payload_t *this)
+METHOD2(payload_t, cert_payload_t, destroy, void,
+ private_cert_payload_t *this)
{
- chunk_free(&this->data);
+ free(this->data.ptr);
free(this);
}
@@ -276,29 +263,28 @@ static void destroy(private_cert_payload_t *this)
*/
cert_payload_t *cert_payload_create()
{
- private_cert_payload_t *this = malloc_thing(private_cert_payload_t);
-
- this->public.payload_interface.verify = (status_t (*) (payload_t*))verify;
- this->public.payload_interface.get_encoding_rules = (void (*) (payload_t*,encoding_rule_t**, size_t*))get_encoding_rules;
- this->public.payload_interface.get_length = (size_t (*) (payload_t*))get_length;
- this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t*))get_next_type;
- this->public.payload_interface.set_next_type = (void (*) (payload_t*,payload_type_t))set_next_type;
- this->public.payload_interface.get_type = (payload_type_t (*) (payload_t*))get_payload_type;
- this->public.payload_interface.destroy = (void (*) (payload_t*))destroy;
-
- this->public.destroy = (void (*) (cert_payload_t*))destroy;
- this->public.get_cert = (certificate_t* (*) (cert_payload_t*))get_cert;
- this->public.get_cert_encoding = (cert_encoding_t (*) (cert_payload_t*))get_cert_encoding;
- this->public.get_hash = (chunk_t (*) (cert_payload_t*))get_hash;
- this->public.get_url = (char* (*) (cert_payload_t*))get_url;
-
- this->critical = FALSE;
- this->next_payload = NO_PAYLOAD;
- this->payload_length = CERT_PAYLOAD_HEADER_LENGTH;
- this->data = chunk_empty;
- this->encoding = 0;
- this->invalid_hash_and_url = FALSE;
-
+ private_cert_payload_t *this;
+
+ INIT(this,
+ .public = {
+ .payload_interface = {
+ .verify = _verify,
+ .get_encoding_rules = _get_encoding_rules,
+ .get_length = _get_length,
+ .get_next_type = _get_next_type,
+ .set_next_type = _set_next_type,
+ .get_type = _get_type,
+ .destroy = _destroy,
+ },
+ .get_cert = _get_cert,
+ .get_cert_encoding = _get_cert_encoding,
+ .get_hash = _get_hash,
+ .get_url = _get_url,
+ .destroy = _destroy,
+ },
+ .next_payload = NO_PAYLOAD,
+ .payload_length = CERT_PAYLOAD_HEADER_LENGTH,
+ );
return &this->public;
}
@@ -343,3 +329,15 @@ cert_payload_t *cert_payload_create_from_hash_and_url(chunk_t hash, char *url)
return &this->public;
}
+/*
+ * Described in header
+ */
+cert_payload_t *cert_payload_create_custom(cert_encoding_t type, chunk_t data)
+{
+ private_cert_payload_t *this = (private_cert_payload_t*)cert_payload_create();
+
+ this->encoding = type;
+ this->data = data;
+ this->payload_length = CERT_PAYLOAD_HEADER_LENGTH + 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 aa1c7bf5a..21b503a40 100644
--- a/src/libcharon/encoding/payloads/cert_payload.h
+++ b/src/libcharon/encoding/payloads/cert_payload.h
@@ -134,4 +134,13 @@ 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);
+/**
+ * Creates a custom certificate payload using type and associated data.
+ *
+ * @param type 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);
+
#endif /** CERT_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/certreq_payload.c b/src/libcharon/encoding/payloads/certreq_payload.c
index 9ff0bdde0..8e0836f0e 100644
--- a/src/libcharon/encoding/payloads/certreq_payload.c
+++ b/src/libcharon/encoding/payloads/certreq_payload.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005-2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -22,14 +23,13 @@
#include "certreq_payload.h"
-
typedef struct private_certreq_payload_t private_certreq_payload_t;
/**
* Private data of an certreq_payload_t object.
- *
*/
struct private_certreq_payload_t {
+
/**
* Public certreq_payload_t interface.
*/
@@ -46,6 +46,11 @@ struct private_certreq_payload_t {
bool critical;
/**
+ * Reserved bits
+ */
+ bool reserved[7];
+
+ /**
* Length of this payload.
*/
u_int16_t payload_length;
@@ -66,21 +71,20 @@ struct private_certreq_payload_t {
*
* The defined offsets are the positions in a object of type
* private_certreq_payload_t.
- *
*/
encoding_rule_t certreq_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
- { U_INT_8, offsetof(private_certreq_payload_t, next_payload) },
+ { U_INT_8, offsetof(private_certreq_payload_t, next_payload) },
/* the critical bit */
- { FLAG, offsetof(private_certreq_payload_t, critical) },
- /* 7 Bit reserved bits, nowhere stored */
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
+ { FLAG, offsetof(private_certreq_payload_t, critical) },
+ /* 7 Bit reserved bits */
+ { RESERVED_BIT, offsetof(private_certreq_payload_t, reserved[0]) },
+ { RESERVED_BIT, offsetof(private_certreq_payload_t, reserved[1]) },
+ { RESERVED_BIT, offsetof(private_certreq_payload_t, reserved[2]) },
+ { RESERVED_BIT, offsetof(private_certreq_payload_t, reserved[3]) },
+ { RESERVED_BIT, offsetof(private_certreq_payload_t, reserved[4]) },
+ { RESERVED_BIT, offsetof(private_certreq_payload_t, reserved[5]) },
+ { RESERVED_BIT, offsetof(private_certreq_payload_t, reserved[6]) },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_certreq_payload_t, payload_length) },
/* 1 Byte CERTREQ type*/
@@ -102,10 +106,8 @@ encoding_rule_t certreq_payload_encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
-/**
- * Implementation of payload_t.verify.
- */
-static status_t verify(private_certreq_payload_t *this)
+METHOD(payload_t, verify, status_t,
+ private_certreq_payload_t *this)
{
if (this->encoding == ENC_X509_SIGNATURE)
{
@@ -120,51 +122,39 @@ static status_t verify(private_certreq_payload_t *this)
return SUCCESS;
}
-/**
- * Implementation of certreq_payload_t.get_encoding_rules.
- */
-static void get_encoding_rules(private_certreq_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, void,
+ private_certreq_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = certreq_payload_encodings;
- *rule_count = sizeof(certreq_payload_encodings) / sizeof(encoding_rule_t);
+ *rule_count = countof(certreq_payload_encodings);
}
-/**
- * Implementation of payload_t.get_type.
- */
-static payload_type_t get_payload_type(private_certreq_payload_t *this)
+METHOD(payload_t, get_type, payload_type_t,
+ private_certreq_payload_t *this)
{
return CERTIFICATE_REQUEST;
}
-/**
- * Implementation of payload_t.get_next_type.
- */
-static payload_type_t get_next_type(private_certreq_payload_t *this)
+METHOD(payload_t, get_next_type, payload_type_t,
+ private_certreq_payload_t *this)
{
- return (this->next_payload);
+ return this->next_payload;
}
-/**
- * Implementation of payload_t.set_next_type.
- */
-static void set_next_type(private_certreq_payload_t *this,payload_type_t type)
+METHOD(payload_t, set_next_type, void,
+ private_certreq_payload_t *this, payload_type_t type)
{
this->next_payload = type;
}
-/**
- * Implementation of payload_t.get_length.
- */
-static size_t get_length(private_certreq_payload_t *this)
+METHOD(payload_t, get_length, size_t,
+ private_certreq_payload_t *this)
{
return this->payload_length;
}
-/**
- * Implementation of certreq_payload_t.add_keyid.
- */
-static void add_keyid(private_certreq_payload_t *this, chunk_t keyid)
+METHOD(certreq_payload_t, add_keyid, void,
+ private_certreq_payload_t *this, chunk_t keyid)
{
this->data = chunk_cat("mc", this->data, keyid);
this->payload_length += keyid.len;
@@ -181,10 +171,8 @@ struct keyid_enumerator_t {
u_char *pos;
};
-/**
- * enumerate function for keyid_enumerator
- */
-static bool keyid_enumerate(keyid_enumerator_t *this, chunk_t *chunk)
+METHOD(enumerator_t, keyid_enumerate, bool,
+ keyid_enumerator_t *this, chunk_t *chunk)
{
if (this->pos == NULL)
{
@@ -207,23 +195,23 @@ static bool keyid_enumerate(keyid_enumerator_t *this, chunk_t *chunk)
return FALSE;
}
-/**
- * Implementation of certreq_payload_t.create_keyid_enumerator.
- */
-static enumerator_t* create_keyid_enumerator(private_certreq_payload_t *this)
+METHOD(certreq_payload_t, create_keyid_enumerator, enumerator_t*,
+ private_certreq_payload_t *this)
{
- keyid_enumerator_t *enumerator = malloc_thing(keyid_enumerator_t);
- enumerator->public.enumerate = (void*)keyid_enumerate;
- enumerator->public.destroy = (void*)free;
- enumerator->full = this->data;
- enumerator->pos = NULL;
+ keyid_enumerator_t *enumerator;
+
+ INIT(enumerator,
+ .public = {
+ .enumerate = (void*)_keyid_enumerate,
+ .destroy = (void*)free,
+ },
+ .full = this->data,
+ );
return &enumerator->public;
}
-/**
- * Implementation of certreq_payload_t.get_cert_type.
- */
-static certificate_type_t get_cert_type(private_certreq_payload_t *this)
+METHOD(certreq_payload_t, get_cert_type, certificate_type_t,
+ private_certreq_payload_t *this)
{
switch (this->encoding)
{
@@ -234,10 +222,8 @@ static certificate_type_t get_cert_type(private_certreq_payload_t *this)
}
}
-/**
- * Implementation of payload_t.destroy and certreq_payload_t.destroy.
- */
-static void destroy(private_certreq_payload_t *this)
+METHOD2(payload_t, certreq_payload_t, destroy, void,
+ private_certreq_payload_t *this)
{
chunk_free(&this->data);
free(this);
@@ -248,30 +234,27 @@ static void destroy(private_certreq_payload_t *this)
*/
certreq_payload_t *certreq_payload_create()
{
- private_certreq_payload_t *this = malloc_thing(private_certreq_payload_t);
-
- /* interface functions */
- this->public.payload_interface.verify = (status_t (*) (payload_t*))verify;
- this->public.payload_interface.get_encoding_rules = (void (*) (payload_t*,encoding_rule_t**,size_t*))get_encoding_rules;
- this->public.payload_interface.get_length = (size_t (*) (payload_t*))get_length;
- this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t*))get_next_type;
- this->public.payload_interface.set_next_type = (void (*) (payload_t*,payload_type_t))set_next_type;
- this->public.payload_interface.get_type = (payload_type_t (*) (payload_t*))get_payload_type;
- this->public.payload_interface.destroy = (void (*) (payload_t*))destroy;
-
- /* public functions */
- this->public.destroy = (void (*) (certreq_payload_t*)) destroy;
- this->public.create_keyid_enumerator = (enumerator_t*(*)(certreq_payload_t*))create_keyid_enumerator;
- this->public.get_cert_type = (certificate_type_t(*)(certreq_payload_t*))get_cert_type;
- this->public.add_keyid = (void(*)(certreq_payload_t*, chunk_t keyid))add_keyid;
-
- /* private variables */
- this->critical = FALSE;
- this->next_payload = NO_PAYLOAD;
- this->payload_length = CERTREQ_PAYLOAD_HEADER_LENGTH;
- this->data = chunk_empty;
- this->encoding = 0;
-
+ private_certreq_payload_t *this;
+
+ INIT(this,
+ .public = {
+ .payload_interface = {
+ .verify = _verify,
+ .get_encoding_rules = _get_encoding_rules,
+ .get_length = _get_length,
+ .get_next_type = _get_next_type,
+ .set_next_type = _set_next_type,
+ .get_type = _get_type,
+ .destroy = _destroy,
+ },
+ .create_keyid_enumerator = _create_keyid_enumerator,
+ .get_cert_type = _get_cert_type,
+ .add_keyid = _add_keyid,
+ .destroy = _destroy,
+ },
+ .next_payload = NO_PAYLOAD,
+ .payload_length = CERTREQ_PAYLOAD_HEADER_LENGTH,
+ );
return &this->public;
}
diff --git a/src/libcharon/encoding/payloads/configuration_attribute.c b/src/libcharon/encoding/payloads/configuration_attribute.c
index 9094fd44d..e608497bd 100644
--- a/src/libcharon/encoding/payloads/configuration_attribute.c
+++ b/src/libcharon/encoding/payloads/configuration_attribute.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2005-2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -22,20 +23,24 @@
#include <library.h>
#include <daemon.h>
-
typedef struct private_configuration_attribute_t private_configuration_attribute_t;
/**
* Private data of an configuration_attribute_t object.
- *
*/
struct private_configuration_attribute_t {
+
/**
* Public configuration_attribute_t interface.
*/
configuration_attribute_t public;
/**
+ * Reserved bit
+ */
+ bool reserved;
+
+ /**
* Type of the attribute.
*/
u_int16_t type;
@@ -58,8 +63,8 @@ struct private_configuration_attribute_t {
* private_configuration_attribute_t.
*/
encoding_rule_t configuration_attribute_encodings[] = {
-
- { RESERVED_BIT, 0 },
+ /* 1 reserved bit */
+ { 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) },
/* Length of attribute value */
@@ -80,10 +85,8 @@ encoding_rule_t configuration_attribute_encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
-/**
- * Implementation of payload_t.verify.
- */
-static status_t verify(private_configuration_attribute_t *this)
+METHOD(payload_t, verify, status_t,
+ private_configuration_attribute_t *this)
{
bool failed = FALSE;
@@ -151,69 +154,51 @@ static status_t verify(private_configuration_attribute_t *this)
return SUCCESS;
}
-/**
- * Implementation of payload_t.get_encoding_rules.
- */
-static void get_encoding_rules(private_configuration_attribute_t *this,
- encoding_rule_t **rules, size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, void,
+ private_configuration_attribute_t *this, encoding_rule_t **rules,
+ size_t *rule_count)
{
*rules = configuration_attribute_encodings;
- *rule_count = sizeof(configuration_attribute_encodings) / sizeof(encoding_rule_t);
+ *rule_count = countof(configuration_attribute_encodings);
}
-/**
- * Implementation of payload_t.get_type.
- */
-static payload_type_t get_type(private_configuration_attribute_t *this)
+METHOD(payload_t, get_type, payload_type_t,
+ private_configuration_attribute_t *this)
{
return CONFIGURATION_ATTRIBUTE;
}
-/**
- * Implementation of payload_t.get_next_type.
- */
-static payload_type_t get_next_type(private_configuration_attribute_t *this)
+METHOD(payload_t, get_next_type, payload_type_t,
+ private_configuration_attribute_t *this)
{
return NO_PAYLOAD;
}
-/**
- * Implementation of payload_t.set_next_type.
- */
-static void set_next_type(private_configuration_attribute_t *this,
- payload_type_t type)
+METHOD(payload_t, set_next_type, void,
+ private_configuration_attribute_t *this, payload_type_t type)
{
}
-/**
- * Implementation of configuration_attribute_t.get_length.
- */
-static size_t get_length(private_configuration_attribute_t *this)
+METHOD(payload_t, get_length, size_t,
+ private_configuration_attribute_t *this)
{
return this->value.len + CONFIGURATION_ATTRIBUTE_HEADER_LENGTH;
}
-/**
- * Implementation of configuration_attribute_t.get_type.
- */
-static configuration_attribute_type_t get_configuration_attribute_type(
- private_configuration_attribute_t *this)
+METHOD(configuration_attribute_t, get_cattr_type, configuration_attribute_type_t,
+ private_configuration_attribute_t *this)
{
return this->type;
}
-/**
- * Implementation of configuration_attribute_t.get_value.
- */
-static chunk_t get_value(private_configuration_attribute_t *this)
+METHOD(configuration_attribute_t, get_value, chunk_t,
+ private_configuration_attribute_t *this)
{
return this->value;
}
-/**
- * Implementation of configuration_attribute_t.destroy and payload_t.destroy.
- */
-static void destroy(private_configuration_attribute_t *this)
+METHOD2(payload_t, configuration_attribute_t, destroy, void,
+ private_configuration_attribute_t *this)
{
free(this->value.ptr);
free(this);
@@ -226,23 +211,22 @@ configuration_attribute_t *configuration_attribute_create()
{
private_configuration_attribute_t *this;
- this = malloc_thing(private_configuration_attribute_t);
- this->public.payload_interface.verify = (status_t(*)(payload_t *))verify;
- this->public.payload_interface.get_encoding_rules = (void(*)(payload_t *, encoding_rule_t **, size_t *) )get_encoding_rules;
- this->public.payload_interface.get_length = (size_t(*)(payload_t *))get_length;
- this->public.payload_interface.get_next_type = (payload_type_t(*)(payload_t *))get_next_type;
- this->public.payload_interface.set_next_type = (void(*)(payload_t *,payload_type_t))set_next_type;
- this->public.payload_interface.get_type = (payload_type_t(*)(payload_t *))get_type;
- this->public.payload_interface.destroy = (void(*)(payload_t*))destroy;
-
- this->public.get_value = (chunk_t(*)(configuration_attribute_t *))get_value;
- this->public.get_type = (configuration_attribute_type_t(*)(configuration_attribute_t *))get_configuration_attribute_type;
- this->public.destroy = (void (*)(configuration_attribute_t*))destroy;
-
- this->type = 0;
- this->value = chunk_empty;
- this->length = 0;
-
+ INIT(this,
+ .public = {
+ .payload_interface = {
+ .verify = _verify,
+ .get_encoding_rules = _get_encoding_rules,
+ .get_length = _get_length,
+ .get_next_type = _get_next_type,
+ .set_next_type = _set_next_type,
+ .get_type = _get_type,
+ .destroy = _destroy,
+ },
+ .get_value = _get_value,
+ .get_type = _get_cattr_type,
+ .destroy = _destroy,
+ },
+ );
return &this->public;
}
diff --git a/src/libcharon/encoding/payloads/cp_payload.c b/src/libcharon/encoding/payloads/cp_payload.c
index f0a26eee2..82e9e51b7 100644
--- a/src/libcharon/encoding/payloads/cp_payload.c
+++ b/src/libcharon/encoding/payloads/cp_payload.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2005-2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -32,9 +33,9 @@ typedef struct private_cp_payload_t private_cp_payload_t;
/**
* Private data of an cp_payload_t object.
- *
*/
struct private_cp_payload_t {
+
/**
* Public cp_payload_t interface.
*/
@@ -51,6 +52,16 @@ struct private_cp_payload_t {
bool critical;
/**
+ * Reserved bits
+ */
+ bool reserved_bit[7];
+
+ /**
+ * Reserved bytes
+ */
+ u_int8_t reserved_byte[3];
+
+ /**
* Length of this payload.
*/
u_int16_t payload_length;
@@ -71,30 +82,30 @@ struct private_cp_payload_t {
*
* The defined offsets are the positions in a object of type
* private_cp_payload_t.
- *
*/
encoding_rule_t cp_payload_encodings[] = {
/* 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) },
- /* 7 Bit reserved bits, nowhere stored */
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
+ { 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) },
+ { 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) },
- { RESERVED_BYTE,0 },
- { RESERVED_BYTE,0 },
- { RESERVED_BYTE,0 },
- { CONFIGURATION_ATTRIBUTES, offsetof(private_cp_payload_t, attributes) }
+ { U_INT_8, offsetof(private_cp_payload_t, 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) }
};
/*
@@ -111,10 +122,8 @@ encoding_rule_t cp_payload_encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
-/**
- * Implementation of payload_t.verify.
- */
-static status_t verify(private_cp_payload_t *this)
+METHOD(payload_t, verify, status_t,
+ private_cp_payload_t *this)
{
status_t status = SUCCESS;
enumerator_t *enumerator;
@@ -133,36 +142,27 @@ static status_t verify(private_cp_payload_t *this)
return status;
}
-/**
- * Implementation of payload_t.get_encoding_rules.
- */
-static void get_encoding_rules(private_cp_payload_t *this,
- encoding_rule_t **rules, size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, void,
+ private_cp_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = cp_payload_encodings;
- *rule_count = sizeof(cp_payload_encodings) / sizeof(encoding_rule_t);
+ *rule_count = countof(cp_payload_encodings);
}
-/**
- * Implementation of payload_t.get_type.
- */
-static payload_type_t get_type(private_cp_payload_t *this)
+METHOD(payload_t, get_type, payload_type_t,
+ private_cp_payload_t *this)
{
return CONFIGURATION;
}
-/**
- * Implementation of payload_t.get_next_type.
- */
-static payload_type_t get_next_type(private_cp_payload_t *this)
+METHOD(payload_t, get_next_type, payload_type_t,
+ private_cp_payload_t *this)
{
return this->next_payload;
}
-/**
- * Implementation of payload_t.set_next_type.
- */
-static void set_next_type(private_cp_payload_t *this,payload_type_t type)
+METHOD(payload_t, set_next_type, void,
+ private_cp_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
@@ -185,44 +185,33 @@ static void compute_length(private_cp_payload_t *this)
enumerator->destroy(enumerator);
}
-/**
- * Implementation of payload_t.get_length.
- */
-static size_t get_length(private_cp_payload_t *this)
+METHOD(payload_t, get_length, size_t,
+ private_cp_payload_t *this)
{
return this->payload_length;
}
-/**
- * Implementation of cp_payload_t.create_attribute_enumerator.
- */
-static enumerator_t *create_attribute_enumerator(private_cp_payload_t *this)
+METHOD(cp_payload_t, create_attribute_enumerator, enumerator_t*,
+ private_cp_payload_t *this)
{
return this->attributes->create_enumerator(this->attributes);
}
-/**
- * Implementation of cp_payload_t.add_attribute.
- */
-static void add_attribute(private_cp_payload_t *this,
- configuration_attribute_t *attribute)
+METHOD(cp_payload_t, add_attribute, void,
+ private_cp_payload_t *this, configuration_attribute_t *attribute)
{
this->attributes->insert_last(this->attributes, attribute);
compute_length(this);
}
-/**
- * Implementation of cp_payload_t.get_type.
- */
-static config_type_t get_config_type(private_cp_payload_t *this)
+METHOD(cp_payload_t, get_config_type, config_type_t,
+ private_cp_payload_t *this)
{
return this->type;
}
-/**
- * Implementation of payload_t.destroy and cp_payload_t.destroy.
- */
-static void destroy(private_cp_payload_t *this)
+METHOD2(payload_t, cp_payload_t, destroy, void,
+ private_cp_payload_t *this)
{
this->attributes->destroy_offset(this->attributes,
offsetof(configuration_attribute_t, destroy));
@@ -232,42 +221,38 @@ static void destroy(private_cp_payload_t *this)
/*
* Described in header.
*/
-cp_payload_t *cp_payload_create()
+cp_payload_t *cp_payload_create_type(config_type_t type)
{
- private_cp_payload_t *this = malloc_thing(private_cp_payload_t);
-
- this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
- this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
- this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
- this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
- this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
- this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
- this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
-
- this->public.create_attribute_enumerator = (enumerator_t*(*)(cp_payload_t *))create_attribute_enumerator;
- this->public.add_attribute = (void (*) (cp_payload_t *,configuration_attribute_t*))add_attribute;
- this->public.get_type = (config_type_t (*) (cp_payload_t *))get_config_type;
- this->public.destroy = (void (*)(cp_payload_t *))destroy;
-
- /* set default values of the fields */
- this->critical = FALSE;
- this->next_payload = NO_PAYLOAD;
- this->payload_length = CP_PAYLOAD_HEADER_LENGTH;
- this->attributes = linked_list_create();
- this->type = CFG_REQUEST;
-
+ private_cp_payload_t *this;
+
+ INIT(this,
+ .public = {
+ .payload_interface = {
+ .verify = _verify,
+ .get_encoding_rules = _get_encoding_rules,
+ .get_length = _get_length,
+ .get_next_type = _get_next_type,
+ .set_next_type = _set_next_type,
+ .get_type = _get_type,
+ .destroy = _destroy,
+ },
+ .create_attribute_enumerator = _create_attribute_enumerator,
+ .add_attribute = _add_attribute,
+ .get_type = _get_config_type,
+ .destroy = _destroy,
+ },
+ .next_payload = NO_PAYLOAD,
+ .payload_length = CP_PAYLOAD_HEADER_LENGTH,
+ .attributes = linked_list_create(),
+ .type = type,
+ );
return &this->public;
}
/*
* Described in header.
*/
-cp_payload_t *cp_payload_create_type(config_type_t type)
+cp_payload_t *cp_payload_create()
{
- private_cp_payload_t *this = (private_cp_payload_t*)cp_payload_create();
-
- this->type = type;
-
- return &this->public;
+ return cp_payload_create_type(CFG_REQUEST);
}
-
diff --git a/src/libcharon/encoding/payloads/delete_payload.c b/src/libcharon/encoding/payloads/delete_payload.c
index 5fc3b7c88..e6ee07d39 100644
--- a/src/libcharon/encoding/payloads/delete_payload.c
+++ b/src/libcharon/encoding/payloads/delete_payload.c
@@ -43,6 +43,11 @@ struct private_delete_payload_t {
bool critical;
/**
+ * reserved bits
+ */
+ bool reserved[7];
+
+ /**
* Length of this payload.
*/
u_int16_t payload_length;
@@ -79,14 +84,14 @@ encoding_rule_t delete_payload_encodings[] = {
{ U_INT_8, offsetof(private_delete_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_delete_payload_t, critical) },
- /* 7 Bit reserved bits, nowhere stored */
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
+ /* 7 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]) },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_delete_payload_t, payload_length) },
{ U_INT_8, offsetof(private_delete_payload_t, protocol_id) },
diff --git a/src/libcharon/encoding/payloads/eap_payload.c b/src/libcharon/encoding/payloads/eap_payload.c
index 21f34a642..eafb668b6 100644
--- a/src/libcharon/encoding/payloads/eap_payload.c
+++ b/src/libcharon/encoding/payloads/eap_payload.c
@@ -43,6 +43,11 @@ struct private_eap_payload_t {
bool critical;
/**
+ * Reserved bits
+ */
+ bool reserved[7];
+
+ /**
* Length of this payload.
*/
u_int16_t payload_length;
@@ -66,13 +71,13 @@ static encoding_rule_t eap_payload_encodings[] = {
/* the critical bit */
{ FLAG, offsetof(private_eap_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
+ { RESERVED_BIT, offsetof(private_eap_payload_t, reserved[0]) },
+ { RESERVED_BIT, offsetof(private_eap_payload_t, reserved[1]) },
+ { RESERVED_BIT, offsetof(private_eap_payload_t, reserved[2]) },
+ { RESERVED_BIT, offsetof(private_eap_payload_t, reserved[3]) },
+ { RESERVED_BIT, offsetof(private_eap_payload_t, reserved[4]) },
+ { RESERVED_BIT, offsetof(private_eap_payload_t, reserved[5]) },
+ { RESERVED_BIT, offsetof(private_eap_payload_t, reserved[6]) },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_eap_payload_t, payload_length) },
/* chunt to data, starting at "code" */
diff --git a/src/libcharon/encoding/payloads/id_payload.c b/src/libcharon/encoding/payloads/id_payload.c
index 4158c3e07..3befadfe2 100644
--- a/src/libcharon/encoding/payloads/id_payload.c
+++ b/src/libcharon/encoding/payloads/id_payload.c
@@ -1,6 +1,7 @@
/*
+ * Copyright (C) 2005-2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
* Copyright (C) 2007 Tobias Brunner
- * Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
*
* Hochschule fuer Technik Rapperswil
@@ -51,6 +52,16 @@ struct private_id_payload_t {
bool critical;
/**
+ * Reserved bits
+ */
+ bool reserved_bit[7];
+
+ /**
+ * Reserved bytes
+ */
+ u_int8_t reserved_byte[3];
+
+ /**
* Length of this payload.
*/
u_int16_t payload_length;
@@ -71,31 +82,30 @@ struct private_id_payload_t {
*
* The defined offsets are the positions in a object of type
* private_id_payload_t.
- *
*/
encoding_rule_t id_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_id_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_id_payload_t, critical) },
- /* 7 Bit reserved bits, nowhere stored */
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
+ /* 7 Bit reserved bits */
+ { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[0]) },
+ { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[1]) },
+ { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[2]) },
+ { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[3]) },
+ { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[4]) },
+ { 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) },
/* 1 Byte ID type*/
{ U_INT_8, offsetof(private_id_payload_t, id_type) },
/* 3 reserved bytes */
- { RESERVED_BYTE, 0 },
- { RESERVED_BYTE, 0 },
- { RESERVED_BYTE, 0 },
+ { RESERVED_BYTE, offsetof(private_id_payload_t, reserved_byte[0])},
+ { 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) }
+ { ID_DATA, offsetof(private_id_payload_t, id_data) }
};
/*
@@ -112,136 +122,59 @@ encoding_rule_t id_payload_encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
-/**
- * Implementation of payload_t.verify.
- */
-static status_t verify(private_id_payload_t *this)
+METHOD(payload_t, verify, status_t,
+ private_id_payload_t *this)
{
- if ((this->id_type == 0) ||
- (this->id_type == 4) ||
- ((this->id_type >= 6) && (this->id_type <= 8)) ||
- ((this->id_type >= 12) && (this->id_type <= 200)))
+ if (this->id_type == 0 || this->id_type == 4)
{
/* reserved IDs */
DBG1(DBG_ENC, "received ID with reserved type %d", this->id_type);
return FAILED;
}
-
return SUCCESS;
}
-/**
- * Implementation of id_payload_t.get_encoding_rules.
- */
-static void get_encoding_rules(private_id_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, void,
+ private_id_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = id_payload_encodings;
- *rule_count = sizeof(id_payload_encodings) / sizeof(encoding_rule_t);
+ *rule_count = countof(id_payload_encodings);
}
-/**
- * Implementation of payload_t.get_type.
- */
-static payload_type_t get_payload_type(private_id_payload_t *this)
+METHOD(payload_t, get_type, payload_type_t,
+ private_id_payload_t *this)
{
return this->payload_type;
}
-/**
- * Implementation of payload_t.get_next_type.
- */
-static payload_type_t get_next_type(private_id_payload_t *this)
+METHOD(payload_t, get_next_type, payload_type_t,
+ private_id_payload_t *this)
{
return this->next_payload;
}
-/**
- * Implementation of payload_t.set_next_type.
- */
-static void set_next_type(private_id_payload_t *this,payload_type_t type)
+METHOD(payload_t, set_next_type, void,
+ private_id_payload_t *this, payload_type_t type)
{
this->next_payload = type;
}
-/**
- * Implementation of payload_t.get_length.
- */
-static size_t get_length(private_id_payload_t *this)
+METHOD(payload_t, get_length, size_t,
+ private_id_payload_t *this)
{
return this->payload_length;
}
-/**
- * Implementation of id_payload_t.set_type.
- */
-static void set_id_type (private_id_payload_t *this, id_type_t type)
-{
- this->id_type = type;
-}
-
-/**
- * Implementation of id_payload_t.get_id_type.
- */
-static id_type_t get_id_type (private_id_payload_t *this)
+METHOD(id_payload_t, get_identification, identification_t*,
+ private_id_payload_t *this)
{
- return (this->id_type);
+ return identification_create_from_encoding(this->id_type, this->id_data);
}
-/**
- * Implementation of id_payload_t.set_data.
- */
-static void set_data (private_id_payload_t *this, chunk_t data)
+METHOD2(payload_t, id_payload_t, destroy, void,
+ private_id_payload_t *this)
{
- if (this->id_data.ptr != NULL)
- {
- chunk_free(&(this->id_data));
- }
- this->id_data.ptr = clalloc(data.ptr,data.len);
- this->id_data.len = data.len;
- this->payload_length = ID_PAYLOAD_HEADER_LENGTH + this->id_data.len;
-}
-
-
-/**
- * Implementation of id_payload_t.get_data_clone.
- */
-static chunk_t get_data (private_id_payload_t *this)
-{
- return (this->id_data);
-}
-
-/**
- * Implementation of id_payload_t.get_data_clone.
- */
-static chunk_t get_data_clone (private_id_payload_t *this)
-{
- chunk_t cloned_data;
- if (this->id_data.ptr == NULL)
- {
- return (this->id_data);
- }
- cloned_data.ptr = clalloc(this->id_data.ptr,this->id_data.len);
- cloned_data.len = this->id_data.len;
- return cloned_data;
-}
-
-/**
- * Implementation of id_payload_t.get_identification.
- */
-static identification_t *get_identification (private_id_payload_t *this)
-{
- return identification_create_from_encoding(this->id_type,this->id_data);
-}
-
-/**
- * Implementation of payload_t.destroy and id_payload_t.destroy.
- */
-static void destroy(private_id_payload_t *this)
-{
- if (this->id_data.ptr != NULL)
- {
- chunk_free(&(this->id_data));
- }
+ free(this->id_data.ptr);
free(this);
}
@@ -250,44 +183,41 @@ static void destroy(private_id_payload_t *this)
*/
id_payload_t *id_payload_create(payload_type_t payload_type)
{
- private_id_payload_t *this = malloc_thing(private_id_payload_t);
-
- /* interface functions */
- this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
- this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
- this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
- this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
- this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
- this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
- this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
-
- /* public functions */
- this->public.destroy = (void (*) (id_payload_t *)) destroy;
- this->public.set_id_type = (void (*) (id_payload_t *,id_type_t)) set_id_type;
- this->public.get_id_type = (id_type_t (*) (id_payload_t *)) get_id_type;
- this->public.set_data = (void (*) (id_payload_t *,chunk_t)) set_data;
- this->public.get_data = (chunk_t (*) (id_payload_t *)) get_data;
- this->public.get_data_clone = (chunk_t (*) (id_payload_t *)) get_data_clone;
-
- this->public.get_identification = (identification_t * (*) (id_payload_t *this)) get_identification;
-
- /* private variables */
- this->critical = FALSE;
- this->next_payload = NO_PAYLOAD;
- this->payload_length =ID_PAYLOAD_HEADER_LENGTH;
- this->id_data = chunk_empty;
- this->payload_type = payload_type;
-
- return (&(this->public));
+ private_id_payload_t *this;
+
+ INIT(this,
+ .public = {
+ .payload_interface = {
+ .verify = _verify,
+ .get_encoding_rules = _get_encoding_rules,
+ .get_length = _get_length,
+ .get_next_type = _get_next_type,
+ .set_next_type = _set_next_type,
+ .get_type = _get_type,
+ .destroy = _destroy,
+ },
+ .get_identification = _get_identification,
+ .destroy = _destroy,
+ },
+ .next_payload = NO_PAYLOAD,
+ .payload_length = ID_PAYLOAD_HEADER_LENGTH,
+ .payload_type = payload_type,
+ );
+ return &this->public;
}
/*
* Described in header.
*/
-id_payload_t *id_payload_create_from_identification(payload_type_t payload_type, identification_t *identification)
+id_payload_t *id_payload_create_from_identification(payload_type_t payload_type,
+ identification_t *id)
{
- id_payload_t *this= id_payload_create(payload_type);
- this->set_data(this,identification->get_encoding(identification));
- this->set_id_type(this,identification->get_type(identification));
- return this;
+ private_id_payload_t *this;
+
+ this = (private_id_payload_t*)id_payload_create(payload_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;
}
diff --git a/src/libcharon/encoding/payloads/id_payload.h b/src/libcharon/encoding/payloads/id_payload.h
index 5502dc961..99831f85f 100644
--- a/src/libcharon/encoding/payloads/id_payload.h
+++ b/src/libcharon/encoding/payloads/id_payload.h
@@ -40,57 +40,15 @@ typedef struct id_payload_t id_payload_t;
* The ID payload format is described in RFC section 3.5.
*/
struct id_payload_t {
+
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
- * Set the ID type.
- *
- * @param type Type of ID
- */
- void (*set_id_type) (id_payload_t *this, id_type_t type);
-
- /**
- * Get the ID type.
- *
- * @return type of the ID
- */
- id_type_t (*get_id_type) (id_payload_t *this);
-
- /**
- * Set the ID data.
- *
- * Data are getting cloned.
- *
- * @param data ID data as chunk_t
- */
- void (*set_data) (id_payload_t *this, chunk_t data);
-
- /**
- * Get the ID data.
- *
- * Returned data are a copy of the internal one
- *
- * @return ID data as chunk_t
- */
- chunk_t (*get_data_clone) (id_payload_t *this);
-
- /**
- * Get the ID data.
- *
- * Returned data are NOT copied.
- *
- * @return ID data as chunk_t
- */
- chunk_t (*get_data) (id_payload_t *this);
-
- /**
* Creates an identification object of this id payload.
*
- * Returned object has to get destroyed by the caller.
- *
* @return identification_t object
*/
identification_t *(*get_identification) (id_payload_t *this);
diff --git a/src/libcharon/encoding/payloads/ike_header.c b/src/libcharon/encoding/payloads/ike_header.c
index 735f01304..80dcee0cb 100644
--- a/src/libcharon/encoding/payloads/ike_header.c
+++ b/src/libcharon/encoding/payloads/ike_header.c
@@ -84,6 +84,11 @@ struct private_ike_header_t {
} flags;
/**
+ * Reserved bits of IKE header
+ */
+ bool reserved[5];
+
+ /**
* Associated Message-ID.
*/
u_int32_t message_id;
@@ -119,30 +124,30 @@ encoding_rule_t ike_header_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 */
- { IKE_SPI, offsetof(private_ike_header_t, responder_spi) },
+ { IKE_SPI, offsetof(private_ike_header_t, responder_spi) },
/* 1 Byte next payload type, stored in the field next_payload */
- { U_INT_8, offsetof(private_ike_header_t, next_payload) },
+ { U_INT_8, offsetof(private_ike_header_t, next_payload) },
/* 4 Bit major version, stored in the field maj_version */
- { U_INT_4, offsetof(private_ike_header_t, maj_version) },
+ { U_INT_4, offsetof(private_ike_header_t, maj_version) },
/* 4 Bit minor version, stored in the field min_version */
- { U_INT_4, offsetof(private_ike_header_t, min_version) },
+ { U_INT_4, offsetof(private_ike_header_t, min_version) },
/* 8 Bit for the exchange type */
- { U_INT_8, offsetof(private_ike_header_t, exchange_type) },
- /* 2 Bit reserved bits, nowhere stored */
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
+ { U_INT_8, offsetof(private_ike_header_t, exchange_type) },
+ /* 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 */
- { 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, nowhere stored */
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
+ { 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]) },
/* 4 Byte message id, stored in the field message_id */
- { U_INT_32, offsetof(private_ike_header_t, 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) },
};
@@ -163,11 +168,8 @@ encoding_rule_t ike_header_encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
-
-/**
- * Implementation of payload_t.verify.
- */
-static status_t verify(private_ike_header_t *this)
+METHOD(payload_t, verify, status_t,
+ private_ike_header_t *this)
{
if ((this->exchange_type < IKE_SA_INIT) ||
((this->exchange_type > INFORMATIONAL)
@@ -179,7 +181,6 @@ static status_t verify(private_ike_header_t *this)
/* unsupported exchange type */
return FAILED;
}
-
if (this->initiator_spi == 0
#ifdef ME
/* we allow zero spi for INFORMATIONAL exchanges,
@@ -191,225 +192,201 @@ static status_t verify(private_ike_header_t *this)
/* initiator spi not set */
return FAILED;
}
+ return SUCCESS;
+}
- /* verification of version is not done in here */
+METHOD(payload_t, get_encoding_rules, void,
+ private_ike_header_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = ike_header_encodings;
+ *rule_count = sizeof(ike_header_encodings) / sizeof(encoding_rule_t);
+}
- return SUCCESS;
+METHOD(payload_t, get_type, payload_type_t,
+ private_ike_header_t *this)
+{
+ return HEADER;
}
-/**
- * Implementation of payload_t.set_next_type.
- */
-static void set_next_type(payload_t *this,payload_type_t type)
+METHOD(payload_t, get_next_type, payload_type_t,
+ private_ike_header_t *this)
{
- ((private_ike_header_t *)this)->next_payload = type;
+ return this->next_payload;
}
-/**
- * Implementation of ike_header_t.get_initiator_spi.
- */
-static u_int64_t get_initiator_spi(private_ike_header_t *this)
+
+METHOD(payload_t, set_next_type, void,
+ private_ike_header_t *this, payload_type_t type)
+{
+ this->next_payload = type;
+}
+
+METHOD(payload_t, get_length, size_t,
+ private_ike_header_t *this)
+{
+ return this->length;
+}
+
+METHOD(ike_header_t, get_initiator_spi, u_int64_t,
+ private_ike_header_t *this)
{
return this->initiator_spi;
}
-/**
- * Implementation of ike_header_t.set_initiator_spi.
- */
-static void set_initiator_spi(private_ike_header_t *this, u_int64_t initiator_spi)
+METHOD(ike_header_t, set_initiator_spi, void,
+ private_ike_header_t *this, u_int64_t initiator_spi)
{
this->initiator_spi = initiator_spi;
}
-/**
- * Implementation of ike_header_t.get_responder_spi.
- */
-static u_int64_t get_responder_spi(private_ike_header_t *this)
+METHOD(ike_header_t, get_responder_spi, u_int64_t,
+ private_ike_header_t *this)
{
return this->responder_spi;
}
-/**
- * Implementation of ike_header_t.set_responder_spi.
- */
-static void set_responder_spi(private_ike_header_t *this, u_int64_t responder_spi)
+METHOD(ike_header_t, set_responder_spi, void,
+ private_ike_header_t *this, u_int64_t responder_spi)
{
this->responder_spi = responder_spi;
}
-/**
- * Implementation of ike_header_t.get_maj_version.
- */
-static u_int8_t get_maj_version(private_ike_header_t *this)
+METHOD(ike_header_t, get_maj_version, u_int8_t,
+ private_ike_header_t *this)
{
return this->maj_version;
}
-/**
- * Implementation of ike_header_t.get_min_version.
- */
-static u_int8_t get_min_version(private_ike_header_t *this)
+METHOD(ike_header_t, set_maj_version, void,
+ private_ike_header_t *this, u_int8_t major)
+{
+ this->maj_version = major;
+}
+
+METHOD(ike_header_t, get_min_version, u_int8_t,
+ private_ike_header_t *this)
{
return this->min_version;
}
-/**
- * Implementation of ike_header_t.get_response_flag.
- */
-static bool get_response_flag(private_ike_header_t *this)
+METHOD(ike_header_t, set_min_version, void,
+ private_ike_header_t *this, u_int8_t minor)
+{
+ this->min_version = minor;
+}
+
+METHOD(ike_header_t, get_response_flag, bool,
+ private_ike_header_t *this)
{
return this->flags.response;
}
-/**
- * Implementation of ike_header_t.set_response_flag.
- */
-static void set_response_flag(private_ike_header_t *this, bool response)
+METHOD(ike_header_t, set_response_flag, void,
+ private_ike_header_t *this, bool response)
{
this->flags.response = response;
}
-/**
- * Implementation of ike_header_t.get_version_flag.
- */
-static bool get_version_flag(private_ike_header_t *this)
+METHOD(ike_header_t, get_version_flag, bool,
+ private_ike_header_t *this)
{
return this->flags.version;
}
-/**
- * Implementation of ike_header_t.get_initiator_flag.
- */
-static bool get_initiator_flag(private_ike_header_t *this)
+METHOD(ike_header_t, set_version_flag, void,
+ private_ike_header_t *this, bool version)
+{
+ this->flags.version = version;
+}
+
+METHOD(ike_header_t, get_initiator_flag, bool,
+ private_ike_header_t *this)
{
return this->flags.initiator;
}
-/**
- * Implementation of ike_header_t.set_initiator_flag.
- */
-static void set_initiator_flag(private_ike_header_t *this, bool initiator)
+METHOD(ike_header_t, set_initiator_flag, void,
+ private_ike_header_t *this, bool initiator)
{
this->flags.initiator = initiator;
}
-/**
- * Implementation of ike_header_t.get_exchange_type.
- */
-static u_int8_t get_exchange_type(private_ike_header_t *this)
+METHOD(ike_header_t, get_exchange_type, u_int8_t,
+ private_ike_header_t *this)
{
return this->exchange_type;
}
-/**
- * Implementation of ike_header_t.set_exchange_type.
- */
-static void set_exchange_type(private_ike_header_t *this, u_int8_t exchange_type)
+METHOD(ike_header_t, set_exchange_type, void,
+ private_ike_header_t *this, u_int8_t exchange_type)
{
this->exchange_type = exchange_type;
}
-/**
- * Implements ike_header_t's get_message_id function.
- * See #ike_header_t.get_message_id for description.
- */
-static u_int32_t get_message_id(private_ike_header_t *this)
+METHOD(ike_header_t, get_message_id, u_int32_t,
+ private_ike_header_t *this)
{
return this->message_id;
}
-/**
- * Implementation of ike_header_t.set_message_id.
- */
-static void set_message_id(private_ike_header_t *this, u_int32_t message_id)
+METHOD(ike_header_t, set_message_id, void,
+ private_ike_header_t *this, u_int32_t message_id)
{
this->message_id = message_id;
}
-/**
- * Implementation of ike_header_t.destroy and payload_t.destroy.
- */
-static void destroy(ike_header_t *this)
+METHOD2(payload_t, ike_header_t, destroy, void,
+ private_ike_header_t *this)
{
free(this);
}
-/**
- * Implementation of payload_t.get_encoding_rules.
- */
-static void get_encoding_rules(payload_t *this, encoding_rule_t **rules, size_t *rule_count)
-{
- *rules = ike_header_encodings;
- *rule_count = sizeof(ike_header_encodings) / sizeof(encoding_rule_t);
-}
-
-/**
- * Implementation of payload_t.get_type.
- */
-static payload_type_t get_type(payload_t *this)
-{
- return HEADER;
-}
-
-/**
- * Implementation of payload_t.get_next_type.
- */
-static payload_type_t get_next_type(payload_t *this)
-{
- return (((private_ike_header_t*)this)->next_payload);
-}
-
-/**
- * Implementation of payload_t.get_length.
- */
-static size_t get_length(payload_t *this)
-{
- return (((private_ike_header_t*)this)->length);
-}
-
/*
* Described in header.
*/
ike_header_t *ike_header_create()
{
- private_ike_header_t *this = malloc_thing(private_ike_header_t);
-
- this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
- this->public.payload_interface.get_encoding_rules = get_encoding_rules;
- this->public.payload_interface.get_length = get_length;
- this->public.payload_interface.get_next_type = get_next_type;
- this->public.payload_interface.set_next_type = set_next_type;
- this->public.payload_interface.get_type = get_type;
- this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
- this->public.destroy = destroy;
-
- this->public.get_initiator_spi = (u_int64_t (*) (ike_header_t*))get_initiator_spi;
- this->public.set_initiator_spi = (void (*) (ike_header_t*,u_int64_t))set_initiator_spi;
- this->public.get_responder_spi = (u_int64_t (*) (ike_header_t*))get_responder_spi;
- this->public.set_responder_spi = (void (*) (ike_header_t *,u_int64_t))set_responder_spi;
- this->public.get_maj_version = (u_int8_t (*) (ike_header_t*))get_maj_version;
- this->public.get_min_version = (u_int8_t (*) (ike_header_t*))get_min_version;
- this->public.get_response_flag = (bool (*) (ike_header_t*))get_response_flag;
- this->public.set_response_flag = (void (*) (ike_header_t*,bool))set_response_flag;
- this->public.get_version_flag = (bool (*) (ike_header_t*))get_version_flag;
- this->public.get_initiator_flag = (bool (*) (ike_header_t*))get_initiator_flag;
- this->public.set_initiator_flag = (void (*) (ike_header_t*,bool))set_initiator_flag;
- this->public.get_exchange_type = (u_int8_t (*) (ike_header_t*))get_exchange_type;
- this->public.set_exchange_type = (void (*) (ike_header_t*,u_int8_t))set_exchange_type;
- this->public.get_message_id = (u_int32_t (*) (ike_header_t*))get_message_id;
- this->public.set_message_id = (void (*) (ike_header_t*,u_int32_t))set_message_id;
-
- /* set default values of the fields */
- this->initiator_spi = 0;
- this->responder_spi = 0;
- this->next_payload = 0;
- this->maj_version = IKE_MAJOR_VERSION;
- this->min_version = IKE_MINOR_VERSION;
- this->exchange_type = EXCHANGE_TYPE_UNDEFINED;
- this->flags.initiator = TRUE;
- this->flags.version = HIGHER_VERSION_SUPPORTED_FLAG;
- this->flags.response = FALSE;
- this->message_id = 0;
- this->length = IKE_HEADER_LENGTH;
-
- return (ike_header_t*)this;
+ private_ike_header_t *this;
+
+ INIT(this,
+ .public = {
+ .payload_interface = {
+ .verify = _verify,
+ .get_encoding_rules = _get_encoding_rules,
+ .get_length = _get_length,
+ .get_next_type = _get_next_type,
+ .set_next_type = _set_next_type,
+ .get_type = _get_type,
+ .destroy = _destroy,
+ },
+ .get_initiator_spi = _get_initiator_spi,
+ .set_initiator_spi = _set_initiator_spi,
+ .get_responder_spi = _get_responder_spi,
+ .set_responder_spi = _set_responder_spi,
+ .get_maj_version = _get_maj_version,
+ .set_maj_version = _set_maj_version,
+ .get_min_version = _get_min_version,
+ .set_min_version = _set_min_version,
+ .get_response_flag = _get_response_flag,
+ .set_response_flag = _set_response_flag,
+ .get_version_flag = _get_version_flag,
+ .set_version_flag = _set_version_flag,
+ .get_initiator_flag = _get_initiator_flag,
+ .set_initiator_flag = _set_initiator_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,
+ );
+
+ return &this->public;
}
diff --git a/src/libcharon/encoding/payloads/ike_header.h b/src/libcharon/encoding/payloads/ike_header.h
index e63e8bf06..f52c852c5 100644
--- a/src/libcharon/encoding/payloads/ike_header.h
+++ b/src/libcharon/encoding/payloads/ike_header.h
@@ -143,6 +143,13 @@ struct ike_header_t {
u_int8_t (*get_maj_version) (ike_header_t *this);
/**
+ * Set the major version.
+ *
+ * @param major major version
+ */
+ void (*set_maj_version) (ike_header_t *this, u_int8_t major);
+
+ /**
* Get the minor version.
*
* @return minor version
@@ -150,6 +157,13 @@ struct ike_header_t {
u_int8_t (*get_min_version) (ike_header_t *this);
/**
+ * Set the minor version.
+ *
+ * @param minor minor version
+ */
+ void (*set_min_version) (ike_header_t *this, u_int8_t minor);
+
+ /**
* Get the response flag.
*
* @return response flag
@@ -162,6 +176,7 @@ struct ike_header_t {
* @param response response flag
*/
void (*set_response_flag) (ike_header_t *this, bool response);
+
/**
* Get "higher version supported"-flag.
*
@@ -170,6 +185,13 @@ struct ike_header_t {
bool (*get_version_flag) (ike_header_t *this);
/**
+ * Set the "higher version supported"-flag.
+ *
+ * @param version flag value
+ */
+ void (*set_version_flag)(ike_header_t *this, bool version);
+
+ /**
* Get the initiator flag.
*
* @return initiator flag
diff --git a/src/libcharon/encoding/payloads/ke_payload.c b/src/libcharon/encoding/payloads/ke_payload.c
index 1bc79f084..999d73192 100644
--- a/src/libcharon/encoding/payloads/ke_payload.c
+++ b/src/libcharon/encoding/payloads/ke_payload.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005-2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -20,14 +21,13 @@
#include <encoding/payloads/encodings.h>
-
typedef struct private_ke_payload_t private_ke_payload_t;
/**
* Private data of an ke_payload_t object.
- *
*/
struct private_ke_payload_t {
+
/**
* Public ke_payload_t interface.
*/
@@ -44,6 +44,16 @@ struct private_ke_payload_t {
bool critical;
/**
+ * Reserved bits
+ */
+ bool reserved_bit[7];
+
+ /**
+ * Reserved bytes
+ */
+ u_int8_t reserved_byte[2];
+
+ /**
* Length of this payload.
*/
u_int16_t payload_length;
@@ -64,27 +74,27 @@ struct private_ke_payload_t {
*
* The defined offsets are the positions in a object of type
* private_ke_payload_t.
- *
*/
encoding_rule_t ke_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
- { U_INT_8, offsetof(private_ke_payload_t, next_payload) },
+ { U_INT_8, offsetof(private_ke_payload_t, next_payload) },
/* the critical bit */
- { FLAG, offsetof(private_ke_payload_t, critical) },
- /* 7 Bit reserved bits, nowhere stored */
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
+ { FLAG, offsetof(private_ke_payload_t, critical) },
+ /* 7 Bit reserved bits */
+ { RESERVED_BIT, offsetof(private_ke_payload_t, reserved_bit[0]) },
+ { RESERVED_BIT, offsetof(private_ke_payload_t, reserved_bit[1]) },
+ { RESERVED_BIT, offsetof(private_ke_payload_t, reserved_bit[2]) },
+ { RESERVED_BIT, offsetof(private_ke_payload_t, reserved_bit[3]) },
+ { RESERVED_BIT, offsetof(private_ke_payload_t, reserved_bit[4]) },
+ { RESERVED_BIT, offsetof(private_ke_payload_t, reserved_bit[5]) },
+ { RESERVED_BIT, offsetof(private_ke_payload_t, reserved_bit[6]) },
/* Length of the whole payload*/
- { PAYLOAD_LENGTH, offsetof(private_ke_payload_t, payload_length) },
+ { PAYLOAD_LENGTH, offsetof(private_ke_payload_t, payload_length) },
/* DH Group number as 16 bit field*/
- { U_INT_16, offsetof(private_ke_payload_t, dh_group_number) },
- { RESERVED_BYTE, 0 },
- { RESERVED_BYTE, 0 },
+ { U_INT_16, offsetof(private_ke_payload_t, dh_group_number) },
+ /* 2 reserved bytes */
+ { 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)}
};
@@ -103,123 +113,60 @@ encoding_rule_t ke_payload_encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
-/**
- * Implementation of payload_t.verify.
- */
-static status_t verify(private_ke_payload_t *this)
+METHOD(payload_t, verify, status_t,
+ private_ke_payload_t *this)
{
- /* dh group is not verified in here */
return SUCCESS;
}
-/**
- * Implementation of payload_t.destroy.
- */
-static void destroy(private_ke_payload_t *this)
-{
- if (this->key_exchange_data.ptr != NULL)
- {
- free(this->key_exchange_data.ptr);
- }
- free(this);
-}
-
-/**
- * Implementation of payload_t.get_encoding_rules.
- */
-static void get_encoding_rules(private_ke_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, void,
+ private_ke_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = ke_payload_encodings;
- *rule_count = sizeof(ke_payload_encodings) / sizeof(encoding_rule_t);
+ *rule_count = countof(ke_payload_encodings);
}
-/**
- * Implementation of payload_t.get_type.
- */
-static payload_type_t get_type(private_ke_payload_t *this)
+METHOD(payload_t, get_type, payload_type_t,
+ private_ke_payload_t *this)
{
return KEY_EXCHANGE;
}
-/**
- * Implementation of payload_t.get_next_type.
- */
-static payload_type_t get_next_type(private_ke_payload_t *this)
+METHOD(payload_t, get_next_type, payload_type_t,
+ private_ke_payload_t *this)
{
- return (this->next_payload);
+ return this->next_payload;
}
-/**
- * Implementation of payload_t.set_next_type.
- */
-static void set_next_type(private_ke_payload_t *this,payload_type_t type)
+METHOD(payload_t, set_next_type, void,
+ private_ke_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
-/**
- * recompute the length of the payload.
- */
-static void compute_length(private_ke_payload_t *this)
-{
- size_t length = KE_PAYLOAD_HEADER_LENGTH;
- if (this->key_exchange_data.ptr != NULL)
- {
- length += this->key_exchange_data.len;
- }
- this->payload_length = length;
-}
-
-/**
- * Implementation of payload_t.get_length.
- */
-static size_t get_length(private_ke_payload_t *this)
+METHOD(payload_t, get_length, size_t,
+ private_ke_payload_t *this)
{
- compute_length(this);
return this->payload_length;
}
-/**
- * Implementation of ke_payload_t.get_key_exchange_data.
- */
-static chunk_t get_key_exchange_data(private_ke_payload_t *this)
+METHOD(ke_payload_t, get_key_exchange_data, chunk_t,
+ private_ke_payload_t *this)
{
- return (this->key_exchange_data);
+ return this->key_exchange_data;
}
-/**
- * Implementation of ke_payload_t.set_key_exchange_data.
- */
-static void set_key_exchange_data(private_ke_payload_t *this, chunk_t key_exchange_data)
-{
- /* destroy existing data first */
- if (this->key_exchange_data.ptr != NULL)
- {
- /* free existing value */
- free(this->key_exchange_data.ptr);
- this->key_exchange_data.ptr = NULL;
- this->key_exchange_data.len = 0;
-
- }
-
- this->key_exchange_data = chunk_clone(key_exchange_data);
- compute_length(this);
-}
-
-/**
- * Implementation of ke_payload_t.get_dh_group_number.
- */
-static diffie_hellman_group_t get_dh_group_number(private_ke_payload_t *this)
+METHOD(ke_payload_t, get_dh_group_number, diffie_hellman_group_t,
+ private_ke_payload_t *this)
{
return this->dh_group_number;
}
-/**
- * Implementation of ke_payload_t.set_dh_group_number.
- */
-static void set_dh_group_number(private_ke_payload_t *this, diffie_hellman_group_t dh_group_number)
+METHOD2(payload_t, ke_payload_t, destroy, void,
+ private_ke_payload_t *this)
{
- this->dh_group_number = dh_group_number;
+ free(this->key_exchange_data.ptr);
+ free(this);
}
/*
@@ -227,31 +174,27 @@ static void set_dh_group_number(private_ke_payload_t *this, diffie_hellman_group
*/
ke_payload_t *ke_payload_create()
{
- private_ke_payload_t *this = malloc_thing(private_ke_payload_t);
-
- /* interface functions */
- this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
- this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
- this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
- this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
- this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
- this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
- this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
-
- /* public functions */
- this->public.get_key_exchange_data = (chunk_t (*) (ke_payload_t *)) get_key_exchange_data;
- this->public.set_key_exchange_data = (void (*) (ke_payload_t *,chunk_t)) set_key_exchange_data;
- this->public.get_dh_group_number = (diffie_hellman_group_t (*) (ke_payload_t *)) get_dh_group_number;
- this->public.set_dh_group_number =(void (*) (ke_payload_t *,diffie_hellman_group_t)) set_dh_group_number;
- this->public.destroy = (void (*) (ke_payload_t *)) destroy;
-
- /* set default values of the fields */
- this->critical = FALSE;
- this->next_payload = NO_PAYLOAD;
- this->payload_length = KE_PAYLOAD_HEADER_LENGTH;
- this->key_exchange_data = chunk_empty;
- this->dh_group_number = MODP_NONE;
-
+ private_ke_payload_t *this;
+
+ INIT(this,
+ .public = {
+ .payload_interface = {
+ .verify = _verify,
+ .get_encoding_rules = _get_encoding_rules,
+ .get_length = _get_length,
+ .get_next_type = _get_next_type,
+ .set_next_type = _set_next_type,
+ .get_type = _get_type,
+ .destroy = _destroy,
+ },
+ .get_key_exchange_data = _get_key_exchange_data,
+ .get_dh_group_number = _get_dh_group_number,
+ .destroy = _destroy,
+ },
+ .next_payload = NO_PAYLOAD,
+ .payload_length = KE_PAYLOAD_HEADER_LENGTH,
+ .dh_group_number = MODP_NONE,
+ );
return &this->public;
}
@@ -264,7 +207,7 @@ ke_payload_t *ke_payload_create_from_diffie_hellman(diffie_hellman_t *dh)
dh->get_my_public_value(dh, &this->key_exchange_data);
this->dh_group_number = dh->get_dh_group(dh);
- compute_length(this);
+ this->payload_length = this->key_exchange_data.len + KE_PAYLOAD_HEADER_LENGTH;
return &this->public;
}
diff --git a/src/libcharon/encoding/payloads/ke_payload.h b/src/libcharon/encoding/payloads/ke_payload.h
index 3ca05009e..65cc11883 100644
--- a/src/libcharon/encoding/payloads/ke_payload.h
+++ b/src/libcharon/encoding/payloads/ke_payload.h
@@ -47,24 +47,13 @@ struct ke_payload_t {
payload_t payload_interface;
/**
- * Returns the currently set key exchange data of this KE payload.
+ * Returns the key exchange data of this KE payload.
*
- * @warning Returned data are not copied.
- *
- * @return chunk_t pointing to the value
+ * @return chunk_t pointing to internal data
*/
chunk_t (*get_key_exchange_data) (ke_payload_t *this);
/**
- * Sets the key exchange data of this KE payload.
- *
- * Value is getting copied.
- *
- * @param key_exchange_data chunk_t pointing to the value to set
- */
- void (*set_key_exchange_data) (ke_payload_t *this, chunk_t key_exchange_data);
-
- /**
* Gets the Diffie-Hellman Group Number of this KE payload.
*
* @return DH Group Number of this payload
@@ -72,14 +61,6 @@ struct ke_payload_t {
diffie_hellman_group_t (*get_dh_group_number) (ke_payload_t *this);
/**
- * Sets the Diffie-Hellman Group Number of this KE payload.
- *
- * @param dh_group_number DH Group to set
- */
- void (*set_dh_group_number) (ke_payload_t *this,
- diffie_hellman_group_t dh_group_number);
-
- /**
* Destroys an ke_payload_t object.
*/
void (*destroy) (ke_payload_t *this);
diff --git a/src/libcharon/encoding/payloads/nonce_payload.c b/src/libcharon/encoding/payloads/nonce_payload.c
index 4ad5ce9dd..78000b8c6 100644
--- a/src/libcharon/encoding/payloads/nonce_payload.c
+++ b/src/libcharon/encoding/payloads/nonce_payload.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005-2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -14,21 +15,19 @@
* for more details.
*/
-/* offsetof macro */
#include <stddef.h>
#include "nonce_payload.h"
#include <encoding/payloads/encodings.h>
-
typedef struct private_nonce_payload_t private_nonce_payload_t;
/**
* Private data of an nonce_payload_t object.
- *
*/
struct private_nonce_payload_t {
+
/**
* Public nonce_payload_t interface.
*/
@@ -45,6 +44,11 @@ struct private_nonce_payload_t {
bool critical;
/**
+ * Reserved bits
+ */
+ bool reserved[7];
+
+ /**
* Length of this payload.
*/
u_int16_t payload_length;
@@ -60,25 +64,24 @@ 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[] = {
/* 1 Byte next payload type, stored in the field next_payload */
- { U_INT_8, offsetof(private_nonce_payload_t, next_payload) },
+ { U_INT_8, offsetof(private_nonce_payload_t, next_payload) },
/* the critical bit */
- { FLAG, offsetof(private_nonce_payload_t, critical) },
- /* 7 Bit reserved bits, nowhere stored */
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
+ { FLAG, offsetof(private_nonce_payload_t, critical) },
+ /* 7 Bit reserved bits */
+ { RESERVED_BIT, offsetof(private_nonce_payload_t, reserved[0]) },
+ { RESERVED_BIT, offsetof(private_nonce_payload_t, reserved[1]) },
+ { RESERVED_BIT, offsetof(private_nonce_payload_t, reserved[2]) },
+ { RESERVED_BIT, offsetof(private_nonce_payload_t, reserved[3]) },
+ { RESERVED_BIT, offsetof(private_nonce_payload_t, reserved[4]) },
+ { RESERVED_BIT, offsetof(private_nonce_payload_t, reserved[5]) },
+ { RESERVED_BIT, offsetof(private_nonce_payload_t, reserved[6]) },
/* Length of the whole nonce payload*/
- { PAYLOAD_LENGTH, offsetof(private_nonce_payload_t, payload_length) },
+ { 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) }
+ { NONCE_DATA, offsetof(private_nonce_payload_t, nonce) },
};
/* 1 2 3
@@ -92,102 +95,64 @@ encoding_rule_t nonce_payload_encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
-/**
- * Implementation of payload_t.verify.
- */
-static status_t verify(private_nonce_payload_t *this)
+METHOD(payload_t, verify, status_t,
+ private_nonce_payload_t *this)
{
- if ((this->nonce.len < 16) || ((this->nonce.len > 256)))
+ if (this->nonce.len < 16 || this->nonce.len > 256)
{
- /* nonce length is wrong */
return FAILED;
}
-
return SUCCESS;
}
-/**
- * Implementation of nonce_payload_t.set_nonce.
- */
-static status_t set_nonce(private_nonce_payload_t *this, chunk_t nonce)
-{
- this->nonce.ptr = clalloc(nonce.ptr, nonce.len);
- this->nonce.len = nonce.len;
- this->payload_length = NONCE_PAYLOAD_HEADER_LENGTH + nonce.len;
- return SUCCESS;
-}
-
-/**
- * Implementation of nonce_payload_t.get_nonce.
- */
-static chunk_t get_nonce(private_nonce_payload_t *this)
-{
- chunk_t nonce;
- nonce.ptr = clalloc(this->nonce.ptr,this->nonce.len);
- nonce.len = this->nonce.len;
- return nonce;
-}
-
-/**
- * Implementation of nonce_payload_t.get_encoding_rules.
- */
-static void get_encoding_rules(private_nonce_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, void,
+ private_nonce_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = nonce_payload_encodings;
- *rule_count = sizeof(nonce_payload_encodings) / sizeof(encoding_rule_t);
+ *rule_count = countof(nonce_payload_encodings);
}
-/**
- * Implementation of payload_t.get_type.
- */
-static payload_type_t get_type(private_nonce_payload_t *this)
+METHOD(payload_t, get_type, payload_type_t,
+ private_nonce_payload_t *this)
{
return NONCE;
}
-/**
- * Implementation of payload_t.get_next_type.
- */
-static payload_type_t get_next_type(private_nonce_payload_t *this)
+METHOD(payload_t, get_next_type, payload_type_t,
+ private_nonce_payload_t *this)
{
- return (this->next_payload);
+ return this->next_payload;
}
-/**
- * Implementation of payload_t.set_next_type.
- */
-static void set_next_type(private_nonce_payload_t *this,payload_type_t type)
+METHOD(payload_t, set_next_type, void,
+ private_nonce_payload_t *this, payload_type_t type)
{
this->next_payload = type;
}
-/**
- * recompute the length of the payload.
- */
-static void compute_length(private_nonce_payload_t *this)
+METHOD(payload_t, get_length, size_t,
+ private_nonce_payload_t *this)
{
- this->payload_length = NONCE_PAYLOAD_HEADER_LENGTH + this->nonce.len;
+ return this->payload_length;
}
-/**
- * Implementation of payload_t.get_length.
- */
-static size_t get_length(private_nonce_payload_t *this)
+METHOD(nonce_payload_t, set_nonce, void,
+ private_nonce_payload_t *this, chunk_t nonce)
{
- compute_length(this);
- return this->payload_length;
+ this->nonce = chunk_clone(nonce);
+ this->payload_length = NONCE_PAYLOAD_HEADER_LENGTH + nonce.len;
}
-/**
- * Implementation of payload_t.destroy and nonce_payload_t.destroy.
- */
-static void destroy(private_nonce_payload_t *this)
+METHOD(nonce_payload_t, get_nonce, chunk_t,
+ private_nonce_payload_t *this)
{
- if (this->nonce.ptr != NULL)
- {
- free(this->nonce.ptr);
- }
+ return chunk_clone(this->nonce);
+}
+METHOD2(payload_t, nonce_payload_t, destroy, void,
+ private_nonce_payload_t *this)
+{
+ free(this->nonce.ptr);
free(this);
}
@@ -196,30 +161,25 @@ static void destroy(private_nonce_payload_t *this)
*/
nonce_payload_t *nonce_payload_create()
{
- private_nonce_payload_t *this = malloc_thing(private_nonce_payload_t);
-
- /* interface functions */
- this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
- this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
- this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
- this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
- this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
- this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
- this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
-
- /* public functions */
- this->public.destroy = (void (*) (nonce_payload_t *)) destroy;
- this->public.set_nonce = (void (*) (nonce_payload_t *,chunk_t)) set_nonce;
- this->public.get_nonce = (chunk_t (*) (nonce_payload_t *)) get_nonce;
-
- /* private variables */
- this->critical = FALSE;
- this->next_payload = NO_PAYLOAD;
- this->payload_length = NONCE_PAYLOAD_HEADER_LENGTH;
- this->nonce.ptr = NULL;
- this->nonce.len = 0;
-
- return (&(this->public));
+ private_nonce_payload_t *this;
+
+ INIT(this,
+ .public = {
+ .payload_interface = {
+ .verify = _verify,
+ .get_encoding_rules = _get_encoding_rules,
+ .get_length = _get_length,
+ .get_next_type = _get_next_type,
+ .set_next_type = _set_next_type,
+ .get_type = _get_type,
+ .destroy = _destroy,
+ },
+ .set_nonce = _set_nonce,
+ .get_nonce = _get_nonce,
+ .destroy = _destroy,
+ },
+ .next_payload = NO_PAYLOAD,
+ .payload_length = NONCE_PAYLOAD_HEADER_LENGTH,
+ );
+ return &this->public;
}
-
-
diff --git a/src/libcharon/encoding/payloads/notify_payload.c b/src/libcharon/encoding/payloads/notify_payload.c
index a56fd1869..77f15ec6d 100644
--- a/src/libcharon/encoding/payloads/notify_payload.c
+++ b/src/libcharon/encoding/payloads/notify_payload.c
@@ -1,7 +1,8 @@
/*
+ * Copyright (C) 2005-2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
* Copyright (C) 2006-2008 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
- * Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -186,9 +187,9 @@ typedef struct private_notify_payload_t private_notify_payload_t;
/**
* Private data of an notify_payload_t object.
- *
*/
struct private_notify_payload_t {
+
/**
* Public notify_payload_t interface.
*/
@@ -205,6 +206,11 @@ struct private_notify_payload_t {
bool critical;
/**
+ * reserved bits
+ */
+ bool reserved[7];
+
+ /**
* Length of this payload.
*/
u_int16_t payload_length;
@@ -240,7 +246,6 @@ struct private_notify_payload_t {
*
* The defined offsets are the positions in a object of type
* private_notify_payload_t.
- *
*/
encoding_rule_t notify_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
@@ -248,13 +253,13 @@ encoding_rule_t notify_payload_encodings[] = {
/* the critical bit */
{ FLAG, offsetof(private_notify_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
+ { 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) },
/* Protocol ID as 8 bit field*/
@@ -262,11 +267,11 @@ encoding_rule_t notify_payload_encodings[] = {
/* 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) },
+ { 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 */
- { NOTIFICATION_DATA, offsetof(private_notify_payload_t, notification_data) }
+ { NOTIFICATION_DATA,offsetof(private_notify_payload_t, notification_data) }
};
/*
@@ -287,10 +292,8 @@ encoding_rule_t notify_payload_encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
-/**
- * Implementation of payload_t.verify.
- */
-static status_t verify(private_notify_payload_t *this)
+METHOD(payload_t, verify, status_t,
+ private_notify_payload_t *this)
{
bool bad_length = FALSE;
@@ -404,35 +407,27 @@ static status_t verify(private_notify_payload_t *this)
return SUCCESS;
}
-/**
- * Implementation of payload_t.get_encoding_rules.
- */
-static void get_encoding_rules(private_notify_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, void,
+ private_notify_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = notify_payload_encodings;
- *rule_count = sizeof(notify_payload_encodings) / sizeof(encoding_rule_t);
+ *rule_count = countof(notify_payload_encodings);
}
-/**
- * Implementation of payload_t.get_type.
- */
-static payload_type_t get_type(private_notify_payload_t *this)
+METHOD(payload_t, get_type, payload_type_t,
+ private_notify_payload_t *this)
{
return NOTIFY;
}
-/**
- * Implementation of payload_t.get_next_type.
- */
-static payload_type_t get_next_type(private_notify_payload_t *this)
+METHOD(payload_t, get_next_type, payload_type_t,
+ private_notify_payload_t *this)
{
- return (this->next_payload);
+ return this->next_payload;
}
-/**
- * Implementation of payload_t.set_next_type.
- */
-static void set_next_type(private_notify_payload_t *this,payload_type_t type)
+METHOD(payload_t, set_next_type, void,
+ private_notify_payload_t *this, payload_type_t type)
{
this->next_payload = type;
}
@@ -443,6 +438,7 @@ static void set_next_type(private_notify_payload_t *this,payload_type_t type)
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;
@@ -454,51 +450,38 @@ static void compute_length (private_notify_payload_t *this)
this->payload_length = length;
}
-/**
- * Implementation of payload_t.get_length.
- */
-static size_t get_length(private_notify_payload_t *this)
+METHOD(payload_t, get_length, size_t,
+ private_notify_payload_t *this)
{
- compute_length(this);
return this->payload_length;
}
-/**
- * Implementation of notify_payload_t.get_protocol_id.
- */
-static u_int8_t get_protocol_id(private_notify_payload_t *this)
+METHOD(notify_payload_t, get_protocol_id, u_int8_t,
+ private_notify_payload_t *this)
{
return this->protocol_id;
}
-/**
- * Implementation of notify_payload_t.set_protocol_id.
- */
-static void set_protocol_id(private_notify_payload_t *this, u_int8_t protocol_id)
+METHOD(notify_payload_t, set_protocol_id, void,
+ private_notify_payload_t *this, u_int8_t protocol_id)
{
this->protocol_id = protocol_id;
}
-/**
- * Implementation of notify_payload_t.get_notify_type.
- */
-static notify_type_t get_notify_type(private_notify_payload_t *this)
+METHOD(notify_payload_t, get_notify_type, notify_type_t,
+ private_notify_payload_t *this)
{
return this->notify_type;
}
-/**
- * Implementation of notify_payload_t.set_notify_type.
- */
-static void set_notify_type(private_notify_payload_t *this, u_int16_t notify_type)
+METHOD(notify_payload_t, set_notify_type, void,
+ private_notify_payload_t *this, notify_type_t notify_type)
{
this->notify_type = notify_type;
}
-/**
- * Implementation of notify_payload_t.get_spi.
- */
-static u_int32_t get_spi(private_notify_payload_t *this)
+METHOD(notify_payload_t, get_spi, u_int32_t,
+ private_notify_payload_t *this)
{
switch (this->protocol_id)
{
@@ -514,10 +497,8 @@ static u_int32_t get_spi(private_notify_payload_t *this)
return 0;
}
-/**
- * Implementation of notify_payload_t.set_spi.
- */
-static void set_spi(private_notify_payload_t *this, u_int32_t spi)
+METHOD(notify_payload_t, set_spi, void,
+ private_notify_payload_t *this, u_int32_t spi)
{
chunk_free(&this->spi);
switch (this->protocol_id)
@@ -534,37 +515,26 @@ static void set_spi(private_notify_payload_t *this, u_int32_t spi)
compute_length(this);
}
-/**
- * Implementation of notify_payload_t.get_notification_data.
- */
-static chunk_t get_notification_data(private_notify_payload_t *this)
+METHOD(notify_payload_t, get_notification_data, chunk_t,
+ private_notify_payload_t *this)
{
- return (this->notification_data);
+ return this->notification_data;
}
-/**
- * Implementation of notify_payload_t.set_notification_data.
- */
-static status_t set_notification_data(private_notify_payload_t *this, chunk_t notification_data)
+METHOD(notify_payload_t, set_notification_data, void,
+ private_notify_payload_t *this, chunk_t data)
{
- chunk_free(&this->notification_data);
- if (notification_data.len > 0)
- {
- this->notification_data = chunk_clone(notification_data);
- }
+ free(this->notification_data.ptr);
+ this->notification_data = chunk_clone(data);
compute_length(this);
- return SUCCESS;
}
-/**
- * Implementation of notify_payload_t.destroy and notify_payload_t.destroy.
- */
-static status_t destroy(private_notify_payload_t *this)
+METHOD2(payload_t, notify_payload_t, destroy, void,
+ private_notify_payload_t *this)
{
- chunk_free(&this->notification_data);
- chunk_free(&this->spi);
+ free(this->notification_data.ptr);
+ free(this->spi.ptr);
free(this);
- return SUCCESS;
}
/*
@@ -572,52 +542,45 @@ static status_t destroy(private_notify_payload_t *this)
*/
notify_payload_t *notify_payload_create()
{
- private_notify_payload_t *this = malloc_thing(private_notify_payload_t);
-
- /* interface functions */
- this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
- this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
- this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
- this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
- this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
- this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
- this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
-
- /* public functions */
- this->public.get_protocol_id = (u_int8_t (*) (notify_payload_t *)) get_protocol_id;
- this->public.set_protocol_id = (void (*) (notify_payload_t *,u_int8_t)) set_protocol_id;
- this->public.get_notify_type = (notify_type_t (*) (notify_payload_t *)) get_notify_type;
- this->public.set_notify_type = (void (*) (notify_payload_t *,notify_type_t)) set_notify_type;
- this->public.get_spi = (u_int32_t (*) (notify_payload_t *)) get_spi;
- this->public.set_spi = (void (*) (notify_payload_t *,u_int32_t)) set_spi;
- this->public.get_notification_data = (chunk_t (*) (notify_payload_t *)) get_notification_data;
- this->public.set_notification_data = (void (*) (notify_payload_t *,chunk_t)) set_notification_data;
- this->public.destroy = (void (*) (notify_payload_t *)) destroy;
-
- /* set default values of the fields */
- this->critical = FALSE;
- this->next_payload = NO_PAYLOAD;
- this->payload_length = NOTIFY_PAYLOAD_HEADER_LENGTH;
- this->protocol_id = 0;
- this->notify_type = 0;
- this->spi.ptr = NULL;
- this->spi.len = 0;
- this->spi_size = 0;
- this->notification_data.ptr = NULL;
- this->notification_data.len = 0;
-
+ private_notify_payload_t *this;
+
+ INIT(this,
+ .public = {
+ .payload_interface = {
+ .verify = _verify,
+ .get_encoding_rules = _get_encoding_rules,
+ .get_length = _get_length,
+ .get_next_type = _get_next_type,
+ .set_next_type = _set_next_type,
+ .get_type = _get_type,
+ .destroy = _destroy,
+ },
+ .get_protocol_id = _get_protocol_id,
+ .set_protocol_id = _set_protocol_id,
+ .get_notify_type = _get_notify_type,
+ .set_notify_type = _set_notify_type,
+ .get_spi = _get_spi,
+ .set_spi = _set_spi,
+ .get_notification_data = _get_notification_data,
+ .set_notification_data = _set_notification_data,
+ .destroy = _destroy,
+ },
+ .next_payload = NO_PAYLOAD,
+ .payload_length = NOTIFY_PAYLOAD_HEADER_LENGTH,
+ );
return &this->public;
}
/*
* Described in header.
*/
-notify_payload_t *notify_payload_create_from_protocol_and_type(protocol_id_t protocol_id, notify_type_t notify_type)
+notify_payload_t *notify_payload_create_from_protocol_and_type(
+ protocol_id_t protocol_id, notify_type_t notify_type)
{
notify_payload_t *notify = notify_payload_create();
- notify->set_notify_type(notify,notify_type);
- notify->set_protocol_id(notify,protocol_id);
+ notify->set_notify_type(notify, notify_type);
+ notify->set_protocol_id(notify, protocol_id);
return notify;
}
diff --git a/src/libcharon/encoding/payloads/payload.c b/src/libcharon/encoding/payloads/payload.c
index 1cee6d2aa..d1e677db7 100644
--- a/src/libcharon/encoding/payloads/payload.c
+++ b/src/libcharon/encoding/payloads/payload.c
@@ -59,25 +59,23 @@ ENUM_NEXT(payload_type_names, SECURITY_ASSOCIATION, EXTENSIBLE_AUTHENTICATION, N
#ifdef ME
ENUM_NEXT(payload_type_names, ID_PEER, ID_PEER, EXTENSIBLE_AUTHENTICATION,
"ID_PEER");
-ENUM_NEXT(payload_type_names, HEADER, UNKNOWN_PAYLOAD, ID_PEER,
+ENUM_NEXT(payload_type_names, HEADER, CONFIGURATION_ATTRIBUTE, ID_PEER,
"HEADER",
"PROPOSAL_SUBSTRUCTURE",
"TRANSFORM_SUBSTRUCTURE",
"TRANSFORM_ATTRIBUTE",
"TRAFFIC_SELECTOR_SUBSTRUCTURE",
- "CONFIGURATION_ATTRIBUTE",
- "UNKNOWN_PAYLOAD");
+ "CONFIGURATION_ATTRIBUTE");
#else
-ENUM_NEXT(payload_type_names, HEADER, UNKNOWN_PAYLOAD, EXTENSIBLE_AUTHENTICATION,
+ENUM_NEXT(payload_type_names, HEADER, CONFIGURATION_ATTRIBUTE, EXTENSIBLE_AUTHENTICATION,
"HEADER",
"PROPOSAL_SUBSTRUCTURE",
"TRANSFORM_SUBSTRUCTURE",
"TRANSFORM_ATTRIBUTE",
"TRAFFIC_SELECTOR_SUBSTRUCTURE",
- "CONFIGURATION_ATTRIBUTE",
- "UNKNOWN_PAYLOAD");
+ "CONFIGURATION_ATTRIBUTE");
#endif /* ME */
-ENUM_END(payload_type_names, UNKNOWN_PAYLOAD);
+ENUM_END(payload_type_names, CONFIGURATION_ATTRIBUTE);
/* short forms of payload names */
ENUM_BEGIN(payload_type_short_names, NO_PAYLOAD, NO_PAYLOAD,
@@ -102,25 +100,23 @@ ENUM_NEXT(payload_type_short_names, SECURITY_ASSOCIATION, EXTENSIBLE_AUTHENTICAT
#ifdef ME
ENUM_NEXT(payload_type_short_names, ID_PEER, ID_PEER, EXTENSIBLE_AUTHENTICATION,
"IDp");
-ENUM_NEXT(payload_type_short_names, HEADER, UNKNOWN_PAYLOAD, ID_PEER,
+ENUM_NEXT(payload_type_short_names, HEADER, CONFIGURATION_ATTRIBUTE, ID_PEER,
"HDR",
"PROP",
"TRANS",
"TRANSATTR",
"TSSUB",
- "CPATTR",
- "??");
+ "CPATTR");
#else
-ENUM_NEXT(payload_type_short_names, HEADER, UNKNOWN_PAYLOAD, EXTENSIBLE_AUTHENTICATION,
+ENUM_NEXT(payload_type_short_names, HEADER, CONFIGURATION_ATTRIBUTE, EXTENSIBLE_AUTHENTICATION,
"HDR",
"PROP",
"TRANS",
"TRANSATTR",
"TSSUB",
- "CPATTR",
- "??");
+ "CPATTR");
#endif /* ME */
-ENUM_END(payload_type_short_names, UNKNOWN_PAYLOAD);
+ENUM_END(payload_type_short_names, CONFIGURATION_ATTRIBUTE);
/*
* see header
@@ -178,7 +174,45 @@ payload_t *payload_create(payload_type_t type)
case ENCRYPTED:
return (payload_t*)encryption_payload_create();
default:
- return (payload_t*)unknown_payload_create();
+ return (payload_t*)unknown_payload_create(type);
}
}
+/**
+ * See header.
+ */
+bool payload_is_known(payload_type_t type)
+{
+ if (type == HEADER ||
+ (type >= SECURITY_ASSOCIATION && type <= EXTENSIBLE_AUTHENTICATION))
+ {
+ return TRUE;
+ }
+#ifdef ME
+ if (type == ID_PEER)
+ {
+ return TRUE;
+ }
+#endif
+ return FALSE;
+}
+
+/**
+ * See header.
+ */
+void* payload_get_field(payload_t *payload, encoding_type_t type, u_int skip)
+{
+ encoding_rule_t *rule;
+ size_t count;
+ int i;
+
+ payload->get_encoding_rules(payload, &rule, &count);
+ for (i = 0; i < count; i++)
+ {
+ if (rule[i].type == type && skip-- == 0)
+ {
+ return ((char*)payload) + rule[i].offset;
+ }
+ }
+ return NULL;
+}
diff --git a/src/libcharon/encoding/payloads/payload.h b/src/libcharon/encoding/payloads/payload.h
index 2e783cb30..0f407ff42 100644
--- a/src/libcharon/encoding/payloads/payload.h
+++ b/src/libcharon/encoding/payloads/payload.h
@@ -137,7 +137,7 @@ enum payload_type_t{
* This payload type is not sent over wire and just
* used internally to handle IKEv2-Header like a payload.
*/
- HEADER = 140,
+ HEADER = 256,
/**
* PROPOSAL_SUBSTRUCTURE has a value of PRIVATE USE space.
@@ -145,7 +145,7 @@ enum payload_type_t{
* This payload type is not sent over wire and just
* used internally to handle a proposal substructure like a payload.
*/
- PROPOSAL_SUBSTRUCTURE = 141,
+ PROPOSAL_SUBSTRUCTURE = 257,
/**
* TRANSFORM_SUBSTRUCTURE has a value of PRIVATE USE space.
@@ -153,7 +153,7 @@ enum payload_type_t{
* This payload type is not sent over wire and just
* used internally to handle a transform substructure like a payload.
*/
- TRANSFORM_SUBSTRUCTURE = 142,
+ TRANSFORM_SUBSTRUCTURE = 258,
/**
* TRANSFORM_ATTRIBUTE has a value of PRIVATE USE space.
@@ -161,7 +161,7 @@ enum payload_type_t{
* This payload type is not sent over wire and just
* used internally to handle a transform attribute like a payload.
*/
- TRANSFORM_ATTRIBUTE = 143,
+ TRANSFORM_ATTRIBUTE = 259,
/**
* TRAFFIC_SELECTOR_SUBSTRUCTURE has a value of PRIVATE USE space.
@@ -169,7 +169,7 @@ enum payload_type_t{
* This payload type is not sent over wire and just
* used internally to handle a transform selector like a payload.
*/
- TRAFFIC_SELECTOR_SUBSTRUCTURE = 144,
+ TRAFFIC_SELECTOR_SUBSTRUCTURE = 260,
/**
* CONFIGURATION_ATTRIBUTE has a value of PRIVATE USE space.
@@ -177,18 +177,9 @@ enum payload_type_t{
* This payload type is not sent over wire and just
* used internally to handle a transform attribute like a payload.
*/
- CONFIGURATION_ATTRIBUTE = 145,
-
- /**
- * A unknown payload has a value of PRIVATE USE space.
- *
- * This payload type is not sent over wire and just
- * used internally to handle a unknown payload.
- */
- UNKNOWN_PAYLOAD = 146,
+ CONFIGURATION_ATTRIBUTE = 261,
};
-
/**
* enum names for payload_type_t.
*/
@@ -269,4 +260,22 @@ struct payload_t {
*/
payload_t *payload_create(payload_type_t type);
+/**
+ * Check if a specific payload is implemented, or handled as unknown payload.
+ *
+ * @param type type of the payload to check
+ * @return FALSE if payload type handled as unknown payload
+ */
+bool payload_is_known(payload_type_t type);
+
+/**
+ * Get the value field in a payload using encoding rules.
+ *
+ * @param payload payload to look up a field
+ * @param type encoding rule type to look up
+ * @param skip number rules of type to skip, 0 to get first
+ * @return type specific value pointer, NULL if not found
+ */
+void* payload_get_field(payload_t *payload, encoding_type_t type, u_int skip);
+
#endif /** PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/proposal_substructure.c b/src/libcharon/encoding/payloads/proposal_substructure.c
index 985b03255..f39c3b0e6 100644
--- a/src/libcharon/encoding/payloads/proposal_substructure.c
+++ b/src/libcharon/encoding/payloads/proposal_substructure.c
@@ -47,6 +47,11 @@ struct private_proposal_substructure_t {
u_int8_t next_payload;
/**
+ * reserved byte
+ */
+ u_int8_t reserved;
+
+ /**
* Length of this payload.
*/
u_int16_t proposal_length;
@@ -91,8 +96,8 @@ struct private_proposal_substructure_t {
encoding_rule_t proposal_substructure_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_proposal_substructure_t, next_payload) },
- /* Reserved Byte is skipped */
- { RESERVED_BYTE, 0 },
+ /* 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 */
@@ -213,28 +218,23 @@ METHOD(payload_t, set_next_type, void,
*/
static void compute_length(private_proposal_substructure_t *this)
{
- iterator_t *iterator;
- payload_t *current_transform;
- size_t transforms_count = 0;
- size_t length = PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH;
+ enumerator_t *enumerator;
+ payload_t *transform;
- iterator = this->transforms->create_iterator(this->transforms,TRUE);
- while (iterator->iterate(iterator, (void**)&current_transform))
+ this->transforms_count = 0;
+ this->proposal_length = PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH + this->spi.len;
+ enumerator = this->transforms->create_enumerator(this->transforms);
+ while (enumerator->enumerate(enumerator, &transform))
{
- length += current_transform->get_length(current_transform);
- transforms_count++;
+ this->proposal_length += transform->get_length(transform);
+ this->transforms_count++;
}
- iterator->destroy(iterator);
-
- length += this->spi.len;
- this->transforms_count = transforms_count;
- this->proposal_length = length;
+ enumerator->destroy(enumerator);
}
METHOD(payload_t, get_length, size_t,
private_proposal_substructure_t *this)
{
- compute_length(this);
return this->proposal_length;
}
@@ -342,32 +342,10 @@ METHOD(proposal_substructure_t, get_proposal, proposal_t*,
return proposal;
}
-METHOD(proposal_substructure_t, clone_, proposal_substructure_t*,
+METHOD(proposal_substructure_t, create_substructure_enumerator, enumerator_t*,
private_proposal_substructure_t *this)
{
- private_proposal_substructure_t *clone;
- enumerator_t *enumerator;
- transform_substructure_t *current;
-
- clone = (private_proposal_substructure_t*)proposal_substructure_create();
- clone->next_payload = this->next_payload;
- clone->proposal_number = this->proposal_number;
- clone->protocol_id = this->protocol_id;
- clone->spi_size = this->spi_size;
- if (this->spi.ptr != NULL)
- {
- clone->spi.ptr = clalloc(this->spi.ptr, this->spi.len);
- clone->spi.len = this->spi.len;
- }
- enumerator = this->transforms->create_enumerator(this->transforms);
- while (enumerator->enumerate(enumerator, &current))
- {
- current = current->clone(current);
- add_transform_substructure(clone, current);
- }
- enumerator->destroy(enumerator);
-
- return &clone->public;
+ return this->transforms->create_enumerator(this->transforms);
}
METHOD2(payload_t, proposal_substructure_t, destroy, void,
@@ -403,12 +381,13 @@ proposal_substructure_t *proposal_substructure_create()
.get_protocol_id = _get_protocol_id,
.set_is_last_proposal = _set_is_last_proposal,
.get_proposal = _get_proposal,
+ .create_substructure_enumerator = _create_substructure_enumerator,
.set_spi = _set_spi,
.get_spi = _get_spi,
- .clone = _clone_,
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
+ .proposal_length = PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH,
.transforms = linked_list_create(),
);
@@ -500,6 +479,7 @@ 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);
return &this->public;
}
diff --git a/src/libcharon/encoding/payloads/proposal_substructure.h b/src/libcharon/encoding/payloads/proposal_substructure.h
index 56e7184b6..d0ba1fd2a 100644
--- a/src/libcharon/encoding/payloads/proposal_substructure.h
+++ b/src/libcharon/encoding/payloads/proposal_substructure.h
@@ -111,11 +111,11 @@ struct proposal_substructure_t {
proposal_t * (*get_proposal) (proposal_substructure_t *this);
/**
- * Clones an proposal_substructure_t object.
+ * Create an enumerator over transform substructures.
*
- * @return cloned object
+ * @return enumerator over transform_substructure_t
*/
- proposal_substructure_t* (*clone) (proposal_substructure_t *this);
+ enumerator_t* (*create_substructure_enumerator)(proposal_substructure_t *this);
/**
* Destroys an proposal_substructure_t object.
diff --git a/src/libcharon/encoding/payloads/sa_payload.c b/src/libcharon/encoding/payloads/sa_payload.c
index 4fbd4cac0..db20d052f 100644
--- a/src/libcharon/encoding/payloads/sa_payload.c
+++ b/src/libcharon/encoding/payloads/sa_payload.c
@@ -46,6 +46,11 @@ struct private_sa_payload_t {
bool critical;
/**
+ * Reserved bits
+ */
+ bool reserved[7];
+
+ /**
* Length of this payload.
*/
u_int16_t payload_length;
@@ -68,13 +73,13 @@ encoding_rule_t sa_payload_encodings[] = {
/* the critical bit */
{ FLAG, offsetof(private_sa_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
+ { 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]) },
/* Length of the whole SA payload*/
{ PAYLOAD_LENGTH, offsetof(private_sa_payload_t, payload_length) },
/* Proposals are stored in a proposal substructure,
@@ -185,7 +190,6 @@ static void compute_length(private_sa_payload_t *this)
METHOD(payload_t, get_length, size_t,
private_sa_payload_t *this)
{
- compute_length(this);
return this->payload_length;
}
@@ -258,6 +262,12 @@ METHOD(sa_payload_t, get_proposals, linked_list_t*,
return list;
}
+METHOD(sa_payload_t, create_substructure_enumerator, enumerator_t*,
+ private_sa_payload_t *this)
+{
+ return this->proposals->create_enumerator(this->proposals);
+}
+
METHOD2(payload_t, sa_payload_t, destroy, void,
private_sa_payload_t *this)
{
@@ -286,6 +296,7 @@ sa_payload_t *sa_payload_create()
},
.add_proposal = _add_proposal,
.get_proposals = _get_proposals,
+ .create_substructure_enumerator = _create_substructure_enumerator,
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
diff --git a/src/libcharon/encoding/payloads/sa_payload.h b/src/libcharon/encoding/payloads/sa_payload.h
index 801a70738..cc8c481c8 100644
--- a/src/libcharon/encoding/payloads/sa_payload.h
+++ b/src/libcharon/encoding/payloads/sa_payload.h
@@ -61,6 +61,13 @@ struct sa_payload_t {
void (*add_proposal) (sa_payload_t *this, proposal_t *proposal);
/**
+ * Create an enumerator over all proposal substructures.
+ *
+ * @return enumerator over proposal_substructure_t
+ */
+ enumerator_t* (*create_substructure_enumerator)(sa_payload_t *this);
+
+ /**
* Destroys an sa_payload_t object.
*/
void (*destroy) (sa_payload_t *this);
diff --git a/src/libcharon/encoding/payloads/traffic_selector_substructure.c b/src/libcharon/encoding/payloads/traffic_selector_substructure.c
index f24857591..df36e4383 100644
--- a/src/libcharon/encoding/payloads/traffic_selector_substructure.c
+++ b/src/libcharon/encoding/payloads/traffic_selector_substructure.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005-2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -19,14 +20,13 @@
#include <encoding/payloads/encodings.h>
#include <utils/linked_list.h>
-
typedef struct private_traffic_selector_substructure_t private_traffic_selector_substructure_t;
/**
* Private data of an traffic_selector_substructure_t object.
- *
*/
struct private_traffic_selector_substructure_t {
+
/**
* Public traffic_selector_substructure_t interface.
*/
@@ -73,24 +73,22 @@ 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[] = {
/* 1 Byte next ts type*/
- { TS_TYPE, offsetof(private_traffic_selector_substructure_t, ts_type) },
+ { TS_TYPE, offsetof(private_traffic_selector_substructure_t, ts_type) },
/* 1 Byte IP protocol id*/
- { U_INT_8, offsetof(private_traffic_selector_substructure_t, ip_protocol_id) },
+ { U_INT_8, offsetof(private_traffic_selector_substructure_t, ip_protocol_id) },
/* Length of the whole payload*/
- { PAYLOAD_LENGTH, offsetof(private_traffic_selector_substructure_t, payload_length) },
+ { PAYLOAD_LENGTH,offsetof(private_traffic_selector_substructure_t, payload_length) },
/* 2 Byte start port*/
- { U_INT_16, offsetof(private_traffic_selector_substructure_t, start_port) },
+ { U_INT_16, offsetof(private_traffic_selector_substructure_t, start_port) },
/* 2 Byte end port*/
{ U_INT_16, offsetof(private_traffic_selector_substructure_t, end_port) },
/* starting address is either 4 or 16 byte */
- { ADDRESS, offsetof(private_traffic_selector_substructure_t, starting_address) },
+ { ADDRESS, offsetof(private_traffic_selector_substructure_t, starting_address) },
/* ending address is either 4 or 16 byte */
- { ADDRESS, offsetof(private_traffic_selector_substructure_t, ending_address) }
-
+ { ADDRESS, offsetof(private_traffic_selector_substructure_t, ending_address) }
};
/*
@@ -111,10 +109,8 @@ encoding_rule_t traffic_selector_substructure_encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
-/**
- * Implementation of payload_t.verify.
- */
-static status_t verify(private_traffic_selector_substructure_t *this)
+METHOD(payload_t, verify, status_t,
+ private_traffic_selector_substructure_t *this)
{
if (this->start_port > this->end_port)
{
@@ -152,72 +148,48 @@ static status_t verify(private_traffic_selector_substructure_t *this)
return SUCCESS;
}
-/**
- * Implementation of traffic_selector_substructure_t.get_encoding_rules.
- */
-static void get_encoding_rules(private_traffic_selector_substructure_t *this, encoding_rule_t **rules, size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, void,
+ private_traffic_selector_substructure_t *this, encoding_rule_t **rules,
+ size_t *rule_count)
{
*rules = traffic_selector_substructure_encodings;
- *rule_count = sizeof(traffic_selector_substructure_encodings) / sizeof(encoding_rule_t);
+ *rule_count = countof(traffic_selector_substructure_encodings);
}
-/**
- * Implementation of payload_t.get_type.
- */
-static payload_type_t get_payload_type(private_traffic_selector_substructure_t *this)
+METHOD(payload_t, get_type, payload_type_t,
+ private_traffic_selector_substructure_t *this)
{
return TRAFFIC_SELECTOR_SUBSTRUCTURE;
}
-/**
- * Implementation of payload_t.get_next_type.
- */
-static payload_type_t get_next_type(private_traffic_selector_substructure_t *this)
+METHOD(payload_t, get_next_type, payload_type_t,
+ private_traffic_selector_substructure_t *this)
{
- return 0;
+ return NO_PAYLOAD;
}
-/**
- * Implementation of payload_t.set_next_type.
- */
-static void set_next_type(private_traffic_selector_substructure_t *this,payload_type_t type)
+METHOD(payload_t, set_next_type, void,
+ private_traffic_selector_substructure_t *this,payload_type_t type)
{
-
}
-/**
- * Implementation of payload_t.get_length.
- */
-static size_t get_length(private_traffic_selector_substructure_t *this)
+METHOD(payload_t, get_length, size_t,
+ private_traffic_selector_substructure_t *this)
{
return this->payload_length;
}
-/**
- * Implementation of traffic_selector_substructure_t.get_traffic_selector.
- */
-static traffic_selector_t *get_traffic_selector(private_traffic_selector_substructure_t *this)
+METHOD(traffic_selector_substructure_t, get_traffic_selector, traffic_selector_t*,
+ private_traffic_selector_substructure_t *this)
{
- traffic_selector_t *ts;
- ts = traffic_selector_create_from_bytes(this->ip_protocol_id, this->ts_type,
- this->starting_address, this->start_port,
- this->ending_address, this->end_port);
- return ts;
+ return traffic_selector_create_from_bytes(
+ this->ip_protocol_id, this->ts_type,
+ this->starting_address, this->start_port,
+ this->ending_address, this->end_port);
}
-/**
- * recompute length field of the payload
- */
-void compute_length(private_traffic_selector_substructure_t *this)
-{
- this->payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH +
- this->ending_address.len + this->starting_address.len;
-}
-
-/**
- * Implementation of payload_t.destroy and traffic_selector_substructure_t.destroy.
- */
-static void destroy(private_traffic_selector_substructure_t *this)
+METHOD2(payload_t, traffic_selector_substructure_t, destroy, void,
+ private_traffic_selector_substructure_t *this)
{
free(this->starting_address.ptr);
free(this->ending_address.ptr);
@@ -229,48 +201,46 @@ static void destroy(private_traffic_selector_substructure_t *this)
*/
traffic_selector_substructure_t *traffic_selector_substructure_create()
{
- private_traffic_selector_substructure_t *this = malloc_thing(private_traffic_selector_substructure_t);
-
- /* interface functions */
- this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
- this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
- this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
- this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
- this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
- this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
- this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
-
- /* public functions */
- this->public.get_traffic_selector = (traffic_selector_t* (*)(traffic_selector_substructure_t*))get_traffic_selector;
- this->public.destroy = (void (*) (traffic_selector_substructure_t *)) destroy;
-
- /* private variables */
- this->payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH;
- this->start_port = 0;
- this->end_port = 0;
- this->starting_address = chunk_empty;
- this->ending_address = chunk_empty;
- this->ip_protocol_id = 0;
- /* must be set to be valid */
- this->ts_type = TS_IPV4_ADDR_RANGE;
-
- return (&(this->public));
+ private_traffic_selector_substructure_t *this;
+
+ INIT(this,
+ .public = {
+ .payload_interface = {
+ .verify = _verify,
+ .get_encoding_rules = _get_encoding_rules,
+ .get_length = _get_length,
+ .get_next_type = _get_next_type,
+ .set_next_type = _set_next_type,
+ .get_type = _get_type,
+ .destroy = _destroy,
+ },
+ .get_traffic_selector = _get_traffic_selector,
+ .destroy = _destroy,
+ },
+ .payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH,
+ /* must be set to be valid */
+ .ts_type = TS_IPV4_ADDR_RANGE,
+ );
+ return &this->public;
}
/*
* Described in header
*/
-traffic_selector_substructure_t *traffic_selector_substructure_create_from_traffic_selector(traffic_selector_t *traffic_selector)
+traffic_selector_substructure_t *traffic_selector_substructure_create_from_traffic_selector(
+ traffic_selector_t *ts)
{
- private_traffic_selector_substructure_t *this = (private_traffic_selector_substructure_t*)traffic_selector_substructure_create();
- this->ts_type = traffic_selector->get_type(traffic_selector);
- this->ip_protocol_id = traffic_selector->get_protocol(traffic_selector);
- this->start_port = traffic_selector->get_from_port(traffic_selector);
- this->end_port = traffic_selector->get_to_port(traffic_selector);
- this->starting_address = chunk_clone(traffic_selector->get_from_address(traffic_selector));
- this->ending_address = chunk_clone(traffic_selector->get_to_address(traffic_selector));
-
- compute_length(this);
+ private_traffic_selector_substructure_t *this;
+
+ this = (private_traffic_selector_substructure_t*)traffic_selector_substructure_create();
+ this->ts_type = ts->get_type(ts);
+ this->ip_protocol_id = ts->get_protocol(ts);
+ this->start_port = ts->get_from_port(ts);
+ 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->ending_address.len + this->starting_address.len;
- return &(this->public);
+ return &this->public;
}
diff --git a/src/libcharon/encoding/payloads/transform_attribute.c b/src/libcharon/encoding/payloads/transform_attribute.c
index 8bf2ddef4..7d21258b1 100644
--- a/src/libcharon/encoding/payloads/transform_attribute.c
+++ b/src/libcharon/encoding/payloads/transform_attribute.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005-2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -26,9 +27,9 @@ typedef struct private_transform_attribute_t private_transform_attribute_t;
/**
* Private data of an transform_attribute_t object.
- *
*/
struct private_transform_attribute_t {
+
/**
* Public transform_attribute_t interface.
*/
@@ -70,7 +71,6 @@ ENUM_END(transform_attribute_type_name, KEY_LENGTH);
*
* The defined offsets are the positions in a object of type
* private_transform_attribute_t.
- *
*/
encoding_rule_t transform_attribute_encodings[] = {
/* Flag defining the format of this payload */
@@ -78,7 +78,7 @@ encoding_rule_t transform_attribute_encodings[] = {
/* 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) },
+ { 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) }
};
@@ -95,162 +95,106 @@ encoding_rule_t transform_attribute_encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
-/**
- * Implementation of payload_t.verify.
- */
-static status_t verify(private_transform_attribute_t *this)
+METHOD(payload_t, verify, status_t,
+ private_transform_attribute_t *this)
{
- if (this->attribute_type != KEY_LENGTH)
- {
- return FAILED;
- }
-
return SUCCESS;
}
-/**
- * Implementation of payload_t.get_encoding_rules.
- */
-static void get_encoding_rules(private_transform_attribute_t *this, encoding_rule_t **rules, size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, void,
+ private_transform_attribute_t *this, encoding_rule_t **rules,
+ size_t *rule_count)
{
*rules = transform_attribute_encodings;
- *rule_count = sizeof(transform_attribute_encodings) / sizeof(encoding_rule_t);
+ *rule_count = countof(transform_attribute_encodings);
}
-/**
- * Implementation of payload_t.get_type.
- */
-static payload_type_t get_type(private_transform_attribute_t *this)
+METHOD(payload_t, get_type, payload_type_t,
+ private_transform_attribute_t *this)
{
return TRANSFORM_ATTRIBUTE;
}
-/**
- * Implementation of payload_t.get_next_type.
- */
-static payload_type_t get_next_type(private_transform_attribute_t *this)
+METHOD(payload_t, get_next_type, payload_type_t,
+ private_transform_attribute_t *this)
{
- return (NO_PAYLOAD);
+ return NO_PAYLOAD;
}
-/**
- * Implementation of payload_t.set_next_type.
- */
-static void set_next_type(private_transform_attribute_t *this,payload_type_t type)
+METHOD(payload_t, set_next_type, void,
+ private_transform_attribute_t *this, payload_type_t type)
{
}
-/**
- * Implementation of transform_attribute_t.get_length.
- */
-static size_t get_length(private_transform_attribute_t *this)
+METHOD(payload_t, get_length, size_t,
+ private_transform_attribute_t *this)
{
- if (this->attribute_format == TRUE)
+ if (this->attribute_format)
{
- /*Attribute size is only 4 byte */
return 4;
}
- return (this->attribute_length_or_value + 4);
+ return this->attribute_length_or_value + 4;
}
-/**
- * Implementation of transform_attribute_t.set_value_chunk.
- */
-static void set_value_chunk(private_transform_attribute_t *this, chunk_t value)
+METHOD(transform_attribute_t, set_value_chunk, void,
+ private_transform_attribute_t *this, chunk_t value)
{
- if (this->attribute_value.ptr != NULL)
- {
- /* free existing value */
- free(this->attribute_value.ptr);
- this->attribute_value.ptr = NULL;
- this->attribute_value.len = 0;
-
- }
+ chunk_free(&this->attribute_value);
- if (value.len > 2)
+ if (value.len != 2)
{
- this->attribute_value.ptr = clalloc(value.ptr,value.len);
- this->attribute_value.len = value.len;
+ this->attribute_value = chunk_clone(value);
this->attribute_length_or_value = value.len;
- /* attribute has not a fixed length */
this->attribute_format = FALSE;
}
else
{
- memcpy(&(this->attribute_length_or_value),value.ptr,value.len);
+ memcpy(&this->attribute_length_or_value, value.ptr, value.len);
}
}
-/**
- * Implementation of transform_attribute_t.set_value.
- */
-static void set_value(private_transform_attribute_t *this, u_int16_t value)
+METHOD(transform_attribute_t, set_value, void,
+ private_transform_attribute_t *this, u_int16_t value)
{
- if (this->attribute_value.ptr != NULL)
- {
- /* free existing value */
- free(this->attribute_value.ptr);
- this->attribute_value.ptr = NULL;
- this->attribute_value.len = 0;
-
- }
+ chunk_free(&this->attribute_value);
this->attribute_length_or_value = value;
+ this->attribute_format = TRUE;
}
-/**
- * Implementation of transform_attribute_t.get_value_chunk.
- */
-static chunk_t get_value_chunk (private_transform_attribute_t *this)
+METHOD(transform_attribute_t, get_value_chunk, chunk_t,
+ private_transform_attribute_t *this)
{
- chunk_t value;
-
- if (this->attribute_format == FALSE)
+ if (this->attribute_format)
{
- value.ptr = this->attribute_value.ptr;
- value.len = this->attribute_value.len;
+ return chunk_from_thing(this->attribute_length_or_value);
}
- else
- {
- value.ptr = (void *) &(this->attribute_length_or_value);
- value.len = 2;
- }
-
- return value;
+ return this->attribute_value;
}
-/**
- * Implementation of transform_attribute_t.get_value.
- */
-static u_int16_t get_value (private_transform_attribute_t *this)
+METHOD(transform_attribute_t, get_value, u_int16_t,
+ private_transform_attribute_t *this)
{
return this->attribute_length_or_value;
}
-
-/**
- * Implementation of transform_attribute_t.set_attribute_type.
- */
-static void set_attribute_type (private_transform_attribute_t *this, u_int16_t type)
+METHOD(transform_attribute_t, set_attribute_type, void,
+ private_transform_attribute_t *this, u_int16_t type)
{
this->attribute_type = type & 0x7FFF;
}
-/**
- * Implementation of transform_attribute_t.get_attribute_type.
- */
-static u_int16_t get_attribute_type (private_transform_attribute_t *this)
+METHOD(transform_attribute_t, get_attribute_type, u_int16_t,
+ private_transform_attribute_t *this)
{
return this->attribute_type;
}
-/**
- * Implementation of transform_attribute_t.clone.
- */
-static transform_attribute_t * _clone(private_transform_attribute_t *this)
+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 = (private_transform_attribute_t *)transform_attribute_create();
new_clone->attribute_format = this->attribute_format;
new_clone->attribute_type = this->attribute_type;
@@ -258,22 +202,15 @@ static transform_attribute_t * _clone(private_transform_attribute_t *this)
if (!new_clone->attribute_format)
{
- new_clone->attribute_value.ptr = clalloc(this->attribute_value.ptr,this->attribute_value.len);
- new_clone->attribute_value.len = this->attribute_value.len;
+ new_clone->attribute_value = chunk_clone(this->attribute_value);
}
-
- return (transform_attribute_t *) new_clone;
+ return &new_clone->public;
}
-/**
- * Implementation of transform_attribute_t.destroy and payload_t.destroy.
- */
-static void destroy(private_transform_attribute_t *this)
+METHOD2(payload_t, transform_attribute_t, destroy, void,
+ private_transform_attribute_t *this)
{
- if (this->attribute_value.ptr != NULL)
- {
- free(this->attribute_value.ptr);
- }
+ free(this->attribute_value.ptr);
free(this);
}
@@ -282,35 +219,31 @@ static void destroy(private_transform_attribute_t *this)
*/
transform_attribute_t *transform_attribute_create()
{
- private_transform_attribute_t *this = malloc_thing(private_transform_attribute_t);
-
- /* payload interface */
- this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
- this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
- this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
- this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
- this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
- this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
- this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
-
- /* public functions */
- this->public.set_value_chunk = (void (*) (transform_attribute_t *,chunk_t)) set_value_chunk;
- this->public.set_value = (void (*) (transform_attribute_t *,u_int16_t)) set_value;
- this->public.get_value_chunk = (chunk_t (*) (transform_attribute_t *)) get_value_chunk;
- this->public.get_value = (u_int16_t (*) (transform_attribute_t *)) get_value;
- this->public.set_attribute_type = (void (*) (transform_attribute_t *,u_int16_t type)) set_attribute_type;
- this->public.get_attribute_type = (u_int16_t (*) (transform_attribute_t *)) get_attribute_type;
- this->public.clone = (transform_attribute_t * (*) (transform_attribute_t *)) _clone;
- this->public.destroy = (void (*) (transform_attribute_t *)) destroy;
-
- /* set default values of the fields */
- this->attribute_format = TRUE;
- this->attribute_type = 0;
- this->attribute_length_or_value = 0;
- this->attribute_value.ptr = NULL;
- this->attribute_value.len = 0;
-
- return (&(this->public));
+ private_transform_attribute_t *this;
+
+ INIT(this,
+ .public = {
+ .payload_interface = {
+ .verify = _verify,
+ .get_encoding_rules = _get_encoding_rules,
+ .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,
+ );
+ return &this->public;
}
/*
@@ -319,7 +252,7 @@ transform_attribute_t *transform_attribute_create()
transform_attribute_t *transform_attribute_create_key_length(u_int16_t key_length)
{
transform_attribute_t *attribute = transform_attribute_create();
- attribute->set_attribute_type(attribute,KEY_LENGTH);
- attribute->set_value(attribute,key_length);
+ attribute->set_attribute_type(attribute, KEY_LENGTH);
+ attribute->set_value(attribute, key_length);
return attribute;
}
diff --git a/src/libcharon/encoding/payloads/transform_substructure.c b/src/libcharon/encoding/payloads/transform_substructure.c
index c94f6c1a2..0428da726 100644
--- a/src/libcharon/encoding/payloads/transform_substructure.c
+++ b/src/libcharon/encoding/payloads/transform_substructure.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005-2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -24,14 +25,13 @@
#include <utils/linked_list.h>
#include <daemon.h>
-
typedef struct private_transform_substructure_t private_transform_substructure_t;
/**
* Private data of an transform_substructure_t object.
- *
*/
struct private_transform_substructure_t {
+
/**
* Public transform_substructure_t interface.
*/
@@ -41,14 +41,16 @@ struct private_transform_substructure_t {
* Next payload type.
*/
u_int8_t next_payload;
-
+ /**
+ * Reserved bytes
+ */
+ u_int8_t reserved[2];
/**
* Length of this payload.
*/
u_int16_t transform_length;
-
/**
* Type of the transform.
*/
@@ -65,30 +67,28 @@ struct private_transform_substructure_t {
linked_list_t *attributes;
};
-
/**
* 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_rule_t transform_substructure_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
- { U_INT_8, offsetof(private_transform_substructure_t, next_payload) },
- /* Reserved Byte is skipped */
- { RESERVED_BYTE, 0 },
+ { U_INT_8, offsetof(private_transform_substructure_t, next_payload) },
+ /* 1 Reserved Byte */
+ { RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[0]) },
/* Length of the whole transform substructure*/
- { PAYLOAD_LENGTH, offsetof(private_transform_substructure_t, transform_length) },
+ { 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) },
- /* Reserved Byte is skipped */
- { RESERVED_BYTE, 0 },
+ { U_INT_8, offsetof(private_transform_substructure_t, transform_type) },
+ /* 1 Reserved Byte */
+ { RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[1]) },
/* tranform ID is a number of 8 bit */
- { U_INT_16, offsetof(private_transform_substructure_t, transform_id) },
+ { 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) }
+ { TRANSFORM_ATTRIBUTES, offsetof(private_transform_substructure_t, attributes) }
};
/*
@@ -105,19 +105,15 @@ encoding_rule_t transform_substructure_encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
-
-/**
- * Implementation of payload_t.verify.
- */
-static status_t verify(private_transform_substructure_t *this)
+METHOD(payload_t, verify, status_t,
+ private_transform_substructure_t *this)
{
status_t status = SUCCESS;
- iterator_t *iterator;
- payload_t *current_attributes;
+ enumerator_t *enumerator;
+ payload_t *attribute;
- if ((this->next_payload != NO_PAYLOAD) && (this->next_payload != 3))
+ if (this->next_payload != NO_PAYLOAD && this->next_payload != 3)
{
- /* must be 0 or 3 */
DBG1(DBG_ENC, "inconsistent next payload");
return FAILED;
}
@@ -138,45 +134,41 @@ static status_t verify(private_transform_substructure_t *this)
return FAILED;
}
}
- iterator = this->attributes->create_iterator(this->attributes,TRUE);
- while(iterator->iterate(iterator, (void**)&current_attributes))
+ enumerator = this->attributes->create_enumerator(this->attributes);
+ while (enumerator->enumerate(enumerator, &attribute))
{
- status = current_attributes->verify(current_attributes);
+ status = attribute->verify(attribute);
if (status != SUCCESS)
{
DBG1(DBG_ENC, "TRANSFORM_ATTRIBUTE verification failed");
+ break;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
/* proposal number is checked in SA payload */
return status;
}
-/**
- * Implementation of payload_t.get_encoding_rules.
- */
-static void get_encoding_rules(private_transform_substructure_t *this, encoding_rule_t **rules, size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, void,
+ private_transform_substructure_t *this, encoding_rule_t **rules,
+ size_t *rule_count)
{
*rules = transform_substructure_encodings;
- *rule_count = sizeof(transform_substructure_encodings) / sizeof(encoding_rule_t);
+ *rule_count = countof(transform_substructure_encodings);
}
-/**
- * Implementation of payload_t.get_type.
- */
-static payload_type_t get_type(private_transform_substructure_t *this)
+METHOD(payload_t, get_type, payload_type_t,
+ private_transform_substructure_t *this)
{
return TRANSFORM_SUBSTRUCTURE;
}
-/**
- * Implementation of payload_t.get_next_type.
- */
-static payload_type_t get_next_type(private_transform_substructure_t *this)
+METHOD(payload_t, get_next_type, payload_type_t,
+ private_transform_substructure_t *this)
{
- return (this->next_payload);
+ return this->next_payload;
}
/**
@@ -184,154 +176,69 @@ static payload_type_t get_next_type(private_transform_substructure_t *this)
*/
static void compute_length (private_transform_substructure_t *this)
{
- iterator_t *iterator;
- payload_t *current_attribute;
- size_t length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
+ enumerator_t *enumerator;
+ payload_t *attribute;
- iterator = this->attributes->create_iterator(this->attributes,TRUE);
- while (iterator->iterate(iterator, (void**)&current_attribute))
+ this->transform_length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
+ enumerator = this->attributes->create_enumerator(this->attributes);
+ while (enumerator->enumerate(enumerator, &attribute))
{
- length += current_attribute->get_length(current_attribute);
+ this->transform_length += attribute->get_length(attribute);
}
- iterator->destroy(iterator);
-
- this->transform_length = length;
+ enumerator->destroy(enumerator);
}
-/**
- * Implementation of payload_t.get_length.
- */
-static size_t get_length(private_transform_substructure_t *this)
+METHOD(payload_t, get_length, size_t,
+ private_transform_substructure_t *this)
{
- compute_length(this);
return this->transform_length;
}
-/**
- * Implementation of transform_substructure_t.create_transform_attribute_iterator.
- */
-static iterator_t *create_transform_attribute_iterator (private_transform_substructure_t *this,bool forward)
-{
- return this->attributes->create_iterator(this->attributes,forward);
-}
-
-/**
- * Implementation of transform_substructure_t.add_transform_attribute.
- */
-static void add_transform_attribute (private_transform_substructure_t *this,transform_attribute_t *attribute)
-{
- this->attributes->insert_last(this->attributes,(void *) attribute);
- compute_length(this);
-}
-
-/**
- * Implementation of transform_substructure_t.set_is_last_transform.
- */
-static void set_is_last_transform (private_transform_substructure_t *this, bool is_last)
-{
- this->next_payload = (is_last) ? 0: TRANSFORM_TYPE_VALUE;
-}
-
-/**
- * Implementation of transform_substructure_t.get_is_last_transform.
- */
-static bool get_is_last_transform (private_transform_substructure_t *this)
-{
- return ((this->next_payload == TRANSFORM_TYPE_VALUE) ? FALSE : TRUE);
-}
-
-/**
- * Implementation of payload_t.set_next_type.
- */
-static void set_next_type(private_transform_substructure_t *this,payload_type_t type)
+METHOD(transform_substructure_t, set_is_last_transform, void,
+ private_transform_substructure_t *this, bool is_last)
{
+ this->next_payload = is_last ? 0: TRANSFORM_TYPE_VALUE;
}
-/**
- * Implementation of transform_substructure_t.set_transform_type.
- */
-static void set_transform_type (private_transform_substructure_t *this,u_int8_t type)
+METHOD(payload_t, set_next_type, void,
+ private_transform_substructure_t *this,payload_type_t type)
{
- this->transform_type = type;
}
-/**
- * Implementation of transform_substructure_t.get_transform_type.
- */
-static u_int8_t get_transform_type (private_transform_substructure_t *this)
+METHOD(transform_substructure_t, get_transform_type, u_int8_t,
+ private_transform_substructure_t *this)
{
return this->transform_type;
}
-/**
- * Implementation of transform_substructure_t.set_transform_id.
- */
-static void set_transform_id (private_transform_substructure_t *this,u_int16_t id)
-{
- this->transform_id = id;
-}
-
-/**
- * Implementation of transform_substructure_t.get_transform_id.
- */
-static u_int16_t get_transform_id (private_transform_substructure_t *this)
+METHOD(transform_substructure_t, get_transform_id, u_int16_t,
+ private_transform_substructure_t *this)
{
return this->transform_id;
}
-/**
- * Implementation of transform_substructure_t.clone.
- */
-static transform_substructure_t *clone_(private_transform_substructure_t *this)
-{
- private_transform_substructure_t *clone;
- iterator_t *attributes;
- transform_attribute_t *current_attribute;
-
- clone = (private_transform_substructure_t *) transform_substructure_create();
- clone->next_payload = this->next_payload;
- clone->transform_type = this->transform_type;
- clone->transform_id = this->transform_id;
-
- attributes = this->attributes->create_iterator(this->attributes, FALSE);
- while (attributes->iterate(attributes, (void**)&current_attribute))
- {
- current_attribute = current_attribute->clone(current_attribute);
- clone->public.add_transform_attribute(&clone->public, current_attribute);
- }
- attributes->destroy(attributes);
-
- return &clone->public;
-}
-
-
-/**
- * Implementation of transform_substructure_t.get_key_length.
- */
-static status_t get_key_length(private_transform_substructure_t *this, u_int16_t *key_length)
+METHOD(transform_substructure_t, get_key_length, status_t,
+ private_transform_substructure_t *this, u_int16_t *key_length)
{
- iterator_t *attributes;
- transform_attribute_t *current_attribute;
+ enumerator_t *enumerator;
+ transform_attribute_t *attribute;
- attributes = this->attributes->create_iterator(this->attributes, TRUE);
- while (attributes->iterate(attributes, (void**)&current_attribute))
+ enumerator = this->attributes->create_enumerator(this->attributes);
+ while (enumerator->enumerate(enumerator, &attribute))
{
- if (current_attribute->get_attribute_type(current_attribute) == KEY_LENGTH)
+ if (attribute->get_attribute_type(attribute) == KEY_LENGTH)
{
- *key_length = current_attribute->get_value(current_attribute);
- attributes->destroy(attributes);
+ *key_length = attribute->get_value(attribute);
+ enumerator->destroy(enumerator);
return SUCCESS;
}
}
- attributes->destroy(attributes);
+ enumerator->destroy(enumerator);
return FAILED;
}
-
-/**
- * Implementation of transform_substructure_t.destroy and payload_t.destroy.
- */
-static void destroy(private_transform_substructure_t *this)
+METHOD2(payload_t, transform_substructure_t, destroy, void,
+ private_transform_substructure_t *this)
{
this->attributes->destroy_offset(this->attributes,
offsetof(transform_attribute_t, destroy));
@@ -343,60 +250,50 @@ static void destroy(private_transform_substructure_t *this)
*/
transform_substructure_t *transform_substructure_create()
{
- private_transform_substructure_t *this = malloc_thing(private_transform_substructure_t);
-
- /* payload interface */
- this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
- this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
- this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
- this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
- this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
- this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
- this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
-
- /* public functions */
- this->public.create_transform_attribute_iterator = (iterator_t * (*) (transform_substructure_t *,bool)) create_transform_attribute_iterator;
- this->public.add_transform_attribute = (void (*) (transform_substructure_t *,transform_attribute_t *)) add_transform_attribute;
- this->public.set_is_last_transform = (void (*) (transform_substructure_t *,bool)) set_is_last_transform;
- this->public.get_is_last_transform = (bool (*) (transform_substructure_t *)) get_is_last_transform;
- this->public.set_transform_type = (void (*) (transform_substructure_t *,u_int8_t)) set_transform_type;
- this->public.get_transform_type = (u_int8_t (*) (transform_substructure_t *)) get_transform_type;
- this->public.set_transform_id = (void (*) (transform_substructure_t *,u_int16_t)) set_transform_id;
- this->public.get_transform_id = (u_int16_t (*) (transform_substructure_t *)) get_transform_id;
- this->public.get_key_length = (status_t (*) (transform_substructure_t *,u_int16_t *)) get_key_length;
- this->public.clone = (transform_substructure_t* (*) (transform_substructure_t *)) clone_;
- this->public.destroy = (void (*) (transform_substructure_t *)) destroy;
-
- /* set default values of the fields */
- this->next_payload = NO_PAYLOAD;
- this->transform_length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
- this->transform_id = 0;
- this->transform_type = 0;
- this->attributes = linked_list_create();
-
- return (&(this->public));
+ private_transform_substructure_t *this;
+
+ INIT(this,
+ .public = {
+ .payload_interface = {
+ .verify = _verify,
+ .get_encoding_rules = _get_encoding_rules,
+ .get_length = _get_length,
+ .get_next_type = _get_next_type,
+ .set_next_type = _set_next_type,
+ .get_type = _get_type,
+ .destroy = _destroy,
+ },
+ .set_is_last_transform = _set_is_last_transform,
+ .get_transform_type = _get_transform_type,
+ .get_transform_id = _get_transform_id,
+ .get_key_length = _get_key_length,
+ .destroy = _destroy,
+ },
+ .next_payload = NO_PAYLOAD,
+ .transform_length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH,
+ .attributes = linked_list_create(),
+ );
+ return &this->public;
}
/*
* Described in header
*/
transform_substructure_t *transform_substructure_create_type(
- transform_type_t transform_type,
- u_int16_t transform_id, u_int16_t key_length)
+ transform_type_t type, u_int16_t id, u_int16_t key_length)
{
- transform_substructure_t *transform = transform_substructure_create();
+ private_transform_substructure_t *this;
- transform->set_transform_type(transform,transform_type);
- transform->set_transform_id(transform,transform_id);
+ this = (private_transform_substructure_t*)transform_substructure_create();
+ this->transform_type = type;
+ this->transform_id = id;
if (key_length)
{
- transform_attribute_t *attribute;
-
- attribute = transform_attribute_create_key_length(key_length);
- transform->add_transform_attribute(transform, attribute);
-
+ this->attributes->insert_last(this->attributes,
+ (void*)transform_attribute_create_key_length(key_length));
+ compute_length(this);
}
- return transform;
+ return &this->public;
}
diff --git a/src/libcharon/encoding/payloads/transform_substructure.h b/src/libcharon/encoding/payloads/transform_substructure.h
index 5d31f8c0a..c961700a4 100644
--- a/src/libcharon/encoding/payloads/transform_substructure.h
+++ b/src/libcharon/encoding/payloads/transform_substructure.h
@@ -34,7 +34,6 @@ typedef struct transform_substructure_t transform_substructure_t;
#include <crypto/crypters/crypter.h>
#include <config/proposal.h>
-
/**
* IKEv1 Value for a transform payload.
*/
@@ -45,32 +44,19 @@ typedef struct transform_substructure_t transform_substructure_t;
*/
#define TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH 8
-
/**
* Class representing an IKEv2- TRANSFORM SUBSTRUCTURE.
*
* The TRANSFORM SUBSTRUCTURE format is described in RFC section 3.3.2.
*/
struct transform_substructure_t {
+
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
- * Creates an iterator of stored transform_attribute_t objects.
- *
- * When deleting an transform attribute using this iterator,
- * the length of this transform substructure has to be refreshed
- * by calling get_length().
- *
- * @param forward iterator direction (TRUE: front to end)
- * @return created iterator_t object.
- */
- iterator_t * (*create_transform_attribute_iterator) (
- transform_substructure_t *this, bool forward);
-
- /**
* Adds a transform_attribute_t object to this object.
*
* @param proposal transform_attribute_t object to add
@@ -89,20 +75,6 @@ struct transform_substructure_t {
void (*set_is_last_transform) (transform_substructure_t *this, bool is_last);
/**
- * Checks if this is the last transform.
- *
- * @return TRUE if this is the last Transform, FALSE otherwise
- */
- bool (*get_is_last_transform) (transform_substructure_t *this);
-
- /**
- * Sets transform type of the current transform substructure.
- *
- * @param type type value to set
- */
- void (*set_transform_type) (transform_substructure_t *this, u_int8_t type);
-
- /**
* get transform type of the current transform.
*
* @return Transform type of current transform substructure.
@@ -110,21 +82,14 @@ struct transform_substructure_t {
u_int8_t (*get_transform_type) (transform_substructure_t *this);
/**
- * Sets transform id of the current transform substructure.
- *
- * @param id transform id to set
- */
- void (*set_transform_id) (transform_substructure_t *this, u_int16_t id);
-
- /**
- * get transform id of the current transform.
+ * Get transform id of the current transform.
*
* @return Transform id of current transform substructure.
*/
u_int16_t (*get_transform_id) (transform_substructure_t *this);
/**
- * get transform id of the current transform.
+ * Get transform id of the current transform.
*
* @param key_length The key length is written to this location
* @return
@@ -136,13 +101,6 @@ struct transform_substructure_t {
u_int16_t *key_length);
/**
- * Clones an transform_substructure_t object.
- *
- * @return cloned transform_substructure_t object
- */
- transform_substructure_t* (*clone) (transform_substructure_t *this);
-
- /**
* Destroys an transform_substructure_t object.
*/
void (*destroy) (transform_substructure_t *this);
@@ -151,24 +109,19 @@ struct transform_substructure_t {
/**
* Creates an empty transform_substructure_t object.
*
- * @return created transform_substructure_t object
+ * @return created transform_substructure_t object
*/
transform_substructure_t *transform_substructure_create(void);
/**
* Creates an empty transform_substructure_t object.
*
- * The key length is used for the transport types ENCRYPTION_ALGORITHM,
- * PSEUDO_RANDOM_FUNCTION, INTEGRITY_ALGORITHM. For all
- * other transport types the key_length parameter is not used
- *
- * @param transform_type type of transform to create
- * @param transform_id transform id specifying the specific algorithm of a transform type
- * @param key_length Key length for key lenght attribute
- * @return 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 lenght attribute, 0 to omit
+ * @return transform_substructure_t object
*/
transform_substructure_t *transform_substructure_create_type(
- transform_type_t transform_type, u_int16_t transform_id,
- u_int16_t key_length);
+ transform_type_t type, u_int16_t id, u_int16_t key_length);
#endif /** TRANSFORM_SUBSTRUCTURE_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/ts_payload.c b/src/libcharon/encoding/payloads/ts_payload.c
index 6bf3e4293..28f760e40 100644
--- a/src/libcharon/encoding/payloads/ts_payload.c
+++ b/src/libcharon/encoding/payloads/ts_payload.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005-2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -25,9 +26,9 @@ typedef struct private_ts_payload_t private_ts_payload_t;
/**
* Private data of an ts_payload_t object.
- *
*/
struct private_ts_payload_t {
+
/**
* Public ts_payload_t interface.
*/
@@ -49,6 +50,16 @@ struct private_ts_payload_t {
bool critical;
/**
+ * reserved bits
+ */
+ bool reserved_bit[7];
+
+ /**
+ * reserved bytes
+ */
+ bool reserved_byte[3];
+
+ /**
* Length of this payload.
*/
u_int16_t payload_length;
@@ -56,12 +67,12 @@ struct private_ts_payload_t {
/**
* Number of traffic selectors
*/
- u_int8_t number_of_traffic_selectors;
+ u_int8_t ts_num;
/**
* Contains the traffic selectors of type traffic_selector_substructure_t.
*/
- linked_list_t *traffic_selectors;
+ linked_list_t *substrs;
};
/**
@@ -69,31 +80,30 @@ 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[] = {
/* 1 Byte next payload type, stored in the field next_payload */
- { U_INT_8, offsetof(private_ts_payload_t, next_payload) },
+ { U_INT_8, offsetof(private_ts_payload_t, next_payload) },
/* the critical bit */
- { FLAG, offsetof(private_ts_payload_t, critical) },
- /* 7 Bit reserved bits, nowhere stored */
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
+ { FLAG, offsetof(private_ts_payload_t, critical) },
+ /* 7 Bit reserved bits */
+ { RESERVED_BIT, offsetof(private_ts_payload_t, reserved_bit[0]) },
+ { RESERVED_BIT, offsetof(private_ts_payload_t, reserved_bit[1]) },
+ { RESERVED_BIT, offsetof(private_ts_payload_t, reserved_bit[2]) },
+ { RESERVED_BIT, offsetof(private_ts_payload_t, reserved_bit[3]) },
+ { RESERVED_BIT, offsetof(private_ts_payload_t, reserved_bit[4]) },
+ { RESERVED_BIT, offsetof(private_ts_payload_t, reserved_bit[5]) },
+ { RESERVED_BIT, offsetof(private_ts_payload_t, reserved_bit[6]) },
/* Length of the whole payload*/
- { PAYLOAD_LENGTH, offsetof(private_ts_payload_t, payload_length)},
+ { PAYLOAD_LENGTH, offsetof(private_ts_payload_t, payload_length) },
/* 1 Byte TS type*/
- { U_INT_8, offsetof(private_ts_payload_t, number_of_traffic_selectors) },
+ { U_INT_8, offsetof(private_ts_payload_t, ts_num) },
/* 3 reserved bytes */
- { RESERVED_BYTE, 0 },
- { RESERVED_BYTE, 0 },
- { RESERVED_BYTE, 0 },
+ { 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, traffic_selectors) }
+ { TRAFFIC_SELECTORS,offsetof(private_ts_payload_t, substrs) }
};
/*
@@ -110,71 +120,56 @@ encoding_rule_t ts_payload_encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
-/**
- * Implementation of payload_t.verify.
- */
-static status_t verify(private_ts_payload_t *this)
+METHOD(payload_t, verify, status_t,
+ private_ts_payload_t *this)
{
- iterator_t *iterator;
- payload_t *current_traffic_selector;
+ enumerator_t *enumerator;
+ payload_t *substr;
status_t status = SUCCESS;
- if (this->number_of_traffic_selectors != (this->traffic_selectors->get_count(this->traffic_selectors)))
+ if (this->ts_num != this->substrs->get_count(this->substrs))
{
- /* must be the same */
return FAILED;
}
-
- iterator = this->traffic_selectors->create_iterator(this->traffic_selectors,TRUE);
- while(iterator->iterate(iterator, (void**)&current_traffic_selector))
+ enumerator = this->substrs->create_enumerator(this->substrs);
+ while (enumerator->enumerate(enumerator, &substr))
{
- status = current_traffic_selector->verify(current_traffic_selector);
+ status = substr->verify(substr);
if (status != SUCCESS)
{
break;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
return status;
}
-/**
- * Implementation of ts_payload_t.get_encoding_rules.
- */
-static void get_encoding_rules(private_ts_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, void,
+ private_ts_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = ts_payload_encodings;
- *rule_count = sizeof(ts_payload_encodings) / sizeof(encoding_rule_t);
+ *rule_count = countof(ts_payload_encodings);
}
-/**
- * Implementation of payload_t.get_type.
- */
-static payload_type_t get_payload_type(private_ts_payload_t *this)
+METHOD(payload_t, get_type, payload_type_t,
+ private_ts_payload_t *this)
{
if (this->is_initiator)
{
return TRAFFIC_SELECTOR_INITIATOR;
}
- else
- {
- return TRAFFIC_SELECTOR_RESPONDER;
- }
+ return TRAFFIC_SELECTOR_RESPONDER;
}
-/**
- * Implementation of payload_t.get_next_type.
- */
-static payload_type_t get_next_type(private_ts_payload_t *this)
+METHOD(payload_t, get_next_type, payload_type_t,
+ private_ts_payload_t *this)
{
- return (this->next_payload);
+ return this->next_payload;
}
-/**
- * Implementation of payload_t.set_next_type.
- */
-static void set_next_type(private_ts_payload_t *this,payload_type_t type)
+METHOD(payload_t, set_next_type, void,
+ private_ts_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
@@ -182,95 +177,64 @@ static void set_next_type(private_ts_payload_t *this,payload_type_t type)
/**
* recompute the length of the payload.
*/
-static void compute_length (private_ts_payload_t *this)
+static void compute_length(private_ts_payload_t *this)
{
- iterator_t *iterator;
- size_t ts_count = 0;
- size_t length = TS_PAYLOAD_HEADER_LENGTH;
- payload_t *current_traffic_selector;
+ enumerator_t *enumerator;
+ payload_t *subst;
- iterator = this->traffic_selectors->create_iterator(this->traffic_selectors,TRUE);
- while (iterator->iterate(iterator, (void**)&current_traffic_selector))
+ this->payload_length = TS_PAYLOAD_HEADER_LENGTH;
+ this->ts_num = 0;
+ enumerator = this->substrs->create_enumerator(this->substrs);
+ while (enumerator->enumerate(enumerator, &subst))
{
- length += current_traffic_selector->get_length(current_traffic_selector);
- ts_count++;
+ this->payload_length += subst->get_length(subst);
+ this->ts_num++;
}
- iterator->destroy(iterator);
-
- this->number_of_traffic_selectors= ts_count;
- this->payload_length = length;
+ enumerator->destroy(enumerator);
}
-/**
- * Implementation of payload_t.get_length.
- */
-static size_t get_length(private_ts_payload_t *this)
+METHOD(payload_t, get_length, size_t,
+ private_ts_payload_t *this)
{
- compute_length(this);
return this->payload_length;
}
-/**
- * Implementation of ts_payload_t.get_initiator.
- */
-static bool get_initiator (private_ts_payload_t *this)
+METHOD(ts_payload_t, get_initiator, bool,
+ private_ts_payload_t *this)
{
- return (this->is_initiator);
+ return this->is_initiator;
}
-/**
- * Implementation of ts_payload_t.set_initiator.
- */
-static void set_initiator (private_ts_payload_t *this,bool is_initiator)
+METHOD(ts_payload_t, set_initiator, void,
+ private_ts_payload_t *this,bool is_initiator)
{
this->is_initiator = is_initiator;
}
-/**
- * Implementation of ts_payload_t.add_traffic_selector_substructure.
- */
-static void add_traffic_selector_substructure (private_ts_payload_t *this,traffic_selector_substructure_t *traffic_selector)
-{
- this->traffic_selectors->insert_last(this->traffic_selectors,traffic_selector);
- this->number_of_traffic_selectors = this->traffic_selectors->get_count(this->traffic_selectors);
-}
-
-/**
- * Implementation of ts_payload_t.create_traffic_selector_substructure_iterator.
- */
-static iterator_t * create_traffic_selector_substructure_iterator (private_ts_payload_t *this, bool forward)
-{
- return this->traffic_selectors->create_iterator(this->traffic_selectors,forward);
-}
-
-/**
- * Implementation of ts_payload_t.get_traffic_selectors.
- */
-static linked_list_t *get_traffic_selectors(private_ts_payload_t *this)
+METHOD(ts_payload_t, get_traffic_selectors, linked_list_t*,
+ private_ts_payload_t *this)
{
traffic_selector_t *ts;
- iterator_t *iterator;
- traffic_selector_substructure_t *ts_substructure;
- linked_list_t *ts_list = linked_list_create();
+ enumerator_t *enumerator;
+ traffic_selector_substructure_t *subst;
+ linked_list_t *list;
- iterator = this->traffic_selectors->create_iterator(this->traffic_selectors, TRUE);
- while (iterator->iterate(iterator, (void**)&ts_substructure))
+ list = linked_list_create();
+ enumerator = this->substrs->create_enumerator(this->substrs);
+ while (enumerator->enumerate(enumerator, &subst))
{
- ts = ts_substructure->get_traffic_selector(ts_substructure);
- ts_list->insert_last(ts_list, (void*)ts);
+ ts = subst->get_traffic_selector(subst);
+ list->insert_last(list, ts);
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
- return ts_list;
+ return list;
}
-/**
- * Implementation of payload_t.destroy and ts_payload_t.destroy.
- */
-static void destroy(private_ts_payload_t *this)
+METHOD2(payload_t, ts_payload_t, destroy, void,
+ private_ts_payload_t *this)
{
- this->traffic_selectors->destroy_offset(this->traffic_selectors,
- offsetof(payload_t, destroy));
+ this->substrs->destroy_offset(this->substrs, offsetof(payload_t, destroy));
free(this);
}
@@ -279,56 +243,53 @@ static void destroy(private_ts_payload_t *this)
*/
ts_payload_t *ts_payload_create(bool is_initiator)
{
- private_ts_payload_t *this = malloc_thing(private_ts_payload_t);
-
- /* interface functions */
- this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
- this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
- this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
- this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
- this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
- this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
- this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
-
- /* public functions */
- this->public.destroy = (void (*) (ts_payload_t *)) destroy;
- this->public.get_initiator = (bool (*) (ts_payload_t *)) get_initiator;
- this->public.set_initiator = (void (*) (ts_payload_t *,bool)) set_initiator;
- this->public.add_traffic_selector_substructure = (void (*) (ts_payload_t *,traffic_selector_substructure_t *)) add_traffic_selector_substructure;
- this->public.create_traffic_selector_substructure_iterator = (iterator_t* (*) (ts_payload_t *,bool)) create_traffic_selector_substructure_iterator;
- this->public.get_traffic_selectors = (linked_list_t *(*) (ts_payload_t *)) get_traffic_selectors;
-
- /* private variables */
- this->critical = FALSE;
- this->next_payload = NO_PAYLOAD;
- this->payload_length =TS_PAYLOAD_HEADER_LENGTH;
- this->is_initiator = is_initiator;
- this->number_of_traffic_selectors = 0;
- this->traffic_selectors = linked_list_create();
+ private_ts_payload_t *this;
- return &(this->public);
+ INIT(this,
+ .public = {
+ .payload_interface = {
+ .verify = _verify,
+ .get_encoding_rules = _get_encoding_rules,
+ .get_length = _get_length,
+ .get_next_type = _get_next_type,
+ .set_next_type = _set_next_type,
+ .get_type = _get_type,
+ .destroy = _destroy,
+ },
+ .get_initiator = _get_initiator,
+ .set_initiator = _set_initiator,
+ .get_traffic_selectors = _get_traffic_selectors,
+ .destroy = _destroy,
+ },
+ .next_payload = NO_PAYLOAD,
+ .payload_length = TS_PAYLOAD_HEADER_LENGTH,
+ .is_initiator = is_initiator,
+ .substrs = linked_list_create(),
+ );
+ return &this->public;
}
/*
* Described in header
*/
-ts_payload_t *ts_payload_create_from_traffic_selectors(bool is_initiator, linked_list_t *traffic_selectors)
+ts_payload_t *ts_payload_create_from_traffic_selectors(bool is_initiator,
+ linked_list_t *traffic_selectors)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
traffic_selector_t *ts;
- traffic_selector_substructure_t *ts_substructure;
+ traffic_selector_substructure_t *subst;
private_ts_payload_t *this;
this = (private_ts_payload_t*)ts_payload_create(is_initiator);
- iterator = traffic_selectors->create_iterator(traffic_selectors, TRUE);
- while (iterator->iterate(iterator, (void**)&ts))
+ enumerator = traffic_selectors->create_enumerator(traffic_selectors);
+ while (enumerator->enumerate(enumerator, &ts))
{
- ts_substructure = traffic_selector_substructure_create_from_traffic_selector(ts);
- this->public.add_traffic_selector_substructure(&(this->public), ts_substructure);
+ subst = traffic_selector_substructure_create_from_traffic_selector(ts);
+ this->substrs->insert_last(this->substrs, subst);
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
+ compute_length(this);
- return &(this->public);
+ return &this->public;
}
-
diff --git a/src/libcharon/encoding/payloads/ts_payload.h b/src/libcharon/encoding/payloads/ts_payload.h
index d322ff1a8..88ca00bc9 100644
--- a/src/libcharon/encoding/payloads/ts_payload.h
+++ b/src/libcharon/encoding/payloads/ts_payload.h
@@ -19,7 +19,6 @@
* @{ @ingroup payloads
*/
-
#ifndef TS_PAYLOAD_H_
#define TS_PAYLOAD_H_
@@ -36,13 +35,13 @@ typedef struct ts_payload_t ts_payload_t;
*/
#define TS_PAYLOAD_HEADER_LENGTH 8
-
/**
* Class representing an IKEv2 TS payload.
*
* The TS payload format is described in RFC section 3.13.
*/
struct ts_payload_t {
+
/**
* The payload_t interface.
*/
@@ -67,27 +66,6 @@ struct ts_payload_t {
void (*set_initiator) (ts_payload_t *this,bool is_initiator);
/**
- * Adds a traffic_selector_substructure_t object to this object.
- *
- * @param traffic_selector traffic_selector_substructure_t object to add
- */
- void (*add_traffic_selector_substructure) (ts_payload_t *this,
- traffic_selector_substructure_t *traffic_selector);
-
- /**
- * Creates an iterator of stored traffic_selector_substructure_t objects.
- *
- * When removing an traffic_selector_substructure_t object
- * using this iterator, the length of this payload
- * has to get refreshed by calling payload_t.get_length!
- *
- * @param forward iterator direction (TRUE: front to end)
- * @return created iterator_t object
- */
- iterator_t *(*create_traffic_selector_substructure_iterator) (
- ts_payload_t *this, bool forward);
-
- /**
* Get a list of nested traffic selectors as traffic_selector_t.
*
* Resulting list and its traffic selectors must be destroyed after usage
@@ -105,19 +83,15 @@ struct ts_payload_t {
/**
* Creates an empty ts_payload_t object.
*
- * @param is_initiator
- * - TRUE if this payload is of type TSi
- * - FALSE if this payload is of type TSr
- * @return ts_payload_t object
+ * @param is_initiator TRUE for TSi, FALSE for TSr payload type
+ * @return ts_payload_t object
*/
ts_payload_t *ts_payload_create(bool is_initiator);
/**
* Creates ts_payload with a list of traffic_selector_t
*
- * @param is_initiator
- * - TRUE if this payload is of type TSi
- * - FALSE if this payload is of type TSr
+ * @param is_initiator TRUE for TSi, FALSE for TSr payload type
* @param traffic_selectors list of traffic selectors to include
* @return ts_payload_t object
*/
diff --git a/src/libcharon/encoding/payloads/unknown_payload.c b/src/libcharon/encoding/payloads/unknown_payload.c
index dd5547dc3..27af338b3 100644
--- a/src/libcharon/encoding/payloads/unknown_payload.c
+++ b/src/libcharon/encoding/payloads/unknown_payload.c
@@ -18,8 +18,6 @@
#include "unknown_payload.h"
-
-
typedef struct private_unknown_payload_t private_unknown_payload_t;
/**
@@ -33,6 +31,11 @@ struct private_unknown_payload_t {
unknown_payload_t public;
/**
+ * Type of this payload
+ */
+ payload_type_t type;
+
+ /**
* Next payload type.
*/
u_int8_t next_payload;
@@ -43,6 +46,11 @@ struct private_unknown_payload_t {
bool critical;
/**
+ * Reserved bits
+ */
+ bool reserved[7];
+
+ /**
* Length of this payload.
*/
u_int16_t payload_length;
@@ -62,21 +70,21 @@ struct private_unknown_payload_t {
*/
encoding_rule_t unknown_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
- { U_INT_8, offsetof(private_unknown_payload_t, next_payload)},
+ { U_INT_8, offsetof(private_unknown_payload_t, next_payload) },
/* the critical bit */
- { FLAG, offsetof(private_unknown_payload_t, critical) },
- /* 7 Bit reserved bits, nowhere stored */
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
+ { FLAG, offsetof(private_unknown_payload_t, critical) },
+ /* 7 Bit reserved bits */
+ { RESERVED_BIT, offsetof(private_unknown_payload_t, reserved[0]) },
+ { RESERVED_BIT, offsetof(private_unknown_payload_t, reserved[1]) },
+ { RESERVED_BIT, offsetof(private_unknown_payload_t, reserved[2]) },
+ { RESERVED_BIT, offsetof(private_unknown_payload_t, reserved[3]) },
+ { RESERVED_BIT, offsetof(private_unknown_payload_t, reserved[4]) },
+ { RESERVED_BIT, offsetof(private_unknown_payload_t, reserved[5]) },
+ { RESERVED_BIT, offsetof(private_unknown_payload_t, reserved[6]) },
/* Length of the whole payload*/
- { PAYLOAD_LENGTH, offsetof(private_unknown_payload_t, payload_length)},
+ { 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) }
+ { UNKNOWN_DATA, offsetof(private_unknown_payload_t, data) },
};
/*
@@ -91,111 +99,109 @@ encoding_rule_t unknown_payload_encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
-/**
- * Implementation of payload_t.verify.
- */
-static status_t verify(private_unknown_payload_t *this)
+METHOD(payload_t, verify, status_t,
+ private_unknown_payload_t *this)
{
- /* can't do any checks, so we assume its good */
+ if (this->payload_length != UNKNOWN_PAYLOAD_HEADER_LENGTH + this->data.len)
+ {
+ return FAILED;
+ }
return SUCCESS;
}
-/**
- * Implementation of payload_t.get_encoding_rules.
- */
-static void get_encoding_rules(private_unknown_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, void,
+ private_unknown_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = unknown_payload_encodings;
*rule_count = sizeof(unknown_payload_encodings) / sizeof(encoding_rule_t);
}
-/**
- * Implementation of payload_t.get_type.
- */
-static payload_type_t get_payload_type(private_unknown_payload_t *this)
+METHOD(payload_t, get_payload_type, payload_type_t,
+ private_unknown_payload_t *this)
{
- return UNKNOWN_PAYLOAD;
+ return this->type;
}
-/**
- * Implementation of payload_t.get_next_type.
- */
-static payload_type_t get_next_type(private_unknown_payload_t *this)
+METHOD(payload_t, get_next_type, payload_type_t,
+ private_unknown_payload_t *this)
{
- return (this->next_payload);
+ return this->next_payload;
}
-/**
- * Implementation of payload_t.set_next_type.
- */
-static void set_next_type(private_unknown_payload_t *this,payload_type_t type)
+METHOD(payload_t, set_next_type, void,
+ private_unknown_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
-/**
- * Implementation of payload_t.get_length.
- */
-static size_t get_length(private_unknown_payload_t *this)
+METHOD(payload_t, get_length, size_t,
+ private_unknown_payload_t *this)
{
return this->payload_length;
}
-/**
- * Implementation of unknown_payload_t.get_data.
- */
-static bool is_critical(private_unknown_payload_t *this)
+METHOD(unknown_payload_t, is_critical, bool,
+ private_unknown_payload_t *this)
{
return this->critical;
}
-/**
- * Implementation of unknown_payload_t.get_data.
- */
-static chunk_t get_data (private_unknown_payload_t *this)
+METHOD(unknown_payload_t, get_data, chunk_t,
+ private_unknown_payload_t *this)
{
- return (this->data);
+ return this->data;
}
-/**
- * Implementation of payload_t.destroy and unknown_payload_t.destroy.
- */
-static void destroy(private_unknown_payload_t *this)
+METHOD2(payload_t, unknown_payload_t, destroy, void,
+ private_unknown_payload_t *this)
{
- if (this->data.ptr != NULL)
- {
- chunk_free(&(this->data));
- }
-
+ free(this->data.ptr);
free(this);
}
/*
* Described in header
*/
-unknown_payload_t *unknown_payload_create()
+unknown_payload_t *unknown_payload_create(payload_type_t type)
+{
+ private_unknown_payload_t *this;
+
+ INIT(this,
+ .public = {
+ .payload_interface = {
+ .verify = _verify,
+ .get_encoding_rules = _get_encoding_rules,
+ .get_length = _get_length,
+ .get_next_type = _get_next_type,
+ .set_next_type = _set_next_type,
+ .get_type = _get_payload_type,
+ .destroy = _destroy,
+ },
+ .is_critical = _is_critical,
+ .get_data = _get_data,
+ .destroy = _destroy,
+ },
+ .next_payload = NO_PAYLOAD,
+ .payload_length = UNKNOWN_PAYLOAD_HEADER_LENGTH,
+ .type = type,
+ );
+
+ return &this->public;
+}
+
+
+/*
+ * Described in header
+ */
+unknown_payload_t *unknown_payload_create_data(payload_type_t type,
+ bool critical, chunk_t data)
{
- private_unknown_payload_t *this = malloc_thing(private_unknown_payload_t);
-
- /* interface functions */
- this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
- this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
- this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
- this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
- this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
- this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
- this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
-
- /* public functions */
- this->public.destroy = (void (*) (unknown_payload_t *)) destroy;
- this->public.is_critical = (bool (*) (unknown_payload_t *)) is_critical;
- this->public.get_data = (chunk_t (*) (unknown_payload_t *)) get_data;
-
- /* private variables */
- this->critical = FALSE;
- this->next_payload = NO_PAYLOAD;
- this->payload_length = UNKNOWN_PAYLOAD_HEADER_LENGTH;
- this->data = chunk_empty;
-
- return (&(this->public));
+ private_unknown_payload_t *this;
+
+ this = (private_unknown_payload_t*)unknown_payload_create(type);
+ this->data = data;
+ this->critical = critical;
+ this->payload_length = UNKNOWN_PAYLOAD_HEADER_LENGTH + data.len;
+
+ return &this->public;
}
diff --git a/src/libcharon/encoding/payloads/unknown_payload.h b/src/libcharon/encoding/payloads/unknown_payload.h
index c761ed2b6..5ae85331b 100644
--- a/src/libcharon/encoding/payloads/unknown_payload.h
+++ b/src/libcharon/encoding/payloads/unknown_payload.h
@@ -70,10 +70,22 @@ struct unknown_payload_t {
};
/**
- * Creates an empty unknown_payload_t object.
+ * Creates an empty unknown_payload_t.
*
- * @return unknown_payload_t object
+ * @param type of the payload
+ * @return unknown_payload_t object
*/
-unknown_payload_t *unknown_payload_create(void);
+unknown_payload_t *unknown_payload_create(payload_type_t type);
+
+/**
+ * Create an unknown payload with data.
+ *
+ * @param type type of payload to create
+ * @param critical TRUE to set critical bit
+ * @param data data to set for this payload, gets owned by payload
+ * @return payload object
+ */
+unknown_payload_t *unknown_payload_create_data(payload_type_t type,
+ bool critical, chunk_t data);
#endif /** UNKNOWN_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/vendor_id_payload.c b/src/libcharon/encoding/payloads/vendor_id_payload.c
index bf33d2418..e9e80e989 100644
--- a/src/libcharon/encoding/payloads/vendor_id_payload.c
+++ b/src/libcharon/encoding/payloads/vendor_id_payload.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2005-2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -41,6 +42,11 @@ struct private_vendor_id_payload_t {
bool critical;
/**
+ * Reserved bits
+ */
+ bool reserved[7];
+
+ /**
* Length of this payload.
*/
u_int16_t payload_length;
@@ -59,21 +65,21 @@ struct private_vendor_id_payload_t {
*/
encoding_rule_t vendor_id_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
- { U_INT_8, offsetof(private_vendor_id_payload_t, next_payload) },
+ { U_INT_8, offsetof(private_vendor_id_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_vendor_id_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
- { RESERVED_BIT, 0 },
+ { RESERVED_BIT, offsetof(private_vendor_id_payload_t, reserved[0]) },
+ { RESERVED_BIT, offsetof(private_vendor_id_payload_t, reserved[1]) },
+ { RESERVED_BIT, offsetof(private_vendor_id_payload_t, reserved[2]) },
+ { RESERVED_BIT, offsetof(private_vendor_id_payload_t, reserved[3]) },
+ { RESERVED_BIT, offsetof(private_vendor_id_payload_t, reserved[4]) },
+ { RESERVED_BIT, offsetof(private_vendor_id_payload_t, reserved[5]) },
+ { RESERVED_BIT, offsetof(private_vendor_id_payload_t, reserved[6]) },
/* 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) }
+ { VID_DATA, offsetof(private_vendor_id_payload_t, data) }
};
/*
@@ -88,68 +94,52 @@ encoding_rule_t vendor_id_payload_encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
-/**
- * Implementation of payload_t.verify.
- */
-static status_t verify(private_vendor_id_payload_t *this)
+METHOD(payload_t, verify, status_t,
+ private_vendor_id_payload_t *this)
{
return SUCCESS;
}
-/**
- * Implementation of vendor_id_payload_t.get_encoding_rules.
- */
-static void get_encoding_rules(private_vendor_id_payload_t *this,
- encoding_rule_t **rules, size_t *rule_count)
+METHOD(payload_t, get_encoding_rules, void,
+ private_vendor_id_payload_t *this, encoding_rule_t **rules,
+ size_t *rule_count)
{
*rules = vendor_id_payload_encodings;
- *rule_count = sizeof(vendor_id_payload_encodings) / sizeof(encoding_rule_t);
+ *rule_count = countof(vendor_id_payload_encodings);
}
-/**
- * Implementation of payload_t.get_type.
- */
-static payload_type_t get_payload_type(private_vendor_id_payload_t *this)
+METHOD(payload_t, get_type, payload_type_t,
+ private_vendor_id_payload_t *this)
{
return VENDOR_ID;
}
-/**
- * Implementation of payload_t.get_next_type.
- */
-static payload_type_t get_next_type(private_vendor_id_payload_t *this)
+METHOD(payload_t, get_next_type, payload_type_t,
+ private_vendor_id_payload_t *this)
{
return this->next_payload;
}
-/**
- * Implementation of payload_t.set_next_type.
- */
-static void set_next_type(private_vendor_id_payload_t *this,payload_type_t type)
+METHOD(payload_t, set_next_type, void,
+ private_vendor_id_payload_t *this, payload_type_t type)
{
this->next_payload = type;
}
-/**
- * Implementation of payload_t.get_length.
- */
-static size_t get_length(private_vendor_id_payload_t *this)
+METHOD(payload_t, get_length, size_t,
+ private_vendor_id_payload_t *this)
{
return this->payload_length;
}
-/**
- * Implementation of vendor_id_payload_t.get_data.
- */
-static chunk_t get_data(private_vendor_id_payload_t *this)
+METHOD(vendor_id_payload_t, get_data, chunk_t,
+ private_vendor_id_payload_t *this)
{
return this->data;
}
-/**
- * Implementation of payload_t.destroy and vendor_id_payload_t.destroy.
- */
-static void destroy(private_vendor_id_payload_t *this)
+METHOD2(payload_t, vendor_id_payload_t, destroy, void,
+ private_vendor_id_payload_t *this)
{
free(this->data.ptr);
free(this);
@@ -158,38 +148,35 @@ static void destroy(private_vendor_id_payload_t *this)
/*
* Described in header
*/
-vendor_id_payload_t *vendor_id_payload_create()
+vendor_id_payload_t *vendor_id_payload_create_data(chunk_t data)
{
- private_vendor_id_payload_t *this = malloc_thing(private_vendor_id_payload_t);
-
- this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
- this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
- this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
- this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
- this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
- this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
- this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
- this->public.get_data = (chunk_t (*) (vendor_id_payload_t *)) get_data;
-
- this->critical = FALSE;
- this->next_payload = NO_PAYLOAD;
- this->payload_length = VENDOR_ID_PAYLOAD_HEADER_LENGTH;
- this->data = chunk_empty;
+ private_vendor_id_payload_t *this;
+ INIT(this,
+ .public = {
+ .payload_interface = {
+ .verify = _verify,
+ .get_encoding_rules = _get_encoding_rules,
+ .get_length = _get_length,
+ .get_next_type = _get_next_type,
+ .set_next_type = _set_next_type,
+ .get_type = _get_type,
+ .destroy = _destroy,
+ },
+ .get_data = _get_data,
+ .destroy = _destroy,
+ },
+ .next_payload = NO_PAYLOAD,
+ .payload_length = VENDOR_ID_PAYLOAD_HEADER_LENGTH + data.len,
+ .data = data,
+ );
return &this->public;
}
/*
* Described in header
*/
-vendor_id_payload_t *vendor_id_payload_create_data(chunk_t data)
+vendor_id_payload_t *vendor_id_payload_create()
{
- private_vendor_id_payload_t *this;
-
- this = (private_vendor_id_payload_t*)vendor_id_payload_create();
- this->payload_length += data.len;
- this->data = data;
-
- return &this->public;
+ return vendor_id_payload_create_data(chunk_empty);
}
-
diff --git a/src/libcharon/encoding/payloads/vendor_id_payload.h b/src/libcharon/encoding/payloads/vendor_id_payload.h
index 241535cac..4e4e7d8eb 100644
--- a/src/libcharon/encoding/payloads/vendor_id_payload.h
+++ b/src/libcharon/encoding/payloads/vendor_id_payload.h
@@ -50,6 +50,11 @@ struct vendor_id_payload_t {
* @return VID data, pointing to an internal chunk_t
*/
chunk_t (*get_data)(vendor_id_payload_t *this);
+
+ /**
+ * Destroy Vendor ID payload.
+ */
+ void (*destroy)(vendor_id_payload_t *this);
};
/**
diff --git a/src/libcharon/plugins/addrblock/Makefile.in b/src/libcharon/plugins/addrblock/Makefile.in
index 426d1a689..018318a59 100644
--- a/src/libcharon/plugins/addrblock/Makefile.in
+++ b/src/libcharon/plugins/addrblock/Makefile.in
@@ -223,9 +223,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -264,6 +262,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/addrblock/addrblock_validator.c b/src/libcharon/plugins/addrblock/addrblock_validator.c
index 44ef38d85..12cf0c941 100644
--- a/src/libcharon/plugins/addrblock/addrblock_validator.c
+++ b/src/libcharon/plugins/addrblock/addrblock_validator.c
@@ -1,8 +1,6 @@
/*
- * Copyright (C) 2010 Martin Willi
- * Copyright (C) 2010 revosec AG
- * Copyright (C) 2009 Andreas Steffen
- * Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2010 Martin Willi, revosec AG
+ * Copyright (C) 2009 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -90,7 +88,8 @@ static bool check_addrblock(x509_t *subject, x509_t *issuer)
METHOD(cert_validator_t, validate, bool,
private_addrblock_validator_t *this, certificate_t *subject,
- certificate_t *issuer, bool online, int pathlen, auth_cfg_t *auth)
+ certificate_t *issuer, bool online, int pathlen, bool anchor,
+ auth_cfg_t *auth)
{
if (subject->get_type(subject) == CERT_X509 &&
issuer->get_type(issuer) == CERT_X509)
diff --git a/src/libcharon/plugins/android/Makefile.in b/src/libcharon/plugins/android/Makefile.in
index d80868798..7d6eb2b9c 100644
--- a/src/libcharon/plugins/android/Makefile.in
+++ b/src/libcharon/plugins/android/Makefile.in
@@ -223,9 +223,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -264,6 +262,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/android/android_creds.c b/src/libcharon/plugins/android/android_creds.c
index aa7fc6f92..601c91e7b 100644
--- a/src/libcharon/plugins/android/android_creds.c
+++ b/src/libcharon/plugins/android/android_creds.c
@@ -235,7 +235,7 @@ METHOD(android_creds_t, set_username_password, void,
DESTROY_IF(this->user);
this->user = id->clone(id);
free(this->pass);
- this->pass = password ? strdup(password) : NULL;
+ this->pass = strdupnull(password);
this->lock->unlock(this->lock);
}
diff --git a/src/libcharon/plugins/android/android_service.c b/src/libcharon/plugins/android/android_service.c
index f9a8e1ea1..487567f2a 100644
--- a/src/libcharon/plugins/android/android_service.c
+++ b/src/libcharon/plugins/android/android_service.c
@@ -291,8 +291,8 @@ static job_requeue_t initiate(private_android_service_t *this)
peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
child_cfg = child_cfg_create("android", &lifetime, NULL, TRUE, MODE_TUNNEL,
- ACTION_NONE, ACTION_NONE, FALSE, 0, 0,
- NULL, NULL);
+ ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE,
+ 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);
diff --git a/src/libcharon/plugins/dhcp/Makefile.in b/src/libcharon/plugins/dhcp/Makefile.in
index e843c42e8..8046fc052 100644
--- a/src/libcharon/plugins/dhcp/Makefile.in
+++ b/src/libcharon/plugins/dhcp/Makefile.in
@@ -220,9 +220,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -261,6 +259,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/dhcp/dhcp_socket.c b/src/libcharon/plugins/dhcp/dhcp_socket.c
index e1e83d648..8851c1b79 100644
--- a/src/libcharon/plugins/dhcp/dhcp_socket.c
+++ b/src/libcharon/plugins/dhcp/dhcp_socket.c
@@ -459,7 +459,7 @@ static void handle_offer(private_dhcp_socket_t *this, dhcp_t *dhcp, int optlen)
{
dhcp_transaction_t *transaction = NULL;
enumerator_t *enumerator;
- host_t *offer, *server;
+ host_t *offer, *server = NULL;
offer = host_create_from_chunk(AF_INET,
chunk_from_thing(dhcp->your_address), 0);
@@ -500,7 +500,7 @@ static void handle_offer(private_dhcp_socket_t *this, dhcp_t *dhcp, int optlen)
chunk_create((char*)&option->data[pos], 4));
}
}
- if (option->type == DHCP_SERVER_ID && option->len == 4)
+ if (!server && option->type == DHCP_SERVER_ID && option->len == 4)
{
server = host_create_from_chunk(AF_INET,
chunk_create(option->data, 4), DHCP_SERVER_PORT);
@@ -515,12 +515,11 @@ static void handle_offer(private_dhcp_socket_t *this, dhcp_t *dhcp, int optlen)
}
DBG1(DBG_CFG, "received DHCP OFFER %H from %H", offer, server);
transaction->set_address(transaction, offer->clone(offer));
- transaction->set_server(transaction, server->clone(server));
+ transaction->set_server(transaction, server);
}
this->mutex->unlock(this->mutex);
this->condvar->broadcast(this->condvar);
offer->destroy(offer);
- server->destroy(server);
}
/**
diff --git a/src/libcharon/plugins/eap_aka/Makefile.in b/src/libcharon/plugins/eap_aka/Makefile.in
index c0750786d..4a23f9010 100644
--- a/src/libcharon/plugins/eap_aka/Makefile.in
+++ b/src/libcharon/plugins/eap_aka/Makefile.in
@@ -223,9 +223,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -264,6 +262,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in
index 41f69546e..ad1ae1906 100644
--- a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in
+++ b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in
@@ -224,9 +224,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -265,6 +263,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/eap_gtc/Makefile.in b/src/libcharon/plugins/eap_gtc/Makefile.in
index 02d659197..142a35e50 100644
--- a/src/libcharon/plugins/eap_gtc/Makefile.in
+++ b/src/libcharon/plugins/eap_gtc/Makefile.in
@@ -221,9 +221,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -262,6 +260,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/eap_identity/Makefile.in b/src/libcharon/plugins/eap_identity/Makefile.in
index 46011694a..5c1e07ade 100644
--- a/src/libcharon/plugins/eap_identity/Makefile.in
+++ b/src/libcharon/plugins/eap_identity/Makefile.in
@@ -223,9 +223,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -264,6 +262,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/eap_md5/Makefile.in b/src/libcharon/plugins/eap_md5/Makefile.in
index 2e307147f..4e01d96cc 100644
--- a/src/libcharon/plugins/eap_md5/Makefile.in
+++ b/src/libcharon/plugins/eap_md5/Makefile.in
@@ -221,9 +221,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -262,6 +260,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/eap_mschapv2/Makefile.in b/src/libcharon/plugins/eap_mschapv2/Makefile.in
index 635cfe6ec..495ccf441 100644
--- a/src/libcharon/plugins/eap_mschapv2/Makefile.in
+++ b/src/libcharon/plugins/eap_mschapv2/Makefile.in
@@ -223,9 +223,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -264,6 +262,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/eap_radius/Makefile.in b/src/libcharon/plugins/eap_radius/Makefile.in
index 1d771d9a4..99084e2c1 100644
--- a/src/libcharon/plugins/eap_radius/Makefile.in
+++ b/src/libcharon/plugins/eap_radius/Makefile.in
@@ -224,9 +224,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -265,6 +263,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/eap_sim/Makefile.in b/src/libcharon/plugins/eap_sim/Makefile.in
index d05930bbd..90f203f61 100644
--- a/src/libcharon/plugins/eap_sim/Makefile.in
+++ b/src/libcharon/plugins/eap_sim/Makefile.in
@@ -223,9 +223,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -264,6 +262,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/eap_sim_file/Makefile.in b/src/libcharon/plugins/eap_sim_file/Makefile.in
index 46a584265..3cd766a75 100644
--- a/src/libcharon/plugins/eap_sim_file/Makefile.in
+++ b/src/libcharon/plugins/eap_sim_file/Makefile.in
@@ -224,9 +224,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -265,6 +263,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in
index 2d8556a59..a48fb652a 100644
--- a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in
+++ b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in
@@ -225,9 +225,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -266,6 +264,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/eap_simaka_reauth/Makefile.in b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in
index e59015f82..f2af3ae0d 100644
--- a/src/libcharon/plugins/eap_simaka_reauth/Makefile.in
+++ b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in
@@ -224,9 +224,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -265,6 +263,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/eap_simaka_sql/Makefile.in b/src/libcharon/plugins/eap_simaka_sql/Makefile.in
index 3c66d2f36..9a58a6055 100644
--- a/src/libcharon/plugins/eap_simaka_sql/Makefile.in
+++ b/src/libcharon/plugins/eap_simaka_sql/Makefile.in
@@ -223,9 +223,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -264,6 +262,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/eap_tls/Makefile.in b/src/libcharon/plugins/eap_tls/Makefile.in
index e4b78faf8..9ebb85be9 100644
--- a/src/libcharon/plugins/eap_tls/Makefile.in
+++ b/src/libcharon/plugins/eap_tls/Makefile.in
@@ -222,9 +222,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -263,6 +261,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/eap_tnc/Makefile.in b/src/libcharon/plugins/eap_tnc/Makefile.in
index fb7108a8a..cf75585ef 100644
--- a/src/libcharon/plugins/eap_tnc/Makefile.in
+++ b/src/libcharon/plugins/eap_tnc/Makefile.in
@@ -222,9 +222,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -263,6 +261,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/eap_tnc/eap_tnc.c b/src/libcharon/plugins/eap_tnc/eap_tnc.c
index f0bff0e1f..dd4ed5322 100644
--- a/src/libcharon/plugins/eap_tnc/eap_tnc.c
+++ b/src/libcharon/plugins/eap_tnc/eap_tnc.c
@@ -18,7 +18,7 @@
#include <tls_eap.h>
#include <daemon.h>
-#include <library.h>
+#include <debug.h>
typedef struct private_eap_tnc_t private_eap_tnc_t;
@@ -114,6 +114,8 @@ static eap_tnc_t *eap_tnc_create(identification_t *server,
private_eap_tnc_t *this;
size_t frag_size;
int max_msg_count;
+ char* protocol;
+ tnccs_type_t type;
tnccs_t *tnccs;
INIT(this,
@@ -133,7 +135,27 @@ static eap_tnc_t *eap_tnc_create(identification_t *server,
"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);
- tnccs = charon->tnccs->create_instance(charon->tnccs, TNCCS_1_1, is_server);
+ protocol = lib->settings->get_str(lib->settings,
+ "charon.plugins.eap-tnc.protocol", "tnccs-1.1");
+ if (strcaseeq(protocol, "tnccs-2.0"))
+ {
+ type = TNCCS_2_0;
+ }
+ else if (strcaseeq(protocol, "tnccs-1.1"))
+ {
+ type = TNCCS_1_1;
+ }
+ else if (strcaseeq(protocol, "tnccs-dynamic") && is_server)
+ {
+ type = TNCCS_DYNAMIC;
+ }
+ else
+ {
+ DBG1(DBG_TNC, "TNCCS protocol '%s' not supported", protocol);
+ free(this);
+ return NULL;
+ }
+ tnccs = charon->tnccs->create_instance(charon->tnccs, type, is_server);
this->tls_eap = tls_eap_create(EAP_TNC, (tls_t*)tnccs, frag_size, max_msg_count);
if (!this->tls_eap)
{
diff --git a/src/libcharon/plugins/eap_ttls/Makefile.in b/src/libcharon/plugins/eap_ttls/Makefile.in
index 2cdd7701d..ff67686b2 100644
--- a/src/libcharon/plugins/eap_ttls/Makefile.in
+++ b/src/libcharon/plugins/eap_ttls/Makefile.in
@@ -225,9 +225,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -266,6 +264,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c b/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c
index 10d08ca2a..29b0a9303 100644
--- a/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c
+++ b/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c
@@ -196,6 +196,7 @@ METHOD(tls_application_t, process, status_t,
in->destroy(in);
return NEED_MORE;
}
+ this->start_phase2 = FALSE;
}
type = this->method->get_type(this->method, &vendor);
diff --git a/src/libcharon/plugins/farp/Makefile.in b/src/libcharon/plugins/farp/Makefile.in
index bfd50d6da..21e8b78db 100644
--- a/src/libcharon/plugins/farp/Makefile.in
+++ b/src/libcharon/plugins/farp/Makefile.in
@@ -220,9 +220,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -261,6 +259,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/ha/Makefile.in b/src/libcharon/plugins/ha/Makefile.in
index 3600eb7c6..2fcd7cc82 100644
--- a/src/libcharon/plugins/ha/Makefile.in
+++ b/src/libcharon/plugins/ha/Makefile.in
@@ -222,9 +222,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -263,6 +261,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/ha/ha_ctl.c b/src/libcharon/plugins/ha/ha_ctl.c
index 980c0551a..15f7824f9 100644
--- a/src/libcharon/plugins/ha/ha_ctl.c
+++ b/src/libcharon/plugins/ha/ha_ctl.c
@@ -21,8 +21,8 @@
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
-#include <pthread.h>
+#include <threading/thread.h>
#include <processing/jobs/callback_job.h>
#define HA_FIFO IPSEC_PIDDIR "/charon.ha"
@@ -60,13 +60,14 @@ struct private_ha_ctl_t {
*/
static job_requeue_t dispatch_fifo(private_ha_ctl_t *this)
{
- int fifo, old;
+ int fifo;
+ bool oldstate;
char buf[8];
u_int segment;
- pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old);
+ oldstate = thread_cancelability(TRUE);
fifo = open(HA_FIFO, O_RDONLY);
- pthread_setcancelstate(old, NULL);
+ thread_cancelability(oldstate);
if (fifo == -1)
{
DBG1(DBG_CFG, "opening HA fifo failed: %s", strerror(errno));
diff --git a/src/libcharon/plugins/ha/ha_dispatcher.c b/src/libcharon/plugins/ha/ha_dispatcher.c
index b46a221bd..85dc0f4a4 100644
--- a/src/libcharon/plugins/ha/ha_dispatcher.c
+++ b/src/libcharon/plugins/ha/ha_dispatcher.c
@@ -596,9 +596,9 @@ static void process_child_add(private_ha_dispatcher_t *this,
if (initiator)
{
if (child_sa->install(child_sa, encr_r, integ_r, inbound_spi,
- inbound_cpi, TRUE, local_ts, remote_ts) != SUCCESS ||
+ inbound_cpi, TRUE, TRUE, local_ts, remote_ts) != SUCCESS ||
child_sa->install(child_sa, encr_i, integ_i, outbound_spi,
- outbound_cpi, FALSE, local_ts, remote_ts) != SUCCESS)
+ outbound_cpi, FALSE, TRUE, local_ts, remote_ts) != SUCCESS)
{
failed = TRUE;
}
@@ -606,9 +606,9 @@ static void process_child_add(private_ha_dispatcher_t *this,
else
{
if (child_sa->install(child_sa, encr_i, integ_i, inbound_spi,
- inbound_cpi, TRUE, local_ts, remote_ts) != SUCCESS ||
+ inbound_cpi, TRUE, TRUE, local_ts, remote_ts) != SUCCESS ||
child_sa->install(child_sa, encr_r, integ_r, outbound_spi,
- outbound_cpi, FALSE, local_ts, remote_ts) != SUCCESS)
+ outbound_cpi, FALSE, TRUE, local_ts, remote_ts) != SUCCESS)
{
failed = TRUE;
}
diff --git a/src/libcharon/plugins/ha/ha_segments.c b/src/libcharon/plugins/ha/ha_segments.c
index 19e0f692e..7c7bef851 100644
--- a/src/libcharon/plugins/ha/ha_segments.c
+++ b/src/libcharon/plugins/ha/ha_segments.c
@@ -15,11 +15,10 @@
#include "ha_segments.h"
-#include <pthread.h>
-
#include <threading/mutex.h>
#include <threading/condvar.h>
#include <utils/linked_list.h>
+#include <threading/thread.h>
#include <processing/jobs/callback_job.h>
#define DEFAULT_HEARTBEAT_DELAY 1000
@@ -255,16 +254,15 @@ METHOD(listener_t, alert_hook, bool,
*/
static job_requeue_t watchdog(private_ha_segments_t *this)
{
- int oldstate;
- bool timeout;
+ bool timeout, oldstate;
this->mutex->lock(this->mutex);
- pthread_cleanup_push((void*)this->mutex->unlock, this->mutex);
- pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
+ thread_cleanup_push((void*)this->mutex->unlock, this->mutex);
+ oldstate = thread_cancelability(TRUE);
timeout = this->condvar->timed_wait(this->condvar, this->mutex,
this->heartbeat_timeout);
- pthread_setcancelstate(oldstate, NULL);
- pthread_cleanup_pop(TRUE);
+ thread_cancelability(oldstate);
+ thread_cleanup_pop(TRUE);
if (timeout)
{
DBG1(DBG_CFG, "no heartbeat received, taking all segments");
diff --git a/src/libcharon/plugins/ha/ha_socket.c b/src/libcharon/plugins/ha/ha_socket.c
index 614c70ed3..086178442 100644
--- a/src/libcharon/plugins/ha/ha_socket.c
+++ b/src/libcharon/plugins/ha/ha_socket.c
@@ -20,10 +20,10 @@
#include <sys/socket.h>
#include <errno.h>
#include <unistd.h>
-#include <pthread.h>
#include <daemon.h>
#include <utils/host.h>
+#include <threading/thread.h>
#include <processing/jobs/callback_job.h>
typedef struct private_ha_socket_t private_ha_socket_t;
@@ -121,12 +121,12 @@ METHOD(ha_socket_t, pull, ha_message_t*,
{
ha_message_t *message;
char buf[1024];
- int oldstate;
+ bool oldstate;
ssize_t len;
- pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
+ oldstate = thread_cancelability(TRUE);
len = recv(this->fd, buf, sizeof(buf), 0);
- pthread_setcancelstate(oldstate, NULL);
+ thread_cancelability(oldstate);
if (len <= 0)
{
switch (errno)
diff --git a/src/libcharon/plugins/ha/ha_tunnel.c b/src/libcharon/plugins/ha/ha_tunnel.c
index fef84a430..299053ec1 100644
--- a/src/libcharon/plugins/ha/ha_tunnel.c
+++ b/src/libcharon/plugins/ha/ha_tunnel.c
@@ -223,8 +223,8 @@ static void setup_tunnel(private_ha_tunnel_t *this,
peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE);
child_cfg = child_cfg_create("ha", &lifetime, NULL, TRUE, MODE_TRANSPORT,
- ACTION_NONE, ACTION_NONE, FALSE, 0, 0,
- NULL, NULL);
+ ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE,
+ 0, 0, NULL, NULL, 0);
ts = traffic_selector_create_dynamic(IPPROTO_UDP, HA_PORT, HA_PORT);
child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
ts = traffic_selector_create_dynamic(IPPROTO_ICMP, 0, 65535);
diff --git a/src/libcharon/plugins/led/Makefile.in b/src/libcharon/plugins/led/Makefile.in
index a4e529d89..fa1194fd0 100644
--- a/src/libcharon/plugins/led/Makefile.in
+++ b/src/libcharon/plugins/led/Makefile.in
@@ -219,9 +219,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -260,6 +258,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/load_tester/Makefile.in b/src/libcharon/plugins/load_tester/Makefile.in
index 85db9a10b..c921ec3db 100644
--- a/src/libcharon/plugins/load_tester/Makefile.in
+++ b/src/libcharon/plugins/load_tester/Makefile.in
@@ -225,9 +225,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -266,6 +264,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/load_tester/load_tester_config.c b/src/libcharon/plugins/load_tester/load_tester_config.c
index a230aa3f5..71391d593 100644
--- a/src/libcharon/plugins/load_tester/load_tester_config.c
+++ b/src/libcharon/plugins/load_tester/load_tester_config.c
@@ -224,8 +224,8 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num)
}
child_cfg = child_cfg_create("load-test", &lifetime, NULL, TRUE, MODE_TUNNEL,
- ACTION_NONE, ACTION_NONE, FALSE, 0, 0,
- NULL, NULL);
+ ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE,
+ 0, 0, NULL, NULL, 0);
proposal = proposal_create_from_string(PROTO_ESP, "aes128-sha1");
child_cfg->add_proposal(child_cfg, proposal);
ts = traffic_selector_create_dynamic(0, 0, 65535);
diff --git a/src/libcharon/plugins/load_tester/load_tester_ipsec.c b/src/libcharon/plugins/load_tester/load_tester_ipsec.c
index aece95e12..ef9d7f9ef 100644
--- a/src/libcharon/plugins/load_tester/load_tester_ipsec.c
+++ b/src/libcharon/plugins/load_tester/load_tester_ipsec.c
@@ -52,7 +52,7 @@ METHOD(kernel_ipsec_t, get_cpi, status_t,
METHOD(kernel_ipsec_t, add_sa, status_t,
private_load_tester_ipsec_t *this, host_t *src, host_t *dst,
u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark,
- lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
+ u_int32_t tfc, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp,
u_int16_t cpi, bool encap, bool inbound, traffic_selector_t *src_ts,
traffic_selector_t *dst_ts)
diff --git a/src/libcharon/plugins/load_tester/load_tester_plugin.c b/src/libcharon/plugins/load_tester/load_tester_plugin.c
index cb9b80c7f..8fd65adfa 100644
--- a/src/libcharon/plugins/load_tester/load_tester_plugin.c
+++ b/src/libcharon/plugins/load_tester/load_tester_plugin.c
@@ -28,6 +28,8 @@
#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;
/**
@@ -189,7 +191,7 @@ plugin_t *load_tester_plugin_create()
this = malloc_thing(private_load_tester_plugin_t);
this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
- lib->crypto->add_dh(lib->crypto, MODP_NULL,
+ lib->crypto->add_dh(lib->crypto, MODP_NULL, plugin_name,
(dh_constructor_t)load_tester_diffie_hellman_create);
this->delay = lib->settings->get_int(lib->settings,
diff --git a/src/libcharon/plugins/maemo/Makefile.am b/src/libcharon/plugins/maemo/Makefile.am
index ed6c76c0f..0bf7fad5d 100644
--- a/src/libcharon/plugins/maemo/Makefile.am
+++ b/src/libcharon/plugins/maemo/Makefile.am
@@ -19,5 +19,9 @@ libstrongswan_maemo_la_LIBADD = ${maemo_LIBS}
dbusservice_DATA = org.strongswan.charon.service
-EXTRA_DIST = $(dbusservice_DATA)
+org.strongswan.charon.service: $(srcdir)/org.strongswan.charon.service.in
+ sed -e 's|[@]LIBEXECDIR[@]|$(libexecdir)|' $< >$@
+
+EXTRA_DIST = org.strongswan.charon.service.in
+CLEANFILES = $(dbusservice_DATA)
diff --git a/src/libcharon/plugins/maemo/Makefile.in b/src/libcharon/plugins/maemo/Makefile.in
index 978950d22..0ca1fa436 100644
--- a/src/libcharon/plugins/maemo/Makefile.in
+++ b/src/libcharon/plugins/maemo/Makefile.in
@@ -224,9 +224,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -265,6 +263,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
@@ -288,7 +288,8 @@ libstrongswan_maemo_la_SOURCES = \
libstrongswan_maemo_la_LDFLAGS = -module -avoid-version
libstrongswan_maemo_la_LIBADD = ${maemo_LIBS}
dbusservice_DATA = org.strongswan.charon.service
-EXTRA_DIST = $(dbusservice_DATA)
+EXTRA_DIST = org.strongswan.charon.service.in
+CLEANFILES = $(dbusservice_DATA)
all: all-am
.SUFFIXES:
@@ -528,6 +529,7 @@ install-strip:
mostlyclean-generic:
clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
@@ -626,6 +628,9 @@ uninstall-am: uninstall-dbusserviceDATA uninstall-pluginLTLIBRARIES
uninstall-pluginLTLIBRARIES
+org.strongswan.charon.service: $(srcdir)/org.strongswan.charon.service.in
+ sed -e 's|[@]LIBEXECDIR[@]|$(libexecdir)|' $< >$@
+
# 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/maemo/maemo_service.c b/src/libcharon/plugins/maemo/maemo_service.c
index efd914a00..0e9fd8ccc 100644
--- a/src/libcharon/plugins/maemo/maemo_service.c
+++ b/src/libcharon/plugins/maemo/maemo_service.c
@@ -115,12 +115,11 @@ METHOD(listener_t, ike_updown, bool,
return TRUE;
}
-METHOD(listener_t, child_state_change, bool,
- private_maemo_service_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
- child_sa_state_t state)
+METHOD(listener_t, ike_state_change, bool,
+ private_maemo_service_t *this, ike_sa_t *ike_sa, ike_sa_state_t state)
{
/* this call back is only registered during initiation */
- if (this->ike_sa == ike_sa && state == CHILD_DESTROYING)
+ if (this->ike_sa == ike_sa && state == IKE_DESTROYING)
{
change_status(this, VPN_STATUS_CONNECTION_FAILED);
return FALSE;
@@ -138,7 +137,7 @@ METHOD(listener_t, child_updown, bool,
{
/* disable hooks registered to catch initiation failures */
this->public.listener.ike_updown = NULL;
- this->public.listener.child_state_change = NULL;
+ this->public.listener.ike_state_change = NULL;
change_status(this, VPN_STATUS_CONNECTED);
}
else
@@ -347,7 +346,7 @@ static gboolean initiate_connection(private_maemo_service_t *this,
child_cfg = child_cfg_create(this->current, &lifetime, NULL /* updown */,
TRUE, MODE_TUNNEL, ACTION_NONE, ACTION_NONE,
- FALSE, 0, 0, NULL, NULL);
+ ACTION_NONE, FALSE, 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);
@@ -371,7 +370,7 @@ static gboolean initiate_connection(private_maemo_service_t *this,
this->ike_sa = ike_sa;
this->status = VPN_STATUS_CONNECTING;
this->public.listener.ike_updown = _ike_updown;
- this->public.listener.child_state_change = _child_state_change;
+ this->public.listener.ike_state_change = _ike_state_change;
charon->bus->add_listener(charon->bus, &this->public.listener);
if (ike_sa->initiate(ike_sa, child_cfg, 0, NULL, NULL) != SUCCESS)
@@ -464,7 +463,7 @@ maemo_service_t *maemo_service_create()
.public = {
.listener = {
.ike_updown = _ike_updown,
- .child_state_change = _child_state_change,
+ .ike_state_change = _ike_state_change,
.child_updown = _child_updown,
.ike_rekey = _ike_rekey,
},
diff --git a/src/libcharon/plugins/maemo/org.strongswan.charon.service b/src/libcharon/plugins/maemo/org.strongswan.charon.service
deleted file mode 100644
index 7dd31ed60..000000000
--- a/src/libcharon/plugins/maemo/org.strongswan.charon.service
+++ /dev/null
@@ -1,4 +0,0 @@
-[D-BUS Service]
-Name=org.strongswan.charon
-Exec=/usr/bin/run-standalone.sh /usr/libexec/ipsec/charon
-User=root
diff --git a/src/libcharon/plugins/maemo/org.strongswan.charon.service.in b/src/libcharon/plugins/maemo/org.strongswan.charon.service.in
new file mode 100644
index 000000000..8fa83af93
--- /dev/null
+++ b/src/libcharon/plugins/maemo/org.strongswan.charon.service.in
@@ -0,0 +1,4 @@
+[D-BUS Service]
+Name=org.strongswan.charon
+Exec=/usr/bin/run-standalone.sh @LIBEXECDIR@/ipsec/charon
+User=root
diff --git a/src/libcharon/plugins/medcli/Makefile.in b/src/libcharon/plugins/medcli/Makefile.in
index 6dcbc99dd..372a436a6 100644
--- a/src/libcharon/plugins/medcli/Makefile.in
+++ b/src/libcharon/plugins/medcli/Makefile.in
@@ -222,9 +222,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -263,6 +261,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/medcli/medcli_config.c b/src/libcharon/plugins/medcli/medcli_config.c
index 870d87c7e..b5672dba9 100644
--- a/src/libcharon/plugins/medcli/medcli_config.c
+++ b/src/libcharon/plugins/medcli/medcli_config.c
@@ -182,8 +182,8 @@ static peer_cfg_t *get_peer_cfg_by_name(private_medcli_config_t *this, char *nam
peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE, MODE_TUNNEL,
- ACTION_NONE, ACTION_NONE, FALSE, 0, 0,
- NULL, NULL);
+ ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE,
+ 0, 0, NULL, NULL, 0);
child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
child_cfg->add_traffic_selector(child_cfg, TRUE, ts_from_string(local_net));
child_cfg->add_traffic_selector(child_cfg, FALSE, ts_from_string(remote_net));
@@ -261,8 +261,8 @@ static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg)
this->current->add_auth_cfg(this->current, auth, FALSE);
child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE, MODE_TUNNEL,
- ACTION_NONE, ACTION_NONE, FALSE, 0, 0,
- NULL, NULL);
+ ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE,
+ 0, 0, NULL, NULL, 0);
child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
child_cfg->add_traffic_selector(child_cfg, TRUE, ts_from_string(local_net));
child_cfg->add_traffic_selector(child_cfg, FALSE, ts_from_string(remote_net));
diff --git a/src/libcharon/plugins/medsrv/Makefile.in b/src/libcharon/plugins/medsrv/Makefile.in
index f6db7d834..4bb65bd09 100644
--- a/src/libcharon/plugins/medsrv/Makefile.in
+++ b/src/libcharon/plugins/medsrv/Makefile.in
@@ -222,9 +222,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -263,6 +261,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/nm/Makefile.in b/src/libcharon/plugins/nm/Makefile.in
index 2f5c20971..69af7bf83 100644
--- a/src/libcharon/plugins/nm/Makefile.in
+++ b/src/libcharon/plugins/nm/Makefile.in
@@ -221,9 +221,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -262,6 +260,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/nm/nm_creds.c b/src/libcharon/plugins/nm/nm_creds.c
index 638787019..ea98c056d 100644
--- a/src/libcharon/plugins/nm/nm_creds.c
+++ b/src/libcharon/plugins/nm/nm_creds.c
@@ -400,7 +400,7 @@ static void set_username_password(private_nm_creds_t *this, identification_t *id
DESTROY_IF(this->user);
this->user = id->clone(id);
free(this->pass);
- this->pass = password ? strdup(password) : NULL;
+ this->pass = strdupnull(password);
this->lock->unlock(this->lock);
}
@@ -411,7 +411,7 @@ static void set_key_password(private_nm_creds_t *this, char *password)
{
this->lock->write_lock(this->lock);
free(this->keypass);
- this->keypass = password ? strdup(password) : NULL;
+ this->keypass = strdupnull(password);
this->lock->unlock(this->lock);
}
@@ -423,7 +423,7 @@ static void set_pin(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 = pin ? strdup(pin) : NULL;
+ this->keypass = strdupnull(pin);
this->keyid = chunk_clone(keyid);
this->lock->unlock(this->lock);
}
diff --git a/src/libcharon/plugins/nm/nm_service.c b/src/libcharon/plugins/nm/nm_service.c
index 72c5bbbb5..4300b57cf 100644
--- a/src/libcharon/plugins/nm/nm_service.c
+++ b/src/libcharon/plugins/nm/nm_service.c
@@ -518,8 +518,8 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
child_cfg = child_cfg_create(priv->name, &lifetime,
NULL, TRUE, MODE_TUNNEL, /* updown, hostaccess */
- ACTION_NONE, ACTION_NONE, ipcomp, 0, 0,
- NULL, NULL);
+ 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);
diff --git a/src/libcharon/plugins/smp/Makefile.in b/src/libcharon/plugins/smp/Makefile.in
index f24e2d1e7..3d2cef13c 100644
--- a/src/libcharon/plugins/smp/Makefile.in
+++ b/src/libcharon/plugins/smp/Makefile.in
@@ -220,9 +220,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -261,6 +259,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/socket_default/Makefile.in b/src/libcharon/plugins/socket_default/Makefile.in
index bd85386b2..b82372e30 100644
--- a/src/libcharon/plugins/socket_default/Makefile.in
+++ b/src/libcharon/plugins/socket_default/Makefile.in
@@ -223,9 +223,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -264,6 +262,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/socket_dynamic/Makefile.in b/src/libcharon/plugins/socket_dynamic/Makefile.in
index 8e0790671..7a49088b2 100644
--- a/src/libcharon/plugins/socket_dynamic/Makefile.in
+++ b/src/libcharon/plugins/socket_dynamic/Makefile.in
@@ -223,9 +223,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -264,6 +262,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/socket_raw/Makefile.in b/src/libcharon/plugins/socket_raw/Makefile.in
index 5f4cba131..744b12fcf 100644
--- a/src/libcharon/plugins/socket_raw/Makefile.in
+++ b/src/libcharon/plugins/socket_raw/Makefile.in
@@ -223,9 +223,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -264,6 +262,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/sql/Makefile.in b/src/libcharon/plugins/sql/Makefile.in
index 7c4521785..4244d3b5e 100644
--- a/src/libcharon/plugins/sql/Makefile.in
+++ b/src/libcharon/plugins/sql/Makefile.in
@@ -220,9 +220,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -261,6 +259,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/sql/sql_config.c b/src/libcharon/plugins/sql/sql_config.c
index a47d93f7b..dc016012c 100644
--- a/src/libcharon/plugins/sql/sql_config.c
+++ b/src/libcharon/plugins/sql/sql_config.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006-2008 Martin Willi
+ * Copyright (C) 2010 Andreas Steffen
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -38,13 +39,13 @@ struct private_sql_config_t {
};
/**
- * forward declaration
+ * Forward declaration
*/
static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
identification_t *me, identification_t *other);
/**
- * build a traffic selector from a SQL query
+ * Build a traffic selector from an SQL query
*/
static traffic_selector_t *build_traffic_selector(private_sql_config_t *this,
enumerator_t *e, bool *local)
@@ -119,24 +120,62 @@ static void add_traffic_selectors(private_sql_config_t *this,
}
/**
- * build a Child configuration from a SQL query
+ * Add ESP proposals to a child config
+ */
+static void add_esp_proposals(private_sql_config_t *this,
+ child_cfg_t *child, int id)
+{
+ enumerator_t *e;
+ proposal_t *proposal;
+ char *prop;
+ bool use_default = TRUE;
+
+ e = this->db->query(this->db,
+ "SELECT proposal "
+ "FROM proposals JOIN child_config_proposal ON id = prop "
+ "WHERE child_cfg = ? ORDER BY prio",
+ DB_INT, id, DB_TEXT);
+ if (e)
+ {
+ while (e->enumerate(e, &prop))
+ {
+ proposal = proposal_create_from_string(PROTO_ESP, prop);
+ if (!proposal)
+ {
+ DBG1(DBG_CFG, "could not create ESP proposal from '%s'", prop);
+ break;
+ }
+ child->add_proposal(child, proposal);
+ use_default = FALSE;
+ }
+ e->destroy(e);
+ }
+ if (use_default)
+ {
+ child->add_proposal(child, proposal_create_default(PROTO_ESP));
+ }
+}
+
+/**
+ * Build a child config from an SQL query
*/
static child_cfg_t *build_child_cfg(private_sql_config_t *this, enumerator_t *e)
{
- int id, lifetime, rekeytime, jitter, hostaccess, mode, dpd, close, ipcomp;
+ int id, lifetime, rekeytime, jitter, hostaccess, mode, ipcomp, reqid;
+ int start, dpd, close;
char *name, *updown;
child_cfg_t *child_cfg;
- if (e->enumerate(e, &id, &name, &lifetime, &rekeytime, &jitter,
- &updown, &hostaccess, &mode, &dpd, &close, &ipcomp))
+ if (e->enumerate(e, &id, &name, &lifetime, &rekeytime, &jitter, &updown,
+ &hostaccess, &mode, &start, &dpd, &close, &ipcomp, &reqid))
{
lifetime_cfg_t lft = {
.time = { .life = lifetime, .rekey = rekeytime, .jitter = jitter }
};
child_cfg = child_cfg_create(name, &lft, updown, hostaccess, mode,
- dpd, close, ipcomp, 0, 0, NULL, NULL);
- /* TODO: read proposal from db */
- child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
+ start, dpd, close, ipcomp, 0, reqid,
+ NULL, NULL, 0);
+ add_esp_proposals(this, child_cfg, id);
add_traffic_selectors(this, child_cfg, id);
return child_cfg;
}
@@ -152,13 +191,13 @@ static void add_child_cfgs(private_sql_config_t *this, peer_cfg_t *peer, int id)
child_cfg_t *child_cfg;
e = this->db->query(this->db,
- "SELECT id, name, lifetime, rekeytime, jitter, "
- "updown, hostaccess, mode, dpd_action, close_action, ipcomp "
+ "SELECT id, name, lifetime, rekeytime, jitter, updown, hostaccess, "
+ "mode, start_action, dpd_action, close_action, ipcomp, reqid "
"FROM child_configs JOIN peer_config_child_config ON id = child_cfg "
"WHERE peer_cfg = ?",
DB_INT, id,
- DB_INT, DB_TEXT, DB_INT, DB_INT, DB_INT,
- DB_TEXT, DB_INT, DB_INT, DB_INT, DB_INT, DB_INT);
+ DB_INT, DB_TEXT, DB_INT, DB_INT, DB_INT, DB_TEXT, DB_INT,
+ DB_INT, DB_INT, DB_INT, DB_INT, DB_INT, DB_INT);
if (e)
{
while ((child_cfg = build_child_cfg(this, e)))
@@ -170,29 +209,65 @@ static void add_child_cfgs(private_sql_config_t *this, peer_cfg_t *peer, int id)
}
/**
- * build a ike configuration from a SQL query
+ * Add IKE proposals to an IKE config
+ */
+static void add_ike_proposals(private_sql_config_t *this,
+ ike_cfg_t *ike_cfg, int id)
+{
+ enumerator_t *e;
+ proposal_t *proposal;
+ char *prop;
+ bool use_default = TRUE;
+
+ e = this->db->query(this->db,
+ "SELECT proposal "
+ "FROM proposals JOIN ike_config_proposal ON id = prop "
+ "WHERE ike_cfg = ? ORDER BY prio",
+ DB_INT, id, DB_TEXT);
+ if (e)
+ {
+ while (e->enumerate(e, &prop))
+ {
+ proposal = proposal_create_from_string(PROTO_IKE, prop);
+ if (!proposal)
+ {
+ DBG1(DBG_CFG, "could not create IKE proposal from '%s'", prop);
+ break;
+ }
+ ike_cfg->add_proposal(ike_cfg, proposal);
+ use_default = FALSE;
+ }
+ e->destroy(e);
+ }
+ if (use_default)
+ {
+ ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
+ }
+}
+
+/**
+ * Build an IKE config from an SQL query
*/
static ike_cfg_t *build_ike_cfg(private_sql_config_t *this, enumerator_t *e,
host_t *my_host, host_t *other_host)
{
- int certreq, force_encap;
+ int id, certreq, force_encap;
char *local, *remote;
- while (e->enumerate(e, &certreq, &force_encap, &local, &remote))
+ while (e->enumerate(e, &id, &certreq, &force_encap, &local, &remote))
{
ike_cfg_t *ike_cfg;
ike_cfg = ike_cfg_create(certreq, force_encap,
local, IKEV2_UDP_PORT, remote, IKEV2_UDP_PORT);
- /* TODO: read proposal from db */
- ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
+ add_ike_proposals(this, ike_cfg, id);
return ike_cfg;
}
return NULL;
}
/**
- * Query a IKE config by its id
+ * Query an IKE config by its id
*/
static ike_cfg_t* get_ike_cfg_by_id(private_sql_config_t *this, int id)
{
@@ -200,10 +275,10 @@ static ike_cfg_t* get_ike_cfg_by_id(private_sql_config_t *this, int id)
ike_cfg_t *ike_cfg = NULL;
e = this->db->query(this->db,
- "SELECT certreq, force_encap, local, remote "
+ "SELECT id, certreq, force_encap, local, remote "
"FROM ike_configs WHERE id = ?",
DB_INT, id,
- DB_INT, DB_INT, DB_TEXT, DB_TEXT);
+ DB_INT, DB_INT, DB_INT, DB_TEXT, DB_TEXT);
if (e)
{
ike_cfg = build_ike_cfg(this, e, NULL, NULL);
@@ -246,7 +321,7 @@ static peer_cfg_t *get_peer_cfg_by_id(private_sql_config_t *this, int id)
}
/**
- * build a peer configuration from a SQL query
+ * Build a peer config from an SQL query
*/
static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
identification_t *me, identification_t *other)
@@ -325,10 +400,8 @@ static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
return NULL;
}
-/**
- * implements backend_t.get_peer_cfg_by_name.
- */
-static peer_cfg_t *get_peer_cfg_by_name(private_sql_config_t *this, char *name)
+METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
+ private_sql_config_t *this, char *name)
{
enumerator_t *e;
peer_cfg_t *peer_cfg = NULL;
@@ -398,11 +471,8 @@ static void ike_enumerator_destroy(ike_enumerator_t *this)
free(this);
}
-/**
- * Implementation of backend_t.create_ike_cfg_enumerator.
- */
-static enumerator_t* create_ike_cfg_enumerator(private_sql_config_t *this,
- host_t *me, host_t *other)
+METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*,
+ private_sql_config_t *this, host_t *me, host_t *other)
{
ike_enumerator_t *e = malloc_thing(ike_enumerator_t);
@@ -414,9 +484,9 @@ static enumerator_t* create_ike_cfg_enumerator(private_sql_config_t *this,
e->public.destroy = (void*)ike_enumerator_destroy;
e->inner = this->db->query(this->db,
- "SELECT certreq, force_encap, local, remote "
+ "SELECT id, certreq, force_encap, local, remote "
"FROM ike_configs",
- DB_INT, DB_INT, DB_TEXT, DB_TEXT);
+ DB_INT, DB_INT, DB_INT, DB_TEXT, DB_TEXT);
if (!e->inner)
{
free(e);
@@ -466,12 +536,8 @@ static void peer_enumerator_destroy(peer_enumerator_t *this)
free(this);
}
-/**
- * Implementation of backend_t.create_peer_cfg_enumerator.
- */
-static enumerator_t* create_peer_cfg_enumerator(private_sql_config_t *this,
- identification_t *me,
- identification_t *other)
+METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
+ private_sql_config_t *this, identification_t *me, identification_t *other)
{
peer_enumerator_t *e = malloc_thing(peer_enumerator_t);
@@ -508,10 +574,8 @@ static enumerator_t* create_peer_cfg_enumerator(private_sql_config_t *this,
return &e->public;
}
-/**
- * Implementation of sql_config_t.destroy.
- */
-static void destroy(private_sql_config_t *this)
+METHOD(sql_config_t, destroy, void,
+ private_sql_config_t *this)
{
free(this);
}
@@ -521,14 +585,19 @@ static void destroy(private_sql_config_t *this)
*/
sql_config_t *sql_config_create(database_t *db)
{
- private_sql_config_t *this = malloc_thing(private_sql_config_t);
-
- this->public.backend.create_peer_cfg_enumerator = (enumerator_t*(*)(backend_t*, identification_t *me, identification_t *other))create_peer_cfg_enumerator;
- this->public.backend.create_ike_cfg_enumerator = (enumerator_t*(*)(backend_t*, host_t *me, host_t *other))create_ike_cfg_enumerator;
- this->public.backend.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_t*,char*))get_peer_cfg_by_name;
- this->public.destroy = (void(*)(sql_config_t*))destroy;
+ private_sql_config_t *this;
- this->db = db;
+ INIT(this,
+ .public = {
+ .backend = {
+ .create_peer_cfg_enumerator = _create_peer_cfg_enumerator,
+ .create_ike_cfg_enumerator = _create_ike_cfg_enumerator,
+ .get_peer_cfg_by_name = _get_peer_cfg_by_name,
+ },
+ .destroy = _destroy,
+ },
+ .db = db
+ );
return &this->public;
}
diff --git a/src/libcharon/plugins/sql/sql_cred.c b/src/libcharon/plugins/sql/sql_cred.c
index 12f4ab045..117eec921 100644
--- a/src/libcharon/plugins/sql/sql_cred.c
+++ b/src/libcharon/plugins/sql/sql_cred.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2010 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -37,6 +38,7 @@ struct private_sql_cred_t {
database_t *db;
};
+
/**
* enumerator over private keys
*/
@@ -49,11 +51,8 @@ typedef struct {
private_key_t *current;
} private_enumerator_t;
-/**
- * Implementation of private_enumerator_t.public.enumerate
- */
-static bool private_enumerator_enumerate(private_enumerator_t *this,
- private_key_t **key)
+METHOD(enumerator_t, private_enumerator_enumerate, bool,
+ private_enumerator_t *this, private_key_t **key)
{
chunk_t blob;
int type;
@@ -62,7 +61,7 @@ static bool private_enumerator_enumerate(private_enumerator_t *this,
while (this->inner->enumerate(this->inner, &type, &blob))
{
this->current = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
- BUILD_BLOB_ASN1_DER, blob,
+ BUILD_BLOB_PEM, blob,
BUILD_END);
if (this->current)
{
@@ -74,29 +73,25 @@ static bool private_enumerator_enumerate(private_enumerator_t *this,
return FALSE;
}
-/**
- * Implementation of private_enumerator_t.public.destroy
- */
-static void private_enumerator_destroy(private_enumerator_t *this)
+METHOD(enumerator_t, private_enumerator_destroy, void,
+ private_enumerator_t *this)
{
DESTROY_IF(this->current);
this->inner->destroy(this->inner);
free(this);
}
-/**
- * Implementation of credential_set_t.create_private_enumerator.
- */
-static enumerator_t* create_private_enumerator(private_sql_cred_t *this,
- key_type_t type,
- identification_t *id)
+METHOD(credential_set_t, create_private_enumerator, enumerator_t*,
+ private_sql_cred_t *this, key_type_t type, identification_t *id)
{
private_enumerator_t *e;
- e = malloc_thing(private_enumerator_t);
- e->current = NULL;
- e->public.enumerate = (void*)private_enumerator_enumerate;
- e->public.destroy = (void*)private_enumerator_destroy;
+ INIT(e,
+ .public = {
+ .enumerate = (void*)_private_enumerator_enumerate,
+ .destroy = _private_enumerator_destroy,
+ },
+ );
if (id && id->get_type(id) != ID_ANY)
{
e->inner = this->db->query(this->db,
@@ -123,6 +118,7 @@ static enumerator_t* create_private_enumerator(private_sql_cred_t *this,
return &e->public;
}
+
/**
* enumerator over certificates
*/
@@ -135,11 +131,8 @@ typedef struct {
certificate_t *current;
} cert_enumerator_t;
-/**
- * Implementation of cert_enumerator_t.public.enumerate
- */
-static bool cert_enumerator_enumerate(cert_enumerator_t *this,
- certificate_t **cert)
+METHOD(enumerator_t, cert_enumerator_enumerate, bool,
+ cert_enumerator_t *this, certificate_t **cert)
{
chunk_t blob;
int type;
@@ -148,7 +141,7 @@ static bool cert_enumerator_enumerate(cert_enumerator_t *this,
while (this->inner->enumerate(this->inner, &type, &blob))
{
this->current = lib->creds->create(lib->creds, CRED_CERTIFICATE, type,
- BUILD_BLOB_ASN1_DER, blob,
+ BUILD_BLOB_PEM, blob,
BUILD_END);
if (this->current)
{
@@ -160,29 +153,26 @@ static bool cert_enumerator_enumerate(cert_enumerator_t *this,
return FALSE;
}
-/**
- * Implementation of cert_enumerator_t.public.destroy
- */
-static void cert_enumerator_destroy(cert_enumerator_t *this)
+METHOD(enumerator_t, cert_enumerator_destroy, void,
+ cert_enumerator_t *this)
{
DESTROY_IF(this->current);
this->inner->destroy(this->inner);
free(this);
}
-/**
- * Implementation of credential_set_t.create_cert_enumerator.
- */
-static enumerator_t* create_cert_enumerator(private_sql_cred_t *this,
- certificate_type_t cert, key_type_t key,
- identification_t *id, bool trusted)
+METHOD(credential_set_t, create_cert_enumerator, enumerator_t*,
+ private_sql_cred_t *this, certificate_type_t cert, key_type_t key,
+ identification_t *id, bool trusted)
{
cert_enumerator_t *e;
- e = malloc_thing(cert_enumerator_t);
- e->current = NULL;
- e->public.enumerate = (void*)cert_enumerator_enumerate;
- e->public.destroy = (void*)cert_enumerator_destroy;
+ INIT(e,
+ .public = {
+ .enumerate = (void*)_cert_enumerator_enumerate,
+ .destroy = _cert_enumerator_destroy,
+ },
+ );
if (id && id->get_type(id) != ID_ANY)
{
e->inner = this->db->query(this->db,
@@ -213,6 +203,7 @@ static enumerator_t* create_cert_enumerator(private_sql_cred_t *this,
return &e->public;
}
+
/**
* enumerator over shared keys
*/
@@ -229,12 +220,9 @@ typedef struct {
shared_key_t *current;
} shared_enumerator_t;
-/**
- * Implementation of shared_enumerator_t.public.enumerate
- */
-static bool shared_enumerator_enumerate(shared_enumerator_t *this,
- shared_key_t **shared,
- id_match_t *me, id_match_t *other)
+METHOD(enumerator_t, shared_enumerator_enumerate, bool,
+ shared_enumerator_t *this, shared_key_t **shared,
+ id_match_t *me, id_match_t *other)
{
chunk_t blob;
int type;
@@ -261,31 +249,28 @@ static bool shared_enumerator_enumerate(shared_enumerator_t *this,
return FALSE;
}
-/**
- * Implementation of shared_enumerator_t.public.destroy
- */
-static void shared_enumerator_destroy(shared_enumerator_t *this)
+METHOD(enumerator_t, shared_enumerator_destroy, void,
+ shared_enumerator_t *this)
{
DESTROY_IF(this->current);
this->inner->destroy(this->inner);
free(this);
}
-/**
- * Implementation of credential_set_t.create_shared_enumerator.
- */
-static enumerator_t* create_shared_enumerator(private_sql_cred_t *this,
- shared_key_type_t type,
- identification_t *me, identification_t *other)
+METHOD(credential_set_t, create_shared_enumerator, enumerator_t*,
+ private_sql_cred_t *this, shared_key_type_t type,
+ identification_t *me, identification_t *other)
{
shared_enumerator_t *e;
- e = malloc_thing(shared_enumerator_t);
- e->me = me;
- e->other = other;
- e->current = NULL;
- e->public.enumerate = (void*)shared_enumerator_enumerate;
- e->public.destroy = (void*)shared_enumerator_destroy;
+ INIT(e,
+ .public = {
+ .enumerate = (void*)_shared_enumerator_enumerate,
+ .destroy = _shared_enumerator_destroy,
+ },
+ .me = me,
+ .other = other,
+ );
if (!me && !other)
{
e->inner = this->db->query(this->db,
@@ -329,36 +314,141 @@ static enumerator_t* create_shared_enumerator(private_sql_cred_t *this,
return &e->public;
}
+
/**
- * Implementation of credential_set_t.cache_cert.
+ * enumerator over CDPs
*/
-static void cache_cert(private_sql_cred_t *this, certificate_t *cert)
+typedef struct {
+ /** implements enumerator_t */
+ enumerator_t public;
+ /** inner SQL enumerator */
+ enumerator_t *inner;
+ /** currently enumerated string */
+ char *current;
+} cdp_enumerator_t;
+
+/**
+ * types of CDPs
+ */
+typedef enum {
+ /** any available CDP */
+ CDP_TYPE_ANY = 0,
+ /** CRL */
+ CDP_TYPE_CRL,
+ /** OCSP Responder */
+ CDP_TYPE_OCSP,
+} cdp_type_t;
+
+METHOD(enumerator_t, cdp_enumerator_enumerate, bool,
+ cdp_enumerator_t *this, char **uri)
+{
+ char *text;
+
+ free(this->current);
+ while (this->inner->enumerate(this->inner, &text))
+ {
+ *uri = this->current = strdup(text);
+ return TRUE;
+ }
+ this->current = NULL;
+ return FALSE;
+}
+
+METHOD(enumerator_t, cdp_enumerator_destroy, void,
+ cdp_enumerator_t *this)
+{
+ free(this->current);
+ this->inner->destroy(this->inner);
+ free(this);
+}
+
+METHOD(credential_set_t, create_cdp_enumerator, enumerator_t*,
+ private_sql_cred_t *this, certificate_type_t type, identification_t *id)
+{
+ cdp_enumerator_t *e;
+ cdp_type_t cdp_type;
+
+ switch (type)
+ { /* we serve CRLs and OCSP responders */
+ case CERT_X509_CRL:
+ cdp_type = CDP_TYPE_CRL;
+ break;
+ case CERT_X509_OCSP_RESPONSE:
+ cdp_type = CDP_TYPE_OCSP;
+ break;
+ case CERT_ANY:
+ cdp_type = CDP_TYPE_ANY;
+ break;
+ default:
+ return NULL;
+ }
+ INIT(e,
+ .public = {
+ .enumerate = (void*)_cdp_enumerator_enumerate,
+ .destroy = _cdp_enumerator_destroy,
+ },
+ );
+ if (id && id->get_type(id) != ID_ANY)
+ {
+ e->inner = this->db->query(this->db,
+ "SELECT dp.uri FROM certificate_distribution_points AS dp "
+ "JOIN certificate_authorities AS ca ON ca.id = dp.ca "
+ "JOIN certificates AS c ON c.id = ca.certificate "
+ "JOIN certificate_identity AS ci ON c.id = ci.certificate "
+ "JOIN identities AS i ON ci.identity = i.id "
+ "WHERE i.type = ? AND i.data = ? AND (? OR dp.type = ?)",
+ DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id),
+ DB_INT, cdp_type == CDP_TYPE_ANY, DB_INT, cdp_type,
+ DB_TEXT);
+ }
+ else
+ {
+ e->inner = this->db->query(this->db,
+ "SELECT dp.uri FROM certificate_distribution_points AS dp "
+ "WHERE (? OR dp.type = ?)",
+ DB_INT, cdp_type == CDP_TYPE_ANY, DB_INT, cdp_type,
+ DB_TEXT);
+ }
+ if (!e->inner)
+ {
+ free(e);
+ return NULL;
+ }
+ return &e->public;
+}
+
+METHOD(credential_set_t, cache_cert, void,
+ private_sql_cred_t *this, certificate_t *cert)
{
/* TODO: implement CRL caching to database */
}
-/**
- * Implementation of sql_cred_t.destroy.
- */
-static void destroy(private_sql_cred_t *this)
+METHOD(sql_cred_t, destroy, void,
+ private_sql_cred_t *this)
{
free(this);
}
+
/**
* Described in header.
*/
sql_cred_t *sql_cred_create(database_t *db)
{
- private_sql_cred_t *this = malloc_thing(private_sql_cred_t);
-
- this->public.set.create_private_enumerator = (void*)create_private_enumerator;
- this->public.set.create_cert_enumerator = (void*)create_cert_enumerator;
- this->public.set.create_shared_enumerator = (void*)create_shared_enumerator;
- this->public.set.create_cdp_enumerator = (void*)return_null;
- this->public.set.cache_cert = (void*)cache_cert;
- this->public.destroy = (void(*)(sql_cred_t*))destroy;
-
- this->db = db;
+ private_sql_cred_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 = _create_cdp_enumerator,
+ .cache_cert = _cache_cert,
+ },
+ .destroy = _destroy,
+ },
+ .db = db,
+ );
return &this->public;
}
diff --git a/src/libcharon/plugins/sql/sql_plugin.c b/src/libcharon/plugins/sql/sql_plugin.c
index 7b0a198d1..ad1eb91b1 100644
--- a/src/libcharon/plugins/sql/sql_plugin.c
+++ b/src/libcharon/plugins/sql/sql_plugin.c
@@ -53,10 +53,8 @@ struct private_sql_plugin_t {
sql_logger_t *logger;
};
-/**
- * Implementation of plugin_t.destroy
- */
-static void destroy(private_sql_plugin_t *this)
+METHOD(plugin_t, destroy, void,
+ private_sql_plugin_t *this)
{
charon->backends->remove_backend(charon->backends, &this->config->backend);
lib->credmgr->remove_set(lib->credmgr, &this->cred->set);
@@ -83,11 +81,15 @@ plugin_t *sql_plugin_create()
return NULL;
}
- this = malloc_thing(private_sql_plugin_t);
-
- this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
+ INIT(this,
+ .public = {
+ .plugin = {
+ .destroy = _destroy,
+ },
+ },
+ .db = lib->db->create(lib->db, uri),
+ );
- this->db = lib->db->create(lib->db, uri);
if (!this->db)
{
DBG1(DBG_CFG, "sql plugin failed to connect to database");
diff --git a/src/libcharon/plugins/stroke/Makefile.am b/src/libcharon/plugins/stroke/Makefile.am
index 40888a40b..e561224e9 100644
--- a/src/libcharon/plugins/stroke/Makefile.am
+++ b/src/libcharon/plugins/stroke/Makefile.am
@@ -21,7 +21,6 @@ libstrongswan_stroke_la_SOURCES = \
stroke_cred.h stroke_cred.c \
stroke_ca.h stroke_ca.c \
stroke_attribute.h stroke_attribute.c \
- stroke_list.h stroke_list.c \
- stroke_shared_key.h stroke_shared_key.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 e6e98838b..ccf3eeede 100644
--- a/src/libcharon/plugins/stroke/Makefile.in
+++ b/src/libcharon/plugins/stroke/Makefile.in
@@ -77,7 +77,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_shared_key.lo
+ stroke_attribute.lo stroke_list.lo
libstrongswan_stroke_la_OBJECTS = \
$(am_libstrongswan_stroke_la_OBJECTS)
libstrongswan_stroke_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@@ -223,9 +223,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -264,6 +262,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
@@ -292,8 +292,7 @@ libstrongswan_stroke_la_SOURCES = \
stroke_cred.h stroke_cred.c \
stroke_ca.h stroke_ca.c \
stroke_attribute.h stroke_attribute.c \
- stroke_list.h stroke_list.c \
- stroke_shared_key.h stroke_shared_key.c
+ stroke_list.h stroke_list.c
libstrongswan_stroke_la_LDFLAGS = -module -avoid-version
all: all-am
@@ -386,7 +385,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_cred.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_shared_key.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_socket.Plo@am__quote@
.c.o:
diff --git a/src/libcharon/plugins/stroke/stroke_ca.c b/src/libcharon/plugins/stroke/stroke_ca.c
index 9a3ae0ab9..69e13deb9 100644
--- a/src/libcharon/plugins/stroke/stroke_ca.c
+++ b/src/libcharon/plugins/stroke/stroke_ca.c
@@ -113,6 +113,7 @@ static void ca_section_destroy(ca_section_t *this)
this->crl->destroy_function(this->crl, free);
this->ocsp->destroy_function(this->ocsp, free);
this->hashes->destroy_offset(this->hashes, offsetof(identification_t, destroy));
+ this->cert->destroy(this->cert);
free(this->certuribase);
free(this->name);
free(this);
@@ -207,11 +208,8 @@ static enumerator_t *create_inner_cdp_hashandurl(ca_section_t *section, cdp_data
return enumerator;
}
-/**
- * Implementation of credential_set_t.create_cdp_enumerator.
- */
-static enumerator_t *create_cdp_enumerator(private_stroke_ca_t *this,
- certificate_type_t type, identification_t *id)
+METHOD(credential_set_t, create_cdp_enumerator, enumerator_t*,
+ private_stroke_ca_t *this, certificate_type_t type, identification_t *id)
{
cdp_data_t *data;
@@ -235,10 +233,9 @@ static enumerator_t *create_cdp_enumerator(private_stroke_ca_t *this,
(type == CERT_X509) ? (void*)create_inner_cdp_hashandurl : (void*)create_inner_cdp,
data, (void*)cdp_data_destroy);
}
-/**
- * Implementation of stroke_ca_t.add.
- */
-static void add(private_stroke_ca_t *this, stroke_msg_t *msg)
+
+METHOD(stroke_ca_t, add, void,
+ private_stroke_ca_t *this, stroke_msg_t *msg)
{
certificate_t *cert;
ca_section_t *ca;
@@ -279,10 +276,8 @@ static void add(private_stroke_ca_t *this, stroke_msg_t *msg)
}
}
-/**
- * Implementation of stroke_ca_t.del.
- */
-static void del(private_stroke_ca_t *this, stroke_msg_t *msg)
+METHOD(stroke_ca_t, del, void,
+ private_stroke_ca_t *this, stroke_msg_t *msg)
{
enumerator_t *enumerator;
ca_section_t *ca = NULL;
@@ -336,10 +331,8 @@ static void list_uris(linked_list_t *list, char *label, FILE *out)
enumerator->destroy(enumerator);
}
-/**
- * Implementation of stroke_ca_t.check_for_hash_and_url.
- */
-static void check_for_hash_and_url(private_stroke_ca_t *this, certificate_t* cert)
+METHOD(stroke_ca_t, check_for_hash_and_url, void,
+ private_stroke_ca_t *this, certificate_t* cert)
{
ca_section_t *section;
enumerator_t *enumerator;
@@ -376,10 +369,8 @@ static void check_for_hash_and_url(private_stroke_ca_t *this, certificate_t* cer
hasher->destroy(hasher);
}
-/**
- * Implementation of stroke_ca_t.list.
- */
-static void list(private_stroke_ca_t *this, stroke_msg_t *msg, FILE *out)
+METHOD(stroke_ca_t, list, void,
+ private_stroke_ca_t *this, stroke_msg_t *msg, FILE *out)
{
bool first = TRUE;
ca_section_t *section;
@@ -426,10 +417,8 @@ static void list(private_stroke_ca_t *this, stroke_msg_t *msg, FILE *out)
this->lock->unlock(this->lock);
}
-/**
- * Implementation of stroke_ca_t.destroy
- */
-static void destroy(private_stroke_ca_t *this)
+METHOD(stroke_ca_t, destroy, void,
+ private_stroke_ca_t *this)
{
this->sections->destroy_function(this->sections, (void*)ca_section_destroy);
this->lock->destroy(this->lock);
@@ -441,22 +430,27 @@ static void destroy(private_stroke_ca_t *this)
*/
stroke_ca_t *stroke_ca_create(stroke_cred_t *cred)
{
- private_stroke_ca_t *this = malloc_thing(private_stroke_ca_t);
-
- this->public.set.create_private_enumerator = (void*)return_null;
- this->public.set.create_cert_enumerator = (void*)return_null;
- this->public.set.create_shared_enumerator = (void*)return_null;
- this->public.set.create_cdp_enumerator = (void*)create_cdp_enumerator;
- this->public.set.cache_cert = (void*)nop;
- this->public.add = (void(*)(stroke_ca_t*, stroke_msg_t *msg))add;
- this->public.del = (void(*)(stroke_ca_t*, stroke_msg_t *msg))del;
- this->public.list = (void(*)(stroke_ca_t*, stroke_msg_t *msg, FILE *out))list;
- this->public.check_for_hash_and_url = (void(*)(stroke_ca_t*, certificate_t*))check_for_hash_and_url;
- this->public.destroy = (void(*)(stroke_ca_t*))destroy;
-
- this->sections = linked_list_create();
- this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
- this->cred = cred;
+ private_stroke_ca_t *this;
+
+ INIT(this,
+ .public = {
+ .set = {
+ .create_private_enumerator = (void*)return_null,
+ .create_cert_enumerator = (void*)return_null,
+ .create_shared_enumerator = (void*)return_null,
+ .create_cdp_enumerator = _create_cdp_enumerator,
+ .cache_cert = (void*)nop,
+ },
+ .add = _add,
+ .del = _del,
+ .list = _list,
+ .check_for_hash_and_url = _check_for_hash_and_url,
+ .destroy = _destroy,
+ },
+ .sections = linked_list_create(),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ .cred = cred,
+ );
return &this->public;
}
diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c
index 165212a5e..ea7d17592 100644
--- a/src/libcharon/plugins/stroke/stroke_config.c
+++ b/src/libcharon/plugins/stroke/stroke_config.c
@@ -53,12 +53,8 @@ struct private_stroke_config_t {
stroke_cred_t *cred;
};
-/**
- * Implementation of backend_t.create_peer_cfg_enumerator.
- */
-static enumerator_t* create_peer_cfg_enumerator(private_stroke_config_t *this,
- identification_t *me,
- identification_t *other)
+METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
+ private_stroke_config_t *this, identification_t *me, identification_t *other)
{
this->mutex->lock(this->mutex);
return enumerator_create_cleaner(this->list->create_enumerator(this->list),
@@ -74,11 +70,8 @@ static bool ike_filter(void *data, peer_cfg_t **in, ike_cfg_t **out)
return TRUE;
}
-/**
- * Implementation of backend_t.create_ike_cfg_enumerator.
- */
-static enumerator_t* create_ike_cfg_enumerator(private_stroke_config_t *this,
- host_t *me, host_t *other)
+METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*,
+ private_stroke_config_t *this, host_t *me, host_t *other)
{
this->mutex->lock(this->mutex);
return enumerator_create_filter(this->list->create_enumerator(this->list),
@@ -86,10 +79,8 @@ static enumerator_t* create_ike_cfg_enumerator(private_stroke_config_t *this,
(void*)this->mutex->unlock);
}
-/**
- * implements backend_t.get_peer_cfg_by_name.
- */
-static peer_cfg_t *get_peer_cfg_by_name(private_stroke_config_t *this, char *name)
+METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
+ private_stroke_config_t *this, char *name)
{
enumerator_t *e1, *e2;
peer_cfg_t *current, *found = NULL;
@@ -438,13 +429,38 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this,
enumerator->destroy(enumerator);
}
+ /* certificatePolicies */
+ if (end->cert_policy)
+ {
+ enumerator_t *enumerator;
+ char *policy;
+
+ enumerator = enumerator_create_token(end->cert_policy, ",", " ");
+ while (enumerator->enumerate(enumerator, &policy))
+ {
+ cfg->add(cfg, AUTH_RULE_CERT_POLICY, strdup(policy));
+ }
+ enumerator->destroy(enumerator);
+ }
+
/* authentication metod (class, actually) */
if (streq(auth, "pubkey") ||
- streq(auth, "rsasig") || streq(auth, "rsa") ||
- streq(auth, "ecdsasig") || streq(auth, "ecdsa"))
+ 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);
+ }
}
else if (streq(auth, "psk") || streq(auth, "secret"))
{
@@ -808,9 +824,9 @@ static child_cfg_t *build_child_cfg(private_stroke_config_t *this,
child_cfg = child_cfg_create(
msg->add_conn.name, &lifetime,
msg->add_conn.me.updown, msg->add_conn.me.hostaccess,
- msg->add_conn.mode, dpd, dpd, msg->add_conn.ipcomp,
+ msg->add_conn.mode, ACTION_NONE, dpd, dpd, msg->add_conn.ipcomp,
msg->add_conn.inactivity, msg->add_conn.reqid,
- &mark_in, &mark_out);
+ &mark_in, &mark_out, msg->add_conn.tfc);
child_cfg->set_mipv6_options(child_cfg, msg->add_conn.proxy_mode,
msg->add_conn.install_policy);
add_ts(this, &msg->add_conn.me, child_cfg, TRUE);
@@ -821,10 +837,8 @@ static child_cfg_t *build_child_cfg(private_stroke_config_t *this,
return child_cfg;
}
-/**
- * Implementation of stroke_config_t.add.
- */
-static void add(private_stroke_config_t *this, stroke_msg_t *msg)
+METHOD(stroke_config_t, add, void,
+ private_stroke_config_t *this, stroke_msg_t *msg)
{
ike_cfg_t *ike_cfg, *existing_ike;
peer_cfg_t *peer_cfg, *existing;
@@ -884,10 +898,8 @@ static void add(private_stroke_config_t *this, stroke_msg_t *msg)
}
}
-/**
- * Implementation of stroke_config_t.del.
- */
-static void del(private_stroke_config_t *this, stroke_msg_t *msg)
+METHOD(stroke_config_t, del, void,
+ private_stroke_config_t *this, stroke_msg_t *msg)
{
enumerator_t *enumerator, *children;
peer_cfg_t *peer;
@@ -938,10 +950,8 @@ static void del(private_stroke_config_t *this, stroke_msg_t *msg)
}
}
-/**
- * Implementation of stroke_config_t.destroy
- */
-static void destroy(private_stroke_config_t *this)
+METHOD(stroke_config_t, destroy, void,
+ private_stroke_config_t *this)
{
this->list->destroy_offset(this->list, offsetof(peer_cfg_t, destroy));
this->mutex->destroy(this->mutex);
@@ -953,19 +963,24 @@ static void destroy(private_stroke_config_t *this)
*/
stroke_config_t *stroke_config_create(stroke_ca_t *ca, stroke_cred_t *cred)
{
- private_stroke_config_t *this = malloc_thing(private_stroke_config_t);
-
- this->public.backend.create_peer_cfg_enumerator = (enumerator_t*(*)(backend_t*, identification_t *me, identification_t *other))create_peer_cfg_enumerator;
- this->public.backend.create_ike_cfg_enumerator = (enumerator_t*(*)(backend_t*, host_t *me, host_t *other))create_ike_cfg_enumerator;
- this->public.backend.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_t*,char*))get_peer_cfg_by_name;
- this->public.add = (void(*)(stroke_config_t*, stroke_msg_t *msg))add;
- this->public.del = (void(*)(stroke_config_t*, stroke_msg_t *msg))del;
- this->public.destroy = (void(*)(stroke_config_t*))destroy;
-
- this->list = linked_list_create();
- this->mutex = mutex_create(MUTEX_TYPE_RECURSIVE);
- this->ca = ca;
- this->cred = cred;
+ private_stroke_config_t *this;
+
+ INIT(this,
+ .public = {
+ .backend = {
+ .create_peer_cfg_enumerator = _create_peer_cfg_enumerator,
+ .create_ike_cfg_enumerator = _create_ike_cfg_enumerator,
+ .get_peer_cfg_by_name = _get_peer_cfg_by_name,
+ },
+ .add = _add,
+ .del = _del,
+ .destroy = _destroy,
+ },
+ .list = linked_list_create(),
+ .mutex = mutex_create(MUTEX_TYPE_RECURSIVE),
+ .ca = ca,
+ .cred = cred,
+ );
return &this->public;
}
diff --git a/src/libcharon/plugins/stroke/stroke_control.c b/src/libcharon/plugins/stroke/stroke_control.c
index e0398ba78..3541ab8f9 100644
--- a/src/libcharon/plugins/stroke/stroke_control.c
+++ b/src/libcharon/plugins/stroke/stroke_control.c
@@ -17,6 +17,8 @@
#include <daemon.h>
#include <processing/jobs/delete_ike_sa_job.h>
+#include <processing/jobs/rekey_ike_sa_job.h>
+#include <processing/jobs/rekey_child_sa_job.h>
typedef struct private_stroke_control_t private_stroke_control_t;
@@ -90,10 +92,8 @@ static child_cfg_t* get_child_from_peer(peer_cfg_t *peer_cfg, char *name)
return found;
}
-/**
- * Implementation of stroke_control_t.initiate.
- */
-static void initiate(private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
+METHOD(stroke_control_t, initiate, void,
+ private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
{
peer_cfg_t *peer_cfg;
child_cfg_t *child_cfg;
@@ -137,76 +137,89 @@ static void initiate(private_stroke_control_t *this, stroke_msg_t *msg, FILE *ou
}
/**
- * Implementation of stroke_control_t.terminate.
+ * Parse a terminate/rekey specifier
*/
-static void terminate(private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
+static bool parse_specifier(char *string, u_int32_t *id,
+ char **name, bool *child, bool *all)
{
- char *string, *pos = NULL, *name = NULL;
- u_int32_t id = 0;
- bool child, all = FALSE;
int len;
- ike_sa_t *ike_sa;
- enumerator_t *enumerator;
- linked_list_t *ike_list, *child_list;
- stroke_log_info_t info;
- uintptr_t del;
+ char *pos = NULL;
- string = msg->terminate.name;
+ *id = 0;
+ *name = NULL;
+ *all = FALSE;
len = strlen(string);
if (len < 1)
{
- DBG1(DBG_CFG, "error parsing string");
- return;
+ return FALSE;
}
switch (string[len-1])
{
case '}':
- child = TRUE;
+ *child = TRUE;
pos = strchr(string, '{');
break;
case ']':
- child = FALSE;
+ *child = FALSE;
pos = strchr(string, '[');
break;
default:
- name = string;
- child = FALSE;
+ *name = string;
+ *child = FALSE;
break;
}
- if (name)
+ if (*name)
{
/* is a single name */
}
else if (pos == string + len - 2)
{ /* is name[] or name{} */
string[len-2] = '\0';
- name = string;
+ *name = string;
}
else
{
if (!pos)
{
- DBG1(DBG_CFG, "error parsing string");
- return;
+ return FALSE;
}
if (*(pos + 1) == '*')
{ /* is name[*] */
- all = TRUE;
+ *all = TRUE;
*pos = '\0';
- name = string;
+ *name = string;
}
else
{ /* is name[123] or name{23} */
- id = atoi(pos + 1);
- if (id == 0)
+ *id = atoi(pos + 1);
+ if (*id == 0)
{
- DBG1(DBG_CFG, "error parsing string");
- return;
+ return FALSE;
}
}
}
+ return TRUE;
+}
+
+METHOD(stroke_control_t, terminate, void,
+ private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
+{
+ char *name;
+ u_int32_t id;
+ bool child, all;
+ ike_sa_t *ike_sa;
+ enumerator_t *enumerator;
+ linked_list_t *ike_list, *child_list;
+ stroke_log_info_t info;
+ uintptr_t del;
+
+ if (!parse_specifier(msg->terminate.name, &id, &name, &child, &all))
+ {
+ DBG1(DBG_CFG, "error parsing specifier string");
+ return;
+ }
info.out = out;
info.level = msg->output_verbosity;
@@ -293,11 +306,68 @@ static void terminate(private_stroke_control_t *this, stroke_msg_t *msg, FILE *o
child_list->destroy(child_list);
}
-/**
- * Implementation of stroke_control_t.terminate_srcip.
- */
-static void terminate_srcip(private_stroke_control_t *this,
- stroke_msg_t *msg, FILE *out)
+METHOD(stroke_control_t, rekey, void,
+ private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
+{
+ char *name;
+ u_int32_t id;
+ bool child, all, finished = FALSE;
+ ike_sa_t *ike_sa;
+ enumerator_t *enumerator;
+
+ if (!parse_specifier(msg->terminate.name, &id, &name, &child, &all))
+ {
+ DBG1(DBG_CFG, "error parsing specifier string");
+ return;
+ }
+ enumerator = charon->controller->create_ike_sa_enumerator(charon->controller);
+ while (enumerator->enumerate(enumerator, &ike_sa))
+ {
+ child_sa_t *child_sa;
+ iterator_t *children;
+
+ if (child)
+ {
+ children = ike_sa->create_child_sa_iterator(ike_sa);
+ while (children->iterate(children, (void**)&child_sa))
+ {
+ if ((name && streq(name, child_sa->get_name(child_sa))) ||
+ (id && id == child_sa->get_reqid(child_sa)))
+ {
+ lib->processor->queue_job(lib->processor,
+ (job_t*)rekey_child_sa_job_create(
+ child_sa->get_reqid(child_sa),
+ child_sa->get_protocol(child_sa),
+ child_sa->get_spi(child_sa, TRUE)));
+ if (!all)
+ {
+ finished = TRUE;
+ break;
+ }
+ }
+ }
+ children->destroy(children);
+ }
+ else if ((name && streq(name, ike_sa->get_name(ike_sa))) ||
+ (id && id == ike_sa->get_unique_id(ike_sa)))
+ {
+ lib->processor->queue_job(lib->processor,
+ (job_t*)rekey_ike_sa_job_create(ike_sa->get_id(ike_sa), FALSE));
+ if (!all)
+ {
+ finished = TRUE;
+ }
+ }
+ if (finished)
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+METHOD(stroke_control_t, terminate_srcip, void,
+ private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
{
enumerator_t *enumerator;
ike_sa_t *ike_sa;
@@ -362,10 +432,8 @@ static void terminate_srcip(private_stroke_control_t *this,
DESTROY_IF(end);
}
-/**
- * Implementation of stroke_control_t.purge_ike
- */
-static void purge_ike(private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
+METHOD(stroke_control_t, purge_ike, void,
+ private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
{
enumerator_t *enumerator;
iterator_t *iterator;
@@ -402,10 +470,8 @@ static void purge_ike(private_stroke_control_t *this, stroke_msg_t *msg, FILE *o
list->destroy(list);
}
-/**
- * Implementation of stroke_control_t.route.
- */
-static void route(private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
+METHOD(stroke_control_t, route, void,
+ private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
{
peer_cfg_t *peer_cfg;
child_cfg_t *child_cfg;
@@ -443,10 +509,8 @@ static void route(private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
child_cfg->destroy(child_cfg);
}
-/**
- * Implementation of stroke_control_t.unroute.
- */
-static void unroute(private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
+METHOD(stroke_control_t, unroute, void,
+ private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
{
child_sa_t *child_sa;
enumerator_t *enumerator;
@@ -468,10 +532,8 @@ static void unroute(private_stroke_control_t *this, stroke_msg_t *msg, FILE *out
fprintf(out, "configuration '%s' not found\n", msg->unroute.name);
}
-/**
- * Implementation of stroke_control_t.destroy
- */
-static void destroy(private_stroke_control_t *this)
+METHOD(stroke_control_t, destroy, void,
+ private_stroke_control_t *this)
{
free(this);
}
@@ -481,15 +543,20 @@ static void destroy(private_stroke_control_t *this)
*/
stroke_control_t *stroke_control_create()
{
- private_stroke_control_t *this = malloc_thing(private_stroke_control_t);
-
- this->public.initiate = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))initiate;
- this->public.terminate = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))terminate;
- this->public.terminate_srcip = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))terminate_srcip;
- this->public.purge_ike = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))purge_ike;
- this->public.route = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))route;
- this->public.unroute = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))unroute;
- this->public.destroy = (void(*)(stroke_control_t*))destroy;
+ private_stroke_control_t *this;
+
+ INIT(this,
+ .public = {
+ .initiate = _initiate,
+ .terminate = _terminate,
+ .terminate_srcip = _terminate_srcip,
+ .rekey = _rekey,
+ .purge_ike = _purge_ike,
+ .route = _route,
+ .unroute = _unroute,
+ .destroy = _destroy,
+ },
+ );
return &this->public;
}
diff --git a/src/libcharon/plugins/stroke/stroke_control.h b/src/libcharon/plugins/stroke/stroke_control.h
index 9b49bdc31..869aab3d3 100644
--- a/src/libcharon/plugins/stroke/stroke_control.h
+++ b/src/libcharon/plugins/stroke/stroke_control.h
@@ -54,6 +54,13 @@ struct stroke_control_t {
void (*terminate_srcip)(stroke_control_t *this, stroke_msg_t *msg, FILE *out);
/**
+ * Rekey a connection.
+ *
+ * @param msg stroke message
+ */
+ void (*rekey)(stroke_control_t *this, stroke_msg_t *msg, FILE *out);
+
+ /**
* Delete IKE_SAs without a CHILD_SA.
*
* @param msg stroke message
diff --git a/src/libcharon/plugins/stroke/stroke_cred.c b/src/libcharon/plugins/stroke/stroke_cred.c
index 91e71f1f4..83e5a9ad6 100644
--- a/src/libcharon/plugins/stroke/stroke_cred.c
+++ b/src/libcharon/plugins/stroke/stroke_cred.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2008-2010 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -25,7 +25,6 @@
#include <unistd.h>
#include "stroke_cred.h"
-#include "stroke_shared_key.h"
#include <credentials/certificates/x509.h>
#include <credentials/certificates/crl.h>
@@ -64,24 +63,9 @@ struct private_stroke_cred_t {
stroke_cred_t public;
/**
- * list of trusted peer/signer/CA certificates (certificate_t)
+ * credentials
*/
- linked_list_t *certs;
-
- /**
- * list of shared secrets (private_shared_key_t)
- */
- linked_list_t *shared;
-
- /**
- * list of private keys (private_key_t)
- */
- linked_list_t *private;
-
- /**
- * read-write lock to lists
- */
- rwlock_t *lock;
+ mem_cred_t *creds;
/**
* cache CRLs to disk?
@@ -90,237 +74,6 @@ struct private_stroke_cred_t {
};
/**
- * data to pass to various filters
- */
-typedef struct {
- private_stroke_cred_t *this;
- identification_t *id;
- certificate_type_t cert;
- key_type_t key;
-} id_data_t;
-
-/**
- * destroy id enumerator data and unlock list
- */
-static void id_data_destroy(id_data_t *data)
-{
- data->this->lock->unlock(data->this->lock);
- free(data);
-}
-
-/**
- * filter function for private key enumerator
- */
-static bool private_filter(id_data_t *data,
- private_key_t **in, private_key_t **out)
-{
- private_key_t *key;
-
- key = *in;
- if (data->key == KEY_ANY || data->key == key->get_type(key))
- {
- if (data->id == NULL)
- {
- *out = key;
- return TRUE;
- }
- if (key->has_fingerprint(key, data->id->get_encoding(data->id)))
- {
- *out = key;
- return TRUE;
- }
- }
- return FALSE;
-}
-
-/**
- * Implements credential_set_t.create_private_enumerator
- */
-static enumerator_t* create_private_enumerator(private_stroke_cred_t *this,
- key_type_t type, identification_t *id)
-{
- id_data_t *data;
-
- data = malloc_thing(id_data_t);
- data->this = this;
- data->id = id;
- data->key = type;
-
- this->lock->read_lock(this->lock);
- return enumerator_create_filter(this->private->create_enumerator(this->private),
- (void*)private_filter, data,
- (void*)id_data_destroy);
-}
-
-/**
- * filter function for certs enumerator
- */
-static bool certs_filter(id_data_t *data, certificate_t **in, certificate_t **out)
-{
- public_key_t *public;
- certificate_t *cert = *in;
-
- if (data->cert != CERT_ANY && data->cert != cert->get_type(cert))
- {
- return FALSE;
- }
- if (data->id == NULL || cert->has_subject(cert, data->id))
- {
- *out = *in;
- return TRUE;
- }
-
- public = cert->get_public_key(cert);
- if (public)
- {
- if (data->key == KEY_ANY || data->key != public->get_type(public))
- {
- if (public->has_fingerprint(public, data->id->get_encoding(data->id)))
- {
- public->destroy(public);
- *out = *in;
- return TRUE;
- }
- }
- public->destroy(public);
- }
- return FALSE;
-}
-
-/**
- * Implements credential_set_t.create_cert_enumerator
- */
-static enumerator_t* create_cert_enumerator(private_stroke_cred_t *this,
- certificate_type_t cert, key_type_t key,
- identification_t *id, bool trusted)
-{
- id_data_t *data;
-
- if (trusted && (cert == CERT_X509_CRL || cert == CERT_X509_AC))
- {
- return NULL;
- }
- data = malloc_thing(id_data_t);
- data->this = this;
- data->id = id;
- data->cert = cert;
- data->key = key;
-
- this->lock->read_lock(this->lock);
- return enumerator_create_filter(this->certs->create_enumerator(this->certs),
- (void*)certs_filter, data,
- (void*)id_data_destroy);
-}
-
-typedef struct {
- private_stroke_cred_t *this;
- identification_t *me;
- identification_t *other;
- shared_key_type_t type;
-} shared_data_t;
-
-/**
- * free shared key enumerator data and unlock list
- */
-static void shared_data_destroy(shared_data_t *data)
-{
- data->this->lock->unlock(data->this->lock);
- free(data);
-}
-
-/**
- * filter function for certs enumerator
- */
-static bool shared_filter(shared_data_t *data,
- stroke_shared_key_t **in, shared_key_t **out,
- void **unused1, id_match_t *me,
- void **unused2, id_match_t *other)
-{
- id_match_t my_match = ID_MATCH_NONE, other_match = ID_MATCH_NONE;
- stroke_shared_key_t *stroke = *in;
- shared_key_t *shared = &stroke->shared;
-
- if (data->type != SHARED_ANY && shared->get_type(shared) != data->type)
- {
- return FALSE;
- }
-
- if (data->me)
- {
- my_match = stroke->has_owner(stroke, data->me);
- }
- if (data->other)
- {
- other_match = stroke->has_owner(stroke, data->other);
- }
- if ((data->me || data->other) && (!my_match && !other_match))
- {
- return FALSE;
- }
- *out = shared;
- if (me)
- {
- *me = my_match;
- }
- if (other)
- {
- *other = other_match;
- }
- return TRUE;
-}
-
-/**
- * Implements credential_set_t.create_shared_enumerator
- */
-static enumerator_t* create_shared_enumerator(private_stroke_cred_t *this,
- shared_key_type_t type, identification_t *me,
- identification_t *other)
-{
- shared_data_t *data = malloc_thing(shared_data_t);
-
- data->this = this;
- data->me = me;
- data->other = other;
- data->type = type;
- this->lock->read_lock(this->lock);
- return enumerator_create_filter(this->shared->create_enumerator(this->shared),
- (void*)shared_filter, data,
- (void*)shared_data_destroy);
-}
-
-/**
- * Add a certificate to chain
- */
-static certificate_t* add_cert(private_stroke_cred_t *this, certificate_t *cert)
-{
- certificate_t *current;
- enumerator_t *enumerator;
- bool new = TRUE;
-
- this->lock->read_lock(this->lock);
- enumerator = this->certs->create_enumerator(this->certs);
- while (enumerator->enumerate(enumerator, (void**)&current))
- {
- if (current->equals(current, cert))
- {
- /* cert already in queue */
- cert->destroy(cert);
- cert = current;
- new = FALSE;
- break;
- }
- }
- enumerator->destroy(enumerator);
-
- if (new)
- {
- this->certs->insert_last(this->certs, cert);
- }
- this->lock->unlock(this->lock);
- return cert;
-}
-
-/**
* Implementation of stroke_cred_t.load_ca.
*/
static certificate_t* load_ca(private_stroke_cred_t *this, char *filename)
@@ -352,85 +105,12 @@ static certificate_t* load_ca(private_stroke_cred_t *this, char *filename)
cert->destroy(cert);
return NULL;
}
- return (certificate_t*)add_cert(this, cert);
+ return this->creds->add_cert_ref(this->creds, TRUE, cert);
}
return NULL;
}
/**
- * Add X.509 CRL to chain
- */
-static bool add_crl(private_stroke_cred_t *this, crl_t* crl)
-{
- certificate_t *current, *cert = &crl->certificate;
- enumerator_t *enumerator;
- bool new = TRUE, found = FALSE;
-
- this->lock->write_lock(this->lock);
- enumerator = this->certs->create_enumerator(this->certs);
- while (enumerator->enumerate(enumerator, (void**)&current))
- {
- if (current->get_type(current) == CERT_X509_CRL)
- {
- crl_t *crl_c = (crl_t*)current;
- chunk_t authkey = crl->get_authKeyIdentifier(crl);
- chunk_t authkey_c = crl_c->get_authKeyIdentifier(crl_c);
-
- /* if compare authorityKeyIdentifiers if available */
- if (authkey.ptr && authkey_c.ptr && chunk_equals(authkey, authkey_c))
- {
- found = TRUE;
- }
- else
- {
- identification_t *issuer = cert->get_issuer(cert);
- identification_t *issuer_c = current->get_issuer(current);
-
- /* otherwise compare issuer distinguished names */
- if (issuer->equals(issuer, issuer_c))
- {
- found = TRUE;
- }
- }
- if (found)
- {
- new = crl_is_newer(crl, crl_c);
- if (new)
- {
- this->certs->remove_at(this->certs, enumerator);
- }
- else
- {
- cert->destroy(cert);
- }
- break;
- }
- }
- }
- enumerator->destroy(enumerator);
-
- if (new)
- {
- this->certs->insert_last(this->certs, cert);
- }
- this->lock->unlock(this->lock);
- return new;
-}
-
-/**
- * Add X.509 attribute certificate to chain
- */
-static bool add_ac(private_stroke_cred_t *this, ac_t* ac)
-{
- certificate_t *cert = &ac->certificate;
-
- this->lock->write_lock(this->lock);
- this->certs->insert_last(this->certs, cert);
- this->lock->unlock(this->lock);
- return TRUE;
-}
-
-/**
* Implementation of stroke_cred_t.load_peer.
*/
static certificate_t* load_peer(private_stroke_cred_t *this, char *filename)
@@ -453,10 +133,10 @@ static certificate_t* load_peer(private_stroke_cred_t *this, char *filename)
BUILD_END);
if (cert)
{
- cert = add_cert(this, cert);
+ cert = this->creds->add_cert_ref(this->creds, TRUE, cert);
DBG1(DBG_CFG, " loaded certificate \"%Y\" from '%s'",
cert->get_subject(cert), filename);
- return cert->get_ref(cert);
+ return cert;
}
DBG1(DBG_CFG, " loading certificate from '%s' failed", filename);
return NULL;
@@ -511,8 +191,8 @@ static void load_certdir(private_stroke_cred_t *this, char *path,
}
else
{
- DBG1(DBG_CFG, " loaded ca certificate \"%Y\" from '%s'",
- cert->get_subject(cert), file);
+ DBG1(DBG_CFG, " loaded ca certificate \"%Y\" "
+ "from '%s'", cert->get_subject(cert), file);
}
}
else
@@ -540,7 +220,7 @@ static void load_certdir(private_stroke_cred_t *this, char *path,
}
if (cert)
{
- add_cert(this, cert);
+ this->creds->add_cert(this->creds, TRUE, cert);
}
break;
case CERT_X509_CRL:
@@ -550,7 +230,7 @@ static void load_certdir(private_stroke_cred_t *this, char *path,
BUILD_END);
if (cert)
{
- add_crl(this, (crl_t*)cert);
+ this->creds->add_crl(this->creds, (crl_t*)cert);
DBG1(DBG_CFG, " loaded crl from '%s'", file);
}
else
@@ -565,7 +245,7 @@ static void load_certdir(private_stroke_cred_t *this, char *path,
BUILD_END);
if (cert)
{
- add_ac(this, (ac_t*)cert);
+ this->creds->add_cert(this->creds, FALSE, cert);
DBG1(DBG_CFG, " loaded attribute certificate from '%s'",
file);
}
@@ -593,7 +273,7 @@ static void cache_cert(private_stroke_cred_t *this, certificate_t *cert)
crl_t *crl = (crl_t*)cert;
cert->get_ref(cert);
- if (add_crl(this, crl))
+ if (this->creds->add_crl(this->creds, crl))
{
char buf[BUF_LEN];
chunk_t chunk, hex;
@@ -914,7 +594,6 @@ static bool load_pin(private_stroke_cred_t *this, chunk_t line, int line_nr,
}
/* unlock: smartcard needs the pin and potentially calls public set */
- this->lock->unlock(this->lock);
switch (format)
{
case SC_FORMAT_SLOT_MODULE_KEYID:
@@ -936,7 +615,6 @@ static bool load_pin(private_stroke_cred_t *this, chunk_t line, int line_nr,
BUILD_PKCS11_KEYID, chunk, BUILD_END);
break;
}
- this->lock->write_lock(this->lock);
if (mem)
{
lib->credmgr->remove_local_set(lib->credmgr, &mem->set);
@@ -951,7 +629,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);
- this->private->insert_last(this->private, key);
+ this->creds->add_key(this->creds, key);
}
return TRUE;
}
@@ -1022,11 +700,8 @@ static bool load_private(private_stroke_cred_t *this, chunk_t line, int line_nr,
cb = callback_cred_create_shared((void*)passphrase_cb, &pp_data);
lib->credmgr->add_local_set(lib->credmgr, &cb->set);
- /* unlock, as the builder might ask for a secret */
- this->lock->unlock(this->lock);
key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, key_type,
BUILD_FROM_FILE, path, BUILD_END);
- this->lock->write_lock(this->lock);
lib->credmgr->remove_local_set(lib->credmgr, &cb->set);
cb->destroy(cb);
@@ -1042,11 +717,8 @@ static bool load_private(private_stroke_cred_t *this, chunk_t line, int line_nr,
mem->add_shared(mem, shared, NULL);
lib->credmgr->add_local_set(lib->credmgr, &mem->set);
- /* unlock, as the builder might ask for a secret */
- this->lock->unlock(this->lock);
key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, key_type,
BUILD_FROM_FILE, path, BUILD_END);
- this->lock->write_lock(this->lock);
lib->credmgr->remove_local_set(lib->credmgr, &mem->set);
mem->destroy(mem);
@@ -1055,7 +727,7 @@ static bool load_private(private_stroke_cred_t *this, chunk_t line, int line_nr,
{
DBG1(DBG_CFG, " loaded %N private key from '%s'",
key_type_names, key->get_type(key), path);
- this->private->insert_last(this->private, key);
+ this->creds->add_key(this->creds, key);
}
else
{
@@ -1070,7 +742,8 @@ static bool load_private(private_stroke_cred_t *this, chunk_t line, int line_nr,
static bool load_shared(private_stroke_cred_t *this, chunk_t line, int line_nr,
shared_key_type_t type, chunk_t ids)
{
- stroke_shared_key_t *shared_key;
+ shared_key_t *shared_key;
+ linked_list_t *owners;
chunk_t secret = chunk_empty;
bool any = TRUE;
@@ -1080,12 +753,12 @@ static bool load_shared(private_stroke_cred_t *this, chunk_t line, int line_nr,
DBG1(DBG_CFG, "line %d: malformed secret: %s", line_nr, ugh);
return FALSE;
}
- shared_key = stroke_shared_key_create(type, secret);
+ shared_key = shared_key_create(type, secret);
DBG1(DBG_CFG, " loaded %N secret for %s", shared_key_type_names, type,
ids.len > 0 ? (char*)ids.ptr : "%any");
DBG4(DBG_CFG, " secret: %#B", &secret);
- this->shared->insert_last(this->shared, shared_key);
+ owners = linked_list_create();
while (ids.len > 0)
{
chunk_t id;
@@ -1111,14 +784,15 @@ static bool load_shared(private_stroke_cred_t *this, chunk_t line, int line_nr,
continue;
}
- shared_key->add_owner(shared_key, peer_id);
+ owners->insert_last(owners, peer_id);
any = FALSE;
}
if (any)
{
- shared_key->add_owner(shared_key,
+ owners->insert_last(owners,
identification_create_from_encoding(ID_ANY, chunk_empty));
}
+ this->creds->add_shared_list(this->creds, shared_key, owners);
return TRUE;
}
@@ -1130,8 +804,6 @@ static void load_secrets(private_stroke_cred_t *this, char *file, int level,
{
int line_nr = 0, fd;
chunk_t src, line;
- private_key_t *private;
- shared_key_t *shared;
struct stat sb;
void *addr;
@@ -1160,20 +832,8 @@ static void load_secrets(private_stroke_cred_t *this, char *file, int level,
src = chunk_create(addr, sb.st_size);
if (level == 0)
- {
- this->lock->write_lock(this->lock);
-
- /* flush secrets on non-recursive invocation */
- while (this->shared->remove_last(this->shared,
- (void**)&shared) == SUCCESS)
- {
- shared->destroy(shared);
- }
- while (this->private->remove_last(this->private,
- (void**)&private) == SUCCESS)
- {
- private->destroy(private);
- }
+ { /* flush secrets on non-recursive invocation */
+ this->creds->clear_secrets(this->creds);
}
while (fetchline(&src, &line))
@@ -1234,7 +894,6 @@ static void load_secrets(private_stroke_cred_t *this, char *file, int level,
if (glob(pattern, GLOB_ERR, NULL, &buf) != 0)
{
DBG1(DBG_CFG, "expanding file expression '%s' failed", pattern);
- globfree(&buf);
}
else
{
@@ -1302,10 +961,6 @@ static void load_secrets(private_stroke_cred_t *this, char *file, int level,
break;
}
}
- if (level == 0)
- {
- this->lock->unlock(this->lock);
- }
munmap(addr, sb.st_size);
close(fd);
}
@@ -1384,10 +1039,8 @@ static void reread(private_stroke_cred_t *this, stroke_msg_t *msg, FILE *prompt)
*/
static void destroy(private_stroke_cred_t *this)
{
- this->certs->destroy_offset(this->certs, offsetof(certificate_t, destroy));
- this->shared->destroy_offset(this->shared, offsetof(shared_key_t, destroy));
- this->private->destroy_offset(this->private, offsetof(private_key_t, destroy));
- this->lock->destroy(this->lock);
+ lib->credmgr->remove_set(lib->credmgr, &this->creds->set);
+ this->creds->destroy(this->creds);
free(this);
}
@@ -1398,9 +1051,9 @@ stroke_cred_t *stroke_cred_create()
{
private_stroke_cred_t *this = malloc_thing(private_stroke_cred_t);
- this->public.set.create_private_enumerator = (void*)create_private_enumerator;
- this->public.set.create_cert_enumerator = (void*)create_cert_enumerator;
- this->public.set.create_shared_enumerator = (void*)create_shared_enumerator;
+ this->public.set.create_private_enumerator = (void*)return_null;
+ this->public.set.create_cert_enumerator = (void*)return_null;
+ this->public.set.create_shared_enumerator = (void*)return_null;
this->public.set.create_cdp_enumerator = (void*)return_null;
this->public.set.cache_cert = (void*)cache_cert;
this->public.reread = (void(*)(stroke_cred_t*, stroke_msg_t *msg, FILE*))reread;
@@ -1409,10 +1062,8 @@ stroke_cred_t *stroke_cred_create()
this->public.cachecrl = (void(*)(stroke_cred_t*, bool enabled))cachecrl;
this->public.destroy = (void(*)(stroke_cred_t*))destroy;
- this->certs = linked_list_create();
- this->shared = linked_list_create();
- this->private = linked_list_create();
- this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
+ this->creds = mem_cred_create();
+ lib->credmgr->add_set(lib->credmgr, &this->creds->set);
load_certs(this);
load_secrets(this, SECRETS_FILE, 0, NULL);
diff --git a/src/libcharon/plugins/stroke/stroke_list.c b/src/libcharon/plugins/stroke/stroke_list.c
index 86deea490..36311f092 100644
--- a/src/libcharon/plugins/stroke/stroke_list.c
+++ b/src/libcharon/plugins/stroke/stroke_list.c
@@ -388,10 +388,8 @@ static void log_auth_cfgs(FILE *out, peer_cfg_t *peer_cfg, bool local)
enumerator->destroy(enumerator);
}
-/**
- * Implementation of stroke_list_t.status.
- */
-static void status(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out, bool all)
+METHOD(stroke_list_t, status, void,
+ private_stroke_list_t *this, stroke_msg_t *msg, FILE *out, bool all)
{
enumerator_t *enumerator, *children;
ike_cfg_t *ike_cfg;
@@ -756,7 +754,7 @@ static void stroke_list_certs(linked_list_t *list, char *label,
enumerator_t *enumerator;
identification_t *altName;
bool first_altName = TRUE;
- int pathlen;
+ u_int pathlen;
chunk_t serial, authkey;
time_t notBefore, notAfter;
public_key_t *public;
@@ -836,10 +834,10 @@ static void stroke_list_certs(linked_list_t *list, char *label,
}
/* list optional pathLenConstraint */
- pathlen = x509->get_pathLenConstraint(x509);
- if (pathlen != X509_NO_PATH_LEN_CONSTRAINT)
+ pathlen = x509->get_constraint(x509, X509_PATH_LEN);
+ if (pathlen != X509_NO_CONSTRAINT)
{
- fprintf(out, " pathlen: %d\n", pathlen);
+ fprintf(out, " pathlen: %u\n", pathlen);
}
/* list optional ipAddrBlocks */
@@ -979,6 +977,10 @@ static void stroke_list_crls(linked_list_t *list, bool utc, FILE *out)
{
fprintf(out, " serial: %#B\n", &chunk);
}
+ if (crl->is_delta_crl(crl, &chunk))
+ {
+ fprintf(out, " delta for: %#B\n", &chunk);
+ }
/* count the number of revoked certificates */
{
@@ -1060,6 +1062,25 @@ static void stroke_list_ocsp(linked_list_t* list, bool utc, FILE *out)
}
/**
+ * Print the name of an algorithm plus the name of the plugin that registered it
+ */
+static void print_alg(FILE *out, int *len, enum_name_t *alg_names, int alg_type,
+ const char *plugin_name)
+{
+ char alg_name[BUF_LEN];
+ int alg_name_len;
+
+ alg_name_len = sprintf(alg_name, " %N[%s]", alg_names, alg_type, plugin_name);
+ if (*len + alg_name_len > CRYPTO_MAX_ALG_LINE)
+ {
+ fprintf(out, "\n ");
+ *len = 13;
+ }
+ fprintf(out, "%s", alg_name);
+ *len += alg_name_len;
+}
+
+/**
* List of registered cryptographical algorithms
*/
static void list_algs(FILE *out)
@@ -1070,58 +1091,73 @@ static void list_algs(FILE *out)
hash_algorithm_t hash;
pseudo_random_function_t prf;
diffie_hellman_group_t group;
+ rng_quality_t quality;
+ const char *plugin_name;
+ int len;
fprintf(out, "\n");
fprintf(out, "List of registered IKEv2 Algorithms:\n");
- fprintf(out, "\n encryption: ");
+ fprintf(out, "\n encryption:");
+ len = 13;
enumerator = lib->crypto->create_crypter_enumerator(lib->crypto);
- while (enumerator->enumerate(enumerator, &encryption))
+ while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
{
- fprintf(out, "%N ", encryption_algorithm_names, encryption);
+ print_alg(out, &len, encryption_algorithm_names, encryption, plugin_name);
}
enumerator->destroy(enumerator);
- fprintf(out, "\n integrity: ");
+ fprintf(out, "\n integrity: ");
+ len = 13;
enumerator = lib->crypto->create_signer_enumerator(lib->crypto);
- while (enumerator->enumerate(enumerator, &integrity))
+ while (enumerator->enumerate(enumerator, &integrity, &plugin_name))
{
- fprintf(out, "%N ", integrity_algorithm_names, integrity);
+ print_alg(out, &len, integrity_algorithm_names, integrity, plugin_name);
}
enumerator->destroy(enumerator);
- fprintf(out, "\n aead: ");
+ fprintf(out, "\n aead: ");
+ len = 13;
enumerator = lib->crypto->create_aead_enumerator(lib->crypto);
- while (enumerator->enumerate(enumerator, &encryption))
+ while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
{
- fprintf(out, "%N ", encryption_algorithm_names, encryption);
+ print_alg(out, &len, encryption_algorithm_names, encryption, plugin_name);
}
enumerator->destroy(enumerator);
- fprintf(out, "\n hasher: ");
+ fprintf(out, "\n hasher: ");
+ len = 13;
enumerator = lib->crypto->create_hasher_enumerator(lib->crypto);
- while (enumerator->enumerate(enumerator, &hash))
+ while (enumerator->enumerate(enumerator, &hash, &plugin_name))
{
- fprintf(out, "%N ", hash_algorithm_names, hash);
+ print_alg(out, &len, hash_algorithm_names, hash, plugin_name);
}
enumerator->destroy(enumerator);
- fprintf(out, "\n prf: ");
+ fprintf(out, "\n prf: ");
+ len = 13;
enumerator = lib->crypto->create_prf_enumerator(lib->crypto);
- while (enumerator->enumerate(enumerator, &prf))
+ while (enumerator->enumerate(enumerator, &prf, &plugin_name))
{
- fprintf(out, "%N ", pseudo_random_function_names, prf);
+ print_alg(out, &len, pseudo_random_function_names, prf, plugin_name);
}
enumerator->destroy(enumerator);
- fprintf(out, "\n dh-group: ");
+ fprintf(out, "\n dh-group: ");
+ len = 13;
enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
- while (enumerator->enumerate(enumerator, &group))
+ while (enumerator->enumerate(enumerator, &group, &plugin_name))
{
- fprintf(out, "%N ", diffie_hellman_group_names, group);
+ print_alg(out, &len, diffie_hellman_group_names, group, plugin_name);
+ }
+ enumerator->destroy(enumerator);
+ fprintf(out, "\n random-gen:");
+ len = 13;
+ enumerator = lib->crypto->create_rng_enumerator(lib->crypto);
+ while (enumerator->enumerate(enumerator, &quality, &plugin_name))
+ {
+ print_alg(out, &len, rng_quality_names, quality, plugin_name);
}
enumerator->destroy(enumerator);
fprintf(out, "\n");
}
-/**
- * Implementation of stroke_list_t.list.
- */
-static void list(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out)
+METHOD(stroke_list_t, list, void,
+ private_stroke_list_t *this, stroke_msg_t *msg, FILE *out)
{
linked_list_t *cert_list = NULL;
@@ -1224,10 +1260,8 @@ static void pool_leases(private_stroke_list_t *this, FILE *out, char *pool,
}
}
-/**
- * Implementation of stroke_list_t.leases
- */
-static void leases(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out)
+METHOD(stroke_list_t, leases, void,
+ private_stroke_list_t *this, stroke_msg_t *msg, FILE *out)
{
enumerator_t *enumerator;
u_int size, offline, online;
@@ -1264,10 +1298,8 @@ static void leases(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out)
DESTROY_IF(address);
}
-/**
- * Implementation of stroke_list_t.destroy
- */
-static void destroy(private_stroke_list_t *this)
+METHOD(stroke_list_t, destroy, void,
+ private_stroke_list_t *this)
{
free(this);
}
@@ -1277,15 +1309,19 @@ static void destroy(private_stroke_list_t *this)
*/
stroke_list_t *stroke_list_create(stroke_attribute_t *attribute)
{
- private_stroke_list_t *this = malloc_thing(private_stroke_list_t);
-
- this->public.list = (void(*)(stroke_list_t*, stroke_msg_t *msg, FILE *out))list;
- this->public.status = (void(*)(stroke_list_t*, stroke_msg_t *msg, FILE *out,bool))status;
- this->public.leases = (void(*)(stroke_list_t*, stroke_msg_t *msg, FILE *out))leases;
- this->public.destroy = (void(*)(stroke_list_t*))destroy;
-
- this->uptime = time_monotonic(NULL);
- this->attribute = attribute;
+ private_stroke_list_t *this;
+
+ INIT(this,
+ .public = {
+
+ .list = _list,
+ .status = _status,
+ .leases = _leases,
+ .destroy = _destroy,
+ },
+ .uptime = time_monotonic(NULL),
+ .attribute = attribute,
+ );
return &this->public;
}
diff --git a/src/libcharon/plugins/stroke/stroke_plugin.c b/src/libcharon/plugins/stroke/stroke_plugin.c
index 4361e5050..2e83d0d28 100644
--- a/src/libcharon/plugins/stroke/stroke_plugin.c
+++ b/src/libcharon/plugins/stroke/stroke_plugin.c
@@ -36,10 +36,8 @@ struct private_stroke_plugin_t {
stroke_socket_t *socket;
};
-/**
- * Implementation of stroke_plugin_t.destroy
- */
-static void destroy(private_stroke_plugin_t *this)
+METHOD(plugin_t, destroy, void,
+ private_stroke_plugin_t *this)
{
this->socket->destroy(this->socket);
free(this);
@@ -50,11 +48,17 @@ static void destroy(private_stroke_plugin_t *this)
*/
plugin_t *stroke_plugin_create()
{
- private_stroke_plugin_t *this = malloc_thing(private_stroke_plugin_t);
+ private_stroke_plugin_t *this;
- this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
+ INIT(this,
+ .public = {
+ .plugin = {
+ .destroy = _destroy,
+ },
+ },
+ .socket = stroke_socket_create(),
+ );
- this->socket = stroke_socket_create();
if (this->socket == NULL)
{
free(this);
diff --git a/src/libcharon/plugins/stroke/stroke_shared_key.c b/src/libcharon/plugins/stroke/stroke_shared_key.c
deleted file mode 100644
index 4f716e83a..000000000
--- a/src/libcharon/plugins/stroke/stroke_shared_key.c
+++ /dev/null
@@ -1,140 +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 "stroke_shared_key.h"
-
-#include <utils/linked_list.h>
-
-typedef struct private_stroke_shared_key_t private_stroke_shared_key_t;
-
-/**
- * private data of shared_key
- */
-struct private_stroke_shared_key_t {
-
- /**
- * implements shared_key_t
- */
- stroke_shared_key_t public;
-
- /**
- * type of this key
- */
- shared_key_type_t type;
-
- /**
- * data of the key
- */
- chunk_t key;
-
- /**
- * list of key owners, as identification_t
- */
- linked_list_t *owners;
-
- /**
- * reference counter
- */
- refcount_t ref;
-};
-
-/**
- * Implementation of shared_key_t.get_type.
- */
-static shared_key_type_t get_type(private_stroke_shared_key_t *this)
-{
- return this->type;
-}
-
-/**
- * Implementation of shared_key_t.get_ref.
- */
-static private_stroke_shared_key_t* get_ref(private_stroke_shared_key_t *this)
-{
- ref_get(&this->ref);
- return this;
-}
-
-/**
- * Implementation of shared_key_t.get_key.
- */
-static chunk_t get_key(private_stroke_shared_key_t *this)
-{
- return this->key;
-}
-
-/**
- * Implementation of stroke_shared_key_t.has_owner.
- */
-static id_match_t has_owner(private_stroke_shared_key_t *this, identification_t *owner)
-{
- enumerator_t *enumerator;
- id_match_t match, best = ID_MATCH_NONE;
- identification_t *current;
-
- enumerator = this->owners->create_enumerator(this->owners);
- while (enumerator->enumerate(enumerator, &current))
- {
- match = owner->matches(owner, current);
- if (match > best)
- {
- best = match;
- }
- }
- enumerator->destroy(enumerator);
- return best;
-}
-/**
- * Implementation of stroke_shared_key_t.add_owner.
- */
-static void add_owner(private_stroke_shared_key_t *this, identification_t *owner)
-{
- this->owners->insert_last(this->owners, owner);
-}
-
-/**
- * Implementation of stroke_shared_key_t.destroy
- */
-static void destroy(private_stroke_shared_key_t *this)
-{
- if (ref_put(&this->ref))
- {
- this->owners->destroy_offset(this->owners, offsetof(identification_t, destroy));
- chunk_free(&this->key);
- free(this);
- }
-}
-
-/**
- * create a shared key
- */
-stroke_shared_key_t *stroke_shared_key_create(shared_key_type_t type, chunk_t key)
-{
- private_stroke_shared_key_t *this = malloc_thing(private_stroke_shared_key_t);
-
- this->public.shared.get_type = (shared_key_type_t(*)(shared_key_t*))get_type;
- this->public.shared.get_key = (chunk_t(*)(shared_key_t*))get_key;
- this->public.shared.get_ref = (shared_key_t*(*)(shared_key_t*))get_ref;
- this->public.shared.destroy = (void(*)(shared_key_t*))destroy;
- this->public.add_owner = (void(*)(stroke_shared_key_t*, identification_t *owner))add_owner;
- this->public.has_owner = (id_match_t(*)(stroke_shared_key_t*, identification_t *owner))has_owner;
-
- this->owners = linked_list_create();
- this->type = type;
- this->key = key;
- this->ref = 1;
-
- return &this->public;
-}
diff --git a/src/libcharon/plugins/stroke/stroke_shared_key.h b/src/libcharon/plugins/stroke/stroke_shared_key.h
deleted file mode 100644
index 05ad55083..000000000
--- a/src/libcharon/plugins/stroke/stroke_shared_key.h
+++ /dev/null
@@ -1,60 +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 stroke_shared_key stroke_shared_key
- * @{ @ingroup stroke
- */
-
-#ifndef STROKE_SHARED_KEY_H_
-#define STROKE_SHARED_KEY_H_
-
-#include <utils/identification.h>
-#include <credentials/keys/shared_key.h>
-
-typedef struct stroke_shared_key_t stroke_shared_key_t;
-
-/**
- * Shared key implementation for keys read from ipsec.secrets
- */
-struct stroke_shared_key_t {
-
- /**
- * Implements the shared_key_t interface.
- */
- shared_key_t shared;
-
- /**
- * Add an owner to the key.
- *
- * @param owner owner to add
- */
- void (*add_owner)(stroke_shared_key_t *this, identification_t *owner);
-
- /**
- * Check if a key has a specific owner.
- *
- * @param owner owner to check
- * @return best match found
- */
- id_match_t (*has_owner)(stroke_shared_key_t *this, identification_t *owner);
-};
-
-/**
- * Create a stroke_shared_key instance.
- */
-stroke_shared_key_t *stroke_shared_key_create(shared_key_type_t type, chunk_t key);
-
-#endif /** STROKE_SHARED_KEY_H_ @}*/
diff --git a/src/libcharon/plugins/stroke/stroke_socket.c b/src/libcharon/plugins/stroke/stroke_socket.c
index 0a5110fd3..18e77905d 100644
--- a/src/libcharon/plugins/stroke/stroke_socket.c
+++ b/src/libcharon/plugins/stroke/stroke_socket.c
@@ -151,6 +151,7 @@ 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->cert_policy);
pop_string(msg, &end->updown);
DBG2(DBG_CFG, " %s=%s", label, end->address);
@@ -246,6 +247,17 @@ static void stroke_terminate_srcip(private_stroke_socket_t *this,
}
/**
+ * rekey a connection by name/id
+ */
+static void stroke_rekey(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
+{
+ pop_string(msg, &msg->terminate.name);
+ DBG1(DBG_CFG, "received stroke: rekey '%s'", msg->rekey.name);
+
+ this->control->rekey(this->control, msg, out);
+}
+
+/**
* route a policy (install SPD entries)
*/
static void stroke_route(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
@@ -348,6 +360,14 @@ static void stroke_purge(private_stroke_socket_t *this,
{
lib->credmgr->flush_cache(lib->credmgr, CERT_X509_OCSP_RESPONSE);
}
+ if (msg->purge.flags & PURGE_CRLS)
+ {
+ lib->credmgr->flush_cache(lib->credmgr, CERT_X509_CRL);
+ }
+ if (msg->purge.flags & PURGE_CERTS)
+ {
+ lib->credmgr->flush_cache(lib->credmgr, CERT_X509);
+ }
if (msg->purge.flags & PURGE_IKE)
{
this->control->purge_ike(this->control, msg, out);
@@ -510,6 +530,9 @@ static job_requeue_t process(stroke_job_context_t *ctx)
case STR_TERMINATE_SRCIP:
stroke_terminate_srcip(this, msg, out);
break;
+ case STR_REKEY:
+ stroke_rekey(this, msg, out);
+ break;
case STR_STATUS:
stroke_status(this, msg, out, FALSE);
break;
diff --git a/src/libcharon/plugins/tnc_imc/Makefile.am b/src/libcharon/plugins/tnc_imc/Makefile.am
index ca8869460..2c551813e 100644
--- a/src/libcharon/plugins/tnc_imc/Makefile.am
+++ b/src/libcharon/plugins/tnc_imc/Makefile.am
@@ -1,11 +1,9 @@
INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
- -I$(top_srcdir)/src/libcharon `xml2-config --cflags`
+ -I$(top_srcdir)/src/libcharon
AM_CFLAGS = -rdynamic
-libstrongswan_tnc_imc_la_LIBADD = -ltnc
-
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-tnc-imc.la
else
@@ -13,7 +11,8 @@ plugin_LTLIBRARIES = libstrongswan-tnc-imc.la
endif
libstrongswan_tnc_imc_la_SOURCES = \
- tnc_imc_plugin.h tnc_imc_plugin.c
+ tnc_imc_plugin.h tnc_imc_plugin.c tnc_imc.h tnc_imc.c \
+ tnc_imc_manager.h tnc_imc_manager.c tnc_imc_bind_function.c
libstrongswan_tnc_imc_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/tnc_imc/Makefile.in b/src/libcharon/plugins/tnc_imc/Makefile.in
index 9a8794e93..dc44408ff 100644
--- a/src/libcharon/plugins/tnc_imc/Makefile.in
+++ b/src/libcharon/plugins/tnc_imc/Makefile.in
@@ -74,8 +74,9 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
-libstrongswan_tnc_imc_la_DEPENDENCIES =
-am_libstrongswan_tnc_imc_la_OBJECTS = tnc_imc_plugin.lo
+libstrongswan_tnc_imc_la_LIBADD =
+am_libstrongswan_tnc_imc_la_OBJECTS = tnc_imc_plugin.lo tnc_imc.lo \
+ tnc_imc_manager.lo tnc_imc_bind_function.lo
libstrongswan_tnc_imc_la_OBJECTS = \
$(am_libstrongswan_tnc_imc_la_OBJECTS)
libstrongswan_tnc_imc_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@@ -221,9 +222,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -262,6 +261,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
@@ -273,14 +274,14 @@ 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 `xml2-config --cflags`
+ -I$(top_srcdir)/src/libcharon
AM_CFLAGS = -rdynamic
-libstrongswan_tnc_imc_la_LIBADD = -ltnc
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-tnc-imc.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-tnc-imc.la
libstrongswan_tnc_imc_la_SOURCES = \
- tnc_imc_plugin.h tnc_imc_plugin.c
+ tnc_imc_plugin.h tnc_imc_plugin.c tnc_imc.h tnc_imc.c \
+ tnc_imc_manager.h tnc_imc_manager.c tnc_imc_bind_function.c
libstrongswan_tnc_imc_la_LDFLAGS = -module -avoid-version
all: all-am
@@ -366,6 +367,9 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_imc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_imc_bind_function.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_imc_manager.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_imc_plugin.Plo@am__quote@
.c.o:
diff --git a/src/libcharon/plugins/tnc_imc/tnc_imc.c b/src/libcharon/plugins/tnc_imc/tnc_imc.c
new file mode 100644
index 000000000..174084436
--- /dev/null
+++ b/src/libcharon/plugins/tnc_imc/tnc_imc.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2006 Mike McCauley
+ * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnc_imc.h"
+
+#include <dlfcn.h>
+
+#include <debug.h>
+#include <library.h>
+
+typedef struct private_tnc_imc_t private_tnc_imc_t;
+
+/**
+ * Private data of an imv_t object.
+ */
+struct private_tnc_imc_t {
+
+ /**
+ * Public members of imc_t.
+ */
+ imc_t public;
+
+ /**
+ * Path of loaded IMC
+ */
+ char *path;
+
+ /**
+ * Name of loaded IMC
+ */
+ char *name;
+
+ /**
+ * Handle of loaded IMC
+ */
+ void *handle;
+
+ /**
+ * ID of loaded IMC
+ */
+ TNC_IMCID id;
+
+ /**
+ * List of message types supported by IMC
+ */
+ TNC_MessageTypeList supported_types;
+
+ /**
+ * Number of supported message types
+ */
+ TNC_UInt32 type_count;
+};
+
+METHOD(imc_t, set_id, void,
+ private_tnc_imc_t *this, TNC_IMCID id)
+{
+ this->id = id;
+}
+
+METHOD(imc_t, get_id, TNC_IMCID,
+ private_tnc_imc_t *this)
+{
+ return this->id;
+}
+
+METHOD(imc_t, get_name, char*,
+ private_tnc_imc_t *this)
+{
+ return this->name;
+}
+
+METHOD(imc_t, set_message_types, void,
+ private_tnc_imc_t *this, TNC_MessageTypeList supported_types,
+ TNC_UInt32 type_count)
+{
+ /* Free an existing MessageType list */
+ free(this->supported_types);
+ this->supported_types = NULL;
+
+ /* Store the new MessageType list */
+ this->type_count = type_count;
+ if (type_count && supported_types)
+ {
+ size_t size = type_count * sizeof(TNC_MessageType);
+
+ this->supported_types = malloc(size);
+ memcpy(this->supported_types, supported_types, size);
+ }
+ DBG2(DBG_TNC, "IMC %u supports %u message types", this->id, type_count);
+}
+
+METHOD(imc_t, type_supported, bool,
+ private_tnc_imc_t *this, TNC_MessageType message_type)
+{
+ TNC_VendorID msg_vid, vid;
+ TNC_MessageSubtype msg_subtype, subtype;
+ int i;
+
+ msg_vid = (message_type >> 8) & TNC_VENDORID_ANY;
+ msg_subtype = message_type & TNC_SUBTYPE_ANY;
+
+ for (i = 0; i < this->type_count; i++)
+ {
+ vid = (this->supported_types[i] >> 8) & TNC_VENDORID_ANY;
+ subtype = this->supported_types[i] & TNC_SUBTYPE_ANY;
+
+ if (this->supported_types[i] == message_type
+ || (subtype == TNC_SUBTYPE_ANY
+ && (msg_vid == vid || vid == TNC_VENDORID_ANY))
+ || (vid == TNC_VENDORID_ANY
+ && (msg_subtype == subtype || subtype == TNC_SUBTYPE_ANY)))
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+METHOD(imc_t, destroy, void,
+ private_tnc_imc_t *this)
+{
+ dlclose(this->handle);
+ free(this->supported_types);
+ free(this->name);
+ free(this->path);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+imc_t* tnc_imc_create(char *name, char *path)
+{
+ private_tnc_imc_t *this;
+
+ INIT(this,
+ .public = {
+ .set_id = _set_id,
+ .get_id = _get_id,
+ .get_name = _get_name,
+ .set_message_types = _set_message_types,
+ .type_supported = _type_supported,
+ .destroy = _destroy,
+ },
+ .name = name,
+ .path = path,
+ );
+
+ this->handle = dlopen(path, RTLD_LAZY);
+ if (!this->handle)
+ {
+ DBG1(DBG_TNC, "IMC \"%s\" failed to load: %s", name, dlerror());
+ free(this);
+ return NULL;
+ }
+
+ this->public.initialize = dlsym(this->handle, "TNC_IMC_Initialize");
+ if (!this->public.initialize)
+ {
+ DBG1(DBG_TNC, "could not resolve TNC_IMC_Initialize in %s: %s\n",
+ path, dlerror());
+ dlclose(this->handle);
+ free(this);
+ return NULL;
+ }
+ this->public.notify_connection_change =
+ dlsym(this->handle, "TNC_IMC_NotifyConnectionChange");
+ this->public.begin_handshake = dlsym(this->handle, "TNC_IMC_BeginHandshake");
+ if (!this->public.begin_handshake)
+ {
+ DBG1(DBG_TNC, "could not resolve TNC_IMC_BeginHandshake in %s: %s\n",
+ path, dlerror());
+ dlclose(this->handle);
+ free(this);
+ return NULL;
+ }
+ this->public.receive_message =
+ dlsym(this->handle, "TNC_IMC_ReceiveMessage");
+ this->public.batch_ending =
+ dlsym(this->handle, "TNC_IMC_BatchEnding");
+ this->public.terminate =
+ dlsym(this->handle, "TNC_IMC_Terminate");
+ this->public.provide_bind_function =
+ dlsym(this->handle, "TNC_IMC_ProvideBindFunction");
+ if (!this->public.provide_bind_function)
+ {
+ DBG1(DBG_TNC, "could not resolve TNC_IMC_ProvideBindFunction in %s: %s\n",
+ path, dlerror());
+ dlclose(this->handle);
+ free(this);
+ return NULL;
+ }
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/tnc_imc/tnc_imc.h b/src/libcharon/plugins/tnc_imc/tnc_imc.h
new file mode 100644
index 000000000..10a67f90b
--- /dev/null
+++ b/src/libcharon/plugins/tnc_imc/tnc_imc.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ *
+ * @defgroup tnc_imc_t tnc_imc
+ * @{ @ingroup tnc_imc
+ */
+
+#ifndef TNC_IMC_H_
+#define TNC_IMC_H_
+
+#include <tnc/imc/imc.h>
+
+/**
+ * Create an Integrity Measurement Collector.
+ *
+ * @param name name of the IMC
+ * @param filename path to the dynamic IMC library
+ * @return instance of the imc_t interface
+ */
+imc_t* tnc_imc_create(char *name, char *filename);
+
+#endif /** TNC_IMC_H_ @}*/
diff --git a/src/libcharon/plugins/tnc_imc/tnc_imc_bind_function.c b/src/libcharon/plugins/tnc_imc/tnc_imc_bind_function.c
new file mode 100644
index 000000000..e18f1b006
--- /dev/null
+++ b/src/libcharon/plugins/tnc_imc/tnc_imc_bind_function.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2006 Mike McCauley
+ * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnc_imc.h"
+
+#include <debug.h>
+#include <daemon.h>
+
+#define TNC_IMVID_ANY 0xffff
+
+/**
+ * Called by the IMC to inform a TNCC about the set of message types the IMC
+ * is able to receive
+ */
+TNC_Result TNC_TNCC_ReportMessageTypes(TNC_IMCID imc_id,
+ TNC_MessageTypeList supported_types,
+ TNC_UInt32 type_count)
+{
+ return charon->imcs->set_message_types(charon->imcs, imc_id,
+ supported_types, type_count);
+}
+
+/**
+ * Called by the IMC to ask a TNCC to retry an Integrity Check Handshake
+ */
+TNC_Result TNC_TNCC_RequestHandshakeRetry(TNC_IMCID imc_id,
+ TNC_ConnectionID connection_id,
+ TNC_RetryReason reason)
+{
+ return charon->tnccs->request_handshake_retry(charon->tnccs, TRUE, imc_id,
+ connection_id, reason);
+}
+
+/**
+ * Called by the IMC when an IMC-IMV message is to be sent
+ */
+TNC_Result TNC_TNCC_SendMessage(TNC_IMCID imc_id,
+ TNC_ConnectionID connection_id,
+ TNC_BufferReference msg,
+ TNC_UInt32 msg_len,
+ TNC_MessageType msg_type)
+{
+ return charon->tnccs->send_message(charon->tnccs, imc_id, TNC_IMVID_ANY,
+ connection_id, msg, msg_len, msg_type);
+}
+
+/**
+ * Called by the IMC when it needs a function pointer
+ */
+TNC_Result TNC_TNCC_BindFunction(TNC_IMCID id,
+ char *function_name,
+ void **function_pointer)
+{
+ if (streq(function_name, "TNC_TNCC_ReportMessageTypes"))
+ {
+ *function_pointer = (void*)TNC_TNCC_ReportMessageTypes;
+ }
+ else if (streq(function_name, "TNC_TNCC_RequestHandshakeRetry"))
+ {
+ *function_pointer = (void*)TNC_TNCC_RequestHandshakeRetry;
+ }
+ else if (streq(function_name, "TNC_TNCC_SendMessage"))
+ {
+ *function_pointer = (void*)TNC_TNCC_SendMessage;
+ }
+ else
+ {
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+ return TNC_RESULT_SUCCESS;
+}
diff --git a/src/libcharon/plugins/tnc_imc/tnc_imc_manager.c b/src/libcharon/plugins/tnc_imc/tnc_imc_manager.c
new file mode 100644
index 000000000..aa20534f5
--- /dev/null
+++ b/src/libcharon/plugins/tnc_imc/tnc_imc_manager.c
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2006 Mike McCauley
+ * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnc_imc_manager.h"
+
+#include <tnc/imc/imc_manager.h>
+#include <tnc/tncifimc.h>
+
+#include <debug.h>
+#include <library.h>
+#include <utils/linked_list.h>
+
+typedef struct private_tnc_imc_manager_t private_tnc_imc_manager_t;
+
+/**
+ * Private data of an imc_manager_t object.
+ */
+struct private_tnc_imc_manager_t {
+
+ /**
+ * Public members of imc_manager_t.
+ */
+ imc_manager_t public;
+
+ /**
+ * Linked list of IMCs
+ */
+ linked_list_t *imcs;
+
+ /**
+ * Next IMC ID to be assigned
+ */
+ TNC_IMCID next_imc_id;
+};
+
+METHOD(imc_manager_t, add, bool,
+ private_tnc_imc_manager_t *this, imc_t *imc)
+{
+ TNC_Version version;
+
+ /* Initialize the module */
+ imc->set_id(imc, this->next_imc_id);
+ if (imc->initialize(imc->get_id(imc), TNC_IFIMC_VERSION_1,
+ TNC_IFIMC_VERSION_1, &version) != TNC_RESULT_SUCCESS)
+ {
+ DBG1(DBG_TNC, "IMC \"%s\" failed to initialize", imc->get_name(imc));
+ return FALSE;
+ }
+ this->imcs->insert_last(this->imcs, imc);
+ this->next_imc_id++;
+
+ if (imc->provide_bind_function(imc->get_id(imc), TNC_TNCC_BindFunction)
+ != TNC_RESULT_SUCCESS)
+ {
+ DBG1(DBG_TNC, "IMC \"%s\" failed to obtain bind function",
+ imc->get_name(imc));
+ this->imcs->remove_last(this->imcs, (void**)&imc);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+METHOD(imc_manager_t, remove_, imc_t*,
+ private_tnc_imc_manager_t *this, TNC_IMCID id)
+{
+ enumerator_t *enumerator;
+ imc_t *imc;
+
+ enumerator = this->imcs->create_enumerator(this->imcs);
+ while (enumerator->enumerate(enumerator, &imc))
+ {
+ if (id == imc->get_id(imc))
+ {
+ this->imcs->remove_at(this->imcs, enumerator);
+ return imc;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return NULL;
+}
+
+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");
+}
+
+METHOD(imc_manager_t, notify_connection_change, void,
+ private_tnc_imc_manager_t *this, TNC_ConnectionID id,
+ TNC_ConnectionState state)
+{
+ enumerator_t *enumerator;
+ imc_t *imc;
+
+ enumerator = this->imcs->create_enumerator(this->imcs);
+ while (enumerator->enumerate(enumerator, &imc))
+ {
+ if (imc->notify_connection_change)
+ {
+ imc->notify_connection_change(imc->get_id(imc), id, state);
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+METHOD(imc_manager_t, begin_handshake, void,
+ private_tnc_imc_manager_t *this, TNC_ConnectionID id)
+{
+ enumerator_t *enumerator;
+ imc_t *imc;
+
+ enumerator = this->imcs->create_enumerator(this->imcs);
+ while (enumerator->enumerate(enumerator, &imc))
+ {
+ imc->begin_handshake(imc->get_id(imc), id);
+ }
+ enumerator->destroy(enumerator);
+}
+
+METHOD(imc_manager_t, set_message_types, TNC_Result,
+ private_tnc_imc_manager_t *this, TNC_IMCID id,
+ TNC_MessageTypeList supported_types,
+ TNC_UInt32 type_count)
+{
+ enumerator_t *enumerator;
+ imc_t *imc;
+ TNC_Result result = TNC_RESULT_FATAL;
+
+ enumerator = this->imcs->create_enumerator(this->imcs);
+ while (enumerator->enumerate(enumerator, &imc))
+ {
+ if (id == imc->get_id(imc))
+ {
+ imc->set_message_types(imc, supported_types, type_count);
+ result = TNC_RESULT_SUCCESS;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return result;
+}
+
+METHOD(imc_manager_t, receive_message, void,
+ private_tnc_imc_manager_t *this, TNC_ConnectionID connection_id,
+ TNC_BufferReference message,
+ TNC_UInt32 message_len,
+ TNC_MessageType message_type)
+{
+ enumerator_t *enumerator;
+ imc_t *imc;
+
+ enumerator = this->imcs->create_enumerator(this->imcs);
+ while (enumerator->enumerate(enumerator, &imc))
+ {
+ if (imc->receive_message && imc->type_supported(imc, message_type))
+ {
+ imc->receive_message(imc->get_id(imc), connection_id,
+ message, message_len, message_type);
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+METHOD(imc_manager_t, batch_ending, void,
+ private_tnc_imc_manager_t *this, TNC_ConnectionID id)
+{
+ enumerator_t *enumerator;
+ imc_t *imc;
+
+ enumerator = this->imcs->create_enumerator(this->imcs);
+ while (enumerator->enumerate(enumerator, &imc))
+ {
+ if (imc->batch_ending)
+ {
+ imc->batch_ending(imc->get_id(imc), id);
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+METHOD(imc_manager_t, destroy, void,
+ private_tnc_imc_manager_t *this)
+{
+ imc_t *imc;
+
+ while (this->imcs->remove_last(this->imcs, (void**)&imc) == SUCCESS)
+ {
+ if (imc->terminate &&
+ imc->terminate(imc->get_id(imc)) != TNC_RESULT_SUCCESS)
+ {
+ DBG1(DBG_TNC, "IMC \"%s\" not terminated successfully",
+ imc->get_name(imc));
+ }
+ imc->destroy(imc);
+ }
+ this->imcs->destroy(this->imcs);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+imc_manager_t* tnc_imc_manager_create(void)
+{
+ private_tnc_imc_manager_t *this;
+
+ INIT(this,
+ .public = {
+ .add = _add,
+ .remove = _remove_, /* avoid name conflict with stdio.h */
+ .get_preferred_language = _get_preferred_language,
+ .notify_connection_change = _notify_connection_change,
+ .begin_handshake = _begin_handshake,
+ .set_message_types = _set_message_types,
+ .receive_message = _receive_message,
+ .batch_ending = _batch_ending,
+ .destroy = _destroy,
+ },
+ .imcs = linked_list_create(),
+ .next_imc_id = 1,
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/tnc_imc/tnc_imc_manager.h b/src/libcharon/plugins/tnc_imc/tnc_imc_manager.h
new file mode 100644
index 000000000..ed490293b
--- /dev/null
+++ b/src/libcharon/plugins/tnc_imc/tnc_imc_manager.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ *
+ * @defgroup tnc_imc_manager tnc_imc_manager
+ * @{ @ingroup tnc_imc
+ */
+
+#ifndef TNC_IMC_MANAGER_H_
+#define TNC_IMC_MANAGER_H_
+
+#include <tnc/imc/imc_manager.h>
+
+/**
+ * Create an IMC manager instance.
+ */
+imc_manager_t *tnc_imc_manager_create();
+
+#endif /** TNC_IMC_MANAGER_H_ @}*/
diff --git a/src/libcharon/plugins/tnc_imc/tnc_imc_plugin.c b/src/libcharon/plugins/tnc_imc/tnc_imc_plugin.c
index 0ce930ba3..89888040a 100644
--- a/src/libcharon/plugins/tnc_imc/tnc_imc_plugin.c
+++ b/src/libcharon/plugins/tnc_imc/tnc_imc_plugin.c
@@ -14,15 +14,137 @@
*/
#include "tnc_imc_plugin.h"
+#include "tnc_imc_manager.h"
+#include "tnc_imc.h"
-#include <libtnctncc.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
#include <daemon.h>
+#include <utils/lexparser.h>
+
+/**
+ * load IMCs from a configuration file
+ */
+static bool load_imcs(char *filename)
+{
+ int fd, line_nr = 0;
+ chunk_t src, line;
+ struct stat sb;
+ void *addr;
+
+ DBG1(DBG_TNC, "loading IMCs from '%s'", filename);
+ fd = open(filename, O_RDONLY);
+ if (fd == -1)
+ {
+ DBG1(DBG_TNC, "opening configuration file '%s' failed: %s", filename,
+ strerror(errno));
+ return FALSE;
+ }
+ if (fstat(fd, &sb) == -1)
+ {
+ DBG1(DBG_LIB, "getting file size of '%s' failed: %s", filename,
+ strerror(errno));
+ close(fd);
+ return FALSE;
+ }
+ addr = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+ if (addr == MAP_FAILED)
+ {
+ DBG1(DBG_LIB, "mapping '%s' failed: %s", filename, strerror(errno));
+ close(fd);
+ return FALSE;
+ }
+ src = chunk_create(addr, sb.st_size);
+
+ while (fetchline(&src, &line))
+ {
+ char *name, *path;
+ chunk_t token;
+ imc_t *imc;
+
+ line_nr++;
+
+ /* skip comments or empty lines */
+ if (*line.ptr == '#' || !eat_whitespace(&line))
+ {
+ continue;
+ }
+
+ /* determine keyword */
+ if (!extract_token(&token, ' ', &line))
+ {
+ DBG1(DBG_TNC, "line %d: keyword must be followed by a space",
+ line_nr);
+ return FALSE;
+ }
+
+ /* only interested in IMCs */
+ if (!match("IMC", &token))
+ {
+ continue;
+ }
+
+ /* advance to the IMC name and extract it */
+ if (!extract_token(&token, '"', &line) ||
+ !extract_token(&token, '"', &line))
+ {
+ DBG1(DBG_TNC, "line %d: IMC name must be set in double quotes",
+ line_nr);
+ return FALSE;
+ }
+
+ /* copy the IMC name */
+ name = malloc(token.len + 1);
+ memcpy(name, token.ptr, token.len);
+ name[token.len] = '\0';
+
+ /* advance to the IMC path and extract it */
+ if (!eat_whitespace(&line))
+ {
+ DBG1(DBG_TNC, "line %d: IMC path is missing", line_nr);
+ free(name);
+ return FALSE;
+ }
+ if (!extract_token(&token, ' ', &line))
+ {
+ token = line;
+ }
+
+ /* copy the IMC path */
+ path = malloc(token.len + 1);
+ memcpy(path, token.ptr, token.len);
+ path[token.len] = '\0';
+
+ /* load and register IMC instance */
+ imc = tnc_imc_create(name, path);
+ if (!imc)
+ {
+ free(name);
+ free(path);
+ return FALSE;
+ }
+ if (!charon->imcs->add(charon->imcs, imc))
+ {
+ imc->destroy(imc);
+ return FALSE;
+ }
+ DBG1(DBG_TNC, "IMC %u \"%s\" loaded from '%s'", imc->get_id(imc),
+ name, path);
+ }
+ munmap(addr, sb.st_size);
+ close(fd);
+ return TRUE;
+}
METHOD(plugin_t, destroy, void,
tnc_imc_plugin_t *this)
{
- libtnc_tncc_Terminate();
+ charon->imcs->destroy(charon->imcs);
free(this);
}
@@ -31,7 +153,7 @@ METHOD(plugin_t, destroy, void,
*/
plugin_t *tnc_imc_plugin_create()
{
- char *tnc_config, *pref_lang;
+ char *tnc_config;
tnc_imc_plugin_t *this;
INIT(this,
@@ -40,18 +162,19 @@ plugin_t *tnc_imc_plugin_create()
},
);
- pref_lang = lib->settings->get_str(lib->settings,
- "charon.plugins.tnc-imc.preferred_language", "en");
+ /* Create IMC manager */
+ charon->imcs = tnc_imc_manager_create();
+
+ /* Load IMCs and abort if not all instances initalize successfully */
tnc_config = lib->settings->get_str(lib->settings,
"charon.plugins.tnc-imc.tnc_config", "/etc/tnc_config");
-
- if (libtnc_tncc_Initialize(tnc_config) != TNC_RESULT_SUCCESS)
+ if (!load_imcs(tnc_config))
{
+ charon->imcs->destroy(charon->imcs);
+ charon->imcs = NULL;
free(this);
- DBG1(DBG_TNC, "TNC IMC initialization failed");
return NULL;
}
-
return &this->plugin;
}
diff --git a/src/libcharon/plugins/tnc_imv/Makefile.am b/src/libcharon/plugins/tnc_imv/Makefile.am
index 9c3b47364..3ba283bb7 100644
--- a/src/libcharon/plugins/tnc_imv/Makefile.am
+++ b/src/libcharon/plugins/tnc_imv/Makefile.am
@@ -1,11 +1,9 @@
INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
- -I$(top_srcdir)/src/libcharon `xml2-config --cflags`
+ -I$(top_srcdir)/src/libcharon
AM_CFLAGS = -rdynamic
-libstrongswan_tnc_imv_la_LIBADD = -ltnc
-
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-tnc-imv.la
else
@@ -13,7 +11,9 @@ plugin_LTLIBRARIES = libstrongswan-tnc-imv.la
endif
libstrongswan_tnc_imv_la_SOURCES = \
- tnc_imv_plugin.h tnc_imv_plugin.c
+ tnc_imv_plugin.h tnc_imv_plugin.c tnc_imv.h tnc_imv.c \
+ tnc_imv_manager.h tnc_imv_manager.c tnc_imv_bind_function.c \
+ tnc_imv_recommendations.h tnc_imv_recommendations.c
libstrongswan_tnc_imv_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/tnc_imv/Makefile.in b/src/libcharon/plugins/tnc_imv/Makefile.in
index f89b5e03b..0324d2eb9 100644
--- a/src/libcharon/plugins/tnc_imv/Makefile.in
+++ b/src/libcharon/plugins/tnc_imv/Makefile.in
@@ -74,8 +74,10 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
-libstrongswan_tnc_imv_la_DEPENDENCIES =
-am_libstrongswan_tnc_imv_la_OBJECTS = tnc_imv_plugin.lo
+libstrongswan_tnc_imv_la_LIBADD =
+am_libstrongswan_tnc_imv_la_OBJECTS = tnc_imv_plugin.lo tnc_imv.lo \
+ tnc_imv_manager.lo tnc_imv_bind_function.lo \
+ tnc_imv_recommendations.lo
libstrongswan_tnc_imv_la_OBJECTS = \
$(am_libstrongswan_tnc_imv_la_OBJECTS)
libstrongswan_tnc_imv_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@@ -221,9 +223,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -262,6 +262,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
@@ -273,14 +275,15 @@ 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 `xml2-config --cflags`
+ -I$(top_srcdir)/src/libcharon
AM_CFLAGS = -rdynamic
-libstrongswan_tnc_imv_la_LIBADD = -ltnc
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-tnc-imv.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-tnc-imv.la
libstrongswan_tnc_imv_la_SOURCES = \
- tnc_imv_plugin.h tnc_imv_plugin.c
+ tnc_imv_plugin.h tnc_imv_plugin.c tnc_imv.h tnc_imv.c \
+ tnc_imv_manager.h tnc_imv_manager.c tnc_imv_bind_function.c \
+ tnc_imv_recommendations.h tnc_imv_recommendations.c
libstrongswan_tnc_imv_la_LDFLAGS = -module -avoid-version
all: all-am
@@ -366,7 +369,11 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_imv.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_imv_bind_function.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_imv_manager.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_imv_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_imv_recommendations.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv.c b/src/libcharon/plugins/tnc_imv/tnc_imv.c
new file mode 100644
index 000000000..f88b645d6
--- /dev/null
+++ b/src/libcharon/plugins/tnc_imv/tnc_imv.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2006 Mike McCauley
+ * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnc_imv.h"
+
+#include <dlfcn.h>
+
+#include <debug.h>
+#include <library.h>
+
+typedef struct private_tnc_imv_t private_tnc_imv_t;
+
+/**
+ * Private data of an imv_t object.
+ */
+struct private_tnc_imv_t {
+
+ /**
+ * Public members of imv_t.
+ */
+ imv_t public;
+
+ /**
+ * Path of loaded IMV
+ */
+ char *path;
+
+ /**
+ * Name of loaded IMV
+ */
+ char *name;
+
+ /**
+ * Handle of loaded IMV
+ */
+ void *handle;
+
+ /**
+ * ID of loaded IMV
+ */
+ TNC_IMVID id;
+
+ /**
+ * List of message types supported by IMC
+ */
+ TNC_MessageTypeList supported_types;
+
+ /**
+ * Number of supported message types
+ */
+ TNC_UInt32 type_count;
+};
+
+METHOD(imv_t, set_id, void,
+ private_tnc_imv_t *this, TNC_IMVID id)
+{
+ this->id = id;
+}
+
+METHOD(imv_t, get_id, TNC_IMVID,
+ private_tnc_imv_t *this)
+{
+ return this->id;
+}
+
+METHOD(imv_t, get_name, char*,
+ private_tnc_imv_t *this)
+{
+ return this->name;
+}
+
+METHOD(imv_t, set_message_types, void,
+ private_tnc_imv_t *this, TNC_MessageTypeList supported_types,
+ TNC_UInt32 type_count)
+{
+ /* Free an existing MessageType list */
+ free(this->supported_types);
+ this->supported_types = NULL;
+
+ /* Store the new MessageType list */
+ this->type_count = type_count;
+ if (type_count && supported_types)
+ {
+ size_t size = type_count * sizeof(TNC_MessageType);
+
+ this->supported_types = malloc(size);
+ memcpy(this->supported_types, supported_types, size);
+ }
+ DBG2(DBG_TNC, "IMV %u supports %u message types", this->id, type_count);
+}
+
+METHOD(imv_t, type_supported, bool,
+ private_tnc_imv_t *this, TNC_MessageType message_type)
+{
+ TNC_VendorID msg_vid, vid;
+ TNC_MessageSubtype msg_subtype, subtype;
+ int i;
+
+ msg_vid = (message_type >> 8) & TNC_VENDORID_ANY;
+ msg_subtype = message_type & TNC_SUBTYPE_ANY;
+
+ for (i = 0; i < this->type_count; i++)
+ {
+ vid = (this->supported_types[i] >> 8) & TNC_VENDORID_ANY;
+ subtype = this->supported_types[i] & TNC_SUBTYPE_ANY;
+
+ if (this->supported_types[i] == message_type
+ || (subtype == TNC_SUBTYPE_ANY
+ && (msg_vid == vid || vid == TNC_VENDORID_ANY))
+ || (vid == TNC_VENDORID_ANY
+ && (msg_subtype == subtype || subtype == TNC_SUBTYPE_ANY)))
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+METHOD(imv_t, destroy, void,
+ private_tnc_imv_t *this)
+{
+ dlclose(this->handle);
+ free(this->supported_types);
+ free(this->name);
+ free(this->path);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+imv_t* tnc_imv_create(char *name, char *path)
+{
+ private_tnc_imv_t *this;
+
+ INIT(this,
+ .public = {
+ .set_id = _set_id,
+ .get_id = _get_id,
+ .get_name = _get_name,
+ .set_message_types = _set_message_types,
+ .type_supported = _type_supported,
+ .destroy = _destroy,
+ },
+ .name = name,
+ .path = path,
+ );
+
+ this->handle = dlopen(path, RTLD_LAZY);
+ if (!this->handle)
+ {
+ DBG1(DBG_TNC, "IMV \"%s\" failed to load: %s", name, dlerror());
+ free(this);
+ return NULL;
+ }
+
+ this->public.initialize = dlsym(this->handle, "TNC_IMV_Initialize");
+ if (!this->public.initialize)
+ {
+ DBG1(DBG_TNC, "could not resolve TNC_IMV_Initialize in %s: %s\n",
+ path, dlerror());
+ dlclose(this->handle);
+ free(this);
+ return NULL;
+ }
+ this->public.notify_connection_change =
+ dlsym(this->handle, "TNC_IMV_NotifyConnectionChange");
+ this->public.solicit_recommendation =
+ dlsym(this->handle, "TNC_IMV_SolicitRecommendation");
+ if (!this->public.solicit_recommendation)
+ {
+ DBG1(DBG_TNC, "could not resolve TNC_IMV_SolicitRecommendation in %s: %s\n",
+ path, dlerror());
+ dlclose(this->handle);
+ free(this);
+ return NULL;
+ }
+ this->public.receive_message =
+ dlsym(this->handle, "TNC_IMV_ReceiveMessage");
+ this->public.batch_ending =
+ dlsym(this->handle, "TNC_IMV_BatchEnding");
+ this->public.terminate =
+ dlsym(this->handle, "TNC_IMV_Terminate");
+ this->public.provide_bind_function =
+ dlsym(this->handle, "TNC_IMV_ProvideBindFunction");
+ if (!this->public.provide_bind_function)
+ {
+ DBG1(DBG_TNC, "could not resolve TNC_IMV_ProvideBindFunction in %s: %s\n",
+ path, dlerror());
+ dlclose(this->handle);
+ free(this);
+ return NULL;
+ }
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv.h b/src/libcharon/plugins/tnc_imv/tnc_imv.h
new file mode 100644
index 000000000..75939e54c
--- /dev/null
+++ b/src/libcharon/plugins/tnc_imv/tnc_imv.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ *
+ * @defgroup tnc_imv_t tnc_imv
+ * @{ @ingroup tnc_imv
+ */
+
+#ifndef TNC_IMV_H_
+#define TNC_IMV_H_
+
+#include <tnc/imv/imv.h>
+
+/**
+ * Create an Integrity Measurement Verifier.
+ *
+ * @param name name of the IMV
+ * @param filename path to the dynamic IMV library
+ * @return instance of the imv_t interface
+ */
+imv_t* tnc_imv_create(char *name, char *filename);
+
+#endif /** TNC_IMV_H_ @}*/
diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv_bind_function.c b/src/libcharon/plugins/tnc_imv/tnc_imv_bind_function.c
new file mode 100644
index 000000000..0ea52f08e
--- /dev/null
+++ b/src/libcharon/plugins/tnc_imv/tnc_imv_bind_function.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2006 Mike McCauley
+ * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnc_imv.h"
+
+#include <debug.h>
+#include <daemon.h>
+
+#define TNC_IMCID_ANY 0xffff
+
+/**
+ * Called by the IMV to inform a TNCS about the set of message types the IMV
+ * is able to receive
+ */
+TNC_Result TNC_TNCS_ReportMessageTypes(TNC_IMVID imv_id,
+ TNC_MessageTypeList supported_types,
+ TNC_UInt32 type_count)
+{
+ return charon->imvs->set_message_types(charon->imvs, imv_id,
+ supported_types, type_count);
+}
+
+/**
+ * Called by the IMV to ask a TNCS to retry an Integrity Check Handshake
+ */
+TNC_Result TNC_TNCS_RequestHandshakeRetry(TNC_IMVID imv_id,
+ TNC_ConnectionID connection_id,
+ TNC_RetryReason reason)
+{
+ return charon->tnccs->request_handshake_retry(charon->tnccs, FALSE, imv_id,
+ connection_id, reason);
+}
+
+/**
+ * Called by the IMV when an IMV-IMC message is to be sent
+ */
+TNC_Result TNC_TNCS_SendMessage(TNC_IMVID imv_id,
+ TNC_ConnectionID connection_id,
+ TNC_BufferReference msg,
+ TNC_UInt32 msg_len,
+ TNC_MessageType msg_type)
+{
+ return charon->tnccs->send_message(charon->tnccs, TNC_IMCID_ANY, imv_id,
+ connection_id, msg, msg_len, msg_type);
+}
+
+/**
+ * Called by the IMV to deliver its IMV Action Recommendation and IMV Evaluation
+ * Result to the TNCS
+ */
+TNC_Result TNC_TNCS_ProvideRecommendation(TNC_IMVID imv_id,
+ TNC_ConnectionID connection_id,
+ TNC_IMV_Action_Recommendation recommendation,
+ TNC_IMV_Evaluation_Result evaluation)
+{
+ return charon->tnccs->provide_recommendation(charon->tnccs, imv_id,
+ connection_id, recommendation, evaluation);
+}
+
+/**
+ * Called by the IMV to get the value of an attribute associated with a
+ * connection or with the TNCS as a whole.
+ */
+TNC_Result TNC_TNCS_GetAttribute(TNC_IMVID imv_id,
+ TNC_ConnectionID connection_id,
+ TNC_AttributeID attribute_id,
+ TNC_UInt32 buffer_len,
+ TNC_BufferReference buffer,
+ TNC_UInt32 *out_value_len)
+{
+ return charon->tnccs->get_attribute(charon->tnccs, imv_id, connection_id,
+ attribute_id, buffer_len, buffer, out_value_len);
+}
+
+/**
+ * Called by the IMV to set the value of an attribute associated with a
+ * connection or with the TNCS as a whole.
+ */
+TNC_Result TNC_TNCS_SetAttribute(TNC_IMVID imv_id,
+ TNC_ConnectionID connection_id,
+ TNC_AttributeID attribute_id,
+ TNC_UInt32 buffer_len,
+ TNC_BufferReference buffer)
+{
+ return charon->tnccs->set_attribute(charon->tnccs, imv_id, connection_id,
+ attribute_id, buffer_len, buffer);
+}
+
+/**
+ * Called by the IMV when it needs a function pointer
+ */
+TNC_Result TNC_TNCS_BindFunction(TNC_IMVID id,
+ char *function_name,
+ void **function_pointer)
+{
+ if (streq(function_name, "TNC_TNCS_ReportMessageTypes"))
+ {
+ *function_pointer = (void*)TNC_TNCS_ReportMessageTypes;
+ }
+ else if (streq(function_name, "TNC_TNCS_RequestHandshakeRetry"))
+ {
+ *function_pointer = (void*)TNC_TNCS_RequestHandshakeRetry;
+ }
+ else if (streq(function_name, "TNC_TNCS_SendMessage"))
+ {
+ *function_pointer = (void*)TNC_TNCS_SendMessage;
+ }
+ else if (streq(function_name, "TNC_TNCS_ProvideRecommendation"))
+ {
+ *function_pointer = (void*)TNC_TNCS_ProvideRecommendation;
+ }
+ else if (streq(function_name, "TNC_TNCS_GetAttribute"))
+ {
+ *function_pointer = (void*)TNC_TNCS_GetAttribute;
+ }
+ else if (streq(function_name, "TNC_TNCS_SetAttribute"))
+ {
+ *function_pointer = (void*)TNC_TNCS_SetAttribute;
+ }
+ else
+ {
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+ return TNC_RESULT_SUCCESS;
+}
diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv_manager.c b/src/libcharon/plugins/tnc_imv/tnc_imv_manager.c
new file mode 100644
index 000000000..559de86d0
--- /dev/null
+++ b/src/libcharon/plugins/tnc_imv/tnc_imv_manager.c
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2006 Mike McCauley
+ * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnc_imv_manager.h"
+#include "tnc_imv_recommendations.h"
+
+#include <tnc/imv/imv_manager.h>
+#include <tnc/tncifimv.h>
+
+#include <debug.h>
+#include <daemon.h>
+#include <threading/mutex.h>
+
+typedef struct private_tnc_imv_manager_t private_tnc_imv_manager_t;
+
+
+/**
+ * Private data of an imv_manager_t object.
+ */
+struct private_tnc_imv_manager_t {
+
+ /**
+ * Public members of imv_manager_t.
+ */
+ imv_manager_t public;
+
+ /**
+ * Linked list of IMVs
+ */
+ linked_list_t *imvs;
+
+ /**
+ * Next IMV ID to be assigned
+ */
+ TNC_IMVID next_imv_id;
+
+ /**
+ * Policy defining how to derive final recommendation from individual ones
+ */
+ recommendation_policy_t policy;
+};
+
+METHOD(imv_manager_t, add, bool,
+ private_tnc_imv_manager_t *this, imv_t *imv)
+{
+ TNC_Version version;
+
+ /* Initialize the IMV module */
+ imv->set_id(imv, this->next_imv_id);
+ if (imv->initialize(imv->get_id(imv), TNC_IFIMV_VERSION_1,
+ TNC_IFIMV_VERSION_1, &version) != TNC_RESULT_SUCCESS)
+ {
+ DBG1(DBG_TNC, "IMV \"%s\" failed to initialize", imv->get_name(imv));
+ return FALSE;
+ }
+ this->imvs->insert_last(this->imvs, imv);
+ this->next_imv_id++;
+
+ if (imv->provide_bind_function(imv->get_id(imv), TNC_TNCS_BindFunction)
+ != TNC_RESULT_SUCCESS)
+ {
+ DBG1(DBG_TNC, "IMV \"%s\" could failed to obtain bind function",
+ imv->get_name(imv));
+ this->imvs->remove_last(this->imvs, (void**)&imv);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+METHOD(imv_manager_t, remove_, imv_t*,
+ private_tnc_imv_manager_t *this, TNC_IMVID id)
+{
+ enumerator_t *enumerator;
+ imv_t *imv;
+
+ enumerator = this->imvs->create_enumerator(this->imvs);
+ while (enumerator->enumerate(enumerator, &imv))
+ {
+ if (id == imv->get_id(imv))
+ {
+ this->imvs->remove_at(this->imvs, enumerator);
+ return imv;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return NULL;
+}
+
+METHOD(imv_manager_t, get_recommendation_policy, recommendation_policy_t,
+ private_tnc_imv_manager_t *this)
+{
+ return this->policy;
+}
+
+METHOD(imv_manager_t, create_recommendations, recommendations_t*,
+ private_tnc_imv_manager_t *this)
+{
+ return tnc_imv_recommendations_create(this->imvs);
+}
+
+METHOD(imv_manager_t, enforce_recommendation, bool,
+ private_tnc_imv_manager_t *this, TNC_IMV_Action_Recommendation rec)
+{
+ char *group;
+ identification_t *id;
+ ike_sa_t *ike_sa;
+ auth_cfg_t *auth;
+
+ switch (rec)
+ {
+ case TNC_IMV_ACTION_RECOMMENDATION_ALLOW:
+ DBG1(DBG_TNC, "TNC recommendation is allow");
+ group = "allow";
+ break;
+ case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE:
+ DBG1(DBG_TNC, "TNC recommendation is isolate");
+ group = "isolate";
+ break;
+ case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS:
+ case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION:
+ default:
+ DBG1(DBG_TNC, "TNC recommendation is none");
+ return FALSE;
+ }
+ ike_sa = charon->bus->get_sa(charon->bus);
+ if (ike_sa)
+ {
+ auth = ike_sa->get_auth_cfg(ike_sa, FALSE);
+ id = identification_create_from_string(group);
+ auth->add(auth, AUTH_RULE_GROUP, id);
+ DBG1(DBG_TNC, "TNC added group membership '%s'", group);
+ }
+ return TRUE;
+}
+
+
+METHOD(imv_manager_t, notify_connection_change, void,
+ private_tnc_imv_manager_t *this, TNC_ConnectionID id,
+ TNC_ConnectionState state)
+{
+ enumerator_t *enumerator;
+ imv_t *imv;
+
+ enumerator = this->imvs->create_enumerator(this->imvs);
+ while (enumerator->enumerate(enumerator, &imv))
+ {
+ if (imv->notify_connection_change)
+ {
+ imv->notify_connection_change(imv->get_id(imv), id, state);
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+METHOD(imv_manager_t, set_message_types, TNC_Result,
+ private_tnc_imv_manager_t *this, TNC_IMVID id,
+ TNC_MessageTypeList supported_types,
+ TNC_UInt32 type_count)
+{
+ enumerator_t *enumerator;
+ imv_t *imv;
+ TNC_Result result = TNC_RESULT_FATAL;
+
+ enumerator = this->imvs->create_enumerator(this->imvs);
+ while (enumerator->enumerate(enumerator, &imv))
+ {
+ if (id == imv->get_id(imv))
+ {
+ imv->set_message_types(imv, supported_types, type_count);
+ result = TNC_RESULT_SUCCESS;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return result;
+}
+
+METHOD(imv_manager_t, solicit_recommendation, void,
+ private_tnc_imv_manager_t *this, TNC_ConnectionID id)
+{
+ enumerator_t *enumerator;
+ imv_t *imv;
+
+ enumerator = this->imvs->create_enumerator(this->imvs);
+ while (enumerator->enumerate(enumerator, &imv))
+ {
+ imv->solicit_recommendation(imv->get_id(imv), id);
+ }
+ enumerator->destroy(enumerator);
+}
+
+METHOD(imv_manager_t, receive_message, void,
+ private_tnc_imv_manager_t *this, TNC_ConnectionID connection_id,
+ TNC_BufferReference message,
+ TNC_UInt32 message_len,
+ TNC_MessageType message_type)
+{
+ enumerator_t *enumerator;
+ imv_t *imv;
+
+ enumerator = this->imvs->create_enumerator(this->imvs);
+ while (enumerator->enumerate(enumerator, &imv))
+ {
+ if (imv->receive_message && imv->type_supported(imv, message_type))
+ {
+ imv->receive_message(imv->get_id(imv), connection_id,
+ message, message_len, message_type);
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+METHOD(imv_manager_t, batch_ending, void,
+ private_tnc_imv_manager_t *this, TNC_ConnectionID id)
+{
+ enumerator_t *enumerator;
+ imv_t *imv;
+
+ enumerator = this->imvs->create_enumerator(this->imvs);
+ while (enumerator->enumerate(enumerator, &imv))
+ {
+ if (imv->batch_ending)
+ {
+ imv->batch_ending(imv->get_id(imv), id);
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+METHOD(imv_manager_t, destroy, void,
+ private_tnc_imv_manager_t *this)
+{
+ imv_t *imv;
+
+ while (this->imvs->remove_last(this->imvs, (void**)&imv) == SUCCESS)
+ {
+ if (imv->terminate &&
+ imv->terminate(imv->get_id(imv)) != TNC_RESULT_SUCCESS)
+ {
+ DBG1(DBG_TNC, "IMV \"%s\" not terminated successfully",
+ imv->get_name(imv));
+ }
+ imv->destroy(imv);
+ }
+ this->imvs->destroy(this->imvs);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+imv_manager_t* tnc_imv_manager_create(void)
+{
+ private_tnc_imv_manager_t *this;
+ recommendation_policy_t policy;
+
+ INIT(this,
+ .public = {
+ .add = _add,
+ .remove = _remove_, /* avoid name conflict with stdio.h */
+ .get_recommendation_policy = _get_recommendation_policy,
+ .create_recommendations = _create_recommendations,
+ .enforce_recommendation = _enforce_recommendation,
+ .notify_connection_change = _notify_connection_change,
+ .set_message_types = _set_message_types,
+ .solicit_recommendation = _solicit_recommendation,
+ .receive_message = _receive_message,
+ .batch_ending = _batch_ending,
+ .destroy = _destroy,
+ },
+ .imvs = linked_list_create(),
+ .next_imv_id = 1,
+ );
+ policy = enum_from_name(recommendation_policy_names,
+ lib->settings->get_str(lib->settings,
+ "charon.plugins.tnc-imv.recommendation_policy", "default"));
+ this->policy = (policy != -1) ? policy : RECOMMENDATION_POLICY_DEFAULT;
+ DBG1(DBG_TNC, "TNC recommendation policy is '%N'",
+ recommendation_policy_names, this->policy);
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv_manager.h b/src/libcharon/plugins/tnc_imv/tnc_imv_manager.h
new file mode 100644
index 000000000..2fe9e7ae3
--- /dev/null
+++ b/src/libcharon/plugins/tnc_imv/tnc_imv_manager.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ *
+ * @defgroup tnc_imv_manager tnc_imv_manager
+ * @{ @ingroup tnc_imv
+ */
+
+#ifndef TNC_IMV_MANAGER_H_
+#define TNC_IMV_MANAGER_H_
+
+#include <tnc/imv/imv_manager.h>
+
+/**
+ * Create an IMV manager instance.
+ */
+imv_manager_t *tnc_imv_manager_create();
+
+#endif /** TNC_IMV_MANAGER_H_ @}*/
diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv_plugin.c b/src/libcharon/plugins/tnc_imv/tnc_imv_plugin.c
index 5b3d3892d..f238f01ea 100644
--- a/src/libcharon/plugins/tnc_imv/tnc_imv_plugin.c
+++ b/src/libcharon/plugins/tnc_imv/tnc_imv_plugin.c
@@ -14,15 +14,137 @@
*/
#include "tnc_imv_plugin.h"
+#include "tnc_imv_manager.h"
+#include "tnc_imv.h"
-#include <libtnctncs.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
#include <daemon.h>
+#include <utils/lexparser.h>
+
+/**
+ * load IMVs from a configuration file
+ */
+static bool load_imvs(char *filename)
+{
+ int fd, line_nr = 0;
+ chunk_t src, line;
+ struct stat sb;
+ void *addr;
+
+ DBG1(DBG_TNC, "loading IMVs from '%s'", filename);
+ fd = open(filename, O_RDONLY);
+ if (fd == -1)
+ {
+ DBG1(DBG_TNC, "opening configuration file '%s' failed: %s", filename,
+ strerror(errno));
+ return FALSE;
+ }
+ if (fstat(fd, &sb) == -1)
+ {
+ DBG1(DBG_LIB, "getting file size of '%s' failed: %s", filename,
+ strerror(errno));
+ close(fd);
+ return FALSE;
+ }
+ addr = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+ if (addr == MAP_FAILED)
+ {
+ DBG1(DBG_LIB, "mapping '%s' failed: %s", filename, strerror(errno));
+ close(fd);
+ return FALSE;
+ }
+ src = chunk_create(addr, sb.st_size);
+
+ while (fetchline(&src, &line))
+ {
+ char *name, *path;
+ chunk_t token;
+ imv_t *imv;
+
+ line_nr++;
+
+ /* skip comments or empty lines */
+ if (*line.ptr == '#' || !eat_whitespace(&line))
+ {
+ continue;
+ }
+
+ /* determine keyword */
+ if (!extract_token(&token, ' ', &line))
+ {
+ DBG1(DBG_TNC, "line %d: keyword must be followed by a space",
+ line_nr);
+ return FALSE;
+ }
+
+ /* only interested in IMVs */
+ if (!match("IMV", &token))
+ {
+ continue;
+ }
+
+ /* advance to the IMV name and extract it */
+ if (!extract_token(&token, '"', &line) ||
+ !extract_token(&token, '"', &line))
+ {
+ DBG1(DBG_TNC, "line %d: IMV name must be set in double quotes",
+ line_nr);
+ return FALSE;
+ }
+
+ /* copy the IMV name */
+ name = malloc(token.len + 1);
+ memcpy(name, token.ptr, token.len);
+ name[token.len] = '\0';
+
+ /* advance to the IMV path and extract it */
+ if (!eat_whitespace(&line))
+ {
+ DBG1(DBG_TNC, "line %d: IMV path is missing", line_nr);
+ free(name);
+ return FALSE;
+ }
+ if (!extract_token(&token, ' ', &line))
+ {
+ token = line;
+ }
+
+ /* copy the IMV path */
+ path = malloc(token.len + 1);
+ memcpy(path, token.ptr, token.len);
+ path[token.len] = '\0';
+
+ /* load and register IMV instance */
+ imv = tnc_imv_create(name, path);
+ if (!imv)
+ {
+ free(name);
+ free(path);
+ return FALSE;
+ }
+ if (!charon->imvs->add(charon->imvs, imv))
+ {
+ imv->destroy(imv);
+ return FALSE;
+ }
+ DBG1(DBG_TNC, "IMV %u \"%s\" loaded from '%s'", imv->get_id(imv),
+ name, path);
+ }
+ munmap(addr, sb.st_size);
+ close(fd);
+ return TRUE;
+}
METHOD(plugin_t, destroy, void,
tnc_imv_plugin_t *this)
{
- libtnc_tncs_Terminate();
+ charon->imvs->destroy(charon->imvs);
free(this);
}
@@ -42,13 +164,18 @@ plugin_t *tnc_imv_plugin_create()
tnc_config = lib->settings->get_str(lib->settings,
"charon.plugins.tnc-imv.tnc_config", "/etc/tnc_config");
- if (libtnc_tncs_Initialize(tnc_config) != TNC_RESULT_SUCCESS)
+
+ /* Create IMV manager */
+ charon->imvs = tnc_imv_manager_create();
+
+ /* Load IMVs and abort if not all instances initalize successfully */
+ if (!load_imvs(tnc_config))
{
+ charon->imvs->destroy(charon->imvs);
+ charon->imvs = NULL;
free(this);
- DBG1(DBG_TNC, "TNC IMV initialization failed");
return NULL;
}
-
return &this->plugin;
}
diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv_recommendations.c b/src/libcharon/plugins/tnc_imv/tnc_imv_recommendations.c
new file mode 100644
index 000000000..5cc6b0ced
--- /dev/null
+++ b/src/libcharon/plugins/tnc_imv/tnc_imv_recommendations.c
@@ -0,0 +1,415 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <debug.h>
+#include <daemon.h>
+#include <tnc/tncifimv.h>
+#include <tnc/imv/imv.h>
+#include <tnc/imv/imv_recommendations.h>
+
+typedef struct private_tnc_imv_recommendations_t private_tnc_imv_recommendations_t;
+typedef struct recommendation_entry_t recommendation_entry_t;
+
+/**
+ * Recommendation entry
+ */
+struct recommendation_entry_t {
+
+ /**
+ * IMV ID
+ */
+ TNC_IMVID id;
+
+ /**
+ * Received a recommendation message from this IMV?
+ */
+ bool have_recommendation;
+
+ /**
+ * Action Recommendation provided by IMV instance
+ */
+ TNC_IMV_Action_Recommendation rec;
+
+ /**
+ * Evaluation Result provided by IMV instance
+ */
+ TNC_IMV_Evaluation_Result eval;
+
+ /**
+ * Reason string provided by IMV instance
+ */
+ chunk_t reason;
+
+ /**
+ * Reason language provided by IMV instance
+ */
+ chunk_t reason_language;
+};
+
+/**
+ * Private data of a recommendations_t object.
+ */
+struct private_tnc_imv_recommendations_t {
+
+ /**
+ * Public members of recommendations_t.
+ */
+ recommendations_t public;
+
+ /**
+ * list of recommendations and evaluations provided by IMVs
+ */
+ linked_list_t *recs;
+
+ /**
+ * Preferred language for remediation messages
+ */
+ chunk_t preferred_language;
+};
+
+METHOD(recommendations_t, provide_recommendation, TNC_Result,
+ private_tnc_imv_recommendations_t* this, TNC_IMVID id,
+ TNC_IMV_Action_Recommendation rec,
+ TNC_IMV_Evaluation_Result eval)
+{
+ enumerator_t *enumerator;
+ recommendation_entry_t *entry;
+ bool found = FALSE;
+
+ DBG2(DBG_TNC, "IMV %u provides recommendation '%N' and evaluation '%N'", id,
+ TNC_IMV_Action_Recommendation_names, rec,
+ TNC_IMV_Evaluation_Result_names, eval);
+
+ enumerator = this->recs->create_enumerator(this->recs);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->id == id)
+ {
+ found = TRUE;
+ entry->have_recommendation = TRUE;
+ entry->rec = rec;
+ entry->eval = eval;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return found ? TNC_RESULT_SUCCESS : TNC_RESULT_FATAL;
+}
+
+METHOD(recommendations_t, have_recommendation, bool,
+ private_tnc_imv_recommendations_t *this, TNC_IMV_Action_Recommendation *rec,
+ TNC_IMV_Evaluation_Result *eval)
+{
+ enumerator_t *enumerator;
+ recommendation_entry_t *entry;
+ recommendation_policy_t policy;
+ TNC_IMV_Action_Recommendation final_rec;
+ 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;
+
+ if (this->recs->get_count(this->recs) == 0)
+ {
+ DBG1(DBG_TNC, "there are no IMVs to make a recommendation");
+ return TRUE;
+ }
+ policy = charon->imvs->get_recommendation_policy(charon->imvs);
+
+ enumerator = this->recs->create_enumerator(this->recs);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (!entry->have_recommendation)
+ {
+ incomplete = TRUE;
+ break;
+ }
+ if (first)
+ {
+ final_rec = entry->rec;
+ final_eval = entry->eval;
+ first = FALSE;
+ continue;
+ }
+ switch (policy)
+ {
+ case RECOMMENDATION_POLICY_DEFAULT:
+ switch (entry->rec)
+ {
+ case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS:
+ final_rec = entry->rec;
+ break;
+ case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE:
+ if (final_rec != TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS)
+ {
+ final_rec = entry->rec;
+ };
+ break;
+ case TNC_IMV_ACTION_RECOMMENDATION_ALLOW:
+ if (final_rec == TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION)
+ {
+ final_rec = entry->rec;
+ };
+ break;
+ case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION:
+ break;
+ }
+ switch (entry->eval)
+ {
+ case TNC_IMV_EVALUATION_RESULT_ERROR:
+ final_eval = entry->eval;
+ break;
+ case TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR:
+ if (final_eval != TNC_IMV_EVALUATION_RESULT_ERROR)
+ {
+ final_eval = entry->eval;
+ }
+ break;
+ case TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR:
+ if (final_eval != TNC_IMV_EVALUATION_RESULT_ERROR &&
+ final_eval != TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR)
+ {
+ final_eval = entry->eval;
+ }
+ break;
+ case TNC_IMV_EVALUATION_RESULT_COMPLIANT:
+ if (final_eval == TNC_IMV_EVALUATION_RESULT_DONT_KNOW)
+ {
+ final_eval = entry->eval;
+ }
+ break;
+ case TNC_IMV_EVALUATION_RESULT_DONT_KNOW:
+ break;
+ }
+ break;
+
+ case RECOMMENDATION_POLICY_ALL:
+ if (entry->rec != final_rec)
+ {
+ final_rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION;
+ }
+ if (entry->eval != final_eval)
+ {
+ final_eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
+ }
+ break;
+
+ case RECOMMENDATION_POLICY_ANY:
+ switch (entry->rec)
+ {
+ case TNC_IMV_ACTION_RECOMMENDATION_ALLOW:
+ final_rec = entry->rec;
+ break;
+ case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE:
+ if (final_rec != TNC_IMV_ACTION_RECOMMENDATION_ALLOW)
+ {
+ final_rec = entry->rec;
+ };
+ break;
+ case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS:
+ if (final_rec == TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION)
+ {
+ final_rec = entry->rec;
+ };
+ break;
+ case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION:
+ break;
+ }
+ switch (entry->eval)
+ {
+ case TNC_IMV_EVALUATION_RESULT_COMPLIANT:
+ final_eval = entry->eval;
+ break;
+ case TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR:
+ if (final_eval != TNC_IMV_EVALUATION_RESULT_COMPLIANT)
+ {
+ final_eval = entry->eval;
+ }
+ break;
+ case TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR:
+ if (final_eval != TNC_IMV_EVALUATION_RESULT_COMPLIANT &&
+ final_eval != TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR)
+ {
+ final_eval = entry->eval;
+ }
+ break;
+ case TNC_IMV_EVALUATION_RESULT_ERROR:
+ if (final_eval == TNC_IMV_EVALUATION_RESULT_DONT_KNOW)
+ {
+ final_eval = entry->eval;
+ }
+ break;
+ case TNC_IMV_EVALUATION_RESULT_DONT_KNOW:
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (incomplete)
+ {
+ return FALSE;
+ }
+ *rec = final_rec;
+ *eval = final_eval;
+ return TRUE;
+}
+
+METHOD(recommendations_t, get_preferred_language, chunk_t,
+ private_tnc_imv_recommendations_t *this)
+{
+ return this->preferred_language;
+}
+
+METHOD(recommendations_t, set_preferred_language, void,
+ private_tnc_imv_recommendations_t *this, chunk_t pref_lang)
+{
+ free(this->preferred_language.ptr);
+ this->preferred_language = chunk_clone(pref_lang);
+}
+
+METHOD(recommendations_t, set_reason_string, TNC_Result,
+ private_tnc_imv_recommendations_t *this, TNC_IMVID id, chunk_t reason)
+{
+ enumerator_t *enumerator;
+ recommendation_entry_t *entry;
+ bool found = FALSE;
+
+ DBG2(DBG_TNC, "IMV %u is setting reason string to '%.*s'",
+ id, reason.len, reason.ptr);
+
+ enumerator = this->recs->create_enumerator(this->recs);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->id == id)
+ {
+ found = TRUE;
+ free(entry->reason.ptr);
+ entry->reason = chunk_clone(reason);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return found ? TNC_RESULT_SUCCESS : TNC_RESULT_INVALID_PARAMETER;
+}
+
+METHOD(recommendations_t, set_reason_language, TNC_Result,
+ private_tnc_imv_recommendations_t *this, TNC_IMVID id, chunk_t reason_lang)
+{
+ enumerator_t *enumerator;
+ recommendation_entry_t *entry;
+ bool found = FALSE;
+
+ DBG2(DBG_TNC, "IMV %u is setting reason language to '%.*s'",
+ id, reason_lang.len, reason_lang.ptr);
+
+ enumerator = this->recs->create_enumerator(this->recs);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->id == id)
+ {
+ found = TRUE;
+ free(entry->reason_language.ptr);
+ entry->reason_language = chunk_clone(reason_lang);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return found ? TNC_RESULT_SUCCESS : TNC_RESULT_INVALID_PARAMETER;
+}
+
+/**
+ * Enumerate reason and reason_language, not recommendation entries
+ */
+static bool reason_filter(void *null, recommendation_entry_t **entry,
+ TNC_IMVID *id, void *i2, chunk_t *reason, void *i3,
+ chunk_t *reason_language)
+{
+ if ((*entry)->reason.len)
+ {
+ *id = (*entry)->id;
+ *reason = (*entry)->reason;
+ *reason_language = (*entry)->reason_language;
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+METHOD(recommendations_t, create_reason_enumerator, enumerator_t*,
+ private_tnc_imv_recommendations_t *this)
+{
+ return enumerator_create_filter(this->recs->create_enumerator(this->recs),
+ (void*)reason_filter, NULL, NULL);
+}
+
+METHOD(recommendations_t, destroy, void,
+ private_tnc_imv_recommendations_t *this)
+{
+ recommendation_entry_t *entry;
+
+ while (this->recs->remove_last(this->recs, (void**)&entry) == SUCCESS)
+ {
+ free(entry->reason.ptr);
+ free(entry->reason_language.ptr);
+ free(entry);
+ }
+ this->recs->destroy(this->recs);
+ free(this->preferred_language.ptr);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+recommendations_t* tnc_imv_recommendations_create(linked_list_t *imv_list)
+{
+ private_tnc_imv_recommendations_t *this;
+ recommendation_entry_t *entry;
+ enumerator_t *enumerator;
+ imv_t *imv;
+
+ INIT(this,
+ .public = {
+ .provide_recommendation = _provide_recommendation,
+ .have_recommendation = _have_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,
+ .destroy = _destroy,
+ },
+ .recs = linked_list_create(),
+ );
+
+ enumerator = imv_list->create_enumerator(imv_list);
+ while (enumerator->enumerate(enumerator, &imv))
+ {
+ entry = malloc_thing(recommendation_entry_t);
+ entry->id = imv->get_id(imv);
+ entry->have_recommendation = FALSE;
+ entry->rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION;
+ entry->eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
+ entry->reason = chunk_empty;
+ entry->reason_language = chunk_empty;
+ this->recs->insert_last(this->recs, entry);
+ }
+ enumerator->destroy(enumerator);
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv_recommendations.h b/src/libcharon/plugins/tnc_imv/tnc_imv_recommendations.h
new file mode 100644
index 000000000..6d65a2521
--- /dev/null
+++ b/src/libcharon/plugins/tnc_imv/tnc_imv_recommendations.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ *
+ * @defgroup tnc_imv_manager tnc_imv_manager
+ * @{ @ingroup tnc_imv
+ */
+
+#ifndef TNC_IMV_RECOMMENDATIONS_H_
+#define TNC_IMV_RECOMMENDATIONS_H_
+
+#include <tnc/imv/imv_recommendations.h>
+#include <utils/linked_list.h>
+
+/**
+ * Create an IMV empty recommendations instance
+ */
+recommendations_t *tnc_imv_recommendations_create();
+
+#endif /** TNC_IMV_RECOMMENDATIONS_H_ @}*/
diff --git a/src/libcharon/plugins/tnccs_11/Makefile.am b/src/libcharon/plugins/tnccs_11/Makefile.am
index 7ccd0dfee..1042c3514 100644
--- a/src/libcharon/plugins/tnccs_11/Makefile.am
+++ b/src/libcharon/plugins/tnccs_11/Makefile.am
@@ -1,21 +1,27 @@
INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
- -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls \
- `xml2-config --cflags`
+ -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls ${xml_CFLAGS}
AM_CFLAGS = -rdynamic
-libstrongswan_tnccs_11_la_LIBADD = -ltnc
+libstrongswan_tnccs_11_la_LIBADD = ${xml_LIBS}
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-tnccs-11.la
else
plugin_LTLIBRARIES = libstrongswan-tnccs-11.la
-libstrongswan_tnccs_11_la_LIBADD += $(top_builddir)/src/libtls/libtls.la
endif
libstrongswan_tnccs_11_la_SOURCES = \
- tnccs_11_plugin.h tnccs_11_plugin.c tnccs_11.h tnccs_11.c
+ tnccs_11_plugin.h tnccs_11_plugin.c tnccs_11.h tnccs_11.c \
+ batch/tnccs_batch.h batch/tnccs_batch.c \
+ messages/tnccs_msg.h messages/tnccs_msg.c \
+ messages/imc_imv_msg.h messages/imc_imv_msg.c \
+ messages/tnccs_error_msg.h messages/tnccs_error_msg.c \
+ messages/tnccs_preferred_language_msg.h messages/tnccs_preferred_language_msg.c \
+ messages/tnccs_reason_strings_msg.h messages/tnccs_reason_strings_msg.c \
+ messages/tnccs_recommendation_msg.h messages/tnccs_recommendation_msg.c \
+ messages/tnccs_tncs_contact_info_msg.h messages/tnccs_tncs_contact_info_msg.c
libstrongswan_tnccs_11_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/tnccs_11/Makefile.in b/src/libcharon/plugins/tnccs_11/Makefile.in
index 200ff7a0a..5ab7ccbca 100644
--- a/src/libcharon/plugins/tnccs_11/Makefile.in
+++ b/src/libcharon/plugins/tnccs_11/Makefile.in
@@ -34,7 +34,6 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-@MONOLITHIC_FALSE@am__append_1 = $(top_builddir)/src/libtls/libtls.la
subdir = src/libcharon/plugins/tnccs_11
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -75,8 +74,12 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
-libstrongswan_tnccs_11_la_DEPENDENCIES = $(am__append_1)
-am_libstrongswan_tnccs_11_la_OBJECTS = tnccs_11_plugin.lo tnccs_11.lo
+am__DEPENDENCIES_1 =
+libstrongswan_tnccs_11_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_libstrongswan_tnccs_11_la_OBJECTS = tnccs_11_plugin.lo tnccs_11.lo \
+ tnccs_batch.lo tnccs_msg.lo imc_imv_msg.lo tnccs_error_msg.lo \
+ tnccs_preferred_language_msg.lo tnccs_reason_strings_msg.lo \
+ tnccs_recommendation_msg.lo tnccs_tncs_contact_info_msg.lo
libstrongswan_tnccs_11_la_OBJECTS = \
$(am_libstrongswan_tnccs_11_la_OBJECTS)
libstrongswan_tnccs_11_la_LINK = $(LIBTOOL) --tag=CC \
@@ -223,9 +226,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -264,6 +265,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
@@ -275,15 +278,22 @@ 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 -I$(top_srcdir)/src/libtls \
- `xml2-config --cflags`
+ -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls ${xml_CFLAGS}
AM_CFLAGS = -rdynamic
-libstrongswan_tnccs_11_la_LIBADD = -ltnc $(am__append_1)
+libstrongswan_tnccs_11_la_LIBADD = ${xml_LIBS}
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-tnccs-11.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-tnccs-11.la
libstrongswan_tnccs_11_la_SOURCES = \
- tnccs_11_plugin.h tnccs_11_plugin.c tnccs_11.h tnccs_11.c
+ tnccs_11_plugin.h tnccs_11_plugin.c tnccs_11.h tnccs_11.c \
+ batch/tnccs_batch.h batch/tnccs_batch.c \
+ messages/tnccs_msg.h messages/tnccs_msg.c \
+ messages/imc_imv_msg.h messages/imc_imv_msg.c \
+ messages/tnccs_error_msg.h messages/tnccs_error_msg.c \
+ messages/tnccs_preferred_language_msg.h messages/tnccs_preferred_language_msg.c \
+ messages/tnccs_reason_strings_msg.h messages/tnccs_reason_strings_msg.c \
+ messages/tnccs_recommendation_msg.h messages/tnccs_recommendation_msg.c \
+ messages/tnccs_tncs_contact_info_msg.h messages/tnccs_tncs_contact_info_msg.c
libstrongswan_tnccs_11_la_LDFLAGS = -module -avoid-version
all: all-am
@@ -369,8 +379,16 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imc_imv_msg.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_11.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_11_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_batch.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_error_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_preferred_language_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_reason_strings_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_recommendation_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_tncs_contact_info_msg.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@@ -393,6 +411,62 @@ distclean-compile:
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+tnccs_batch.lo: batch/tnccs_batch.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tnccs_batch.lo -MD -MP -MF $(DEPDIR)/tnccs_batch.Tpo -c -o tnccs_batch.lo `test -f 'batch/tnccs_batch.c' || echo '$(srcdir)/'`batch/tnccs_batch.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tnccs_batch.Tpo $(DEPDIR)/tnccs_batch.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='batch/tnccs_batch.c' object='tnccs_batch.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 tnccs_batch.lo `test -f 'batch/tnccs_batch.c' || echo '$(srcdir)/'`batch/tnccs_batch.c
+
+tnccs_msg.lo: messages/tnccs_msg.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tnccs_msg.lo -MD -MP -MF $(DEPDIR)/tnccs_msg.Tpo -c -o tnccs_msg.lo `test -f 'messages/tnccs_msg.c' || echo '$(srcdir)/'`messages/tnccs_msg.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tnccs_msg.Tpo $(DEPDIR)/tnccs_msg.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/tnccs_msg.c' object='tnccs_msg.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 tnccs_msg.lo `test -f 'messages/tnccs_msg.c' || echo '$(srcdir)/'`messages/tnccs_msg.c
+
+imc_imv_msg.lo: messages/imc_imv_msg.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imc_imv_msg.lo -MD -MP -MF $(DEPDIR)/imc_imv_msg.Tpo -c -o imc_imv_msg.lo `test -f 'messages/imc_imv_msg.c' || echo '$(srcdir)/'`messages/imc_imv_msg.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/imc_imv_msg.Tpo $(DEPDIR)/imc_imv_msg.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/imc_imv_msg.c' object='imc_imv_msg.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 imc_imv_msg.lo `test -f 'messages/imc_imv_msg.c' || echo '$(srcdir)/'`messages/imc_imv_msg.c
+
+tnccs_error_msg.lo: messages/tnccs_error_msg.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tnccs_error_msg.lo -MD -MP -MF $(DEPDIR)/tnccs_error_msg.Tpo -c -o tnccs_error_msg.lo `test -f 'messages/tnccs_error_msg.c' || echo '$(srcdir)/'`messages/tnccs_error_msg.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tnccs_error_msg.Tpo $(DEPDIR)/tnccs_error_msg.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/tnccs_error_msg.c' object='tnccs_error_msg.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 tnccs_error_msg.lo `test -f 'messages/tnccs_error_msg.c' || echo '$(srcdir)/'`messages/tnccs_error_msg.c
+
+tnccs_preferred_language_msg.lo: messages/tnccs_preferred_language_msg.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tnccs_preferred_language_msg.lo -MD -MP -MF $(DEPDIR)/tnccs_preferred_language_msg.Tpo -c -o tnccs_preferred_language_msg.lo `test -f 'messages/tnccs_preferred_language_msg.c' || echo '$(srcdir)/'`messages/tnccs_preferred_language_msg.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tnccs_preferred_language_msg.Tpo $(DEPDIR)/tnccs_preferred_language_msg.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/tnccs_preferred_language_msg.c' object='tnccs_preferred_language_msg.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 tnccs_preferred_language_msg.lo `test -f 'messages/tnccs_preferred_language_msg.c' || echo '$(srcdir)/'`messages/tnccs_preferred_language_msg.c
+
+tnccs_reason_strings_msg.lo: messages/tnccs_reason_strings_msg.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tnccs_reason_strings_msg.lo -MD -MP -MF $(DEPDIR)/tnccs_reason_strings_msg.Tpo -c -o tnccs_reason_strings_msg.lo `test -f 'messages/tnccs_reason_strings_msg.c' || echo '$(srcdir)/'`messages/tnccs_reason_strings_msg.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tnccs_reason_strings_msg.Tpo $(DEPDIR)/tnccs_reason_strings_msg.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/tnccs_reason_strings_msg.c' object='tnccs_reason_strings_msg.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 tnccs_reason_strings_msg.lo `test -f 'messages/tnccs_reason_strings_msg.c' || echo '$(srcdir)/'`messages/tnccs_reason_strings_msg.c
+
+tnccs_recommendation_msg.lo: messages/tnccs_recommendation_msg.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tnccs_recommendation_msg.lo -MD -MP -MF $(DEPDIR)/tnccs_recommendation_msg.Tpo -c -o tnccs_recommendation_msg.lo `test -f 'messages/tnccs_recommendation_msg.c' || echo '$(srcdir)/'`messages/tnccs_recommendation_msg.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tnccs_recommendation_msg.Tpo $(DEPDIR)/tnccs_recommendation_msg.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/tnccs_recommendation_msg.c' object='tnccs_recommendation_msg.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 tnccs_recommendation_msg.lo `test -f 'messages/tnccs_recommendation_msg.c' || echo '$(srcdir)/'`messages/tnccs_recommendation_msg.c
+
+tnccs_tncs_contact_info_msg.lo: messages/tnccs_tncs_contact_info_msg.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tnccs_tncs_contact_info_msg.lo -MD -MP -MF $(DEPDIR)/tnccs_tncs_contact_info_msg.Tpo -c -o tnccs_tncs_contact_info_msg.lo `test -f 'messages/tnccs_tncs_contact_info_msg.c' || echo '$(srcdir)/'`messages/tnccs_tncs_contact_info_msg.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tnccs_tncs_contact_info_msg.Tpo $(DEPDIR)/tnccs_tncs_contact_info_msg.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/tnccs_tncs_contact_info_msg.c' object='tnccs_tncs_contact_info_msg.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 tnccs_tncs_contact_info_msg.lo `test -f 'messages/tnccs_tncs_contact_info_msg.c' || echo '$(srcdir)/'`messages/tnccs_tncs_contact_info_msg.c
+
mostlyclean-libtool:
-rm -f *.lo
diff --git a/src/libcharon/plugins/tnccs_11/batch/tnccs_batch.c b/src/libcharon/plugins/tnccs_11/batch/tnccs_batch.c
new file mode 100644
index 000000000..0f6f3a675
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_11/batch/tnccs_batch.c
@@ -0,0 +1,323 @@
+/*
+ * Copyright (C) 2006 Mike McCauley (mikem@open.com.au)
+ * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnccs_batch.h"
+#include "messages/tnccs_error_msg.h"
+
+#include <debug.h>
+#include <utils/linked_list.h>
+#include <tnc/tnccs/tnccs.h>
+
+#include <libxml/parser.h>
+
+typedef struct private_tnccs_batch_t private_tnccs_batch_t;
+
+/**
+ * Private data of a tnccs_batch_t object.
+ *
+ */
+struct private_tnccs_batch_t {
+ /**
+ * Public tnccs_batch_t interface.
+ */
+ tnccs_batch_t public;
+
+ /**
+ * Batch ID
+ */
+ int batch_id;
+
+ /**
+ * TNCC if TRUE, TNCS if FALSE
+ */
+ bool is_server;
+
+ /**
+ * linked list of TNCCS messages
+ */
+ linked_list_t *messages;
+
+ /**
+ * linked list of TNCCS error messages
+ */
+ linked_list_t *errors;
+
+ /**
+ * XML document
+ */
+ xmlDocPtr doc;
+
+ /**
+ * Encoded message
+ */
+ chunk_t encoding;
+};
+
+METHOD(tnccs_batch_t, get_encoding, chunk_t,
+ private_tnccs_batch_t *this)
+{
+ return this->encoding;
+}
+
+METHOD(tnccs_batch_t, add_msg, void,
+ private_tnccs_batch_t *this, tnccs_msg_t* msg)
+{
+ xmlNodePtr root;
+
+ DBG2(DBG_TNC, "adding %N message", tnccs_msg_type_names,
+ msg->get_type(msg));
+ this->messages->insert_last(this->messages, msg);
+ root = xmlDocGetRootElement(this->doc);
+ xmlAddChild(root, msg->get_node(msg));
+}
+
+METHOD(tnccs_batch_t, build, void,
+ private_tnccs_batch_t *this)
+{
+ xmlChar *xmlbuf;
+ int buf_size;
+
+ xmlDocDumpFormatMemory(this->doc, &xmlbuf, &buf_size, 1);
+ this->encoding = chunk_create((u_char*)xmlbuf, buf_size);
+ this->encoding = chunk_clone(this->encoding);
+ xmlFree(xmlbuf);
+}
+
+METHOD(tnccs_batch_t, process, status_t,
+ private_tnccs_batch_t *this)
+{
+ tnccs_msg_t *tnccs_msg, *msg;
+ tnccs_error_type_t error_type = TNCCS_ERROR_OTHER;
+ char *error_msg, buf[BUF_LEN];
+ xmlNodePtr cur;
+ xmlNsPtr ns;
+ xmlChar *batchid, *recipient;
+ int batch_id;
+
+ this->doc = xmlParseMemory(this->encoding.ptr, this->encoding.len);
+ if (!this->doc)
+ {
+ error_type = TNCCS_ERROR_MALFORMED_BATCH;
+ error_msg = "failed to parse XML message";
+ goto fatal;
+ }
+
+ /* check out the XML document */
+ cur = xmlDocGetRootElement(this->doc);
+ if (!cur)
+ {
+ error_type = TNCCS_ERROR_MALFORMED_BATCH;
+ error_msg = "empty XML document";
+ goto fatal;
+ }
+
+ /* check TNCCS namespace */
+ ns = xmlSearchNsByHref(this->doc, cur, (const xmlChar*)
+ "http://www.trustedcomputinggroup.org/IWG/TNC/1_0/IF_TNCCS#");
+ if (!ns)
+ {
+ error_type = TNCCS_ERROR_MALFORMED_BATCH;
+ error_msg = "TNCCS namespace not found";
+ goto fatal;
+ }
+
+ /* check XML document type */
+ if (xmlStrcmp(cur->name, (const xmlChar*)"TNCCS-Batch"))
+ {
+ error_type = TNCCS_ERROR_MALFORMED_BATCH;
+ error_msg = buf;
+ snprintf(buf, BUF_LEN, "wrong XML document type '%s', expected TNCCS-Batch",
+ cur->name);
+ goto fatal;
+ }
+
+ /* check presence of BatchID property */
+ batchid = xmlGetProp(cur, (const xmlChar*)"BatchId");
+ if (!batchid)
+ {
+ error_type = TNCCS_ERROR_INVALID_BATCH_ID;
+ error_msg = "BatchId is missing";
+ goto fatal;
+ }
+
+ /* check BatchID */
+ batch_id = atoi((char*)batchid);
+ xmlFree(batchid);
+ if (batch_id != this->batch_id)
+ {
+ error_type = TNCCS_ERROR_INVALID_BATCH_ID;
+ error_msg = buf;
+ snprintf(buf, BUF_LEN, "BatchId %d expected, got %d", this->batch_id,
+ batch_id);
+ goto fatal;
+ }
+
+ /* check presence of Recipient property */
+ recipient = xmlGetProp(cur, (const xmlChar*)"Recipient");
+ if (!recipient)
+ {
+ error_type = TNCCS_ERROR_INVALID_RECIPIENT_TYPE;
+ error_msg = "Recipient is missing";
+ goto fatal;
+ }
+
+ /* check recipient */
+ if (!streq((char*)recipient, this->is_server ? "TNCS" : "TNCC"))
+ {
+ error_type = TNCCS_ERROR_INVALID_RECIPIENT_TYPE;
+ error_msg = buf;
+ snprintf(buf, BUF_LEN, "message recipient expected '%s', got '%s'",
+ this->is_server ? "TNCS" : "TNCC", (char*)recipient);
+ xmlFree(recipient);
+ goto fatal;
+ }
+ xmlFree(recipient);
+
+ DBG2(DBG_TNC, "processing TNCCS Batch #%d", batch_id);
+
+ /* Now walk the tree, handling message nodes as we go */
+ for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next)
+ {
+ /* ignore empty or blank nodes */
+ if (xmlIsBlankNode(cur))
+ {
+ continue;
+ }
+
+ /* ignore nodes with wrong namespace */
+ if (cur->ns != ns)
+ {
+ DBG1(DBG_TNC, "ignoring message node '%s' having wrong namespace",
+ (char*)cur->name);
+ continue;
+ }
+
+ tnccs_msg = tnccs_msg_create_from_node(cur, this->errors);
+
+ /* exit if a message parsing error occurred */
+ if (this->errors->get_count(this->errors) > 0)
+ {
+ return FAILED;
+ }
+
+ /* ignore unrecognized messages */
+ if (!tnccs_msg)
+ {
+ continue;
+ }
+
+ this->messages->insert_last(this->messages, tnccs_msg);
+ }
+ return SUCCESS;
+
+fatal:
+ msg = tnccs_error_msg_create(error_type, error_msg);
+ this->errors->insert_last(this->errors, msg);
+ return FAILED;
+}
+
+METHOD(tnccs_batch_t, create_msg_enumerator, enumerator_t*,
+ private_tnccs_batch_t *this)
+{
+ return this->messages->create_enumerator(this->messages);
+}
+
+METHOD(tnccs_batch_t, create_error_enumerator, enumerator_t*,
+ private_tnccs_batch_t *this)
+{
+ return this->errors->create_enumerator(this->errors);
+}
+
+METHOD(tnccs_batch_t, destroy, void,
+ private_tnccs_batch_t *this)
+{
+ this->messages->destroy_offset(this->messages,
+ offsetof(tnccs_msg_t, destroy));
+ this->errors->destroy_offset(this->errors,
+ offsetof(tnccs_msg_t, destroy));
+ xmlFreeDoc(this->doc);
+ free(this->encoding.ptr);
+ free(this);
+}
+
+/**
+ * See header
+ */
+tnccs_batch_t* tnccs_batch_create(bool is_server, int batch_id)
+{
+ private_tnccs_batch_t *this;
+ xmlNodePtr n;
+ char buf[12];
+ const char *recipient;
+
+ INIT(this,
+ .public = {
+ .get_encoding = _get_encoding,
+ .add_msg = _add_msg,
+ .build = _build,
+ .process = _process,
+ .create_msg_enumerator = _create_msg_enumerator,
+ .create_error_enumerator = _create_error_enumerator,
+ .destroy = _destroy,
+ },
+ .is_server = is_server,
+ .messages = linked_list_create(),
+ .errors = linked_list_create(),
+ .batch_id = batch_id,
+ .doc = xmlNewDoc(BAD_CAST "1.0"),
+ );
+
+ DBG2(DBG_TNC, "creating TNCCS Batch #%d", this->batch_id);
+ n = xmlNewNode(NULL, BAD_CAST "TNCCS-Batch");
+ snprintf(buf, sizeof(buf), "%d", batch_id);
+ recipient = this->is_server ? "TNCC" : "TNCS";
+ xmlNewProp(n, BAD_CAST "BatchId", BAD_CAST buf);
+ xmlNewProp(n, BAD_CAST "Recipient", BAD_CAST recipient);
+ xmlNewProp(n, BAD_CAST "xmlns", BAD_CAST "http://www.trustedcomputinggroup.org/IWG/TNC/1_0/IF_TNCCS#");
+ xmlNewProp(n, BAD_CAST "xmlns:xsi", BAD_CAST "http://www.w3.org/2001/XMLSchema-instance");
+ xmlNewProp(n, BAD_CAST "xsi:schemaLocation", BAD_CAST "http://www.trustedcomputinggroup.org/IWG/TNC/1_0/IF_TNCCS# "
+ "https://www.trustedcomputinggroup.org/XML/SCHEMA/TNCCS_1.0.xsd");
+ xmlDocSetRootElement(this->doc, n);
+
+ return &this->public;
+}
+
+/**
+ * See header
+ */
+tnccs_batch_t* tnccs_batch_create_from_data(bool is_server, int batch_id, chunk_t data)
+{
+ private_tnccs_batch_t *this;
+
+ INIT(this,
+ .public = {
+ .get_encoding = _get_encoding,
+ .add_msg = _add_msg,
+ .build = _build,
+ .process = _process,
+ .create_msg_enumerator = _create_msg_enumerator,
+ .create_error_enumerator = _create_error_enumerator,
+ .destroy = _destroy,
+ },
+ .is_server = is_server,
+ .batch_id = batch_id,
+ .messages = linked_list_create(),
+ .errors = linked_list_create(),
+ .encoding = chunk_clone(data),
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/tnccs_11/batch/tnccs_batch.h b/src/libcharon/plugins/tnccs_11/batch/tnccs_batch.h
new file mode 100644
index 000000000..25301f763
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_11/batch/tnccs_batch.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tnccs_batch tnccs_batch
+ * @{ @ingroup tnccs_11
+ */
+
+#ifndef TNCCS_BATCH_H_
+#define TNCCS_BATCH_H_
+
+typedef enum tnccs_batch_type_t tnccs_batch_type_t;
+typedef struct tnccs_batch_t tnccs_batch_t;
+
+#include "messages/tnccs_msg.h"
+
+#include <library.h>
+
+/**
+ * Interface for a TNCCS 1.x Batch.
+ */
+struct tnccs_batch_t {
+
+ /**
+ * Get the encoding of the TNCCS 1.x Batch
+ *
+ * @return encoded TNCCS 1.x batch
+ */
+ chunk_t (*get_encoding)(tnccs_batch_t *this);
+
+ /**
+ * Add TNCCS message
+ *
+ * @param msg TNCCS message to be addedd
+ */
+ void (*add_msg)(tnccs_batch_t *this, tnccs_msg_t* msg);
+
+ /**
+ * Build the TNCCS 1.x Batch
+ */
+ void (*build)(tnccs_batch_t *this);
+
+ /**
+ * Process the TNCCS 1.x Batch
+ *
+ * @return return processing status
+ */
+ status_t (*process)(tnccs_batch_t *this);
+
+ /**
+ * Enumerates over all TNCCS Messages
+ *
+ * @return return message enumerator
+ */
+ enumerator_t* (*create_msg_enumerator)(tnccs_batch_t *this);
+
+ /**
+ * Enumerates over all parsing errors
+ *
+ * @return return error enumerator
+ */
+ enumerator_t* (*create_error_enumerator)(tnccs_batch_t *this);
+
+ /**
+ * Destroys a tnccs_batch_t object.
+ */
+ void (*destroy)(tnccs_batch_t *this);
+};
+
+/**
+ * Create an empty TNCCS 1.x Batch
+ *
+ * @param is_server TRUE if server, FALSE if client
+ * @param batch_id number of the batch to be sent
+ */
+tnccs_batch_t* tnccs_batch_create(bool is_server, int batch_id);
+
+/**
+ * Create an unprocessed TNCCS 1.x Batch from data
+ *
+ * @param is_server TRUE if server, FALSE if client
+ * @param batch_id current Batch ID
+ * @param data encoded PB-TNC batch
+ */
+tnccs_batch_t* tnccs_batch_create_from_data(bool is_server, int batch_id,
+ chunk_t data);
+
+#endif /** TNCCS_BATCH_H_ @}*/
diff --git a/src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.c b/src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.c
new file mode 100644
index 000000000..f24c0dac9
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.c
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2006 Mike McCauley (mikem@open.com.au)
+ * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "imc_imv_msg.h"
+
+#include <tnc/tnccs/tnccs.h>
+#include <debug.h>
+#include <utils/lexparser.h>
+
+typedef struct private_imc_imv_msg_t private_imc_imv_msg_t;
+
+#define BYTES_PER_LINE 57
+
+/**
+ * Private data of a imc_imv_msg_t object.
+ *
+ */
+struct private_imc_imv_msg_t {
+ /**
+ * Public imc_imv_msg_t interface.
+ */
+ imc_imv_msg_t public;
+
+ /**
+ * TNCCS message type
+ */
+ tnccs_msg_type_t type;
+
+ /**
+ * XML-encoded message node
+ */
+ xmlNodePtr node;
+
+ /**
+ * IMC-IMV message type
+ */
+ TNC_MessageType msg_type;
+
+ /**
+ * IMC-IMV message body
+ */
+ chunk_t msg_body;
+
+};
+
+/**
+ * Encodes message data into multiple base64-encoded lines
+ */
+static chunk_t encode_base64(chunk_t data)
+{
+ chunk_t encoding;
+ u_char *pos;
+ size_t b64_chars, b64_lines;
+
+ /* handle empty message data object */
+ if (data.len == 0)
+ {
+ encoding = chunk_alloc(1);
+ *encoding.ptr = '\0';
+ return encoding;
+ }
+
+ /* compute and allocate maximum size of base64 object */
+ b64_chars = 4 * ((data.len + 2) / 3);
+ b64_lines = (data.len + BYTES_PER_LINE - 1) / BYTES_PER_LINE;
+ encoding = chunk_alloc(b64_chars + b64_lines);
+ pos = encoding.ptr;
+
+ /* encode lines */
+ while (b64_lines--)
+ {
+ chunk_t data_line, b64_line;
+
+ data_line = chunk_create(data.ptr, min(data.len, BYTES_PER_LINE));
+ data.ptr += data_line.len;
+ data.len -= data_line.len;
+ b64_line = chunk_to_base64(data_line, pos);
+ pos += b64_line.len;
+ *pos = '\n';
+ pos++;
+ }
+ /* terminate last line with NULL character instead of newline */
+ *(pos-1) = '\0';
+
+ return encoding;
+}
+
+/**
+ * Decodes message data from multiple base64-encoded lines
+ */
+static chunk_t decode_base64(chunk_t data)
+{
+ chunk_t decoding, data_line, b64_line;
+ u_char *pos;
+
+ /* compute and allocate maximum size of decoded message data */
+ decoding = chunk_alloc(3 * ((data.len + 3) / 4));
+ pos = decoding.ptr;
+ decoding.len = 0;
+
+ while (fetchline(&data, &b64_line))
+ {
+ data_line = chunk_from_base64(b64_line, pos);
+ pos += data_line.len;
+ decoding.len += data_line.len;
+ }
+
+ return decoding;
+}
+
+METHOD(tnccs_msg_t, get_type, tnccs_msg_type_t,
+ private_imc_imv_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(tnccs_msg_t, get_node, xmlNodePtr,
+ private_imc_imv_msg_t *this)
+{
+ return this->node;
+}
+
+METHOD(tnccs_msg_t, destroy, void,
+ private_imc_imv_msg_t *this)
+{
+ free(this->msg_body.ptr);
+ free(this);
+}
+
+METHOD(imc_imv_msg_t, get_msg_type, TNC_MessageType,
+ private_imc_imv_msg_t *this)
+{
+ return this->msg_type;
+}
+
+METHOD(imc_imv_msg_t, get_msg_body, chunk_t,
+ private_imc_imv_msg_t *this)
+{
+ return this->msg_body;
+}
+
+/**
+ * See header
+ */
+tnccs_msg_t *imc_imv_msg_create_from_node(xmlNodePtr node, linked_list_t *errors)
+{
+ private_imc_imv_msg_t *this;
+ xmlNsPtr ns;
+ xmlNodePtr cur;
+ xmlChar *content;
+ chunk_t b64_body;
+
+ INIT(this,
+ .public = {
+ .tnccs_msg_interface = {
+ .get_type = _get_type,
+ .get_node = _get_node,
+ .destroy = _destroy,
+ },
+ .get_msg_type = _get_msg_type,
+ .get_msg_body = _get_msg_body,
+ },
+ .type = IMC_IMV_MSG,
+ .node = node,
+ );
+
+ ns = node->ns;
+ cur = node->xmlChildrenNode;
+ while (cur)
+ {
+ if (streq((char*)cur->name, "Type") && cur->ns == ns)
+ {
+ content = xmlNodeGetContent(cur);
+ this->msg_type = strtoul((char*)content, NULL, 16);
+ xmlFree(content);
+ }
+ else if (streq((char*)cur->name, "Base64") && cur->ns == ns)
+ {
+ content = xmlNodeGetContent(cur);
+ b64_body = chunk_create((char*)content, strlen((char*)content));
+ this->msg_body = decode_base64(b64_body);
+ xmlFree(content);
+ }
+ cur = cur->next;
+ }
+
+ return &this->public.tnccs_msg_interface;
+}
+
+/**
+ * See header
+ */
+tnccs_msg_t *imc_imv_msg_create(TNC_MessageType msg_type, chunk_t msg_body)
+{
+ private_imc_imv_msg_t *this;
+ chunk_t b64_body;
+ char buf[10]; /* big enough for hex-encoded message type */
+ xmlNodePtr n;
+
+ INIT(this,
+ .public = {
+ .tnccs_msg_interface = {
+ .get_type = _get_type,
+ .get_node = _get_node,
+ .destroy = _destroy,
+ },
+ .get_msg_type = _get_msg_type,
+ .get_msg_body = _get_msg_body,
+ },
+ .type = IMC_IMV_MSG,
+ .node = xmlNewNode(NULL, BAD_CAST "IMC-IMV-Message"),
+ .msg_type = msg_type,
+ .msg_body = chunk_clone(msg_body),
+ );
+
+ /* add the message type number in hex */
+ n = xmlNewNode(NULL, BAD_CAST "Type");
+ snprintf(buf, 10, "%08x", this->msg_type);
+ xmlNodeSetContent(n, BAD_CAST buf);
+ xmlAddChild(this->node, n);
+
+ /* encode the message as a Base64 node */
+ n = xmlNewNode(NULL, BAD_CAST "Base64");
+ b64_body = encode_base64(this->msg_body);
+ xmlNodeSetContent(n, BAD_CAST b64_body.ptr);
+ xmlAddChild(this->node, n);
+ free(b64_body.ptr);
+
+ return &this->public.tnccs_msg_interface;
+}
diff --git a/src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.h b/src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.h
new file mode 100644
index 000000000..02f07199f
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup imc_imv_msg imc_imv_msg
+ * @{ @ingroup tnccs_11
+ */
+
+#ifndef IMC_IMV_MSG_H_
+#define IMC_IMV_MSG_H_
+
+typedef struct imc_imv_msg_t imc_imv_msg_t;
+
+#include "tnccs_msg.h"
+
+#include <tnc/tncif.h>
+
+/**
+ * Classs representing the PB-PA message type.
+ */
+struct imc_imv_msg_t {
+
+ /**
+ * TNCCS Message interface
+ */
+ tnccs_msg_t tnccs_msg_interface;
+
+ /**
+ * Get IMC-IMV message type
+ *
+ * @return IMC-IMV message type
+ */
+ TNC_MessageType (*get_msg_type)(imc_imv_msg_t *this);
+
+ /**
+ * Get IMC-IMV message body
+ *
+ * @return IMC-IMV message body
+ */
+ chunk_t (*get_msg_body)(imc_imv_msg_t *this);
+};
+
+/**
+ * Create an IMC-IMV message from XML-encoded message node
+ *
+ * @param node XML-encoded message node
+ * @param errors linked list of TNCCS error messages
+*/
+tnccs_msg_t *imc_imv_msg_create_from_node(xmlNodePtr node, linked_list_t *errors);
+
+/**
+ * Create an IMC-IMV message from parameters
+ *
+ * @param msg_type IMC-IMV message type
+ * @param msg_body IMC-IMV message body
+ */
+tnccs_msg_t *imc_imv_msg_create(TNC_MessageType msg_type, chunk_t msg_body);
+
+#endif /** IMC_IMV_MSG_H_ @}*/
diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_error_msg.c b/src/libcharon/plugins/tnccs_11/messages/tnccs_error_msg.c
new file mode 100644
index 000000000..d0df4e7ca
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_error_msg.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2006 Mike McCauley (mikem@open.com.au)
+ * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnccs_error_msg.h"
+
+#include <debug.h>
+
+ENUM(tnccs_error_type_names, TNCCS_ERROR_BATCH_TOO_LONG, TNCCS_ERROR_OTHER,
+ "batch-too-long",
+ "malformed-batch",
+ "invalid-batch-id",
+ "invalid-recipient-type",
+ "internal-error",
+ "other"
+);
+
+typedef struct private_tnccs_error_msg_t private_tnccs_error_msg_t;
+
+/**
+ * Private data of a tnccs_error_msg_t object.
+ *
+ */
+struct private_tnccs_error_msg_t {
+ /**
+ * Public tnccs_error_msg_t interface.
+ */
+ tnccs_error_msg_t public;
+
+ /**
+ * TNCCS message type
+ */
+ tnccs_msg_type_t type;
+
+ /**
+ * XML-encoded message node
+ */
+ xmlNodePtr node;
+
+ /**
+ * Error type
+ */
+ tnccs_error_type_t error_type;
+
+ /**
+ * Error message
+ */
+ char *error_msg;
+
+ /**
+ * reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(tnccs_msg_t, get_type, tnccs_msg_type_t,
+ private_tnccs_error_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(tnccs_msg_t, get_node, xmlNodePtr,
+ private_tnccs_error_msg_t *this)
+{
+ return this->node;
+}
+
+METHOD(tnccs_msg_t, get_ref, tnccs_msg_t*,
+ private_tnccs_error_msg_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.tnccs_msg_interface;
+}
+
+METHOD(tnccs_msg_t, destroy, void,
+ private_tnccs_error_msg_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->error_msg);
+ free(this);
+ }
+}
+
+METHOD(tnccs_error_msg_t, get_message, char*,
+ private_tnccs_error_msg_t *this, tnccs_error_type_t *type)
+{
+ *type = this->error_type;
+
+ return this->error_msg;
+}
+
+/**
+ * See header
+ */
+tnccs_msg_t *tnccs_error_msg_create_from_node(xmlNodePtr node)
+{
+ private_tnccs_error_msg_t *this;
+ xmlChar *error_type_name, *error_msg;
+
+ INIT(this,
+ .public = {
+ .tnccs_msg_interface = {
+ .get_type = _get_type,
+ .get_node = _get_node,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_message = _get_message,
+ },
+ .type = TNCCS_MSG_ERROR,
+ .ref = 1,
+ .node = node,
+ .error_type = TNCCS_ERROR_OTHER,
+ );
+
+ error_type_name = xmlGetProp(node, (const xmlChar*)"type");
+ if (error_type_name)
+ {
+ this->error_type = enum_from_name(tnccs_error_type_names,
+ (char*)error_type_name);
+ if (this->error_type == -1)
+ {
+ this->error_type = TNCCS_ERROR_OTHER;
+ }
+ xmlFree(error_type_name);
+ }
+
+ error_msg = xmlNodeGetContent(node);
+ if (error_msg)
+ {
+ this->error_msg = strdup((char*)error_msg);
+ xmlFree(error_msg);
+ }
+
+ return &this->public.tnccs_msg_interface;
+}
+
+/**
+ * See header
+ */
+tnccs_msg_t *tnccs_error_msg_create(tnccs_error_type_t type, char *msg)
+{
+ private_tnccs_error_msg_t *this;
+ xmlNodePtr n, n2;
+
+ INIT(this,
+ .public = {
+ .tnccs_msg_interface = {
+ .get_type = _get_type,
+ .get_node = _get_node,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_message = _get_message,
+ },
+ .type = TNCCS_MSG_ERROR,
+ .ref = 1,
+ .node = xmlNewNode(NULL, BAD_CAST "TNCC-TNCS-Message"),
+ .error_type = type,
+ .error_msg = strdup(msg),
+ );
+
+ DBG1(DBG_TNC, "%s", msg);
+
+ n = xmlNewNode(NULL, BAD_CAST "Type");
+ xmlNodeSetContent(n, BAD_CAST "00000002");
+ xmlAddChild(this->node, n);
+
+ n = xmlNewNode(NULL, BAD_CAST "XML");
+ xmlAddChild(this->node, n);
+
+ n2 = xmlNewNode(NULL, BAD_CAST enum_to_name(tnccs_msg_type_names, this->type));
+ xmlNewProp(n2, BAD_CAST "type",
+ BAD_CAST enum_to_name(tnccs_error_type_names, type));
+ xmlNodeSetContent(n2, BAD_CAST msg);
+ xmlAddChild(n, n2);
+
+ return &this->public.tnccs_msg_interface;
+}
diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_error_msg.h b/src/libcharon/plugins/tnccs_11/messages/tnccs_error_msg.h
new file mode 100644
index 000000000..ce2ce9755
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_error_msg.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tnccs_error_msg tnccs_error_msg
+ * @{ @ingroup tnccs_11
+ */
+
+#ifndef TNCCS_ERROR_MSG_H_
+#define TNCCS_ERROR_MSG_H_
+
+typedef enum tnccs_error_type_t tnccs_error_type_t;
+typedef struct tnccs_error_msg_t tnccs_error_msg_t;
+
+#include "tnccs_msg.h"
+
+/**
+ * TNCCS error types as defined in section 8.1.4 of TCG TNC IF-TNCCS v1.2
+ */
+enum tnccs_error_type_t {
+ TNCCS_ERROR_BATCH_TOO_LONG,
+ TNCCS_ERROR_MALFORMED_BATCH,
+ TNCCS_ERROR_INVALID_BATCH_ID,
+ TNCCS_ERROR_INVALID_RECIPIENT_TYPE,
+ TNCCS_ERROR_INTERNAL_ERROR,
+ TNCCS_ERROR_OTHER
+};
+
+/**
+ * enum name for tnccs_error_type_t.
+ */
+extern enum_name_t *tnccs_error_type_names;
+
+/**
+ * Class representing the TNCCS-Error message type
+ */
+struct tnccs_error_msg_t {
+
+ /**
+ * TNCCS Message interface
+ */
+ tnccs_msg_t tnccs_msg_interface;
+
+ /**
+ * Get error message and type
+ *
+ * @param type TNCCS error type
+ * @return arbitrary error message
+ */
+ char* (*get_message)(tnccs_error_msg_t *this, tnccs_error_type_t *type);
+};
+
+/**
+ * Create a TNCCS-Error message from XML-encoded message node
+ *
+ * @param node XML-encoded message node
+ */
+tnccs_msg_t *tnccs_error_msg_create_from_node(xmlNodePtr node);
+
+/**
+ * Create a TNCCS-Error message from parameters
+ *
+ * @param type TNCCS error type
+ * @param msg arbitrary error message
+ */
+tnccs_msg_t *tnccs_error_msg_create(tnccs_error_type_t type, char *msg);
+
+#endif /** TNCCS_ERROR_MSG_H_ @}*/
diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_msg.c b/src/libcharon/plugins/tnccs_11/messages/tnccs_msg.c
new file mode 100644
index 000000000..5a050393a
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_msg.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2006 Mike McCauley (mikem@open.com.au)
+ * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnccs_msg.h"
+#include "imc_imv_msg.h"
+#include "tnccs_error_msg.h"
+#include "tnccs_preferred_language_msg.h"
+#include "tnccs_reason_strings_msg.h"
+#include "tnccs_recommendation_msg.h"
+#include "tnccs_tncs_contact_info_msg.h"
+
+#include <library.h>
+#include <debug.h>
+
+ENUM(tnccs_msg_type_names, IMC_IMV_MSG, TNCCS_MSG_ROOF,
+ "IMC-IMV",
+ "TNCCS-Recommendation",
+ "TNCCS-Error",
+ "TNCCS-PreferredLanguage",
+ "TNCCS-ReasonStrings",
+ "TNCCS-TNCSContactInfo"
+);
+
+/**
+ * See header
+ */
+tnccs_msg_t* tnccs_msg_create_from_node(xmlNodePtr node, linked_list_t *errors)
+{
+ char *error_msg, buf[BUF_LEN];
+ tnccs_error_type_t error_type = TNCCS_ERROR_MALFORMED_BATCH;
+ tnccs_msg_t *msg;
+ tnccs_msg_type_t type = IMC_IMV_MSG;
+
+ if (streq((char*)node->name, "IMC-IMV-Message"))
+ {
+ DBG2(DBG_TNC, "processing %N message", tnccs_msg_type_names, type);
+ return imc_imv_msg_create_from_node(node, errors);
+ }
+ else if (streq((char*)node->name, "TNCC-TNCS-Message"))
+ {
+ bool found = FALSE;
+ xmlNsPtr ns = node->ns;
+ xmlNodePtr cur = node->xmlChildrenNode;
+ xmlNodePtr xml_msg_node = NULL;
+
+ while (cur)
+ {
+ if (streq((char*)cur->name, "Type") && cur->ns == ns)
+ {
+ xmlChar *content = xmlNodeGetContent(cur);
+
+ type = strtol((char*)content, NULL, 16);
+ xmlFree(content);
+ found = TRUE;
+ }
+ else if (streq((char*)cur->name, "XML") && cur->ns == ns)
+ {
+ xml_msg_node = cur->xmlChildrenNode;
+ }
+ cur = cur->next;
+ }
+ if (!found)
+ {
+ error_msg = "Type is missing in TNCC-TNCS-Message";
+ goto fatal;
+ }
+ if (!xml_msg_node)
+ {
+ error_msg = "XML node is missing in TNCC-TNCS-Message";
+ goto fatal;
+ }
+ cur = xml_msg_node;
+
+ /* skip empty and blank nodes */
+ while (cur && xmlIsBlankNode(cur))
+ {
+ cur = cur->next;
+ }
+ if (!cur)
+ {
+ error_msg = "XML node is empty";
+ goto fatal;
+ }
+
+ /* check if TNCCS message type and node name agree */
+ if (type >= TNCCS_MSG_RECOMMENDATION && type <= TNCCS_MSG_ROOF)
+ {
+ DBG2(DBG_TNC, "processing %N message", tnccs_msg_type_names, type);
+ if (cur->ns != ns)
+ {
+ error_msg = "node is not in the TNCCS message namespace";
+ goto fatal;
+ }
+ if (type != enum_from_name(tnccs_msg_type_names, (char*)cur->name))
+ {
+ error_msg = buf;
+ snprintf(buf, BUF_LEN, "expected '%N' node but was '%s'",
+ tnccs_msg_type_names, type, (char*)cur->name);
+ goto fatal;
+ }
+ }
+
+ switch (type)
+ {
+ case TNCCS_MSG_RECOMMENDATION:
+ return tnccs_recommendation_msg_create_from_node(cur, errors);
+ case TNCCS_MSG_ERROR:
+ return tnccs_error_msg_create_from_node(cur);
+ case TNCCS_MSG_PREFERRED_LANGUAGE:
+ return tnccs_preferred_language_msg_create_from_node(cur, errors);
+ case TNCCS_MSG_REASON_STRINGS:
+ return tnccs_reason_strings_msg_create_from_node(cur, errors);
+ case TNCCS_MSG_TNCS_CONTACT_INFO:
+ return tnccs_tncs_contact_info_msg_create_from_node(cur, errors);
+ default:
+ DBG1(DBG_TNC, "ignoring TNCC-TNCS-Message with type %d", type);
+ return NULL;
+ }
+ }
+ DBG1(DBG_TNC, "ignoring unknown message node '%s'", (char*)node->name);
+ return NULL;
+
+fatal:
+ msg = tnccs_error_msg_create(error_type, error_msg);
+ errors->insert_last(errors, msg);
+ return NULL;
+}
+
diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_msg.h b/src/libcharon/plugins/tnccs_11/messages/tnccs_msg.h
new file mode 100644
index 000000000..e0b54449a
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_msg.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tnccs_msg tnccs_msg
+ * @{ @ingroup tnccs_11
+ */
+
+#ifndef TNCCS_MSG_H_
+#define TNCCS_MSG_H_
+
+typedef enum tnccs_msg_type_t tnccs_msg_type_t;
+typedef struct tnccs_msg_t tnccs_msg_t;
+
+#include <library.h>
+#include <utils/linked_list.h>
+#include <libxml/parser.h>
+
+/**
+ * TNCC-TNCS messages as defined in section 2.8.5 of TCG TNC IF-TNCCS v1.2
+ */
+enum tnccs_msg_type_t {
+ IMC_IMV_MSG = 0,
+ TNCCS_MSG_RECOMMENDATION = 1,
+ TNCCS_MSG_ERROR = 2,
+ TNCCS_MSG_PREFERRED_LANGUAGE = 3,
+ TNCCS_MSG_REASON_STRINGS = 4,
+ TNCCS_MSG_TNCS_CONTACT_INFO = 5,
+ TNCCS_MSG_ROOF = 5
+};
+
+/**
+ * enum name for tnccs_msg_type_t.
+ */
+extern enum_name_t *tnccs_msg_type_names;
+
+/**
+ * Generic interface for all TNCCS message types.
+ *
+ * To handle all messages in a generic way, this interface
+ * must be implemented by each message type.
+ */
+struct tnccs_msg_t {
+
+ /**
+ * Get the TNCCS Message Type
+ *
+ * @return TNCCS Message Type
+ */
+ tnccs_msg_type_t (*get_type)(tnccs_msg_t *this);
+
+ /**
+ * Get the XML-encoded Message Node
+ *
+ * @return Message Node
+ */
+ xmlNodePtr (*get_node)(tnccs_msg_t *this);
+
+ /**
+ * Process the TNCCS Message
+ *
+ * @return return processing status
+ */
+ status_t (*process)(tnccs_msg_t *this);
+
+ /**
+ * Get a new reference to the message.
+ *
+ * @return this, with an increased refcount
+ */
+ tnccs_msg_t* (*get_ref)(tnccs_msg_t *this);
+
+ /**
+ * Destroys a tnccs_msg_t object.
+ */
+ void (*destroy)(tnccs_msg_t *this);
+};
+
+/**
+ * Create a pre-processed TNCCS message
+ *
+ * Useful for the parser which wants a generic constructor for all
+ * tnccs_msg_t types.
+ *
+ * @param node TNCCS message node
+ * @param errors linked list of TNCCS error messages
+ */
+tnccs_msg_t* tnccs_msg_create_from_node(xmlNodePtr node, linked_list_t *errors);
+
+#endif /** TNCCS_MSG_H_ @}*/
diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_preferred_language_msg.c b/src/libcharon/plugins/tnccs_11/messages/tnccs_preferred_language_msg.c
new file mode 100644
index 000000000..fd85350b5
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_preferred_language_msg.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2006 Mike McCauley (mikem@open.com.au)
+ * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnccs_preferred_language_msg.h"
+
+#include <debug.h>
+
+typedef struct private_tnccs_preferred_language_msg_t private_tnccs_preferred_language_msg_t;
+
+/**
+ * Private data of a tnccs_preferred_language_msg_t object.
+ *
+ */
+struct private_tnccs_preferred_language_msg_t {
+ /**
+ * Public tnccs_preferred_language_msg_t interface.
+ */
+ tnccs_preferred_language_msg_t public;
+
+ /**
+ * TNCCS message type
+ */
+ tnccs_msg_type_t type;
+
+ /**
+ * XML-encoded message node
+ */
+ xmlNodePtr node;
+
+ /**
+ * Preferred language
+ */
+ char *preferred_language;
+};
+
+METHOD(tnccs_msg_t, get_type, tnccs_msg_type_t,
+ private_tnccs_preferred_language_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(tnccs_msg_t, get_node, xmlNodePtr,
+ private_tnccs_preferred_language_msg_t *this)
+{
+ return this->node;
+}
+
+METHOD(tnccs_msg_t, destroy, void,
+ private_tnccs_preferred_language_msg_t *this)
+{
+ free(this->preferred_language);
+ free(this);
+}
+
+METHOD(tnccs_preferred_language_msg_t, get_preferred_language, char*,
+ private_tnccs_preferred_language_msg_t *this)
+{
+ return this->preferred_language;
+}
+
+/**
+ * See header
+ */
+tnccs_msg_t *tnccs_preferred_language_msg_create_from_node(xmlNodePtr node,
+ linked_list_t *errors)
+{
+ private_tnccs_preferred_language_msg_t *this;
+ xmlChar *language;
+
+ INIT(this,
+ .public = {
+ .tnccs_msg_interface = {
+ .get_type = _get_type,
+ .get_node = _get_node,
+ .destroy = _destroy,
+ },
+ .get_preferred_language = _get_preferred_language,
+ },
+ .type = TNCCS_MSG_PREFERRED_LANGUAGE,
+ .node = node,
+ );
+
+ language = xmlNodeGetContent(node);
+ this->preferred_language = strdup((char*)language);
+ xmlFree(language);
+
+ return &this->public.tnccs_msg_interface;
+}
+
+/**
+ * See header
+ */
+tnccs_msg_t *tnccs_preferred_language_msg_create(char *language)
+{
+ private_tnccs_preferred_language_msg_t *this;
+ xmlNodePtr n, n2;
+
+ INIT(this,
+ .public = {
+ .tnccs_msg_interface = {
+ .get_type = _get_type,
+ .get_node = _get_node,
+ .destroy = _destroy,
+ },
+ .get_preferred_language = _get_preferred_language,
+ },
+ .type = TNCCS_MSG_PREFERRED_LANGUAGE,
+ .node = xmlNewNode(NULL, BAD_CAST "TNCC-TNCS-Message"),
+ .preferred_language = strdup(language),
+ );
+
+ /* add the message type number in hex */
+ n = xmlNewNode(NULL, BAD_CAST "Type");
+ xmlNodeSetContent(n, BAD_CAST "00000003");
+ xmlAddChild(this->node, n);
+
+ n = xmlNewNode(NULL, BAD_CAST "XML");
+ xmlAddChild(this->node, n);
+
+ n2 = xmlNewNode(NULL, BAD_CAST enum_to_name(tnccs_msg_type_names, this->type));
+ xmlNodeSetContent(n2, BAD_CAST language);
+ xmlAddChild(n, n2);
+
+ return &this->public.tnccs_msg_interface;
+}
diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_preferred_language_msg.h b/src/libcharon/plugins/tnccs_11/messages/tnccs_preferred_language_msg.h
new file mode 100644
index 000000000..d301ab2bb
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_preferred_language_msg.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tnccs_preferred_language_msg tnccs_preferred_language_msg
+ * @{ @ingroup tnccs_11
+ */
+
+#ifndef TNCCS_PREFERRED_LANGUAGE_MSG_H_
+#define TNCCS_PREFERRED_LANGUAGE_MSG_H_
+
+typedef struct tnccs_preferred_language_msg_t tnccs_preferred_language_msg_t;
+
+#include "tnccs_msg.h"
+
+#include <tnc/tncif.h>
+
+/**
+ * Class representing the TNCCS-PreferredLanguage message type
+ */
+struct tnccs_preferred_language_msg_t {
+
+ /**
+ * TNCCS Message interface
+ */
+ tnccs_msg_t tnccs_msg_interface;
+
+ /**
+ * Get preferred language string
+ *
+ * @return preferred language string
+ */
+ char* (*get_preferred_language)(tnccs_preferred_language_msg_t *this);
+};
+
+/**
+ * Create a TNCCS-PreferredLanguage message from XML-encoded message node
+ *
+ * @param node XML-encoded message node
+ * @param errors linked list of TNCCS error messages
+ */
+tnccs_msg_t *tnccs_preferred_language_msg_create_from_node(xmlNodePtr node,
+ linked_list_t *errors);
+
+/**
+ * Create a TNCCS-PreferredLanguage message from parameters
+ *
+ * @param language preferred language string
+ */
+tnccs_msg_t *tnccs_preferred_language_msg_create(char *language);
+
+#endif /** TNCCS_PREFERRED_LANGUAGE_MSG_H_ @}*/
diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_reason_strings_msg.c b/src/libcharon/plugins/tnccs_11/messages/tnccs_reason_strings_msg.c
new file mode 100644
index 000000000..d4b5d9bf9
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_reason_strings_msg.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2006 Mike McCauley (mikem@open.com.au)
+ * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnccs_reason_strings_msg.h"
+
+#include <debug.h>
+
+typedef struct private_tnccs_reason_strings_msg_t private_tnccs_reason_strings_msg_t;
+
+/**
+ * Private data of a tnccs_reason_strings_msg_t object.
+ *
+ */
+struct private_tnccs_reason_strings_msg_t {
+ /**
+ * Public tnccs_reason_strings_msg_t interface.
+ */
+ tnccs_reason_strings_msg_t public;
+
+ /**
+ * TNCCS message type
+ */
+ tnccs_msg_type_t type;
+
+ /**
+ * XML-encoded message node
+ */
+ xmlNodePtr node;
+
+ /**
+ * Reason String
+ */
+ chunk_t reason;
+
+ /**
+ * Reason Language
+ */
+ chunk_t language;
+};
+
+METHOD(tnccs_msg_t, get_type, tnccs_msg_type_t,
+ private_tnccs_reason_strings_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(tnccs_msg_t, get_node, xmlNodePtr,
+ private_tnccs_reason_strings_msg_t *this)
+{
+ return this->node;
+}
+
+METHOD(tnccs_msg_t, destroy, void,
+ private_tnccs_reason_strings_msg_t *this)
+{
+ free(this->reason.ptr);
+ free(this->language.ptr);
+ free(this);
+}
+
+METHOD(tnccs_reason_strings_msg_t, get_reason, chunk_t,
+ private_tnccs_reason_strings_msg_t *this, chunk_t *language)
+{
+ *language = this->language;
+
+ return this->reason;
+}
+
+/**
+ * See header
+ */
+tnccs_msg_t *tnccs_reason_strings_msg_create_from_node(xmlNodePtr node,
+ linked_list_t *errors)
+{
+ private_tnccs_reason_strings_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .tnccs_msg_interface = {
+ .get_type = _get_type,
+ .get_node = _get_node,
+ .destroy = _destroy,
+ },
+ .get_reason = _get_reason,
+ },
+ .type = TNCCS_MSG_REASON_STRINGS,
+ .node = node,
+ );
+
+ return &this->public.tnccs_msg_interface;
+}
+
+/**
+ * See header
+ */
+tnccs_msg_t *tnccs_reason_strings_msg_create(chunk_t reason, chunk_t language)
+{
+ private_tnccs_reason_strings_msg_t *this;
+ xmlNodePtr n, n2, n3;
+
+ INIT(this,
+ .public = {
+ .tnccs_msg_interface = {
+ .get_type = _get_type,
+ .get_node = _get_node,
+ .destroy = _destroy,
+ },
+ .get_reason = _get_reason,
+ },
+ .type = TNCCS_MSG_REASON_STRINGS,
+ .node = xmlNewNode(NULL, BAD_CAST "TNCC-TNCS-Message"),
+ .reason = chunk_create_clone(malloc(reason.len + 1), reason),
+ .language = chunk_create_clone(malloc(language.len + 1), language),
+ );
+
+ /* add NULL termination for XML string representation */
+ this->reason.ptr[this->reason.len] = '\0';
+ this->language.ptr[this->language.len] = '\0';
+
+ /* add the message type number in hex */
+ n = xmlNewNode(NULL, BAD_CAST "Type");
+ xmlNodeSetContent(n, BAD_CAST "00000004");
+ xmlAddChild(this->node, n);
+
+ n = xmlNewNode(NULL, BAD_CAST "XML");
+ xmlAddChild(this->node, n);
+
+ n2 = xmlNewNode(NULL, BAD_CAST enum_to_name(tnccs_msg_type_names, this->type));
+
+ /* could add multiple reasons here, if we had them */
+ n3 = xmlNewNode(NULL, BAD_CAST "ReasonString");
+ xmlNewProp(n3, BAD_CAST "xml:lang", BAD_CAST this->language.ptr);
+ xmlNodeSetContent(n3, BAD_CAST this->reason.ptr);
+ xmlAddChild(n2, n3);
+
+ return &this->public.tnccs_msg_interface;
+}
diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_reason_strings_msg.h b/src/libcharon/plugins/tnccs_11/messages/tnccs_reason_strings_msg.h
new file mode 100644
index 000000000..0046a5789
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_reason_strings_msg.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tnccs_reason_strings_msg tnccs_reason_strings_msg
+ * @{ @ingroup tnccs_11
+ */
+
+#ifndef TNCCS_REASON_STRINGS_MSG_H_
+#define TNCCS_REASON_STRINGS_MSG_H_
+
+typedef struct tnccs_reason_strings_msg_t tnccs_reason_strings_msg_t;
+
+#include "tnccs_msg.h"
+
+/**
+ * Class representing the TNCCS-ReasonStrings message type
+ */
+struct tnccs_reason_strings_msg_t {
+
+ /**
+ * TNCCS Message interface
+ */
+ tnccs_msg_t tnccs_msg_interface;
+
+ /**
+ * Get reason string and language
+ *
+ * @param language reason language
+ * @return reason string
+ */
+ chunk_t (*get_reason)(tnccs_reason_strings_msg_t *this, chunk_t *language);
+};
+
+/**
+ * Create a TNCCS-ReasonStrings message from XML-encoded message node
+ *
+ * @param node XML-encoded message node
+ * @param errors linked list of TNCCS error messages
+ */
+tnccs_msg_t *tnccs_reason_strings_msg_create_from_node(xmlNodePtr node,
+ linked_list_t *errors);
+
+/**
+ * Create a TNCCS-ReasonStrings message from parameters
+ *
+ * @param reason reason string
+ * @param language reason language
+ */
+tnccs_msg_t *tnccs_reason_strings_msg_create(chunk_t reason, chunk_t language);
+
+#endif /** TNCCS_REASON_STRINGS_MSG_H_ @}*/
diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.c b/src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.c
new file mode 100644
index 000000000..adc7b54b9
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2006 Mike McCauley (mikem@open.com.au)
+ * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnccs_recommendation_msg.h"
+#include "tnccs_error_msg.h"
+
+#include <debug.h>
+
+typedef struct private_tnccs_recommendation_msg_t private_tnccs_recommendation_msg_t;
+
+/**
+ * Private data of a tnccs_recommendation_msg_t object.
+ *
+ */
+struct private_tnccs_recommendation_msg_t {
+ /**
+ * Public tnccs_recommendation_msg_t interface.
+ */
+ tnccs_recommendation_msg_t public;
+
+ /**
+ * TNCCS message type
+ */
+ tnccs_msg_type_t type;
+
+ /**
+ * XML-encoded message node
+ */
+ xmlNodePtr node;
+
+ /**
+ * Action Recommendation
+ */
+ TNC_IMV_Action_Recommendation rec;
+};
+
+METHOD(tnccs_msg_t, get_type, tnccs_msg_type_t,
+ private_tnccs_recommendation_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(tnccs_msg_t, get_node, xmlNodePtr,
+ private_tnccs_recommendation_msg_t *this)
+{
+ return this->node;
+}
+
+METHOD(tnccs_msg_t, destroy, void,
+ private_tnccs_recommendation_msg_t *this)
+{
+ free(this);
+}
+
+METHOD(tnccs_recommendation_msg_t, get_recommendation, TNC_IMV_Action_Recommendation,
+ private_tnccs_recommendation_msg_t *this)
+{
+ return this->rec;
+}
+
+/**
+ * See header
+ */
+tnccs_msg_t *tnccs_recommendation_msg_create_from_node(xmlNodePtr node,
+ linked_list_t *errors)
+{
+ private_tnccs_recommendation_msg_t *this;
+ xmlChar *rec_string;
+ char *error_msg, buf[BUF_LEN];
+ tnccs_error_type_t error_type = TNCCS_ERROR_MALFORMED_BATCH;
+ tnccs_msg_t *msg;
+
+ INIT(this,
+ .public = {
+ .tnccs_msg_interface = {
+ .get_type = _get_type,
+ .get_node = _get_node,
+ .destroy = _destroy,
+ },
+ .get_recommendation = _get_recommendation,
+ },
+ .type = TNCCS_MSG_RECOMMENDATION,
+ .node = node,
+ );
+
+ rec_string = xmlGetProp(node, (const xmlChar*)"type");
+ if (!rec_string)
+ {
+ error_msg = "type property in TNCCS-Recommendation is missing";
+ goto fatal;
+ }
+ else if (streq((char*)rec_string, "allow"))
+ {
+ this->rec = TNC_IMV_ACTION_RECOMMENDATION_ALLOW;
+ }
+ else if (streq((char*)rec_string, "isolate"))
+ {
+ this->rec = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE;
+ }
+ else if (streq((char*)rec_string, "none"))
+ {
+ this->rec = TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS;
+ }
+ else
+ {
+ error_msg = buf;
+ snprintf(buf, BUF_LEN, "unsupported type property value '%s' "
+ "in TNCCS-Recommendation", rec_string);
+ xmlFree(rec_string);
+ goto fatal;
+ }
+ xmlFree(rec_string);
+
+ return &this->public.tnccs_msg_interface;
+
+fatal:
+ msg = tnccs_error_msg_create(error_type, error_msg);
+ errors->insert_last(errors, msg);
+ _destroy(this);
+ return NULL;
+}
+
+/**
+ * See header
+ */
+tnccs_msg_t *tnccs_recommendation_msg_create(TNC_IMV_Action_Recommendation rec)
+{
+ private_tnccs_recommendation_msg_t *this;
+ xmlNodePtr n, n2;
+ char *rec_string;
+
+ INIT(this,
+ .public = {
+ .tnccs_msg_interface = {
+ .get_type = _get_type,
+ .get_node = _get_node,
+ .destroy = _destroy,
+ },
+ .get_recommendation = _get_recommendation,
+ },
+ .type = TNCCS_MSG_RECOMMENDATION,
+ .node = xmlNewNode(NULL, BAD_CAST "TNCC-TNCS-Message"),
+ .rec = rec,
+ );
+
+ /* add the message type number in hex */
+ n = xmlNewNode(NULL, BAD_CAST "Type");
+ xmlNodeSetContent(n, BAD_CAST "00000001");
+ xmlAddChild(this->node, n);
+
+ n = xmlNewNode(NULL, BAD_CAST "XML");
+ xmlAddChild(this->node, n);
+
+ switch (rec)
+ {
+ case TNC_IMV_ACTION_RECOMMENDATION_ALLOW:
+ rec_string = "allow";
+ break;
+ case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE:
+ rec_string = "isolate";
+ break;
+ case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS:
+ case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION:
+ default:
+ rec_string = "none";
+ }
+
+ n2 = xmlNewNode(NULL, BAD_CAST enum_to_name(tnccs_msg_type_names, this->type));
+ xmlNewProp(n2, BAD_CAST "type", BAD_CAST rec_string);
+ xmlNodeSetContent(n2, "");
+ xmlAddChild(n, n2);
+
+ return &this->public.tnccs_msg_interface;
+}
diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.h b/src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.h
new file mode 100644
index 000000000..685049e95
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tnccs_recommendation_msg tnccs_recommendation_msg
+ * @{ @ingroup tnccs_11
+ */
+
+#ifndef TNCCS_RECOMMENDATION_MSG_H_
+#define TNCCS_RECOMMENDATION_MSG_H_
+
+typedef struct tnccs_recommendation_msg_t tnccs_recommendation_msg_t;
+
+#include "tnccs_msg.h"
+
+#include <tnc/tncifimv.h>
+
+/**
+ * Class representing the TNCCS-Recommendation message type
+ */
+struct tnccs_recommendation_msg_t {
+
+ /**
+ * TNCCS Message interface
+ */
+ tnccs_msg_t tnccs_msg_interface;
+
+ /**
+ * Get Action Recommendation
+ *
+ * @return Action Recommendation
+ */
+ TNC_IMV_Action_Recommendation (*get_recommendation)(tnccs_recommendation_msg_t *this);
+};
+
+/**
+ * Create a TNCCS-Recommendation message from XML-encoded message node
+ *
+ * @param node XML-encoded message node
+ * @param errors linked list of TNCCS error messages
+ */
+tnccs_msg_t *tnccs_recommendation_msg_create_from_node(xmlNodePtr node,
+ linked_list_t *errors);
+
+/**
+ * Create a TNCCS-Recommendation message from parameters
+ *
+ * @param rec Action Recommendation
+ */
+tnccs_msg_t *tnccs_recommendation_msg_create(TNC_IMV_Action_Recommendation rec);
+
+#endif /** TNCCS_RECOMMENDATION_MSG_H_ @}*/
diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.c b/src/libcharon/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.c
new file mode 100644
index 000000000..b8aac30fa
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnccs_tncs_contact_info_msg.h"
+
+#include <debug.h>
+
+typedef struct private_tnccs_tncs_contact_info_msg_t private_tnccs_tncs_contact_info_msg_t;
+
+/**
+ * Private data of a tnccs_tncs_contact_info_msg_t object.
+ *
+ */
+struct private_tnccs_tncs_contact_info_msg_t {
+ /**
+ * Public tnccs_tncs_contact_info_msg_t interface.
+ */
+ tnccs_tncs_contact_info_msg_t public;
+
+ /**
+ * TNCCS message type
+ */
+ tnccs_msg_type_t type;
+
+ /**
+ * XML-encoded message node
+ */
+ xmlNodePtr node;
+};
+
+METHOD(tnccs_msg_t, get_type, tnccs_msg_type_t,
+ private_tnccs_tncs_contact_info_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(tnccs_msg_t, get_node, xmlNodePtr,
+ private_tnccs_tncs_contact_info_msg_t *this)
+{
+ return this->node;
+}
+
+METHOD(tnccs_msg_t, destroy, void,
+ private_tnccs_tncs_contact_info_msg_t *this)
+{
+ free(this);
+}
+
+/**
+ * See header
+ */
+tnccs_msg_t *tnccs_tncs_contact_info_msg_create_from_node(xmlNodePtr node,
+ linked_list_t *errors)
+{
+ private_tnccs_tncs_contact_info_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .tnccs_msg_interface = {
+ .get_type = _get_type,
+ .get_node = _get_node,
+ .destroy = _destroy,
+ },
+ },
+ .type = TNCCS_MSG_TNCS_CONTACT_INFO,
+ .node = node,
+ );
+
+ return &this->public.tnccs_msg_interface;
+}
+
+/**
+ * See header
+ */
+tnccs_msg_t *tnccs_tncs_contact_info_msg_create(void)
+{
+ private_tnccs_tncs_contact_info_msg_t *this;
+ xmlNodePtr n /*, n2 */;
+
+ INIT(this,
+ .public = {
+ .tnccs_msg_interface = {
+ .get_type = _get_type,
+ .get_node = _get_node,
+ .destroy = _destroy,
+ },
+ },
+ .type = TNCCS_MSG_TNCS_CONTACT_INFO,
+ .node = xmlNewNode(NULL, BAD_CAST "TNCC-TNCS-Message"),
+ );
+
+ /* add the message type number in hex */
+ n = xmlNewNode(NULL, BAD_CAST "Type");
+ xmlNodeSetContent(n, BAD_CAST "00000005");
+ xmlAddChild(this->node, n);
+
+ n = xmlNewNode(NULL, BAD_CAST "XML");
+ xmlAddChild(this->node, n);
+
+/* TODO
+ n2 = xmlNewNode(NULL, BAD_CAST enum_to_name(tnccs_msg_type_names, this->type));
+ xmlNodeSetContent(n2, BAD_CAST language);
+ xmlAddChild(n, n2);
+*/
+
+ return &this->public.tnccs_msg_interface;
+}
diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.h b/src/libcharon/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.h
new file mode 100644
index 000000000..8ed210a57
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tnccs_tncs_contact_info_msg tnccs_tncs_contact_info_msg
+ * @{ @ingroup tnccs_11
+ */
+
+#ifndef TNCCS_TNCS_CONTACT_INFO_MSG_H_
+#define TNCCS_TNCS_CONTACT_INFO_MSG_H_
+
+typedef struct tnccs_tncs_contact_info_msg_t tnccs_tncs_contact_info_msg_t;
+
+#include "tnccs_msg.h"
+
+/**
+ * Class representing the TNCCS-TNCSContactInfo message type
+ */
+struct tnccs_tncs_contact_info_msg_t {
+
+ /**
+ * TNCCS Message interface
+ */
+ tnccs_msg_t tnccs_msg_interface;
+};
+
+/**
+ * Create a TNCCS-TNCSContactInfo message from XML-encoded message node
+ *
+ * @param node XML-encoded message node
+ * @param errors linked list of TNCCS error messages
+ */
+tnccs_msg_t *tnccs_tncs_contact_info_msg_create_from_node(xmlNodePtr node,
+ linked_list_t *errors);
+
+/**
+ * Create a TNCCS-TNCSContactInfo message from parameters
+ *
+ */
+tnccs_msg_t *tnccs_tncs_contact_info_msg_create(void);
+
+#endif /** TNCCS_TNCS_CONTACT_INFO_MSG_H_ @}*/
diff --git a/src/libcharon/plugins/tnccs_11/tnccs_11.c b/src/libcharon/plugins/tnccs_11/tnccs_11.c
index 704bf64ed..2104bf401 100644
--- a/src/libcharon/plugins/tnccs_11/tnccs_11.c
+++ b/src/libcharon/plugins/tnccs_11/tnccs_11.c
@@ -14,81 +14,20 @@
*/
#include "tnccs_11.h"
-
-#include <libtnctncc.h>
-#include <libtnctncs.h>
+#include "batch/tnccs_batch.h"
+#include "messages/tnccs_msg.h"
+#include "messages/imc_imv_msg.h"
+#include "messages/tnccs_error_msg.h"
+#include "messages/tnccs_preferred_language_msg.h"
+#include "messages/tnccs_reason_strings_msg.h"
+#include "messages/tnccs_recommendation_msg.h"
#include <daemon.h>
#include <debug.h>
-
-#define TNC_SEND_BUFFER_SIZE 32
-
-static chunk_t tnc_send_buffer[TNC_SEND_BUFFER_SIZE];
-
-/**
- * Buffers TNCCS batch to be sent (TODO make the buffer scalable)
- */
-static TNC_Result buffer_batch(u_int32_t id, const char *data, size_t len)
-{
- if (id >= TNC_SEND_BUFFER_SIZE)
- {
- DBG1(DBG_TNC, "TNCCS Batch for Connection ID %u cannot be stored in "
- "send buffer with size %d", id, TNC_SEND_BUFFER_SIZE);
- return TNC_RESULT_FATAL;
- }
- if (tnc_send_buffer[id].ptr)
- {
- DBG1(DBG_TNC, "send buffer slot for Connection ID %u is already "
- "occupied", id);
- return TNC_RESULT_FATAL;
- }
- tnc_send_buffer[id] = chunk_alloc(len);
- memcpy(tnc_send_buffer[id].ptr, data, len);
-
- return TNC_RESULT_SUCCESS;
-}
-
-/**
- * Retrieves TNCCS batch to be sent
- */
-static bool retrieve_batch(u_int32_t id, chunk_t *batch)
-{
- if (id >= TNC_SEND_BUFFER_SIZE)
- {
- DBG1(DBG_TNC, "TNCCS Batch for Connection ID %u cannot be retrieved from "
- "send buffer with size %d", id, TNC_SEND_BUFFER_SIZE);
- return FALSE;
- }
-
- *batch = tnc_send_buffer[id];
- return TRUE;
-}
-
-/**
- * Frees TNCCS batch that was sent
- */
-static void free_batch(u_int32_t id)
-{
- if (id < TNC_SEND_BUFFER_SIZE)
- {
- chunk_free(&tnc_send_buffer[id]);
- }
-}
-
-/**
- * Define callback functions called by the libtnc library
- */
-TNC_Result TNC_TNCC_SendBatch(libtnc_tncc_connection* conn,
- const char* messageBuffer, size_t messageLength)
-{
- return buffer_batch(conn->connectionID, messageBuffer, messageLength);
-}
-
-TNC_Result TNC_TNCS_SendBatch(libtnc_tncs_connection* conn,
- const char* messageBuffer, size_t messageLength)
-{
- return buffer_batch(conn->connectionID, messageBuffer, messageLength);
-}
+#include <threading/mutex.h>
+#include <tnc/tncif.h>
+#include <tnc/tncifimv.h>
+#include <tnc/tnccs/tnccs.h>
typedef struct private_tnccs_11_t private_tnccs_11_t;
@@ -108,116 +47,372 @@ struct private_tnccs_11_t {
bool is_server;
/**
- * TNCC Connection to IMCs
+ * Connection ID assigned to this TNCCS connection
+ */
+ TNC_ConnectionID connection_id;
+
+ /**
+ * Last TNCCS batch ID
+ */
+ int batch_id;
+
+ /**
+ * TNCCS batch being constructed
+ */
+ tnccs_batch_t *batch;
+
+ /**
+ * Mutex locking the batch in construction
*/
- libtnc_tncc_connection* tncc_connection;
+ mutex_t *mutex;
/**
- * TNCS Connection to IMVs
+ * Flag set while processing
*/
- libtnc_tncs_connection* tncs_connection;
+ bool fatal_error;
+
+ /**
+ * Flag set by TNCCS-Recommendation message
+ */
+ bool delete_state;
+
+ /**
+ * Flag set by IMC/IMV RequestHandshakeRetry() function
+ */
+ bool request_handshake_retry;
+
+ /**
+ * Set of IMV recommendations (TNC Server only)
+ */
+ recommendations_t *recs;
};
-METHOD(tls_t, process, status_t,
- private_tnccs_11_t *this, void *buf, size_t buflen)
+METHOD(tnccs_t, send_msg, void,
+ private_tnccs_11_t* this, TNC_IMCID imc_id, TNC_IMVID imv_id,
+ TNC_BufferReference msg,
+ TNC_UInt32 msg_len,
+ TNC_MessageType msg_type)
{
- u_int32_t conn_id;
+ tnccs_msg_t *tnccs_msg;
- if (this->is_server && !this->tncs_connection)
+ tnccs_msg = imc_imv_msg_create(msg_type, chunk_create(msg, msg_len));
+
+ /* adding an IMC-IMV Message to TNCCS batch */
+ this->mutex->lock(this->mutex);
+ if (!this->batch)
{
- this->tncs_connection = libtnc_tncs_CreateConnection(NULL);
- if (!this->tncs_connection)
+ this->batch = tnccs_batch_create(this->is_server, ++this->batch_id);
+ }
+ this->batch->add_msg(this->batch, tnccs_msg);
+ this->mutex->unlock(this->mutex);
+}
+
+/**
+ * Handle a single TNCCS message according to its type
+ */
+static void handle_message(private_tnccs_11_t *this, tnccs_msg_t *msg)
+{
+ switch (msg->get_type(msg))
+ {
+ case IMC_IMV_MSG:
{
- DBG1(DBG_TNC, "TNCS CreateConnection failed");
- return FAILED;
+ imc_imv_msg_t *imc_imv_msg;
+ TNC_MessageType msg_type;
+ chunk_t msg_body;
+
+ imc_imv_msg = (imc_imv_msg_t*)msg;
+ msg_type = imc_imv_msg->get_msg_type(imc_imv_msg);
+ msg_body = imc_imv_msg->get_msg_body(imc_imv_msg);
+
+ DBG2(DBG_TNC, "handling IMC_IMV message type 0x%08x", msg_type);
+
+ if (this->is_server)
+ {
+ charon->imvs->receive_message(charon->imvs,
+ this->connection_id, msg_body.ptr, msg_body.len, msg_type);
+ }
+ else
+ {
+ charon->imcs->receive_message(charon->imcs,
+ this->connection_id, msg_body.ptr, msg_body.len,msg_type);
+ }
+ break;
+ }
+ case TNCCS_MSG_RECOMMENDATION:
+ {
+ tnccs_recommendation_msg_t *rec_msg;
+ TNC_IMV_Action_Recommendation rec;
+ TNC_ConnectionState state = TNC_CONNECTION_STATE_ACCESS_NONE;
+
+ rec_msg = (tnccs_recommendation_msg_t*)msg;
+ rec = rec_msg->get_recommendation(rec_msg);
+ if (this->is_server)
+ {
+ DBG1(DBG_TNC, "ignoring NCCS-Recommendation message from "
+ " TNC client");
+ break;
+ }
+ DBG1(DBG_TNC, "TNC recommendation is '%N'",
+ TNC_IMV_Action_Recommendation_names, rec);
+ switch (rec)
+ {
+ case TNC_IMV_ACTION_RECOMMENDATION_ALLOW:
+ state = TNC_CONNECTION_STATE_ACCESS_ALLOWED;
+ break;
+ case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE:
+ state = TNC_CONNECTION_STATE_ACCESS_ISOLATED;
+ break;
+ case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS:
+ default:
+ state = TNC_CONNECTION_STATE_ACCESS_NONE;
+ }
+ charon->imcs->notify_connection_change(charon->imcs,
+ this->connection_id, state);
+ this->delete_state = TRUE;
+ break;
+ }
+ case TNCCS_MSG_ERROR:
+ {
+ tnccs_error_msg_t *err_msg;
+ tnccs_error_type_t error_type;
+ char *error_msg;
+
+ err_msg = (tnccs_error_msg_t*)msg;
+ error_msg = err_msg->get_message(err_msg, &error_type);
+ DBG1(DBG_TNC, "received '%N' TNCCS-Error: %s",
+ tnccs_error_type_names, error_type, error_msg);
+
+ /* we assume that all errors are fatal */
+ this->fatal_error = TRUE;
+ break;
}
- DBG1(DBG_TNC, "assigned TNCS Connection ID %u",
- this->tncs_connection->connectionID);
- if (libtnc_tncs_BeginSession(this->tncs_connection) != TNC_RESULT_SUCCESS)
+ case TNCCS_MSG_PREFERRED_LANGUAGE:
+ {
+ tnccs_preferred_language_msg_t *lang_msg;
+ char *lang;
+
+ lang_msg = (tnccs_preferred_language_msg_t*)msg;
+ lang = lang_msg->get_preferred_language(lang_msg);
+
+ DBG2(DBG_TNC, "setting preferred language to '%s'", lang);
+ this->recs->set_preferred_language(this->recs,
+ chunk_create(lang, strlen(lang)));
+ break;
+ }
+ case TNCCS_MSG_REASON_STRINGS:
+ {
+ tnccs_reason_strings_msg_t *reason_msg;
+ chunk_t reason_string, reason_lang;
+
+ 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);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+METHOD(tls_t, process, status_t,
+ private_tnccs_11_t *this, void *buf, size_t buflen)
+{
+ chunk_t data;
+ tnccs_batch_t *batch;
+ tnccs_msg_t *msg;
+ enumerator_t *enumerator;
+ status_t status;
+
+ if (this->is_server && !this->connection_id)
+ {
+ this->connection_id = charon->tnccs->create_connection(charon->tnccs,
+ (tnccs_t*)this, _send_msg,
+ &this->request_handshake_retry, &this->recs);
+ if (!this->connection_id)
{
- DBG1(DBG_TNC, "TNCS BeginSession failed");
return FAILED;
}
+ charon->imvs->notify_connection_change(charon->imvs,
+ this->connection_id, TNC_CONNECTION_STATE_CREATE);
}
- conn_id = this->is_server ? this->tncs_connection->connectionID
- : this->tncc_connection->connectionID;
+ data = chunk_create(buf, buflen);
DBG1(DBG_TNC, "received TNCCS Batch (%u bytes) for Connection ID %u",
- buflen, conn_id);
- DBG3(DBG_TNC, "%.*s", buflen, buf);
+ data.len, this->connection_id);
+ DBG3(DBG_TNC, "%.*s", data.len, data.ptr);
+ batch = tnccs_batch_create_from_data(this->is_server, ++this->batch_id, data);
+ status = batch->process(batch);
- if (this->is_server)
+ if (status == FAILED)
{
- if (libtnc_tncs_ReceiveBatch(this->tncs_connection, buf, buflen) !=
- TNC_RESULT_SUCCESS)
+ this->fatal_error = TRUE;
+ this->mutex->lock(this->mutex);
+ if (this->batch)
{
- DBG1(DBG_TNC, "TNCS ReceiveBatch failed");
- return FAILED;
+ DBG1(DBG_TNC, "cancelling TNCCS batch");
+ this->batch->destroy(this->batch);
+ this->batch_id--;
+ }
+ this->batch = tnccs_batch_create(this->is_server, ++this->batch_id);
+
+ /* add error messages to outbound batch */
+ enumerator = batch->create_error_enumerator(batch);
+ while (enumerator->enumerate(enumerator, &msg))
+ {
+ this->batch->add_msg(this->batch, msg->get_ref(msg));
}
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
}
else
{
- if (libtnc_tncc_ReceiveBatch(this->tncc_connection, buf, buflen) !=
- TNC_RESULT_SUCCESS)
+ enumerator = batch->create_msg_enumerator(batch);
+ while (enumerator->enumerate(enumerator, &msg))
{
- DBG1(DBG_TNC, "TNCC ReceiveBatch failed");
+ handle_message(this, msg);
+ }
+ enumerator->destroy(enumerator);
+
+ /* received any TNCCS-Error messages */
+ if (this->fatal_error)
+ {
+ DBG1(DBG_TNC, "a fatal TNCCS-Error occurred, terminating connection");
+ batch->destroy(batch);
return FAILED;
}
+
+ if (this->is_server)
+ {
+ charon->imvs->batch_ending(charon->imvs, this->connection_id);
+ }
+ else
+ {
+ charon->imcs->batch_ending(charon->imcs, this->connection_id);
+ }
}
+ batch->destroy(batch);
+
return NEED_MORE;
}
-METHOD(tls_t, build, status_t,
- private_tnccs_11_t *this, void *buf, size_t *buflen, size_t *msglen)
+/**
+ * Add a recommendation message if a final recommendation is available
+ */
+static void check_and_build_recommendation(private_tnccs_11_t *this)
{
- chunk_t batch;
- u_int32_t conn_id;
- size_t len;
+ TNC_IMV_Action_Recommendation rec;
+ TNC_IMV_Evaluation_Result eval;
+ TNC_IMVID id;
+ chunk_t reason, language;
+ enumerator_t *enumerator;
+ tnccs_msg_t *msg;
- if (!this->is_server && !this->tncc_connection)
+ if (!this->recs->have_recommendation(this->recs, &rec, &eval))
+ {
+ charon->imvs->solicit_recommendation(charon->imvs, this->connection_id);
+ }
+ if (this->recs->have_recommendation(this->recs, &rec, &eval))
{
- this->tncc_connection = libtnc_tncc_CreateConnection(NULL);
- if (!this->tncc_connection)
+ if (!this->batch)
{
- DBG1(DBG_TNC, "TNCC CreateConnection failed");
- return FAILED;
+ this->batch = tnccs_batch_create(this->is_server, ++this->batch_id);
}
- DBG1(DBG_TNC, "assigned TNCC Connection ID %u",
- this->tncc_connection->connectionID);
- if (libtnc_tncc_BeginSession(this->tncc_connection) != TNC_RESULT_SUCCESS)
+
+ msg = tnccs_recommendation_msg_create(rec);
+ this->batch->add_msg(this->batch, msg);
+
+ /* currently we just send the first Reason String */
+ enumerator = this->recs->create_reason_enumerator(this->recs);
+ if (enumerator->enumerate(enumerator, &id, &reason, &language))
{
- DBG1(DBG_TNC, "TNCC BeginSession failed");
- return FAILED;
+ msg = tnccs_reason_strings_msg_create(reason, language);
+ this->batch->add_msg(this->batch, msg);
}
+ enumerator->destroy(enumerator);
+
+ /* we have reache the final state */
+ this->delete_state = TRUE;
}
- conn_id = this->is_server ? this->tncs_connection->connectionID
- : this->tncc_connection->connectionID;
-
- if (!retrieve_batch(conn_id, &batch))
+}
+
+METHOD(tls_t, build, status_t,
+ private_tnccs_11_t *this, void *buf, size_t *buflen, size_t *msglen)
+{
+ status_t status;
+
+ /* Initialize the connection */
+ if (!this->is_server && !this->connection_id)
{
- return FAILED;
+ tnccs_msg_t *msg;
+ char *pref_lang;
+
+ this->connection_id = charon->tnccs->create_connection(charon->tnccs,
+ (tnccs_t*)this, _send_msg,
+ &this->request_handshake_retry, NULL);
+ if (!this->connection_id)
+ {
+ return FAILED;
+ }
+
+ /* Create TNCCS-PreferredLanguage message */
+ pref_lang = charon->imcs->get_preferred_language(charon->imcs);
+ msg = tnccs_preferred_language_msg_create(pref_lang);
+ this->mutex->lock(this->mutex);
+ this->batch = tnccs_batch_create(this->is_server, ++this->batch_id);
+ this->batch->add_msg(this->batch, msg);
+ this->mutex->unlock(this->mutex);
+
+ charon->imcs->notify_connection_change(charon->imcs,
+ this->connection_id, TNC_CONNECTION_STATE_CREATE);
+ charon->imcs->notify_connection_change(charon->imcs,
+ this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE);
+ charon->imcs->begin_handshake(charon->imcs, this->connection_id);
}
- len = *buflen;
- len = min(len, batch.len);
- *buflen = len;
- if (msglen)
+
+ /* Do not allow any asynchronous IMCs or IMVs to add additional messages */
+ this->mutex->lock(this->mutex);
+
+ if (this->is_server && !this->delete_state &&
+ (!this->batch || this->fatal_error))
{
- *msglen = batch.len;
+ check_and_build_recommendation(this);
}
- if (batch.len)
+ if (this->batch)
{
+ chunk_t data;
+
+ this->batch->build(this->batch);
+ data = this->batch->get_encoding(this->batch);
DBG1(DBG_TNC, "sending TNCCS Batch (%d bytes) for Connection ID %u",
- batch.len, conn_id);
- DBG3(DBG_TNC, "%.*s", batch.len, batch.ptr);
- memcpy(buf, batch.ptr, len);
- free_batch(conn_id);
- return ALREADY_DONE;
+ data.len, this->connection_id);
+ DBG3(DBG_TNC, "%.*s", data.len, data.ptr);
+ *msglen = data.len;
+
+ if (data.len > *buflen)
+ {
+ DBG1(DBG_TNC, "fragmentation of TNCCS batch not supported yet");
+ }
+ else
+ {
+ *buflen = data.len;
+ }
+ memcpy(buf, data.ptr, *buflen);
+ this->batch->destroy(this->batch);
+ this->batch = NULL;
+ status = ALREADY_DONE;
}
else
{
- return INVALID_STATE;
+ DBG1(DBG_TNC, "no TNCCS Batch to send");
+ status = INVALID_STATE;
}
+ this->mutex->unlock(this->mutex);
+
+ return status;
}
METHOD(tls_t, is_server, bool,
@@ -237,39 +432,14 @@ METHOD(tls_t, is_complete, bool,
{
TNC_IMV_Action_Recommendation rec;
TNC_IMV_Evaluation_Result eval;
- char *group;
- identification_t *id;
- ike_sa_t *ike_sa;
- auth_cfg_t *auth;
-
- if (libtnc_tncs_HaveRecommendation(this->tncs_connection, &rec, &eval) ==
- TNC_RESULT_SUCCESS)
+
+ if (this->recs && this->recs->have_recommendation(this->recs, &rec, &eval))
{
- switch (rec)
- {
- case TNC_IMV_ACTION_RECOMMENDATION_ALLOW:
- DBG1(DBG_TNC, "TNC recommendation is allow");
- group = "allow";
- break;
- case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE:
- DBG1(DBG_TNC, "TNC recommendation is isolate");
- group = "isolate";
- break;
- case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS:
- case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION:
- default:
- DBG1(DBG_TNC, "TNC recommendation is none");
- return FALSE;
- }
- ike_sa = charon->bus->get_sa(charon->bus);
- if (ike_sa)
- {
- auth = ike_sa->get_auth_cfg(ike_sa, FALSE);
- id = identification_create_from_string(group);
- auth->add(auth, AUTH_RULE_GROUP, id);
- DBG1(DBG_TNC, "added group membership '%s' based on TNC recommendation", group);
- }
- return TRUE;
+ DBG2(DBG_TNC, "Final recommendation is '%N' and evaluation is '%N'",
+ TNC_IMV_Action_Recommendation_names, rec,
+ TNC_IMV_Evaluation_Result_names, eval);
+
+ return charon->imvs->enforce_recommendation(charon->imvs, rec);
}
else
{
@@ -288,19 +458,17 @@ METHOD(tls_t, destroy, void,
{
if (this->is_server)
{
- if (this->tncs_connection)
- {
- libtnc_tncs_DeleteConnection(this->tncs_connection);
- }
+ charon->imvs->notify_connection_change(charon->imvs,
+ this->connection_id, TNC_CONNECTION_STATE_DELETE);
}
else
{
- if (this->tncc_connection)
- {
- libtnc_tncc_DeleteConnection(this->tncc_connection);
- }
- libtnc_tncc_Terminate();
+ charon->imcs->notify_connection_change(charon->imcs,
+ this->connection_id, TNC_CONNECTION_STATE_DELETE);
}
+ charon->tnccs->remove_connection(charon->tnccs, this->connection_id);
+ this->mutex->destroy(this->mutex);
+ DESTROY_IF(this->batch);
free(this);
}
@@ -322,6 +490,7 @@ tls_t *tnccs_11_create(bool is_server)
.destroy = _destroy,
},
.is_server = is_server,
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
);
return &this->public;
diff --git a/src/libcharon/plugins/tnccs_20/Makefile.am b/src/libcharon/plugins/tnccs_20/Makefile.am
index 3018121e3..d72fd3e34 100644
--- a/src/libcharon/plugins/tnccs_20/Makefile.am
+++ b/src/libcharon/plugins/tnccs_20/Makefile.am
@@ -1,21 +1,28 @@
INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
- -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls \
- `xml2-config --cflags`
+ -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls
AM_CFLAGS = -rdynamic
-libstrongswan_tnccs_20_la_LIBADD = -ltnc
-
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-tnccs-20.la
else
plugin_LTLIBRARIES = libstrongswan-tnccs-20.la
-libstrongswan_tnccs_20_la_LIBADD += $(top_builddir)/src/libtls/libtls.la
+libstrongswan_tnccs_20_la_LIBADD = $(top_builddir)/src/libtls/libtls.la
endif
libstrongswan_tnccs_20_la_SOURCES = \
- tnccs_20_plugin.h tnccs_20_plugin.c tnccs_20.h tnccs_20.c
+ tnccs_20_plugin.h tnccs_20_plugin.c tnccs_20.h tnccs_20.c \
+ batch/pb_tnc_batch.h batch/pb_tnc_batch.c \
+ messages/pb_tnc_msg.h messages/pb_tnc_msg.c \
+ messages/pb_experimental_msg.h messages/pb_experimental_msg.c \
+ messages/pb_pa_msg.h messages/pb_pa_msg.c \
+ messages/pb_assessment_result_msg.h messages/pb_assessment_result_msg.c \
+ messages/pb_access_recommendation_msg.h messages/pb_access_recommendation_msg.c \
+ messages/pb_error_msg.h messages/pb_error_msg.c \
+ messages/pb_language_preference_msg.h messages/pb_language_preference_msg.c \
+ messages/pb_reason_string_msg.h messages/pb_reason_string_msg.c \
+ messages/pb_remediation_parameters_msg.h messages/pb_remediation_parameters_msg.c \
+ state_machine/pb_tnc_state_machine.h state_machine/pb_tnc_state_machine.c
libstrongswan_tnccs_20_la_LDFLAGS = -module -avoid-version
-
diff --git a/src/libcharon/plugins/tnccs_20/Makefile.in b/src/libcharon/plugins/tnccs_20/Makefile.in
index 6101f91df..9853be338 100644
--- a/src/libcharon/plugins/tnccs_20/Makefile.in
+++ b/src/libcharon/plugins/tnccs_20/Makefile.in
@@ -34,7 +34,6 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-@MONOLITHIC_FALSE@am__append_1 = $(top_builddir)/src/libtls/libtls.la
subdir = src/libcharon/plugins/tnccs_20
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -75,8 +74,14 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
-libstrongswan_tnccs_20_la_DEPENDENCIES = $(am__append_1)
-am_libstrongswan_tnccs_20_la_OBJECTS = tnccs_20_plugin.lo tnccs_20.lo
+@MONOLITHIC_FALSE@libstrongswan_tnccs_20_la_DEPENDENCIES = \
+@MONOLITHIC_FALSE@ $(top_builddir)/src/libtls/libtls.la
+am_libstrongswan_tnccs_20_la_OBJECTS = tnccs_20_plugin.lo tnccs_20.lo \
+ pb_tnc_batch.lo pb_tnc_msg.lo pb_experimental_msg.lo \
+ pb_pa_msg.lo pb_assessment_result_msg.lo \
+ pb_access_recommendation_msg.lo pb_error_msg.lo \
+ pb_language_preference_msg.lo pb_reason_string_msg.lo \
+ pb_remediation_parameters_msg.lo pb_tnc_state_machine.lo
libstrongswan_tnccs_20_la_OBJECTS = \
$(am_libstrongswan_tnccs_20_la_OBJECTS)
libstrongswan_tnccs_20_la_LINK = $(LIBTOOL) --tag=CC \
@@ -223,9 +228,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -264,6 +267,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
@@ -275,15 +280,25 @@ 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 -I$(top_srcdir)/src/libtls \
- `xml2-config --cflags`
+ -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls
AM_CFLAGS = -rdynamic
-libstrongswan_tnccs_20_la_LIBADD = -ltnc $(am__append_1)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-tnccs-20.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-tnccs-20.la
+@MONOLITHIC_FALSE@libstrongswan_tnccs_20_la_LIBADD = $(top_builddir)/src/libtls/libtls.la
libstrongswan_tnccs_20_la_SOURCES = \
- tnccs_20_plugin.h tnccs_20_plugin.c tnccs_20.h tnccs_20.c
+ tnccs_20_plugin.h tnccs_20_plugin.c tnccs_20.h tnccs_20.c \
+ batch/pb_tnc_batch.h batch/pb_tnc_batch.c \
+ messages/pb_tnc_msg.h messages/pb_tnc_msg.c \
+ messages/pb_experimental_msg.h messages/pb_experimental_msg.c \
+ messages/pb_pa_msg.h messages/pb_pa_msg.c \
+ messages/pb_assessment_result_msg.h messages/pb_assessment_result_msg.c \
+ messages/pb_access_recommendation_msg.h messages/pb_access_recommendation_msg.c \
+ messages/pb_error_msg.h messages/pb_error_msg.c \
+ messages/pb_language_preference_msg.h messages/pb_language_preference_msg.c \
+ messages/pb_reason_string_msg.h messages/pb_reason_string_msg.c \
+ messages/pb_remediation_parameters_msg.h messages/pb_remediation_parameters_msg.c \
+ state_machine/pb_tnc_state_machine.h state_machine/pb_tnc_state_machine.c
libstrongswan_tnccs_20_la_LDFLAGS = -module -avoid-version
all: all-am
@@ -369,6 +384,17 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_access_recommendation_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_assessment_result_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_error_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_experimental_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_language_preference_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_pa_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_reason_string_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_remediation_parameters_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_tnc_batch.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_tnc_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_tnc_state_machine.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_20.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_20_plugin.Plo@am__quote@
@@ -393,6 +419,83 @@ distclean-compile:
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+pb_tnc_batch.lo: batch/pb_tnc_batch.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pb_tnc_batch.lo -MD -MP -MF $(DEPDIR)/pb_tnc_batch.Tpo -c -o pb_tnc_batch.lo `test -f 'batch/pb_tnc_batch.c' || echo '$(srcdir)/'`batch/pb_tnc_batch.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_tnc_batch.Tpo $(DEPDIR)/pb_tnc_batch.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='batch/pb_tnc_batch.c' object='pb_tnc_batch.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 pb_tnc_batch.lo `test -f 'batch/pb_tnc_batch.c' || echo '$(srcdir)/'`batch/pb_tnc_batch.c
+
+pb_tnc_msg.lo: messages/pb_tnc_msg.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pb_tnc_msg.lo -MD -MP -MF $(DEPDIR)/pb_tnc_msg.Tpo -c -o pb_tnc_msg.lo `test -f 'messages/pb_tnc_msg.c' || echo '$(srcdir)/'`messages/pb_tnc_msg.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_tnc_msg.Tpo $(DEPDIR)/pb_tnc_msg.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/pb_tnc_msg.c' object='pb_tnc_msg.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 pb_tnc_msg.lo `test -f 'messages/pb_tnc_msg.c' || echo '$(srcdir)/'`messages/pb_tnc_msg.c
+
+pb_experimental_msg.lo: messages/pb_experimental_msg.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pb_experimental_msg.lo -MD -MP -MF $(DEPDIR)/pb_experimental_msg.Tpo -c -o pb_experimental_msg.lo `test -f 'messages/pb_experimental_msg.c' || echo '$(srcdir)/'`messages/pb_experimental_msg.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_experimental_msg.Tpo $(DEPDIR)/pb_experimental_msg.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/pb_experimental_msg.c' object='pb_experimental_msg.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 pb_experimental_msg.lo `test -f 'messages/pb_experimental_msg.c' || echo '$(srcdir)/'`messages/pb_experimental_msg.c
+
+pb_pa_msg.lo: messages/pb_pa_msg.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pb_pa_msg.lo -MD -MP -MF $(DEPDIR)/pb_pa_msg.Tpo -c -o pb_pa_msg.lo `test -f 'messages/pb_pa_msg.c' || echo '$(srcdir)/'`messages/pb_pa_msg.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_pa_msg.Tpo $(DEPDIR)/pb_pa_msg.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/pb_pa_msg.c' object='pb_pa_msg.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 pb_pa_msg.lo `test -f 'messages/pb_pa_msg.c' || echo '$(srcdir)/'`messages/pb_pa_msg.c
+
+pb_assessment_result_msg.lo: messages/pb_assessment_result_msg.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pb_assessment_result_msg.lo -MD -MP -MF $(DEPDIR)/pb_assessment_result_msg.Tpo -c -o pb_assessment_result_msg.lo `test -f 'messages/pb_assessment_result_msg.c' || echo '$(srcdir)/'`messages/pb_assessment_result_msg.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_assessment_result_msg.Tpo $(DEPDIR)/pb_assessment_result_msg.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/pb_assessment_result_msg.c' object='pb_assessment_result_msg.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 pb_assessment_result_msg.lo `test -f 'messages/pb_assessment_result_msg.c' || echo '$(srcdir)/'`messages/pb_assessment_result_msg.c
+
+pb_access_recommendation_msg.lo: messages/pb_access_recommendation_msg.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pb_access_recommendation_msg.lo -MD -MP -MF $(DEPDIR)/pb_access_recommendation_msg.Tpo -c -o pb_access_recommendation_msg.lo `test -f 'messages/pb_access_recommendation_msg.c' || echo '$(srcdir)/'`messages/pb_access_recommendation_msg.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_access_recommendation_msg.Tpo $(DEPDIR)/pb_access_recommendation_msg.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/pb_access_recommendation_msg.c' object='pb_access_recommendation_msg.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 pb_access_recommendation_msg.lo `test -f 'messages/pb_access_recommendation_msg.c' || echo '$(srcdir)/'`messages/pb_access_recommendation_msg.c
+
+pb_error_msg.lo: messages/pb_error_msg.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pb_error_msg.lo -MD -MP -MF $(DEPDIR)/pb_error_msg.Tpo -c -o pb_error_msg.lo `test -f 'messages/pb_error_msg.c' || echo '$(srcdir)/'`messages/pb_error_msg.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_error_msg.Tpo $(DEPDIR)/pb_error_msg.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/pb_error_msg.c' object='pb_error_msg.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 pb_error_msg.lo `test -f 'messages/pb_error_msg.c' || echo '$(srcdir)/'`messages/pb_error_msg.c
+
+pb_language_preference_msg.lo: messages/pb_language_preference_msg.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pb_language_preference_msg.lo -MD -MP -MF $(DEPDIR)/pb_language_preference_msg.Tpo -c -o pb_language_preference_msg.lo `test -f 'messages/pb_language_preference_msg.c' || echo '$(srcdir)/'`messages/pb_language_preference_msg.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_language_preference_msg.Tpo $(DEPDIR)/pb_language_preference_msg.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/pb_language_preference_msg.c' object='pb_language_preference_msg.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 pb_language_preference_msg.lo `test -f 'messages/pb_language_preference_msg.c' || echo '$(srcdir)/'`messages/pb_language_preference_msg.c
+
+pb_reason_string_msg.lo: messages/pb_reason_string_msg.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pb_reason_string_msg.lo -MD -MP -MF $(DEPDIR)/pb_reason_string_msg.Tpo -c -o pb_reason_string_msg.lo `test -f 'messages/pb_reason_string_msg.c' || echo '$(srcdir)/'`messages/pb_reason_string_msg.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_reason_string_msg.Tpo $(DEPDIR)/pb_reason_string_msg.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/pb_reason_string_msg.c' object='pb_reason_string_msg.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 pb_reason_string_msg.lo `test -f 'messages/pb_reason_string_msg.c' || echo '$(srcdir)/'`messages/pb_reason_string_msg.c
+
+pb_remediation_parameters_msg.lo: messages/pb_remediation_parameters_msg.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pb_remediation_parameters_msg.lo -MD -MP -MF $(DEPDIR)/pb_remediation_parameters_msg.Tpo -c -o pb_remediation_parameters_msg.lo `test -f 'messages/pb_remediation_parameters_msg.c' || echo '$(srcdir)/'`messages/pb_remediation_parameters_msg.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_remediation_parameters_msg.Tpo $(DEPDIR)/pb_remediation_parameters_msg.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/pb_remediation_parameters_msg.c' object='pb_remediation_parameters_msg.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 pb_remediation_parameters_msg.lo `test -f 'messages/pb_remediation_parameters_msg.c' || echo '$(srcdir)/'`messages/pb_remediation_parameters_msg.c
+
+pb_tnc_state_machine.lo: state_machine/pb_tnc_state_machine.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pb_tnc_state_machine.lo -MD -MP -MF $(DEPDIR)/pb_tnc_state_machine.Tpo -c -o pb_tnc_state_machine.lo `test -f 'state_machine/pb_tnc_state_machine.c' || echo '$(srcdir)/'`state_machine/pb_tnc_state_machine.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_tnc_state_machine.Tpo $(DEPDIR)/pb_tnc_state_machine.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='state_machine/pb_tnc_state_machine.c' object='pb_tnc_state_machine.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 pb_tnc_state_machine.lo `test -f 'state_machine/pb_tnc_state_machine.c' || echo '$(srcdir)/'`state_machine/pb_tnc_state_machine.c
+
mostlyclean-libtool:
-rm -f *.lo
diff --git a/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c b/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c
new file mode 100644
index 000000000..3f38543ed
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c
@@ -0,0 +1,543 @@
+/*
+ * Copyright (C) 2010 Sansar Choinyanbuu
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pb_tnc_batch.h"
+#include "messages/pb_error_msg.h"
+#include "state_machine/pb_tnc_state_machine.h"
+
+#include <debug.h>
+#include <utils/linked_list.h>
+#include <tls_writer.h>
+#include <tls_reader.h>
+#include <tnc/tnccs/tnccs.h>
+
+ENUM(pb_tnc_batch_type_names, PB_BATCH_CDATA, PB_BATCH_CLOSE,
+ "CDATA",
+ "SDATA",
+ "RESULT",
+ "CRETRY",
+ "SRETRY",
+ "CLOSE"
+);
+
+typedef struct private_pb_tnc_batch_t private_pb_tnc_batch_t;
+
+/**
+ * PB-Batch Header (see section 4.1 of RFC 5793)
+ *
+ * 0 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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Version |D| Reserved | B-Type|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Batch Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define PB_TNC_BATCH_FLAG_NONE 0x00
+#define PB_TNC_BATCH_FLAG_D (1<<7)
+#define PB_TNC_BATCH_HEADER_SIZE 8
+
+/**
+ * PB-TNC Message (see section 4.2 of RFC 5793)
+ *
+ * 0 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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Flags | PB-TNC Vendor ID |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | PB-TNC Message Type |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | PB-TNC Message Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | PB-TNC Message Value (Variable Length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define PB_TNC_FLAG_NONE 0x00
+#define PB_TNC_FLAG_NOSKIP (1<<7)
+#define PB_TNC_HEADER_SIZE 12
+
+#define PB_TNC_RESERVED_MSG_TYPE 0xffffffff
+
+/**
+ * Private data of a pb_tnc_batch_t object.
+ *
+ */
+struct private_pb_tnc_batch_t {
+ /**
+ * Public pb_pa_msg_t interface.
+ */
+ pb_tnc_batch_t public;
+
+ /**
+ * TNCC if TRUE, TNCS if FALSE
+ */
+ bool is_server;
+
+ /**
+ * PB-TNC Batch type
+ */
+ pb_tnc_batch_type_t type;
+
+ /**
+ * linked list of PB-TNC messages
+ */
+ linked_list_t *messages;
+
+ /**
+ * linked list of PB-TNC error messages
+ */
+ linked_list_t *errors;
+
+ /**
+ * Encoded message
+ */
+ chunk_t encoding;
+
+ /**
+ * Offset into encoding (used for error reporting)
+ */
+ u_int32_t offset;
+};
+
+METHOD(pb_tnc_batch_t, get_type, pb_tnc_batch_type_t,
+ private_pb_tnc_batch_t *this)
+{
+ return this->type;
+}
+
+METHOD(pb_tnc_batch_t, get_encoding, chunk_t,
+ private_pb_tnc_batch_t *this)
+{
+ return this->encoding;
+}
+
+METHOD(pb_tnc_batch_t, add_msg, void,
+ private_pb_tnc_batch_t *this, pb_tnc_msg_t* msg)
+{
+ DBG2(DBG_TNC, "adding %N message", pb_tnc_msg_type_names,
+ msg->get_type(msg));
+ this->messages->insert_last(this->messages, msg);
+}
+
+METHOD(pb_tnc_batch_t, build, void,
+ private_pb_tnc_batch_t *this)
+{
+ u_int32_t batch_len, msg_len;
+ chunk_t msg_value;
+ enumerator_t *enumerator;
+ pb_tnc_msg_type_t msg_type;
+ pb_tnc_msg_t *msg;
+ tls_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 = tls_writer_create(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);
+
+ /* build PB-TNC messages */
+ enumerator = this->messages->create_enumerator(this->messages);
+ while (enumerator->enumerate(enumerator, &msg))
+ {
+ u_int8_t flags = PB_TNC_FLAG_NONE;
+
+ /* build PB-TNC message */
+ msg_value = msg->get_encoding(msg);
+ msg_len = PB_TNC_HEADER_SIZE + msg_value.len;
+ msg_type = msg->get_type(msg);
+ if (pb_tnc_msg_infos[msg_type].has_noskip_flag)
+ {
+ flags |= PB_TNC_FLAG_NOSKIP;
+ }
+ writer->write_uint8 (writer, flags);
+ writer->write_uint24(writer, IETF_VENDOR_ID);
+ writer->write_uint32(writer, msg_type);
+ writer->write_uint32(writer, msg_len);
+ writer->write_data (writer, msg_value);
+ }
+ enumerator->destroy(enumerator);
+
+ this->encoding = chunk_clone(writer->get_buf(writer));
+ writer->destroy(writer);
+}
+
+static status_t process_batch_header(private_pb_tnc_batch_t *this,
+ pb_tnc_state_machine_t *state_machine)
+{
+ tls_reader_t *reader;
+ pb_tnc_msg_t *msg;
+ pb_error_msg_t *err_msg;
+ u_int8_t version, flags, reserved, type;
+ u_int32_t batch_len;
+ bool directionality;
+
+ if (this->encoding.len < PB_TNC_BATCH_HEADER_SIZE)
+ {
+ DBG1(DBG_TNC, "%u bytes insufficient to parse PB-TNC batch header",
+ this->encoding.len);
+ msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID,
+ PB_ERROR_INVALID_PARAMETER, 0);
+ goto fatal;
+ }
+
+ reader = tls_reader_create(this->encoding);
+ reader->read_uint8 (reader, &version);
+ reader->read_uint8 (reader, &flags);
+ reader->read_uint8 (reader, &reserved);
+ reader->read_uint8 (reader, &type);
+ reader->read_uint32(reader, &batch_len);
+ reader->destroy(reader);
+
+ /* Version */
+ if (version != PB_TNC_VERSION)
+ {
+ DBG1(DBG_TNC, "unsupported TNCCS batch version 0x%01x", version);
+ msg = pb_error_msg_create(TRUE, IETF_VENDOR_ID,
+ PB_ERROR_VERSION_NOT_SUPPORTED);
+ err_msg = (pb_error_msg_t*)msg;
+ err_msg->set_bad_version(err_msg, version);
+ goto fatal;
+ }
+
+ /* Directionality */
+ directionality = (flags & PB_TNC_BATCH_FLAG_D) != PB_TNC_BATCH_FLAG_NONE;
+ if (directionality == this->is_server)
+ {
+ DBG1(DBG_TNC, "wrong Directionality: batch is from a PB %s",
+ directionality ? "server" : "client");
+ msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID,
+ PB_ERROR_INVALID_PARAMETER, 1);
+ goto fatal;
+ }
+
+ /* Batch Type */
+ this->type = type & 0x0F;
+ if (this->type > PB_BATCH_ROOF)
+ {
+ DBG1(DBG_TNC, "unknown PB-TNC batch type: %d", this->type);
+ msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID,
+ PB_ERROR_INVALID_PARAMETER, 3);
+ goto fatal;
+ }
+
+ if (!state_machine->receive_batch(state_machine, this->type))
+ {
+ DBG1(DBG_TNC, "unexpected PB-TNC batch type: %N",
+ pb_tnc_batch_type_names, this->type);
+ msg = pb_error_msg_create(TRUE, IETF_VENDOR_ID,
+ PB_ERROR_UNEXPECTED_BATCH_TYPE);
+ goto fatal;
+ }
+
+ /* Batch Length */
+ if (this->encoding.len != batch_len)
+ {
+ DBG1(DBG_TNC, "%u bytes of data is not equal to batch length of %u bytes",
+ this->encoding.len, batch_len);
+ msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID,
+ PB_ERROR_INVALID_PARAMETER, 4);
+ goto fatal;
+ }
+
+ this->offset = PB_TNC_BATCH_HEADER_SIZE;
+ return SUCCESS;
+
+fatal:
+ this->errors->insert_last(this->errors, msg);
+ return FAILED;
+}
+
+static status_t process_tnc_msg(private_pb_tnc_batch_t *this)
+{
+ tls_reader_t *reader;
+ pb_tnc_msg_t *pb_tnc_msg, *msg;
+ u_int8_t flags;
+ u_int32_t vendor_id, msg_type, msg_len, offset;
+ chunk_t data, msg_value;
+ bool noskip_flag;
+ status_t status;
+
+ data = chunk_skip(this->encoding, this->offset);
+
+ if (data.len < PB_TNC_HEADER_SIZE)
+ {
+ DBG1(DBG_TNC, "%u bytes insufficient to parse PB-TNC message header",
+ data.len);
+ msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID,
+ PB_ERROR_INVALID_PARAMETER, this->offset);
+ goto fatal;
+ }
+
+ reader = tls_reader_create(data);
+ reader->read_uint8 (reader, &flags);
+ reader->read_uint24(reader, &vendor_id);
+ reader->read_uint32(reader, &msg_type);
+ reader->read_uint32(reader, &msg_len);
+ reader->destroy(reader);
+
+ noskip_flag = (flags & PB_TNC_FLAG_NOSKIP) != PB_TNC_FLAG_NONE;
+
+ if (msg_len > data.len)
+ {
+ DBG1(DBG_TNC, "%u bytes insufficient to parse PB-TNC message", data.len);
+ msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID,
+ PB_ERROR_INVALID_PARAMETER, this->offset + 8);
+ goto fatal;
+ }
+
+ if (vendor_id == RESERVED_VENDOR_ID)
+ {
+ DBG1(DBG_TNC, "Vendor ID 0x%06x is reserved", RESERVED_VENDOR_ID);
+ msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID,
+ PB_ERROR_INVALID_PARAMETER, this->offset + 1);
+ goto fatal;
+
+ }
+
+ if (msg_type == PB_TNC_RESERVED_MSG_TYPE)
+ {
+ DBG1(DBG_TNC, "PB-TNC message Type 0x%08x is reserved",
+ PB_TNC_RESERVED_MSG_TYPE);
+ msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID,
+ PB_ERROR_INVALID_PARAMETER, this->offset + 4);
+ goto fatal;
+ }
+
+
+ if (vendor_id != IETF_VENDOR_ID || msg_type > PB_MSG_ROOF)
+ {
+ if (msg_len < PB_TNC_HEADER_SIZE)
+ {
+ DBG1(DBG_TNC, "%u bytes too small for PB-TNC message length",
+ msg_len);
+ msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID,
+ PB_ERROR_INVALID_PARAMETER, this->offset + 8);
+ goto fatal;
+ }
+
+ if (noskip_flag)
+ {
+ DBG1(DBG_TNC, "reject PB-TNC message (Vendor ID 0x%06x / "
+ "Type 0x%08x)", vendor_id, msg_type);
+ msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID,
+ PB_ERROR_UNSUPPORTED_MANDATORY_MSG, this->offset);
+ goto fatal;
+ }
+ else
+ {
+ DBG1(DBG_TNC, "ignore PB-TNC message (Vendor ID 0x%06x / "
+ "Type 0x%08x)", vendor_id, msg_type);
+ this->offset += msg_len;
+ return SUCCESS;
+ }
+ }
+ else
+ {
+ if (pb_tnc_msg_infos[msg_type].has_noskip_flag != TRUE_OR_FALSE &&
+ pb_tnc_msg_infos[msg_type].has_noskip_flag != noskip_flag)
+ {
+ DBG1(DBG_TNC, "%N message must%s have NOSKIP flag set",
+ pb_tnc_msg_type_names, msg_type,
+ pb_tnc_msg_infos[msg_type].has_noskip_flag ? "" : " not");
+ msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID,
+ PB_ERROR_INVALID_PARAMETER, this->offset);
+ goto fatal;
+ }
+
+ if (msg_len < pb_tnc_msg_infos[msg_type].min_size ||
+ (pb_tnc_msg_infos[msg_type].exact_size &&
+ msg_len != pb_tnc_msg_infos[msg_type].min_size))
+ {
+ DBG1(DBG_TNC, "%N message length must be %s %u bytes but is %u bytes",
+ pb_tnc_msg_type_names, msg_type,
+ pb_tnc_msg_infos[msg_type].exact_size ? "exactly" : "at least",
+ pb_tnc_msg_infos[msg_type].min_size, msg_len);
+ msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID,
+ PB_ERROR_INVALID_PARAMETER, this->offset);
+ goto fatal;
+ }
+ }
+
+ if (pb_tnc_msg_infos[msg_type].in_result_batch &&
+ this->type != PB_BATCH_RESULT)
+ {
+ if (this->is_server)
+ {
+ DBG1(DBG_TNC,"reject %N message received from a PB-TNC client",
+ pb_tnc_msg_type_names, msg_type);
+ msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID,
+ PB_ERROR_INVALID_PARAMETER, this->offset);
+ goto fatal;
+ }
+ else
+ {
+ DBG1(DBG_TNC,"ignore %N message not received within RESULT batch",
+ pb_tnc_msg_type_names, msg_type);
+ this->offset += msg_len;
+ return SUCCESS;
+ }
+ }
+
+ DBG2(DBG_TNC, "processing %N message (%u bytes)", pb_tnc_msg_type_names,
+ msg_type, msg_len);
+ data.len = msg_len;
+ msg_value = chunk_skip(data, PB_TNC_HEADER_SIZE);
+ pb_tnc_msg = pb_tnc_msg_create_from_data(msg_type, msg_value);
+
+ status = pb_tnc_msg->process(pb_tnc_msg, &offset);
+ if (status == FAILED || status == VERIFY_ERROR)
+ {
+ msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID,
+ PB_ERROR_INVALID_PARAMETER, this->offset);
+ this->errors->insert_last(this->errors, msg);
+ }
+ if (status == FAILED)
+ {
+ pb_tnc_msg->destroy(pb_tnc_msg);
+ return FAILED;
+ }
+ this->messages->insert_last(this->messages, pb_tnc_msg);
+ this->offset += msg_len;
+ return status;
+
+fatal:
+ this->errors->insert_last(this->errors, msg);
+ return FAILED;
+}
+
+METHOD(pb_tnc_batch_t, process, status_t,
+ private_pb_tnc_batch_t *this, pb_tnc_state_machine_t *state_machine)
+{
+ status_t status;
+
+ status = process_batch_header(this, state_machine);
+ if (status != SUCCESS)
+ {
+ 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))
+ {
+ case FAILED:
+ return FAILED;
+ case VERIFY_ERROR:
+ status = VERIFY_ERROR;
+ break;
+ case SUCCESS:
+ default:
+ break;
+ }
+ }
+ return status;
+}
+
+METHOD(pb_tnc_batch_t, create_msg_enumerator, enumerator_t*,
+ private_pb_tnc_batch_t *this)
+{
+ return this->messages->create_enumerator(this->messages);
+}
+
+METHOD(pb_tnc_batch_t, create_error_enumerator, enumerator_t*,
+ private_pb_tnc_batch_t *this)
+{
+ return this->errors->create_enumerator(this->errors);
+}
+
+METHOD(pb_tnc_batch_t, destroy, void,
+ private_pb_tnc_batch_t *this)
+{
+ this->messages->destroy_offset(this->messages,
+ offsetof(pb_tnc_msg_t, destroy));
+ this->errors->destroy_offset(this->errors,
+ offsetof(pb_tnc_msg_t, destroy));
+ free(this->encoding.ptr);
+ free(this);
+}
+
+/**
+ * See header
+ */
+pb_tnc_batch_t* pb_tnc_batch_create(bool is_server, pb_tnc_batch_type_t type)
+{
+ private_pb_tnc_batch_t *this;
+
+ INIT(this,
+ .public = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .add_msg = _add_msg,
+ .build = _build,
+ .process = _process,
+ .create_msg_enumerator = _create_msg_enumerator,
+ .create_error_enumerator = _create_error_enumerator,
+ .destroy = _destroy,
+ },
+ .is_server = is_server,
+ .type = type,
+ .messages = linked_list_create(),
+ .errors = linked_list_create(),
+ );
+
+ DBG2(DBG_TNC, "creating PB-TNC %N batch", pb_tnc_batch_type_names, type);
+
+ return &this->public;
+}
+
+/**
+ * See header
+ */
+pb_tnc_batch_t* pb_tnc_batch_create_from_data(bool is_server, chunk_t data)
+{
+ private_pb_tnc_batch_t *this;
+
+ INIT(this,
+ .public = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .add_msg = _add_msg,
+ .build = _build,
+ .process = _process,
+ .create_msg_enumerator = _create_msg_enumerator,
+ .create_error_enumerator = _create_error_enumerator,
+ .destroy = _destroy,
+ },
+ .is_server = is_server,
+ .messages = linked_list_create(),
+ .errors = linked_list_create(),
+ .encoding = chunk_clone(data),
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.h b/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.h
new file mode 100644
index 000000000..17e5fff4c
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pb_tnc_batch pb_tnc_batch
+ * @{ @ingroup tnccs_20
+ */
+
+#ifndef PB_TNC_BATCH_H_
+#define PB_TNC_BATCH_H_
+
+typedef enum pb_tnc_batch_type_t pb_tnc_batch_type_t;
+typedef struct pb_tnc_batch_t pb_tnc_batch_t;
+
+#include "messages/pb_tnc_msg.h"
+#include "state_machine/pb_tnc_state_machine.h"
+
+#include <library.h>
+
+/**
+ * PB-TNC Batch Types as defined in section 4.1 of RFC 5793
+ */
+enum pb_tnc_batch_type_t {
+ PB_BATCH_CDATA = 1,
+ PB_BATCH_SDATA = 2,
+ PB_BATCH_RESULT = 3,
+ PB_BATCH_CRETRY = 4,
+ PB_BATCH_SRETRY = 5,
+ PB_BATCH_CLOSE = 6,
+ PB_BATCH_ROOF = 6
+};
+
+/**
+ * enum name for pb_tnc_batch_type_t.
+ */
+extern enum_name_t *pb_tnc_batch_type_names;
+
+/**
+ * Interface for all PB-TNC Batch Types.
+ */
+struct pb_tnc_batch_t {
+
+ /**
+ * Get the PB-TNC Message Type
+ *
+ * @return PB-TNC batch type
+ */
+ pb_tnc_batch_type_t (*get_type)(pb_tnc_batch_t *this);
+
+ /**
+ * Get the encoding of the PB-TNC Batch
+ *
+ * @return encoded PB-TNC batch
+ */
+ chunk_t (*get_encoding)(pb_tnc_batch_t *this);
+
+ /**
+ * Add a PB-TNC Message
+ *
+ * @param msg PB-TNC message to be addedd
+ */
+ void (*add_msg)(pb_tnc_batch_t *this, pb_tnc_msg_t* msg);
+
+ /**
+ * Build the PB-TNC Batch
+ */
+ void (*build)(pb_tnc_batch_t *this);
+
+ /**
+ * Process the PB-TNC Batch
+ *
+ * @param PB-TNC state machine
+ * @return return processing status
+ */
+ status_t (*process)(pb_tnc_batch_t *this,
+ pb_tnc_state_machine_t *state_machine);
+
+ /**
+ * Enumerates over all PB-TNC Messages
+ *
+ * @return return message enumerator
+ */
+ enumerator_t* (*create_msg_enumerator)(pb_tnc_batch_t *this);
+
+ /**
+ * Enumerates over all parsing errors
+ *
+ * @return return error enumerator
+ */
+ enumerator_t* (*create_error_enumerator)(pb_tnc_batch_t *this);
+
+ /**
+ * Destroys a pb_tnc_batch_t object.
+ */
+ void (*destroy)(pb_tnc_batch_t *this);
+};
+
+/**
+ * Create an empty PB-TNC Batch of a given type
+ *
+ * @param is_server TRUE if server, FALSE if client
+ * @param type PB-TNC batch type
+ */
+pb_tnc_batch_t* pb_tnc_batch_create(bool is_server, pb_tnc_batch_type_t type);
+
+/**
+ * Create an unprocessed PB-TNC Batch from data
+ *
+ * @param is_server TRUE if server, FALSE if client
+ * @param data encoded PB-TNC batch
+ */
+pb_tnc_batch_t* pb_tnc_batch_create_from_data(bool is_server, chunk_t data);
+
+#endif /** PB_TNC_BATCH_H_ @}*/
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
new file mode 100644
index 000000000..41b9e31f6
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_20/messages/pb_access_recommendation_msg.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2010 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pb_access_recommendation_msg.h"
+
+#include <tls_writer.h>
+#include <tls_reader.h>
+#include <debug.h>
+
+ENUM(pb_access_recommendation_code_names, PB_REC_ACCESS_ALLOWED, PB_REC_QUARANTINED,
+ "Access Allowed",
+ "Access Denied",
+ "Quarantined"
+);
+
+typedef struct private_pb_access_recommendation_msg_t private_pb_access_recommendation_msg_t;
+
+/**
+ * PB-Access-Recommendation message (see section 4.7 of RFC 5793)
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Reserved | Access Recommendation Code |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define ACCESS_RECOMMENDATION_RESERVED 0x0000
+#define ACCESS_RECOMMENDATION_MSG_SIZE 4
+/**
+ * Private data of a pb_access_recommendation_msg_t object.
+ *
+ */
+struct private_pb_access_recommendation_msg_t {
+ /**
+ * Public pb_access_recommendation_msg_t interface.
+ */
+ pb_access_recommendation_msg_t public;
+
+ /**
+ * PB-TNC message type
+ */
+ pb_tnc_msg_type_t type;
+
+ /**
+ * Access recommendation code
+ */
+ u_int16_t recommendation;
+
+ /**
+ * Encoded message
+ */
+ chunk_t encoding;
+};
+
+METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t,
+ private_pb_access_recommendation_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
+ private_pb_access_recommendation_msg_t *this)
+{
+ return this->encoding;
+}
+
+METHOD(pb_tnc_msg_t, build, void,
+ private_pb_access_recommendation_msg_t *this)
+{
+ tls_writer_t *writer;
+
+ /* build message */
+ writer = tls_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);
+}
+
+METHOD(pb_tnc_msg_t, process, status_t,
+ private_pb_access_recommendation_msg_t *this, u_int32_t *offset)
+{
+ tls_reader_t *reader;
+ u_int16_t reserved;
+
+ /* process message */
+ reader = tls_reader_create(this->encoding);
+ reader->read_uint16(reader, &reserved);
+ reader->read_uint16(reader, &this->recommendation);
+ reader->destroy(reader);
+
+ if (this->recommendation < PB_REC_ACCESS_ALLOWED ||
+ this->recommendation > PB_REC_QUARANTINED)
+ {
+ DBG1(DBG_TNC, "invalid access recommendation code (%u)",
+ this->recommendation);
+ *offset = 2;
+ return FAILED;
+ }
+
+ return SUCCESS;
+}
+
+METHOD(pb_tnc_msg_t, destroy, void,
+ private_pb_access_recommendation_msg_t *this)
+{
+ free(this->encoding.ptr);
+ free(this);
+}
+
+METHOD(pb_access_recommendation_msg_t, get_access_recommendation, u_int16_t,
+ private_pb_access_recommendation_msg_t *this)
+{
+ return this->recommendation;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_access_recommendation_msg_create_from_data(chunk_t data)
+{
+ private_pb_access_recommendation_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ .get_access_recommendation = _get_access_recommendation,
+ },
+ .type = PB_MSG_ACCESS_RECOMMENDATION,
+ .encoding = chunk_clone(data),
+ );
+
+ return &this->public.pb_interface;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_access_recommendation_msg_create(u_int16_t recommendation)
+{
+ private_pb_access_recommendation_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ .get_access_recommendation = _get_access_recommendation,
+ },
+ .type = PB_MSG_ACCESS_RECOMMENDATION,
+ .recommendation = recommendation,
+ );
+
+ return &this->public.pb_interface;
+}
diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_access_recommendation_msg.h b/src/libcharon/plugins/tnccs_20/messages/pb_access_recommendation_msg.h
new file mode 100644
index 000000000..01b83cfd7
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_20/messages/pb_access_recommendation_msg.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2010 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pb_access_recommendation_msg pb_access_recommendation_msg
+ * @{ @ingroup tnccs_20
+ */
+
+#ifndef PB_ACCESS_RECOMMENDATION_MSG_H_
+#define PB_ACCESS_RECOMMENDATION_MSG_H_
+
+typedef enum pb_access_recommendation_code_t pb_access_recommendation_code_t;
+typedef struct pb_access_recommendation_msg_t pb_access_recommendation_msg_t;
+
+#include "pb_tnc_msg.h"
+
+/**
+ * PB Access Recommendation Codes as defined in section 4.7 of RFC 5793
+ */
+enum pb_access_recommendation_code_t {
+ PB_REC_ACCESS_ALLOWED = 1,
+ PB_REC_ACCESS_DENIED = 2,
+ PB_REC_QUARANTINED = 3,
+};
+
+/**
+ * enum name for pb_access_recommendation_code_t.
+ */
+extern enum_name_t *pb_access_recommendation_code_names;
+
+
+/**
+ * Class representing the PB-Access-Recommendation message type.
+ */
+struct pb_access_recommendation_msg_t {
+
+ /**
+ * PB-TNC Message interface
+ */
+ pb_tnc_msg_t pb_interface;
+
+ /**
+ * Get PB Access Recommendation
+ *
+ * @return PB Access Recommendation
+ */
+ u_int16_t (*get_access_recommendation)(pb_access_recommendation_msg_t *this);
+};
+
+/**
+ * Create a PB-Access-Recommendation message from parameters
+ *
+ * @param recommendation Access Recommendation code
+ */
+pb_tnc_msg_t* pb_access_recommendation_msg_create(u_int16_t recommendation);
+
+/**
+ * Create an unprocessed PB-Access-Recommendation message from raw data
+ *
+ * @param data PB-Access-Recommendation message data
+ */
+pb_tnc_msg_t* pb_access_recommendation_msg_create_from_data(chunk_t data);
+
+#endif /** PB_PA_MSG_H_ @}*/
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
new file mode 100644
index 000000000..c91e54176
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_20/messages/pb_assessment_result_msg.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2010 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pb_assessment_result_msg.h"
+
+#include <tls_writer.h>
+#include <tls_reader.h>
+#include <tnc/tncifimv.h>
+#include <debug.h>
+
+typedef struct private_pb_assessment_result_msg_t private_pb_assessment_result_msg_t;
+
+/**
+ * PB-Assessment-Result message (see section 4.6 of RFC 5793)
+ *
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Assessment Result |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define ASSESSMENT_RESULT_MSG_SIZE 4
+
+/**
+ * Private data of a pb_assessment_result_msg_t object.
+ *
+ */
+struct private_pb_assessment_result_msg_t {
+ /**
+ * Public pb_assessment_result_msg_t interface.
+ */
+ pb_assessment_result_msg_t public;
+
+ /**
+ * PB-TNC message type
+ */
+ pb_tnc_msg_type_t type;
+
+ /**
+ * Assessment result code
+ */
+ u_int32_t assessment_result;
+
+ /**
+ * Encoded message
+ */
+ chunk_t encoding;
+};
+
+METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t,
+ private_pb_assessment_result_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
+ private_pb_assessment_result_msg_t *this)
+{
+ return this->encoding;
+}
+
+METHOD(pb_tnc_msg_t, build, void,
+ private_pb_assessment_result_msg_t *this)
+{
+ tls_writer_t *writer;
+
+ /* build message */
+ writer = tls_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);
+}
+
+METHOD(pb_tnc_msg_t, process, status_t,
+ private_pb_assessment_result_msg_t *this, u_int32_t *offset)
+{
+ tls_reader_t *reader;
+
+ /* process message */
+ reader = tls_reader_create(this->encoding);
+ reader->read_uint32(reader, &this->assessment_result);
+ reader->destroy(reader);
+
+ if (this->assessment_result < TNC_IMV_EVALUATION_RESULT_COMPLIANT ||
+ this->assessment_result > TNC_IMV_EVALUATION_RESULT_DONT_KNOW)
+ {
+ DBG1(DBG_TNC, "invalid assessment result (%u)",
+ this->assessment_result);
+ *offset = 0;
+ return FAILED;
+ }
+
+ return SUCCESS;
+}
+
+METHOD(pb_tnc_msg_t, destroy, void,
+ private_pb_assessment_result_msg_t *this)
+{
+ free(this->encoding.ptr);
+ free(this);
+}
+
+METHOD(pb_assessment_result_msg_t, get_assessment_result, u_int32_t,
+ private_pb_assessment_result_msg_t *this)
+{
+ return this->assessment_result;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_assessment_result_msg_create_from_data(chunk_t data)
+{
+ private_pb_assessment_result_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ .get_assessment_result = _get_assessment_result,
+ },
+ .type = PB_MSG_ASSESSMENT_RESULT,
+ .encoding = chunk_clone(data),
+ );
+
+ return &this->public.pb_interface;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_assessment_result_msg_create(u_int32_t assessment_result)
+{
+ private_pb_assessment_result_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ .get_assessment_result = _get_assessment_result,
+ },
+ .type = PB_MSG_ASSESSMENT_RESULT,
+ .assessment_result = assessment_result,
+ );
+
+ return &this->public.pb_interface;
+}
diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_assessment_result_msg.h b/src/libcharon/plugins/tnccs_20/messages/pb_assessment_result_msg.h
new file mode 100644
index 000000000..d2b005114
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_20/messages/pb_assessment_result_msg.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2010 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pb_assessment_result_msg pb_assessment_result_msg
+ * @{ @ingroup tnccs_20
+ */
+
+#ifndef PB_ASSESSMENT_RESULT_MSG_H_
+#define PB_ASSESSMENT_RESULT_MSG_H_
+
+typedef struct pb_assessment_result_msg_t pb_assessment_result_msg_t;
+
+#include "pb_tnc_msg.h"
+
+/**
+ * Class representing the PB-Assessment-Result message type.
+ */
+struct pb_assessment_result_msg_t {
+
+ /**
+ * PB-TNC Message interface
+ */
+ pb_tnc_msg_t pb_interface;
+
+ /**
+ * Get PB Assessment result
+ *
+ * @return PB Assessment result
+ */
+ u_int32_t (*get_assessment_result)(pb_assessment_result_msg_t *this);
+};
+
+/**
+ * Create a PB-Assessment-Result message from parameters
+ *
+ * @param assessment_result Assessment result code
+ */
+pb_tnc_msg_t* pb_assessment_result_msg_create(u_int32_t assessment_result);
+
+/**
+ * Create an unprocessed PB-Assessment-Result message from raw data
+ *
+ * @param data PB-Assessment-Result message data
+ */
+pb_tnc_msg_t* pb_assessment_result_msg_create_from_data(chunk_t data);
+
+#endif /** PB_PA_MSG_H_ @}*/
diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_error_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_error_msg.c
new file mode 100644
index 000000000..e1755c512
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_20/messages/pb_error_msg.c
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2010 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pb_error_msg.h"
+
+#include <debug.h>
+#include <tls_writer.h>
+#include <tls_reader.h>
+#include <tnc/tnccs/tnccs.h>
+
+ENUM(pb_tnc_error_code_names, PB_ERROR_UNEXPECTED_BATCH_TYPE,
+ PB_ERROR_VERSION_NOT_SUPPORTED,
+ "Unexpected Batch Type",
+ "Invalid Parameter",
+ "Local Error",
+ "Unsupported Mandatory Message",
+ "Version Not Supported"
+);
+
+typedef struct private_pb_error_msg_t private_pb_error_msg_t;
+
+/**
+ * PB-Error message (see section 4.9 of RFC 5793)
+ *
+ * 0 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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Flags | Error Code Vendor ID |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Error Code | Reserved |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Error Parameters (Variable Length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define ERROR_FLAG_NONE 0x00
+#define ERROR_FLAG_FATAL (1<<7)
+#define ERROR_RESERVED 0x0000
+#define ERROR_HEADER_SIZE 8
+
+/**
+ * Private data of a pb_error_msg_t object.
+ *
+ */
+struct private_pb_error_msg_t {
+ /**
+ * Public pb_error_msg_t interface.
+ */
+ pb_error_msg_t public;
+
+ /**
+ * PB-TNC message type
+ */
+ pb_tnc_msg_type_t type;
+
+ /**
+ * Fatal flag
+ */
+ bool fatal;
+
+ /**
+ * PB Error Code Vendor ID
+ */
+ u_int32_t vendor_id;
+
+ /**
+ * PB Error Code
+ */
+ u_int16_t error_code;
+
+ /**
+ * PB Error Offset
+ */
+ u_int32_t error_offset;
+
+ /**
+ * Bad PB-TNC version received
+ */
+ u_int8_t bad_version;
+
+ /**
+ * Encoded message
+ */
+ chunk_t encoding;
+
+ /**
+ * reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t,
+ private_pb_error_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
+ private_pb_error_msg_t *this)
+{
+ return this->encoding;
+}
+
+METHOD(pb_tnc_msg_t, build, void,
+ private_pb_error_msg_t *this)
+{
+ tls_writer_t *writer;
+
+ /* build message header */
+ writer = tls_writer_create(ERROR_HEADER_SIZE);
+ writer->write_uint8 (writer, this->fatal ?
+ ERROR_FLAG_FATAL : ERROR_FLAG_NONE);
+ writer->write_uint24(writer, this->vendor_id);
+ writer->write_uint16(writer, this->error_code);
+ writer->write_uint16(writer, ERROR_RESERVED);
+
+ /* build message body */
+ if (this->error_code == PB_ERROR_VERSION_NOT_SUPPORTED)
+ {
+ /* Bad version */
+ writer->write_uint8(writer, this->bad_version);
+ writer->write_uint8(writer, PB_TNC_VERSION); /* Max version */
+ writer->write_uint8(writer, PB_TNC_VERSION); /* Min version */
+ writer->write_uint8(writer, 0x00); /* Reserved */
+ }
+ else
+ {
+ /* 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);
+}
+
+METHOD(pb_tnc_msg_t, process, status_t,
+ private_pb_error_msg_t *this, u_int32_t *offset)
+{
+ u_int8_t flags, max_version, min_version;
+ u_int16_t reserved;
+ tls_reader_t *reader;
+
+ if (this->encoding.len < ERROR_HEADER_SIZE)
+ {
+ DBG1(DBG_TNC,"%N message is shorter than header size of %u bytes",
+ pb_tnc_msg_type_names, PB_MSG_ERROR, ERROR_HEADER_SIZE);
+ return FAILED;
+ }
+
+ /* process message header */
+ reader = tls_reader_create(this->encoding);
+ reader->read_uint8 (reader, &flags);
+ reader->read_uint24(reader, &this->vendor_id);
+ reader->read_uint16(reader, &this->error_code);
+ reader->read_uint16(reader, &reserved);
+ this->fatal = (flags & ERROR_FLAG_FATAL) != ERROR_FLAG_NONE;
+
+ if (this->vendor_id == IETF_VENDOR_ID && reader->remaining(reader) == 4)
+ {
+ if (this->error_code == PB_ERROR_VERSION_NOT_SUPPORTED)
+ {
+ reader->read_uint8(reader, &this->bad_version);
+ reader->read_uint8(reader, &max_version);
+ reader->read_uint8(reader, &min_version);
+ }
+ else
+ {
+ reader->read_uint32(reader, &this->error_offset);
+ }
+ }
+ reader->destroy(reader);
+
+ return SUCCESS;
+}
+
+METHOD(pb_tnc_msg_t, get_ref, pb_tnc_msg_t*,
+ private_pb_error_msg_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pb_interface;
+}
+
+METHOD(pb_tnc_msg_t, destroy, void,
+ private_pb_error_msg_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->encoding.ptr);
+ free(this);
+ }
+}
+
+METHOD(pb_error_msg_t, get_fatal_flag, bool,
+ private_pb_error_msg_t *this)
+{
+ return this->fatal;
+}
+
+METHOD(pb_error_msg_t, get_vendor_id, u_int32_t,
+ private_pb_error_msg_t *this)
+{
+ return this->vendor_id;
+}
+
+METHOD(pb_error_msg_t, get_error_code, u_int16_t,
+ private_pb_error_msg_t *this)
+{
+ return this->error_code;
+}
+
+METHOD(pb_error_msg_t, get_offset, u_int32_t,
+ private_pb_error_msg_t *this)
+{
+ return this->error_offset;
+}
+
+METHOD(pb_error_msg_t, get_bad_version, u_int8_t,
+ private_pb_error_msg_t *this)
+{
+ return this->bad_version;
+}
+
+METHOD(pb_error_msg_t, set_bad_version, void,
+ private_pb_error_msg_t *this, u_int8_t version)
+{
+ this->bad_version = version;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t* pb_error_msg_create(bool fatal, u_int32_t vendor_id,
+ pb_tnc_error_code_t error_code)
+{
+ private_pb_error_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_fatal_flag = _get_fatal_flag,
+ .get_vendor_id = _get_vendor_id,
+ .get_error_code = _get_error_code,
+ .get_offset = _get_offset,
+ .get_bad_version = _get_bad_version,
+ .set_bad_version = _set_bad_version,
+ },
+ .type = PB_MSG_ERROR,
+ .ref = 1,
+ .fatal = fatal,
+ .vendor_id = vendor_id,
+ .error_code = error_code,
+ );
+
+ return &this->public.pb_interface;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t* pb_error_msg_create_with_offset(bool fatal, u_int32_t vendor_id,
+ pb_tnc_error_code_t error_code,
+ u_int32_t error_offset)
+{
+ private_pb_error_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_fatal_flag = _get_fatal_flag,
+ .get_vendor_id = _get_vendor_id,
+ .get_error_code = _get_error_code,
+ .get_offset = _get_offset,
+ .get_bad_version = _get_bad_version,
+ .set_bad_version = _set_bad_version,
+ },
+ .type = PB_MSG_ERROR,
+ .ref = 1,
+ .fatal = fatal,
+ .vendor_id = vendor_id,
+ .error_code = error_code,
+ .error_offset = error_offset,
+ );
+
+ return &this->public.pb_interface;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_error_msg_create_from_data(chunk_t data)
+{
+ private_pb_error_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_fatal_flag = _get_fatal_flag,
+ .get_vendor_id = _get_vendor_id,
+ .get_error_code = _get_error_code,
+ .get_offset = _get_offset,
+ .get_bad_version = _get_bad_version,
+ .set_bad_version = _set_bad_version,
+ },
+ .type = PB_MSG_ERROR,
+ .ref = 1,
+ .encoding = chunk_clone(data),
+ );
+
+ return &this->public.pb_interface;
+}
+
diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_error_msg.h b/src/libcharon/plugins/tnccs_20/messages/pb_error_msg.h
new file mode 100644
index 000000000..8b92742b5
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_20/messages/pb_error_msg.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2010 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pb_error_msg pb_error_msg
+ * @{ @ingroup tnccs_20
+ */
+
+#ifndef PB_ERROR_MSG_H_
+#define PB_ERROR_MSG_H_
+
+typedef enum pb_tnc_error_code_t pb_tnc_error_code_t;
+typedef struct pb_error_msg_t pb_error_msg_t;
+
+#include "pb_tnc_msg.h"
+
+/**
+ * PB-TNC Error Codes as defined in section 4.9.1 of RFC 5793
+ */
+enum pb_tnc_error_code_t {
+ PB_ERROR_UNEXPECTED_BATCH_TYPE = 0,
+ PB_ERROR_INVALID_PARAMETER = 1,
+ PB_ERROR_LOCAL_ERROR = 2,
+ PB_ERROR_UNSUPPORTED_MANDATORY_MSG = 3,
+ PB_ERROR_VERSION_NOT_SUPPORTED = 4
+};
+
+/**
+ * enum name for pb_tnc_error_code_t.
+ */
+extern enum_name_t *pb_tnc_error_code_names;
+
+/**
+ * Class representing the PB-Error message type.
+ */
+struct pb_error_msg_t {
+
+ /**
+ * PB-TNC Message interface
+ */
+ pb_tnc_msg_t pb_interface;
+
+ /**
+ * Get the fatal flag
+ *
+ * @return fatal flag
+ */
+ bool (*get_fatal_flag)(pb_error_msg_t *this);
+
+ /**
+ * Get PB Error code Vendor ID
+ *
+ * @return PB Error Code Vendor ID
+ */
+ u_int32_t (*get_vendor_id)(pb_error_msg_t *this);
+
+ /**
+ * Get PB Error Code
+ *
+ * @return PB Error Code
+ */
+ u_int16_t (*get_error_code)(pb_error_msg_t *this);
+
+ /**
+ * Get the PB Error Offset
+ *
+ * @return PB Error Offset
+ */
+ u_int32_t (*get_offset)(pb_error_msg_t *this);
+
+ /**
+ * Get the PB Bad Version
+ *
+ * @return PB Bad Version
+ */
+ u_int8_t (*get_bad_version)(pb_error_msg_t *this);
+
+ /**
+ * Set the PB Bad Version
+ *
+ * @param version PB Bad Version
+ */
+ void (*set_bad_version)(pb_error_msg_t *this, u_int8_t version);
+};
+
+/**
+ * Create a PB-Error message from parameters
+ *
+ * @param fatal fatal flag
+ * @param vendor_id Error Code Vendor ID
+ * @param error_code Error Code
+ */
+pb_tnc_msg_t* pb_error_msg_create(bool fatal, u_int32_t vendor_id,
+ pb_tnc_error_code_t error_code);
+
+/**
+ * Create a PB-Error message from parameters with offset field
+ *
+ * @param fatal fatal flag
+ * @param vendor_id Error Code Vendor ID
+ * @param error_code Error Code
+ * @param error_offset Error Offset
+ */
+pb_tnc_msg_t* pb_error_msg_create_with_offset(bool fatal, u_int32_t vendor_id,
+ pb_tnc_error_code_t error_code,
+ u_int32_t error_offset);
+
+/**
+ * Create an unprocessed PB-Error message from raw data
+ *
+ * @param data PB-Error message data
+ */
+pb_tnc_msg_t* pb_error_msg_create_from_data(chunk_t data);
+
+#endif /** PB_PA_MSG_H_ @}*/
diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_experimental_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_experimental_msg.c
new file mode 100644
index 000000000..7dfba136f
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_20/messages/pb_experimental_msg.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pb_experimental_msg.h"
+
+typedef struct private_pb_experimental_msg_t private_pb_experimental_msg_t;
+
+/**
+ * Private data of a pb_experimental_msg_t object.
+ *
+ */
+struct private_pb_experimental_msg_t {
+ /**
+ * Public pb_experimental_msg_t interface.
+ */
+ pb_experimental_msg_t public;
+
+ /**
+ * PB-TNC message type
+ */
+ pb_tnc_msg_type_t type;
+
+ /**
+ * Encoded message
+ */
+ chunk_t encoding;
+};
+
+METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t,
+ private_pb_experimental_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
+ private_pb_experimental_msg_t *this)
+{
+ return this->encoding;
+}
+
+METHOD(pb_tnc_msg_t, build, void,
+ private_pb_experimental_msg_t *this)
+{
+ /* nothing to do since message contents equal encoding */
+}
+
+METHOD(pb_tnc_msg_t, process, status_t,
+ private_pb_experimental_msg_t *this, u_int32_t *offset)
+{
+ return SUCCESS;
+}
+
+METHOD(pb_tnc_msg_t, destroy, void,
+ private_pb_experimental_msg_t *this)
+{
+ free(this->encoding.ptr);
+ free(this);
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_experimental_msg_create_from_data(chunk_t data)
+{
+ private_pb_experimental_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ },
+ .type = PB_MSG_EXPERIMENTAL,
+ .encoding = chunk_clone(data),
+ );
+
+ return &this->public.pb_interface;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_experimental_msg_create(chunk_t body)
+{
+ return pb_experimental_msg_create_from_data(body);
+}
diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_experimental_msg.h b/src/libcharon/plugins/tnccs_20/messages/pb_experimental_msg.h
new file mode 100644
index 000000000..b1cc4f46e
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_20/messages/pb_experimental_msg.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2010 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pb_experimental_msg pb_experimental_msg
+ * @{ @ingroup tnccs_20
+ */
+
+#ifndef PB_EXPERIMENTAL_MSG_H_
+#define PB_EXPERIMENTAL_MSG_H_
+
+typedef struct pb_experimental_msg_t pb_experimental_msg_t;
+
+#include "pb_tnc_msg.h"
+
+/**
+ * Class representing the PB-Experimental message type.
+ */
+struct pb_experimental_msg_t {
+
+ /**
+ * PB-TNC Message interface
+ */
+ pb_tnc_msg_t pb_interface;
+};
+
+/**
+ * Create a PB-Experimental message from parameters
+ *
+ * @param body message body
+ */
+pb_tnc_msg_t* pb_experimental_msg_create(chunk_t body);
+
+/**
+ * Create an unprocessed PB-Experimental message from raw data
+ *
+ * @param data PB-Experimental message data
+ */
+pb_tnc_msg_t* pb_experimental_msg_create_from_data(chunk_t data);
+
+#endif /** PB_EXPERIMENTAL_MSG_H_ @}*/
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
new file mode 100644
index 000000000..9a94edf30
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_20/messages/pb_language_preference_msg.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2010 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pb_language_preference_msg.h"
+
+#include <tls_writer.h>
+#include <tls_reader.h>
+#include <debug.h>
+
+typedef struct private_pb_language_preference_msg_t private_pb_language_preference_msg_t;
+
+/**
+ * PB-Language-Preference message (see section 4.10 of RFC 5793)
+ *
+ * 0 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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Language Preference (Variable Length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define PB_LANG_PREFIX "Accept-Language: "
+#define PB_LANG_PREFIX_LEN strlen(PB_LANG_PREFIX)
+
+/**
+ * Private data of a pb_language_preference_msg_t object.
+ *
+ */
+struct private_pb_language_preference_msg_t {
+ /**
+ * Public pb_access_recommendation_msg_t interface.
+ */
+ pb_language_preference_msg_t public;
+
+ /**
+ * PB-TNC message type
+ */
+ pb_tnc_msg_type_t type;
+
+ /**
+ * Language preference
+ */
+ chunk_t language_preference;
+
+ /**
+ * Encoded message
+ */
+ chunk_t encoding;
+};
+
+METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t,
+ private_pb_language_preference_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
+ private_pb_language_preference_msg_t *this)
+{
+ return this->encoding;
+}
+
+METHOD(pb_tnc_msg_t, build, void,
+ private_pb_language_preference_msg_t *this)
+{
+ this->encoding = chunk_cat("cc",
+ chunk_create(PB_LANG_PREFIX, PB_LANG_PREFIX_LEN),
+ this->language_preference);
+}
+
+METHOD(pb_tnc_msg_t, process, status_t,
+ private_pb_language_preference_msg_t *this, u_int32_t *offset)
+{
+ chunk_t lang;
+
+ if (this->encoding.len >= PB_LANG_PREFIX_LEN &&
+ memeq(this->encoding.ptr, PB_LANG_PREFIX, PB_LANG_PREFIX_LEN))
+ {
+ lang = chunk_skip(this->encoding, PB_LANG_PREFIX_LEN);
+ this->language_preference = lang.len ? chunk_clone(lang) : chunk_empty;
+ }
+ else
+ {
+ DBG1(DBG_TNC, "language preference must be preceded by '%s'",
+ PB_LANG_PREFIX);
+ *offset = 0;
+ return FAILED;
+ }
+
+ if (this->language_preference.len &&
+ this->language_preference.ptr[this->language_preference.len-1] == '\0')
+ {
+ DBG1(DBG_TNC, "language preference must not be null terminated");
+ *offset = PB_LANG_PREFIX_LEN + this->language_preference.len - 1;
+ return FAILED;
+ }
+
+ return SUCCESS;
+}
+
+METHOD(pb_tnc_msg_t, destroy, void,
+ private_pb_language_preference_msg_t *this)
+{
+ free(this->encoding.ptr);
+ free(this->language_preference.ptr);
+ free(this);
+}
+
+METHOD(pb_language_preference_msg_t, get_language_preference, chunk_t,
+ private_pb_language_preference_msg_t *this)
+{
+ return this->language_preference;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_language_preference_msg_create_from_data(chunk_t data)
+{
+ private_pb_language_preference_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ .get_language_preference = _get_language_preference,
+ },
+ .type = PB_MSG_LANGUAGE_PREFERENCE,
+ .encoding = chunk_clone(data),
+ );
+
+ return &this->public.pb_interface;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_language_preference_msg_create(chunk_t language_preference)
+{
+ private_pb_language_preference_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ .get_language_preference = _get_language_preference,
+ },
+ .type = PB_MSG_LANGUAGE_PREFERENCE,
+ .language_preference = chunk_clone(language_preference),
+ );
+
+ return &this->public.pb_interface;
+}
diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_language_preference_msg.h b/src/libcharon/plugins/tnccs_20/messages/pb_language_preference_msg.h
new file mode 100644
index 000000000..17106f6fa
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_20/messages/pb_language_preference_msg.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2010 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pb_language_preference_msg pb_language_preference_msg
+ * @{ @ingroup tnccs_20
+ */
+
+#ifndef PB_LANGUAGE_PREFERENCE_MSG_H_
+#define PB_LANGUAGE_PREFERENCE_MSG_H_
+
+typedef struct pb_language_preference_msg_t pb_language_preference_msg_t;
+
+#include "pb_tnc_msg.h"
+
+/**
+ * Class representing the PB-Language-Preference message type.
+ */
+struct pb_language_preference_msg_t {
+
+ /**
+ * PB-TNC Message interface
+ */
+ pb_tnc_msg_t pb_interface;
+
+ /**
+ * Get PB Language Preference
+ *
+ * @return Language preference
+ */
+ chunk_t (*get_language_preference)(pb_language_preference_msg_t *this);
+};
+
+/**
+ * Create a PB-Language-Preference message from parameters
+ *
+ * @param language_preference Preferred language(s)
+ */
+pb_tnc_msg_t* pb_language_preference_msg_create(chunk_t language_preference);
+
+/**
+ * Create an unprocessed PB-Language-Preference message from raw data
+ *
+ * @param data PB-Language-Preference message data
+ */
+pb_tnc_msg_t* pb_language_preference_msg_create_from_data(chunk_t data);
+
+#endif /** PB_PA_MSG_H_ @}*/
diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.c
new file mode 100644
index 000000000..8315bfb76
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.c
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2010 Sansar Choinyanbuu
+ * Copyright (C) 2010 Andreas Steffen
+ *
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pb_pa_msg.h"
+
+#include <tls_writer.h>
+#include <tls_reader.h>
+#include <tnc/tnccs/tnccs.h>
+#include <debug.h>
+
+ENUM(pa_tnc_subtype_names, PA_SUBTYPE_TESTING, PA_SUBTYPE_NEA_CLIENT,
+ "Testing",
+ "Operating System",
+ "Anti-Virus",
+ "Anti-Spyware",
+ "Anti-Malware",
+ "Firewall",
+ "IDPS",
+ "VPN",
+ "NEA Client"
+);
+
+typedef struct private_pb_pa_msg_t private_pb_pa_msg_t;
+
+/**
+ * PB-PA message
+ *
+ * 0 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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Flags | PA Message Vendor ID |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | PA Subtype |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Posture Collector Identifier | Posture Validator Identifier |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | PA Message Body (Variable Length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define PA_FLAG_NONE 0x00
+#define PA_FLAG_EXCL (1<<7)
+#define PA_RESERVED_SUBTYPE 0xffffffff
+
+
+/**
+ * Private data of a pb_pa_msg_t object.
+ *
+ */
+struct private_pb_pa_msg_t {
+ /**
+ * Public pb_pa_msg_t interface.
+ */
+ pb_pa_msg_t public;
+
+ /**
+ * PB-TNC message type
+ */
+ pb_tnc_msg_type_t type;
+
+ /**
+ * Exclusive flag
+ */
+ bool excl;
+
+ /**
+ * PA Message Vendor ID
+ */
+ u_int32_t vendor_id;
+
+ /**
+ * PA Subtype
+ */
+ u_int32_t subtype;
+
+ /**
+ * Posture Validator Identifier
+ */
+ u_int16_t collector_id;
+
+ /**
+ * Posture Validator Identifier
+ */
+ u_int16_t validator_id;
+
+ /**
+ * PA Message Body
+ */
+ chunk_t msg_body;
+
+ /**
+ * Encoded message
+ */
+ chunk_t encoding;
+};
+
+METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t,
+ private_pb_pa_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
+ private_pb_pa_msg_t *this)
+{
+ return this->encoding;
+}
+
+METHOD(pb_tnc_msg_t, build, void,
+ private_pb_pa_msg_t *this)
+{
+ chunk_t msg_header;
+ tls_writer_t *writer;
+
+ /* build message header */
+ writer = tls_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_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);
+}
+
+METHOD(pb_tnc_msg_t, process, status_t,
+ private_pb_pa_msg_t *this, u_int32_t *offset)
+{
+ u_int8_t flags;
+ size_t msg_body_len;
+ tls_reader_t *reader;
+
+ /* process message header */
+ reader = tls_reader_create(this->encoding);
+ reader->read_uint8 (reader, &flags);
+ reader->read_uint24(reader, &this->vendor_id);
+ reader->read_uint32(reader, &this->subtype);
+ reader->read_uint16(reader, &this->collector_id);
+ reader->read_uint16(reader, &this->validator_id);
+ this->excl = ((flags & PA_FLAG_EXCL) != PA_FLAG_NONE);
+
+ /* process message body */
+ msg_body_len = reader->remaining(reader);
+ if (msg_body_len)
+ {
+ reader->read_data(reader, msg_body_len, &this->msg_body);
+ this->msg_body = chunk_clone(this->msg_body);
+ }
+ reader->destroy(reader);
+
+ if (this->vendor_id == RESERVED_VENDOR_ID)
+ {
+ DBG1(DBG_TNC, "Vendor ID 0x%06x is reserved", RESERVED_VENDOR_ID);
+ *offset = 1;
+ return FAILED;
+ }
+
+ if (this->subtype == PA_RESERVED_SUBTYPE)
+ {
+ DBG1(DBG_TNC, "PA Subtype 0x%08x is reserved", PA_RESERVED_SUBTYPE);
+ *offset = 4;
+ }
+
+ return SUCCESS;
+}
+
+METHOD(pb_tnc_msg_t, destroy, void,
+ private_pb_pa_msg_t *this)
+{
+ free(this->encoding.ptr);
+ free(this->msg_body.ptr);
+ free(this);
+}
+
+METHOD(pb_pa_msg_t, get_vendor_id, u_int32_t,
+ private_pb_pa_msg_t *this, u_int32_t *subtype)
+{
+ *subtype = this->subtype;
+ return this->vendor_id;
+}
+
+METHOD(pb_pa_msg_t, get_collector_id, u_int16_t,
+ private_pb_pa_msg_t *this)
+{
+ return this->collector_id;
+}
+
+METHOD(pb_pa_msg_t, get_validator_id, u_int16_t,
+ private_pb_pa_msg_t *this)
+{
+ return this->validator_id;
+}
+
+METHOD(pb_pa_msg_t, get_body, chunk_t,
+ private_pb_pa_msg_t *this)
+{
+ return this->msg_body;
+}
+
+METHOD(pb_pa_msg_t, get_exclusive_flag, bool,
+ private_pb_pa_msg_t *this)
+{
+ return this->excl;
+}
+
+METHOD(pb_pa_msg_t, set_exclusive_flag, void,
+ private_pb_pa_msg_t *this, bool excl)
+{
+ this->excl = excl;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_pa_msg_create_from_data(chunk_t data)
+{
+ private_pb_pa_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ .get_vendor_id = _get_vendor_id,
+ .get_collector_id = _get_collector_id,
+ .get_validator_id = _get_validator_id,
+ .get_body = _get_body,
+ .get_exclusive_flag = _get_exclusive_flag,
+ .set_exclusive_flag = _set_exclusive_flag,
+ },
+ .type = PB_MSG_PA,
+ .encoding = chunk_clone(data),
+ );
+
+ return &this->public.pb_interface;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_pa_msg_create(u_int32_t vendor_id, u_int32_t subtype,
+ u_int16_t collector_id, u_int16_t validator_id,
+ chunk_t msg_body)
+{
+ private_pb_pa_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ .get_vendor_id = _get_vendor_id,
+ .get_collector_id = _get_collector_id,
+ .get_validator_id = _get_validator_id,
+ .get_body = _get_body,
+ .get_exclusive_flag = _get_exclusive_flag,
+ .set_exclusive_flag = _set_exclusive_flag,
+ },
+ .type = PB_MSG_PA,
+ .vendor_id = vendor_id,
+ .subtype = subtype,
+ .collector_id = collector_id,
+ .validator_id = validator_id,
+ .msg_body = chunk_clone(msg_body),
+ );
+
+ return &this->public.pb_interface;
+}
diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.h b/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.h
new file mode 100644
index 000000000..366d790f6
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pb_pa_msg pb_pa_msg
+ * @{ @ingroup tnccs_20
+ */
+
+#ifndef PB_PA_MSG_H_
+#define PB_PA_MSG_H_
+
+typedef enum pa_tnc_subtype_t pa_tnc_subtype_t;
+typedef struct pb_pa_msg_t pb_pa_msg_t;
+
+#include "pb_tnc_msg.h"
+
+/**
+ * PA-TNC Subtypes as defined in section 3.5 of RFC 5792
+ */
+ enum pa_tnc_subtype_t {
+ PA_SUBTYPE_TESTING = 0,
+ PA_SUBTYPE_OPERATING_SYSTEM = 1,
+ PA_SUBTYPE_ANTI_VIRUS = 2,
+ PA_SUBTYPE_ANTI_SPYWARE = 3,
+ PA_SUBTYPE_ANTI_MALWARE = 4,
+ PA_SUBTYPE_FIREWALL = 5,
+ PA_SUBTYPE_IDPS = 6,
+ PA_SUBTYPE_VPN = 7,
+ PA_SUBTYPE_NEA_CLIENT = 8
+};
+
+/**
+ * enum name for pa_tnc_subtype_t.
+ */
+extern enum_name_t *pa_tnc_subtype_names;
+
+/**
+ * Class representing the PB-PA message type.
+ */
+struct pb_pa_msg_t {
+
+ /**
+ * PB-TNC Message interface
+ */
+ pb_tnc_msg_t pb_interface;
+
+ /**
+ * Get PA Message Vendor ID and Subtype
+ *
+ * @param subtype PA Subtype
+ * @return PA Message Vendor ID
+ */
+ u_int32_t (*get_vendor_id)(pb_pa_msg_t *this, u_int32_t *subtype);
+
+ /**
+ * Get Posture Collector ID
+ *
+ * @return Posture Collector ID
+ */
+ u_int16_t (*get_collector_id)(pb_pa_msg_t *this);
+
+ /**
+ * Get Posture Validator ID
+ *
+ * @return Posture Validator ID
+ */
+ u_int16_t (*get_validator_id)(pb_pa_msg_t *this);
+
+ /**
+ * Get the PA Message Body
+ *
+ * @return PA Message Body
+ */
+ chunk_t (*get_body)(pb_pa_msg_t *this);
+
+ /**
+ * Get the exclusive flag
+ *
+ * @return exclusive flag
+ */
+ bool (*get_exclusive_flag)(pb_pa_msg_t *this);
+
+ /**
+ * Set the exclusive flag
+ *
+ * @param excl vexclusive flag
+ */
+ void (*set_exclusive_flag)(pb_pa_msg_t *this, bool excl);
+};
+
+/**
+ * Create a PB-PA message from parameters
+ *
+ * @param vendor_id PA Message Vendor ID
+ * @param subtype PA Subtype
+ * @param collector_id Posture Collector ID
+ * @param validator_id Posture Validator ID
+ * @param msg_body PA Message Body
+ */
+pb_tnc_msg_t *pb_pa_msg_create(u_int32_t vendor_id, u_int32_t subtype,
+ u_int16_t collector_id, u_int16_t validator_id,
+ chunk_t msg_body);
+
+/**
+ * Create an unprocessed PB-PA message from raw data
+ *
+ * @param data PB-PA message data
+ */
+pb_tnc_msg_t* pb_pa_msg_create_from_data(chunk_t data);
+
+#endif /** PB_PA_MSG_H_ @}*/
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
new file mode 100644
index 000000000..e361cf2b2
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_20/messages/pb_reason_string_msg.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2010 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pb_reason_string_msg.h"
+
+#include <tls_writer.h>
+#include <tls_reader.h>
+#include <debug.h>
+
+typedef struct private_pb_reason_string_msg_t private_pb_reason_string_msg_t;
+
+/**
+ * PB-Language-Preference message (see section 4.11 of RFC 5793)
+ *
+ * 0 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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Reason String Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Reason String (Variable Length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Lang Code Len | Reason String Language Code (Variable Length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+/**
+ * Private data of a pb_reason_string_msg_t object.
+ *
+ */
+struct private_pb_reason_string_msg_t {
+ /**
+ * Public pb_reason_string_msg_t interface.
+ */
+ pb_reason_string_msg_t public;
+
+ /**
+ * PB-TNC message type
+ */
+ pb_tnc_msg_type_t type;
+
+ /**
+ * Reason string
+ */
+ chunk_t reason_string;
+
+ /**
+ * Language code
+ */
+ chunk_t language_code;
+
+ /**
+ * Encoded message
+ */
+ chunk_t encoding;
+};
+
+METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t,
+ private_pb_reason_string_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
+ private_pb_reason_string_msg_t *this)
+{
+ return this->encoding;
+}
+
+METHOD(pb_tnc_msg_t, build, void,
+ private_pb_reason_string_msg_t *this)
+{
+ tls_writer_t *writer;
+
+ /* build message */
+ writer = tls_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);
+}
+
+METHOD(pb_tnc_msg_t, process, status_t,
+ private_pb_reason_string_msg_t *this, u_int32_t *offset)
+{
+ tls_reader_t *reader;
+
+ /* process message */
+ reader = tls_reader_create(this->encoding);
+ if (!reader->read_data32(reader, &this->reason_string))
+ {
+ DBG1(DBG_TNC, "could not parse reason string");
+ reader->destroy(reader);
+ *offset = 0;
+ return FAILED;
+ };
+ this->reason_string = chunk_clone(this->reason_string);
+
+ if (this->reason_string.len &&
+ this->reason_string.ptr[this->reason_string.len-1] == '\0')
+ {
+ DBG1(DBG_TNC, "reason string must not be null terminated");
+ reader->destroy(reader);
+ *offset = 3 + this->reason_string.len;
+ return FAILED;
+ }
+
+ if (!reader->read_data8(reader, &this->language_code))
+ {
+ DBG1(DBG_TNC, "could not parse language code");
+ reader->destroy(reader);
+ *offset = 4 + this->reason_string.len;
+ return FAILED;
+ };
+ this->language_code = chunk_clone(this->language_code);
+ reader->destroy(reader);
+
+ if (this->language_code.len &&
+ this->language_code.ptr[this->language_code.len-1] == '\0')
+ {
+ DBG1(DBG_TNC, "language code must not be null terminated");
+ *offset = 4 + this->reason_string.len + this->language_code.len;
+ return FAILED;
+ }
+
+ return SUCCESS;
+}
+
+METHOD(pb_tnc_msg_t, destroy, void,
+ private_pb_reason_string_msg_t *this)
+{
+ free(this->encoding.ptr);
+ free(this->reason_string.ptr);
+ free(this->language_code.ptr);
+ free(this);
+}
+
+METHOD(pb_reason_string_msg_t, get_reason_string, chunk_t,
+ private_pb_reason_string_msg_t *this)
+{
+ return this->reason_string;
+}
+
+METHOD(pb_reason_string_msg_t, get_language_code, chunk_t,
+ private_pb_reason_string_msg_t *this)
+{
+ return this->language_code;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_reason_string_msg_create_from_data(chunk_t data)
+{
+ private_pb_reason_string_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ .get_reason_string = _get_reason_string,
+ .get_language_code = _get_language_code,
+ },
+ .type = PB_MSG_REASON_STRING,
+ .encoding = chunk_clone(data),
+ );
+
+ return &this->public.pb_interface;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_reason_string_msg_create(chunk_t reason_string,
+ chunk_t language_code)
+{
+ private_pb_reason_string_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ .get_reason_string = _get_reason_string,
+ .get_language_code = _get_language_code,
+ },
+ .type = PB_MSG_REASON_STRING,
+ .reason_string = chunk_clone(reason_string),
+ .language_code = chunk_clone(language_code),
+ );
+
+ return &this->public.pb_interface;
+}
diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_reason_string_msg.h b/src/libcharon/plugins/tnccs_20/messages/pb_reason_string_msg.h
new file mode 100644
index 000000000..bb296a90c
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_20/messages/pb_reason_string_msg.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2010 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pb_reason_string_msg pb_reason_string_msg
+ * @{ @ingroup tnccs_20
+ */
+
+#ifndef PB_REASON_STRING_MSG_H_
+#define PB_REASON_STRING_MSG_H_
+
+typedef struct pb_reason_string_msg_t pb_reason_string_msg_t;
+
+#include "pb_tnc_msg.h"
+
+/**
+ * Class representing the PB-Reason-String message type.
+ */
+struct pb_reason_string_msg_t {
+
+ /**
+ * PB-TNC Message interface
+ */
+ pb_tnc_msg_t pb_interface;
+
+ /**
+ * Get Reason String
+ *
+ * @return Reason string
+ */
+ chunk_t (*get_reason_string)(pb_reason_string_msg_t *this);
+
+ /**
+ * Get Reason String Language Code
+ *
+ * @return Language code
+ */
+ chunk_t (*get_language_code)(pb_reason_string_msg_t *this);
+};
+
+/**
+ * Create a PB-Reason-String message from parameters
+ *
+ * @param reason_string Reason string
+ * @param language_code Language code
+ */
+pb_tnc_msg_t* pb_reason_string_msg_create(chunk_t reason_string,
+ chunk_t language_code);
+
+/**
+ * Create an unprocessed PB-Reason-String message from raw data
+ *
+ * @param data PB-Reason-String message data
+ */
+pb_tnc_msg_t* pb_reason_string_msg_create_from_data(chunk_t data);
+
+#endif /** PB_PA_MSG_H_ @}*/
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
new file mode 100644
index 000000000..79381a7b1
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pb_remediation_parameters_msg.h"
+
+#include <tls_writer.h>
+#include <tls_reader.h>
+#include <debug.h>
+
+ENUM(pb_tnc_remed_param_type_names, PB_REMEDIATION_URI, PB_REMEDIATION_STRING,
+ "Remediation-URI",
+ "Remediation-String"
+);
+
+typedef struct private_pb_remediation_parameters_msg_t private_pb_remediation_parameters_msg_t;
+
+/**
+ * PB-Remediation-Parameters message (see section 4.8 of RFC 5793)
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Reserved | Remediation Parameters Vendor ID |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Remediation Parameters Type |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Remediation Parameters (Variable Length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * 0 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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Remediation String Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Remediation String (Variable Length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Lang Code Len | Remediation String Lang Code (Variable Len) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+/**
+ * Private data of a pb_remediation_parameters_msg_t object.
+ *
+ */
+struct private_pb_remediation_parameters_msg_t {
+ /**
+ * Public pb_remediation_parameters_msg_t interface.
+ */
+ pb_remediation_parameters_msg_t public;
+
+ /**
+ * PB-TNC message type
+ */
+ pb_tnc_msg_type_t type;
+
+ /**
+ * Remediation Parameters Vendor ID
+ */
+ u_int32_t vendor_id;
+
+ /**
+ * Remediation Parameters Type
+ */
+ u_int32_t parameters_type;
+
+ /**
+ * Remediation Parameters string
+ */
+ chunk_t remediation_string;
+
+ /**
+ * Language code
+ */
+ chunk_t language_code;
+
+ /**
+ * Encoded message
+ */
+ chunk_t encoding;
+};
+
+METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t,
+ private_pb_remediation_parameters_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
+ private_pb_remediation_parameters_msg_t *this)
+{
+ return this->encoding;
+}
+
+METHOD(pb_tnc_msg_t, build, void,
+ private_pb_remediation_parameters_msg_t *this)
+{
+ tls_writer_t *writer;
+
+ /* build message */
+ writer = tls_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);
+}
+
+METHOD(pb_tnc_msg_t, process, status_t,
+ private_pb_remediation_parameters_msg_t *this, u_int32_t *offset)
+{
+ tls_reader_t *reader;
+
+ /* process message */
+ reader = tls_reader_create(this->encoding);
+ reader->read_uint32(reader, &this->vendor_id);
+ reader->read_uint32(reader, &this->parameters_type);
+
+ if (!reader->read_data32(reader, &this->remediation_string))
+ {
+ DBG1(DBG_TNC, "could not parse remediation string");
+ reader->destroy(reader);
+ *offset = 8;
+ return FAILED;
+ };
+ this->remediation_string = chunk_clone(this->remediation_string);
+
+ if (this->remediation_string.len &&
+ this->remediation_string.ptr[this->remediation_string.len-1] == '\0')
+ {
+ DBG1(DBG_TNC, "remediation string must not be null terminated");
+ reader->destroy(reader);
+ *offset = 11 + this->remediation_string.len;
+ return FAILED;
+ }
+
+ if (!reader->read_data8(reader, &this->language_code))
+ {
+ DBG1(DBG_TNC, "could not parse language code");
+ reader->destroy(reader);
+ *offset = 12 + this->remediation_string.len;
+ return FAILED;
+ };
+ this->language_code = chunk_clone(this->language_code);
+ reader->destroy(reader);
+
+ if (this->language_code.len &&
+ this->language_code.ptr[this->language_code.len-1] == '\0')
+ {
+ DBG1(DBG_TNC, "language code must not be null terminated");
+ *offset = 12 + this->remediation_string.len + this->language_code.len;
+ return FAILED;
+ }
+
+ return SUCCESS;
+}
+
+METHOD(pb_tnc_msg_t, destroy, void,
+ private_pb_remediation_parameters_msg_t *this)
+{
+ free(this->encoding.ptr);
+ free(this->remediation_string.ptr);
+ free(this->language_code.ptr);
+ free(this);
+}
+
+METHOD(pb_remediation_parameters_msg_t, get_vendor_id, u_int32_t,
+ private_pb_remediation_parameters_msg_t *this, u_int32_t *type)
+{
+ *type = this->parameters_type;
+ return this->vendor_id;
+}
+
+METHOD(pb_remediation_parameters_msg_t, get_remediation_string, chunk_t,
+ private_pb_remediation_parameters_msg_t *this)
+{
+ return this->remediation_string;
+}
+
+METHOD(pb_remediation_parameters_msg_t, get_language_code, chunk_t,
+ private_pb_remediation_parameters_msg_t *this)
+{
+ return this->language_code;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_remediation_parameters_msg_create_from_data(chunk_t data)
+{
+ private_pb_remediation_parameters_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ .get_vendor_id = _get_vendor_id,
+ .get_remediation_string = _get_remediation_string,
+ .get_language_code = _get_language_code,
+ },
+ .type = PB_MSG_REASON_STRING,
+ .encoding = chunk_clone(data),
+ );
+
+ return &this->public.pb_interface;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t* pb_remediation_parameters_msg_create(u_int32_t vendor_id,
+ u_int32_t type,
+ chunk_t remediation_string,
+ chunk_t language_code)
+{
+ private_pb_remediation_parameters_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ .get_vendor_id = _get_vendor_id,
+ .get_remediation_string = _get_remediation_string,
+ .get_language_code = _get_language_code,
+ },
+ .type = PB_MSG_REASON_STRING,
+ .vendor_id = vendor_id,
+ .parameters_type = type,
+ .remediation_string = chunk_clone(remediation_string),
+ .language_code = chunk_clone(language_code),
+ );
+
+ return &this->public.pb_interface;
+}
diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.h b/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.h
new file mode 100644
index 000000000..258d495ec
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pb_remediation_parameters_msg pb_remediation_parameters_msg
+ * @{ @ingroup tnccs_20
+ */
+
+#ifndef PB_REMEDIATION_PARAMETERS_MSG_H_
+#define PB_REMEDIATION_PARAMETERS_MSG_H_
+
+typedef enum pb_tnc_remed_param_type_t pb_tnc_remed_param_type_t;
+typedef struct pb_remediation_parameters_msg_t pb_remediation_parameters_msg_t;
+
+#include "pb_tnc_msg.h"
+
+/**
+ * PB-TNC Remediation Parameter Types as defined in section 4.8.1 of RFC 5793
+ */
+enum pb_tnc_remed_param_type_t {
+ PB_REMEDIATION_URI = 1,
+ PB_REMEDIATION_STRING = 2,
+};
+
+/**
+ * enum name for pb_tnc_remed_param_type_t.
+ */
+extern enum_name_t *pb_tnc_remed_param_type_names;
+
+/**
+ * Class representing the PB-Remediation-Parameters message type.
+ */
+struct pb_remediation_parameters_msg_t {
+
+ /**
+ * PB-TNC Message interface
+ */
+ pb_tnc_msg_t pb_interface;
+
+ /**
+ * Get Remediation Parameters Vendor ID and Type
+ *
+ * @param type Remediation Parameters Type
+ * @return Remediation Parameters Vendor ID
+ */
+ u_int32_t (*get_vendor_id)(pb_remediation_parameters_msg_t *this,
+ u_int32_t *type);
+
+ /**
+ * Get Remediation String
+ *
+ * @return Remediation String
+ */
+ chunk_t (*get_remediation_string)(pb_remediation_parameters_msg_t *this);
+
+ /**
+ * Get Reason String Language Code
+ *
+ * @return Language Code
+ */
+ chunk_t (*get_language_code)(pb_remediation_parameters_msg_t *this);
+};
+
+/**
+ * Create a PB-Remediation-Parameters message from parameters
+ *
+ * @param vendor_id Remediation Parameters Vendor ID
+ * @param type Remediation Parameters Type
+ * @param remediation_string Remediation String
+ * @param language_code Language Code
+ */
+pb_tnc_msg_t* pb_remediation_parameters_msg_create(u_int32_t vendor_id,
+ u_int32_t type,
+ chunk_t remediation_string,
+ chunk_t language_code);
+
+/**
+ * Create an unprocessed PB-Remediation-Parameters message from raw data
+ *
+ * @param data PB-Remediation-Parameters message data
+ */
+pb_tnc_msg_t* pb_remediation_parameters_msg_create_from_data(chunk_t data);
+
+#endif /** PB_PA_MSG_H_ @}*/
diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_tnc_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_tnc_msg.c
new file mode 100644
index 000000000..3565c2d84
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_20/messages/pb_tnc_msg.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pb_tnc_msg.h"
+#include "pb_experimental_msg.h"
+#include "pb_pa_msg.h"
+#include "pb_error_msg.h"
+#include "pb_language_preference_msg.h"
+#include "pb_assessment_result_msg.h"
+#include "pb_access_recommendation_msg.h"
+#include "pb_remediation_parameters_msg.h"
+#include "pb_reason_string_msg.h"
+
+#include <library.h>
+
+ENUM(pb_tnc_msg_type_names, PB_MSG_EXPERIMENTAL, PB_MSG_REASON_STRING,
+ "PB-Experimental",
+ "PB-PA",
+ "PB-Assessment-Result",
+ "PB-Access-Recommendation",
+ "PB-Remediation-Parameters",
+ "PB-Error",
+ "PB-Language-Preference",
+ "PB-Reason-String"
+);
+
+pb_tnc_msg_info_t pb_tnc_msg_infos[] = {
+ { 12, FALSE, FALSE, TRUE_OR_FALSE },
+ { 24, FALSE, FALSE, TRUE },
+ { 16, TRUE, TRUE, TRUE },
+ { 16, TRUE, TRUE, FALSE },
+ { 20, FALSE, TRUE, FALSE },
+ { 20, FALSE, FALSE, TRUE },
+ { 12, FALSE, FALSE, FALSE },
+ { 17, FALSE, TRUE, FALSE },
+};
+
+/**
+ * See header
+ */
+pb_tnc_msg_t* pb_tnc_msg_create_from_data(pb_tnc_msg_type_t type, chunk_t value)
+{
+ switch (type)
+ {
+ case PB_MSG_PA:
+ return pb_pa_msg_create_from_data(value);
+ case PB_MSG_ERROR:
+ return pb_error_msg_create_from_data(value);
+ case PB_MSG_EXPERIMENTAL:
+ return pb_experimental_msg_create_from_data(value);
+ case PB_MSG_LANGUAGE_PREFERENCE:
+ return pb_language_preference_msg_create_from_data(value);
+ case PB_MSG_ASSESSMENT_RESULT:
+ return pb_assessment_result_msg_create_from_data(value);
+ case PB_MSG_ACCESS_RECOMMENDATION:
+ return pb_access_recommendation_msg_create_from_data(value);
+ case PB_MSG_REMEDIATION_PARAMETERS:
+ return pb_remediation_parameters_msg_create_from_data(value);
+ case PB_MSG_REASON_STRING:
+ return pb_reason_string_msg_create_from_data(value);
+ }
+ return NULL;
+}
diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_tnc_msg.h b/src/libcharon/plugins/tnccs_20/messages/pb_tnc_msg.h
new file mode 100644
index 000000000..e20c8d8ff
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_20/messages/pb_tnc_msg.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pb_tnc_msg pb_tnc_msg
+ * @{ @ingroup tnccs_20
+ */
+
+#ifndef PB_TNC_MSG_H_
+#define PB_TNC_MSG_H_
+
+typedef enum pb_tnc_msg_type_t pb_tnc_msg_type_t;
+typedef struct pb_tnc_msg_info_t pb_tnc_msg_info_t;
+typedef struct pb_tnc_msg_t pb_tnc_msg_t;
+
+#include <library.h>
+
+#define PB_TNC_VERSION 2
+
+/**
+ * PB-TNC Message Types as defined in section 4.3 of RFC 5793
+ */
+enum pb_tnc_msg_type_t {
+ PB_MSG_EXPERIMENTAL = 0,
+ PB_MSG_PA = 1,
+ PB_MSG_ASSESSMENT_RESULT = 2,
+ PB_MSG_ACCESS_RECOMMENDATION = 3,
+ PB_MSG_REMEDIATION_PARAMETERS = 4,
+ PB_MSG_ERROR = 5,
+ PB_MSG_LANGUAGE_PREFERENCE = 6,
+ PB_MSG_REASON_STRING = 7,
+ PB_MSG_ROOF = 7
+};
+
+/**
+ * enum name for pb_tnc_msg_type_t.
+ */
+extern enum_name_t *pb_tnc_msg_type_names;
+
+/**
+ * Information entry describing a PB-TNC Message Type
+ */
+struct pb_tnc_msg_info_t {
+ u_int32_t min_size;
+ bool exact_size;
+ bool in_result_batch;
+ bool has_noskip_flag;
+};
+
+#define TRUE_OR_FALSE 2
+
+/**
+ * Information on PB-TNC Message Types
+ */
+extern pb_tnc_msg_info_t pb_tnc_msg_infos[];
+
+/**
+ * Generic interface for all PB-TNC message types.
+ *
+ * To handle all messages in a generic way, this interface
+ * must be implemented by each message type.
+ */
+struct pb_tnc_msg_t {
+
+ /**
+ * Get the PB-TNC Message Type
+ *
+ * @return PB-TNC Message Type
+ */
+ pb_tnc_msg_type_t (*get_type)(pb_tnc_msg_t *this);
+
+ /**
+ * Get the encoding of the PB-TNC Message Value
+ *
+ * @return encoded PB-TNC Message Value
+ */
+ chunk_t (*get_encoding)(pb_tnc_msg_t *this);
+
+ /**
+ * Build the PB-TNC Message Value
+ */
+ void (*build)(pb_tnc_msg_t *this);
+
+ /**
+ * Process the PB-TNC Message Value
+ *
+ * @param relative offset where an error occurred
+ * @return return processing status
+ */
+ status_t (*process)(pb_tnc_msg_t *this, u_int32_t *offset);
+
+ /**
+ * Get a new reference to the message.
+ *
+ * @return this, with an increased refcount
+ */
+ pb_tnc_msg_t* (*get_ref)(pb_tnc_msg_t *this);
+
+ /**
+ * Destroys a pb_tnc_msg_t object.
+ */
+ void (*destroy)(pb_tnc_msg_t *this);
+};
+
+/**
+ * Create an unprocessed PB-TNC message
+ *
+ * Useful for the parser which wants a generic constructor for all
+ * pb_tnc_message_t types.
+ *
+ * @param type PB-TNC message type
+ * @param value PB-TNC message value
+ */
+pb_tnc_msg_t* pb_tnc_msg_create_from_data(pb_tnc_msg_type_t type, chunk_t value);
+
+#endif /** PB_TNC_MSG_H_ @}*/
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
new file mode 100644
index 000000000..a46dc0ab9
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.c
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pb_tnc_state_machine.h"
+
+#include <debug.h>
+
+ENUM(pb_tnc_state_names, PB_STATE_INIT, PB_STATE_END,
+ "Init",
+ "Server Working",
+ "Client Working",
+ "Decided",
+ "End"
+);
+
+/**
+ * PB-TNC State Machine (see section 3.2 of RFC 5793)
+ *
+ * Receive CRETRY SRETRY
+ * or SRETRY +----------------+
+ * +--+ | |
+ * v | v |
+ * +---------+ CRETRY +---------+
+ * CDATA | Server |<---------| Decided | CLOSE
+ * +----------->| Working |--------->| |-------+
+ * | +---------+ RESULT +---------+ |
+ * | ^ | | v
+ * | | | +---------------------->=======
+ * ======== | | CLOSE " End "
+ * " Init " CDATA| |SDATA =======
+ * ======== | | ^ ^
+ * | | | v | |
+ * | | SDATA +---------+ CLOSE | |
+ * | +-------->| Client |----------------------+ |
+ * | | Working | |
+ * | +---------+ |
+ * | | ^ |
+ * | +--+ |
+ * | Receive CRETRY |
+ * | CLOSE |
+ * +--------------------------------------------------+
+ */
+
+typedef struct private_pb_tnc_state_machine_t private_pb_tnc_state_machine_t;
+
+/**
+ * Private data of a pb_tnc_state_machine_t object.
+ *
+ */
+struct private_pb_tnc_state_machine_t {
+ /**
+ * Public pb_pa_message_t interface.
+ */
+ pb_tnc_state_machine_t public;
+
+ /**
+ * PB-TNC Server if TRUE, PB-TNC Client if FALSE
+ */
+ bool is_server;
+
+ /**
+ * Current PB-TNC state
+ */
+ pb_tnc_state_t state;
+};
+
+METHOD(pb_tnc_state_machine_t, get_state, pb_tnc_state_t,
+ private_pb_tnc_state_machine_t *this)
+{
+ return this->state;
+}
+
+METHOD(pb_tnc_state_machine_t, receive_batch, bool,
+ private_pb_tnc_state_machine_t *this, pb_tnc_batch_type_t type)
+{
+ pb_tnc_state_t old_state = this->state;
+
+ switch (this->state)
+ {
+ case PB_STATE_INIT:
+ if (this->is_server && type == PB_BATCH_CDATA)
+ {
+ this->state = PB_STATE_SERVER_WORKING;
+ break;
+ }
+ if (!this->is_server && type == PB_BATCH_SDATA)
+ {
+ this->state = PB_STATE_CLIENT_WORKING;
+ break;
+ }
+ if (type == PB_BATCH_CLOSE)
+ {
+ this->state = PB_STATE_END;
+ break;
+ }
+ return FALSE;
+ case PB_STATE_SERVER_WORKING:
+ if (!this->is_server && type == PB_BATCH_SDATA)
+ {
+ this->state = PB_STATE_CLIENT_WORKING;
+ break;
+ }
+ if (!this->is_server && type == PB_BATCH_RESULT)
+ {
+ this->state = PB_STATE_DECIDED;
+ break;
+ }
+ if ((this->is_server && type == PB_BATCH_CRETRY) ||
+ (!this->is_server && type == PB_BATCH_SRETRY))
+ {
+ break;
+ }
+ if (type == PB_BATCH_CLOSE)
+ {
+ this->state = PB_STATE_END;
+ break;
+ }
+ return FALSE;
+ case PB_STATE_CLIENT_WORKING:
+ if (this->is_server && type == PB_BATCH_CDATA)
+ {
+ this->state = PB_STATE_SERVER_WORKING;
+ break;
+ }
+ if (this->is_server && type == PB_BATCH_CRETRY)
+ {
+ break;
+ }
+ if (type == PB_BATCH_CLOSE)
+ {
+ this->state = PB_STATE_END;
+ break;
+ }
+ return FALSE;
+ case PB_STATE_DECIDED:
+ if ((this->is_server && type == PB_BATCH_CRETRY) ||
+ (!this->is_server && type == PB_BATCH_SRETRY))
+ {
+ this->state = PB_STATE_SERVER_WORKING;
+ break;
+ }
+ if (type == PB_BATCH_CLOSE)
+ {
+ this->state = PB_STATE_END;
+ break;
+ }
+ return FALSE;
+ case PB_STATE_END:
+ if (type == PB_BATCH_CLOSE)
+ {
+ break;
+ }
+ return FALSE;
+ }
+
+ if (this->state != old_state)
+ {
+ DBG2(DBG_TNC, "PB-TNC state transition from '%N' to '%N'",
+ pb_tnc_state_names, old_state, pb_tnc_state_names, this->state);
+ }
+ return TRUE;
+}
+
+METHOD(pb_tnc_state_machine_t, send_batch, bool,
+ private_pb_tnc_state_machine_t *this, pb_tnc_batch_type_t type)
+{
+ pb_tnc_state_t old_state = this->state;
+
+ switch (this->state)
+ {
+ case PB_STATE_INIT:
+ if (!this->is_server && type == PB_BATCH_CDATA)
+ {
+ this->state = PB_STATE_SERVER_WORKING;
+ break;
+ }
+ if (this->is_server && type == PB_BATCH_SDATA)
+ {
+ this->state = PB_STATE_CLIENT_WORKING;
+ break;
+ }
+ if (type == PB_BATCH_CLOSE)
+ {
+ this->state = PB_STATE_END;
+ break;
+ }
+ return FALSE;
+ case PB_STATE_SERVER_WORKING:
+ if (this->is_server && type == PB_BATCH_SDATA)
+ {
+ this->state = PB_STATE_CLIENT_WORKING;
+ break;
+ }
+ if (this->is_server && type == PB_BATCH_RESULT)
+ {
+ this->state = PB_STATE_DECIDED;
+ break;
+ }
+ if (this->is_server && type == PB_BATCH_SRETRY)
+ {
+ break;
+ }
+ if (type == PB_BATCH_CLOSE)
+ {
+ this->state = PB_STATE_END;
+ break;
+ }
+ return FALSE;
+ case PB_STATE_CLIENT_WORKING:
+ if (!this->is_server && type == PB_BATCH_CDATA)
+ {
+ this->state = PB_STATE_SERVER_WORKING;
+ break;
+ }
+ if (type == PB_BATCH_CLOSE)
+ {
+ this->state = PB_STATE_END;
+ break;
+ }
+ return FALSE;
+ case PB_STATE_DECIDED:
+ if ((this->is_server && type == PB_BATCH_SRETRY) ||
+ (!this->is_server && type == PB_BATCH_CRETRY))
+ {
+ this->state = PB_STATE_SERVER_WORKING;
+ break;
+ }
+ if (type == PB_BATCH_CLOSE)
+ {
+ this->state = PB_STATE_END;
+ break;
+ }
+ return FALSE;
+ case PB_STATE_END:
+ if (type == PB_BATCH_CLOSE)
+ {
+ break;
+ }
+ return FALSE;
+ }
+
+ if (this->state != old_state)
+ {
+ DBG2(DBG_TNC, "PB-TNC state transition from '%N' to '%N'",
+ pb_tnc_state_names, old_state, pb_tnc_state_names, this->state);
+ }
+ return TRUE;
+}
+
+METHOD(pb_tnc_state_machine_t, destroy, void,
+ private_pb_tnc_state_machine_t *this)
+{
+ free(this);
+}
+
+/**
+ * See header
+ */
+pb_tnc_state_machine_t* pb_tnc_state_machine_create(bool is_server)
+{
+ private_pb_tnc_state_machine_t *this;
+
+ INIT(this,
+ .public = {
+ .get_state = _get_state,
+ .receive_batch = _receive_batch,
+ .send_batch = _send_batch,
+ .destroy = _destroy,
+ },
+ .is_server = is_server,
+ .state = PB_STATE_INIT,
+ );
+
+ return &this->public;
+}
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
new file mode 100644
index 000000000..8076b6ded
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pb_tnc_state_machine pb_tnc_state_machine
+ * @{ @ingroup tnccs_20
+ */
+
+#ifndef PB_TNC_STATE_MACHINE_H_
+#define PB_TNC_STATE_MACHINE_H_
+
+typedef struct pb_tnc_state_machine_t pb_tnc_state_machine_t;
+typedef enum pb_tnc_state_t pb_tnc_state_t;
+
+#include "batch/pb_tnc_batch.h"
+
+#include <library.h>
+
+/**
+ * PB-TNC States (state machine) as defined in section 3.2 of RFC 5793
+ */
+enum pb_tnc_state_t {
+ PB_STATE_INIT,
+ PB_STATE_SERVER_WORKING,
+ PB_STATE_CLIENT_WORKING,
+ PB_STATE_DECIDED,
+ PB_STATE_END,
+};
+
+/**
+ * enum name for pb_tnc_state_t.
+ */
+extern enum_name_t *pb_tnc_state_names;
+
+/**
+ * Interface for the PB-TNC state machine.
+ */
+struct pb_tnc_state_machine_t {
+
+ /**
+ * Get the current PB-TNC STATE
+ *
+ * @return current state
+ */
+ pb_tnc_state_t (*get_state)(pb_tnc_state_machine_t *this);
+
+ /**
+ * Compute state transition due to received PB-TNC Batch
+ *
+ * @param type type of received batch
+ * @result TRUE if a valid transition was found, FALSE otherwise
+ */
+ bool (*receive_batch)(pb_tnc_state_machine_t *this, pb_tnc_batch_type_t type);
+
+ /**
+ * Compute state transition due to sent PB-TNC Batch
+ *
+ * @param type type of sent batch
+ * @result TRUE if a valid transition was found, FALSE otherwise
+ */
+ bool (*send_batch)(pb_tnc_state_machine_t *this, pb_tnc_batch_type_t type);
+
+ /**
+ * Destroys a pb_tnc_state_machine_t object.
+ */
+ void (*destroy)(pb_tnc_state_machine_t *this);
+};
+
+/**
+ * Create and initialize a PB-TNC state machine
+ *
+ * @param is_server TRUE if PB-TNC server, FALSE if PB-TNC client
+ */
+pb_tnc_state_machine_t* pb_tnc_state_machine_create(bool is_server);
+
+#endif /** PB_TNC_STATE_MACHINE_H_ @}*/
diff --git a/src/libcharon/plugins/tnccs_20/tnccs_20.c b/src/libcharon/plugins/tnccs_20/tnccs_20.c
index 2bd1bc476..d53fd8eb7 100644
--- a/src/libcharon/plugins/tnccs_20/tnccs_20.c
+++ b/src/libcharon/plugins/tnccs_20/tnccs_20.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2010 Sansar Choinyanbuu
* Copyright (C) 2010 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
@@ -14,10 +15,23 @@
*/
#include "tnccs_20.h"
+#include "batch/pb_tnc_batch.h"
+#include "messages/pb_tnc_msg.h"
+#include "messages/pb_pa_msg.h"
+#include "messages/pb_error_msg.h"
+#include "messages/pb_assessment_result_msg.h"
+#include "messages/pb_access_recommendation_msg.h"
+#include "messages/pb_remediation_parameters_msg.h"
+#include "messages/pb_reason_string_msg.h"
+#include "messages/pb_language_preference_msg.h"
+#include "state_machine/pb_tnc_state_machine.h"
#include <debug.h>
-
-static chunk_t tncc_output;
+#include <daemon.h>
+#include <threading/mutex.h>
+#include <tnc/tncif.h>
+#include <tnc/tncifimv.h>
+#include <tnc/tnccs/tnccs.h>
typedef struct private_tnccs_20_t private_tnccs_20_t;
@@ -35,18 +49,541 @@ struct private_tnccs_20_t {
* TNCC if TRUE, TNCS if FALSE
*/
bool is_server;
+
+ /**
+ * PB-TNC State Machine
+ */
+ pb_tnc_state_machine_t *state_machine;
+
+ /**
+ * Connection ID assigned to this TNCCS connection
+ */
+ TNC_ConnectionID connection_id;
+
+ /**
+ * PB-TNC batch being constructed
+ */
+ pb_tnc_batch_t *batch;
+
+ /**
+ * Mutex locking the batch in construction
+ */
+ mutex_t *mutex;
+
+ /**
+ * Flag set while processing
+ */
+ bool fatal_error;
+
+ /**
+ * Flag set by IMC/IMV RequestHandshakeRetry() function
+ */
+ bool request_handshake_retry;
+
+ /**
+ * Set of IMV recommendations (TNC Server only)
+ */
+ recommendations_t *recs;
};
+METHOD(tnccs_t, send_msg, void,
+ private_tnccs_20_t* this, TNC_IMCID imc_id, TNC_IMVID imv_id,
+ TNC_BufferReference msg,
+ TNC_UInt32 msg_len,
+ TNC_MessageType msg_type)
+{
+ TNC_MessageSubtype msg_sub_type;
+ TNC_VendorID msg_vendor_id;
+ pb_tnc_msg_t *pb_tnc_msg;
+ pb_tnc_batch_type_t batch_type;
+
+ msg_sub_type = msg_type & TNC_SUBTYPE_ANY;
+ msg_vendor_id = (msg_type >> 8) & TNC_VENDORID_ANY;
+
+ pb_tnc_msg = pb_pa_msg_create(msg_vendor_id, msg_sub_type, imc_id, imv_id,
+ chunk_create(msg, msg_len));
+
+ /* 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)
+ {
+ this->batch = pb_tnc_batch_create(this->is_server, batch_type);
+ }
+ if (this->batch->get_type(this->batch) == batch_type)
+ {
+ this->batch->add_msg(this->batch, pb_tnc_msg);
+ }
+ else
+ {
+ pb_tnc_msg->destroy(pb_tnc_msg);
+ }
+ this->mutex->unlock(this->mutex);
+}
+
+/**
+ * Handle a single PB-TNC message according to its type
+ */
+static void handle_message(private_tnccs_20_t *this, pb_tnc_msg_t *msg)
+{
+ switch (msg->get_type(msg))
+ {
+ case PB_MSG_EXPERIMENTAL:
+ /* nothing to do */
+ break;
+ case PB_MSG_PA:
+ {
+ pb_pa_msg_t *pa_msg;
+ TNC_MessageType msg_type;
+ u_int32_t vendor_id, subtype;
+ chunk_t msg_body;
+
+ pa_msg = (pb_pa_msg_t*)msg;
+ vendor_id = pa_msg->get_vendor_id(pa_msg, &subtype);
+ msg_type = (vendor_id << 8) | (subtype & 0xff);
+ msg_body = pa_msg->get_body(pa_msg);
+
+ DBG2(DBG_TNC, "handling PB-PA message type 0x%08x", msg_type);
+
+ if (this->is_server)
+ {
+ charon->imvs->receive_message(charon->imvs,
+ this->connection_id, msg_body.ptr, msg_body.len, msg_type);
+ }
+ else
+ {
+ charon->imcs->receive_message(charon->imcs,
+ this->connection_id, msg_body.ptr, msg_body.len,msg_type);
+ }
+ break;
+ }
+ case PB_MSG_ASSESSMENT_RESULT:
+ {
+ pb_assessment_result_msg_t *assess_msg;
+ u_int32_t result;
+
+ assess_msg = (pb_assessment_result_msg_t*)msg;
+ result = assess_msg->get_assessment_result(assess_msg);
+ DBG1(DBG_TNC, "PB-TNC assessment result is '%N'",
+ TNC_IMV_Evaluation_Result_names, result);
+ break;
+ }
+ case PB_MSG_ACCESS_RECOMMENDATION:
+ {
+ pb_access_recommendation_msg_t *rec_msg;
+ pb_access_recommendation_code_t rec;
+ TNC_ConnectionState state = TNC_CONNECTION_STATE_ACCESS_NONE;
+
+ rec_msg = (pb_access_recommendation_msg_t*)msg;
+ rec = rec_msg->get_access_recommendation(rec_msg);
+ DBG1(DBG_TNC, "PB-TNC access recommendation is '%N'",
+ pb_access_recommendation_code_names, rec);
+ switch (rec)
+ {
+ case PB_REC_ACCESS_ALLOWED:
+ state = TNC_CONNECTION_STATE_ACCESS_ALLOWED;
+ break;
+ case PB_REC_ACCESS_DENIED:
+ state = TNC_CONNECTION_STATE_ACCESS_NONE;
+ break;
+ case PB_REC_QUARANTINED:
+ state = TNC_CONNECTION_STATE_ACCESS_ISOLATED;
+ }
+ charon->imcs->notify_connection_change(charon->imcs,
+ this->connection_id, state);
+ break;
+ }
+ case PB_MSG_REMEDIATION_PARAMETERS:
+ {
+ /* TODO : Remediation parameters message processing */
+ break;
+ }
+ case PB_MSG_ERROR:
+ {
+ pb_error_msg_t *err_msg;
+ bool fatal;
+ u_int32_t vendor_id;
+ u_int16_t error_code;
+
+ err_msg = (pb_error_msg_t*)msg;
+ fatal = err_msg->get_fatal_flag(err_msg);
+ vendor_id = err_msg->get_vendor_id(err_msg);
+ error_code = err_msg->get_error_code(err_msg);
+
+ if (fatal)
+ {
+ this->fatal_error = TRUE;
+ }
+
+ if (vendor_id == IETF_VENDOR_ID)
+ {
+ switch (error_code)
+ {
+ case PB_ERROR_INVALID_PARAMETER:
+ case PB_ERROR_UNSUPPORTED_MANDATORY_MSG:
+ DBG1(DBG_TNC, "received %s PB-TNC error '%N' "
+ "(offset %u bytes)",
+ fatal ? "fatal" : "non-fatal",
+ pb_tnc_error_code_names, error_code,
+ err_msg->get_offset(err_msg));
+ break;
+ case PB_ERROR_VERSION_NOT_SUPPORTED:
+ DBG1(DBG_TNC, "received %s PB-TNC error '%N' "
+ "caused by bad version 0x%02x",
+ fatal ? "fatal" : "non-fatal",
+ pb_tnc_error_code_names, error_code,
+ err_msg->get_bad_version(err_msg));
+ break;
+ case PB_ERROR_UNEXPECTED_BATCH_TYPE:
+ case PB_ERROR_LOCAL_ERROR:
+ default:
+ DBG1(DBG_TNC, "received %s PB-TNC error '%N'",
+ fatal ? "fatal" : "non-fatal",
+ pb_tnc_error_code_names, error_code);
+ break;
+ }
+ }
+ else
+ {
+ DBG1(DBG_TNC, "received %s PB-TNC error (%u) "
+ "with Vendor ID 0x%06x",
+ fatal ? "fatal" : "non-fatal",
+ error_code, vendor_id);
+ }
+ break;
+ }
+ case PB_MSG_LANGUAGE_PREFERENCE:
+ {
+ pb_language_preference_msg_t *lang_msg;
+ chunk_t lang;
+
+ lang_msg = (pb_language_preference_msg_t*)msg;
+ lang = lang_msg->get_language_preference(lang_msg);
+
+ DBG2(DBG_TNC, "setting language preference to '%.*s'",
+ lang.len, lang.ptr);
+ this->recs->set_preferred_language(this->recs, lang);
+ break;
+ }
+ case PB_MSG_REASON_STRING:
+ {
+ pb_reason_string_msg_t *reason_msg;
+ chunk_t reason_string, language_code;
+
+ 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,
+ reason_string.ptr);
+ DBG2(DBG_TNC, "language code is '%.*s", language_code.len,
+ language_code.ptr);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+/**
+ * Build a CRETRY or SRETRY batch
+ */
+static void build_retry_batch(private_tnccs_20_t *this)
+{
+ 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,
+ this->is_server ? PB_BATCH_SRETRY : PB_BATCH_CRETRY);
+}
+
METHOD(tls_t, process, status_t,
private_tnccs_20_t *this, void *buf, size_t buflen)
{
+ chunk_t data;
+ pb_tnc_batch_t *batch;
+ pb_tnc_msg_t *msg;
+ enumerator_t *enumerator;
+ status_t status;
+
+ if (this->is_server && !this->connection_id)
+ {
+ this->connection_id = charon->tnccs->create_connection(charon->tnccs,
+ (tnccs_t*)this, _send_msg,
+ &this->request_handshake_retry, &this->recs);
+ if (!this->connection_id)
+ {
+ return FAILED;
+ }
+ charon->imvs->notify_connection_change(charon->imvs,
+ this->connection_id, TNC_CONNECTION_STATE_CREATE);
+ }
+
+ 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, "%B", &data);
+ batch = pb_tnc_batch_create_from_data(this->is_server, data);
+ status = batch->process(batch, this->state_machine);
+
+ if (status != FAILED)
+ {
+ enumerator_t *enumerator;
+ pb_tnc_msg_t *msg;
+ pb_tnc_batch_type_t batch_type;
+ bool empty = TRUE;
+
+ batch_type = batch->get_type(batch);
+
+ if (batch_type == PB_BATCH_CRETRY)
+ {
+ /* Send an SRETRY batch in response */
+ this->mutex->lock(this->mutex);
+ build_retry_batch(this);
+ this->mutex->unlock(this->mutex);
+ }
+ else if (batch_type == PB_BATCH_SRETRY)
+ {
+ /* Restart the measurements */
+ charon->imcs->notify_connection_change(charon->imcs,
+ this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE);
+ charon->imcs->begin_handshake(charon->imcs, this->connection_id);
+ }
+
+ enumerator = batch->create_msg_enumerator(batch);
+ while (enumerator->enumerate(enumerator, &msg))
+ {
+ handle_message(this, msg);
+ empty = FALSE;
+ }
+ enumerator->destroy(enumerator);
+
+ /* received an empty CLOSE batch from PB-TNC client */
+ if (this->is_server && batch_type == PB_BATCH_CLOSE && empty)
+ {
+ batch->destroy(batch);
+ if (this->fatal_error)
+ {
+ DBG1(DBG_TNC, "a fatal PB-TNC error occurred, "
+ "terminating connection");
+ return FAILED;
+ }
+ else
+ {
+ return SUCCESS;
+ }
+ }
+
+ if (this->is_server)
+ {
+ charon->imvs->batch_ending(charon->imvs, this->connection_id);
+ }
+ else
+ {
+ charon->imcs->batch_ending(charon->imcs, this->connection_id);
+ }
+ }
+
+ switch (status)
+ {
+ 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);
+ this->mutex->unlock(this->mutex);
+ /* fall through to add error messages to outbound batch */
+ case VERIFY_ERROR:
+ enumerator = batch->create_error_enumerator(batch);
+ while (enumerator->enumerate(enumerator, &msg))
+ {
+ this->mutex->lock(this->mutex);
+ this->batch->add_msg(this->batch, msg->get_ref(msg));
+ this->mutex->unlock(this->mutex);
+ }
+ enumerator->destroy(enumerator);
+ break;
+ case SUCCESS:
+ default:
+ break;
+ }
+ batch->destroy(batch);
+
return NEED_MORE;
}
+/**
+ * Build a RESULT batch if a final recommendation is available
+ */
+static void check_and_build_recommendation(private_tnccs_20_t *this)
+{
+ TNC_IMV_Action_Recommendation rec;
+ TNC_IMV_Evaluation_Result eval;
+ TNC_IMVID id;
+ chunk_t reason, language;
+ enumerator_t *enumerator;
+ pb_tnc_msg_t *msg;
+
+ if (!this->recs->have_recommendation(this->recs, &rec, &eval))
+ {
+ charon->imvs->solicit_recommendation(charon->imvs, this->connection_id);
+ }
+ if (this->recs->have_recommendation(this->recs, &rec, &eval))
+ {
+ this->batch = pb_tnc_batch_create(this->is_server, PB_BATCH_RESULT);
+
+ msg = pb_assessment_result_msg_create(eval);
+ this->batch->add_msg(this->batch, msg);
+
+ /**
+ * IMV Action Recommendation and PB Access Recommendation codes
+ * are shifted by one.
+ */
+ msg = pb_access_recommendation_msg_create(rec + 1);
+ this->batch->add_msg(this->batch, 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);
+ }
+ enumerator->destroy(enumerator);
+ }
+}
+
METHOD(tls_t, build, status_t,
private_tnccs_20_t *this, void *buf, size_t *buflen, size_t *msglen)
{
- return ALREADY_DONE;
+ status_t status;
+
+ /* Initialize the connection */
+ if (!this->is_server && !this->connection_id)
+ {
+ pb_tnc_msg_t *msg;
+ char *pref_lang;
+
+ this->connection_id = charon->tnccs->create_connection(charon->tnccs,
+ (tnccs_t*)this, _send_msg,
+ &this->request_handshake_retry, NULL);
+ if (!this->connection_id)
+ {
+ return FAILED;
+ }
+
+ /* Create PB-TNC Language Preference message */
+ pref_lang = charon->imcs->get_preferred_language(charon->imcs);
+ 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->mutex->unlock(this->mutex);
+
+ charon->imcs->notify_connection_change(charon->imcs,
+ this->connection_id, TNC_CONNECTION_STATE_CREATE);
+ charon->imcs->notify_connection_change(charon->imcs,
+ this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE);
+ charon->imcs->begin_handshake(charon->imcs, this->connection_id);
+ }
+
+ if (this->is_server && this->fatal_error &&
+ this->state_machine->get_state(this->state_machine) == PB_STATE_END)
+ {
+ DBG1(DBG_TNC, "a fatal PB-TNC error occurred, terminating connection");
+ return FAILED;
+ }
+
+ /* Do not allow any asynchronous IMCs or IMVs to add additional messages */
+ this->mutex->lock(this->mutex);
+
+ if (this->request_handshake_retry)
+ {
+ build_retry_batch(this);
+
+ /* Reset the flag for the next handshake retry request */
+ this->request_handshake_retry = FALSE;
+ }
+
+ if (!this->batch)
+ {
+ pb_tnc_state_t state;
+
+ state = this->state_machine->get_state(this->state_machine);
+ if (this->is_server)
+ {
+ if (state == PB_STATE_SERVER_WORKING)
+ {
+ check_and_build_recommendation(this);
+ }
+ }
+ 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,
+ * a PB-TNC client replies with an empty CLOSE batch.
+ */
+ if (state == PB_STATE_DECIDED || state == PB_STATE_END)
+ {
+ this->batch = pb_tnc_batch_create(this->is_server, PB_BATCH_CLOSE);
+ }
+ }
+ }
+
+ if (this->batch)
+ {
+ pb_tnc_batch_type_t batch_type;
+ chunk_t data;
+
+ batch_type = this->batch->get_type(this->batch);
+
+ if (this->state_machine->send_batch(this->state_machine, batch_type))
+ {
+ this->batch->build(this->batch);
+ data = this->batch->get_encoding(this->batch);
+ DBG1(DBG_TNC, "sending PB-TNC %N batch (%d bytes) for Connection ID %u",
+ pb_tnc_batch_type_names, batch_type, data.len,
+ this->connection_id);
+ DBG3(DBG_TNC, "%B", &data);
+ *msglen = data.len;
+
+ if (data.len > *buflen)
+ {
+ DBG1(DBG_TNC, "fragmentation of PB-TNC batch not supported yet");
+ }
+ else
+ {
+ *buflen = data.len;
+ }
+ 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);
+ status = INVALID_STATE;
+ }
+
+ this->batch->destroy(this->batch);
+ this->batch = NULL;
+ }
+ else
+ {
+ DBG1(DBG_TNC, "no PB-TNC batch to send");
+ status = INVALID_STATE;
+ }
+ this->mutex->unlock(this->mutex);
+
+ return status;
}
METHOD(tls_t, is_server, bool,
@@ -64,7 +601,21 @@ METHOD(tls_t, get_purpose, tls_purpose_t,
METHOD(tls_t, is_complete, bool,
private_tnccs_20_t *this)
{
- return FALSE;
+ TNC_IMV_Action_Recommendation rec;
+ TNC_IMV_Evaluation_Result eval;
+
+ if (this->recs && this->recs->have_recommendation(this->recs, &rec, &eval))
+ {
+ DBG2(DBG_TNC, "Final recommendation is '%N' and evaluation is '%N'",
+ TNC_IMV_Action_Recommendation_names, rec,
+ TNC_IMV_Evaluation_Result_names, eval);
+
+ return charon->imvs->enforce_recommendation(charon->imvs, rec);
+ }
+ else
+ {
+ return FALSE;
+ }
}
METHOD(tls_t, get_eap_msk, chunk_t,
@@ -76,6 +627,20 @@ METHOD(tls_t, get_eap_msk, chunk_t,
METHOD(tls_t, destroy, void,
private_tnccs_20_t *this)
{
+ if (this->is_server)
+ {
+ charon->imvs->notify_connection_change(charon->imvs,
+ this->connection_id, TNC_CONNECTION_STATE_DELETE);
+ }
+ else
+ {
+ charon->imcs->notify_connection_change(charon->imcs,
+ this->connection_id, TNC_CONNECTION_STATE_DELETE);
+ }
+ charon->tnccs->remove_connection(charon->tnccs, this->connection_id);
+ this->state_machine->destroy(this->state_machine);
+ this->mutex->destroy(this->mutex);
+ DESTROY_IF(this->batch);
free(this);
}
@@ -97,6 +662,8 @@ tls_t *tnccs_20_create(bool is_server)
.destroy = _destroy,
},
.is_server = is_server,
+ .state_machine = pb_tnc_state_machine_create(is_server),
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
);
return &this->public;
diff --git a/src/libcharon/plugins/tnccs_dynamic/Makefile.am b/src/libcharon/plugins/tnccs_dynamic/Makefile.am
new file mode 100644
index 000000000..9a81d065f
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_dynamic/Makefile.am
@@ -0,0 +1,17 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-tnccs-dynamic.la
+else
+plugin_LTLIBRARIES = libstrongswan-tnccs-dynamic.la
+libstrongswan_tnccs_dynamic_la_LIBADD = $(top_builddir)/src/libtls/libtls.la
+endif
+
+libstrongswan_tnccs_dynamic_la_SOURCES = \
+ tnccs_dynamic_plugin.h tnccs_dynamic_plugin.c tnccs_dynamic.h tnccs_dynamic.c
+
+libstrongswan_tnccs_dynamic_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/tnccs_dynamic/Makefile.in b/src/libcharon/plugins/tnccs_dynamic/Makefile.in
new file mode 100644
index 000000000..722da2830
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_dynamic/Makefile.in
@@ -0,0 +1,607 @@
+# 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/tnccs_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_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)
+@MONOLITHIC_FALSE@libstrongswan_tnccs_dynamic_la_DEPENDENCIES = \
+@MONOLITHIC_FALSE@ $(top_builddir)/src/libtls/libtls.la
+am_libstrongswan_tnccs_dynamic_la_OBJECTS = tnccs_dynamic_plugin.lo \
+ tnccs_dynamic.lo
+libstrongswan_tnccs_dynamic_la_OBJECTS = \
+ $(am_libstrongswan_tnccs_dynamic_la_OBJECTS)
+libstrongswan_tnccs_dynamic_la_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_tnccs_dynamic_la_LDFLAGS) $(LDFLAGS) -o $@
+@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@
+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_tnccs_dynamic_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_tnccs_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@
+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@
+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@
+datadir = @datadir@
+datarootdir = @datarootdir@
+dbusservicedir = @dbusservicedir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+h_plugins = @h_plugins@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgroup = @ipsecgroup@
+ipsecuser = @ipsecuser@
+libcharon_plugins = @libcharon_plugins@
+libdir = @libdir@
+libexecdir = @libexecdir@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+maemo_CFLAGS = @maemo_CFLAGS@
+maemo_LIBS = @maemo_LIBS@
+manager_plugins = @manager_plugins@
+mandir = @mandir@
+medsrv_plugins = @medsrv_plugins@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+openac_plugins = @openac_plugins@
+p_plugins = @p_plugins@
+pdfdir = @pdfdir@
+piddir = @piddir@
+pki_plugins = @pki_plugins@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+pool_plugins = @pool_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+s_plugins = @s_plugins@
+sbindir = @sbindir@
+scepclient_plugins = @scepclient_plugins@
+scripts_plugins = @scripts_plugins@
+sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls
+
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-tnccs-dynamic.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-tnccs-dynamic.la
+@MONOLITHIC_FALSE@libstrongswan_tnccs_dynamic_la_LIBADD = $(top_builddir)/src/libtls/libtls.la
+libstrongswan_tnccs_dynamic_la_SOURCES = \
+ tnccs_dynamic_plugin.h tnccs_dynamic_plugin.c tnccs_dynamic.h tnccs_dynamic.c
+
+libstrongswan_tnccs_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/tnccs_dynamic/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/tnccs_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-tnccs-dynamic.la: $(libstrongswan_tnccs_dynamic_la_OBJECTS) $(libstrongswan_tnccs_dynamic_la_DEPENDENCIES)
+ $(libstrongswan_tnccs_dynamic_la_LINK) $(am_libstrongswan_tnccs_dynamic_la_rpath) $(libstrongswan_tnccs_dynamic_la_OBJECTS) $(libstrongswan_tnccs_dynamic_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_dynamic.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_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/tnccs_dynamic/tnccs_dynamic.c b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.c
new file mode 100644
index 000000000..b7985fa51
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnccs_dynamic.h"
+
+#include <tnc/tnccs/tnccs.h>
+#include <daemon.h>
+
+typedef struct private_tnccs_dynamic_t private_tnccs_dynamic_t;
+
+/**
+ * Private data of a tnccs_dynamic_t object.
+ */
+struct private_tnccs_dynamic_t {
+
+ /**
+ * Public tls_t interface.
+ */
+ tls_t public;
+
+ /**
+ * Detected TNC IF-TNCCS stack
+ */
+ tls_t *tls;
+};
+
+/**
+ * Determine the version of the IF-TNCCS protocol used by analyzing the first
+ * byte of the TNCCS batch received from a TNC Client according to the rules
+ * defined by section 3.5 "Interoperability with older IF-TNCCS versions" of
+ * the TCG TNC IF-TNCCS TLV Bindings Version 2.0 standard.
+ */
+tnccs_type_t determine_tnccs_protocol(char version)
+{
+ switch (version)
+ {
+ case '\t':
+ case '\n':
+ case '\r':
+ case ' ':
+ case '<':
+ return TNCCS_1_1;
+ case 0x00:
+ return TNCCS_SOH;
+ case 0x02:
+ return TNCCS_2_0;
+ default:
+ return TNCCS_UNKNOWN;
+ }
+}
+
+METHOD(tls_t, process, status_t,
+ private_tnccs_dynamic_t *this, void *buf, size_t buflen)
+{
+ tnccs_type_t type;
+
+ if (!this->tls)
+ {
+ if (buflen == 0)
+ {
+ return FAILED;
+ }
+ type = determine_tnccs_protocol(*(char*)buf);
+ DBG1(DBG_TNC, "%N protocol detected dynamically",
+ tnccs_type_names, type);
+ this->tls = (tls_t*)charon->tnccs->create_instance(charon->tnccs,
+ type, TRUE);
+ if (!this->tls)
+ {
+ DBG1(DBG_TNC, "N% protocol not supported", tnccs_type_names, type);
+ return FAILED;
+ }
+ }
+ return this->tls->process(this->tls, buf, buflen);
+}
+
+METHOD(tls_t, build, status_t,
+ private_tnccs_dynamic_t *this, void *buf, size_t *buflen, size_t *msglen)
+{
+ return this->tls->build(this->tls, buf, buflen, msglen);
+}
+
+METHOD(tls_t, is_server, bool,
+ private_tnccs_dynamic_t *this)
+{
+ return TRUE;
+}
+
+METHOD(tls_t, get_purpose, tls_purpose_t,
+ private_tnccs_dynamic_t *this)
+{
+ return TLS_PURPOSE_EAP_TNC;
+}
+
+METHOD(tls_t, is_complete, bool,
+ private_tnccs_dynamic_t *this)
+{
+ return this->tls ? this->tls->is_complete(this->tls) : FALSE;
+}
+
+METHOD(tls_t, get_eap_msk, chunk_t,
+ private_tnccs_dynamic_t *this)
+{
+ return chunk_empty;
+}
+
+METHOD(tls_t, destroy, void,
+ private_tnccs_dynamic_t *this)
+{
+ DESTROY_IF(this->tls);
+ free(this);
+}
+
+/**
+ * See header
+ */
+tls_t *tnccs_dynamic_create(bool is_server)
+{
+ private_tnccs_dynamic_t *this;
+
+ INIT(this,
+ .public = {
+ .process = _process,
+ .build = _build,
+ .is_server = _is_server,
+ .get_purpose = _get_purpose,
+ .is_complete = _is_complete,
+ .get_eap_msk = _get_eap_msk,
+ .destroy = _destroy,
+ },
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.h b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.h
new file mode 100644
index 000000000..42410b17f
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tnccs_dynamic_h tnccs_dynamic
+ * @{ @ingroup tnccs_dynamic
+ */
+
+#ifndef TNCCS_DYNAMIC_H_
+#define TNCCS_DYNAMIC_H_
+
+#include <library.h>
+
+#include <tls.h>
+
+/**
+ * Create an instance of a dynamic TNC IF-TNCCS protocol handler.
+ *
+ * @param is_server TRUE to act as TNC Server, FALSE for TNC Client
+ * @return dynamic TNC IF-TNCCS protocol stack
+ */
+tls_t *tnccs_dynamic_create(bool is_server);
+
+#endif /** TNCCS_DYNAMIC_H_ @}*/
diff --git a/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic_plugin.c b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic_plugin.c
new file mode 100644
index 000000000..dbbf222e0
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic_plugin.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnccs_dynamic_plugin.h"
+#include "tnccs_dynamic.h"
+
+#include <daemon.h>
+
+METHOD(plugin_t, destroy, void,
+ tnccs_dynamic_plugin_t *this)
+{
+ charon->tnccs->remove_method(charon->tnccs,
+ (tnccs_constructor_t)tnccs_dynamic_create);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *tnccs_dynamic_plugin_create()
+{
+ tnccs_dynamic_plugin_t *this;
+
+ INIT(this,
+ .plugin = {
+ .destroy = _destroy,
+ },
+ );
+
+ charon->tnccs->add_method(charon->tnccs, TNCCS_DYNAMIC,
+ (tnccs_constructor_t)tnccs_dynamic_create);
+
+ return &this->plugin;
+}
+
diff --git a/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic_plugin.h b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic_plugin.h
new file mode 100644
index 000000000..b518e1278
--- /dev/null
+++ b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tnccs_dynamic tnccs_dynamic
+ * @ingroup cplugins
+ *
+ * @defgroup tnccs_dynamic_plugin tnccs_dynamic_plugin
+ * @{ @ingroup tnccs_dynamic
+ */
+
+#ifndef TNCCS_DYNAMIC_PLUGIN_H_
+#define TNCCS_DYNAMIC_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct tnccs_dynamic_plugin_t tnccs_dynamic_plugin_t;
+
+/**
+ * EAP-TNC plugin
+ */
+struct tnccs_dynamic_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** TNCCS_DYNAMIC_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/uci/Makefile.in b/src/libcharon/plugins/uci/Makefile.in
index 9cb5f794a..f7162d800 100644
--- a/src/libcharon/plugins/uci/Makefile.in
+++ b/src/libcharon/plugins/uci/Makefile.in
@@ -220,9 +220,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -261,6 +259,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/uci/uci_config.c b/src/libcharon/plugins/uci/uci_config.c
index ddddae782..4e43388ec 100644
--- a/src/libcharon/plugins/uci/uci_config.c
+++ b/src/libcharon/plugins/uci/uci_config.c
@@ -196,8 +196,8 @@ static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg)
this->peer_cfg->add_auth_cfg(this->peer_cfg, auth, FALSE);
child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE, MODE_TUNNEL,
- ACTION_NONE, ACTION_NONE, FALSE, 0, 0,
- NULL, NULL);
+ ACTION_NONE, ACTION_NONE, ACTION_NONE,
+ FALSE, 0, 0, NULL, NULL, 0);
child_cfg->add_proposal(child_cfg, create_proposal(esp_proposal, PROTO_ESP));
child_cfg->add_traffic_selector(child_cfg, TRUE, create_ts(local_net));
child_cfg->add_traffic_selector(child_cfg, FALSE, create_ts(remote_net));
diff --git a/src/libcharon/plugins/unit_tester/Makefile.in b/src/libcharon/plugins/unit_tester/Makefile.in
index 47fff7e1d..5fa749e56 100644
--- a/src/libcharon/plugins/unit_tester/Makefile.in
+++ b/src/libcharon/plugins/unit_tester/Makefile.in
@@ -226,9 +226,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -267,6 +265,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/plugins/updown/Makefile.in b/src/libcharon/plugins/updown/Makefile.in
index e93955d71..5dd2dc843 100644
--- a/src/libcharon/plugins/updown/Makefile.in
+++ b/src/libcharon/plugins/updown/Makefile.in
@@ -222,9 +222,7 @@ includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
-ipsecgid = @ipsecgid@
ipsecgroup = @ipsecgroup@
-ipsecuid = @ipsecuid@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -263,6 +261,8 @@ sbindir = @sbindir@
scepclient_plugins = @scepclient_plugins@
scripts_plugins = @scripts_plugins@
sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
diff --git a/src/libcharon/processing/jobs/acquire_job.c b/src/libcharon/processing/jobs/acquire_job.c
index 45ace9312..3544dd332 100644
--- a/src/libcharon/processing/jobs/acquire_job.c
+++ b/src/libcharon/processing/jobs/acquire_job.c
@@ -45,20 +45,16 @@ struct private_acquire_job_t {
traffic_selector_t *dst_ts;
};
-/**
- * Implementation of job_t.destroy.
- */
-static void destroy(private_acquire_job_t *this)
+METHOD(job_t, destroy, void,
+ private_acquire_job_t *this)
{
DESTROY_IF(this->src_ts);
DESTROY_IF(this->dst_ts);
free(this);
}
-/**
- * Implementation of job_t.execute.
- */
-static void execute(private_acquire_job_t *this)
+METHOD(job_t, execute, void,
+ private_acquire_job_t *this)
{
charon->traps->acquire(charon->traps, this->reqid,
this->src_ts, this->dst_ts);
@@ -72,14 +68,19 @@ acquire_job_t *acquire_job_create(u_int32_t reqid,
traffic_selector_t *src_ts,
traffic_selector_t *dst_ts)
{
- private_acquire_job_t *this = malloc_thing(private_acquire_job_t);
-
- this->public.job_interface.execute = (void (*) (job_t *)) execute;
- this->public.job_interface.destroy = (void (*)(job_t*)) destroy;
+ private_acquire_job_t *this;
- this->reqid = reqid;
- this->src_ts = src_ts;
- this->dst_ts = dst_ts;
+ INIT(this,
+ .public = {
+ .job_interface = {
+ .execute = _execute,
+ .destroy = _destroy,
+ },
+ },
+ .reqid = reqid,
+ .src_ts = src_ts,
+ .dst_ts = dst_ts,
+ );
return &this->public;
}
diff --git a/src/libcharon/processing/jobs/delete_child_sa_job.c b/src/libcharon/processing/jobs/delete_child_sa_job.c
index ca55721f2..29122cd03 100644
--- a/src/libcharon/processing/jobs/delete_child_sa_job.c
+++ b/src/libcharon/processing/jobs/delete_child_sa_job.c
@@ -46,18 +46,14 @@ struct private_delete_child_sa_job_t {
u_int32_t spi;
};
-/**
- * Implementation of job_t.destroy.
- */
-static void destroy(private_delete_child_sa_job_t *this)
+METHOD(job_t, destroy, void,
+ private_delete_child_sa_job_t *this)
{
free(this);
}
-/**
- * Implementation of job_t.execute.
- */
-static void execute(private_delete_child_sa_job_t *this)
+METHOD(job_t, execute, void,
+ private_delete_child_sa_job_t *this)
{
ike_sa_t *ike_sa;
@@ -84,16 +80,19 @@ delete_child_sa_job_t *delete_child_sa_job_create(u_int32_t reqid,
protocol_id_t protocol,
u_int32_t spi)
{
- private_delete_child_sa_job_t *this = malloc_thing(private_delete_child_sa_job_t);
-
- /* interface functions */
- this->public.job_interface.execute = (void (*) (job_t *)) execute;
- this->public.job_interface.destroy = (void (*)(job_t*)) destroy;
-
- /* private variables */
- this->reqid = reqid;
- this->protocol = protocol;
- this->spi = spi;
+ private_delete_child_sa_job_t *this;
+
+ INIT(this,
+ .public = {
+ .job_interface = {
+ .execute = _execute,
+ .destroy = _destroy,
+ },
+ },
+ .reqid = reqid,
+ .protocol = protocol,
+ .spi = spi,
+ );
return &this->public;
}
diff --git a/src/libcharon/processing/jobs/delete_ike_sa_job.c b/src/libcharon/processing/jobs/delete_ike_sa_job.c
index dffd08ba3..da3ecf06f 100644
--- a/src/libcharon/processing/jobs/delete_ike_sa_job.c
+++ b/src/libcharon/processing/jobs/delete_ike_sa_job.c
@@ -41,19 +41,15 @@ struct private_delete_ike_sa_job_t {
};
-/**
- * Implements job_t.destroy.
- */
-static void destroy(private_delete_ike_sa_job_t *this)
+METHOD(job_t, destroy, void,
+ private_delete_ike_sa_job_t *this)
{
this->ike_sa_id->destroy(this->ike_sa_id);
free(this);
}
-/**
- * Implementation of job_t.execute.
- */
-static void execute(private_delete_ike_sa_job_t *this)
+METHOD(job_t, execute, void,
+ private_delete_ike_sa_job_t *this)
{
ike_sa_t *ike_sa;
@@ -102,15 +98,18 @@ static void execute(private_delete_ike_sa_job_t *this)
delete_ike_sa_job_t *delete_ike_sa_job_create(ike_sa_id_t *ike_sa_id,
bool delete_if_established)
{
- private_delete_ike_sa_job_t *this = malloc_thing(private_delete_ike_sa_job_t);
-
- /* interface functions */
- this->public.job_interface.execute = (void (*) (job_t *)) execute;
- this->public.job_interface.destroy = (void (*)(job_t *)) destroy;;
+ private_delete_ike_sa_job_t *this;
- /* private variables */
- this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
- this->delete_if_established = delete_if_established;
+ INIT(this,
+ .public = {
+ .job_interface = {
+ .execute = _execute,
+ .destroy = _destroy,
+ },
+ },
+ .ike_sa_id = ike_sa_id->clone(ike_sa_id),
+ .delete_if_established = delete_if_established,
+ );
return &(this->public);
}
diff --git a/src/libcharon/processing/jobs/migrate_job.c b/src/libcharon/processing/jobs/migrate_job.c
index 05f47340c..5e7c7ae88 100644
--- a/src/libcharon/processing/jobs/migrate_job.c
+++ b/src/libcharon/processing/jobs/migrate_job.c
@@ -57,10 +57,8 @@ struct private_migrate_job_t {
host_t *remote;
};
-/**
- * Implementation of job_t.destroy.
- */
-static void destroy(private_migrate_job_t *this)
+METHOD(job_t, destroy, void,
+ private_migrate_job_t *this)
{
DESTROY_IF(this->src_ts);
DESTROY_IF(this->dst_ts);
@@ -69,10 +67,8 @@ static void destroy(private_migrate_job_t *this)
free(this);
}
-/**
- * Implementation of job_t.execute.
- */
-static void execute(private_migrate_job_t *this)
+METHOD(job_t, execute, void,
+ private_migrate_job_t *this)
{
ike_sa_t *ike_sa = NULL;
@@ -133,18 +129,21 @@ migrate_job_t *migrate_job_create(u_int32_t reqid,
policy_dir_t dir,
host_t *local, host_t *remote)
{
- private_migrate_job_t *this = malloc_thing(private_migrate_job_t);
-
- /* interface functions */
- this->public.job_interface.execute = (void (*) (job_t *)) execute;
- this->public.job_interface.destroy = (void (*)(job_t*)) destroy;
-
- /* private variables */
- this->reqid = reqid;
- this->src_ts = (dir == POLICY_OUT) ? src_ts : dst_ts;
- this->dst_ts = (dir == POLICY_OUT) ? dst_ts : src_ts;
- this->local = local;
- this->remote = remote;
+ private_migrate_job_t *this;
+
+ INIT(this,
+ .public = {
+ .job_interface = {
+ .execute = _execute,
+ .destroy = _destroy,
+ },
+ },
+ .reqid = reqid,
+ .src_ts = (dir == POLICY_OUT) ? src_ts : dst_ts,
+ .dst_ts = (dir == POLICY_OUT) ? dst_ts : src_ts,
+ .local = local,
+ .remote = remote,
+ );
return &this->public;
}
diff --git a/src/libcharon/processing/jobs/process_message_job.c b/src/libcharon/processing/jobs/process_message_job.c
index a47d48e38..b6de4fc0f 100644
--- a/src/libcharon/processing/jobs/process_message_job.c
+++ b/src/libcharon/processing/jobs/process_message_job.c
@@ -35,19 +35,15 @@ struct private_process_message_job_t {
message_t *message;
};
-/**
- * Implements job_t.destroy.
- */
-static void destroy(private_process_message_job_t *this)
+METHOD(job_t, destroy, void,
+ private_process_message_job_t *this)
{
this->message->destroy(this->message);
free(this);
}
-/**
- * Implementation of job_t.execute.
- */
-static void execute(private_process_message_job_t *this)
+METHOD(job_t, execute, void,
+ private_process_message_job_t *this)
{
ike_sa_t *ike_sa;
@@ -93,14 +89,17 @@ static void execute(private_process_message_job_t *this)
*/
process_message_job_t *process_message_job_create(message_t *message)
{
- private_process_message_job_t *this = malloc_thing(private_process_message_job_t);
-
- /* interface functions */
- this->public.job_interface.execute = (void (*) (job_t *)) execute;
- this->public.job_interface.destroy = (void(*)(job_t*))destroy;
+ private_process_message_job_t *this;
- /* private variables */
- this->message = message;
+ INIT(this,
+ .public = {
+ .job_interface = {
+ .execute = _execute,
+ .destroy = _destroy,
+ },
+ },
+ .message = message,
+ );
return &(this->public);
}
diff --git a/src/libcharon/processing/jobs/rekey_child_sa_job.c b/src/libcharon/processing/jobs/rekey_child_sa_job.c
index b797d181e..2bcee2ddf 100644
--- a/src/libcharon/processing/jobs/rekey_child_sa_job.c
+++ b/src/libcharon/processing/jobs/rekey_child_sa_job.c
@@ -45,18 +45,14 @@ struct private_rekey_child_sa_job_t {
u_int32_t spi;
};
-/**
- * Implementation of job_t.destroy.
- */
-static void destroy(private_rekey_child_sa_job_t *this)
+METHOD(job_t, destroy, void,
+ private_rekey_child_sa_job_t *this)
{
free(this);
}
-/**
- * Implementation of job_t.execute.
- */
-static void execute(private_rekey_child_sa_job_t *this)
+METHOD(job_t, execute, void,
+ private_rekey_child_sa_job_t *this)
{
ike_sa_t *ike_sa;
@@ -82,16 +78,19 @@ rekey_child_sa_job_t *rekey_child_sa_job_create(u_int32_t reqid,
protocol_id_t protocol,
u_int32_t spi)
{
- private_rekey_child_sa_job_t *this = malloc_thing(private_rekey_child_sa_job_t);
-
- /* interface functions */
- this->public.job_interface.execute = (void (*) (job_t *)) execute;
- this->public.job_interface.destroy = (void (*)(job_t*)) destroy;
+ private_rekey_child_sa_job_t *this;
- /* private variables */
- this->reqid = reqid;
- this->protocol = protocol;
- this->spi = spi;
+ INIT(this,
+ .public = {
+ .job_interface = {
+ .execute = _execute,
+ .destroy = _destroy,
+ },
+ },
+ .reqid = reqid,
+ .protocol = protocol,
+ .spi = spi,
+ );
return &this->public;
}
diff --git a/src/libcharon/processing/jobs/rekey_ike_sa_job.c b/src/libcharon/processing/jobs/rekey_ike_sa_job.c
index 5ec0b1b88..dc86ba9b3 100644
--- a/src/libcharon/processing/jobs/rekey_ike_sa_job.c
+++ b/src/libcharon/processing/jobs/rekey_ike_sa_job.c
@@ -39,19 +39,15 @@ struct private_rekey_ike_sa_job_t {
bool reauth;
};
-/**
- * Implementation of job_t.destroy.
- */
-static void destroy(private_rekey_ike_sa_job_t *this)
+METHOD(job_t, destroy, void,
+ private_rekey_ike_sa_job_t *this)
{
this->ike_sa_id->destroy(this->ike_sa_id);
free(this);
}
-/**
- * Implementation of job_t.execute.
- */
-static void execute(private_rekey_ike_sa_job_t *this)
+METHOD(job_t, execute, void,
+ private_rekey_ike_sa_job_t *this)
{
ike_sa_t *ike_sa;
status_t status = SUCCESS;
@@ -90,15 +86,18 @@ static void execute(private_rekey_ike_sa_job_t *this)
*/
rekey_ike_sa_job_t *rekey_ike_sa_job_create(ike_sa_id_t *ike_sa_id, bool reauth)
{
- private_rekey_ike_sa_job_t *this = malloc_thing(private_rekey_ike_sa_job_t);
-
- /* interface functions */
- this->public.job_interface.execute = (void (*) (job_t *)) execute;
- this->public.job_interface.destroy = (void (*)(job_t*)) destroy;
+ private_rekey_ike_sa_job_t *this;
- /* private variables */
- this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
- this->reauth = reauth;
+ INIT(this,
+ .public = {
+ .job_interface = {
+ .execute = _execute,
+ .destroy = _destroy,
+ },
+ },
+ .ike_sa_id = ike_sa_id->clone(ike_sa_id),
+ .reauth = reauth,
+ );
return &(this->public);
}
diff --git a/src/libcharon/processing/jobs/retransmit_job.c b/src/libcharon/processing/jobs/retransmit_job.c
index fc787f208..1c78abd27 100644
--- a/src/libcharon/processing/jobs/retransmit_job.c
+++ b/src/libcharon/processing/jobs/retransmit_job.c
@@ -40,19 +40,15 @@ struct private_retransmit_job_t {
ike_sa_id_t *ike_sa_id;
};
-/**
- * Implements job_t.destroy.
- */
-static void destroy(private_retransmit_job_t *this)
+METHOD(job_t, destroy, void,
+ private_retransmit_job_t *this)
{
this->ike_sa_id->destroy(this->ike_sa_id);
free(this);
}
-/**
- * Implementation of job_t.execute.
- */
-static void execute(private_retransmit_job_t *this)
+METHOD(job_t, execute, void,
+ private_retransmit_job_t *this)
{
ike_sa_t *ike_sa;
@@ -79,15 +75,18 @@ static void execute(private_retransmit_job_t *this)
*/
retransmit_job_t *retransmit_job_create(u_int32_t message_id,ike_sa_id_t *ike_sa_id)
{
- private_retransmit_job_t *this = malloc_thing(private_retransmit_job_t);
-
- /* interface functions */
- this->public.job_interface.execute = (void (*) (job_t *)) execute;
- this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
+ private_retransmit_job_t *this;
- /* private variables */
- this->message_id = message_id;
- this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
+ INIT(this,
+ .public = {
+ .job_interface = {
+ .execute = _execute,
+ .destroy = _destroy,
+ },
+ },
+ .message_id = message_id,
+ .ike_sa_id = ike_sa_id->clone(ike_sa_id),
+ );
return &this->public;
}
diff --git a/src/libcharon/processing/jobs/roam_job.c b/src/libcharon/processing/jobs/roam_job.c
index adc884a8a..74ef8bd6d 100644
--- a/src/libcharon/processing/jobs/roam_job.c
+++ b/src/libcharon/processing/jobs/roam_job.c
@@ -38,18 +38,14 @@ struct private_roam_job_t {
bool address;
};
-/**
- * Implements job_t.destroy.
- */
-static void destroy(private_roam_job_t *this)
+METHOD(job_t, destroy, void,
+ private_roam_job_t *this)
{
free(this);
}
-/**
- * Implementation of job_t.execute.
- */
-static void execute(private_roam_job_t *this)
+METHOD(job_t, execute, void,
+ private_roam_job_t *this)
{
ike_sa_t *ike_sa;
linked_list_t *list;
@@ -94,12 +90,17 @@ static void execute(private_roam_job_t *this)
*/
roam_job_t *roam_job_create(bool address)
{
- private_roam_job_t *this = malloc_thing(private_roam_job_t);
-
- this->public.job_interface.execute = (void (*) (job_t *)) execute;
- this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
-
- this->address = address;
+ private_roam_job_t *this;
+
+ INIT(this,
+ .public = {
+ .job_interface = {
+ .execute = _execute,
+ .destroy = _destroy,
+ },
+ },
+ .address = address,
+ );
return &this->public;
}
diff --git a/src/libcharon/processing/jobs/send_dpd_job.c b/src/libcharon/processing/jobs/send_dpd_job.c
index 1c2da52b8..47b525363 100644
--- a/src/libcharon/processing/jobs/send_dpd_job.c
+++ b/src/libcharon/processing/jobs/send_dpd_job.c
@@ -38,19 +38,15 @@ struct private_send_dpd_job_t {
ike_sa_id_t *ike_sa_id;
};
-/**
- * Implements job_t.destroy.
- */
-static void destroy(private_send_dpd_job_t *this)
+METHOD(job_t, destroy, void,
+ private_send_dpd_job_t *this)
{
this->ike_sa_id->destroy(this->ike_sa_id);
free(this);
}
-/**
- * Implementation of job_t.execute.
- */
-static void execute(private_send_dpd_job_t *this)
+METHOD(job_t, execute, void,
+ private_send_dpd_job_t *this)
{
ike_sa_t *ike_sa;
@@ -75,14 +71,17 @@ static void execute(private_send_dpd_job_t *this)
*/
send_dpd_job_t *send_dpd_job_create(ike_sa_id_t *ike_sa_id)
{
- private_send_dpd_job_t *this = malloc_thing(private_send_dpd_job_t);
-
- /* interface functions */
- this->public.job_interface.execute = (void (*) (job_t *)) execute;
- this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
+ private_send_dpd_job_t *this;
- /* private variables */
- this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
+ INIT(this,
+ .public = {
+ .job_interface = {
+ .execute = _execute,
+ .destroy = _destroy,
+ },
+ },
+ .ike_sa_id = ike_sa_id->clone(ike_sa_id),
+ );
return &this->public;
}
diff --git a/src/libcharon/processing/jobs/send_keepalive_job.c b/src/libcharon/processing/jobs/send_keepalive_job.c
index 3d02cea2e..8d98aad7e 100644
--- a/src/libcharon/processing/jobs/send_keepalive_job.c
+++ b/src/libcharon/processing/jobs/send_keepalive_job.c
@@ -38,19 +38,15 @@ struct private_send_keepalive_job_t {
ike_sa_id_t *ike_sa_id;
};
-/**
- * Implements job_t.destroy.
- */
-static void destroy(private_send_keepalive_job_t *this)
+METHOD(job_t, destroy, void,
+ private_send_keepalive_job_t *this)
{
this->ike_sa_id->destroy(this->ike_sa_id);
free(this);
}
-/**
- * Implementation of job_t.execute.
- */
-static void execute(private_send_keepalive_job_t *this)
+METHOD(job_t, execute, void,
+ private_send_keepalive_job_t *this)
{
ike_sa_t *ike_sa;
@@ -69,14 +65,17 @@ static void execute(private_send_keepalive_job_t *this)
*/
send_keepalive_job_t *send_keepalive_job_create(ike_sa_id_t *ike_sa_id)
{
- private_send_keepalive_job_t *this = malloc_thing(private_send_keepalive_job_t);
-
- /* interface functions */
- this->public.job_interface.execute = (void (*) (job_t *)) execute;
- this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
+ private_send_keepalive_job_t *this;
- /* private variables */
- this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
+ INIT(this,
+ .public = {
+ .job_interface = {
+ .execute = _execute,
+ .destroy = _destroy,
+ },
+ },
+ .ike_sa_id = ike_sa_id->clone(ike_sa_id),
+ );
return &this->public;
}
diff --git a/src/libcharon/processing/jobs/start_action_job.c b/src/libcharon/processing/jobs/start_action_job.c
new file mode 100644
index 000000000..5dda18be2
--- /dev/null
+++ b/src/libcharon/processing/jobs/start_action_job.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "start_action_job.h"
+
+#include <daemon.h>
+
+
+typedef struct private_start_action_job_t private_start_action_job_t;
+
+/**
+ * Private data of an start_action_job_t object.
+ */
+struct private_start_action_job_t {
+ /**
+ * Public start_action_job_t interface.
+ */
+ start_action_job_t public;
+};
+
+METHOD(job_t, destroy, void,
+ private_start_action_job_t *this)
+{
+ free(this);
+}
+
+METHOD(job_t, execute, void,
+ private_start_action_job_t *this)
+{
+ enumerator_t *enumerator, *children;
+ peer_cfg_t *peer_cfg;
+ child_cfg_t *child_cfg;
+ char *name;
+
+ enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
+ NULL, NULL, NULL, NULL);
+ 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))
+ {
+ name = child_cfg->get_name(child_cfg);
+
+ switch (child_cfg->get_start_action(child_cfg))
+ {
+ case ACTION_RESTART:
+ DBG1(DBG_JOB, "start action: initiate '%s'", name);
+ charon->controller->initiate(charon->controller,
+ peer_cfg->get_ref(peer_cfg),
+ child_cfg->get_ref(child_cfg),
+ NULL, NULL);
+ break;
+ case ACTION_ROUTE:
+ DBG1(DBG_JOB, "start action: route '%s'", name);
+ charon->traps->install(charon->traps, peer_cfg, child_cfg);
+ break;
+ case ACTION_NONE:
+ break;
+ }
+ }
+ children->destroy(children);
+ }
+ enumerator->destroy(enumerator);
+ destroy(this);
+}
+
+/*
+ * Described in header
+ */
+start_action_job_t *start_action_job_create(void)
+{
+ private_start_action_job_t *this;
+
+ INIT(this,
+ .public = {
+ .job_interface = {
+ .execute = _execute,
+ .destroy = _destroy,
+ },
+ },
+ )
+ return &this->public;
+}
+
diff --git a/src/libcharon/processing/jobs/start_action_job.h b/src/libcharon/processing/jobs/start_action_job.h
new file mode 100644
index 000000000..ffc167c05
--- /dev/null
+++ b/src/libcharon/processing/jobs/start_action_job.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup start_action_job start_action_job
+ * @{ @ingroup cjobs
+ */
+
+#ifndef START_ACTION_JOB_H_
+#define START_ACTION_JOB_H_
+
+typedef struct start_action_job_t start_action_job_t;
+
+#include <library.h>
+#include <processing/jobs/job.h>
+
+/**
+ * Class representing a start_action Job.
+ *
+ * This job handles all child configurations stored in an [SQL database]
+ * backend according to their start_action field (start, route, none).
+ */
+struct start_action_job_t {
+ /**
+ * The job_t interface.
+ */
+ job_t job_interface;
+};
+
+/**
+ * Creates a job of type start_action.
+ *
+ * @return start_action_job_t object
+ */
+start_action_job_t *start_action_job_create(void);
+
+#endif /** START_ACTION_JOB_H_ @}*/
diff --git a/src/libcharon/processing/jobs/update_sa_job.c b/src/libcharon/processing/jobs/update_sa_job.c
index 17dce2548..3b4e9949f 100644
--- a/src/libcharon/processing/jobs/update_sa_job.c
+++ b/src/libcharon/processing/jobs/update_sa_job.c
@@ -43,19 +43,15 @@ struct private_update_sa_job_t {
host_t *new;
};
-/**
- * Implements job_t.destroy.
- */
-static void destroy(private_update_sa_job_t *this)
+METHOD(job_t, destroy, void,
+ private_update_sa_job_t *this)
{
this->new->destroy(this->new);
free(this);
}
-/**
- * Implementation of job_t.execute.
- */
-static void execute(private_update_sa_job_t *this)
+METHOD(job_t, execute, void,
+ private_update_sa_job_t *this)
{
ike_sa_t *ike_sa;
@@ -71,7 +67,7 @@ static void execute(private_update_sa_job_t *this)
if (ike_sa->has_condition(ike_sa, COND_NAT_THERE) &&
!ike_sa->has_condition(ike_sa, COND_NAT_HERE))
{
- ike_sa->update_hosts(ike_sa, NULL, this->new);
+ ike_sa->update_hosts(ike_sa, NULL, this->new, FALSE);
}
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
}
@@ -83,13 +79,18 @@ static void execute(private_update_sa_job_t *this)
*/
update_sa_job_t *update_sa_job_create(u_int32_t reqid, host_t *new)
{
- private_update_sa_job_t *this = malloc_thing(private_update_sa_job_t);
-
- this->public.job_interface.execute = (void (*) (job_t *)) execute;
- this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
-
- this->reqid = reqid;
- this->new = new;
+ private_update_sa_job_t *this;
+
+ INIT(this,
+ .public = {
+ .job_interface = {
+ .execute = _execute,
+ .destroy = _destroy,
+ },
+ },
+ .reqid = reqid,
+ .new = new,
+ );
return &this->public;
}
diff --git a/src/libcharon/sa/authenticators/authenticator.c b/src/libcharon/sa/authenticators/authenticator.c
index cd340e53e..83f5fbaad 100644
--- a/src/libcharon/sa/authenticators/authenticator.c
+++ b/src/libcharon/sa/authenticators/authenticator.c
@@ -39,7 +39,8 @@ ENUM_END(auth_method_names, AUTH_ECDSA_521);
*/
authenticator_t *authenticator_create_builder(ike_sa_t *ike_sa, auth_cfg_t *cfg,
chunk_t received_nonce, chunk_t sent_nonce,
- chunk_t received_init, chunk_t sent_init)
+ chunk_t received_init, chunk_t sent_init,
+ char reserved[3])
{
switch ((uintptr_t)cfg->get(cfg, AUTH_RULE_AUTH_CLASS))
{
@@ -47,13 +48,14 @@ authenticator_t *authenticator_create_builder(ike_sa_t *ike_sa, auth_cfg_t *cfg,
/* defaults to PUBKEY */
case AUTH_CLASS_PUBKEY:
return (authenticator_t*)pubkey_authenticator_create_builder(ike_sa,
- received_nonce, sent_init);
+ received_nonce, sent_init, reserved);
case AUTH_CLASS_PSK:
return (authenticator_t*)psk_authenticator_create_builder(ike_sa,
- received_nonce, sent_init);
+ received_nonce, sent_init, reserved);
case AUTH_CLASS_EAP:
return (authenticator_t*)eap_authenticator_create_builder(ike_sa,
- received_nonce, sent_nonce, received_init, sent_init);
+ received_nonce, sent_nonce,
+ received_init, sent_init, reserved);
default:
return NULL;
}
@@ -65,7 +67,8 @@ authenticator_t *authenticator_create_builder(ike_sa_t *ike_sa, auth_cfg_t *cfg,
authenticator_t *authenticator_create_verifier(
ike_sa_t *ike_sa, message_t *message,
chunk_t received_nonce, chunk_t sent_nonce,
- chunk_t received_init, chunk_t sent_init)
+ chunk_t received_init, chunk_t sent_init,
+ char reserved[3])
{
auth_payload_t *auth_payload;
@@ -73,7 +76,8 @@ authenticator_t *authenticator_create_verifier(
if (auth_payload == NULL)
{
return (authenticator_t*)eap_authenticator_create_verifier(ike_sa,
- received_nonce, sent_nonce, received_init, sent_init);
+ received_nonce, sent_nonce,
+ received_init, sent_init, reserved);
}
switch (auth_payload->get_auth_method(auth_payload))
{
@@ -82,10 +86,10 @@ authenticator_t *authenticator_create_verifier(
case AUTH_ECDSA_384:
case AUTH_ECDSA_521:
return (authenticator_t*)pubkey_authenticator_create_verifier(ike_sa,
- sent_nonce, received_init);
+ sent_nonce, received_init, reserved);
case AUTH_PSK:
return (authenticator_t*)psk_authenticator_create_verifier(ike_sa,
- sent_nonce, received_init);
+ sent_nonce, received_init, reserved);
default:
return NULL;
}
diff --git a/src/libcharon/sa/authenticators/authenticator.h b/src/libcharon/sa/authenticators/authenticator.h
index 89178b5cf..d27e006a3 100644
--- a/src/libcharon/sa/authenticators/authenticator.h
+++ b/src/libcharon/sa/authenticators/authenticator.h
@@ -130,12 +130,14 @@ struct authenticator_t {
* @param sent_nonce nonce sent in IKE_SA_INIT
* @param received_init received IKE_SA_INIT message data
* @param sent_init sent IKE_SA_INIT message data
+ * @param reserved reserved bytes of the ID payload
* @return authenticator, NULL if not supported
*/
authenticator_t *authenticator_create_builder(
ike_sa_t *ike_sa, auth_cfg_t *cfg,
chunk_t received_nonce, chunk_t sent_nonce,
- chunk_t received_init, chunk_t sent_init);
+ chunk_t received_init, chunk_t sent_init,
+ char reserved[3]);
/**
* Create an authenticator to verify signatures.
@@ -146,11 +148,13 @@ authenticator_t *authenticator_create_builder(
* @param sent_nonce nonce sent in IKE_SA_INIT
* @param received_init received IKE_SA_INIT message data
* @param sent_init sent IKE_SA_INIT message data
+ * @param reserved reserved bytes of the ID payload
* @return authenticator, NULL if not supported
*/
authenticator_t *authenticator_create_verifier(
ike_sa_t *ike_sa, message_t *message,
chunk_t received_nonce, chunk_t sent_nonce,
- chunk_t received_init, chunk_t sent_init);
+ chunk_t received_init, chunk_t sent_init,
+ char reserved[3]);
#endif /** AUTHENTICATOR_H_ @}*/
diff --git a/src/libcharon/sa/authenticators/eap_authenticator.c b/src/libcharon/sa/authenticators/eap_authenticator.c
index 8b22fd1d7..dea02755d 100644
--- a/src/libcharon/sa/authenticators/eap_authenticator.c
+++ b/src/libcharon/sa/authenticators/eap_authenticator.c
@@ -58,6 +58,11 @@ struct private_eap_authenticator_t {
chunk_t sent_init;
/**
+ * Reserved bytes of ID payload
+ */
+ char reserved[3];
+
+ /**
* Current EAP method processing
*/
eap_method_t *method;
@@ -422,7 +427,7 @@ static bool verify_auth(private_eap_authenticator_t *this, message_t *message,
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->msk, other_id, this->reserved);
recv_auth_data = auth_payload->get_data(auth_payload);
if (!auth_data.len || !chunk_equals(auth_data, recv_auth_data))
{
@@ -458,7 +463,8 @@ static void build_auth(private_eap_authenticator_t *this, message_t *message,
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);
+ auth_data = keymat->get_psk_sig(keymat, FALSE, init, nonce,
+ this->msk, my_id, this->reserved);
auth_payload = auth_payload_create();
auth_payload->set_auth_method(auth_payload, AUTH_PSK);
auth_payload->set_data(auth_payload, auth_data);
@@ -642,7 +648,8 @@ METHOD(authenticator_t, destroy, void,
*/
eap_authenticator_t *eap_authenticator_create_builder(ike_sa_t *ike_sa,
chunk_t received_nonce, chunk_t sent_nonce,
- chunk_t received_init, chunk_t sent_init)
+ chunk_t received_init, chunk_t sent_init,
+ char reserved[3])
{
private_eap_authenticator_t *this;
@@ -661,6 +668,7 @@ eap_authenticator_t *eap_authenticator_create_builder(ike_sa_t *ike_sa,
.sent_init = sent_init,
.sent_nonce = sent_nonce,
);
+ memcpy(this->reserved, reserved, sizeof(this->reserved));
return &this->public;
}
@@ -670,7 +678,8 @@ eap_authenticator_t *eap_authenticator_create_builder(ike_sa_t *ike_sa,
*/
eap_authenticator_t *eap_authenticator_create_verifier(ike_sa_t *ike_sa,
chunk_t received_nonce, chunk_t sent_nonce,
- chunk_t received_init, chunk_t sent_init)
+ chunk_t received_init, chunk_t sent_init,
+ char reserved[3])
{
private_eap_authenticator_t *this;
@@ -689,6 +698,7 @@ eap_authenticator_t *eap_authenticator_create_verifier(ike_sa_t *ike_sa,
.sent_init = sent_init,
.sent_nonce = sent_nonce,
);
+ memcpy(this->reserved, reserved, sizeof(this->reserved));
return &this->public;
}
diff --git a/src/libcharon/sa/authenticators/eap_authenticator.h b/src/libcharon/sa/authenticators/eap_authenticator.h
index 41eb6a8c9..726411a18 100644
--- a/src/libcharon/sa/authenticators/eap_authenticator.h
+++ b/src/libcharon/sa/authenticators/eap_authenticator.h
@@ -75,11 +75,13 @@ struct eap_authenticator_t {
* @param sent_nonce nonce sent in IKE_SA_INIT
* @param received_init received IKE_SA_INIT message data
* @param sent_init sent IKE_SA_INIT message data
+ * @param reserved reserved bytes of ID payload
* @return EAP authenticator
*/
eap_authenticator_t *eap_authenticator_create_builder(ike_sa_t *ike_sa,
chunk_t received_nonce, chunk_t sent_nonce,
- chunk_t received_init, chunk_t sent_init);
+ chunk_t received_init, chunk_t sent_init,
+ char reserved[3]);
/**
* Create an authenticator to authenticate EAP clients.
@@ -89,10 +91,12 @@ eap_authenticator_t *eap_authenticator_create_builder(ike_sa_t *ike_sa,
* @param sent_nonce nonce sent in IKE_SA_INIT
* @param received_init received IKE_SA_INIT message data
* @param sent_init sent IKE_SA_INIT message data
+ * @param reserved reserved bytes of ID payload
* @return EAP authenticator
*/
eap_authenticator_t *eap_authenticator_create_verifier(ike_sa_t *ike_sa,
chunk_t received_nonce, chunk_t sent_nonce,
- chunk_t received_init, chunk_t sent_init);
+ chunk_t received_init, chunk_t sent_init,
+ char reserved[3]);
#endif /** EAP_AUTHENTICATOR_H_ @}*/
diff --git a/src/libcharon/sa/authenticators/psk_authenticator.c b/src/libcharon/sa/authenticators/psk_authenticator.c
index e69f30dcf..21fc0f9b8 100644
--- a/src/libcharon/sa/authenticators/psk_authenticator.c
+++ b/src/libcharon/sa/authenticators/psk_authenticator.c
@@ -45,12 +45,15 @@ struct private_psk_authenticator_t {
* IKE_SA_INIT message data to include in AUTH calculation
*/
chunk_t ike_sa_init;
+
+ /**
+ * Reserved bytes of ID payload
+ */
+ char reserved[3];
};
-/*
- * Implementation of authenticator_t.build for builder
- */
-static status_t build(private_psk_authenticator_t *this, message_t *message)
+METHOD(authenticator_t, build, status_t,
+ private_psk_authenticator_t *this, message_t *message)
{
identification_t *my_id, *other_id;
auth_payload_t *auth_payload;
@@ -70,7 +73,7 @@ static status_t build(private_psk_authenticator_t *this, message_t *message)
return NOT_FOUND;
}
auth_data = keymat->get_psk_sig(keymat, FALSE, this->ike_sa_init,
- this->nonce, key->get_key(key), my_id);
+ this->nonce, key->get_key(key), my_id, this->reserved);
key->destroy(key);
DBG2(DBG_IKE, "successfully created shared key MAC");
auth_payload = auth_payload_create();
@@ -82,10 +85,8 @@ static status_t build(private_psk_authenticator_t *this, message_t *message)
return SUCCESS;
}
-/**
- * Implementation of authenticator_t.process for verifier
- */
-static status_t process(private_psk_authenticator_t *this, message_t *message)
+METHOD(authenticator_t, process, status_t,
+ private_psk_authenticator_t *this, message_t *message)
{
chunk_t auth_data, recv_auth_data;
identification_t *my_id, *other_id;
@@ -113,7 +114,7 @@ static status_t process(private_psk_authenticator_t *this, message_t *message)
keys_found++;
auth_data = keymat->get_psk_sig(keymat, TRUE, this->ike_sa_init,
- this->nonce, key->get_key(key), other_id);
+ this->nonce, key->get_key(key), other_id, this->reserved);
if (auth_data.len && chunk_equals(auth_data, recv_auth_data))
{
DBG1(DBG_IKE, "authentication of '%Y' with %N successful",
@@ -141,19 +142,8 @@ static status_t process(private_psk_authenticator_t *this, message_t *message)
return SUCCESS;
}
-/**
- * Implementation of authenticator_t.process for builder
- * Implementation of authenticator_t.build for verifier
- */
-static status_t return_failed()
-{
- return FAILED;
-}
-
-/**
- * Implementation of authenticator_t.destroy.
- */
-static void destroy(private_psk_authenticator_t *this)
+METHOD(authenticator_t, destroy, void,
+ private_psk_authenticator_t *this)
{
free(this);
}
@@ -162,18 +152,25 @@ static void destroy(private_psk_authenticator_t *this)
* Described in header.
*/
psk_authenticator_t *psk_authenticator_create_builder(ike_sa_t *ike_sa,
- chunk_t received_nonce, chunk_t sent_init)
+ chunk_t received_nonce, chunk_t sent_init,
+ char reserved[3])
{
- private_psk_authenticator_t *this = malloc_thing(private_psk_authenticator_t);
-
- this->public.authenticator.build = (status_t(*)(authenticator_t*, message_t *message))build;
- this->public.authenticator.process = (status_t(*)(authenticator_t*, message_t *message))return_failed;
- this->public.authenticator.is_mutual = (bool(*)(authenticator_t*))return_false;
- this->public.authenticator.destroy = (void(*)(authenticator_t*))destroy;
-
- this->ike_sa = ike_sa;
- this->ike_sa_init = sent_init;
- this->nonce = received_nonce;
+ private_psk_authenticator_t *this;
+
+ INIT(this,
+ .public = {
+ .authenticator = {
+ .build = _build,
+ .process = (void*)return_failed,
+ .is_mutual = (void*)return_false,
+ .destroy = _destroy,
+ },
+ },
+ .ike_sa = ike_sa,
+ .ike_sa_init = sent_init,
+ .nonce = received_nonce,
+ );
+ memcpy(this->reserved, reserved, sizeof(this->reserved));
return &this->public;
}
@@ -182,18 +179,25 @@ psk_authenticator_t *psk_authenticator_create_builder(ike_sa_t *ike_sa,
* Described in header.
*/
psk_authenticator_t *psk_authenticator_create_verifier(ike_sa_t *ike_sa,
- chunk_t sent_nonce, chunk_t received_init)
+ chunk_t sent_nonce, chunk_t received_init,
+ char reserved[3])
{
- private_psk_authenticator_t *this = malloc_thing(private_psk_authenticator_t);
-
- this->public.authenticator.build = (status_t(*)(authenticator_t*, message_t *messageh))return_failed;
- this->public.authenticator.process = (status_t(*)(authenticator_t*, message_t *message))process;
- this->public.authenticator.is_mutual = (bool(*)(authenticator_t*))return_false;
- this->public.authenticator.destroy = (void(*)(authenticator_t*))destroy;
-
- this->ike_sa = ike_sa;
- this->ike_sa_init = received_init;
- this->nonce = sent_nonce;
+ private_psk_authenticator_t *this;
+
+ INIT(this,
+ .public = {
+ .authenticator = {
+ .build = (void*)return_failed,
+ .process = _process,
+ .is_mutual = (void*)return_false,
+ .destroy = _destroy,
+ },
+ },
+ .ike_sa = ike_sa,
+ .ike_sa_init = received_init,
+ .nonce = sent_nonce,
+ );
+ memcpy(this->reserved, reserved, sizeof(this->reserved));
return &this->public;
}
diff --git a/src/libcharon/sa/authenticators/psk_authenticator.h b/src/libcharon/sa/authenticators/psk_authenticator.h
index 0fab11095..8cf1a0f98 100644
--- a/src/libcharon/sa/authenticators/psk_authenticator.h
+++ b/src/libcharon/sa/authenticators/psk_authenticator.h
@@ -42,10 +42,12 @@ struct psk_authenticator_t {
* @param ike_sa associated ike_sa
* @param received_nonce nonce received in IKE_SA_INIT
* @param sent_init sent IKE_SA_INIT message data
+ * @param reserved reserved bytes of ID payload
* @return PSK authenticator
*/
psk_authenticator_t *psk_authenticator_create_builder(ike_sa_t *ike_sa,
- chunk_t received_nonce, chunk_t sent_init);
+ chunk_t received_nonce, chunk_t sent_init,
+ char reserved[3]);
/**
* Create an authenticator to verify PSK signatures.
@@ -53,9 +55,11 @@ psk_authenticator_t *psk_authenticator_create_builder(ike_sa_t *ike_sa,
* @param ike_sa associated ike_sa
* @param sent_nonce nonce sent in IKE_SA_INIT
* @param received_init received IKE_SA_INIT message data
+ * @param reserved reserved bytes of ID payload
* @return PSK authenticator
*/
psk_authenticator_t *psk_authenticator_create_verifier(ike_sa_t *ike_sa,
- chunk_t sent_nonce, chunk_t received_init);
+ chunk_t sent_nonce, chunk_t received_init,
+ char reserved[3]);
#endif /** PSK_AUTHENTICATOR_H_ @}*/
diff --git a/src/libcharon/sa/authenticators/pubkey_authenticator.c b/src/libcharon/sa/authenticators/pubkey_authenticator.c
index 54b4338bb..247891670 100644
--- a/src/libcharon/sa/authenticators/pubkey_authenticator.c
+++ b/src/libcharon/sa/authenticators/pubkey_authenticator.c
@@ -46,12 +46,15 @@ struct private_pubkey_authenticator_t {
* IKE_SA_INIT message data to include in AUTH calculation
*/
chunk_t ike_sa_init;
+
+ /**
+ * Reserved bytes of ID payload
+ */
+ char reserved[3];
};
-/**
- * Implementation of authenticator_t.build for builder
- */
-static status_t build(private_pubkey_authenticator_t *this, message_t *message)
+METHOD(authenticator_t, build, status_t,
+ private_pubkey_authenticator_t *this, message_t *message)
{
chunk_t octets, auth_data;
status_t status = FAILED;
@@ -109,7 +112,7 @@ static status_t build(private_pubkey_authenticator_t *this, message_t *message)
}
keymat = this->ike_sa->get_keymat(this->ike_sa);
octets = keymat->get_auth_octets(keymat, FALSE, this->ike_sa_init,
- this->nonce, id);
+ this->nonce, id, this->reserved);
if (private->sign(private, scheme, octets, &auth_data))
{
auth_payload = auth_payload_create();
@@ -128,10 +131,8 @@ static status_t build(private_pubkey_authenticator_t *this, message_t *message)
return status;
}
-/**
- * Implementation of authenticator_t.process for verifier
- */
-static status_t process(private_pubkey_authenticator_t *this, message_t *message)
+METHOD(authenticator_t, process, status_t,
+ private_pubkey_authenticator_t *this, message_t *message)
{
public_key_t *public;
auth_method_t auth_method;
@@ -175,7 +176,7 @@ static status_t process(private_pubkey_authenticator_t *this, message_t *message
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->nonce, id, this->reserved);
auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
enumerator = lib->credmgr->create_public_enumerator(lib->credmgr,
key_type, id, auth);
@@ -206,19 +207,8 @@ static status_t process(private_pubkey_authenticator_t *this, message_t *message
return status;
}
-/**
- * Implementation of authenticator_t.process for builder
- * Implementation of authenticator_t.build for verifier
- */
-static status_t return_failed()
-{
- return FAILED;
-}
-
-/**
- * Implementation of authenticator_t.destroy.
- */
-static void destroy(private_pubkey_authenticator_t *this)
+METHOD(authenticator_t, destroy, void,
+ private_pubkey_authenticator_t *this)
{
free(this);
}
@@ -227,18 +217,25 @@ static void destroy(private_pubkey_authenticator_t *this)
* Described in header.
*/
pubkey_authenticator_t *pubkey_authenticator_create_builder(ike_sa_t *ike_sa,
- chunk_t received_nonce, chunk_t sent_init)
+ chunk_t received_nonce, chunk_t sent_init,
+ char reserved[3])
{
- private_pubkey_authenticator_t *this = malloc_thing(private_pubkey_authenticator_t);
+ private_pubkey_authenticator_t *this;
- this->public.authenticator.build = (status_t(*)(authenticator_t*, message_t *message))build;
- this->public.authenticator.process = (status_t(*)(authenticator_t*, message_t *message))return_failed;
- this->public.authenticator.is_mutual = (bool(*)(authenticator_t*))return_false;
- this->public.authenticator.destroy = (void(*)(authenticator_t*))destroy;
-
- this->ike_sa = ike_sa;
- this->ike_sa_init = sent_init;
- this->nonce = received_nonce;
+ INIT(this,
+ .public = {
+ .authenticator = {
+ .build = _build,
+ .process = (void*)return_failed,
+ .is_mutual = (void*)return_false,
+ .destroy = _destroy,
+ },
+ },
+ .ike_sa = ike_sa,
+ .ike_sa_init = sent_init,
+ .nonce = received_nonce,
+ );
+ memcpy(this->reserved, reserved, sizeof(this->reserved));
return &this->public;
}
@@ -247,18 +244,25 @@ pubkey_authenticator_t *pubkey_authenticator_create_builder(ike_sa_t *ike_sa,
* Described in header.
*/
pubkey_authenticator_t *pubkey_authenticator_create_verifier(ike_sa_t *ike_sa,
- chunk_t sent_nonce, chunk_t received_init)
+ chunk_t sent_nonce, chunk_t received_init,
+ char reserved[3])
{
- private_pubkey_authenticator_t *this = malloc_thing(private_pubkey_authenticator_t);
-
- this->public.authenticator.build = (status_t(*)(authenticator_t*, message_t *message))return_failed;
- this->public.authenticator.process = (status_t(*)(authenticator_t*, message_t *message))process;
- this->public.authenticator.is_mutual = (bool(*)(authenticator_t*))return_false;
- this->public.authenticator.destroy = (void(*)(authenticator_t*))destroy;
+ private_pubkey_authenticator_t *this;
- this->ike_sa = ike_sa;
- this->ike_sa_init = received_init;
- this->nonce = sent_nonce;
+ INIT(this,
+ .public = {
+ .authenticator = {
+ .build = (void*)return_failed,
+ .process = _process,
+ .is_mutual = (void*)return_false,
+ .destroy = _destroy,
+ },
+ },
+ .ike_sa = ike_sa,
+ .ike_sa_init = received_init,
+ .nonce = sent_nonce,
+ );
+ memcpy(this->reserved, reserved, sizeof(this->reserved));
return &this->public;
}
diff --git a/src/libcharon/sa/authenticators/pubkey_authenticator.h b/src/libcharon/sa/authenticators/pubkey_authenticator.h
index be369cb89..4c3937ecc 100644
--- a/src/libcharon/sa/authenticators/pubkey_authenticator.h
+++ b/src/libcharon/sa/authenticators/pubkey_authenticator.h
@@ -43,10 +43,12 @@ struct pubkey_authenticator_t {
* @param ike_sa associated ike_sa
* @param received_nonce nonce received in IKE_SA_INIT
* @param sent_init sent IKE_SA_INIT message data
+ * @param reserved reserved bytes of ID payload
* @return public key authenticator
*/
pubkey_authenticator_t *pubkey_authenticator_create_builder(ike_sa_t *ike_sa,
- chunk_t received_nonce, chunk_t sent_init);
+ chunk_t received_nonce, chunk_t sent_init,
+ char reserved[3]);
/**
* Create an authenticator to verify public key signatures.
@@ -54,9 +56,11 @@ pubkey_authenticator_t *pubkey_authenticator_create_builder(ike_sa_t *ike_sa,
* @param ike_sa associated ike_sa
* @param sent_nonce nonce sent in IKE_SA_INIT
* @param received_init received IKE_SA_INIT message data
+ * @param reserved reserved bytes of ID payload
* @return public key authenticator
*/
pubkey_authenticator_t *pubkey_authenticator_create_verifier(ike_sa_t *ike_sa,
- chunk_t sent_nonce, chunk_t received_init);
+ chunk_t sent_nonce, chunk_t received_init,
+ char reserved[3]);
#endif /** PUBKEY_AUTHENTICATOR_H_ @}*/
diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c
index b6ef31da0..495929965 100644
--- a/src/libcharon/sa/child_sa.c
+++ b/src/libcharon/sa/child_sa.c
@@ -559,13 +559,14 @@ METHOD(child_sa_t, alloc_cpi, u_int16_t,
METHOD(child_sa_t, install, status_t,
private_child_sa_t *this, chunk_t encr, chunk_t integ, u_int32_t spi,
- u_int16_t cpi, bool inbound, linked_list_t *my_ts,
+ u_int16_t cpi, bool inbound, bool tfcv3, linked_list_t *my_ts,
linked_list_t *other_ts)
{
u_int16_t enc_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED, size;
traffic_selector_t *src_ts = NULL, *dst_ts = NULL;
time_t now;
lifetime_cfg_t *lifetime;
+ u_int32_t tfc = 0;
host_t *src, *dst;
status_t status;
bool update = FALSE;
@@ -590,6 +591,11 @@ METHOD(child_sa_t, install, status_t,
dst = this->other_addr;
this->other_spi = spi;
this->other_cpi = cpi;
+
+ if (tfcv3)
+ {
+ tfc = this->config->get_tfc(this->config);
+ }
}
DBG2(DBG_CHD, "adding %s %N SA", inbound ? "inbound" : "outbound",
@@ -620,7 +626,7 @@ METHOD(child_sa_t, install, status_t,
lifetime->time.rekey = 0;
}
- if (this->mode == MODE_BEET)
+ if (this->mode == MODE_BEET || this->mode == MODE_TRANSPORT)
{
/* BEET requires the bound address from the traffic selectors.
* TODO: We add just the first traffic selector for now, as the
@@ -639,7 +645,7 @@ METHOD(child_sa_t, install, status_t,
status = hydra->kernel_interface->add_sa(hydra->kernel_interface,
src, dst, spi, proto_ike2ip(this->protocol), this->reqid,
- inbound ? this->mark_in : this->mark_out,
+ inbound ? this->mark_in : this->mark_out, tfc,
lifetime, enc_alg, encr, int_alg, integ, this->mode,
this->ipcomp, cpi, this->encap, update, src_ts, dst_ts);
diff --git a/src/libcharon/sa/child_sa.h b/src/libcharon/sa/child_sa.h
index 95bc297b0..f17ef01ac 100644
--- a/src/libcharon/sa/child_sa.h
+++ b/src/libcharon/sa/child_sa.h
@@ -313,12 +313,13 @@ struct child_sa_t {
* @param spi SPI to use, allocated for inbound
* @param cpi CPI to use, allocated for outbound
* @param inbound TRUE to install an inbound SA, FALSE for outbound
+ * @param tfcv3 TRUE if peer supports ESPv3 TFC
* @param my_ts negotiated local traffic selector list
* @param other_ts negotiated remote traffic selector list
* @return SUCCESS or FAILED
*/
status_t (*install)(child_sa_t *this, chunk_t encr, chunk_t integ,
- u_int32_t spi, u_int16_t cpi, bool inbound,
+ u_int32_t spi, u_int16_t cpi, bool inbound, bool tfcv3,
linked_list_t *my_ts, linked_list_t *other_ts);
/**
* Install the policies using some traffic selectors.
diff --git a/src/libcharon/sa/connect_manager.c b/src/libcharon/sa/connect_manager.c
index 1fb286863..972cc98ad 100644
--- a/src/libcharon/sa/connect_manager.c
+++ b/src/libcharon/sa/connect_manager.c
@@ -1194,7 +1194,10 @@ static job_requeue_t initiate_mediated(initiate_data_t *data)
DBG1(DBG_IKE, "establishing mediated connection failed");
charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, sa);
}
- charon->ike_sa_manager->checkin(charon->ike_sa_manager, sa);
+ else
+ {
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, sa);
+ }
}
iterator->destroy(iterator);
}
diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c
index a4e4028ab..9b6f9d06d 100644
--- a/src/libcharon/sa/ike_sa.c
+++ b/src/libcharon/sa/ike_sa.c
@@ -50,6 +50,7 @@
#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>
#ifdef ME
#include <sa/tasks/ike_me.h>
@@ -559,13 +560,6 @@ METHOD(ike_sa_t, send_dpd, status_t,
time_t diff, delay;
delay = this->peer_cfg->get_dpd(this->peer_cfg);
-
- if (delay == 0)
- {
- /* DPD disabled */
- return SUCCESS;
- }
-
if (this->task_manager->busy(this->task_manager))
{
/* an exchange is in the air, no need to start a DPD check */
@@ -578,7 +572,7 @@ METHOD(ike_sa_t, send_dpd, status_t,
last_in = get_use_time(this, TRUE);
now = time_monotonic(NULL);
diff = now - last_in;
- if (diff >= delay)
+ if (!delay || diff >= delay)
{
/* to long ago, initiate dead peer detection */
task_t *task;
@@ -604,8 +598,11 @@ METHOD(ike_sa_t, send_dpd, status_t,
}
}
/* recheck in "interval" seconds */
- job = (job_t*)send_dpd_job_create(this->ike_sa_id);
- lib->scheduler->schedule_job(lib->scheduler, job, delay - diff);
+ if (delay)
+ {
+ job = (job_t*)send_dpd_job_create(this->ike_sa_id);
+ lib->scheduler->schedule_job(lib->scheduler, job, delay - diff);
+ }
return SUCCESS;
}
@@ -680,7 +677,10 @@ METHOD(ike_sa_t, set_state, void,
}
/* start DPD checks */
- send_dpd(this);
+ if (this->peer_cfg->get_dpd(this->peer_cfg))
+ {
+ send_dpd(this);
+ }
}
break;
}
@@ -825,7 +825,7 @@ METHOD(ike_sa_t, float_ports, void,
}
METHOD(ike_sa_t, update_hosts, void,
- private_ike_sa_t *this, host_t *me, host_t *other)
+ private_ike_sa_t *this, host_t *me, host_t *other, bool force)
{
bool update = FALSE;
@@ -858,7 +858,7 @@ METHOD(ike_sa_t, update_hosts, void,
if (!other->equals(other, this->other_host))
{
/* update others adress if we are NOT NATed */
- if (!has_condition(this, COND_NAT_HERE))
+ if (force || !has_condition(this, COND_NAT_HERE))
{
set_other_host(this, other->clone(other));
update = TRUE;
@@ -891,8 +891,14 @@ 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)
{
+ if (message->is_encoded(message))
+ { /* already done */
+ *packet = message->get_packet(message);
+ return SUCCESS;
+ }
this->stats[STAT_OUTBOUND] = time_monotonic(NULL);
message->set_ike_sa_id(message, this->ike_sa_id);
+ charon->bus->message(charon->bus, message, FALSE);
return message->generate(message,
this->keymat->get_aead(this->keymat, FALSE), packet);
}
@@ -901,7 +907,7 @@ METHOD(ike_sa_t, generate_message, status_t,
* send a notify back to the sender
*/
static void send_notify_response(private_ike_sa_t *this, message_t *request,
- notify_type_t type)
+ notify_type_t type, chunk_t data)
{
message_t *response;
packet_t *packet;
@@ -910,7 +916,7 @@ static void send_notify_response(private_ike_sa_t *this, message_t *request,
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, chunk_empty);
+ response->add_notify(response, FALSE, type, data);
if (this->my_host->is_anyaddr(this->my_host))
{
this->my_host->destroy(this->my_host);
@@ -1175,6 +1181,7 @@ METHOD(ike_sa_t, process_message, status_t,
{
status_t status;
bool is_request;
+ u_int8_t type = 0;
if (this->state == IKE_PASSIVE)
{ /* do not handle messages in passive state */
@@ -1185,9 +1192,29 @@ METHOD(ike_sa_t, process_message, status_t,
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))
+ {
+ DBG1(DBG_ENC, "payload type %N is not supported, "
+ "but its critical!", payload_type_names, type);
+ status = NOT_SUPPORTED;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
if (status != SUCCESS)
{
-
if (is_request)
{
switch (status)
@@ -1196,21 +1223,28 @@ METHOD(ike_sa_t, process_message, status_t,
DBG1(DBG_IKE, "critical unknown payloads found");
if (is_request)
{
- send_notify_response(this, message, UNSUPPORTED_CRITICAL_PAYLOAD);
+ 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);
+ 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);
+ send_notify_response(this, message,
+ INVALID_SYNTAX, chunk_empty);
+ this->task_manager->incr_mid(this->task_manager, FALSE);
}
break;
case FAILED:
@@ -1219,10 +1253,6 @@ METHOD(ike_sa_t, process_message, status_t,
break;
case INVALID_STATE:
DBG1(DBG_IKE, "found encrypted message, but no keys available");
- if (is_request)
- {
- send_notify_response(this, message, INVALID_SYNTAX);
- }
default:
break;
}
@@ -1252,7 +1282,8 @@ METHOD(ike_sa_t, process_message, status_t,
/* 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);
+ send_notify_response(this, message,
+ NO_PROPOSAL_CHOSEN, chunk_empty);
return DESTROY_ME;
}
/* add a timeout if peer does not establish it completely */
diff --git a/src/libcharon/sa/ike_sa.h b/src/libcharon/sa/ike_sa.h
index c0007e27d..988100bcc 100644
--- a/src/libcharon/sa/ike_sa.h
+++ b/src/libcharon/sa/ike_sa.h
@@ -343,8 +343,9 @@ struct ike_sa_t {
*
* @param me new local host address, or NULL
* @param other new remote host address, or NULL
+ * @param force force update
*/
- void (*update_hosts)(ike_sa_t *this, host_t *me, host_t *other);
+ void (*update_hosts)(ike_sa_t *this, host_t *me, host_t *other, bool force);
/**
* Get the own identification.
diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c
index fa94bb86d..d695c7f7c 100644
--- a/src/libcharon/sa/ike_sa_manager.c
+++ b/src/libcharon/sa/ike_sa_manager.c
@@ -1,6 +1,7 @@
/*
+ * Copyright (C) 2005-2011 Martin Willi
+ * Copyright (C) 2011 revosec AG
* Copyright (C) 2008 Tobias Brunner
- * Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -85,7 +86,9 @@ struct entry_t {
chunk_t init_hash;
/**
- * remote host address, required for DoS detection
+ * remote host address, required for DoS detection and duplicate
+ * checking (host with same my_id and other_id is *not* considered
+ * a duplicate if the address family differs)
*/
host_t *other;
@@ -241,6 +244,9 @@ struct connected_peers_t {
/** remote identity */
identification_t *other_id;
+ /** ip address family of peer */
+ int family;
+
/** list of ike_sa_id_t objects of IKE_SAs between the two identities */
linked_list_t *sas;
};
@@ -257,10 +263,12 @@ 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,
- identification_t *my_id, identification_t *other_id)
+ identification_t *my_id, identification_t *other_id,
+ uintptr_t family)
{
return my_id->equals(my_id, connected_peers->my_id) &&
- other_id->equals(other_id, connected_peers->other_id);
+ other_id->equals(other_id, connected_peers->other_id) &&
+ family == connected_peers->family;
}
typedef struct segment_t segment_t;
@@ -396,7 +404,7 @@ static void lock_all_segments(private_ike_sa_manager_t *this)
{
u_int i;
- for (i = 0; i < this->segment_count; ++i)
+ for (i = 0; i < this->segment_count; i++)
{
this->segments[i].mutex->lock(this->segments[i].mutex);
}
@@ -409,7 +417,7 @@ static void unlock_all_segments(private_ike_sa_manager_t *this)
{
u_int i;
- for (i = 0; i < this->segment_count; ++i)
+ for (i = 0; i < this->segment_count; i++)
{
this->segments[i].mutex->unlock(this->segments[i].mutex);
}
@@ -453,10 +461,8 @@ struct private_enumerator_t {
enumerator_t *current;
};
-/**
- * Implementation of private_enumerator_t.enumerator.enumerate.
- */
-static bool enumerate(private_enumerator_t *this, entry_t **entry, u_int *segment)
+METHOD(enumerator_t, enumerate, bool,
+ private_enumerator_t *this, entry_t **entry, u_int *segment)
{
if (this->entry)
{
@@ -502,10 +508,8 @@ static bool enumerate(private_enumerator_t *this, entry_t **entry, u_int *segmen
return FALSE;
}
-/**
- * Implementation of private_enumerator_t.enumerator.destroy.
- */
-static void enumerator_destroy(private_enumerator_t *this)
+METHOD(enumerator_t, enumerator_destroy, void,
+ private_enumerator_t *this)
{
if (this->entry)
{
@@ -524,16 +528,15 @@ static void enumerator_destroy(private_enumerator_t *this)
*/
static enumerator_t* create_table_enumerator(private_ike_sa_manager_t *this)
{
- private_enumerator_t *enumerator = malloc_thing(private_enumerator_t);
-
- enumerator->enumerator.enumerate = (void*)enumerate;
- enumerator->enumerator.destroy = (void*)enumerator_destroy;
- enumerator->manager = this;
- enumerator->segment = 0;
- enumerator->entry = NULL;
- enumerator->row = 0;
- enumerator->current = NULL;
-
+ private_enumerator_t *enumerator;
+
+ INIT(enumerator,
+ .enumerator = {
+ .enumerate = (void*)_enumerate,
+ .destroy = _enumerator_destroy,
+ },
+ .manager = this,
+ );
return &enumerator->enumerator;
}
@@ -544,11 +547,14 @@ 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;
- u_int row = ike_sa_id_hash(entry->ike_sa_id) & this->table_mask;
- u_int segment = row & this->segment_mask;
+ u_int row, segment;
+
+ row = ike_sa_id_hash(entry->ike_sa_id) & this->table_mask;
+ segment = row & this->segment_mask;
lock_single_segment(this, segment);
- if ((list = this->ike_sa_table[row]) == NULL)
+ list = this->ike_sa_table[row];
+ if (!list)
{
list = this->ike_sa_table[row] = linked_list_create();
}
@@ -564,14 +570,17 @@ 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;
- u_int row = ike_sa_id_hash(entry->ike_sa_id) & this->table_mask;
- u_int segment = row & this->segment_mask;
+ u_int row, segment;
- if ((list = this->ike_sa_table[row]) != NULL)
+ 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)
{
entry_t *current;
+ enumerator_t *enumerator;
- enumerator_t *enumerator = list->create_enumerator(list);
+ enumerator = list->create_enumerator(list);
while (enumerator->enumerate(enumerator, &current))
{
if (current == entry)
@@ -609,11 +618,14 @@ static status_t get_entry_by_match_function(private_ike_sa_manager_t *this,
{
entry_t *current;
linked_list_t *list;
- u_int row = ike_sa_id_hash(ike_sa_id) & this->table_mask;
- u_int seg = row & this->segment_mask;
+ 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);
- if ((list = this->ike_sa_table[row]) != NULL)
+ list = this->ike_sa_table[row];
+ if (list)
{
if (list->find_first(list, match, (void**)&current, p1, p2) == SUCCESS)
{
@@ -697,19 +709,20 @@ 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 = entry->other->get_address(entry->other);
- u_int row = chunk_hash(addr) & this->table_mask;
- u_int segment = row & this->segment_mask;
+ chunk_t addr;
+ u_int row, segment;
+ rwlock_t *lock;
- rwlock_t *lock = this->half_open_segments[segment].lock;
+ 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);
- if ((list = this->half_open_table[row]) == NULL)
- {
- list = this->half_open_table[row] = linked_list_create();
- }
- else
+ list = this->half_open_table[row];
+ if (list)
{
half_open_t *current;
+
if (list->find_first(list, (linked_list_match_t)half_open_match,
(void**)&current, &addr) == SUCCESS)
{
@@ -718,12 +731,17 @@ static void put_half_open(private_ike_sa_manager_t *this, entry_t *entry)
this->half_open_segments[segment].count++;
}
}
+ else
+ {
+ list = this->half_open_table[row] = linked_list_create();
+ }
if (!half_open)
{
- half_open = malloc_thing(half_open_t);
- half_open->other = chunk_clone(addr);
- half_open->count = 1;
+ INIT(half_open,
+ .other = chunk_clone(addr),
+ .count = 1,
+ );
list->insert_last(list, half_open);
this->half_open_segments[segment].count++;
}
@@ -736,16 +754,22 @@ 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 = entry->other->get_address(entry->other);
- u_int row = chunk_hash(addr) & this->table_mask;
- u_int segment = row & this->segment_mask;
+ chunk_t addr;
+ u_int row, segment;
+ rwlock_t *lock;
- rwlock_t *lock = this->half_open_segments[segment].lock;
+ 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);
- if ((list = this->half_open_table[row]) != NULL)
+ list = this->half_open_table[row];
+ if (list)
{
half_open_t *current;
- enumerator_t *enumerator = list->create_enumerator(list);
+ enumerator_t *enumerator;
+
+ enumerator = list->create_enumerator(list);
while (enumerator->enumerate(enumerator, &current))
{
if (half_open_match(current, &addr))
@@ -769,24 +793,26 @@ 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)
{
- linked_list_t *list;
connected_peers_t *connected_peers = NULL;
- chunk_t my_id = entry->my_id->get_encoding(entry->my_id),
- other_id = entry->other_id->get_encoding(entry->other_id);
- u_int row = chunk_hash_inc(other_id, chunk_hash(my_id)) & this->table_mask;
- u_int segment = row & this->segment_mask;
+ chunk_t my_id, other_id;
+ linked_list_t *list;
+ u_int row, segment;
+ rwlock_t *lock;
- rwlock_t *lock = this->connected_peers_segments[segment].lock;
+ my_id = entry->my_id->get_encoding(entry->my_id);
+ other_id = entry->other_id->get_encoding(entry->other_id);
+ 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);
- if ((list = this->connected_peers_table[row]) == NULL)
- {
- list = this->connected_peers_table[row] = linked_list_create();
- }
- else
+ list = this->connected_peers_table[row];
+ if (list)
{
connected_peers_t *current;
+
if (list->find_first(list, (linked_list_match_t)connected_peers_match,
- (void**)&current, entry->my_id, entry->other_id) == SUCCESS)
+ (void**)&current, entry->my_id, entry->other_id,
+ (uintptr_t)entry->other->get_family(entry->other)) == SUCCESS)
{
connected_peers = current;
if (connected_peers->sas->find_first(connected_peers->sas,
@@ -798,13 +824,19 @@ static void put_connected_peers(private_ike_sa_manager_t *this, entry_t *entry)
}
}
}
+ else
+ {
+ list = this->connected_peers_table[row] = linked_list_create();
+ }
if (!connected_peers)
{
- connected_peers = malloc_thing(connected_peers_t);
- connected_peers->my_id = entry->my_id->clone(entry->my_id);
- connected_peers->other_id = entry->other_id->clone(entry->other_id);
- connected_peers->sas = linked_list_create();
+ 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),
+ .sas = linked_list_create(),
+ );
list->insert_last(list, connected_peers);
}
connected_peers->sas->insert_last(connected_peers->sas,
@@ -818,24 +850,34 @@ 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;
- chunk_t my_id = entry->my_id->get_encoding(entry->my_id),
- other_id = entry->other_id->get_encoding(entry->other_id);
- u_int row = chunk_hash_inc(other_id, chunk_hash(my_id)) & this->table_mask;
- u_int segment = row & this->segment_mask;
+ u_int row, segment;
+ rwlock_t *lock;
+
+ my_id = entry->my_id->get_encoding(entry->my_id);
+ other_id = entry->other_id->get_encoding(entry->other_id);
+ row = chunk_hash_inc(other_id, chunk_hash(my_id)) & this->table_mask;
+ segment = row & this->segment_mask;
- rwlock_t *lock = this->connected_peers_segments[segment].lock;
+ lock = this->connected_peers_segments[segment].lock;
lock->write_lock(lock);
- if ((list = this->connected_peers_table[row]) != NULL)
+ list = this->connected_peers_table[row];
+ if (list)
{
connected_peers_t *current;
- enumerator_t *enumerator = list->create_enumerator(list);
+ enumerator_t *enumerator;
+
+ enumerator = list->create_enumerator(list);
while (enumerator->enumerate(enumerator, &current))
{
- if (connected_peers_match(current, entry->my_id, entry->other_id))
+ 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 = current->sas->create_enumerator(current->sas);
+ enumerator_t *inner;
+
+ inner = current->sas->create_enumerator(current->sas);
while (inner->enumerate(inner, &ike_sa_id))
{
if (ike_sa_id->equals(ike_sa_id, entry->ike_sa_id))
@@ -861,20 +903,21 @@ static void remove_connected_peers(private_ike_sa_manager_t *this, entry_t *entr
}
/**
- * Implementation of private_ike_sa_manager_t.get_next_spi.
+ * Get a random SPI for new IKE_SAs
*/
-static u_int64_t get_next_spi(private_ike_sa_manager_t *this)
+static u_int64_t get_spi(private_ike_sa_manager_t *this)
{
- u_int64_t spi;
+ u_int64_t spi = 0;
- this->rng->get_bytes(this->rng, sizeof(spi), (u_int8_t*)&spi);
+ if (this->rng)
+ {
+ this->rng->get_bytes(this->rng, sizeof(spi), (u_int8_t*)&spi);
+ }
return spi;
}
-/**
- * Implementation of of ike_sa_manager.checkout.
- */
-static ike_sa_t* checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id)
+METHOD(ike_sa_manager_t, checkout, ike_sa_t*,
+ private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id)
{
ike_sa_t *ike_sa = NULL;
entry_t *entry;
@@ -897,62 +940,46 @@ static ike_sa_t* checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id
return ike_sa;
}
-/**
- * Implementation of of ike_sa_manager.checkout_new.
- */
-static ike_sa_t *checkout_new(private_ike_sa_manager_t* this, bool initiator)
+METHOD(ike_sa_manager_t, checkout_new, ike_sa_t*,
+ private_ike_sa_manager_t* this, bool initiator)
{
ike_sa_id_t *ike_sa_id;
ike_sa_t *ike_sa;
- entry_t *entry;
- u_int segment;
if (initiator)
{
- ike_sa_id = ike_sa_id_create(get_next_spi(this), 0, TRUE);
+ ike_sa_id = ike_sa_id_create(get_spi(this), 0, TRUE);
}
else
{
- ike_sa_id = ike_sa_id_create(0, get_next_spi(this), FALSE);
+ ike_sa_id = ike_sa_id_create(0, get_spi(this), FALSE);
}
ike_sa = ike_sa_create(ike_sa_id);
+ 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 (!initiator)
- {
- ike_sa_id->destroy(ike_sa_id);
- return ike_sa;
- }
-
- entry = entry_create();
- entry->ike_sa_id = ike_sa_id;
- entry->ike_sa = ike_sa;
- segment = put_entry(this, entry);
- entry->checked_out = TRUE;
- unlock_single_segment(this, segment);
- return entry->ike_sa;
+ return ike_sa;
}
-/**
- * Implementation of of ike_sa_manager.checkout_by_message.
- */
-static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this,
- message_t *message)
+METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*,
+ private_ike_sa_manager_t* this, message_t *message)
{
u_int segment;
entry_t *entry;
ike_sa_t *ike_sa = NULL;
- ike_sa_id_t *id = message->get_ike_sa_id(message);
+ ike_sa_id_t *id;
+ id = message->get_ike_sa_id(message);
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)
+ message->get_exchange_type(message) == IKE_SA_INIT &&
+ this->hasher)
{
/* IKE_SA_INIT request. Check for an IKE_SA with such a message hash. */
chunk_t data, hash;
@@ -988,7 +1015,7 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this,
message->get_exchange_type(message) == IKE_SA_INIT)
{
/* no IKE_SA found, create a new one */
- id->set_responder_spi(id, get_next_spi(this));
+ 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);
@@ -1048,11 +1075,8 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this,
return ike_sa;
}
-/**
- * Implementation of of ike_sa_manager.checkout_by_config.
- */
-static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this,
- peer_cfg_t *peer_cfg)
+METHOD(ike_sa_manager_t, checkout_by_config, ike_sa_t*,
+ private_ike_sa_manager_t *this, peer_cfg_t *peer_cfg)
{
enumerator_t *enumerator;
entry_t *entry;
@@ -1107,11 +1131,8 @@ static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this,
return ike_sa;
}
-/**
- * Implementation of of ike_sa_manager.checkout_by_id.
- */
-static ike_sa_t* checkout_by_id(private_ike_sa_manager_t *this, u_int32_t id,
- bool child)
+METHOD(ike_sa_manager_t, checkout_by_id, ike_sa_t*,
+ private_ike_sa_manager_t *this, u_int32_t id, bool child)
{
enumerator_t *enumerator;
iterator_t *children;
@@ -1164,11 +1185,8 @@ static ike_sa_t* checkout_by_id(private_ike_sa_manager_t *this, u_int32_t id,
return ike_sa;
}
-/**
- * Implementation of of ike_sa_manager.checkout_by_name.
- */
-static ike_sa_t* checkout_by_name(private_ike_sa_manager_t *this, char *name,
- bool child)
+METHOD(ike_sa_manager_t, checkout_by_name, ike_sa_t*,
+ private_ike_sa_manager_t *this, char *name, bool child)
{
enumerator_t *enumerator;
iterator_t *children;
@@ -1233,20 +1251,15 @@ static bool enumerator_filter(private_ike_sa_manager_t *this,
return FALSE;
}
-/**
- * Implementation of ike_sa_manager_t.create_enumerator.
- */
-static enumerator_t *create_enumerator(private_ike_sa_manager_t* this)
+METHOD(ike_sa_manager_t, create_enumerator, enumerator_t*,
+ private_ike_sa_manager_t* this)
{
- return enumerator_create_filter(
- create_table_enumerator(this),
- (void*)enumerator_filter, this, NULL);
+ return enumerator_create_filter(create_table_enumerator(this),
+ (void*)enumerator_filter, this, NULL);
}
-/**
- * Implementation of ike_sa_manager_t.checkin.
- */
-static void checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
+METHOD(ike_sa_manager_t, checkin, void,
+ private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
{
/* to check the SA back in, we look for the pointer of the ike_sa
* in all entries.
@@ -1311,13 +1324,16 @@ static void checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
segment = put_entry(this, entry);
}
- /* apply identities for duplicate test (only as responder) */
- if (!entry->ike_sa_id->is_initiator(entry->ike_sa_id) &&
- ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
+ /* apply identities for duplicate test */
+ if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
entry->my_id == NULL && entry->other_id == NULL)
{
entry->my_id = my_id->clone(my_id);
entry->other_id = other_id->clone(other_id);
+ if (!entry->other)
+ {
+ entry->other = other->clone(other);
+ }
put_connected_peers(this, entry);
}
@@ -1326,10 +1342,8 @@ static void checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
charon->bus->set_sa(charon->bus, NULL);
}
-/**
- * Implementation of ike_sa_manager_t.checkin_and_destroy.
- */
-static void checkin_and_destroy(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
+METHOD(ike_sa_manager_t, checkin_and_destroy, void,
+ private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
{
/* deletion is a bit complex, we must ensure that no thread is waiting for
* this SA.
@@ -1366,8 +1380,7 @@ static void checkin_and_destroy(private_ike_sa_manager_t *this, ike_sa_t *ike_sa
{
remove_half_open(this, entry);
}
- if (!entry->ike_sa_id->is_initiator(entry->ike_sa_id) &&
- entry->my_id && entry->other_id)
+ if (entry->my_id && entry->other_id)
{
remove_connected_peers(this, entry);
}
@@ -1384,11 +1397,8 @@ static void checkin_and_destroy(private_ike_sa_manager_t *this, ike_sa_t *ike_sa
charon->bus->set_sa(charon->bus, NULL);
}
-
-/**
- * Implementation of ike_sa_manager_t.check_uniqueness.
- */
-static bool check_uniqueness(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
+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;
@@ -1402,7 +1412,7 @@ static bool check_uniqueness(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
peer_cfg = ike_sa->get_peer_cfg(ike_sa);
policy = peer_cfg->get_unique_policy(peer_cfg);
- if (policy == UNIQUE_NO)
+ if (policy == UNIQUE_NO && !force_replace)
{
return FALSE;
}
@@ -1416,12 +1426,16 @@ static bool check_uniqueness(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
lock = this->connected_peers_segments[segment & this->segment_mask].lock;
lock->read_lock(lock);
- if ((list = this->connected_peers_table[row]) != NULL)
+ list = this->connected_peers_table[row];
+ if (list)
{
connected_peers_t *current;
+ host_t *other_host;
+ 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) == SUCCESS)
+ (void**)&current, me, other,
+ (uintptr_t)other_host->get_family(other_host)) == SUCCESS)
{
/* clone the list, so we can release the lock */
duplicate_ids = current->sas->clone_offset(current->sas,
@@ -1446,6 +1460,13 @@ static bool check_uniqueness(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
{
continue;
}
+ if (force_replace)
+ {
+ DBG1(DBG_IKE, "destroying duplicate IKE_SA for peer '%Y', "
+ "received INITIAL_CONTACT", other);
+ checkin_and_destroy(this, duplicate);
+ continue;
+ }
peer_cfg = duplicate->get_peer_cfg(duplicate);
if (peer_cfg && peer_cfg->equals(peer_cfg, ike_sa->get_peer_cfg(ike_sa)))
{
@@ -1490,21 +1511,49 @@ static bool check_uniqueness(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
return cancel;
}
-/**
- * Implementation of ike_sa_manager_t.get_half_open_count.
- */
-static int get_half_open_count(private_ike_sa_manager_t *this, host_t *ip)
+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;
+ u_int row, segment;
+ rwlock_t *lock;
+ bool found = FALSE;
+
+ 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->read_lock(lock);
+ list = this->connected_peers_table[row];
+ if (list)
+ {
+ if (list->find_first(list, (linked_list_match_t)connected_peers_match,
+ NULL, me, other, family) == SUCCESS)
+ {
+ found = TRUE;
+ }
+ }
+ lock->unlock(lock);
+
+ return found;
+}
+
+METHOD(ike_sa_manager_t, get_half_open_count, int,
+ private_ike_sa_manager_t *this, host_t *ip)
{
+ linked_list_t *list;
+ u_int segment, row;
+ rwlock_t *lock;
+ chunk_t addr;
int count = 0;
if (ip)
{
- linked_list_t *list;
- chunk_t addr = ip->get_address(ip);
- u_int row = chunk_hash(addr) & this->table_mask;
- u_int segment = row & this->segment_mask;
-
- rwlock_t *lock = this->half_open_segments[segment & this->segment_mask].lock;
+ 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->read_lock(lock);
if ((list = this->half_open_table[row]) != NULL)
{
@@ -1520,25 +1569,19 @@ static int get_half_open_count(private_ike_sa_manager_t *this, host_t *ip)
}
else
{
- u_int segment;
-
- for (segment = 0; segment < this->segment_count; ++segment)
+ for (segment = 0; segment < this->segment_count; segment++)
{
- rwlock_t *lock;
lock = this->half_open_segments[segment & this->segment_mask].lock;
lock->read_lock(lock);
count += this->half_open_segments[segment].count;
lock->unlock(lock);
}
}
-
return count;
}
-/**
- * Implementation of ike_sa_manager_t.flush.
- */
-static void flush(private_ike_sa_manager_t *this)
+METHOD(ike_sa_manager_t, flush, void,
+ private_ike_sa_manager_t *this)
{
/* destroy all list entries */
enumerator_t *enumerator;
@@ -1602,8 +1645,7 @@ static void flush(private_ike_sa_manager_t *this)
{
remove_half_open(this, entry);
}
- if (!entry->ike_sa_id->is_initiator(entry->ike_sa_id) &&
- entry->my_id && entry->other_id)
+ if (entry->my_id && entry->other_id)
{
remove_connected_peers(this, entry);
}
@@ -1615,37 +1657,26 @@ static void flush(private_ike_sa_manager_t *this)
unlock_all_segments(this);
this->rng->destroy(this->rng);
+ this->rng = NULL;
this->hasher->destroy(this->hasher);
+ this->hasher = NULL;
}
-/**
- * Implementation of ike_sa_manager_t.destroy.
- */
-static void destroy(private_ike_sa_manager_t *this)
+METHOD(ike_sa_manager_t, destroy, void,
+ private_ike_sa_manager_t *this)
{
u_int i;
- for (i = 0; i < this->table_size; ++i)
+ for (i = 0; i < this->table_size; i++)
{
- linked_list_t *list;
-
- if ((list = this->ike_sa_table[i]) != NULL)
- {
- list->destroy(list);
- }
- if ((list = this->half_open_table[i]) != NULL)
- {
- list->destroy(list);
- }
- if ((list = this->connected_peers_table[i]) != NULL)
- {
- list->destroy(list);
- }
+ DESTROY_IF(this->ike_sa_table[i]);
+ DESTROY_IF(this->half_open_table[i]);
+ DESTROY_IF(this->connected_peers_table[i]);
}
free(this->ike_sa_table);
free(this->half_open_table);
free(this->connected_peers_table);
- for (i = 0; i < this->segment_count; ++i)
+ 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);
@@ -1681,25 +1712,28 @@ static u_int get_nearest_powerof2(u_int n)
*/
ike_sa_manager_t *ike_sa_manager_create()
{
+ private_ike_sa_manager_t *this;
u_int i;
- private_ike_sa_manager_t *this = malloc_thing(private_ike_sa_manager_t);
-
- /* assign public functions */
- this->public.flush = (void(*)(ike_sa_manager_t*))flush;
- this->public.destroy = (void(*)(ike_sa_manager_t*))destroy;
- this->public.checkout = (ike_sa_t*(*)(ike_sa_manager_t*, ike_sa_id_t*))checkout;
- this->public.checkout_new = (ike_sa_t*(*)(ike_sa_manager_t*,bool))checkout_new;
- this->public.checkout_by_message = (ike_sa_t*(*)(ike_sa_manager_t*,message_t*))checkout_by_message;
- this->public.checkout_by_config = (ike_sa_t*(*)(ike_sa_manager_t*,peer_cfg_t*))checkout_by_config;
- this->public.checkout_by_id = (ike_sa_t*(*)(ike_sa_manager_t*,u_int32_t,bool))checkout_by_id;
- this->public.checkout_by_name = (ike_sa_t*(*)(ike_sa_manager_t*,char*,bool))checkout_by_name;
- this->public.check_uniqueness = (bool(*)(ike_sa_manager_t*, ike_sa_t *ike_sa))check_uniqueness;
- this->public.create_enumerator = (enumerator_t*(*)(ike_sa_manager_t*))create_enumerator;
- this->public.checkin = (void(*)(ike_sa_manager_t*,ike_sa_t*))checkin;
- this->public.checkin_and_destroy = (void(*)(ike_sa_manager_t*,ike_sa_t*))checkin_and_destroy;
- this->public.get_half_open_count = (int(*)(ike_sa_manager_t*,host_t*))get_half_open_count;
-
- /* initialize private variables */
+
+ INIT(this,
+ .public = {
+ .checkout = _checkout,
+ .checkout_new = _checkout_new,
+ .checkout_by_message = _checkout_by_message,
+ .checkout_by_config = _checkout_by_config,
+ .checkout_by_id = _checkout_by_id,
+ .checkout_by_name = _checkout_by_name,
+ .check_uniqueness = _check_uniqueness,
+ .has_contact = _has_contact,
+ .create_enumerator = _create_enumerator,
+ .checkin = _checkin,
+ .checkin_and_destroy = _checkin_and_destroy,
+ .get_half_open_count = _get_half_open_count,
+ .flush = _flush,
+ .destroy = _destroy,
+ },
+ );
+
this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_PREFERRED);
if (this->hasher == NULL)
{
@@ -1715,6 +1749,7 @@ ike_sa_manager_t *ike_sa_manager_create()
free(this);
return NULL;
}
+
this->table_size = get_nearest_powerof2(lib->settings->get_int(lib->settings,
"charon.ikesa_table_size", DEFAULT_HASHTABLE_SIZE));
this->table_size = max(1, min(this->table_size, MAX_HASHTABLE_SIZE));
@@ -1724,11 +1759,10 @@ ike_sa_manager_t *ike_sa_manager_create()
"charon.ikesa_table_segments", DEFAULT_SEGMENT_COUNT));
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->segments = (segment_t*)calloc(this->segment_count, sizeof(segment_t));
- for (i = 0; i < this->segment_count; ++i)
+ for (i = 0; i < this->segment_count; i++)
{
this->segments[i].mutex = mutex_create(MUTEX_TYPE_RECURSIVE);
this->segments[i].count = 0;
@@ -1737,7 +1771,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_segments = calloc(this->segment_count, sizeof(shareable_segment_t));
- for (i = 0; i < this->segment_count; ++i)
+ for (i = 0; i < this->segment_count; i++)
{
this->half_open_segments[i].lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
this->half_open_segments[i].count = 0;
@@ -1746,7 +1780,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_segments = calloc(this->segment_count, sizeof(shareable_segment_t));
- for (i = 0; i < this->segment_count; ++i)
+ for (i = 0; i < this->segment_count; i++)
{
this->connected_peers_segments[i].lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
this->connected_peers_segments[i].count = 0;
diff --git a/src/libcharon/sa/ike_sa_manager.h b/src/libcharon/sa/ike_sa_manager.h
index f4eabf808..ec157ab3a 100644
--- a/src/libcharon/sa/ike_sa_manager.h
+++ b/src/libcharon/sa/ike_sa_manager.h
@@ -52,9 +52,6 @@ struct ike_sa_manager_t {
/**
* Create and check out a new IKE_SA.
*
- * @note If initiator equals FALSE, the returned IKE_SA is not registered
- * in the manager.
- *
* @param initiator TRUE for initiator, FALSE otherwise
* @returns created and checked out IKE_SA
*/
@@ -109,10 +106,23 @@ struct ike_sa_manager_t {
* deadlocks occur otherwise.
*
* @param ike_sa ike_sa to check
+ * @param force_replace replace existing SAs, regardless of unique policy
* @return TRUE, if the given IKE_SA has duplicates and
* should be deleted
*/
- bool (*check_uniqueness)(ike_sa_manager_t *this, ike_sa_t *ike_sa);
+ bool (*check_uniqueness)(ike_sa_manager_t *this, ike_sa_t *ike_sa,
+ bool force_replace);
+
+ /**
+ * Check if we already have a connected IKE_SA between two identities.
+ *
+ * @param me own identity
+ * @param other remote identity
+ * @param family address family to include in uniqueness check
+ * @return TRUE if we have a connected IKE_SA
+ */
+ bool (*has_contact)(ike_sa_manager_t *this, identification_t *me,
+ identification_t *other, int family);
/**
* Check out an IKE_SA a unique ID.
diff --git a/src/libcharon/sa/keymat.c b/src/libcharon/sa/keymat.c
index 878ad124f..33ece24b2 100644
--- a/src/libcharon/sa/keymat.c
+++ b/src/libcharon/sa/keymat.c
@@ -214,7 +214,7 @@ static bool derive_ike_traditional(private_keymat_t *this, u_int16_t enc_alg,
{
DBG1(DBG_IKE, "%N %N (key size %d) not supported!",
transform_type_names, ENCRYPTION_ALGORITHM,
- encryption_algorithm_names, enc_alg, key_size);
+ encryption_algorithm_names, enc_alg, enc_size);
signer_i->destroy(signer_i);
signer_r->destroy(signer_r);
return FALSE;
@@ -540,7 +540,7 @@ METHOD(keymat_t, get_aead, aead_t*,
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)
+ chunk_t nonce, identification_t *id, char reserved[3])
{
chunk_t chunk, idx, octets;
chunk_t skp;
@@ -548,8 +548,8 @@ METHOD(keymat_t, get_auth_octets, chunk_t,
skp = verify ? this->skp_verify : this->skp_build;
chunk = chunk_alloca(4);
- memset(chunk.ptr, 0, chunk.len);
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);
@@ -570,7 +570,7 @@ METHOD(keymat_t, get_auth_octets, chunk_t,
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)
+ chunk_t nonce, chunk_t secret, identification_t *id, char reserved[3])
{
chunk_t key_pad, key, sig, octets;
@@ -578,7 +578,7 @@ METHOD(keymat_t, get_psk_sig, chunk_t,
{ /* 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);
+ 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);
diff --git a/src/libcharon/sa/keymat.h b/src/libcharon/sa/keymat.h
index 4f01aa411..11e0fa79a 100644
--- a/src/libcharon/sa/keymat.h
+++ b/src/libcharon/sa/keymat.h
@@ -117,10 +117,12 @@ struct keymat_t {
* @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);
+ chunk_t nonce, identification_t *id,
+ char reserved[3]);
/**
* Build the shared secret signature used for PSK and EAP authentication.
*
@@ -133,10 +135,12 @@ struct keymat_t {
* @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);
+ chunk_t nonce, chunk_t secret,
+ identification_t *id, char reserved[3]);
/**
* Destroy a keymat_t.
*/
diff --git a/src/libcharon/sa/task_manager.c b/src/libcharon/sa/task_manager.c
index 18703ce36..9467d1586 100644
--- a/src/libcharon/sa/task_manager.c
+++ b/src/libcharon/sa/task_manager.c
@@ -465,7 +465,6 @@ METHOD(task_manager_t, initiate, status_t,
/* update exchange type if a task changed it */
this->initiating.type = message->get_exchange_type(message);
- charon->bus->message(charon->bus, message, FALSE);
status = this->ike_sa->generate_message(this->ike_sa, message,
&this->initiating.packet);
if (status != SUCCESS)
@@ -654,7 +653,6 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
/* message complete, send it */
DESTROY_IF(this->responding.packet);
this->responding.packet = NULL;
- charon->bus->message(charon->bus, message, FALSE);
status = this->ike_sa->generate_message(this->ike_sa, message,
&this->responding.packet);
message->destroy(message);
@@ -882,8 +880,12 @@ static status_t process_request(private_task_manager_t *this,
METHOD(task_manager_t, process_message, status_t,
private_task_manager_t *this, message_t *msg)
{
- u_int32_t mid = msg->get_message_id(msg);
- host_t *me = msg->get_destination(msg), *other = msg->get_source(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))
{
@@ -895,10 +897,14 @@ METHOD(task_manager_t, process_message, status_t,
{ /* 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);
+ 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);
@@ -909,15 +915,15 @@ METHOD(task_manager_t, process_message, status_t,
else if ((mid == this->responding.mid - 1) && this->responding.packet)
{
packet_t *clone;
- host_t *me, *other;
+ host_t *host;
DBG1(DBG_IKE, "received retransmit of request with ID %d, "
"retransmitting response", mid);
clone = this->responding.packet->clone(this->responding.packet);
- me = msg->get_destination(msg);
- other = msg->get_source(msg);
- clone->set_source(clone, me->clone(me));
- clone->set_destination(clone, other->clone(other));
+ 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
@@ -936,10 +942,14 @@ METHOD(task_manager_t, process_message, status_t,
{ /* 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);
+ 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);
@@ -1002,6 +1012,19 @@ METHOD(task_manager_t, busy, bool,
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)
{
@@ -1085,6 +1108,7 @@ task_manager_t *task_manager_create(ike_sa_t *ike_sa)
.queue_task = _queue_task,
.initiate = _initiate,
.retransmit = _retransmit,
+ .incr_mid = _incr_mid,
.reset = _reset,
.adopt_tasks = _adopt_tasks,
.busy = _busy,
diff --git a/src/libcharon/sa/task_manager.h b/src/libcharon/sa/task_manager.h
index 14fccd5f9..5bc6c80c4 100644
--- a/src/libcharon/sa/task_manager.h
+++ b/src/libcharon/sa/task_manager.h
@@ -149,6 +149,16 @@ struct task_manager_t {
void (*adopt_tasks) (task_manager_t *this, task_manager_t *other);
/**
+ * Increment a message ID counter, in- or outbound.
+ *
+ * If a message is processed outside of the manager, this call increments
+ * the message ID counters of the task manager.
+ *
+ * @param inititate TRUE to increment the initiating ID
+ */
+ void (*incr_mid)(task_manager_t *this, bool initiate);
+
+ /**
* Reset message ID counters of the task manager.
*
* The IKEv2 protocol requires to restart exchanges with message IDs
diff --git a/src/libcharon/sa/tasks/child_create.c b/src/libcharon/sa/tasks/child_create.c
index 57beedba9..fc02a334b 100644
--- a/src/libcharon/sa/tasks/child_create.c
+++ b/src/libcharon/sa/tasks/child_create.c
@@ -117,6 +117,11 @@ struct private_child_create_t {
ipsec_mode_t mode;
/**
+ * peer accepts TFC padding for this SA
+ */
+ bool tfcv3;
+
+ /**
* IPComp transform to use
*/
ipcomp_transform_t ipcomp;
@@ -455,17 +460,21 @@ static status_t select_and_install(private_child_create_t *this,
{
if (this->initiator)
{
- status_i = this->child_sa->install(this->child_sa, encr_r, integ_r,
- this->my_spi, this->my_cpi, TRUE, my_ts, other_ts);
- status_o = this->child_sa->install(this->child_sa, encr_i, integ_i,
- this->other_spi, this->other_cpi, FALSE, my_ts, other_ts);
+ status_i = this->child_sa->install(this->child_sa,
+ encr_r, integ_r, this->my_spi, this->my_cpi,
+ TRUE, this->tfcv3, my_ts, other_ts);
+ status_o = this->child_sa->install(this->child_sa,
+ encr_i, integ_i, this->other_spi, this->other_cpi,
+ FALSE, this->tfcv3, my_ts, other_ts);
}
else
{
- status_i = this->child_sa->install(this->child_sa, encr_i, integ_i,
- this->my_spi, this->my_cpi, TRUE, my_ts, other_ts);
- status_o = this->child_sa->install(this->child_sa, encr_r, integ_r,
- this->other_spi, this->other_cpi, FALSE, my_ts, other_ts);
+ status_i = this->child_sa->install(this->child_sa,
+ encr_i, integ_i, this->my_spi, this->my_cpi,
+ TRUE, this->tfcv3, my_ts, other_ts);
+ status_o = this->child_sa->install(this->child_sa,
+ encr_r, integ_r, this->other_spi, this->other_cpi,
+ FALSE, this->tfcv3, my_ts, other_ts);
}
}
chunk_clear(&integ_i);
@@ -631,7 +640,13 @@ static void handle_notify(private_child_create_t *this, notify_payload_t *notify
ipcomp_transform_names, ipcomp);
break;
}
+ break;
}
+ case ESP_TFC_PADDING_NOT_SUPPORTED:
+ DBG1(DBG_IKE, "received %N, not using ESPv3 TFC padding",
+ notify_type_names, notify->get_notify_type(notify));
+ this->tfcv3 = FALSE;
+ break;
default:
break;
}
@@ -691,10 +706,8 @@ static void process_payloads(private_child_create_t *this, message_t *message)
enumerator->destroy(enumerator);
}
-/**
- * Implementation of task_t.build for initiator
- */
-static status_t build_i(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;
peer_cfg_t *peer_cfg;
@@ -831,10 +844,8 @@ static status_t build_i(private_child_create_t *this, message_t *message)
return NEED_MORE;
}
-/**
- * Implementation of task_t.process for responder
- */
-static status_t process_r(private_child_create_t *this, message_t *message)
+METHOD(task_t, process_r, status_t,
+ private_child_create_t *this, message_t *message)
{
switch (message->get_exchange_type(message))
{
@@ -877,10 +888,8 @@ static void handle_child_sa_failure(private_child_create_t *this,
}
}
-/**
- * Implementation of task_t.build for responder
- */
-static status_t build_r(private_child_create_t *this, message_t *message)
+METHOD(task_t, build_r, status_t,
+ private_child_create_t *this, message_t *message)
{
peer_cfg_t *peer_cfg;
payload_t *payload;
@@ -958,7 +967,7 @@ static status_t build_r(private_child_create_t *this, message_t *message)
case INTERNAL_ADDRESS_FAILURE:
case FAILED_CP_REQUIRED:
{
- DBG1(DBG_IKE,"configuration payload negotation "
+ DBG1(DBG_IKE,"configuration payload negotiation "
"failed, no CHILD_SA built");
enumerator->destroy(enumerator);
handle_child_sa_failure(this, message);
@@ -1029,10 +1038,8 @@ static status_t build_r(private_child_create_t *this, message_t *message)
return SUCCESS;
}
-/**
- * Implementation of task_t.process for initiator
- */
-static status_t process_i(private_child_create_t *this, message_t *message)
+METHOD(task_t, process_i, status_t,
+ private_child_create_t *this, message_t *message)
{
enumerator_t *enumerator;
payload_t *payload;
@@ -1103,7 +1110,21 @@ static status_t process_i(private_child_create_t *this, message_t *message)
return NEED_MORE;
}
default:
+ {
+ if (message->get_exchange_type(message) == CREATE_CHILD_SA)
+ { /* handle notifies if not handled in IKE_AUTH */
+ if (type <= 16383)
+ {
+ DBG1(DBG_IKE, "received %N notify error",
+ notify_type_names, type);
+ enumerator->destroy(enumerator);
+ return SUCCESS;
+ }
+ DBG2(DBG_IKE, "received %N notify",
+ notify_type_names, type);
+ }
break;
+ }
}
}
}
@@ -1155,34 +1176,20 @@ static status_t process_i(private_child_create_t *this, message_t *message)
return SUCCESS;
}
-/**
- * Implementation of task_t.get_type
- */
-static task_type_t get_type(private_child_create_t *this)
-{
- return CHILD_CREATE;
-}
-
-/**
- * Implementation of child_create_t.use_reqid
- */
-static void use_reqid(private_child_create_t *this, u_int32_t reqid)
+METHOD(child_create_t, use_reqid, void,
+ private_child_create_t *this, u_int32_t reqid)
{
this->reqid = reqid;
}
-/**
- * Implementation of child_create_t.get_child
- */
-static child_sa_t* get_child(private_child_create_t *this)
+METHOD(child_create_t, get_child, child_sa_t*,
+ private_child_create_t *this)
{
return this->child_sa;
}
-/**
- * Implementation of child_create_t.get_lower_nonce
- */
-static chunk_t get_lower_nonce(private_child_create_t *this)
+METHOD(child_create_t, get_lower_nonce, chunk_t,
+ private_child_create_t *this)
{
if (memcmp(this->my_nonce.ptr, this->other_nonce.ptr,
min(this->my_nonce.len, this->other_nonce.len)) < 0)
@@ -1195,10 +1202,14 @@ static chunk_t get_lower_nonce(private_child_create_t *this)
}
}
-/**
- * Implementation of task_t.migrate
- */
-static void migrate(private_child_create_t *this, ike_sa_t *ike_sa)
+METHOD(task_t, get_type, task_type_t,
+ private_child_create_t *this)
+{
+ return CHILD_CREATE;
+}
+
+METHOD(task_t, migrate, void,
+ private_child_create_t *this, ike_sa_t *ike_sa)
{
chunk_free(&this->my_nonce);
chunk_free(&this->other_nonce);
@@ -1234,10 +1245,8 @@ static void migrate(private_child_create_t *this, ike_sa_t *ike_sa)
this->established = FALSE;
}
-/**
- * Implementation of task_t.destroy
- */
-static void destroy(private_child_create_t *this)
+METHOD(task_t, destroy, void,
+ private_child_create_t *this)
{
chunk_free(&this->my_nonce);
chunk_free(&this->other_nonce);
@@ -1273,52 +1282,45 @@ child_create_t *child_create_create(ike_sa_t *ike_sa,
child_cfg_t *config, bool rekey,
traffic_selector_t *tsi, traffic_selector_t *tsr)
{
- private_child_create_t *this = malloc_thing(private_child_create_t);
-
- this->public.get_child = (child_sa_t*(*)(child_create_t*))get_child;
- this->public.get_lower_nonce = (chunk_t(*)(child_create_t*))get_lower_nonce;
- this->public.use_reqid = (void(*)(child_create_t*,u_int32_t))use_reqid;
- this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
- this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
- this->public.task.destroy = (void(*)(task_t*))destroy;
+ private_child_create_t *this;
+
+ INIT(this,
+ .public = {
+ .get_child = _get_child,
+ .get_lower_nonce = _get_lower_nonce,
+ .use_reqid = _use_reqid,
+ .task = {
+ .get_type = _get_type,
+ .migrate = _migrate,
+ .destroy = _destroy,
+ },
+ },
+ .ike_sa = ike_sa,
+ .config = config,
+ .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),
+ .mode = MODE_TUNNEL,
+ .tfcv3 = TRUE,
+ .ipcomp = IPCOMP_NONE,
+ .ipcomp_received = IPCOMP_NONE,
+ .rekey = rekey,
+ );
+
if (config)
{
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
+ this->public.task.build = _build_i;
+ this->public.task.process = _process_i;
this->initiator = TRUE;
config->get_ref(config);
}
else
{
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
+ this->public.task.build = _build_r;
+ this->public.task.process = _process_r;
this->initiator = FALSE;
}
- this->ike_sa = ike_sa;
- this->config = config;
- this->my_nonce = chunk_empty;
- this->other_nonce = chunk_empty;
- this->proposals = NULL;
- this->proposal = NULL;
- this->tsi = NULL;
- this->tsr = NULL;
- this->packet_tsi = tsi ? tsi->clone(tsi) : NULL;
- this->packet_tsr = tsr ? tsr->clone(tsr) : NULL;
- this->dh = NULL;
- this->dh_group = MODP_NONE;
- this->keymat = ike_sa->get_keymat(ike_sa);
- this->child_sa = NULL;
- this->mode = MODE_TUNNEL;
- this->ipcomp = IPCOMP_NONE;
- this->ipcomp_received = IPCOMP_NONE;
- this->my_spi = 0;
- this->other_spi = 0;
- this->my_cpi = 0;
- this->other_cpi = 0;
- this->reqid = 0;
- this->established = FALSE;
- this->rekey = rekey;
-
return &this->public;
}
diff --git a/src/libcharon/sa/tasks/child_rekey.c b/src/libcharon/sa/tasks/child_rekey.c
index fdaaea4b8..e74ca4eef 100644
--- a/src/libcharon/sa/tasks/child_rekey.c
+++ b/src/libcharon/sa/tasks/child_rekey.c
@@ -241,12 +241,11 @@ static child_sa_t *handle_collision(private_child_rekey_t *this)
/* if we have the lower nonce, delete rekeyed SA. If not, delete
* the redundant. */
if (memcmp(this_nonce.ptr, other_nonce.ptr,
- min(this_nonce.len, other_nonce.len)) < 0)
+ min(this_nonce.len, other_nonce.len)) > 0)
{
child_sa_t *child_sa;
- DBG1(DBG_IKE, "CHILD_SA rekey collision won, "
- "deleting rekeyed child");
+ DBG1(DBG_IKE, "CHILD_SA rekey collision won, deleting old child");
to_delete = this->child_sa;
/* don't touch child other created, it has already been deleted */
if (!this->other_child_destroyed)
@@ -259,7 +258,7 @@ static child_sa_t *handle_collision(private_child_rekey_t *this)
else
{
DBG1(DBG_IKE, "CHILD_SA rekey collision lost, "
- "deleting redundant child");
+ "deleting rekeyed child");
to_delete = this->child_create->get_child(this->child_create);
}
}
diff --git a/src/libcharon/sa/tasks/ike_auth.c b/src/libcharon/sa/tasks/ike_auth.c
index b440ec811..0756c7d60 100644
--- a/src/libcharon/sa/tasks/ike_auth.c
+++ b/src/libcharon/sa/tasks/ike_auth.c
@@ -68,6 +68,11 @@ struct private_ike_auth_t {
packet_t *other_packet;
/**
+ * Reserved bytes of ID payload
+ */
+ char reserved[3];
+
+ /**
* currently active authenticator, to authenticate us
*/
authenticator_t *my_auth;
@@ -101,6 +106,11 @@ struct private_ike_auth_t {
* should we send a AUTHENTICATION_FAILED notify?
*/
bool authentication_failed;
+
+ /**
+ * received an INITIAL_CONTACT?
+ */
+ bool initial_contact;
};
/**
@@ -160,6 +170,24 @@ static status_t collect_other_init_data(private_ike_auth_t *this,
}
/**
+ * Get and store reserved bytes of id_payload, required for AUTH payload
+ */
+static void get_reserved_id_bytes(private_ike_auth_t *this, id_payload_t *id)
+{
+ u_int8_t *byte;
+ int i;
+
+ for (i = 0; i < countof(this->reserved); i++)
+ {
+ byte = payload_get_field(&id->payload_interface, RESERVED_BYTE, i);
+ if (byte)
+ {
+ this->reserved[i] = *byte;
+ }
+ }
+}
+
+/**
* Get the next authentication configuration
*/
static auth_cfg_t *get_auth_cfg(private_ike_auth_t *this, bool local)
@@ -329,10 +357,8 @@ static bool update_cfg_candidates(private_ike_auth_t *this, bool strict)
return this->peer_cfg != NULL;
}
-/**
- * Implementation of task_t.build for initiator
- */
-static status_t build_i(private_ike_auth_t *this, message_t *message)
+METHOD(task_t, build_i, status_t,
+ private_ike_auth_t *this, message_t *message)
{
auth_cfg_t *cfg;
@@ -367,7 +393,7 @@ static status_t build_i(private_ike_auth_t *this, message_t *message)
/* check if an authenticator is in progress */
if (this->my_auth == NULL)
{
- identification_t *id;
+ identification_t *idi, *idr = NULL;
id_payload_t *id_payload;
/* clean up authentication config from a previous round */
@@ -378,33 +404,48 @@ static status_t build_i(private_ike_auth_t *this, message_t *message)
cfg = get_auth_cfg(this, FALSE);
if (cfg)
{
- id = cfg->get(cfg, AUTH_RULE_IDENTITY);
- if (id && !id->contains_wildcards(id))
+ idr = cfg->get(cfg, AUTH_RULE_IDENTITY);
+ if (idr && !idr->contains_wildcards(idr))
{
- this->ike_sa->set_other_id(this->ike_sa, id->clone(id));
+ this->ike_sa->set_other_id(this->ike_sa, idr->clone(idr));
id_payload = id_payload_create_from_identification(
- ID_RESPONDER, id);
+ ID_RESPONDER, idr);
message->add_payload(message, (payload_t*)id_payload);
}
}
/* add IDi */
cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
cfg->merge(cfg, get_auth_cfg(this, TRUE), TRUE);
- id = cfg->get(cfg, AUTH_RULE_IDENTITY);
- if (!id)
+ idi = cfg->get(cfg, AUTH_RULE_IDENTITY);
+ if (!idi)
{
DBG1(DBG_CFG, "configuration misses IDi");
return FAILED;
}
- this->ike_sa->set_my_id(this->ike_sa, id->clone(id));
- id_payload = id_payload_create_from_identification(ID_INITIATOR, id);
+ this->ike_sa->set_my_id(this->ike_sa, idi->clone(idi));
+ id_payload = id_payload_create_from_identification(ID_INITIATOR, idi);
+ get_reserved_id_bytes(this, id_payload);
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)
+ {
+ host_t *host;
+
+ host = this->ike_sa->get_other_host(this->ike_sa);
+ if (!charon->ike_sa_manager->has_contact(charon->ike_sa_manager,
+ idi, idr, host->get_family(host)))
+ {
+ message->add_notify(message, FALSE, INITIAL_CONTACT, chunk_empty);
+ }
+ }
+
/* build authentication data */
this->my_auth = authenticator_create_builder(this->ike_sa, cfg,
this->other_nonce, this->my_nonce,
this->other_packet->get_data(this->other_packet),
- this->my_packet->get_data(this->my_packet));
+ this->my_packet->get_data(this->my_packet),
+ this->reserved);
if (!this->my_auth)
{
return FAILED;
@@ -441,10 +482,8 @@ static status_t build_i(private_ike_auth_t *this, message_t *message)
return NEED_MORE;
}
-/**
- * Implementation of task_t.process for responder
- */
-static status_t process_r(private_ike_auth_t *this, message_t *message)
+METHOD(task_t, process_r, status_t,
+ private_ike_auth_t *this, message_t *message)
{
auth_cfg_t *cfg, *cand;
id_payload_t *id_payload;
@@ -498,6 +537,7 @@ static status_t process_r(private_ike_auth_t *this, message_t *message)
return FAILED;
}
id = id_payload->get_identification(id_payload);
+ get_reserved_id_bytes(this, id_payload);
this->ike_sa->set_other_id(this->ike_sa, id);
cfg = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
cfg->add(cfg, AUTH_RULE_IDENTITY, id->clone(id));
@@ -548,7 +588,8 @@ static status_t process_r(private_ike_auth_t *this, message_t *message)
this->other_auth = authenticator_create_verifier(this->ike_sa,
message, this->other_nonce, this->my_nonce,
this->other_packet->get_data(this->other_packet),
- this->my_packet->get_data(this->my_packet));
+ this->my_packet->get_data(this->my_packet),
+ this->reserved);
if (!this->other_auth)
{
this->authentication_failed = TRUE;
@@ -572,10 +613,13 @@ static status_t process_r(private_ike_auth_t *this, message_t *message)
return NEED_MORE;
}
- /* store authentication information */
- cfg = auth_cfg_create();
- cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, FALSE), FALSE);
- this->ike_sa->add_auth_cfg(this->ike_sa, FALSE, cfg);
+ /* If authenticated (with non-EAP) and received INITIAL_CONTACT,
+ * delete any existing IKE_SAs with that peer. */
+ if (message->get_message_id(message) == 1 &&
+ message->get_notify(message, INITIAL_CONTACT))
+ {
+ this->initial_contact = TRUE;
+ }
/* another auth round done, invoke authorize hook */
if (!charon->bus->authorize(charon->bus, FALSE))
@@ -585,6 +629,11 @@ static status_t process_r(private_ike_auth_t *this, message_t *message)
return NEED_MORE;
}
+ /* store authentication information */
+ cfg = auth_cfg_create();
+ cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, FALSE), FALSE);
+ this->ike_sa->add_auth_cfg(this->ike_sa, FALSE, cfg);
+
if (!update_cfg_candidates(this, FALSE))
{
this->authentication_failed = TRUE;
@@ -603,10 +652,8 @@ static status_t process_r(private_ike_auth_t *this, message_t *message)
return NEED_MORE;
}
-/**
- * Implementation of task_t.build for responder
- */
-static status_t build_r(private_ike_auth_t *this, message_t *message)
+METHOD(task_t, build_r, status_t,
+ private_ike_auth_t *this, message_t *message)
{
auth_cfg_t *cfg;
@@ -662,8 +709,16 @@ static status_t build_r(private_ike_auth_t *this, message_t *message)
}
id_payload = id_payload_create_from_identification(ID_RESPONDER, id);
+ get_reserved_id_bytes(this, id_payload);
message->add_payload(message, (payload_t*)id_payload);
+ if (this->initial_contact)
+ {
+ charon->ike_sa_manager->check_uniqueness(charon->ike_sa_manager,
+ this->ike_sa, TRUE);
+ this->initial_contact = FALSE;
+ }
+
if ((uintptr_t)cfg->get(cfg, AUTH_RULE_AUTH_CLASS) == AUTH_CLASS_EAP)
{ /* EAP-only authentication */
if (!this->ike_sa->supports_extension(this->ike_sa,
@@ -682,7 +737,8 @@ static status_t build_r(private_ike_auth_t *this, message_t *message)
this->my_auth = authenticator_create_builder(this->ike_sa, cfg,
this->other_nonce, this->my_nonce,
this->other_packet->get_data(this->other_packet),
- this->my_packet->get_data(this->my_packet));
+ this->my_packet->get_data(this->my_packet),
+ this->reserved);
if (!this->my_auth)
{
message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
@@ -744,7 +800,7 @@ static status_t build_r(private_ike_auth_t *this, message_t *message)
if (!this->do_another_auth && !this->expect_another_auth)
{
if (charon->ike_sa_manager->check_uniqueness(charon->ike_sa_manager,
- this->ike_sa))
+ this->ike_sa, FALSE))
{
DBG1(DBG_IKE, "cancelling IKE_SA setup due uniqueness policy");
message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
@@ -772,10 +828,8 @@ static status_t build_r(private_ike_auth_t *this, message_t *message)
return NEED_MORE;
}
-/**
- * Implementation of task_t.process for initiator
- */
-static status_t process_i(private_ike_auth_t *this, message_t *message)
+METHOD(task_t, process_i, status_t,
+ private_ike_auth_t *this, message_t *message)
{
enumerator_t *enumerator;
payload_t *payload;
@@ -857,6 +911,7 @@ static status_t process_i(private_ike_auth_t *this, message_t *message)
return FAILED;
}
id = id_payload->get_identification(id_payload);
+ get_reserved_id_bytes(this, id_payload);
this->ike_sa->set_other_id(this->ike_sa, id);
cfg = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
cfg->add(cfg, AUTH_RULE_IDENTITY, id->clone(id));
@@ -867,7 +922,8 @@ static status_t process_i(private_ike_auth_t *this, message_t *message)
this->other_auth = authenticator_create_verifier(this->ike_sa,
message, this->other_nonce, this->my_nonce,
this->other_packet->get_data(this->other_packet),
- this->my_packet->get_data(this->my_packet));
+ this->my_packet->get_data(this->my_packet),
+ this->reserved);
if (!this->other_auth)
{
return FAILED;
@@ -893,17 +949,17 @@ static status_t process_i(private_ike_auth_t *this, message_t *message)
this->other_auth->destroy(this->other_auth);
this->other_auth = NULL;
}
- /* store authentication information, reset authenticator */
- cfg = auth_cfg_create();
- cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, FALSE), FALSE);
- this->ike_sa->add_auth_cfg(this->ike_sa, FALSE, cfg);
-
/* another auth round done, invoke authorize hook */
if (!charon->bus->authorize(charon->bus, FALSE))
{
DBG1(DBG_IKE, "authorization forbids IKE_SA, cancelling");
return FAILED;
}
+
+ /* store authentication information, reset authenticator */
+ cfg = auth_cfg_create();
+ cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, FALSE), FALSE);
+ this->ike_sa->add_auth_cfg(this->ike_sa, FALSE, cfg);
}
if (this->my_auth)
@@ -964,18 +1020,14 @@ static status_t process_i(private_ike_auth_t *this, message_t *message)
return NEED_MORE;
}
-/**
- * Implementation of task_t.get_type
- */
-static task_type_t get_type(private_ike_auth_t *this)
+METHOD(task_t, get_type, task_type_t,
+ private_ike_auth_t *this)
{
return IKE_AUTHENTICATE;
}
-/**
- * Implementation of task_t.migrate
- */
-static void migrate(private_ike_auth_t *this, ike_sa_t *ike_sa)
+METHOD(task_t, migrate, void,
+ private_ike_auth_t *this, ike_sa_t *ike_sa)
{
chunk_free(&this->my_nonce);
chunk_free(&this->other_nonce);
@@ -998,10 +1050,8 @@ static void migrate(private_ike_auth_t *this, ike_sa_t *ike_sa)
this->candidates = linked_list_create();
}
-/**
- * Implementation of task_t.destroy
- */
-static void destroy(private_ike_auth_t *this)
+METHOD(task_t, destroy, void,
+ private_ike_auth_t *this)
{
chunk_free(&this->my_nonce);
chunk_free(&this->other_nonce);
@@ -1019,37 +1069,29 @@ static void destroy(private_ike_auth_t *this)
*/
ike_auth_t *ike_auth_create(ike_sa_t *ike_sa, bool initiator)
{
- private_ike_auth_t *this = malloc_thing(private_ike_auth_t);
-
- this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
- this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
- this->public.task.destroy = (void(*)(task_t*))destroy;
-
+ private_ike_auth_t *this;
+
+ INIT(this,
+ .public = {
+ .task = {
+ .get_type = _get_type,
+ .migrate = _migrate,
+ .build = _build_r,
+ .process = _process_r,
+ .destroy = _destroy,
+ },
+ },
+ .ike_sa = ike_sa,
+ .initiator = initiator,
+ .candidates = linked_list_create(),
+ .do_another_auth = TRUE,
+ .expect_another_auth = TRUE,
+ );
if (initiator)
{
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
- }
- else
- {
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
+ this->public.task.build = _build_i;
+ this->public.task.process = _process_i;
}
-
- this->ike_sa = ike_sa;
- this->initiator = initiator;
- this->my_nonce = chunk_empty;
- this->other_nonce = chunk_empty;
- this->my_packet = NULL;
- this->other_packet = NULL;
- this->peer_cfg = NULL;
- this->candidates = linked_list_create();
- this->my_auth = NULL;
- this->other_auth = NULL;
- this->do_another_auth = TRUE;
- this->expect_another_auth = TRUE;
- this->authentication_failed = FALSE;
-
return &this->public;
}
diff --git a/src/libcharon/sa/tasks/ike_cert_pre.c b/src/libcharon/sa/tasks/ike_cert_pre.c
index 1c0c54727..a59b8dcce 100644
--- a/src/libcharon/sa/tasks/ike_cert_pre.c
+++ b/src/libcharon/sa/tasks/ike_cert_pre.c
@@ -76,6 +76,7 @@ static void process_certreqs(private_ike_cert_pre_t *this, message_t *message)
{
certreq_payload_t *certreq = (certreq_payload_t*)payload;
enumerator_t *enumerator;
+ u_int unknown = 0;
chunk_t keyid;
this->ike_sa->set_condition(this->ike_sa, COND_CERTREQ_SEEN, TRUE);
@@ -103,12 +104,18 @@ static void process_certreqs(private_ike_cert_pre_t *this, message_t *message)
}
else
{
- DBG1(DBG_IKE, "received cert request for unknown ca "
+ DBG2(DBG_IKE, "received cert request for unknown ca "
"with keyid %Y", id);
+ unknown++;
}
id->destroy(id);
}
enumerator->destroy(enumerator);
+ if (unknown)
+ {
+ DBG1(DBG_IKE, "received %u cert requests for an unknown ca",
+ unknown);
+ }
break;
}
case NOTIFY:
@@ -253,11 +260,19 @@ static void process_certs(private_ike_cert_pre_t *this, message_t *message)
}
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_CRL:
case ENC_ARL:
case ENC_SPKI:
case ENC_X509_ATTRIBUTE:
diff --git a/src/libcharon/sa/tasks/ike_rekey.c b/src/libcharon/sa/tasks/ike_rekey.c
index 1a6c140c4..44c55036e 100644
--- a/src/libcharon/sa/tasks/ike_rekey.c
+++ b/src/libcharon/sa/tasks/ike_rekey.c
@@ -255,19 +255,20 @@ static status_t process_i(private_ike_rekey_t *this, message_t *message)
/* if we have the lower nonce, delete rekeyed SA. If not, delete
* the redundant. */
if (memcmp(this_nonce.ptr, other_nonce.ptr,
- min(this_nonce.len, other_nonce.len)) < 0)
+ min(this_nonce.len, other_nonce.len)) > 0)
{
/* peer should delete this SA. Add a timeout just in case. */
job_t *job = (job_t*)delete_ike_sa_job_create(
other->new_sa->get_id(other->new_sa), TRUE);
lib->scheduler->schedule_job(lib->scheduler, job, 10);
- DBG1(DBG_IKE, "IKE_SA rekey collision won, deleting rekeyed IKE_SA");
+ DBG1(DBG_IKE, "IKE_SA rekey collision won, waiting for delete");
charon->ike_sa_manager->checkin(charon->ike_sa_manager, other->new_sa);
other->new_sa = NULL;
}
else
{
- DBG1(DBG_IKE, "IKE_SA rekey collision lost, deleting redundant IKE_SA");
+ DBG1(DBG_IKE, "IKE_SA rekey collision lost, "
+ "deleting redundant IKE_SA");
/* apply host for a proper delete */
host = this->ike_sa->get_my_host(this->ike_sa);
this->new_sa->set_my_host(this->new_sa, host->clone(host));
diff --git a/src/libcharon/tnc/imc/imc.h b/src/libcharon/tnc/imc/imc.h
new file mode 100644
index 000000000..fe8f25b0f
--- /dev/null
+++ b/src/libcharon/tnc/imc/imc.h
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup imc imc
+ * @ingroup tnc
+ *
+ * @defgroup imct imc
+ * @{ @ingroup imc
+ */
+
+#ifndef IMC_H_
+#define IMC_H_
+
+#include <tnc/tncifimc.h>
+#include <library.h>
+
+typedef struct imc_t imc_t;
+
+/**
+ * Controls a single Integrity Measurement Collector (IMC)
+ */
+struct imc_t {
+
+ /**
+ * The TNC Client calls this function to initialize the IMC and agree on
+ * the API version number to be used. It also supplies the IMC ID, an IMC
+ * identifier that the IMC must use when calling TNC Client callback functions.
+ *
+ * @param imcID IMC ID assigned by TNCC
+ * @param minVersion minimum API version supported by TNCC
+ * @param maxVersion maximum API version supported by TNCC
+ * @param OutActualVersion mutually supported API version number
+ * @return TNC result code
+ */
+ TNC_Result (*initialize)(TNC_IMCID imcID,
+ TNC_Version minVersion,
+ TNC_Version maxVersion,
+ TNC_Version *OutActualVersion);
+
+ /**
+ * The TNC Client calls this function to inform the IMC that the state of
+ * the network connection identified by connectionID has changed to newState.
+ *
+ * @param imcID IMC ID assigned by TNCC
+ * @param connectionID network connection ID assigned by TNCC
+ * @param newState new network connection state
+ * @return TNC result code
+ */
+ TNC_Result (*notify_connection_change)(TNC_IMCID imcID,
+ TNC_ConnectionID connectionID,
+ TNC_ConnectionState newState);
+
+ /**
+ * The TNC Client calls this function to indicate that an Integrity Check
+ * Handshake is beginning and solicit messages from IMCs for the first batch.
+ *
+ * @param imcID IMC ID assigned by TNCC
+ * @param connectionID network connection ID assigned by TNCC
+ * @return TNC result code
+ */
+ TNC_Result (*begin_handshake)(TNC_IMCID imcID,
+ TNC_ConnectionID connectionID);
+
+ /**
+ * The TNC Client calls this function to deliver a message to the IMC.
+ * The message is contained in the buffer referenced by message and contains
+ * the number of octets indicated by messageLength. The type of the message
+ * is indicated by messageType.
+ *
+ * @param imcID IMC ID assigned by TNCS
+ * @param connectionID network connection ID assigned by TNCC
+ * @param message reference to buffer containing message
+ * @param messageLength number of octets in message
+ * @param messageType message type of message
+ * @return TNC result code
+ */
+ TNC_Result (*receive_message)(TNC_IMCID imcID,
+ TNC_ConnectionID connectionID,
+ TNC_BufferReference message,
+ TNC_UInt32 messageLength,
+ TNC_MessageType messageType);
+
+ /**
+ * The TNC Client calls this function to notify IMCs that all IMV messages
+ * received in a batch have been delivered and this is the IMC’s last chance
+ * to send a message in the batch of IMC messages currently being collected.
+ *
+ * @param imcID IMC ID assigned by TNCC
+ * @param connectionID network connection ID assigned by TNCC
+ * @return TNC result code
+ */
+ TNC_Result (*batch_ending)(TNC_IMCID imcID,
+ TNC_ConnectionID connectionID);
+
+ /**
+ * The TNC Client calls this function to close down the IMC when all work is
+ * complete or the IMC reports TNC_RESULT_FATAL.
+ *
+ * @param imcID IMC ID assigned by TNCC
+ * @return TNC result code
+ */
+ TNC_Result (*terminate)(TNC_IMCID imcID);
+
+ /**
+ * IMVs implementing the UNIX/Linux Dynamic Linkage platform binding MUST
+ * define this additional function. The TNC Server MUST call the function
+ * immediately after calling TNC_IMV_Initialize to provide a pointer to the
+ * TNCS bind function. The IMV can then use the TNCS bind function to obtain
+ * pointers to any other TNCS functions.
+ *
+ * @param imcID IMC ID assigned by TNCC
+ * @param bindFunction pointer to TNC_TNCC_BindFunction
+ * @return TNC result code
+ */
+ TNC_Result (*provide_bind_function)(TNC_IMCID imcID,
+ TNC_TNCC_BindFunctionPointer bindFunction);
+
+ /**
+ * Sets the ID of an imc_t object.
+ *
+ * @param id IMC ID to be assigned
+ */
+ void (*set_id)(imc_t *this, TNC_IMCID id);
+
+ /**
+ * Returns the ID of an imc_t object.
+ *
+ * @return assigned IMC ID
+ */
+ TNC_IMCID (*get_id)(imc_t *this);
+
+ /**
+ * Returns the name of an imc_t object.
+ *
+ * @return name of IMC
+ */
+ char* (*get_name)(imc_t *this);
+
+ /**
+ * Sets the supported message types of an imc_t object.
+ *
+ * @param supported_types list of messages type supported by IMC
+ * @param type_count number of supported message types
+ */
+ void (*set_message_types)(imc_t *this, TNC_MessageTypeList supported_types,
+ TNC_UInt32 type_count);
+
+ /**
+ * Check if the IMC supports a given message type.
+ *
+ * @param message_type message type
+ * @return TRUE if supported
+ */
+ bool (*type_supported)(imc_t *this, TNC_MessageType message_type);
+
+ /**
+ * Destroys an imc_t object.
+ */
+ void (*destroy)(imc_t *this);
+};
+
+#endif /** IMC_H_ @}*/
diff --git a/src/libcharon/tnc/imc/imc_manager.h b/src/libcharon/tnc/imc/imc_manager.h
new file mode 100644
index 000000000..634afdbe8
--- /dev/null
+++ b/src/libcharon/tnc/imc/imc_manager.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup imc_manager imc_manager
+ * @{ @ingroup imc
+ */
+
+#ifndef IMC_MANAGER_H_
+#define IMC_MANAGER_H_
+
+#include "imc.h"
+
+#include <library.h>
+
+typedef struct imc_manager_t imc_manager_t;
+
+/**
+ * The IMC manager controls all IMC instances.
+ */
+struct imc_manager_t {
+
+ /**
+ * Add an IMC instance
+ *
+ * @param imc IMC instance
+ * @return TRUE if initialization successful
+ */
+ bool (*add)(imc_manager_t *this, imc_t *imc);
+
+ /**
+ * Remove an IMC instance from the list and return it
+ *
+ * @param id ID of IMC instance
+ * @return removed IMC instance
+ */
+ imc_t* (*remove)(imc_manager_t *this, TNC_IMCID id);
+
+ /**
+ * Return the preferred language for recommendations
+ *
+ * @return preferred language string
+ */
+ char* (*get_preferred_language)(imc_manager_t *this);
+
+ /**
+ * Notify all IMC instances
+ *
+ * @param state communicate the state a connection has reached
+ */
+ void (*notify_connection_change)(imc_manager_t *this,
+ TNC_ConnectionID id,
+ TNC_ConnectionState state);
+
+ /**
+ * Begin a handshake between the IMCs and a connection
+ *
+ * @param id connection ID
+ */
+ void (*begin_handshake)(imc_manager_t *this, TNC_ConnectionID id);
+
+ /**
+ * Sets the supported message types reported by a given IMC
+ *
+ * @param id ID of reporting IMC
+ * @param supported_types list of messages type supported by IMC
+ * @param type_count number of supported message types
+ * @return TNC result code
+ */
+ TNC_Result (*set_message_types)(imc_manager_t *this,
+ TNC_IMCID id,
+ TNC_MessageTypeList supported_types,
+ TNC_UInt32 type_count);
+
+ /**
+ * Delivers a message to interested IMCs.
+ *
+ * @param connection_id ID of connection over which message was received
+ * @param message message
+ * @param message_len message length
+ * @param message_type message type
+ */
+ void (*receive_message)(imc_manager_t *this,
+ TNC_ConnectionID connection_id,
+ TNC_BufferReference message,
+ TNC_UInt32 message_len,
+ TNC_MessageType message_type);
+
+ /**
+ * Notify all IMCs that all IMV messages received in a batch have been
+ * delivered and this is the IMCs last chance to send a message in the
+ * batch of IMC messages currently being collected.
+ *
+ * @param id connection ID
+ */
+ void (*batch_ending)(imc_manager_t *this, TNC_ConnectionID id);
+
+ /**
+ * Destroy an IMC manager and all its controlled instances.
+ */
+ void (*destroy)(imc_manager_t *this);
+};
+
+#endif /** IMC_MANAGER_H_ @}*/
diff --git a/src/libcharon/tnc/imv/imv.h b/src/libcharon/tnc/imv/imv.h
new file mode 100644
index 000000000..26874ab0b
--- /dev/null
+++ b/src/libcharon/tnc/imv/imv.h
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup imv imv
+ * @ingroup tnc
+ *
+ * @defgroup imvt imv
+ * @{ @ingroup imv
+ */
+
+#ifndef IMV_H_
+#define IMV_H_
+
+#include <tnc/tncifimv.h>
+#include <library.h>
+
+typedef struct imv_t imv_t;
+
+/**
+ * Controls a single Integrity Measurement Verifier (IMV)
+ */
+struct imv_t {
+
+ /**
+ * The TNC Server calls this function to initialize the IMV and agree on
+ * the API version number to be used. It also supplies the IMV ID, an IMV
+ * identifier that the IMV must use when calling TNC Server callback functions.
+ *
+ * @param imvID IMV ID assigned by TNCS
+ * @param minVersion minimum API version supported
+ * @param maxVersion maximum API version supported by TNCS
+ * @param OutActualVersion mutually supported API version number
+ * @return TNC result code
+ */
+ TNC_Result (*initialize)(TNC_IMVID imvID,
+ TNC_Version minVersion,
+ TNC_Version maxVersion,
+ TNC_Version *OutActualVersion);
+
+ /**
+ * The TNC Server calls this function to inform the IMV that the state of
+ * the network connection identified by connectionID has changed to newState.
+ *
+ * @param imvID IMV ID assigned by TNCS
+ * @param connectionID network connection ID assigned by TNCS
+ * @param newState new network connection state
+ * @return TNC result code
+ */
+ TNC_Result (*notify_connection_change)(TNC_IMVID imvID,
+ TNC_ConnectionID connectionID,
+ TNC_ConnectionState newState);
+
+ /**
+ * The TNC Server calls this function at the end of an Integrity Check
+ * Handshake (after all IMC-IMV messages have been delivered) to solicit
+ * recommendations from IMVs that have not yet provided a recommendation.
+ *
+ * @param imvID IMV ID assigned by TNCS
+ * @param connectionID network connection ID assigned by TNCS
+ * @return TNC result code
+ */
+ TNC_Result (*solicit_recommendation)(TNC_IMVID imvID,
+ TNC_ConnectionID connectionID);
+
+ /**
+ * The TNC Server calls this function to deliver a message to the IMV.
+ * The message is contained in the buffer referenced by message and contains
+ * the number of octets indicated by messageLength. The type of the message
+ * is indicated by messageType.
+ *
+ * @param imvID IMV ID assigned by TNCS
+ * @param connectionID network connection ID assigned by TNCS
+ * @param message reference to buffer containing message
+ * @param messageLength number of octets in message
+ * @param messageType message type of message
+ * @return TNC result code
+ */
+ TNC_Result (*receive_message)(TNC_IMVID imvID,
+ TNC_ConnectionID connectionID,
+ TNC_BufferReference message,
+ TNC_UInt32 messageLength,
+ TNC_MessageType messageType);
+
+ /**
+ * The TNC Server calls this function to notify IMVs that all IMC messages
+ * received in a batch have been delivered and this is the IMV’s last chance
+ * to send a message in the batch of IMV messages currently being collected.
+ *
+ * @param imvID IMV ID assigned by TNCS
+ * @param connectionID network connection ID assigned by TNCS
+ * @return TNC result code
+ */
+ TNC_Result (*batch_ending)(TNC_IMVID imvID,
+ TNC_ConnectionID connectionID);
+
+ /**
+ * The TNC Server calls this function to close down the IMV.
+ *
+ * @param imvID IMV ID assigned by TNCS
+ * @return TNC result code
+ */
+ TNC_Result (*terminate)(TNC_IMVID imvID);
+
+ /**
+ * IMVs implementing the UNIX/Linux Dynamic Linkage platform binding MUST
+ * define this additional function. The TNC Server MUST call the function
+ * immediately after calling TNC_IMV_Initialize to provide a pointer to the
+ * TNCS bind function. The IMV can then use the TNCS bind function to obtain
+ * pointers to any other TNCS functions.
+ *
+ * @param imvID IMV ID assigned by TNCS
+ * @param bindFunction pointer to TNC_TNCS_BindFunction
+ * @return TNC result code
+ */
+ TNC_Result (*provide_bind_function)(TNC_IMVID imvID,
+ TNC_TNCS_BindFunctionPointer bindFunction);
+
+ /**
+ * Sets the ID of an imv_t object.
+ *
+ * @param id IMV ID to be assigned
+ */
+ void (*set_id)(imv_t *this, TNC_IMVID id);
+
+ /**
+ * Returns the ID of an imv_t object.
+ *
+ * @return IMV ID assigned by TNCS
+ */
+ TNC_IMVID (*get_id)(imv_t *this);
+
+ /**
+ * Returns the name of an imv_t object.
+ *
+ * @return name of IMV
+ */
+ char* (*get_name)(imv_t *this);
+
+ /**
+ * Sets the supported message types of an imv_t object.
+ *
+ * @param supported_types list of messages type supported by IMV
+ * @param type_count number of supported message types
+ */
+ void (*set_message_types)(imv_t *this, TNC_MessageTypeList supported_types,
+ TNC_UInt32 type_count);
+
+ /**
+ * Check if the IMV supports a given message type.
+ *
+ * @param message_type message type
+ * @return TRUE if supported
+ */
+ bool (*type_supported)(imv_t *this, TNC_MessageType message_type);
+
+ /**
+ * Destroys an imv_t object.
+ */
+ void (*destroy)(imv_t *this);
+};
+
+#endif /** IMV_H_ @}*/
diff --git a/src/libcharon/tnc/imv/imv_manager.h b/src/libcharon/tnc/imv/imv_manager.h
new file mode 100644
index 000000000..b5c581a75
--- /dev/null
+++ b/src/libcharon/tnc/imv/imv_manager.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup imv_manager imv_manager
+ * @{ @ingroup imv
+ */
+
+#ifndef IMV_MANAGER_H_
+#define IMV_MANAGER_H_
+
+#include "imv.h"
+#include "imv_recommendations.h"
+
+#include <library.h>
+
+typedef struct imv_manager_t imv_manager_t;
+
+/**
+ * The IMV manager controls all IMV instances.
+ */
+struct imv_manager_t {
+
+ /**
+ * Add an IMV instance
+ *
+ * @param imv IMV instance
+ * @return TRUE if initialization successful
+ */
+ bool (*add)(imv_manager_t *this, imv_t *imv);
+
+ /**
+ * Remove an IMV instance from the list and return it
+ *
+ * @param id ID of IMV instance
+ * @return removed IMC instance
+ */
+ imv_t* (*remove)(imv_manager_t *this, TNC_IMVID id);
+
+ /**
+ * Get the configured recommendation policy
+ *
+ * @return configured recommendation policy
+ */
+ recommendation_policy_t (*get_recommendation_policy)(imv_manager_t *this);
+
+ /**
+ * Create an empty set of IMV recommendations and evaluations
+ *
+ * @return instance of a recommendations_t list
+ */
+ recommendations_t* (*create_recommendations)(imv_manager_t *this);
+
+ /**
+ * Enforce the TNC recommendation on the IKE_SA by either inserting an
+ * allow|isolate group membership rule (TRUE) or by blocking access (FALSE)
+ *
+ * @param void TNC action recommendation
+ * @return TRUE for allow|isolate, FALSE for none
+ */
+ bool (*enforce_recommendation)(imv_manager_t *this,
+ TNC_IMV_Action_Recommendation rec);
+
+ /**
+ * Notify all IMV instances
+ *
+ * @param state communicate the state a connection has reached
+ */
+ void (*notify_connection_change)(imv_manager_t *this,
+ TNC_ConnectionID id,
+ TNC_ConnectionState state);
+
+ /**
+ * Sets the supported message types reported by a given IMV
+ *
+ * @param id ID of reporting IMV
+ * @param supported_types list of messages type supported by IMV
+ * @param type_count number of supported message types
+ * @return TNC result code
+ */
+ TNC_Result (*set_message_types)(imv_manager_t *this,
+ TNC_IMVID id,
+ TNC_MessageTypeList supported_types,
+ TNC_UInt32 type_count);
+
+ /**
+ * Solicit recommendations from IMVs that have not yet provided one
+ *
+ * @param id connection ID
+ */
+ void (*solicit_recommendation)(imv_manager_t *this, TNC_ConnectionID id);
+
+ /**
+ * Delivers a message to interested IMVs.
+ *
+ * @param connection_id ID of connection over which message was received
+ * @param message message
+ * @param message_len message length
+ * @param message_type message type
+ */
+ void (*receive_message)(imv_manager_t *this,
+ TNC_ConnectionID connection_id,
+ TNC_BufferReference message,
+ TNC_UInt32 message_len,
+ TNC_MessageType message_type);
+
+ /**
+ * Notify all IMVs that all IMC messages received in a batch have been
+ * delivered and this is the IMVs last chance to send a message in the
+ * batch of IMV messages currently being collected.
+ *
+ * @param id connection ID
+ */
+ void (*batch_ending)(imv_manager_t *this, TNC_ConnectionID id);
+
+ /**
+ * Destroy an IMV manager and all its controlled instances.
+ */
+ void (*destroy)(imv_manager_t *this);
+};
+
+#endif /** IMV_MANAGER_H_ @}*/
diff --git a/src/libcharon/tnc/imv/imv_recommendations.c b/src/libcharon/tnc/imv/imv_recommendations.c
new file mode 100644
index 000000000..9daaca16c
--- /dev/null
+++ b/src/libcharon/tnc/imv/imv_recommendations.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "imv_recommendations.h"
+
+ENUM(recommendation_policy_names, RECOMMENDATION_POLICY_DEFAULT,
+ RECOMMENDATION_POLICY_ALL,
+ "default",
+ "any",
+ "all"
+);
+
diff --git a/src/libcharon/tnc/imv/imv_recommendations.h b/src/libcharon/tnc/imv/imv_recommendations.h
new file mode 100644
index 000000000..3a6e25c9f
--- /dev/null
+++ b/src/libcharon/tnc/imv/imv_recommendations.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup imv_recommendations imv_recommendations
+ * @{ @ingroup imv
+ */
+
+#ifndef IMV_RECOMMENDATIONS_H_
+#define IMV_RECOMMENDATIONS_H_
+
+#include <tnc/tncifimv.h>
+#include <library.h>
+
+typedef enum recommendation_policy_t recommendation_policy_t;
+
+enum recommendation_policy_t {
+ RECOMMENDATION_POLICY_DEFAULT,
+ RECOMMENDATION_POLICY_ANY,
+ RECOMMENDATION_POLICY_ALL
+};
+
+extern enum_name_t *recommendation_policy_names;
+
+
+typedef struct recommendations_t recommendations_t;
+
+/**
+ * Collection of all IMV action recommendations and evaluation results
+ */
+struct recommendations_t {
+
+ /**
+ * Deliver an IMV action recommendation and IMV evaluation result to the TNCS
+ *
+ * @param imv_id ID of the IMV providing the recommendation
+ * @param rec action recommendation
+ * @param eval evaluation result
+ * @return return code
+ */
+ TNC_Result (*provide_recommendation)(recommendations_t *this,
+ TNC_IMVID imv_id,
+ TNC_IMV_Action_Recommendation rec,
+ TNC_IMV_Evaluation_Result eval);
+
+ /**
+ * If all IMVs provided a recommendation, derive a consolidated action
+ * recommendation and evaluation result based on a configured policy
+ *
+ * @param rec action recommendation
+ * @param eval evaluation result
+ * @return TRUE if all IMVs provided a recommendation
+ */
+ bool (*have_recommendation)(recommendations_t *this,
+ TNC_IMV_Action_Recommendation *rec,
+ TNC_IMV_Evaluation_Result *eval);
+
+ /**
+ * Get the preferred language for remediation messages
+ *
+ * @return preferred language
+ */
+ chunk_t (*get_preferred_language)(recommendations_t *this);
+
+ /**
+ * Set the preferred language for remediation messages
+ *
+ * @param pref_lang preferred language
+ */
+ void (*set_preferred_language)(recommendations_t *this, chunk_t pref_lang);
+
+ /**
+ * Set the reason string
+ *
+ * @param id ID of IMV setting the reason string
+ * @param reason reason string
+ * @result return code
+ */
+ TNC_Result (*set_reason_string)(recommendations_t *this, TNC_IMVID id,
+ chunk_t reason);
+
+ /**
+ * Set the language for reason strings
+ *
+ * @param id ID of IMV setting the reason language
+ * @param reason_lang reason language
+ * @result return code
+ */
+ TNC_Result (*set_reason_language)(recommendations_t *this, TNC_IMVID id,
+ chunk_t reason_lang);
+
+ /**
+ * Enumerates over all IMVs sending a reason string.
+ * Format: TNC_IMVID *id, chunk_t *reason, chunk_t *reason_language
+ *
+ * @return enumerator
+ */
+ enumerator_t* (*create_reason_enumerator)(recommendations_t *this);
+ /**
+ * Destroys an imv_t object.
+ */
+ void (*destroy)(recommendations_t *this);
+};
+
+#endif /** IMV_RECOMMENDATIONS_H_ @}*/
diff --git a/src/libcharon/tnccs/tnccs.c b/src/libcharon/tnc/tnccs/tnccs.c
index 2facf02c8..575b850f5 100644
--- a/src/libcharon/tnccs/tnccs.c
+++ b/src/libcharon/tnc/tnccs/tnccs.c
@@ -15,7 +15,8 @@
#include "tnccs.h"
-ENUM(eap_type_names, TNCCS_1_1, TNCCS_2_0,
+ENUM(tnccs_type_names, TNCCS_UNKNOWN, TNCCS_2_0,
+ "unknown TNCCS",
"TNCCS 1.1",
"TNCCS SOH",
"TNCCS 2.0",
diff --git a/src/libcharon/tnccs/tnccs.h b/src/libcharon/tnc/tnccs/tnccs.h
index 583512e82..c5d6f5ef0 100644
--- a/src/libcharon/tnccs/tnccs.h
+++ b/src/libcharon/tnc/tnccs/tnccs.h
@@ -15,23 +15,38 @@
/**
* @defgroup tnccs tnccs
- * @{ @ingroup libcharon
+ * @ingroup tnc
+ *
+ * @defgroup tnccst tnccs
+ * @{ @ingroup tnccs
*/
#ifndef TNCCS_H_
#define TNCCS_H_
-typedef enum tnccs_type_t tnccs_type_t;
-
+#include <tnc/tncif.h>
+#include <tnc/tncifimc.h>
+#include <tnc/tncifimv.h>
#include <library.h>
+#define IETF_VENDOR_ID 0x000000 /* 0 */
+#define MICROSOFT_VENDOR_ID 0x000137 /* 311 */
+#define OSC_VENDOR_ID 0x002358 /* 9048 */
+#define FHH_VENDOR_ID 0x0080ab /* 32939 */
+#define ITA_VENDOR_ID 0x00902a /* 36906 */
+#define RESERVED_VENDOR_ID 0xffffff /* 16777215 */
+
+typedef enum tnccs_type_t tnccs_type_t;
+
/**
* Type of TNC Client/Server protocol
*/
enum tnccs_type_t {
+ TNCCS_UNKNOWN,
TNCCS_1_1,
TNCCS_SOH,
- TNCCS_2_0
+ TNCCS_2_0,
+ TNCCS_DYNAMIC
};
/**
@@ -49,4 +64,19 @@ typedef struct tnccs_t tnccs_t;
*/
typedef tnccs_t* (*tnccs_constructor_t)(bool is_server);
-#endif /** TNC_H_ @}*/
+/**
+ * Callback function adding a message to a TNCCS batch
+ *
+ * @param imc_id ID of IMC or TNC_IMCID_ANY
+ * @param imc_id ID of IMV or TNC_IMVID_ANY
+ * @param msg message to be added
+ * @param msg_len message length
+ * @param msg_type message type
+ */
+typedef void (*tnccs_send_message_t)(tnccs_t* tncss, TNC_IMCID imc_id,
+ TNC_IMVID imv_id,
+ TNC_BufferReference msg,
+ TNC_UInt32 msg_len,
+ TNC_MessageType msg_type);
+
+#endif /** TNCCS_H_ @}*/
diff --git a/src/libcharon/tnc/tnccs/tnccs_manager.c b/src/libcharon/tnc/tnccs/tnccs_manager.c
new file mode 100644
index 000000000..7e522b870
--- /dev/null
+++ b/src/libcharon/tnc/tnccs/tnccs_manager.c
@@ -0,0 +1,477 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnccs_manager.h"
+
+#include <tnc/imv/imv_recommendations.h>
+
+#include <debug.h>
+#include <daemon.h>
+#include <utils/linked_list.h>
+#include <threading/rwlock.h>
+
+typedef struct private_tnccs_manager_t private_tnccs_manager_t;
+typedef struct tnccs_entry_t tnccs_entry_t;
+typedef struct tnccs_connection_entry_t tnccs_connection_entry_t;
+
+/**
+ * TNCCS constructor entry
+ */
+struct tnccs_entry_t {
+
+ /**
+ * TNCCS protocol type
+ */
+ tnccs_type_t type;
+
+ /**
+ * constructor function to create instance
+ */
+ tnccs_constructor_t constructor;
+};
+
+/**
+ * TNCCS connection entry
+ */
+struct tnccs_connection_entry_t {
+
+ /**
+ * TNCCS connection ID
+ */
+ TNC_ConnectionID id;
+
+ /**
+ * TNCCS instance
+ */
+ tnccs_t *tnccs;
+
+ /**
+ * TNCCS send message function
+ */
+ tnccs_send_message_t send_message;
+
+ /**
+ * TNCCS request handshake retry flag
+ */
+ bool *request_handshake_retry;
+
+ /**
+ * collection of IMV recommendations
+ */
+ recommendations_t *recs;
+};
+
+/**
+ * private data of tnccs_manager
+ */
+struct private_tnccs_manager_t {
+
+ /**
+ * public functions
+ */
+ tnccs_manager_t public;
+
+ /**
+ * list of TNCCS protocol entries
+ */
+ linked_list_t *protocols;
+
+ /**
+ * rwlock to lock the TNCCS protocol entries
+ */
+ rwlock_t *protocol_lock;
+
+ /**
+ * connection ID counter
+ */
+ TNC_ConnectionID connection_id;
+
+ /**
+ * list of TNCCS connection entries
+ */
+ linked_list_t *connections;
+
+ /**
+ * rwlock to lock TNCCS connection entries
+ */
+ rwlock_t *connection_lock;
+
+};
+
+METHOD(tnccs_manager_t, add_method, void,
+ private_tnccs_manager_t *this, tnccs_type_t type,
+ tnccs_constructor_t constructor)
+{
+ tnccs_entry_t *entry;
+
+ entry = malloc_thing(tnccs_entry_t);
+ entry->type = type;
+ entry->constructor = constructor;
+
+ this->protocol_lock->write_lock(this->protocol_lock);
+ this->protocols->insert_last(this->protocols, entry);
+ this->protocol_lock->unlock(this->protocol_lock);
+}
+
+METHOD(tnccs_manager_t, remove_method, void,
+ private_tnccs_manager_t *this, tnccs_constructor_t constructor)
+{
+ enumerator_t *enumerator;
+ tnccs_entry_t *entry;
+
+ this->protocol_lock->write_lock(this->protocol_lock);
+ enumerator = this->protocols->create_enumerator(this->protocols);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (constructor == entry->constructor)
+ {
+ this->protocols->remove_at(this->protocols, enumerator);
+ free(entry);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->protocol_lock->unlock(this->protocol_lock);
+}
+
+METHOD(tnccs_manager_t, create_instance, tnccs_t*,
+ private_tnccs_manager_t *this, tnccs_type_t type, bool is_server)
+{
+ enumerator_t *enumerator;
+ tnccs_entry_t *entry;
+ tnccs_t *protocol = NULL;
+
+ this->protocol_lock->read_lock(this->protocol_lock);
+ enumerator = this->protocols->create_enumerator(this->protocols);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (type == entry->type)
+ {
+ protocol = entry->constructor(is_server);
+ if (protocol)
+ {
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->protocol_lock->unlock(this->protocol_lock);
+
+ return protocol;
+}
+
+METHOD(tnccs_manager_t, create_connection, TNC_ConnectionID,
+ private_tnccs_manager_t *this, tnccs_t *tnccs,
+ tnccs_send_message_t send_message, bool* request_handshake_retry,
+ recommendations_t **recs)
+{
+ tnccs_connection_entry_t *entry;
+
+ entry = malloc_thing(tnccs_connection_entry_t);
+ entry->tnccs = tnccs;
+ entry->send_message = send_message;
+ entry->request_handshake_retry = request_handshake_retry;
+ if (recs)
+ {
+ /* we assume a TNC Server needing recommendations from IMVs */
+ if (!charon->imvs)
+ {
+ DBG1(DBG_TNC, "no IMV manager available!");
+ free(entry);
+ return 0;
+ }
+ entry->recs = charon->imvs->create_recommendations(charon->imvs);
+ *recs = entry->recs;
+ }
+ else
+ {
+ /* we assume a TNC Client */
+ if (!charon->imcs)
+ {
+ DBG1(DBG_TNC, "no IMC manager available!");
+ free(entry);
+ return 0;
+ }
+ entry->recs = NULL;
+ }
+ this->connection_lock->write_lock(this->connection_lock);
+ entry->id = ++this->connection_id;
+ this->connections->insert_last(this->connections, entry);
+ this->connection_lock->unlock(this->connection_lock);
+
+ DBG1(DBG_TNC, "assigned TNCCS Connection ID %u", entry->id);
+ return entry->id;
+}
+
+METHOD(tnccs_manager_t, remove_connection, void,
+ private_tnccs_manager_t *this, TNC_ConnectionID id)
+{
+ enumerator_t *enumerator;
+ tnccs_connection_entry_t *entry;
+
+ this->connection_lock->write_lock(this->connection_lock);
+ enumerator = this->connections->create_enumerator(this->connections);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (id == entry->id)
+ {
+ this->connections->remove_at(this->connections, enumerator);
+ if (entry->recs)
+ {
+ entry->recs->destroy(entry->recs);
+ }
+ free(entry);
+ DBG1(DBG_TNC, "removed TNCCS Connection ID %u", id);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->connection_lock->unlock(this->connection_lock);
+}
+
+METHOD(tnccs_manager_t, request_handshake_retry, TNC_Result,
+ private_tnccs_manager_t *this, bool is_imc, TNC_UInt32 imcv_id,
+ TNC_ConnectionID id,
+ TNC_RetryReason reason)
+{
+ enumerator_t *enumerator;
+ tnccs_connection_entry_t *entry;
+
+ if (id == TNC_CONNECTIONID_ANY)
+ {
+ DBG2(DBG_TNC, "%s %u requests handshake retry for all connections "
+ "(reason: %u)", is_imc ? "IMC":"IMV", reason);
+ }
+ else
+ {
+ DBG2(DBG_TNC, "%s %u requests handshake retry for connection ID %u "
+ "(reason: %u)", is_imc ? "IMC":"IMV", id, reason);
+ }
+ this->connection_lock->read_lock(this->connection_lock);
+ enumerator = this->connections->create_enumerator(this->connections);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (id == TNC_CONNECTIONID_ANY || id == entry->id)
+ {
+ *entry->request_handshake_retry = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->connection_lock->unlock(this->connection_lock);
+
+ return TNC_RESULT_SUCCESS;
+}
+
+METHOD(tnccs_manager_t, send_message, TNC_Result,
+ private_tnccs_manager_t *this, TNC_IMCID imc_id, TNC_IMVID imv_id,
+ TNC_ConnectionID id,
+ TNC_BufferReference msg,
+ TNC_UInt32 msg_len,
+ TNC_MessageType msg_type)
+{
+ enumerator_t *enumerator;
+ tnccs_connection_entry_t *entry;
+ tnccs_send_message_t send_message = NULL;
+ tnccs_t *tnccs = NULL;
+
+ this->connection_lock->read_lock(this->connection_lock);
+ enumerator = this->connections->create_enumerator(this->connections);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (id == entry->id)
+ {
+ tnccs = entry->tnccs;
+ send_message = entry->send_message;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->connection_lock->unlock(this->connection_lock);
+
+ if (tnccs && send_message)
+ {
+ send_message(tnccs, imc_id, imv_id, msg, msg_len, msg_type);
+ return TNC_RESULT_SUCCESS;
+ }
+ return TNC_RESULT_FATAL;
+}
+
+METHOD(tnccs_manager_t, provide_recommendation, TNC_Result,
+ private_tnccs_manager_t *this, TNC_IMVID imv_id,
+ TNC_ConnectionID id,
+ TNC_IMV_Action_Recommendation rec,
+ TNC_IMV_Evaluation_Result eval)
+{
+ enumerator_t *enumerator;
+ tnccs_connection_entry_t *entry;
+ recommendations_t *recs = NULL;
+
+ this->connection_lock->read_lock(this->connection_lock);
+ enumerator = this->connections->create_enumerator(this->connections);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (id == entry->id)
+ {
+ recs = entry->recs;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->connection_lock->unlock(this->connection_lock);
+
+ if (recs)
+ {
+ recs->provide_recommendation(recs, imv_id, rec, eval);
+ return TNC_RESULT_SUCCESS;
+ }
+ return TNC_RESULT_FATAL;
+}
+
+METHOD(tnccs_manager_t, get_attribute, TNC_Result,
+ private_tnccs_manager_t *this, TNC_IMVID imv_id,
+ TNC_ConnectionID id,
+ TNC_AttributeID attribute_id,
+ TNC_UInt32 buffer_len,
+ TNC_BufferReference buffer,
+ TNC_UInt32 *out_value_len)
+{
+ enumerator_t *enumerator;
+ tnccs_connection_entry_t *entry;
+ recommendations_t *recs = NULL;
+
+ if (id == TNC_CONNECTIONID_ANY ||
+ attribute_id != TNC_ATTRIBUTEID_PREFERRED_LANGUAGE)
+ {
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+
+ this->connection_lock->read_lock(this->connection_lock);
+ enumerator = this->connections->create_enumerator(this->connections);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (id == entry->id)
+ {
+ recs = entry->recs;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->connection_lock->unlock(this->connection_lock);
+
+ if (recs)
+ {
+ chunk_t pref_lang;
+
+ pref_lang = recs->get_preferred_language(recs);
+ if (pref_lang.len == 0)
+ {
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+ *out_value_len = pref_lang.len;
+ if (buffer && buffer_len <= pref_lang.len)
+ {
+ memcpy(buffer, pref_lang.ptr, pref_lang.len);
+ }
+ return TNC_RESULT_SUCCESS;
+ }
+ return TNC_RESULT_INVALID_PARAMETER;
+}
+
+METHOD(tnccs_manager_t, set_attribute, TNC_Result,
+ private_tnccs_manager_t *this, TNC_IMVID imv_id,
+ TNC_ConnectionID id,
+ TNC_AttributeID attribute_id,
+ TNC_UInt32 buffer_len,
+ TNC_BufferReference buffer)
+{
+ enumerator_t *enumerator;
+ tnccs_connection_entry_t *entry;
+ recommendations_t *recs = NULL;
+
+ if (id == TNC_CONNECTIONID_ANY ||
+ (attribute_id != TNC_ATTRIBUTEID_REASON_STRING &&
+ attribute_id != TNC_ATTRIBUTEID_REASON_LANGUAGE))
+ {
+ return TNC_RESULT_INVALID_PARAMETER;
+ }
+
+ this->connection_lock->read_lock(this->connection_lock);
+ enumerator = this->connections->create_enumerator(this->connections);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (id == entry->id)
+ {
+ recs = entry->recs;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->connection_lock->unlock(this->connection_lock);
+
+ if (recs)
+ {
+ chunk_t attribute = { buffer, buffer_len };
+
+ if (attribute_id == TNC_ATTRIBUTEID_REASON_STRING)
+ {
+ return recs->set_reason_string(recs, imv_id, attribute);
+ }
+ else
+ {
+ return recs->set_reason_language(recs, imv_id, attribute);
+ }
+ }
+ return TNC_RESULT_INVALID_PARAMETER;
+}
+
+METHOD(tnccs_manager_t, destroy, void,
+ private_tnccs_manager_t *this)
+{
+ this->protocols->destroy_function(this->protocols, free);
+ this->protocol_lock->destroy(this->protocol_lock);
+ this->connections->destroy_function(this->connections, free);
+ this->connection_lock->destroy(this->connection_lock);
+ free(this);
+}
+
+/*
+ * See header
+ */
+tnccs_manager_t *tnccs_manager_create()
+{
+ private_tnccs_manager_t *this;
+
+ INIT(this,
+ .public = {
+ .add_method = _add_method,
+ .remove_method = _remove_method,
+ .create_instance = _create_instance,
+ .create_connection = _create_connection,
+ .remove_connection = _remove_connection,
+ .request_handshake_retry = _request_handshake_retry,
+ .send_message = _send_message,
+ .provide_recommendation = _provide_recommendation,
+ .get_attribute = _get_attribute,
+ .set_attribute = _set_attribute,
+ .destroy = _destroy,
+ },
+ .protocols = linked_list_create(),
+ .connections = linked_list_create(),
+ .protocol_lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ .connection_lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/tnc/tnccs/tnccs_manager.h b/src/libcharon/tnc/tnccs/tnccs_manager.h
new file mode 100644
index 000000000..c02eac03c
--- /dev/null
+++ b/src/libcharon/tnc/tnccs/tnccs_manager.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tnccs_manager tnccs_manager
+ * @{ @ingroup tnccs
+ */
+
+#ifndef TNCCS_MANAGER_H_
+#define TNCCS_MANAGER_H_
+
+#include "tnccs.h"
+
+#include <tnc/imv/imv_recommendations.h>
+
+typedef struct tnccs_manager_t tnccs_manager_t;
+
+/**
+ * The TNCCS manager manages all TNCCS implementations and creates instances.
+ *
+ * A plugin registers its implemented TNCCS protocol with the manager by
+ * providing type and a constructor function. The manager then creates
+ * TNCCS protocol instances via the provided constructor.
+ */
+struct tnccs_manager_t {
+
+ /**
+ * Register a TNCCS protocol implementation.
+ *
+ * @param type TNCCS protocol type
+ * @param constructor constructor, returns a TNCCS protocol implementation
+ */
+ void (*add_method)(tnccs_manager_t *this, tnccs_type_t type,
+ tnccs_constructor_t constructor);
+
+ /**
+ * Unregister a TNCCS protocol implementation using it's constructor.
+ *
+ * @param constructor constructor function to remove, as added in add_method
+ */
+ void (*remove_method)(tnccs_manager_t *this, tnccs_constructor_t constructor);
+
+ /**
+ * Create a new TNCCS protocol instance.
+ *
+ * @param type type of the TNCCS protocol
+ * @param is_server TRUE if TNC Server, FALSE if TNC Client
+ * @return TNCCS protocol instance, NULL if no constructor found
+ */
+ tnccs_t* (*create_instance)(tnccs_manager_t *this, tnccs_type_t type,
+ bool is_server);
+
+ /**
+ * Create a TNCCS connection and assign a unique connection ID as well a
+ * callback function for adding a message to a TNCCS batch and create
+ * an empty set for collecting IMV recommendations
+ *
+ * @param tnccs TNCCS connection instance
+ * @param send_message TNCCS callback function
+ * @param request_handshake_retry pointer to boolean variable
+ * @param recs pointer to IMV recommendation set
+ * @return assigned connection ID
+ */
+ TNC_ConnectionID (*create_connection)(tnccs_manager_t *this, tnccs_t *tnccs,
+ tnccs_send_message_t send_message,
+ bool *request_handshake_retry,
+ recommendations_t **recs);
+
+ /**
+ * Remove a TNCCS connection using its connection ID.
+ *
+ * @param id ID of the connection to be removed
+ */
+ void (*remove_connection)(tnccs_manager_t *this, TNC_ConnectionID id);
+
+ /**
+ * Request a handshake retry
+ *
+ * @param is_imc TRUE if IMC, FALSE if IMV
+ * @param imcv_id ID of IMC or IMV requesting the retry
+ * @param id ID of a specific connection or any connection
+ * @param reason reason for the handshake retry
+ * @return return code
+ */
+ TNC_Result (*request_handshake_retry)(tnccs_manager_t *this, bool is_imc,
+ TNC_UInt32 imcv_id,
+ TNC_ConnectionID id,
+ TNC_RetryReason reason);
+
+ /**
+ * Add an IMC/IMV message to the batch of a given connection ID.
+ *
+ * @param imc_id ID of IMC or TNC_IMCID_ANY
+ * @param imv_id ID of IMV or TNC_IMVID_ANY
+ * @param id ID of target connection
+ * @param msg message to be added
+ * @param msg_len message length
+ * @param msg_type message type
+ * @return return code
+ */
+ TNC_Result (*send_message)(tnccs_manager_t *this, TNC_IMCID imc_id,
+ TNC_IMVID imv_id,
+ TNC_ConnectionID id,
+ TNC_BufferReference msg,
+ TNC_UInt32 msg_len,
+ TNC_MessageType msg_type);
+
+ /**
+ * Deliver an IMV Action Recommendation and IMV Evaluation Result to the TNCS
+ *
+ * @param imv_id ID of the IMV providing the recommendation
+ * @param id ID of target connection
+ * @param rec action recommendation
+ * @param eval evaluation result
+ * @return return code
+ */
+ TNC_Result (*provide_recommendation)(tnccs_manager_t *this,
+ TNC_IMVID imv_id,
+ TNC_ConnectionID id,
+ TNC_IMV_Action_Recommendation rec,
+ TNC_IMV_Evaluation_Result eval);
+
+ /**
+ * Get the value of an attribute associated with a connection or with the
+ * TNCS as a whole.
+ *
+ * @param imv_id ID of the IMV requesting the attribute
+ * @param id ID of target connection
+ * @param attribute_id ID of the requested attribute
+ * @param buffer_len length of the buffer in bytes
+ * @param buffer pointer to the buffer
+ * @param out_value_len actual length of the returned attribute
+ * @return return code
+ */
+ TNC_Result (*get_attribute)(tnccs_manager_t *this,
+ TNC_IMVID imv_id,
+ TNC_ConnectionID id,
+ TNC_AttributeID attribute_id,
+ TNC_UInt32 buffer_len,
+ TNC_BufferReference buffer,
+ TNC_UInt32 *out_value_len);
+
+ /**
+ * Set the value of an attribute associated with a connection or with the
+ * TNCS as a whole.
+ *
+ * @param imv_id ID of the IMV setting the attribute
+ * @param id ID of target connection
+ * @param attribute_id ID of the attribute to be set
+ * @param buffer_len length of the buffer in bytes
+ * @param buffer pointer to the buffer
+ * @return return code
+ */
+ TNC_Result (*set_attribute)(tnccs_manager_t *this,
+ TNC_IMVID imv_id,
+ TNC_ConnectionID id,
+ TNC_AttributeID attribute_id,
+ TNC_UInt32 buffer_len,
+ TNC_BufferReference buffer);
+
+ /**
+ * Destroy a tnccs_manager instance.
+ */
+ void (*destroy)(tnccs_manager_t *this);
+};
+
+/**
+ * Create a tnccs_manager instance.
+ */
+tnccs_manager_t *tnccs_manager_create();
+
+#endif /** TNCCS_MANAGER_H_ @}*/
diff --git a/src/libcharon/tnc/tncif.h b/src/libcharon/tnc/tncif.h
new file mode 100644
index 000000000..99441a9a9
--- /dev/null
+++ b/src/libcharon/tnc/tncif.h
@@ -0,0 +1,106 @@
+/* tncif.h
+ *
+ * Trusted Network Connect IF-IMV API version 1.20
+ * Microsoft Windows DLL Platform Binding C Header
+ * February 5, 2007
+ *
+ * Copyright(c) 2005-2007, Trusted Computing Group, Inc. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * - Neither the name of the Trusted Computing Group nor the names of
+ * its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Contact the Trusted Computing Group at
+ * admin@trustedcomputinggroup.org for information on specification
+ * licensing through membership agreements.
+ *
+ * Any marks and brands contained herein are the property of their
+ * respective owners.
+ *
+ * Trusted Network Connect IF-IMC/IF-IMV API version 1.00 Revision 3
+ * Microsoft Windows DLL Platform Binding C Header
+ * Common definitions for IF-IMC and IF-IMV
+ * extracted from tncifimc.h and tncifimv.h
+ * Feb 12, 2007
+ */
+
+/**
+ * @defgroup tnc tnc
+ * @ingroup libcharon
+ *
+ * @defgroup tncif tncif
+ * @{ @ingroup tnc
+ */
+
+#ifndef TNCIF_H_
+#define TNCIF_H_
+
+/* Basic Types */
+typedef unsigned long TNC_UInt32;
+typedef unsigned char *TNC_BufferReference;
+
+/* Derived Types */
+typedef TNC_UInt32 TNC_ConnectionID;
+typedef TNC_UInt32 TNC_ConnectionState;
+typedef TNC_UInt32 TNC_RetryReason;
+typedef TNC_UInt32 TNC_MessageType;
+typedef TNC_MessageType *TNC_MessageTypeList;
+typedef TNC_UInt32 TNC_VendorID;
+typedef TNC_UInt32 TNC_MessageSubtype;
+typedef TNC_UInt32 TNC_Version;
+typedef TNC_UInt32 TNC_Result;
+
+/* Result Codes */
+#define TNC_RESULT_SUCCESS 0
+#define TNC_RESULT_NOT_INITIALIZED 1
+#define TNC_RESULT_ALREADY_INITIALIZED 2
+#define TNC_RESULT_NO_COMMON_VERSION 3
+#define TNC_RESULT_CANT_RETRY 4
+#define TNC_RESULT_WONT_RETRY 5
+#define TNC_RESULT_INVALID_PARAMETER 6
+#define TNC_RESULT_CANT_RESPOND 7
+#define TNC_RESULT_ILLEGAL_OPERATION 8
+#define TNC_RESULT_OTHER 9
+#define TNC_RESULT_FATAL 10
+
+/* Network Connection ID Values */
+#define TNC_CONNECTIONID_ANY 0xFFFFFFFF
+/* Network Connection State Values */
+#define TNC_CONNECTION_STATE_CREATE 0
+#define TNC_CONNECTION_STATE_HANDSHAKE 1
+#define TNC_CONNECTION_STATE_ACCESS_ALLOWED 2
+#define TNC_CONNECTION_STATE_ACCESS_ISOLATED 3
+#define TNC_CONNECTION_STATE_ACCESS_NONE 4
+#define TNC_CONNECTION_STATE_DELETE 5
+
+/* Vendor ID Values */
+#define TNC_VENDORID_TCG 0
+#define TNC_VENDORID_ANY ((TNC_VendorID) 0xffffff)
+/* Message Subtype Values */
+#define TNC_SUBTYPE_ANY ((TNC_MessageSubtype) 0xff)
+
+#endif /** TNCIF_H_ @}*/
diff --git a/src/libcharon/tnc/tncifimc.h b/src/libcharon/tnc/tncifimc.h
new file mode 100644
index 000000000..c6ddabd45
--- /dev/null
+++ b/src/libcharon/tnc/tncifimc.h
@@ -0,0 +1,180 @@
+/* tncifimc.h
+ *
+ * Trusted Network Connect IF-IMC API version 1.20 Revision 8
+ * Microsoft Windows DLL Platform Binding C Header
+ * February 5, 2007
+ *
+ * Copyright(c) 2005-2007, Trusted Computing Group, Inc. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * - Neither the name of the Trusted Computing Group nor the names of
+ * its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Contact the Trusted Computing Group at
+ * admin@trustedcomputinggroup.org for information on specification
+ * licensing through membership agreements.
+ *
+ * Any marks and brands contained herein are the property of their
+ * respective owners.
+ *
+ */
+
+/**
+ * @defgroup tncifimc tncifimc
+ * @{ @ingroup tnc
+ */
+
+#ifndef TNCIFIMC_H_
+#define TNCIFIMC_H_
+
+#include "tncif.h"
+
+/* Derived Types */
+
+typedef TNC_UInt32 TNC_IMCID;
+
+/* Function pointers */
+
+typedef TNC_Result (*TNC_IMC_InitializePointer)(
+ TNC_IMCID imcID,
+ TNC_Version minVersion,
+ TNC_Version maxVersion,
+ TNC_Version *pOutActualVersion);
+typedef TNC_Result (*TNC_IMC_NotifyConnectionChangePointer)(
+ TNC_IMCID imcID,
+ TNC_ConnectionID connectionID,
+ TNC_ConnectionState newState);
+typedef TNC_Result (*TNC_IMC_BeginHandshakePointer)(
+ TNC_IMCID imcID,
+ TNC_ConnectionID connectionID);
+typedef TNC_Result (*TNC_IMC_ReceiveMessagePointer)(
+ TNC_IMCID imcID,
+ TNC_ConnectionID connectionID,
+ TNC_BufferReference message,
+ TNC_UInt32 messageLength,
+ TNC_MessageType messageType);
+typedef TNC_Result (*TNC_IMC_BatchEndingPointer)(
+ TNC_IMCID imcID,
+ TNC_ConnectionID connectionID);
+typedef TNC_Result (*TNC_IMC_TerminatePointer)(
+ TNC_IMCID imcID);
+typedef TNC_Result (*TNC_TNCC_ReportMessageTypesPointer)(
+ TNC_IMCID imcID,
+ TNC_MessageTypeList supportedTypes,
+ TNC_UInt32 typeCount);
+typedef TNC_Result (*TNC_TNCC_SendMessagePointer)(
+ TNC_IMCID imcID,
+ TNC_ConnectionID connectionID,
+ TNC_BufferReference message,
+ TNC_UInt32 messageLength,
+ TNC_MessageType messageType);
+typedef TNC_Result (*TNC_TNCC_RequestHandshakeRetryPointer)(
+ TNC_IMCID imcID,
+ TNC_ConnectionID connectionID,
+ TNC_RetryReason reason);
+typedef TNC_Result (*TNC_TNCC_BindFunctionPointer)(
+ TNC_IMCID imcID,
+ char *functionName,
+ void **pOutfunctionPointer);
+typedef TNC_Result (*TNC_IMC_ProvideBindFunctionPointer)(
+ TNC_IMCID imcID,
+ TNC_TNCC_BindFunctionPointer bindFunction);
+
+#define TNC_IFIMC_VERSION_1 1
+
+/* Handshake Retry Reason Values */
+
+#define TNC_RETRY_REASON_IMC_REMEDIATION_COMPLETE 0
+#define TNC_RETRY_REASON_IMC_SERIOUS_EVENT 1
+#define TNC_RETRY_REASON_IMC_INFORMATIONAL_EVENT 2
+#define TNC_RETRY_REASON_IMC_PERIODIC 3
+/* reserved for TNC_RETRY_REASON_IMV_IMPORTANT_POLICY_CHANGE: 4 */
+/* reserved for TNC_RETRY_REASON_IMV_MINOR_POLICY_CHANGE: 5 */
+/* reserved for TNC_RETRY_REASON_IMV_SERIOUS_EVENT: 6 */
+/* reserved for TNC_RETRY_REASON_IMV_MINOR_EVENT: 7 */
+/* reserved for TNC_RETRY_REASON_IMV_PERIODIC: 8 */
+
+/* IMC Functions */
+
+TNC_Result TNC_IMC_Initialize(
+/*in*/ TNC_IMCID imcID,
+/*in*/ TNC_Version minVersion,
+/*in*/ TNC_Version maxVersion,
+/*out*/ TNC_Version *pOutActualVersion);
+
+TNC_Result TNC_IMC_NotifyConnectionChange(
+/*in*/ TNC_IMCID imcID,
+/*in*/ TNC_ConnectionID connectionID,
+/*in*/ TNC_ConnectionState newState);
+
+TNC_Result TNC_IMC_BeginHandshake(
+/*in*/ TNC_IMCID imcID,
+/*in*/ TNC_ConnectionID connectionID);
+
+TNC_Result TNC_IMC_ReceiveMessage(
+/*in*/ TNC_IMCID imcID,
+/*in*/ TNC_ConnectionID connectionID,
+/*in*/ TNC_BufferReference messageBuffer,
+/*in*/ TNC_UInt32 messageLength,
+/*in*/ TNC_MessageType messageType);
+
+TNC_Result TNC_IMC_BatchEnding(
+/*in*/ TNC_IMCID imcID,
+/*in*/ TNC_ConnectionID connectionID);
+
+TNC_Result TNC_IMC_Terminate(
+/*in*/ TNC_IMCID imcID);
+
+TNC_Result TNC_IMC_ProvideBindFunction(
+/*in*/ TNC_IMCID imcID,
+/*in*/ TNC_TNCC_BindFunctionPointer bindFunction);
+
+/* TNC Client Functions */
+
+TNC_Result TNC_TNCC_ReportMessageTypes(
+/*in*/ TNC_IMCID imcID,
+/*in*/ TNC_MessageTypeList supportedTypes,
+/*in*/ TNC_UInt32 typeCount);
+
+TNC_Result TNC_TNCC_SendMessage(
+/*in*/ TNC_IMCID imcID,
+/*in*/ TNC_ConnectionID connectionID,
+/*in*/ TNC_BufferReference message,
+/*in*/ TNC_UInt32 messageLength,
+/*in*/ TNC_MessageType messageType);
+
+TNC_Result TNC_TNCC_RequestHandshakeRetry(
+/*in*/ TNC_IMCID imcID,
+/*in*/ TNC_ConnectionID connectionID,
+/*in*/ TNC_RetryReason reason);
+
+TNC_Result TNC_TNCC_BindFunction(
+/*in*/ TNC_IMCID imcID,
+/*in*/ char *functionName,
+/*out*/ void **pOutfunctionPointer);
+
+#endif /** TNCIFIMC_H_ @}*/
diff --git a/src/libcharon/tnc/tncifimv.c b/src/libcharon/tnc/tncifimv.c
new file mode 100644
index 000000000..fbfd56566
--- /dev/null
+++ b/src/libcharon/tnc/tncifimv.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tncifimv.h"
+
+ENUM(TNC_IMV_Action_Recommendation_names,
+ TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
+ TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
+ "allow",
+ "no access",
+ "isolate",
+ "no recommendation"
+);
+
+ENUM(TNC_IMV_Evaluation_Result_names,
+ TNC_IMV_EVALUATION_RESULT_COMPLIANT,
+ TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
+ "compliant",
+ "non-compliant minor",
+ "non-compliant major",
+ "error",
+ "don't know"
+);
+
diff --git a/src/libcharon/tnc/tncifimv.h b/src/libcharon/tnc/tncifimv.h
new file mode 100644
index 000000000..4ec101337
--- /dev/null
+++ b/src/libcharon/tnc/tncifimv.h
@@ -0,0 +1,248 @@
+/* tncifimv.h
+ *
+ * Trusted Network Connect IF-IMV API version 1.20
+ * Microsoft Windows DLL Platform Binding C Header
+ * February 5, 2007
+ *
+ * Copyright(c) 2005-2007, Trusted Computing Group, Inc. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * - Neither the name of the Trusted Computing Group nor the names of
+ * its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Contact the Trusted Computing Group at
+ * admin@trustedcomputinggroup.org for information on specification
+ * licensing through membership agreements.
+ *
+ * Any marks and brands contained herein are the property of their
+ * respective owners.
+ */
+
+/**
+ * @defgroup tncifimv tncifimv
+ * @{ @ingroup tnc
+ */
+
+#ifndef TNCIFIMV_H_
+#define TNCIFIMV_H_
+
+#include "tncif.h"
+
+#include <library.h>
+
+typedef TNC_UInt32 TNC_IMVID;
+typedef TNC_UInt32 TNC_IMV_Action_Recommendation;
+typedef TNC_UInt32 TNC_IMV_Evaluation_Result;
+typedef TNC_UInt32 TNC_AttributeID;
+
+/* Function pointers */
+
+typedef TNC_Result (*TNC_IMV_InitializePointer)(
+ TNC_IMVID imvID,
+ TNC_Version minVersion,
+ TNC_Version maxVersion,
+ TNC_Version *pOutActualVersion);
+typedef TNC_Result (*TNC_IMV_NotifyConnectionChangePointer)(
+ TNC_IMVID imvID,
+ TNC_ConnectionID connectionID,
+ TNC_ConnectionState newState);
+typedef TNC_Result (*TNC_IMV_ReceiveMessagePointer)(
+ TNC_IMVID imvID,
+ TNC_ConnectionID connectionID,
+ TNC_BufferReference message,
+ TNC_UInt32 messageLength,
+ TNC_MessageType messageType);
+typedef TNC_Result (*TNC_IMV_SolicitRecommendationPointer)(
+ TNC_IMVID imvID,
+ TNC_ConnectionID connectionID);
+typedef TNC_Result (*TNC_IMV_BatchEndingPointer)(
+ TNC_IMVID imvID,
+ TNC_ConnectionID connectionID);
+typedef TNC_Result (*TNC_IMV_TerminatePointer)(
+ TNC_IMVID imvID);
+typedef TNC_Result (*TNC_TNCS_ReportMessageTypesPointer)(
+ TNC_IMVID imvID,
+ TNC_MessageTypeList supportedTypes,
+ TNC_UInt32 typeCount);
+typedef TNC_Result (*TNC_TNCS_SendMessagePointer)(
+ TNC_IMVID imvID,
+ TNC_ConnectionID connectionID,
+ TNC_BufferReference message,
+ TNC_UInt32 messageLength,
+ TNC_MessageType messageType);
+typedef TNC_Result (*TNC_TNCS_RequestHandshakeRetryPointer)(
+ TNC_IMVID imvID,
+ TNC_ConnectionID connectionID,
+ TNC_RetryReason reason);
+typedef TNC_Result (*TNC_TNCS_ProvideRecommendationPointer)(
+ TNC_IMVID imvID,
+ TNC_ConnectionID connectionID,
+ TNC_IMV_Action_Recommendation recommendation,
+ TNC_IMV_Evaluation_Result evaluation);
+typedef TNC_Result (*TNC_TNCS_GetAttributePointer)(
+ TNC_IMVID imvID,
+TNC_ConnectionID connectionID,
+TNC_AttributeID attributeID,
+ TNC_UInt32 bufferLength,
+ TNC_BufferReference buffer,
+ TNC_UInt32 *pOutValueLength);
+typedef TNC_Result (*TNC_TNCS_SetAttributePointer)(
+ TNC_IMVID imvID,
+ TNC_ConnectionID connectionID,
+TNC_AttributeID attributeID,
+ TNC_UInt32 bufferLength,
+ TNC_BufferReference buffer);
+typedef TNC_Result (*TNC_TNCS_BindFunctionPointer)(
+ TNC_IMVID imvID,
+ char *functionName,
+ void **pOutfunctionPointer);
+typedef TNC_Result (*TNC_IMV_ProvideBindFunctionPointer)(
+ TNC_IMVID imvID,
+ TNC_TNCS_BindFunctionPointer bindFunction);
+
+/* Version Numbers */
+
+#define TNC_IFIMV_VERSION_1 1
+
+/* Handshake Retry Reason Values */
+
+/* reserved for TNC_RETRY_REASON_IMC_REMEDIATION_COMPLETE: 0 */
+/* reserved for TNC_RETRY_REASON_IMC_SERIOUS_EVENT: 1 */
+/* reserved for TNC_RETRY_REASON_IMC_INFORMATIONAL_EVENT: 2 */
+/* reserved for TNC_RETRY_REASON_IMC_PERIODIC: 3 */
+#define TNC_RETRY_REASON_IMV_IMPORTANT_POLICY_CHANGE 4
+#define TNC_RETRY_REASON_IMV_MINOR_POLICY_CHANGE 5
+#define TNC_RETRY_REASON_IMV_SERIOUS_EVENT 6
+#define TNC_RETRY_REASON_IMV_MINOR_EVENT 7
+#define TNC_RETRY_REASON_IMV_PERIODIC 8
+
+/* IMV Action Recommendation Values */
+
+#define TNC_IMV_ACTION_RECOMMENDATION_ALLOW 0
+#define TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS 1
+#define TNC_IMV_ACTION_RECOMMENDATION_ISOLATE 2
+#define TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION 3
+
+extern enum_name_t *TNC_IMV_Action_Recommendation_names;
+
+/* IMV Evaluation Result Values */
+
+#define TNC_IMV_EVALUATION_RESULT_COMPLIANT 0
+#define TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR 1
+#define TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR 2
+#define TNC_IMV_EVALUATION_RESULT_ERROR 3
+#define TNC_IMV_EVALUATION_RESULT_DONT_KNOW 4
+
+extern enum_name_t *TNC_IMV_Evaluation_Result_names;
+
+/* Message Attribute ID Values */
+
+#define TNC_ATTRIBUTEID_PREFERRED_LANGUAGE ((TNC_AttributeID) 0x00000001)
+#define TNC_ATTRIBUTEID_REASON_STRING ((TNC_AttributeID) 0x00000002)
+#define TNC_ATTRIBUTEID_REASON_LANGUAGE ((TNC_AttributeID) 0x00000003)
+
+/* IMV Functions */
+
+TNC_Result TNC_IMV_Initialize(
+/*in*/ TNC_IMVID imvID,
+/*in*/ TNC_Version minVersion,
+/*in*/ TNC_Version maxVersion,
+/*in*/ TNC_Version *pOutActualVersion);
+
+TNC_Result TNC_IMV_NotifyConnectionChange(
+/*in*/ TNC_IMVID imvID,
+/*in*/ TNC_ConnectionID connectionID,
+/*in*/ TNC_ConnectionState newState);
+
+TNC_Result TNC_IMV_ReceiveMessage(
+/*in*/ TNC_IMVID imvID,
+/*in*/ TNC_ConnectionID connectionID,
+/*in*/ TNC_BufferReference messageBuffer,
+/*in*/ TNC_UInt32 messageLength,
+/*in*/ TNC_MessageType messageType);
+
+TNC_Result TNC_IMV_SolicitRecommendation(
+/*in*/ TNC_IMVID imvID,
+/*in*/ TNC_ConnectionID connectionID);
+
+TNC_Result TNC_IMV_BatchEnding(
+/*in*/ TNC_IMVID imvID,
+/*in*/ TNC_ConnectionID connectionID);
+
+TNC_Result TNC_IMV_Terminate(
+/*in*/ TNC_IMVID imvID);
+
+TNC_Result TNC_IMV_ProvideBindFunction(
+/*in*/ TNC_IMVID imvID,
+/*in*/ TNC_TNCS_BindFunctionPointer bindFunction);
+
+/* TNC Server Functions */
+
+TNC_Result TNC_TNCS_ReportMessageTypes(
+/*in*/ TNC_IMVID imvID,
+/*in*/ TNC_MessageTypeList supportedTypes,
+/*in*/ TNC_UInt32 typeCount);
+
+TNC_Result TNC_TNCS_SendMessage(
+/*in*/ TNC_IMVID imvID,
+/*in*/ TNC_ConnectionID connectionID,
+/*in*/ TNC_BufferReference message,
+/*in*/ TNC_UInt32 messageLength,
+/*in*/ TNC_MessageType messageType);
+
+TNC_Result TNC_TNCS_RequestHandshakeRetry(
+/*in*/ TNC_IMVID imvID,
+/*in*/ TNC_ConnectionID connectionID,
+/*in*/ TNC_RetryReason reason);
+
+TNC_Result TNC_TNCS_ProvideRecommendation(
+/*in*/ TNC_IMVID imvID,
+/*in*/ TNC_ConnectionID connectionID,
+/*in*/ TNC_IMV_Action_Recommendation recommendation,
+/*in*/ TNC_IMV_Evaluation_Result evaluation);
+
+TNC_Result TNC_TNCS_GetAttribute(
+/*in*/ TNC_IMVID imvID,
+/*in*/ TNC_ConnectionID connectionID,
+/*in*/ TNC_AttributeID attributeID,
+/*in*/ TNC_UInt32 bufferLength,
+/*out*/ TNC_BufferReference buffer,
+/*out*/ TNC_UInt32 *pOutValueLength);
+
+TNC_Result TNC_TNCS_SetAttribute(
+/*in*/ TNC_IMVID imvID,
+/*in*/ TNC_ConnectionID connectionID,
+/*in*/ TNC_AttributeID attributeID,
+/*in*/ TNC_UInt32 bufferLength,
+/*in*/ TNC_BufferReference buffer);
+
+TNC_Result TNC_TNCS_BindFunction(
+/*in*/ TNC_IMVID imvID,
+/*in*/ char *functionName,
+/*in*/ void **pOutfunctionPointer);
+
+#endif /** TNCIFIMV_H_ @}*/
diff --git a/src/libcharon/tnccs/tnccs_manager.c b/src/libcharon/tnccs/tnccs_manager.c
deleted file mode 100644
index 0fd6737c0..000000000
--- a/src/libcharon/tnccs/tnccs_manager.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2010 Andreas Steffen
- * HSR Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include "tnccs_manager.h"
-
-#include <utils/linked_list.h>
-#include <threading/rwlock.h>
-
-typedef struct private_tnccs_manager_t private_tnccs_manager_t;
-typedef struct tnccs_entry_t tnccs_entry_t;
-
-/**
- * TNCCS constructor entry
- */
-struct tnccs_entry_t {
-
- /**
- * TNCCS protocol type
- */
- tnccs_type_t type;
-
- /**
- * constructor function to create instance
- */
- tnccs_constructor_t constructor;
-};
-
-/**
- * private data of tnccs_manager
- */
-struct private_tnccs_manager_t {
-
- /**
- * public functions
- */
- tnccs_manager_t public;
-
- /**
- * list of tnccs_entry_t's
- */
- linked_list_t *protocols;
-
- /**
- * rwlock to lock methods
- */
- rwlock_t *lock;
-};
-
-METHOD(tnccs_manager_t, add_method, void,
- private_tnccs_manager_t *this, tnccs_type_t type,
- tnccs_constructor_t constructor)
-{
- tnccs_entry_t *entry = malloc_thing(tnccs_entry_t);
-
- entry->type = type;
- entry->constructor = constructor;
-
- this->lock->write_lock(this->lock);
- this->protocols->insert_last(this->protocols, entry);
- this->lock->unlock(this->lock);
-}
-
-METHOD(tnccs_manager_t, remove_method, void,
- private_tnccs_manager_t *this, tnccs_constructor_t constructor)
-{
- enumerator_t *enumerator;
- tnccs_entry_t *entry;
-
- this->lock->write_lock(this->lock);
- enumerator = this->protocols->create_enumerator(this->protocols);
- while (enumerator->enumerate(enumerator, &entry))
- {
- if (constructor == entry->constructor)
- {
- this->protocols->remove_at(this->protocols, enumerator);
- free(entry);
- }
- }
- enumerator->destroy(enumerator);
- this->lock->unlock(this->lock);
-}
-
-METHOD(tnccs_manager_t, create_instance, tnccs_t*,
- private_tnccs_manager_t *this, tnccs_type_t type, bool is_server)
-{
- enumerator_t *enumerator;
- tnccs_entry_t *entry;
- tnccs_t *protocol = NULL;
-
- this->lock->read_lock(this->lock);
- enumerator = this->protocols->create_enumerator(this->protocols);
- while (enumerator->enumerate(enumerator, &entry))
- {
- if (type == entry->type)
- {
- protocol = entry->constructor(is_server);
- if (protocol)
- {
- break;
- }
- }
- }
- enumerator->destroy(enumerator);
- this->lock->unlock(this->lock);
- return protocol;
-}
-
-METHOD(tnccs_manager_t, destroy, void,
- private_tnccs_manager_t *this)
-{
- this->protocols->destroy_function(this->protocols, free);
- this->lock->destroy(this->lock);
- free(this);
-}
-
-/*
- * See header
- */
-tnccs_manager_t *tnccs_manager_create()
-{
- private_tnccs_manager_t *this;
-
- INIT(this,
- .public = {
- .add_method = _add_method,
- .remove_method = _remove_method,
- .create_instance = _create_instance,
- .destroy = _destroy,
- },
- .protocols = linked_list_create(),
- .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
- );
-
- return &this->public;
-}
-
diff --git a/src/libcharon/tnccs/tnccs_manager.h b/src/libcharon/tnccs/tnccs_manager.h
deleted file mode 100644
index 2f4a961a7..000000000
--- a/src/libcharon/tnccs/tnccs_manager.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2010 Andreas Steffen
- * HSR Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup tnccs_manager tnccs_manager
- * @{ @ingroup tnccs
- */
-
-#ifndef TNCCS_MANAGER_H_
-#define TNCCS_MANAGER_H_
-
-#include "tnccs.h"
-
-typedef struct tnccs_manager_t tnccs_manager_t;
-
-/**
- * The TNCCS manager manages all TNCCS implementations and creates instances.
- *
- * A plugin registers its implemented TNCCS protocol with the manager by
- * providing type and a constructor function. The manager then creates
- * TNCCS protocol instances via the provided constructor.
- */
-struct tnccs_manager_t {
-
- /**
- * Register a TNCCS protocol implementation.
- *
- * @param type TNCCS protocol type
- * @param constructor constructor, returns a TNCCS protocol implementation
- */
- void (*add_method)(tnccs_manager_t *this, tnccs_type_t type,
- tnccs_constructor_t constructor);
-
- /**
- * Unregister a TNCCS protocol implementation using it's constructor.
- *
- * @param constructor constructor function to remove, as added in add_method
- */
- void (*remove_method)(tnccs_manager_t *this, tnccs_constructor_t constructor);
-
- /**
- * Create a new TNCCS protocol instance.
- *
- * @param type type of the TNCCS protocol
- * @param is_server TRUE if TNC Server, FALSE if TNC Client
- * @return TNCCS protocol instance, NULL if no constructor found
- */
- tnccs_t* (*create_instance)(tnccs_manager_t *this, tnccs_type_t type,
- bool is_server);
-
- /**
- * Destroy a tnccs_manager instance.
- */
- void (*destroy)(tnccs_manager_t *this);
-};
-
-/**
- * Create a tnccs_manager instance.
- */
-tnccs_manager_t *tnccs_manager_create();
-
-#endif /** TNCCS_MANAGER_H_ @}*/